mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 07:45:30 +08:00
6.5.3 clean
This commit is contained in:
56
tests/manual/examples/widgets/itemviews/chart/CMakeLists.txt
Normal file
56
tests/manual/examples/widgets/itemviews/chart/CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(chart LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/chart")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(chart
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
pieview.cpp pieview.h
|
||||
)
|
||||
|
||||
set_target_properties(chart PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(chart PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(chart_resource_files
|
||||
"qtdata.cht"
|
||||
)
|
||||
|
||||
qt_add_resources(chart "chart"
|
||||
PREFIX
|
||||
"/Charts"
|
||||
FILES
|
||||
${chart_resource_files}
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORKS)
|
||||
target_link_libraries(chart PRIVATE
|
||||
m
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS chart
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
14
tests/manual/examples/widgets/itemviews/chart/chart.pro
Normal file
14
tests/manual/examples/widgets/itemviews/chart/chart.pro
Normal file
@ -0,0 +1,14 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(filedialog))
|
||||
|
||||
HEADERS = mainwindow.h \
|
||||
pieview.h
|
||||
RESOURCES = chart.qrc
|
||||
SOURCES = main.cpp \
|
||||
mainwindow.cpp \
|
||||
pieview.cpp
|
||||
unix:!mac:!vxworks:!integrity:!haiku:LIBS += -lm
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/chart
|
||||
INSTALLS += target
|
5
tests/manual/examples/widgets/itemviews/chart/chart.qrc
Normal file
5
tests/manual/examples/widgets/itemviews/chart/chart.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/Charts" >
|
||||
<file>qtdata.cht</file>
|
||||
</qresource>
|
||||
</RCC>
|
14
tests/manual/examples/widgets/itemviews/chart/main.cpp
Normal file
14
tests/manual/examples/widgets/itemviews/chart/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
136
tests/manual/examples/widgets/itemviews/chart/mainwindow.cpp
Normal file
136
tests/manual/examples/widgets/itemviews/chart/mainwindow.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "pieview.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
QMenu *fileMenu = new QMenu(tr("&File"), this);
|
||||
QAction *openAction = fileMenu->addAction(tr("&Open..."));
|
||||
openAction->setShortcuts(QKeySequence::Open);
|
||||
QAction *saveAction = fileMenu->addAction(tr("&Save As..."));
|
||||
saveAction->setShortcuts(QKeySequence::SaveAs);
|
||||
QAction *quitAction = fileMenu->addAction(tr("E&xit"));
|
||||
quitAction->setShortcuts(QKeySequence::Quit);
|
||||
|
||||
setupModel();
|
||||
setupViews();
|
||||
|
||||
connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
|
||||
connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
|
||||
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
|
||||
|
||||
menuBar()->addMenu(fileMenu);
|
||||
statusBar();
|
||||
|
||||
loadFile(":/Charts/qtdata.cht");
|
||||
|
||||
setWindowTitle(tr("Chart"));
|
||||
resize(870, 550);
|
||||
}
|
||||
|
||||
void MainWindow::setupModel()
|
||||
{
|
||||
model = new QStandardItemModel(8, 2, this);
|
||||
model->setHeaderData(0, Qt::Horizontal, tr("Label"));
|
||||
model->setHeaderData(1, Qt::Horizontal, tr("Quantity"));
|
||||
}
|
||||
|
||||
void MainWindow::setupViews()
|
||||
{
|
||||
QSplitter *splitter = new QSplitter;
|
||||
QTableView *table = new QTableView;
|
||||
pieChart = new PieView;
|
||||
splitter->addWidget(table);
|
||||
splitter->addWidget(pieChart);
|
||||
splitter->setStretchFactor(0, 0);
|
||||
splitter->setStretchFactor(1, 1);
|
||||
|
||||
table->setModel(model);
|
||||
pieChart->setModel(model);
|
||||
|
||||
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
|
||||
table->setSelectionModel(selectionModel);
|
||||
pieChart->setSelectionModel(selectionModel);
|
||||
|
||||
QHeaderView *headerView = table->horizontalHeader();
|
||||
headerView->setStretchLastSection(true);
|
||||
|
||||
setCentralWidget(splitter);
|
||||
}
|
||||
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
const QString fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Choose a data file"), "", "*.cht");
|
||||
if (!fileName.isEmpty())
|
||||
loadFile(fileName);
|
||||
}
|
||||
|
||||
void MainWindow::loadFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return;
|
||||
|
||||
QTextStream stream(&file);
|
||||
|
||||
model->removeRows(0, model->rowCount(QModelIndex()), QModelIndex());
|
||||
|
||||
int row = 0;
|
||||
while (!stream.atEnd()) {
|
||||
const QString line = stream.readLine();
|
||||
if (!line.isEmpty()) {
|
||||
model->insertRows(row, 1, QModelIndex());
|
||||
|
||||
const QStringList pieces = line.split(QLatin1Char(','), Qt::SkipEmptyParts);
|
||||
if (pieces.size() < 3)
|
||||
continue;
|
||||
model->setData(model->index(row, 0, QModelIndex()),
|
||||
pieces.value(0));
|
||||
model->setData(model->index(row, 1, QModelIndex()),
|
||||
pieces.value(1));
|
||||
model->setData(model->index(row, 0, QModelIndex()),
|
||||
QColor(pieces.value(2)), Qt::DecorationRole);
|
||||
row++;
|
||||
}
|
||||
};
|
||||
|
||||
file.close();
|
||||
statusBar()->showMessage(tr("Loaded %1").arg(fileName), 2000);
|
||||
}
|
||||
|
||||
void MainWindow::saveFile()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this,
|
||||
tr("Save file as"), "", "*.cht");
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text))
|
||||
return;
|
||||
|
||||
QTextStream stream(&file);
|
||||
for (int row = 0; row < model->rowCount(QModelIndex()); ++row) {
|
||||
|
||||
QStringList pieces;
|
||||
|
||||
pieces.append(model->data(model->index(row, 0, QModelIndex()),
|
||||
Qt::DisplayRole).toString());
|
||||
pieces.append(model->data(model->index(row, 1, QModelIndex()),
|
||||
Qt::DisplayRole).toString());
|
||||
pieces.append(model->data(model->index(row, 0, QModelIndex()),
|
||||
Qt::DecorationRole).toString());
|
||||
|
||||
stream << pieces.join(',') << "\n";
|
||||
}
|
||||
|
||||
file.close();
|
||||
statusBar()->showMessage(tr("Saved %1").arg(fileName), 2000);
|
||||
}
|
34
tests/manual/examples/widgets/itemviews/chart/mainwindow.h
Normal file
34
tests/manual/examples/widgets/itemviews/chart/mainwindow.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemModel;
|
||||
class QAbstractItemView;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void openFile();
|
||||
void saveFile();
|
||||
|
||||
private:
|
||||
void setupModel();
|
||||
void setupViews();
|
||||
void loadFile(const QString &path);
|
||||
|
||||
QAbstractItemModel *model = nullptr;
|
||||
QAbstractItemView *pieChart = nullptr;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
506
tests/manual/examples/widgets/itemviews/chart/pieview.cpp
Normal file
506
tests/manual/examples/widgets/itemviews/chart/pieview.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "pieview.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
PieView::PieView(QWidget *parent)
|
||||
: QAbstractItemView(parent)
|
||||
{
|
||||
horizontalScrollBar()->setRange(0, 0);
|
||||
verticalScrollBar()->setRange(0, 0);
|
||||
}
|
||||
|
||||
void PieView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QList<int> &roles)
|
||||
{
|
||||
QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
|
||||
|
||||
if (!roles.contains(Qt::DisplayRole))
|
||||
return;
|
||||
|
||||
validItems = 0;
|
||||
totalValue = 0.0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index, Qt::DisplayRole).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
totalValue += value;
|
||||
validItems++;
|
||||
}
|
||||
}
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
bool PieView::edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
return QAbstractItemView::edit(index, trigger, event);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the item that covers the coordinate given in the view.
|
||||
*/
|
||||
|
||||
QModelIndex PieView::indexAt(const QPoint &point) const
|
||||
{
|
||||
if (validItems == 0)
|
||||
return QModelIndex();
|
||||
|
||||
// Transform the view coordinates into contents widget coordinates.
|
||||
int wx = point.x() + horizontalScrollBar()->value();
|
||||
int wy = point.y() + verticalScrollBar()->value();
|
||||
|
||||
if (wx < totalSize) {
|
||||
double cx = wx - totalSize / 2;
|
||||
double cy = totalSize / 2 - wy; // positive cy for items above the center
|
||||
|
||||
// Determine the distance from the center point of the pie chart.
|
||||
double d = std::sqrt(std::pow(cx, 2) + std::pow(cy, 2));
|
||||
|
||||
if (d == 0 || d > pieSize / 2)
|
||||
return QModelIndex();
|
||||
|
||||
// Determine the angle of the point.
|
||||
double angle = qRadiansToDegrees(std::atan2(cy, cx));
|
||||
if (angle < 0)
|
||||
angle = 360 + angle;
|
||||
|
||||
// Find the relevant slice of the pie.
|
||||
double startAngle = 0.0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double sliceAngle = 360 * value / totalValue;
|
||||
|
||||
if (angle >= startAngle && angle < (startAngle + sliceAngle))
|
||||
return model()->index(row, 1, rootIndex());
|
||||
|
||||
startAngle += sliceAngle;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
double itemHeight = QFontMetrics(option.font).height();
|
||||
int listItem = int((wy - margin) / itemHeight);
|
||||
int validRow = 0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
if (model()->data(index).toDouble() > 0.0) {
|
||||
|
||||
if (listItem == validRow)
|
||||
return model()->index(row, 0, rootIndex());
|
||||
|
||||
// Update the list index that corresponds to the next valid row.
|
||||
++validRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool PieView::isIndexHidden(const QModelIndex & /*index*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the rectangle of the item at position \a index in the
|
||||
model. The rectangle is in contents coordinates.
|
||||
*/
|
||||
|
||||
QRect PieView::itemRect(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QRect();
|
||||
|
||||
// Check whether the index's row is in the list of rows represented
|
||||
// by slices.
|
||||
QModelIndex valueIndex;
|
||||
|
||||
if (index.column() != 1)
|
||||
valueIndex = model()->index(index.row(), 1, rootIndex());
|
||||
else
|
||||
valueIndex = index;
|
||||
|
||||
if (model()->data(valueIndex).toDouble() <= 0.0)
|
||||
return QRect();
|
||||
|
||||
int listItem = 0;
|
||||
for (int row = index.row()-1; row >= 0; --row) {
|
||||
if (model()->data(model()->index(row, 1, rootIndex())).toDouble() > 0.0)
|
||||
listItem++;
|
||||
}
|
||||
|
||||
switch (index.column()) {
|
||||
case 0: {
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
const qreal itemHeight = QFontMetricsF(option.font).height();
|
||||
return QRect(totalSize,
|
||||
qRound(margin + listItem * itemHeight),
|
||||
totalSize - margin, qRound(itemHeight));
|
||||
}
|
||||
case 1:
|
||||
return viewport()->rect();
|
||||
}
|
||||
return QRect();
|
||||
}
|
||||
|
||||
QRegion PieView::itemRegion(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QRegion();
|
||||
|
||||
if (index.column() != 1)
|
||||
return itemRect(index);
|
||||
|
||||
if (model()->data(index).toDouble() <= 0.0)
|
||||
return QRegion();
|
||||
|
||||
double startAngle = 0.0;
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex sliceIndex = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(sliceIndex).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double angle = 360 * value / totalValue;
|
||||
|
||||
if (sliceIndex == index) {
|
||||
QPainterPath slicePath;
|
||||
slicePath.moveTo(totalSize / 2, totalSize / 2);
|
||||
slicePath.arcTo(margin, margin, margin + pieSize, margin + pieSize,
|
||||
startAngle, angle);
|
||||
slicePath.closeSubpath();
|
||||
|
||||
return QRegion(slicePath.toFillPolygon().toPolygon());
|
||||
}
|
||||
|
||||
startAngle += angle;
|
||||
}
|
||||
}
|
||||
|
||||
return QRegion();
|
||||
}
|
||||
|
||||
int PieView::horizontalOffset() const
|
||||
{
|
||||
return horizontalScrollBar()->value();
|
||||
}
|
||||
|
||||
void PieView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractItemView::mousePressEvent(event);
|
||||
origin = event->position().toPoint();
|
||||
if (!rubberBand)
|
||||
rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport());
|
||||
rubberBand->setGeometry(QRect(origin, QSize()));
|
||||
rubberBand->show();
|
||||
}
|
||||
|
||||
void PieView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (rubberBand)
|
||||
rubberBand->setGeometry(QRect(origin, event->position().toPoint()).normalized());
|
||||
QAbstractItemView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void PieView::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractItemView::mouseReleaseEvent(event);
|
||||
if (rubberBand)
|
||||
rubberBand->hide();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
QModelIndex PieView::moveCursor(QAbstractItemView::CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers /*modifiers*/)
|
||||
{
|
||||
QModelIndex current = currentIndex();
|
||||
|
||||
switch (cursorAction) {
|
||||
case MoveLeft:
|
||||
case MoveUp:
|
||||
if (current.row() > 0)
|
||||
current = model()->index(current.row() - 1, current.column(),
|
||||
rootIndex());
|
||||
else
|
||||
current = model()->index(0, current.column(), rootIndex());
|
||||
break;
|
||||
case MoveRight:
|
||||
case MoveDown:
|
||||
if (current.row() < rows(current) - 1)
|
||||
current = model()->index(current.row() + 1, current.column(),
|
||||
rootIndex());
|
||||
else
|
||||
current = model()->index(rows(current) - 1, current.column(),
|
||||
rootIndex());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
viewport()->update();
|
||||
return current;
|
||||
}
|
||||
|
||||
void PieView::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QItemSelectionModel *selections = selectionModel();
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
|
||||
QBrush background = option.palette.base();
|
||||
QPen foreground(option.palette.color(QPalette::WindowText));
|
||||
|
||||
QPainter painter(viewport());
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
painter.fillRect(event->rect(), background);
|
||||
painter.setPen(foreground);
|
||||
|
||||
// Viewport rectangles
|
||||
QRect pieRect = QRect(margin, margin, pieSize, pieSize);
|
||||
|
||||
if (validItems <= 0)
|
||||
return;
|
||||
|
||||
painter.save();
|
||||
painter.translate(pieRect.x() - horizontalScrollBar()->value(),
|
||||
pieRect.y() - verticalScrollBar()->value());
|
||||
painter.drawEllipse(0, 0, pieSize, pieSize);
|
||||
double startAngle = 0.0;
|
||||
int row;
|
||||
|
||||
for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double angle = 360 * value / totalValue;
|
||||
|
||||
QModelIndex colorIndex = model()->index(row, 0, rootIndex());
|
||||
QColor color = QColor(model()->data(colorIndex, Qt::DecorationRole).toString());
|
||||
|
||||
if (currentIndex() == index)
|
||||
painter.setBrush(QBrush(color, Qt::Dense4Pattern));
|
||||
else if (selections->isSelected(index))
|
||||
painter.setBrush(QBrush(color, Qt::Dense3Pattern));
|
||||
else
|
||||
painter.setBrush(QBrush(color));
|
||||
|
||||
painter.drawPie(0, 0, pieSize, pieSize, int(startAngle*16), int(angle*16));
|
||||
|
||||
startAngle += angle;
|
||||
}
|
||||
}
|
||||
painter.restore();
|
||||
|
||||
for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
QModelIndex labelIndex = model()->index(row, 0, rootIndex());
|
||||
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
|
||||
option.rect = visualRect(labelIndex);
|
||||
if (selections->isSelected(labelIndex))
|
||||
option.state |= QStyle::State_Selected;
|
||||
if (currentIndex() == labelIndex)
|
||||
option.state |= QStyle::State_HasFocus;
|
||||
itemDelegate()->paint(&painter, option, labelIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PieView::resizeEvent(QResizeEvent * /* event */)
|
||||
{
|
||||
updateGeometries();
|
||||
}
|
||||
|
||||
int PieView::rows(const QModelIndex &index) const
|
||||
{
|
||||
return model()->rowCount(model()->parent(index));
|
||||
}
|
||||
|
||||
void PieView::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||
{
|
||||
for (int row = start; row <= end; ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
totalValue += value;
|
||||
++validItems;
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractItemView::rowsInserted(parent, start, end);
|
||||
}
|
||||
|
||||
void PieView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
||||
{
|
||||
for (int row = start; row <= end; ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
if (value > 0.0) {
|
||||
totalValue -= value;
|
||||
--validItems;
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
|
||||
}
|
||||
|
||||
void PieView::scrollContentsBy(int dx, int dy)
|
||||
{
|
||||
viewport()->scroll(dx, dy);
|
||||
}
|
||||
|
||||
void PieView::scrollTo(const QModelIndex &index, ScrollHint)
|
||||
{
|
||||
QRect area = viewport()->rect();
|
||||
QRect rect = visualRect(index);
|
||||
|
||||
if (rect.left() < area.left()) {
|
||||
horizontalScrollBar()->setValue(
|
||||
horizontalScrollBar()->value() + rect.left() - area.left());
|
||||
} else if (rect.right() > area.right()) {
|
||||
horizontalScrollBar()->setValue(
|
||||
horizontalScrollBar()->value() + qMin(
|
||||
rect.right() - area.right(), rect.left() - area.left()));
|
||||
}
|
||||
|
||||
if (rect.top() < area.top()) {
|
||||
verticalScrollBar()->setValue(
|
||||
verticalScrollBar()->value() + rect.top() - area.top());
|
||||
} else if (rect.bottom() > area.bottom()) {
|
||||
verticalScrollBar()->setValue(
|
||||
verticalScrollBar()->value() + qMin(
|
||||
rect.bottom() - area.bottom(), rect.top() - area.top()));
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/*
|
||||
Find the indices corresponding to the extent of the selection.
|
||||
*/
|
||||
|
||||
void PieView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
// Use content widget coordinates because we will use the itemRegion()
|
||||
// function to check for intersections.
|
||||
|
||||
QRect contentsRect = rect.translated(
|
||||
horizontalScrollBar()->value(),
|
||||
verticalScrollBar()->value()).normalized();
|
||||
|
||||
int rows = model()->rowCount(rootIndex());
|
||||
int columns = model()->columnCount(rootIndex());
|
||||
QModelIndexList indexes;
|
||||
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
for (int column = 0; column < columns; ++column) {
|
||||
QModelIndex index = model()->index(row, column, rootIndex());
|
||||
QRegion region = itemRegion(index);
|
||||
if (region.intersects(contentsRect))
|
||||
indexes.append(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (indexes.size() > 0) {
|
||||
int firstRow = indexes.at(0).row();
|
||||
int lastRow = firstRow;
|
||||
int firstColumn = indexes.at(0).column();
|
||||
int lastColumn = firstColumn;
|
||||
|
||||
for (int i = 1; i < indexes.size(); ++i) {
|
||||
firstRow = qMin(firstRow, indexes.at(i).row());
|
||||
lastRow = qMax(lastRow, indexes.at(i).row());
|
||||
firstColumn = qMin(firstColumn, indexes.at(i).column());
|
||||
lastColumn = qMax(lastColumn, indexes.at(i).column());
|
||||
}
|
||||
|
||||
QItemSelection selection(
|
||||
model()->index(firstRow, firstColumn, rootIndex()),
|
||||
model()->index(lastRow, lastColumn, rootIndex()));
|
||||
selectionModel()->select(selection, command);
|
||||
} else {
|
||||
QModelIndex noIndex;
|
||||
QItemSelection selection(noIndex, noIndex);
|
||||
selectionModel()->select(selection, command);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PieView::updateGeometries()
|
||||
{
|
||||
horizontalScrollBar()->setPageStep(viewport()->width());
|
||||
horizontalScrollBar()->setRange(0, qMax(0, 2 * totalSize - viewport()->width()));
|
||||
verticalScrollBar()->setPageStep(viewport()->height());
|
||||
verticalScrollBar()->setRange(0, qMax(0, totalSize - viewport()->height()));
|
||||
}
|
||||
|
||||
int PieView::verticalOffset() const
|
||||
{
|
||||
return verticalScrollBar()->value();
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the position of the item in viewport coordinates.
|
||||
*/
|
||||
|
||||
QRect PieView::visualRect(const QModelIndex &index) const
|
||||
{
|
||||
QRect rect = itemRect(index);
|
||||
if (!rect.isValid())
|
||||
return rect;
|
||||
|
||||
return QRect(rect.left() - horizontalScrollBar()->value(),
|
||||
rect.top() - verticalScrollBar()->value(),
|
||||
rect.width(), rect.height());
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a region corresponding to the selection in viewport coordinates.
|
||||
*/
|
||||
|
||||
QRegion PieView::visualRegionForSelection(const QItemSelection &selection) const
|
||||
{
|
||||
int ranges = selection.count();
|
||||
|
||||
if (ranges == 0)
|
||||
return QRect();
|
||||
|
||||
QRegion region;
|
||||
for (int i = 0; i < ranges; ++i) {
|
||||
const QItemSelectionRange &range = selection.at(i);
|
||||
for (int row = range.top(); row <= range.bottom(); ++row) {
|
||||
for (int col = range.left(); col <= range.right(); ++col) {
|
||||
QModelIndex index = model()->index(row, col, rootIndex());
|
||||
region += visualRect(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return region;
|
||||
}
|
66
tests/manual/examples/widgets/itemviews/chart/pieview.h
Normal file
66
tests/manual/examples/widgets/itemviews/chart/pieview.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef PIEVIEW_H
|
||||
#define PIEVIEW_H
|
||||
|
||||
#include <QAbstractItemView>
|
||||
|
||||
//! [0]
|
||||
class PieView : public QAbstractItemView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PieView(QWidget *parent = nullptr);
|
||||
|
||||
QRect visualRect(const QModelIndex &index) const override;
|
||||
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
QModelIndex indexAt(const QPoint &point) const override;
|
||||
|
||||
protected slots:
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QList<int> &roles = QList<int>()) override;
|
||||
void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
|
||||
protected:
|
||||
bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event) override;
|
||||
QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
int horizontalOffset() const override;
|
||||
int verticalOffset() const override;
|
||||
|
||||
bool isIndexHidden(const QModelIndex &index) const override;
|
||||
|
||||
void setSelection(const QRect&, QItemSelectionModel::SelectionFlags command) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void scrollContentsBy(int dx, int dy) override;
|
||||
|
||||
QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
|
||||
private:
|
||||
QRect itemRect(const QModelIndex &item) const;
|
||||
QRegion itemRegion(const QModelIndex &index) const;
|
||||
int rows(const QModelIndex &index = QModelIndex()) const;
|
||||
void updateGeometries() override;
|
||||
|
||||
int margin = 0;
|
||||
int totalSize = 300;
|
||||
int pieSize = totalSize - 2 * margin;
|
||||
int validItems = 0;
|
||||
double totalValue = 0.0;
|
||||
QRubberBand *rubberBand = nullptr;
|
||||
QPoint origin;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // PIEVIEW_H
|
14
tests/manual/examples/widgets/itemviews/chart/qtdata.cht
Normal file
14
tests/manual/examples/widgets/itemviews/chart/qtdata.cht
Normal file
@ -0,0 +1,14 @@
|
||||
Scientific Research,21,#99e600
|
||||
Engineering & Design,18,#99cc00
|
||||
Automotive,14,#99b300
|
||||
Aerospace,13,#9f991a
|
||||
Automation & Machine Tools,13,#a48033
|
||||
Medical & Bioinformatics,13,#a9664d
|
||||
Imaging & Special Effects,12,#ae4d66
|
||||
Defense,11,#b33380
|
||||
Test & Measurement Systems,9,#a64086
|
||||
Oil & Gas,9,#994d8d
|
||||
Entertainment & Broadcasting,7,#8d5a93
|
||||
Financial,6,#806699
|
||||
Consumer Electronics,4,#8073a6
|
||||
Other,38,#8080b3
|
Reference in New Issue
Block a user