From 806dda08d685bc5f9ed71dfe8b61f21848d48066 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 17 Aug 2012 13:23:19 +0200 Subject: Moving .qdoc files under examples/widgets/doc Updated those .qdoc files to refer to the new relative examples emplacement. Images and snippets to be moved later. Also grouped all widgets related examples under widgets. Change-Id: Ib29696e2d8948524537f53e8dda88f9ee26a597f Reviewed-by: J-P Nurmi --- examples/widgets/itemviews/chart/chart.desktop | 11 + examples/widgets/itemviews/chart/chart.pro | 18 + examples/widgets/itemviews/chart/chart.qrc | 5 + examples/widgets/itemviews/chart/main.cpp | 53 +++ examples/widgets/itemviews/chart/mainwindow.cpp | 172 ++++++++ examples/widgets/itemviews/chart/mainwindow.h | 72 +++ examples/widgets/itemviews/chart/mydata.cht | 8 + examples/widgets/itemviews/chart/pieview.cpp | 557 ++++++++++++++++++++++++ examples/widgets/itemviews/chart/pieview.h | 114 +++++ examples/widgets/itemviews/chart/qtdata.cht | 14 + 10 files changed, 1024 insertions(+) create mode 100644 examples/widgets/itemviews/chart/chart.desktop create mode 100644 examples/widgets/itemviews/chart/chart.pro create mode 100644 examples/widgets/itemviews/chart/chart.qrc create mode 100644 examples/widgets/itemviews/chart/main.cpp create mode 100644 examples/widgets/itemviews/chart/mainwindow.cpp create mode 100644 examples/widgets/itemviews/chart/mainwindow.h create mode 100644 examples/widgets/itemviews/chart/mydata.cht create mode 100644 examples/widgets/itemviews/chart/pieview.cpp create mode 100644 examples/widgets/itemviews/chart/pieview.h create mode 100644 examples/widgets/itemviews/chart/qtdata.cht (limited to 'examples/widgets/itemviews/chart') diff --git a/examples/widgets/itemviews/chart/chart.desktop b/examples/widgets/itemviews/chart/chart.desktop new file mode 100644 index 0000000000..73e017baeb --- /dev/null +++ b/examples/widgets/itemviews/chart/chart.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Type=Application +Terminal=false +Name=Chart +Exec=/opt/usr/bin/chart +Icon=chart +X-Window-Icon= +X-HildonDesk-ShowInToolbar=true +X-Osso-Type=application/x-executable diff --git a/examples/widgets/itemviews/chart/chart.pro b/examples/widgets/itemviews/chart/chart.pro new file mode 100644 index 0000000000..310bb85ad7 --- /dev/null +++ b/examples/widgets/itemviews/chart/chart.pro @@ -0,0 +1,18 @@ +HEADERS = mainwindow.h \ + pieview.h +RESOURCES = chart.qrc +SOURCES = main.cpp \ + mainwindow.cpp \ + pieview.cpp +unix:!mac:!vxworks:!integrity:LIBS+= -lm + +TARGET.EPOCHEAPSIZE = 0x200000 0x800000 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/itemviews/chart +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.cht +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/itemviews/chart +INSTALLS += target sources + +QT += widgets + diff --git a/examples/widgets/itemviews/chart/chart.qrc b/examples/widgets/itemviews/chart/chart.qrc new file mode 100644 index 0000000000..7401d4d2f8 --- /dev/null +++ b/examples/widgets/itemviews/chart/chart.qrc @@ -0,0 +1,5 @@ + + + qtdata.cht + + diff --git a/examples/widgets/itemviews/chart/main.cpp b/examples/widgets/itemviews/chart/main.cpp new file mode 100644 index 0000000000..b1c13116c9 --- /dev/null +++ b/examples/widgets/itemviews/chart/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(chart); + + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} diff --git a/examples/widgets/itemviews/chart/mainwindow.cpp b/examples/widgets/itemviews/chart/mainwindow.cpp new file mode 100644 index 0000000000..584390252b --- /dev/null +++ b/examples/widgets/itemviews/chart/mainwindow.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "pieview.h" +#include "mainwindow.h" + +MainWindow::MainWindow() +{ + 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, SIGNAL(triggered()), this, SLOT(openFile())); + connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile())); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + menuBar()->addMenu(fileMenu); + statusBar(); + + openFile(":/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 &path) +{ + QString fileName; + if (path.isNull()) + fileName = QFileDialog::getOpenFileName(this, tr("Choose a data file"), + "", "*.cht"); + else + fileName = path; + + if (!fileName.isEmpty()) { + QFile file(fileName); + + if (file.open(QFile::ReadOnly | QFile::Text)) { + QTextStream stream(&file); + QString line; + + model->removeRows(0, model->rowCount(QModelIndex()), QModelIndex()); + + int row = 0; + do { + line = stream.readLine(); + if (!line.isEmpty()) { + + model->insertRows(row, 1, QModelIndex()); + + QStringList pieces = line.split(",", QString::SkipEmptyParts); + 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++; + } + } while (!line.isEmpty()); + + 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()) { + QFile file(fileName); + QTextStream stream(&file); + + if (file.open(QFile::WriteOnly | QFile::Text)) { + 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); + } +} diff --git a/examples/widgets/itemviews/chart/mainwindow.h b/examples/widgets/itemviews/chart/mainwindow.h new file mode 100644 index 0000000000..5ce4f30e32 --- /dev/null +++ b/examples/widgets/itemviews/chart/mainwindow.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +class QAbstractItemModel; +class QAbstractItemView; +class QItemSelectionModel; +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +private slots: + void openFile(const QString &path = QString()); + void saveFile(); + +private: + void setupModel(); + void setupViews(); + + QAbstractItemModel *model; + QAbstractItemView *pieChart; + QItemSelectionModel *selectionModel; +}; + +#endif diff --git a/examples/widgets/itemviews/chart/mydata.cht b/examples/widgets/itemviews/chart/mydata.cht new file mode 100644 index 0000000000..029fd81458 --- /dev/null +++ b/examples/widgets/itemviews/chart/mydata.cht @@ -0,0 +1,8 @@ +London,4,red +Stockholm,5,pink +Paris,2,lightgreen +Rome,11,green +Lisbon,9,blue +Madrid,8,lightblue +Berlin,6,magenta +Vienna,7,purple diff --git a/examples/widgets/itemviews/chart/pieview.cpp b/examples/widgets/itemviews/chart/pieview.cpp new file mode 100644 index 0000000000..30f3255689 --- /dev/null +++ b/examples/widgets/itemviews/chart/pieview.cpp @@ -0,0 +1,557 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#ifndef M_PI +#define M_PI 3.1415927 +#endif + +#include "pieview.h" + +PieView::PieView(QWidget *parent) + : QAbstractItemView(parent) +{ + horizontalScrollBar()->setRange(0, 0); + verticalScrollBar()->setRange(0, 0); + + margin = 8; + totalSize = 300; + pieSize = totalSize - 2*margin; + validItems = 0; + totalValue = 0.0; + rubberBand = 0; +} + +void PieView::dataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector &) +{ + QAbstractItemView::dataChanged(topLeft, bottomRight); + + 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).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 = pow(pow(cx, 2) + pow(cy, 2), 0.5); + + if (d == 0 || d > pieSize/2) + return QModelIndex(); + + // Determine the angle of the point. + double angle = (180 / M_PI) * acos(cx/d); + if (cy < 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 { + double itemHeight = QFontMetrics(viewOptions().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) { + + int listItem = 0; + for (int row = index.row()-1; row >= 0; --row) { + if (model()->data(model()->index(row, 1, rootIndex())).toDouble() > 0.0) + listItem++; + } + + double itemHeight; + + switch (index.column()) { + case 0: + itemHeight = QFontMetrics(viewOptions().font).height(); + + return QRect(totalSize, + int(margin + listItem*itemHeight), + totalSize - margin, int(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->pos(); + 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->pos()).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 = viewOptions(); + + 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) { + + 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(); + + int keyNumber = 0; + + 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 = viewOptions(); + 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); + + keyNumber++; + } + } + } +} + +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[0].row(); + int lastRow = indexes[0].row(); + int firstColumn = indexes[0].column(); + int lastColumn = indexes[0].column(); + + for (int i = 1; i < indexes.size(); ++i) { + firstRow = qMin(firstRow, indexes[i].row()); + lastRow = qMax(lastRow, indexes[i].row()); + firstColumn = qMin(firstColumn, indexes[i].column()); + lastColumn = qMax(lastColumn, indexes[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 QRect(rect.left() - horizontalScrollBar()->value(), + rect.top() - verticalScrollBar()->value(), + rect.width(), rect.height()); + else + return rect; +} + +/* + 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) { + 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; +} diff --git a/examples/widgets/itemviews/chart/pieview.h b/examples/widgets/itemviews/chart/pieview.h new file mode 100644 index 0000000000..208159bf73 --- /dev/null +++ b/examples/widgets/itemviews/chart/pieview.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PIEVIEW_H +#define PIEVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QRubberBand; +QT_END_NAMESPACE + +//! [0] +class PieView : public QAbstractItemView +{ + Q_OBJECT + +public: + PieView(QWidget *parent = 0); + + QRect visualRect(const QModelIndex &index) const; + void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible); + QModelIndex indexAt(const QPoint &point) const; + +protected slots: + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector & = QVector()); + void rowsInserted(const QModelIndex &parent, int start, int end); + void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + +protected: + bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event); + QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction, + Qt::KeyboardModifiers modifiers); + + int horizontalOffset() const; + int verticalOffset() const; + + bool isIndexHidden(const QModelIndex &index) const; + + void setSelection(const QRect&, QItemSelectionModel::SelectionFlags command); + + void mousePressEvent(QMouseEvent *event); + + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + void scrollContentsBy(int dx, int dy); + + QRegion visualRegionForSelection(const QItemSelection &selection) const; + +private: + QRect itemRect(const QModelIndex &item) const; + QRegion itemRegion(const QModelIndex &index) const; + int rows(const QModelIndex &index = QModelIndex()) const; + void updateGeometries(); + + int margin; + int totalSize; + int pieSize; + int validItems; + double totalValue; + QPoint origin; + QRubberBand *rubberBand; +}; +//! [0] + +#endif diff --git a/examples/widgets/itemviews/chart/qtdata.cht b/examples/widgets/itemviews/chart/qtdata.cht new file mode 100644 index 0000000000..6386246c4b --- /dev/null +++ b/examples/widgets/itemviews/chart/qtdata.cht @@ -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 -- cgit v1.2.3