6.5.3 clean

This commit is contained in:
kleuter
2023-11-01 18:02:52 +01:00
parent bbe896803b
commit 7018d9e6c8
2170 changed files with 57471 additions and 43550 deletions

View 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}"
)

View 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

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/Charts" >
<file>qtdata.cht</file>
</qresource>
</RCC>

View 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();
}

View 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);
}

View 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

View 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;
}

View 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

View 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

View File

@ -0,0 +1,36 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(dirview LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/dirview")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(dirview
main.cpp
)
set_target_properties(dirview PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(dirview PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS dirview
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,8 @@
QT += widgets
requires(qtConfig(treeview))
SOURCES = main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/dirview
INSTALLS += target

View File

@ -0,0 +1,62 @@
// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QFileSystemModel>
#include <QFileIconProvider>
#include <QScreen>
#include <QScroller>
#include <QTreeView>
#include <QCommandLineParser>
#include <QCommandLineOption>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription("Qt Dir View Example");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption dontUseCustomDirectoryIconsOption("c", "Set QFileSystemModel::DontUseCustomDirectoryIcons");
parser.addOption(dontUseCustomDirectoryIconsOption);
QCommandLineOption dontWatchOption("w", "Set QFileSystemModel::DontWatch");
parser.addOption(dontWatchOption);
parser.addPositionalArgument("directory", "The directory to start in.");
parser.process(app);
const QString rootPath = parser.positionalArguments().isEmpty()
? QString() : parser.positionalArguments().first();
QFileSystemModel model;
QFileIconProvider iconProvider;
model.setIconProvider(&iconProvider);
model.setRootPath("");
if (parser.isSet(dontUseCustomDirectoryIconsOption))
model.setOption(QFileSystemModel::DontUseCustomDirectoryIcons);
if (parser.isSet(dontWatchOption))
model.setOption(QFileSystemModel::DontWatchForChanges);
QTreeView tree;
tree.setModel(&model);
if (!rootPath.isEmpty()) {
const QModelIndex rootIndex = model.index(QDir::cleanPath(rootPath));
if (rootIndex.isValid())
tree.setRootIndex(rootIndex);
}
// Demonstrating look and feel features
tree.setAnimated(false);
tree.setIndentation(20);
tree.setSortingEnabled(true);
const QSize availableSize = tree.screen()->availableGeometry().size();
tree.resize(availableSize / 2);
tree.setColumnWidth(0, tree.width() / 3);
// Make it flickable on touchscreens
QScroller::grabGesture(&tree, QScroller::TouchGesture);
tree.setWindowTitle(QObject::tr("Dir View"));
tree.show();
return app.exec();
}

View File

@ -0,0 +1,51 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(interview LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/interview")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(interview
main.cpp
model.cpp model.h
)
set_target_properties(interview PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(interview PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(interview_resource_files
"images/folder.png"
"images/interview.png"
"images/services.png"
)
qt_add_resources(interview "interview"
PREFIX
"/"
FILES
${interview_resource_files}
)
install(TARGETS interview
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,2 @@
The interview example shows the same model and selection being shared
between three different views.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,16 @@
TEMPLATE = app
QT += widgets
requires(qtConfig(treeview))
HEADERS += model.h
SOURCES += model.cpp main.cpp
RESOURCES += interview.qrc
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/interview
INSTALLS += target

View File

@ -0,0 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>images/folder.png</file>
<file>images/services.png</file>
<file>images/interview.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,55 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "model.h"
#include <QApplication>
#include <QHeaderView>
#include <QListView>
#include <QSplitter>
#include <QTableView>
#include <QTreeView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSplitter page;
QAbstractItemModel *data = new Model(1000, 10, &page);
QItemSelectionModel *selections = new QItemSelectionModel(data);
QTableView *table = new QTableView;
table->setModel(data);
table->setSelectionModel(selections);
table->horizontalHeader()->setSectionsMovable(true);
table->verticalHeader()->setSectionsMovable(true);
// Set StaticContents to enable minimal repaints on resizes.
table->viewport()->setAttribute(Qt::WA_StaticContents);
page.addWidget(table);
QTreeView *tree = new QTreeView;
tree->setModel(data);
tree->setSelectionModel(selections);
tree->setUniformRowHeights(true);
tree->header()->setStretchLastSection(false);
tree->viewport()->setAttribute(Qt::WA_StaticContents);
// Disable the focus rect to get minimal repaints when scrolling on Mac.
tree->setAttribute(Qt::WA_MacShowFocusRect, false);
page.addWidget(tree);
QListView *list = new QListView;
list->setModel(data);
list->setSelectionModel(selections);
list->setViewMode(QListView::IconMode);
list->setSelectionMode(QAbstractItemView::ExtendedSelection);
list->setAlternatingRowColors(false);
list->viewport()->setAttribute(Qt::WA_StaticContents);
list->setAttribute(Qt::WA_MacShowFocusRect, false);
page.addWidget(list);
page.setWindowIcon(QPixmap(":/images/interview.png"));
page.setWindowTitle("Interview");
page.show();
return app.exec();
}

View File

@ -0,0 +1,110 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "model.h"
#include <QPixmap>
Model::Model(int rows, int columns, QObject *parent)
: QAbstractItemModel(parent),
services(QPixmap(":/images/services.png")),
rc(rows),
cc(columns),
tree(new QList<Node>(rows, Node()))
{
}
Model::~Model()
{
delete tree;
}
QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if (row < rc && row >= 0 && column < cc && column >= 0) {
Node *parentNode = static_cast<Node*>(parent.internalPointer());
Node *childNode = node(row, parentNode);
if (childNode)
return createIndex(row, column, childNode);
}
return QModelIndex();
}
QModelIndex Model::parent(const QModelIndex &child) const
{
if (child.isValid()) {
Node *childNode = static_cast<Node*>(child.internalPointer());
Node *parentNode = parent(childNode);
if (parentNode)
return createIndex(row(parentNode), 0, parentNode);
}
return QModelIndex();
}
int Model::rowCount(const QModelIndex &parent) const
{
return (parent.isValid() && parent.column() != 0) ? 0 : rc;
}
int Model::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return cc;
}
QVariant Model::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant("Item " + QString::number(index.row()) + ':' + QString::number(index.column()));
if (role == Qt::DecorationRole) {
if (index.column() == 0)
return iconProvider.icon(QFileIconProvider::Folder);
return iconProvider.icon(QFileIconProvider::File);
}
return QVariant();
}
QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole)
return QString::number(section);
if (role == Qt::DecorationRole)
return QVariant::fromValue(services);
return QAbstractItemModel::headerData(section, orientation, role);
}
bool Model::hasChildren(const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return false;
return rc > 0 && cc > 0;
}
Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
if (!index.isValid())
return {};
return Qt::ItemIsDragEnabled|QAbstractItemModel::flags(index);
}
Model::Node *Model::node(int row, Node *parent) const
{
if (parent && !parent->children)
parent->children = new QList<Node>(rc, Node(parent));
QList<Node> *v = parent ? parent->children : tree;
return const_cast<Node*>(&(v->at(row)));
}
Model::Node *Model::parent(Node *child) const
{
return child ? child->parent : nullptr;
}
int Model::row(Node *node) const
{
const Node *first = node->parent ? &(node->parent->children->at(0)) : &(tree->at(0));
return node - first;
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MODEL_H
#define MODEL_H
#include <QAbstractItemModel>
#include <QFileIconProvider>
#include <QIcon>
#include <QList>
class Model : public QAbstractItemModel
{
Q_OBJECT
public:
Model(int rows, int columns, QObject *parent = nullptr);
~Model();
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool hasChildren(const QModelIndex &parent) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
private:
struct Node
{
Node(Node *parent = nullptr) : parent(parent), children(nullptr) {}
~Node() { delete children; }
Node *parent;
QList<Node> *children;
};
Node *node(int row, Node *parent) const;
Node *parent(Node *child) const;
int row(Node *node) const;
QIcon services;
int rc;
int cc;
QList<Node> *tree;
QFileIconProvider iconProvider;
};
#endif // MODEL_H

View File

@ -0,0 +1,58 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(pixelator LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/pixelator")
find_package(Qt6
REQUIRED COMPONENTS Core Gui Widgets
OPTIONAL_COMPONENTS PrintSupport
)
qt_standard_project_setup()
qt_add_executable(pixelator
imagemodel.cpp imagemodel.h
main.cpp
mainwindow.cpp mainwindow.h
pixeldelegate.cpp pixeldelegate.h
)
set_target_properties(pixelator PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(pixelator PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
if(TARGET Qt6::PrintSupport)
target_link_libraries(pixelator PRIVATE Qt6::PrintSupport)
endif()
# Resources:
set(images_resource_files
"images/qt.png"
)
qt_add_resources(pixelator "images"
PREFIX
"/"
FILES
${images_resource_files}
)
install(TARGETS pixelator
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,53 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "imagemodel.h"
//! [0]
ImageModel::ImageModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
//! [0]
//! [1]
void ImageModel::setImage(const QImage &image)
{
beginResetModel();
modelImage = image;
endResetModel();
}
//! [1]
//! [2]
int ImageModel::rowCount(const QModelIndex & /* parent */) const
{
return modelImage.height();
}
int ImageModel::columnCount(const QModelIndex & /* parent */) const
//! [2] //! [3]
{
return modelImage.width();
}
//! [3]
//! [4]
QVariant ImageModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || role != Qt::DisplayRole)
return QVariant();
return qGray(modelImage.pixel(index.column(), index.row()));
}
//! [4]
//! [5]
QVariant ImageModel::headerData(int /* section */,
Qt::Orientation /* orientation */,
int role) const
{
if (role == Qt::SizeHintRole)
return QSize(1, 1);
return QVariant();
}
//! [5]

View File

@ -0,0 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef IMAGEMODEL_H
#define IMAGEMODEL_H
#include <QAbstractTableModel>
#include <QImage>
//! [0]
class ImageModel : public QAbstractTableModel
{
Q_OBJECT
public:
ImageModel(QObject *parent = nullptr);
void setImage(const QImage &image);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
private:
QImage modelImage;
};
//! [0]
#endif // IMAGEMODEL_H

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/qt.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,15 @@
// 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();
window.openImage(":/images/qt.png");
return app.exec();
}

View File

@ -0,0 +1,214 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "imagemodel.h"
#include "pixeldelegate.h"
#include <QtWidgets>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
#include <QPrinter>
#include <QPrintDialog>
#endif
#endif
//! [0]
MainWindow::MainWindow()
{
//! [0]
currentPath = QDir::homePath();
model = new ImageModel(this);
QWidget *centralWidget = new QWidget;
//! [1]
view = new QTableView;
view->setShowGrid(false);
view->horizontalHeader()->hide();
view->verticalHeader()->hide();
view->horizontalHeader()->setMinimumSectionSize(1);
view->verticalHeader()->setMinimumSectionSize(1);
view->setModel(model);
//! [1]
//! [2]
PixelDelegate *delegate = new PixelDelegate(this);
view->setItemDelegate(delegate);
//! [2]
//! [3]
QLabel *pixelSizeLabel = new QLabel(tr("Pixel size:"));
QSpinBox *pixelSizeSpinBox = new QSpinBox;
pixelSizeSpinBox->setMinimum(4);
pixelSizeSpinBox->setMaximum(32);
pixelSizeSpinBox->setValue(12);
//! [3]
QMenu *fileMenu = new QMenu(tr("&File"), this);
QAction *openAction = fileMenu->addAction(tr("&Open..."));
openAction->setShortcuts(QKeySequence::Open);
printAction = fileMenu->addAction(tr("&Print..."));
printAction->setEnabled(false);
printAction->setShortcut(QKeySequence::Print);
QAction *quitAction = fileMenu->addAction(tr("E&xit"));
quitAction->setShortcuts(QKeySequence::Quit);
QMenu *helpMenu = new QMenu(tr("&Help"), this);
QAction *aboutAction = helpMenu->addAction(tr("&About"));
menuBar()->addMenu(fileMenu);
menuBar()->addSeparator();
menuBar()->addMenu(helpMenu);
connect(openAction, &QAction::triggered, this, &MainWindow::chooseImage);
connect(printAction, &QAction::triggered, this, &MainWindow::printImage);
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutBox);
//! [4]
connect(pixelSizeSpinBox, &QSpinBox::valueChanged,
delegate, &PixelDelegate::setPixelSize);
connect(pixelSizeSpinBox, &QSpinBox::valueChanged,
this, &MainWindow::updateView);
//! [4]
QHBoxLayout *controlsLayout = new QHBoxLayout;
controlsLayout->addWidget(pixelSizeLabel);
controlsLayout->addWidget(pixelSizeSpinBox);
controlsLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(view);
mainLayout->addLayout(controlsLayout);
centralWidget->setLayout(mainLayout);
setCentralWidget(centralWidget);
setWindowTitle(tr("Pixelator"));
resize(640, 480);
//! [5]
}
//! [5]
void MainWindow::chooseImage()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Choose an image"), currentPath, "*");
if (!fileName.isEmpty())
openImage(fileName);
}
void MainWindow::openImage(const QString &fileName)
{
QImage image;
if (image.load(fileName)) {
model->setImage(image);
if (!fileName.startsWith(":/")) {
currentPath = fileName;
setWindowTitle(tr("%1 - Pixelator").arg(currentPath));
}
printAction->setEnabled(true);
updateView();
}
}
void MainWindow::printImage()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
if (model->rowCount(QModelIndex())*model->columnCount(QModelIndex()) > 90000) {
QMessageBox::StandardButton answer;
answer = QMessageBox::question(this, tr("Large Image Size"),
tr("The printed image may be very large. Are you sure that "
"you want to print it?"),
QMessageBox::Yes | QMessageBox::No);
if (answer == QMessageBox::No)
return;
}
QPrinter printer(QPrinter::HighResolution);
QPrintDialog dlg(&printer, this);
dlg.setWindowTitle(tr("Print Image"));
if (dlg.exec() != QDialog::Accepted) {
return;
}
QPainter painter;
painter.begin(&printer);
int rows = model->rowCount(QModelIndex());
int columns = model->columnCount(QModelIndex());
int sourceWidth = (columns + 1) * ItemSize;
int sourceHeight = (rows + 1) * ItemSize;
painter.save();
double xscale = printer.pageRect(QPrinter::DevicePixel).width() / double(sourceWidth);
double yscale = printer.pageRect(QPrinter::DevicePixel).height() / double(sourceHeight);
double scale = qMin(xscale, yscale);
painter.translate(printer.paperRect(QPrinter::DevicePixel).x() + printer.pageRect(QPrinter::DevicePixel).width() / 2,
printer.paperRect(QPrinter::DevicePixel).y() + printer.pageRect(QPrinter::DevicePixel).height() / 2);
painter.scale(scale, scale);
painter.translate(-sourceWidth / 2, -sourceHeight / 2);
QStyleOptionViewItem option;
QModelIndex parent = QModelIndex();
QProgressDialog progress(tr("Printing..."), tr("Cancel"), 0, rows, this);
progress.setWindowModality(Qt::ApplicationModal);
float y = ItemSize / 2;
for (int row = 0; row < rows; ++row) {
progress.setValue(row);
qApp->processEvents();
if (progress.wasCanceled())
break;
float x = ItemSize / 2;
for (int column = 0; column < columns; ++column) {
option.rect = QRect(int(x), int(y), ItemSize, ItemSize);
view->itemDelegate()->paint(&painter, option,
model->index(row, column, parent));
x = x + ItemSize;
}
y = y + ItemSize;
}
progress.setValue(rows);
painter.restore();
painter.end();
if (progress.wasCanceled()) {
QMessageBox::information(this, tr("Printing canceled"),
tr("The printing process was canceled."), QMessageBox::Cancel);
}
#else
QMessageBox::information(this, tr("Printing canceled"),
tr("Printing is not supported on this Qt build"), QMessageBox::Cancel);
#endif
}
void MainWindow::showAboutBox()
{
QMessageBox::about(this, tr("About the Pixelator example"),
tr("This example demonstrates how a standard view and a custom\n"
"delegate can be used to produce a specialized representation\n"
"of data in a simple custom model."));
}
//! [6]
void MainWindow::updateView()
{
view->resizeColumnsToContents();
view->resizeRowsToContents();
}
//! [6]

View File

@ -0,0 +1,37 @@
// 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>
class ImageModel;
QT_BEGIN_NAMESPACE
class QAction;
class QTableView;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
void openImage(const QString &fileName);
public slots:
void chooseImage();
void printImage();
void showAboutBox();
void updateView();
private:
ImageModel *model;
QAction *printAction;
QString currentPath;
QTableView *view;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,16 @@
QT += widgets
requires(qtConfig(tableview))
qtHaveModule(printsupport): QT += printsupport
HEADERS = imagemodel.h \
mainwindow.h \
pixeldelegate.h
SOURCES = imagemodel.cpp \
main.cpp \
mainwindow.cpp \
pixeldelegate.cpp
RESOURCES += images.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/pixelator
INSTALLS += target

View File

@ -0,0 +1,68 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "pixeldelegate.h"
#include <QPainter>
//! [0]
PixelDelegate::PixelDelegate(QObject *parent)
: QAbstractItemDelegate(parent), pixelSize(12)
{}
//! [0]
//! [1]
void PixelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
//! [2]
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
//! [1]
//! [3]
const int size = qMin(option.rect.width(), option.rect.height());
//! [3] //! [4]
const int brightness = index.model()->data(index, Qt::DisplayRole).toInt();
const double radius = (size / 2.0) - (brightness / 255.0 * size / 2.0);
if (qFuzzyIsNull(radius))
return;
//! [4]
//! [5]
painter->save();
//! [5] //! [6]
painter->setRenderHint(QPainter::Antialiasing, true);
//! [6] //! [7]
painter->setPen(Qt::NoPen);
//! [7] //! [8]
if (option.state & QStyle::State_Selected)
//! [8] //! [9]
painter->setBrush(option.palette.highlightedText());
else
//! [2]
painter->setBrush(option.palette.text());
//! [9]
//! [10]
painter->drawEllipse(QRectF(option.rect.x() + option.rect.width() / 2 - radius,
option.rect.y() + option.rect.height() / 2 - radius,
2 * radius, 2 * radius));
painter->restore();
}
//! [10]
//! [11]
QSize PixelDelegate::sizeHint(const QStyleOptionViewItem & /* option */,
const QModelIndex & /* index */) const
{
return QSize(pixelSize, pixelSize);
}
//! [11]
//! [12]
void PixelDelegate::setPixelSize(int size)
{
pixelSize = size;
}
//! [12]

View File

@ -0,0 +1,41 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef PIXELDELEGATE_H
#define PIXELDELEGATE_H
#include <QAbstractItemDelegate>
#include <QModelIndex>
#include <QSize>
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QObject;
class QPainter;
QT_END_NAMESPACE
static constexpr int ItemSize = 256;
//! [0]
class PixelDelegate : public QAbstractItemDelegate
{
Q_OBJECT
public:
PixelDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
public slots:
void setPixelSize(int size);
private:
int pixelSize;
};
//! [0]
#endif // PIXELDELEGATE_H

View File

@ -0,0 +1,51 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(puzzle LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/puzzle")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(itemviews_puzzle
main.cpp
mainwindow.cpp mainwindow.h
piecesmodel.cpp piecesmodel.h
puzzlewidget.cpp puzzlewidget.h
)
set_target_properties(itemviews_puzzle PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(itemviews_puzzle PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(puzzle_resource_files
"example.jpg"
)
qt_add_resources(itemviews_puzzle "puzzle"
PREFIX
"/images"
FILES
${puzzle_resource_files}
)
install(TARGETS itemviews_puzzle
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.loadImage(QStringLiteral(":/images/example.jpg"));
window.show();
return app.exec();
}

View File

@ -0,0 +1,115 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "piecesmodel.h"
#include "puzzlewidget.h"
#include <QtWidgets>
#include <stdlib.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupMenus();
setupWidgets();
model = new PiecesModel(puzzleWidget->pieceSize(), this);
piecesList->setModel(model);
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
setWindowTitle(tr("Puzzle"));
}
void MainWindow::openImage()
{
const QString directory =
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
QFileDialog dialog(this, tr("Open Image"), directory);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::ExistingFile);
QStringList mimeTypeFilters;
for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
if (dialog.exec() == QDialog::Accepted)
loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
{
QPixmap newImage;
if (!newImage.load(fileName)) {
QMessageBox::warning(this, tr("Open Image"),
tr("The image file could not be loaded."),
QMessageBox::Close);
return;
}
puzzleImage = newImage;
setupPuzzle();
}
void MainWindow::setCompleted()
{
QMessageBox::information(this, tr("Puzzle Completed"),
tr("Congratulations! You have completed the puzzle!\n"
"Click OK to start again."),
QMessageBox::Ok);
setupPuzzle();
}
void MainWindow::setupPuzzle()
{
int size = qMin(puzzleImage.width(), puzzleImage.height());
puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2,
(puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->imageSize(),
puzzleWidget->imageSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
model->addPieces(puzzleImage);
puzzleWidget->clear();
}
void MainWindow::setupMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage);
openAction->setShortcuts(QKeySequence::Open);
QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit);
exitAction->setShortcuts(QKeySequence::Quit);
QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));
gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle);
}
void MainWindow::setupWidgets()
{
QFrame *frame = new QFrame;
QHBoxLayout *frameLayout = new QHBoxLayout(frame);
puzzleWidget = new PuzzleWidget(400);
piecesList = new QListView;
piecesList->setDragEnabled(true);
piecesList->setViewMode(QListView::IconMode);
piecesList->setIconSize(QSize(puzzleWidget->pieceSize() - 20, puzzleWidget->pieceSize() - 20));
piecesList->setGridSize(QSize(puzzleWidget->pieceSize(), puzzleWidget->pieceSize()));
piecesList->setSpacing(10);
piecesList->setMovement(QListView::Snap);
piecesList->setAcceptDrops(true);
piecesList->setDropIndicatorShown(true);
PiecesModel *model = new PiecesModel(puzzleWidget->pieceSize(), this);
piecesList->setModel(model);
connect(puzzleWidget, &PuzzleWidget::puzzleCompleted,
this, &MainWindow::setCompleted, Qt::QueuedConnection);
frameLayout->addWidget(piecesList);
frameLayout->addWidget(puzzleWidget);
setCentralWidget(frame);
}

View File

@ -0,0 +1,41 @@
// 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>
#include <QPixmap>
class PuzzleWidget;
class PiecesModel;
QT_BEGIN_NAMESPACE
class QListView;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
public slots:
void openImage();
void loadImage(const QString &path);
void setupPuzzle();
private slots:
void setCompleted();
private:
void setupMenus();
void setupWidgets();
QPixmap puzzleImage;
QListView *piecesList;
PuzzleWidget *puzzleWidget;
PiecesModel *model;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,168 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "piecesmodel.h"
#include <QIcon>
#include <QMimeData>
#include <QRandomGenerator>
PiecesModel::PiecesModel(int pieceSize, QObject *parent)
: QAbstractListModel(parent), m_PieceSize(pieceSize)
{
}
QVariant PiecesModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DecorationRole)
return QIcon(pixmaps.value(index.row()).scaled(m_PieceSize, m_PieceSize,
Qt::KeepAspectRatio, Qt::SmoothTransformation));
else if (role == Qt::UserRole)
return pixmaps.value(index.row());
else if (role == Qt::UserRole + 1)
return locations.value(index.row());
return QVariant();
}
void PiecesModel::addPiece(const QPixmap &pixmap, const QPoint &location)
{
int row;
if (QRandomGenerator::global()->bounded(2) == 1)
row = 0;
else
row = pixmaps.size();
beginInsertRows(QModelIndex(), row, row);
pixmaps.insert(row, pixmap);
locations.insert(row, location);
endInsertRows();
}
Qt::ItemFlags PiecesModel::flags(const QModelIndex &index) const
{
if (index.isValid())
return (QAbstractListModel::flags(index)|Qt::ItemIsDragEnabled);
return Qt::ItemIsDropEnabled;
}
bool PiecesModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (parent.isValid())
return false;
if (row >= pixmaps.size() || row + count <= 0)
return false;
int beginRow = qMax(0, row);
int endRow = qMin(row + count - 1, pixmaps.size() - 1);
beginRemoveRows(parent, beginRow, endRow);
while (beginRow <= endRow) {
pixmaps.removeAt(beginRow);
locations.removeAt(beginRow);
++beginRow;
}
endRemoveRows();
return true;
}
QStringList PiecesModel::mimeTypes() const
{
QStringList types;
types << "image/x-puzzle-piece";
return types;
}
QMimeData *PiecesModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QDataStream::WriteOnly);
for (const QModelIndex &index : indexes) {
if (index.isValid()) {
QPixmap pixmap = qvariant_cast<QPixmap>(data(index, Qt::UserRole));
QPoint location = data(index, Qt::UserRole+1).toPoint();
stream << pixmap << location;
}
}
mimeData->setData("image/x-puzzle-piece", encodedData);
return mimeData;
}
bool PiecesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
if (!data->hasFormat("image/x-puzzle-piece"))
return false;
if (action == Qt::IgnoreAction)
return true;
if (column > 0)
return false;
int endRow;
if (!parent.isValid()) {
if (row < 0)
endRow = pixmaps.size();
else
endRow = qMin(row, pixmaps.size());
} else {
endRow = parent.row();
}
QByteArray encodedData = data->data("image/x-puzzle-piece");
QDataStream stream(&encodedData, QDataStream::ReadOnly);
while (!stream.atEnd()) {
QPixmap pixmap;
QPoint location;
stream >> pixmap >> location;
beginInsertRows(QModelIndex(), endRow, endRow);
pixmaps.insert(endRow, pixmap);
locations.insert(endRow, location);
endInsertRows();
++endRow;
}
return true;
}
int PiecesModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : pixmaps.size();
}
Qt::DropActions PiecesModel::supportedDropActions() const
{
return Qt::CopyAction | Qt::MoveAction;
}
void PiecesModel::addPieces(const QPixmap &pixmap)
{
if (!pixmaps.isEmpty()) {
beginRemoveRows(QModelIndex(), 0, pixmaps.size() - 1);
pixmaps.clear();
locations.clear();
endRemoveRows();
}
for (int y = 0; y < 5; ++y) {
for (int x = 0; x < 5; ++x) {
QPixmap pieceImage = pixmap.copy(x*m_PieceSize, y*m_PieceSize, m_PieceSize, m_PieceSize);
addPiece(pieceImage, QPoint(x, y));
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef PIECESLIST_H
#define PIECESLIST_H
#include <QAbstractListModel>
#include <QPixmap>
#include <QPoint>
#include <QStringList>
#include <QList>
QT_BEGIN_NAMESPACE
class QMimeData;
QT_END_NAMESPACE
class PiecesModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit PiecesModel(int pieceSize, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool removeRows(int row, int count, const QModelIndex &parent) override;
bool dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent) override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
QStringList mimeTypes() const override;
int rowCount(const QModelIndex &parent) const override;
Qt::DropActions supportedDropActions() const override;
void addPiece(const QPixmap &pixmap, const QPoint &location);
void addPieces(const QPixmap &pixmap);
private:
QList<QPoint> locations;
QList<QPixmap> pixmaps;
int m_PieceSize;
};
#endif // PIECESLIST_H

View File

@ -0,0 +1,15 @@
QT += widgets
requires(qtConfig(listview))
HEADERS = mainwindow.h \
piecesmodel.h \
puzzlewidget.h
RESOURCES = puzzle.qrc
SOURCES = main.cpp \
mainwindow.cpp \
piecesmodel.cpp \
puzzlewidget.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/puzzle
INSTALLS += target

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/images">
<file>example.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,163 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "puzzlewidget.h"
#include <QtWidgets>
PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
: QWidget(parent), m_ImageSize(imageSize)
{
setAcceptDrops(true);
setMinimumSize(m_ImageSize, m_ImageSize);
setMaximumSize(m_ImageSize, m_ImageSize);
}
void PuzzleWidget::clear()
{
pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
}
void PuzzleWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("image/x-puzzle-piece"))
event->accept();
else
event->ignore();
}
void PuzzleWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
QRect updateRect = highlightedRect;
highlightedRect = QRect();
update(updateRect);
event->accept();
}
void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
{
QRect updateRect = highlightedRect.united(targetSquare(event->position().toPoint()));
if (event->mimeData()->hasFormat("image/x-puzzle-piece")
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
highlightedRect = targetSquare(event->position().toPoint());
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
highlightedRect = QRect();
event->ignore();
}
update(updateRect);
}
void PuzzleWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("image/x-puzzle-piece")
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece");
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
Piece piece;
piece.rect = targetSquare(event->position().toPoint());
dataStream >> piece.pixmap >> piece.location;
pieces.append(piece);
highlightedRect = QRect();
update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
}
} else {
highlightedRect = QRect();
event->ignore();
}
}
int PuzzleWidget::findPiece(const QRect &pieceRect) const
{
for (int i = 0, size = pieces.size(); i < size; ++i) {
if (pieces.at(i).rect == pieceRect)
return i;
}
return -1;
}
void PuzzleWidget::mousePressEvent(QMouseEvent *event)
{
QRect square = targetSquare(event->position().toPoint());
int found = findPiece(square);
if (found == -1)
return;
Piece piece = pieces.takeAt(found);
if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData("image/x-puzzle-piece", itemData);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->position().toPoint() - square.topLeft());
drag->setPixmap(piece.pixmap);
if (drag->exec(Qt::MoveAction) == Qt::IgnoreAction) {
pieces.insert(found, piece);
update(targetSquare(event->position().toPoint()));
if (piece.location == QPoint(square.x() / pieceSize(), square.y() / pieceSize()))
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
painter.setBrush(QColor("#ffcccc"));
painter.setPen(Qt::NoPen);
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
for (const Piece &piece : pieces)
painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
QPoint topLeft = QPoint(position.x() / pieceSize(), position.y() / pieceSize()) * pieceSize();
return QRect(topLeft, QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const
{
return m_ImageSize / 5;
}
int PuzzleWidget::imageSize() const
{
return m_ImageSize;
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
#include <QPoint>
#include <QPixmap>
#include <QList>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDragEnterEvent;
class QDropEvent;
class QMouseEvent;
QT_END_NAMESPACE
class PuzzleWidget : public QWidget
{
Q_OBJECT
public:
explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
int imageSize() const;
signals:
void puzzleCompleted();
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragLeaveEvent(QDragLeaveEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
struct Piece {
QPixmap pixmap;
QRect rect;
QPoint location;
};
int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
QList<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;
};
#endif // PUZZLEWIDGET_H

View File

@ -0,0 +1,40 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(simpledommodel LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/simpledommodel")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Xml)
qt_standard_project_setup()
qt_add_executable(simpledommodel
domitem.cpp domitem.h
dommodel.cpp dommodel.h
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(simpledommodel PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(simpledommodel PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::Xml
)
install(TARGETS simpledommodel
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,62 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "domitem.h"
#include <QtXml>
//! [0]
DomItem::DomItem(const QDomNode &node, int row, DomItem *parent)
: domNode(node),
//! [0]
// Record the item's location within its parent.
//! [1]
parentItem(parent),
rowNumber(row)
{}
//! [1]
//! [2]
DomItem::~DomItem()
{
qDeleteAll(childItems);
}
//! [2]
//! [3]
QDomNode DomItem::node() const
{
return domNode;
}
//! [3]
//! [4]
DomItem *DomItem::parent()
{
return parentItem;
}
//! [4]
//! [5]
DomItem *DomItem::child(int i)
{
DomItem *childItem = childItems.value(i);
if (childItem)
return childItem;
// if child does not yet exist, create it
if (i >= 0 && i < domNode.childNodes().count()) {
QDomNode childNode = domNode.childNodes().item(i);
childItem = new DomItem(childNode, i, this);
childItems[i] = childItem;
}
return childItem;
}
//! [5]
//! [6]
int DomItem::row() const
{
return rowNumber;
}
//! [6]

View File

@ -0,0 +1,29 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DOMITEM_H
#define DOMITEM_H
#include <QDomNode>
#include <QHash>
//! [0]
class DomItem
{
public:
DomItem(const QDomNode &node, int row, DomItem *parent = nullptr);
~DomItem();
DomItem *child(int i);
DomItem *parent();
QDomNode node() const;
int row() const;
private:
QDomNode domNode;
QHash<int, DomItem *> childItems;
DomItem *parentItem;
int rowNumber;
};
//! [0]
#endif // DOMITEM_H

View File

@ -0,0 +1,153 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "dommodel.h"
#include "domitem.h"
#include <QtXml>
//! [0]
DomModel::DomModel(const QDomDocument &document, QObject *parent)
: QAbstractItemModel(parent),
domDocument(document),
rootItem(new DomItem(domDocument, 0))
{
}
//! [0]
//! [1]
DomModel::~DomModel()
{
delete rootItem;
}
//! [1]
//! [2]
int DomModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 3;
}
//! [2]
//! [3]
QVariant DomModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
const DomItem *item = static_cast<DomItem*>(index.internalPointer());
const QDomNode node = item->node();
//! [3] //! [4]
switch (index.column()) {
case 0:
return node.nodeName();
case 1:
{
const QDomNamedNodeMap attributeMap = node.attributes();
QStringList attributes;
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
attributes << attribute.nodeName() + "=\""
+ attribute.nodeValue() + '"';
}
return attributes.join(' ');
}
case 2:
return node.nodeValue().split('\n').join(' ');
default:
break;
}
return QVariant();
}
//! [4]
//! [5]
Qt::ItemFlags DomModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return QAbstractItemModel::flags(index);
}
//! [5]
//! [6]
QVariant DomModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Name");
case 1:
return tr("Attributes");
case 2:
return tr("Value");
default:
break;
}
}
return QVariant();
}
//! [6]
//! [7]
QModelIndex DomModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
DomItem *parentItem;
if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<DomItem*>(parent.internalPointer());
//! [7]
//! [8]
DomItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
return QModelIndex();
}
//! [8]
//! [9]
QModelIndex DomModel::parent(const QModelIndex &child) const
{
if (!child.isValid())
return QModelIndex();
DomItem *childItem = static_cast<DomItem*>(child.internalPointer());
DomItem *parentItem = childItem->parent();
if (!parentItem || parentItem == rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
//! [9]
//! [10]
int DomModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
DomItem *parentItem;
if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<DomItem*>(parent.internalPointer());
return parentItem->node().childNodes().count();
}
//! [10]

View File

@ -0,0 +1,38 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DOMMODEL_H
#define DOMMODEL_H
#include <QAbstractItemModel>
#include <QDomDocument>
#include <QModelIndex>
class DomItem;
//! [0]
class DomModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit DomModel(const QDomDocument &document, QObject *parent = nullptr);
~DomModel();
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
private:
QDomDocument domDocument;
DomItem *rootItem;
};
//! [0]
#endif // DOMMODEL_H

View File

@ -0,0 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.resize(640, 480);
window.show();
return app.exec();
}

View File

@ -0,0 +1,47 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "dommodel.h"
#include <QDomDocument>
#include <QTreeView>
#include <QMenuBar>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
model(new DomModel(QDomDocument(), this)),
view(new QTreeView(this))
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(tr("&Open..."), QKeySequence::Open, this, &MainWindow::openFile);
fileMenu->addAction(tr("E&xit"), QKeySequence::Quit, this, &QWidget::close);
view->setModel(model);
setCentralWidget(view);
setWindowTitle(tr("Simple DOM Model"));
}
void MainWindow::openFile()
{
QString filePath = QFileDialog::getOpenFileName(this, tr("Open File"),
xmlPath, tr("XML files (*.xml);;HTML files (*.html);;"
"SVG files (*.svg);;User Interface files (*.ui)"));
if (!filePath.isEmpty()) {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
QDomDocument document;
if (document.setContent(&file)) {
DomModel *newModel = new DomModel(document, this);
view->setModel(newModel);
delete model;
model = newModel;
xmlPath = filePath;
}
file.close();
}
}
}

View File

@ -0,0 +1,33 @@
// 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>
#include <QString>
class DomModel;
QT_BEGIN_NAMESPACE
class QMenu;
class QTreeView;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
public slots:
void openFile();
private:
DomModel *model;
QMenu *fileMenu;
QString xmlPath;
QTreeView *view;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,14 @@
HEADERS = domitem.h \
dommodel.h \
mainwindow.h
SOURCES = domitem.cpp \
dommodel.cpp \
main.cpp \
mainwindow.cpp
QT += xml widgets
requires(qtConfig(filedialog))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/simpledommodel
INSTALLS += target

View File

@ -0,0 +1,37 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(simplewidgetmapper LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/simplewidgetmapper")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(simplewidgetmapper
main.cpp
window.cpp window.h
)
set_target_properties(simplewidgetmapper PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(simplewidgetmapper PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS simplewidgetmapper
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,14 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include <QApplication>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}

View File

@ -0,0 +1,10 @@
QT += widgets
requires(qtConfig(datawidgetmapper))
HEADERS = window.h
SOURCES = main.cpp \
window.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/simplewidgetmapper
INSTALLS += target

View File

@ -0,0 +1,93 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include <QtWidgets>
//! [Set up widgets]
Window::Window(QWidget *parent)
: QWidget(parent)
{
setupModel();
nameLabel = new QLabel(tr("Na&me:"));
nameEdit = new QLineEdit();
addressLabel = new QLabel(tr("&Address:"));
addressEdit = new QTextEdit();
ageLabel = new QLabel(tr("A&ge (in years):"));
ageSpinBox = new QSpinBox();
nextButton = new QPushButton(tr("&Next"));
previousButton = new QPushButton(tr("&Previous"));
nameLabel->setBuddy(nameEdit);
addressLabel->setBuddy(addressEdit);
ageLabel->setBuddy(ageSpinBox);
//! [Set up widgets]
//! [Set up the mapper]
mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->addMapping(nameEdit, 0);
mapper->addMapping(addressEdit, 1);
mapper->addMapping(ageSpinBox, 2);
connect(previousButton, &QAbstractButton::clicked, mapper, &QDataWidgetMapper::toPrevious);
connect(nextButton, &QAbstractButton::clicked, mapper, &QDataWidgetMapper::toNext);
connect(mapper, &QDataWidgetMapper::currentIndexChanged, this, &Window::updateButtons);
//! [Set up the mapper]
//! [Set up the layout]
QGridLayout *layout = new QGridLayout();
layout->addWidget(nameLabel, 0, 0, 1, 1);
layout->addWidget(nameEdit, 0, 1, 1, 1);
layout->addWidget(previousButton, 0, 2, 1, 1);
layout->addWidget(addressLabel, 1, 0, 1, 1);
layout->addWidget(addressEdit, 1, 1, 2, 1);
layout->addWidget(nextButton, 1, 2, 1, 1);
layout->addWidget(ageLabel, 3, 0, 1, 1);
layout->addWidget(ageSpinBox, 3, 1, 1, 1);
setLayout(layout);
setWindowTitle(tr("Simple Widget Mapper"));
mapper->toFirst();
}
//! [Set up the layout]
//! [Set up the model]
void Window::setupModel()
{
model = new QStandardItemModel(5, 3, this);
QStringList names;
names << "Alice" << "Bob" << "Carol" << "Donald" << "Emma";
QStringList addresses;
addresses << "<qt>123 Main Street<br/>Market Town</qt>"
<< "<qt>PO Box 32<br/>Mail Handling Service"
"<br/>Service City</qt>"
<< "<qt>The Lighthouse<br/>Remote Island</qt>"
<< "<qt>47338 Park Avenue<br/>Big City</qt>"
<< "<qt>Research Station<br/>Base Camp<br/>Big Mountain</qt>";
QStringList ages;
ages << "20" << "31" << "32" << "19" << "26";
for (int row = 0; row < 5; ++row) {
QStandardItem *item = new QStandardItem(names[row]);
model->setItem(row, 0, item);
item = new QStandardItem(addresses[row]);
model->setItem(row, 1, item);
item = new QStandardItem(ages[row]);
model->setItem(row, 2, item);
}
}
//! [Set up the model]
//! [Slot for updating the buttons]
void Window::updateButtons(int row)
{
previousButton->setEnabled(row > 0);
nextButton->setEnabled(row < model->rowCount() - 1);
}
//! [Slot for updating the buttons]

View File

@ -0,0 +1,47 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDataWidgetMapper;
class QLabel;
class QLineEdit;
class QPushButton;
class QSpinBox;
class QStandardItemModel;
class QTextEdit;
QT_END_NAMESPACE
//! [Window definition]
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = nullptr);
private slots:
void updateButtons(int row);
private:
void setupModel();
QLabel *nameLabel;
QLabel *addressLabel;
QLabel *ageLabel;
QLineEdit *nameEdit;
QTextEdit *addressEdit;
QSpinBox *ageSpinBox;
QPushButton *nextButton;
QPushButton *previousButton;
QStandardItemModel *model;
QDataWidgetMapper *mapper;
};
//! [Window definition]
#endif // WINDOW_H

View File

@ -0,0 +1,37 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(storageview LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/storageview")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(storageview
main.cpp
storagemodel.cpp storagemodel.h
)
set_target_properties(storageview PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(storageview PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS storageview
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,32 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Ivan Komissarov
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QShortcut>
#include <QTreeView>
#include "storagemodel.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTreeView view;
view.resize(640, 480);
view.setWindowTitle("Storage View");
view.setSelectionBehavior(QAbstractItemView::SelectRows);
StorageModel *model = new StorageModel(&view);
model->refresh();
QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, &view);
QObject::connect(refreshShortcut, &QShortcut::activated, model, &StorageModel::refresh);
view.setModel(model);
int columnCount = view.model()->columnCount();
for (int c = 0; c < columnCount; ++c)
view.resizeColumnToContents(c);
view.show();
return a.exec();
}

View File

@ -0,0 +1,164 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Ivan Komissarov
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "storagemodel.h"
#include <QDir>
#include <QLocale>
void StorageModel::refresh()
{
beginResetModel();
m_volumes = QStorageInfo::mountedVolumes();
std::sort(m_volumes.begin(), m_volumes.end(),
[](const QStorageInfo &st1, const QStorageInfo &st2) {
static const QString rootSortString = QStringLiteral(" ");
return (st1.isRoot() ? rootSortString : st1.rootPath())
< (st2.isRoot() ? rootSortString : st2.rootPath());
});
endResetModel();
}
int StorageModel::columnCount(const QModelIndex &/*parent*/) const
{
return ColumnCount;
}
int StorageModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return m_volumes.count();
}
Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags result = QAbstractTableModel::flags(index);
switch (index.column()) {
case ColumnAvailable:
case ColumnIsReady:
case ColumnIsReadOnly:
case ColumnIsValid:
result |= Qt::ItemIsUserCheckable;
break;
default:
break;
}
return result;
}
QVariant StorageModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole) {
const QStorageInfo &volume = m_volumes.at(index.row());
switch (index.column()) {
case ColumnRootPath:
return QDir::toNativeSeparators(volume.rootPath());
case ColumnName:
return volume.name();
case ColumnDevice:
return volume.device();
case ColumnFileSystemName:
return volume.fileSystemType();
case ColumnTotal:
return QLocale().formattedDataSize(volume.bytesTotal());
case ColumnFree:
return QLocale().formattedDataSize(volume.bytesFree());
case ColumnAvailable:
return QLocale().formattedDataSize(volume.bytesAvailable());
default:
break;
}
} else if (role == Qt::CheckStateRole) {
const QStorageInfo &volume = m_volumes.at(index.row());
switch (index.column()) {
case ColumnIsReady:
return volume.isReady();
case ColumnIsReadOnly:
return volume.isReadOnly();
case ColumnIsValid:
return volume.isValid();
default:
break;
}
} else if (role == Qt::TextAlignmentRole) {
switch (index.column()) {
case ColumnTotal:
case ColumnFree:
case ColumnAvailable:
return Qt::AlignTrailing;
default:
break;
}
return Qt::AlignLeading;
} else if (role == Qt::ToolTipRole) {
QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row());
return tr("Root path : %1\n"
"Name: %2\n"
"Display Name: %3\n"
"Device: %4\n"
"FileSystem: %5\n"
"Total size: %6\n"
"Free size: %7\n"
"Available size: %8\n"
"Is Ready: %9\n"
"Is Read-only: %10\n"
"Is Valid: %11\n"
"Is Root: %12"
).
arg(QDir::toNativeSeparators(volume.rootPath())).
arg(volume.name()).
arg(volume.displayName()).
arg(QString::fromUtf8(volume.device())).
arg(QString::fromUtf8(volume.fileSystemType())).
arg(locale.formattedDataSize(volume.bytesTotal())).
arg(locale.formattedDataSize(volume.bytesFree())).
arg(locale.formattedDataSize(volume.bytesAvailable())).
arg(volume.isReady() ? tr("true") : tr("false")).
arg(volume.isReadOnly() ? tr("true") : tr("false")).
arg(volume.isValid() ? tr("true") : tr("false")).
arg(volume.isRoot() ? tr("true") : tr("false"));
}
return QVariant();
}
QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Horizontal)
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
switch (section) {
case ColumnRootPath:
return tr("Root Path");
case ColumnName:
return tr("Volume Name");
case ColumnDevice:
return tr("Device");
case ColumnFileSystemName:
return tr("File System");
case ColumnTotal:
return tr("Total");
case ColumnFree:
return tr("Free");
case ColumnAvailable:
return tr("Available");
case ColumnIsReady:
return tr("Ready");
case ColumnIsReadOnly:
return tr("Read-only");
case ColumnIsValid:
return tr("Valid");
default:
break;
}
return QVariant();
}

View File

@ -0,0 +1,46 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Ivan Komissarov
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef STORAGEMODEL_H
#define STORAGEMODEL_H
#include <QAbstractTableModel>
#include <QStorageInfo>
class StorageModel : public QAbstractTableModel
{
Q_OBJECT
Q_DISABLE_COPY(StorageModel)
public:
enum Column {
ColumnRootPath = 0,
ColumnName,
ColumnDevice,
ColumnFileSystemName,
ColumnTotal,
ColumnFree,
ColumnAvailable,
ColumnIsReady,
ColumnIsReadOnly,
ColumnIsValid,
ColumnCount
};
using QAbstractTableModel::QAbstractTableModel;
int columnCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
public slots:
void refresh();
private:
QList<QStorageInfo> m_volumes;
};
#endif // STORAGEMODEL_H

View File

@ -0,0 +1,12 @@
QT += core gui widgets
requires(qtConfig(treeview))
TARGET = storageview
TEMPLATE = app
SOURCES += storagemodel.cpp \
main.cpp
HEADERS += \
storagemodel.h
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/storageview
INSTALLS += target