mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 07:45:30 +08:00
qt 6.5.1 original
This commit is contained in:
28
examples/widgets/itemviews/CMakeLists.txt
Normal file
28
examples/widgets/itemviews/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
qt_internal_add_example(addressbook)
|
||||
qt_internal_add_example(basicsortfiltermodel)
|
||||
qt_internal_add_example(chart)
|
||||
qt_internal_add_example(coloreditorfactory)
|
||||
qt_internal_add_example(combowidgetmapper)
|
||||
qt_internal_add_example(customsortfiltermodel)
|
||||
qt_internal_add_example(dirview)
|
||||
qt_internal_add_example(editabletreemodel)
|
||||
qt_internal_add_example(fetchmore)
|
||||
qt_internal_add_example(flattreeview)
|
||||
qt_internal_add_example(frozencolumn)
|
||||
qt_internal_add_example(interview)
|
||||
qt_internal_add_example(pixelator)
|
||||
qt_internal_add_example(simpletreemodel)
|
||||
qt_internal_add_example(simplewidgetmapper)
|
||||
qt_internal_add_example(spinboxdelegate)
|
||||
qt_internal_add_example(spreadsheet)
|
||||
qt_internal_add_example(stardelegate)
|
||||
qt_internal_add_example(storageview)
|
||||
if(QT_FEATURE_draganddrop)
|
||||
qt_internal_add_example(puzzle)
|
||||
endif()
|
||||
if(TARGET Qt6::Xml)
|
||||
qt_internal_add_example(simpledommodel)
|
||||
endif()
|
8
examples/widgets/itemviews/README
Normal file
8
examples/widgets/itemviews/README
Normal file
@ -0,0 +1,8 @@
|
||||
Item views are widgets that typically display data sets. Qt 4's model/view
|
||||
framework lets you handle large data sets by separating the underlying data
|
||||
from the way it is represented to the user, and provides support for
|
||||
customized rendering through the use of delegates.
|
||||
|
||||
|
||||
Documentation for these examples can be found via the Examples
|
||||
link in the main Qt documentation.
|
41
examples/widgets/itemviews/addressbook/CMakeLists.txt
Normal file
41
examples/widgets/itemviews/addressbook/CMakeLists.txt
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(addressbook LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/addressbook")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(addressbook
|
||||
adddialog.cpp adddialog.h
|
||||
addresswidget.cpp addresswidget.h
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
newaddresstab.cpp newaddresstab.h
|
||||
tablemodel.cpp tablemodel.h
|
||||
)
|
||||
|
||||
set_target_properties(addressbook PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(addressbook PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS addressbook
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
59
examples/widgets/itemviews/addressbook/adddialog.cpp
Normal file
59
examples/widgets/itemviews/addressbook/adddialog.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "adddialog.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
AddDialog::AddDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
nameText(new QLineEdit),
|
||||
addressText(new QTextEdit)
|
||||
{
|
||||
auto nameLabel = new QLabel(tr("Name"));
|
||||
auto addressLabel = new QLabel(tr("Address"));
|
||||
auto okButton = new QPushButton(tr("OK"));
|
||||
auto cancelButton = new QPushButton(tr("Cancel"));
|
||||
|
||||
auto gLayout = new QGridLayout;
|
||||
gLayout->setColumnStretch(1, 2);
|
||||
gLayout->addWidget(nameLabel, 0, 0);
|
||||
gLayout->addWidget(nameText, 0, 1);
|
||||
|
||||
gLayout->addWidget(addressLabel, 1, 0, Qt::AlignLeft|Qt::AlignTop);
|
||||
gLayout->addWidget(addressText, 1, 1, Qt::AlignLeft);
|
||||
|
||||
auto buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(okButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
gLayout->addLayout(buttonLayout, 2, 1, Qt::AlignRight);
|
||||
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(gLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(okButton, &QAbstractButton::clicked, this, &QDialog::accept);
|
||||
connect(cancelButton, &QAbstractButton::clicked, this, &QDialog::reject);
|
||||
|
||||
setWindowTitle(tr("Add a Contact"));
|
||||
}
|
||||
|
||||
QString AddDialog::name() const
|
||||
{
|
||||
return nameText->text();
|
||||
}
|
||||
|
||||
QString AddDialog::address() const
|
||||
{
|
||||
return addressText->toPlainText();
|
||||
}
|
||||
|
||||
void AddDialog::editAddress(const QString &name, const QString &address)
|
||||
{
|
||||
nameText->setReadOnly(true);
|
||||
nameText->setText(name);
|
||||
addressText->setPlainText(address);
|
||||
}
|
||||
//! [0]
|
34
examples/widgets/itemviews/addressbook/adddialog.h
Normal file
34
examples/widgets/itemviews/addressbook/adddialog.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef ADDDIALOG_H
|
||||
#define ADDDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class QTextEdit;
|
||||
class QLineEdit;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
//! [0]
|
||||
class AddDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddDialog(QWidget *parent = nullptr);
|
||||
|
||||
QString name() const;
|
||||
QString address() const;
|
||||
void editAddress(const QString &name, const QString &address);
|
||||
|
||||
private:
|
||||
QLineEdit *nameText;
|
||||
QTextEdit *addressText;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // ADDDIALOG_H
|
18
examples/widgets/itemviews/addressbook/addressbook.pro
Normal file
18
examples/widgets/itemviews/addressbook/addressbook.pro
Normal file
@ -0,0 +1,18 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(listview))
|
||||
|
||||
SOURCES = adddialog.cpp \
|
||||
addresswidget.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
newaddresstab.cpp \
|
||||
tablemodel.cpp
|
||||
HEADERS = adddialog.h \
|
||||
addresswidget.h \
|
||||
mainwindow.h \
|
||||
newaddresstab.h \
|
||||
tablemodel.h
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/addressbook
|
||||
INSTALLS += target
|
186
examples/widgets/itemviews/addressbook/addresswidget.cpp
Normal file
186
examples/widgets/itemviews/addressbook/addresswidget.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "addresswidget.h"
|
||||
#include "adddialog.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
AddressWidget::AddressWidget(QWidget *parent)
|
||||
: QTabWidget(parent),
|
||||
table(new TableModel(this)),
|
||||
newAddressTab(new NewAddressTab(this))
|
||||
{
|
||||
connect(newAddressTab, &NewAddressTab::sendDetails,
|
||||
this, &AddressWidget::addEntry);
|
||||
|
||||
addTab(newAddressTab, tr("Address Book"));
|
||||
|
||||
setupTabs();
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [2]
|
||||
void AddressWidget::showAddEntryDialog()
|
||||
{
|
||||
AddDialog aDialog;
|
||||
|
||||
if (aDialog.exec())
|
||||
addEntry(aDialog.name(), aDialog.address());
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void AddressWidget::addEntry(const QString &name, const QString &address)
|
||||
{
|
||||
if (!table->getContacts().contains({ name, address })) {
|
||||
table->insertRows(0, 1, QModelIndex());
|
||||
|
||||
QModelIndex index = table->index(0, 0, QModelIndex());
|
||||
table->setData(index, name, Qt::EditRole);
|
||||
index = table->index(0, 1, QModelIndex());
|
||||
table->setData(index, address, Qt::EditRole);
|
||||
removeTab(indexOf(newAddressTab));
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Duplicate Name"),
|
||||
tr("The name \"%1\" already exists.").arg(name));
|
||||
}
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4a]
|
||||
void AddressWidget::editEntry()
|
||||
{
|
||||
QTableView *temp = static_cast<QTableView*>(currentWidget());
|
||||
QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
|
||||
QItemSelectionModel *selectionModel = temp->selectionModel();
|
||||
|
||||
const QModelIndexList indexes = selectionModel->selectedRows();
|
||||
QString name;
|
||||
QString address;
|
||||
int row = -1;
|
||||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
row = proxy->mapToSource(index).row();
|
||||
QModelIndex nameIndex = table->index(row, 0, QModelIndex());
|
||||
QVariant varName = table->data(nameIndex, Qt::DisplayRole);
|
||||
name = varName.toString();
|
||||
|
||||
QModelIndex addressIndex = table->index(row, 1, QModelIndex());
|
||||
QVariant varAddr = table->data(addressIndex, Qt::DisplayRole);
|
||||
address = varAddr.toString();
|
||||
}
|
||||
//! [4a]
|
||||
|
||||
//! [4b]
|
||||
AddDialog aDialog;
|
||||
aDialog.setWindowTitle(tr("Edit a Contact"));
|
||||
aDialog.editAddress(name, address);
|
||||
|
||||
if (aDialog.exec()) {
|
||||
const QString newAddress = aDialog.address();
|
||||
if (newAddress != address) {
|
||||
const QModelIndex index = table->index(row, 1, QModelIndex());
|
||||
table->setData(index, newAddress, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [4b]
|
||||
|
||||
//! [5]
|
||||
void AddressWidget::removeEntry()
|
||||
{
|
||||
QTableView *temp = static_cast<QTableView*>(currentWidget());
|
||||
QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
|
||||
QItemSelectionModel *selectionModel = temp->selectionModel();
|
||||
|
||||
const QModelIndexList indexes = selectionModel->selectedRows();
|
||||
|
||||
for (QModelIndex index : indexes) {
|
||||
int row = proxy->mapToSource(index).row();
|
||||
table->removeRows(row, 1, QModelIndex());
|
||||
}
|
||||
|
||||
if (table->rowCount(QModelIndex()) == 0)
|
||||
insertTab(0, newAddressTab, tr("Address Book"));
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [1]
|
||||
void AddressWidget::setupTabs()
|
||||
{
|
||||
using namespace Qt::StringLiterals;
|
||||
const auto groups = { "ABC"_L1, "DEF"_L1, "GHI"_L1, "JKL"_L1, "MNO"_L1, "PQR"_L1,
|
||||
"STU"_L1, "VW"_L1, "XYZ"_L1 };
|
||||
|
||||
for (QLatin1StringView str : groups) {
|
||||
const auto regExp = QRegularExpression(QLatin1StringView("^[%1].*").arg(str),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
auto proxyModel = new QSortFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(table);
|
||||
proxyModel->setFilterRegularExpression(regExp);
|
||||
proxyModel->setFilterKeyColumn(0);
|
||||
|
||||
QTableView *tableView = new QTableView;
|
||||
tableView->setModel(proxyModel);
|
||||
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
tableView->horizontalHeader()->setStretchLastSection(true);
|
||||
tableView->verticalHeader()->hide();
|
||||
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
tableView->setSortingEnabled(true);
|
||||
|
||||
connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &AddressWidget::selectionChanged);
|
||||
|
||||
connect(this, &QTabWidget::currentChanged, this, [this, tableView](int tabIndex) {
|
||||
if (widget(tabIndex) == tableView)
|
||||
emit selectionChanged(tableView->selectionModel()->selection());
|
||||
});
|
||||
|
||||
addTab(tableView, str);
|
||||
}
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [7]
|
||||
void AddressWidget::readFromFile()
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
QMessageBox::information(this, tr("Unable to open file"),
|
||||
file.errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
QList<Contact> contacts;
|
||||
QDataStream in(&file);
|
||||
in >> contacts;
|
||||
|
||||
if (contacts.isEmpty()) {
|
||||
QMessageBox::information(this, tr("No contacts in file"),
|
||||
tr("The file you are attempting to open contains no contacts."));
|
||||
} else {
|
||||
for (const auto &contact: std::as_const(contacts))
|
||||
addEntry(contact.name, contact.address);
|
||||
}
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [6]
|
||||
void AddressWidget::writeToFile()
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
QMessageBox::information(this, tr("Unable to open file"), file.errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream out(&file);
|
||||
out << table->getContacts();
|
||||
}
|
||||
//! [6]
|
49
examples/widgets/itemviews/addressbook/addresswidget.h
Normal file
49
examples/widgets/itemviews/addressbook/addresswidget.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef ADDRESSWIDGET_H
|
||||
#define ADDRESSWIDGET_H
|
||||
|
||||
#include "newaddresstab.h"
|
||||
#include "tablemodel.h"
|
||||
|
||||
#include <QItemSelection>
|
||||
#include <QTabWidget>
|
||||
#include <QStandardPaths>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSortFilterProxyModel;
|
||||
class QItemSelectionModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
//! [0]
|
||||
class AddressWidget : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddressWidget(QWidget *parent = nullptr);
|
||||
void readFromFile();
|
||||
void writeToFile();
|
||||
|
||||
public slots:
|
||||
void showAddEntryDialog();
|
||||
void addEntry(const QString &name, const QString &address);
|
||||
void editEntry();
|
||||
void removeEntry();
|
||||
|
||||
signals:
|
||||
void selectionChanged (const QItemSelection &selected);
|
||||
|
||||
private:
|
||||
void setupTabs();
|
||||
|
||||
inline static QString fileName =
|
||||
QStandardPaths::standardLocations(QStandardPaths::TempLocation).value(0)
|
||||
+ QStringLiteral("/addressbook.dat");
|
||||
TableModel *table;
|
||||
NewAddressTab *newAddressTab;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // ADDRESSWIDGET_H
|
16
examples/widgets/itemviews/addressbook/main.cpp
Normal file
16
examples/widgets/itemviews/addressbook/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
//! [0]
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
MainWindow mw;
|
||||
mw.show();
|
||||
return app.exec();
|
||||
}
|
||||
//! [0]
|
93
examples/widgets/itemviews/addressbook/mainwindow.cpp
Normal file
93
examples/widgets/itemviews/addressbook/mainwindow.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <QMenuBar>
|
||||
|
||||
//! [0]
|
||||
MainWindow::MainWindow()
|
||||
: QMainWindow(),
|
||||
addressWidget(new AddressWidget)
|
||||
{
|
||||
setCentralWidget(addressWidget);
|
||||
createMenus();
|
||||
setWindowTitle(tr("Address Book"));
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1a]
|
||||
void MainWindow::createMenus()
|
||||
{
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
|
||||
QAction *openAct = new QAction(tr("&Open..."), this);
|
||||
fileMenu->addAction(openAct);
|
||||
connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
|
||||
//! [1a]
|
||||
|
||||
QAction *saveAct = new QAction(tr("&Save"), this);
|
||||
fileMenu->addAction(saveAct);
|
||||
connect(saveAct, &QAction::triggered, this, &MainWindow::saveFile);
|
||||
|
||||
fileMenu->addSeparator();
|
||||
|
||||
QAction *exitAct = new QAction(tr("E&xit"), this);
|
||||
fileMenu->addAction(exitAct);
|
||||
connect(exitAct, &QAction::triggered, this, &QWidget::close);
|
||||
|
||||
QMenu *toolMenu = menuBar()->addMenu(tr("&Tools"));
|
||||
|
||||
QAction *addAct = new QAction(tr("&Add Entry..."), this);
|
||||
toolMenu->addAction(addAct);
|
||||
connect(addAct, &QAction::triggered,
|
||||
addressWidget, &AddressWidget::showAddEntryDialog);
|
||||
|
||||
//! [1b]
|
||||
editAct = new QAction(tr("&Edit Entry..."), this);
|
||||
editAct->setEnabled(false);
|
||||
toolMenu->addAction(editAct);
|
||||
connect(editAct, &QAction::triggered, addressWidget, &AddressWidget::editEntry);
|
||||
|
||||
toolMenu->addSeparator();
|
||||
|
||||
removeAct = new QAction(tr("&Remove Entry"), this);
|
||||
removeAct->setEnabled(false);
|
||||
toolMenu->addAction(removeAct);
|
||||
connect(removeAct, &QAction::triggered, addressWidget, &AddressWidget::removeEntry);
|
||||
|
||||
connect(addressWidget, &AddressWidget::selectionChanged,
|
||||
this, &MainWindow::updateActions);
|
||||
}
|
||||
//! [1b]
|
||||
|
||||
//! [2]
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
addressWidget->readFromFile();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void MainWindow::saveFile()
|
||||
{
|
||||
addressWidget->writeToFile();
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
void MainWindow::updateActions(const QItemSelection &selection)
|
||||
{
|
||||
QModelIndexList indexes = selection.indexes();
|
||||
|
||||
if (!indexes.isEmpty()) {
|
||||
removeAct->setEnabled(true);
|
||||
editAct->setEnabled(true);
|
||||
} else {
|
||||
removeAct->setEnabled(false);
|
||||
editAct->setEnabled(false);
|
||||
}
|
||||
}
|
||||
//! [4]
|
33
examples/widgets/itemviews/addressbook/mainwindow.h
Normal file
33
examples/widgets/itemviews/addressbook/mainwindow.h
Normal 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 "addresswidget.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
//! [0]
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow();
|
||||
|
||||
private slots:
|
||||
void updateActions(const QItemSelection &selection);
|
||||
void openFile();
|
||||
void saveFile();
|
||||
|
||||
private:
|
||||
void createMenus();
|
||||
|
||||
AddressWidget *addressWidget;
|
||||
QAction *editAct;
|
||||
QAction *removeAct;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // MAINWINDOW_H
|
36
examples/widgets/itemviews/addressbook/newaddresstab.cpp
Normal file
36
examples/widgets/itemviews/addressbook/newaddresstab.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "newaddresstab.h"
|
||||
#include "adddialog.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
NewAddressTab::NewAddressTab(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto descriptionLabel = new QLabel(tr("There are currently no contacts in your address book. "
|
||||
"\nClick Add to add new contacts."));
|
||||
|
||||
auto addButton = new QPushButton(tr("Add"));
|
||||
|
||||
connect(addButton, &QAbstractButton::clicked, this, &NewAddressTab::addEntry);
|
||||
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(descriptionLabel);
|
||||
mainLayout->addWidget(addButton, 0, Qt::AlignCenter);
|
||||
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
void NewAddressTab::addEntry()
|
||||
{
|
||||
AddDialog aDialog;
|
||||
|
||||
if (aDialog.exec())
|
||||
emit sendDetails(aDialog.name(), aDialog.address());
|
||||
}
|
||||
//! [1]
|
31
examples/widgets/itemviews/addressbook/newaddresstab.h
Normal file
31
examples/widgets/itemviews/addressbook/newaddresstab.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef NEWADDRESSTAB_H
|
||||
#define NEWADDRESSTAB_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class QVBoxLayout;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
//! [0]
|
||||
class NewAddressTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NewAddressTab(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void addEntry();
|
||||
|
||||
signals:
|
||||
void sendDetails(const QString &name, const QString &address);
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
145
examples/widgets/itemviews/addressbook/tablemodel.cpp
Normal file
145
examples/widgets/itemviews/addressbook/tablemodel.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "tablemodel.h"
|
||||
|
||||
//! [0]
|
||||
TableModel::TableModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
TableModel::TableModel(const QList<Contact> &contacts, QObject *parent)
|
||||
: QAbstractTableModel(parent), contacts(contacts)
|
||||
{
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
int TableModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : contacts.size();
|
||||
}
|
||||
|
||||
int TableModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 2;
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
QVariant TableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (index.row() >= contacts.size() || index.row() < 0)
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
const auto &contact = contacts.at(index.row());
|
||||
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return contact.name;
|
||||
case 1:
|
||||
return contact.address;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return tr("Name");
|
||||
case 1:
|
||||
return tr("Address");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
bool TableModel::insertRows(int position, int rows, const QModelIndex &index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
beginInsertRows(QModelIndex(), position, position + rows - 1);
|
||||
|
||||
for (int row = 0; row < rows; ++row)
|
||||
contacts.insert(position, { QString(), QString() });
|
||||
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
bool TableModel::removeRows(int position, int rows, const QModelIndex &index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
beginRemoveRows(QModelIndex(), position, position + rows - 1);
|
||||
|
||||
for (int row = 0; row < rows; ++row)
|
||||
contacts.removeAt(position);
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (index.isValid() && role == Qt::EditRole) {
|
||||
const int row = index.row();
|
||||
auto contact = contacts.value(row);
|
||||
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
contact.name = value.toString();
|
||||
break;
|
||||
case 1:
|
||||
contact.address = value.toString();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
contacts.replace(row, contact);
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::ItemIsEnabled;
|
||||
|
||||
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
const QList<Contact> &TableModel::getContacts() const
|
||||
{
|
||||
return contacts;
|
||||
}
|
||||
//! [8]
|
56
examples/widgets/itemviews/addressbook/tablemodel.h
Normal file
56
examples/widgets/itemviews/addressbook/tablemodel.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef TABLEMODEL_H
|
||||
#define TABLEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QList>
|
||||
|
||||
//! [0]
|
||||
|
||||
struct Contact
|
||||
{
|
||||
QString name;
|
||||
QString address;
|
||||
|
||||
bool operator==(const Contact &other) const
|
||||
{
|
||||
return name == other.name && address == other.address;
|
||||
}
|
||||
};
|
||||
|
||||
inline QDataStream &operator<<(QDataStream &stream, const Contact &contact)
|
||||
{
|
||||
return stream << contact.name << contact.address;
|
||||
}
|
||||
|
||||
inline QDataStream &operator>>(QDataStream &stream, Contact &contact)
|
||||
{
|
||||
return stream >> contact.name >> contact.address;
|
||||
}
|
||||
|
||||
class TableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TableModel(QObject *parent = nullptr);
|
||||
TableModel(const QList<Contact> &contacts, QObject *parent = nullptr);
|
||||
|
||||
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;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
|
||||
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
|
||||
const QList<Contact> &getContacts() const;
|
||||
|
||||
private:
|
||||
QList<Contact> contacts;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // TABLEMODEL_H
|
@ -0,0 +1,37 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(basicsortfiltermodel LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/basicsortfiltermodel")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(basicsortfiltermodel
|
||||
main.cpp
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(basicsortfiltermodel PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(basicsortfiltermodel PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS basicsortfiltermodel
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(combobox))
|
||||
|
||||
HEADERS = window.h
|
||||
SOURCES = main.cpp \
|
||||
window.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/basicsortfiltermodel
|
||||
INSTALLS += target
|
58
examples/widgets/itemviews/basicsortfiltermodel/main.cpp
Normal file
58
examples/widgets/itemviews/basicsortfiltermodel/main.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTime>
|
||||
|
||||
void addMail(QAbstractItemModel *model, const QString &subject,
|
||||
const QString &sender, const QDateTime &date)
|
||||
{
|
||||
model->insertRow(0);
|
||||
model->setData(model->index(0, 0), subject);
|
||||
model->setData(model->index(0, 1), sender);
|
||||
model->setData(model->index(0, 2), date);
|
||||
}
|
||||
|
||||
QAbstractItemModel *createMailModel(QObject *parent)
|
||||
{
|
||||
QStandardItemModel *model = new QStandardItemModel(0, 3, parent);
|
||||
|
||||
model->setHeaderData(0, Qt::Horizontal, QObject::tr("Subject"));
|
||||
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Sender"));
|
||||
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Date"));
|
||||
|
||||
addMail(model, "Happy New Year!", "Grace K. <grace@software-inc.com>",
|
||||
QDateTime(QDate(2006, 12, 31), QTime(17, 03)));
|
||||
addMail(model, "Radically new concept", "Grace K. <grace@software-inc.com>",
|
||||
QDateTime(QDate(2006, 12, 22), QTime(9, 44)));
|
||||
addMail(model, "Accounts", "pascale@nospam.com",
|
||||
QDateTime(QDate(2006, 12, 31), QTime(12, 50)));
|
||||
addMail(model, "Expenses", "Joe Bloggs <joe@bloggs.com>",
|
||||
QDateTime(QDate(2006, 12, 25), QTime(11, 39)));
|
||||
addMail(model, "Re: Expenses", "Andy <andy@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 02), QTime(16, 05)));
|
||||
addMail(model, "Re: Accounts", "Joe Bloggs <joe@bloggs.com>",
|
||||
QDateTime(QDate(2007, 01, 03), QTime(14, 18)));
|
||||
addMail(model, "Re: Accounts", "Andy <andy@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 03), QTime(14, 26)));
|
||||
addMail(model, "Sports", "Linda Smith <linda.smith@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(11, 33)));
|
||||
addMail(model, "AW: Sports", "Rolf Newschweinstein <rolfn@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(12, 00)));
|
||||
addMail(model, "RE: Sports", "Petra Schmidt <petras@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(12, 01)));
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
Window window;
|
||||
window.setSourceModel(createMailModel(&window));
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
153
examples/widgets/itemviews/basicsortfiltermodel/window.cpp
Normal file
153
examples/widgets/itemviews/basicsortfiltermodel/window.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
static inline QColor textColor(const QPalette &palette)
|
||||
{
|
||||
return palette.color(QPalette::Active, QPalette::Text);
|
||||
}
|
||||
|
||||
static void setTextColor(QWidget *w, const QColor &c)
|
||||
{
|
||||
auto palette = w->palette();
|
||||
if (textColor(palette) != c) {
|
||||
palette.setColor(QPalette::Active, QPalette::Text, c);
|
||||
w->setPalette(palette);
|
||||
}
|
||||
}
|
||||
|
||||
Window::Window()
|
||||
{
|
||||
proxyModel = new QSortFilterProxyModel;
|
||||
|
||||
sourceView = new QTreeView;
|
||||
sourceView->setRootIsDecorated(false);
|
||||
sourceView->setAlternatingRowColors(true);
|
||||
|
||||
proxyView = new QTreeView;
|
||||
proxyView->setRootIsDecorated(false);
|
||||
proxyView->setAlternatingRowColors(true);
|
||||
proxyView->setModel(proxyModel);
|
||||
proxyView->setSortingEnabled(true);
|
||||
|
||||
sortCaseSensitivityCheckBox = new QCheckBox(tr("Case sensitive sorting"));
|
||||
filterCaseSensitivityCheckBox = new QCheckBox(tr("Case sensitive filter"));
|
||||
|
||||
filterPatternLineEdit = new QLineEdit;
|
||||
filterPatternLineEdit->setClearButtonEnabled(true);
|
||||
filterPatternLabel = new QLabel(tr("&Filter pattern:"));
|
||||
filterPatternLabel->setBuddy(filterPatternLineEdit);
|
||||
|
||||
filterSyntaxComboBox = new QComboBox;
|
||||
filterSyntaxComboBox->addItem(tr("Regular expression"), RegularExpression);
|
||||
filterSyntaxComboBox->addItem(tr("Wildcard"), Wildcard);
|
||||
filterSyntaxComboBox->addItem(tr("Fixed string"), FixedString);
|
||||
filterSyntaxLabel = new QLabel(tr("Filter &syntax:"));
|
||||
filterSyntaxLabel->setBuddy(filterSyntaxComboBox);
|
||||
|
||||
filterColumnComboBox = new QComboBox;
|
||||
filterColumnComboBox->addItem(tr("Subject"));
|
||||
filterColumnComboBox->addItem(tr("Sender"));
|
||||
filterColumnComboBox->addItem(tr("Date"));
|
||||
filterColumnLabel = new QLabel(tr("Filter &column:"));
|
||||
filterColumnLabel->setBuddy(filterColumnComboBox);
|
||||
|
||||
connect(filterPatternLineEdit, &QLineEdit::textChanged,
|
||||
this, &Window::filterRegularExpressionChanged);
|
||||
connect(filterSyntaxComboBox, &QComboBox::currentIndexChanged,
|
||||
this, &Window::filterRegularExpressionChanged);
|
||||
connect(filterColumnComboBox, &QComboBox::currentIndexChanged,
|
||||
this, &Window::filterColumnChanged);
|
||||
connect(filterCaseSensitivityCheckBox, &QAbstractButton::toggled,
|
||||
this, &Window::filterRegularExpressionChanged);
|
||||
connect(sortCaseSensitivityCheckBox, &QAbstractButton::toggled,
|
||||
this, &Window::sortChanged);
|
||||
|
||||
sourceGroupBox = new QGroupBox(tr("Original Model"));
|
||||
proxyGroupBox = new QGroupBox(tr("Sorted/Filtered Model"));
|
||||
|
||||
QHBoxLayout *sourceLayout = new QHBoxLayout;
|
||||
sourceLayout->addWidget(sourceView);
|
||||
sourceGroupBox->setLayout(sourceLayout);
|
||||
|
||||
QGridLayout *proxyLayout = new QGridLayout;
|
||||
proxyLayout->addWidget(proxyView, 0, 0, 1, 3);
|
||||
proxyLayout->addWidget(filterPatternLabel, 1, 0);
|
||||
proxyLayout->addWidget(filterPatternLineEdit, 1, 1, 1, 2);
|
||||
proxyLayout->addWidget(filterSyntaxLabel, 2, 0);
|
||||
proxyLayout->addWidget(filterSyntaxComboBox, 2, 1, 1, 2);
|
||||
proxyLayout->addWidget(filterColumnLabel, 3, 0);
|
||||
proxyLayout->addWidget(filterColumnComboBox, 3, 1, 1, 2);
|
||||
proxyLayout->addWidget(filterCaseSensitivityCheckBox, 4, 0, 1, 2);
|
||||
proxyLayout->addWidget(sortCaseSensitivityCheckBox, 4, 2);
|
||||
proxyGroupBox->setLayout(proxyLayout);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
|
||||
mainLayout->addWidget(sourceGroupBox);
|
||||
mainLayout->addWidget(proxyGroupBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
setWindowTitle(tr("Basic Sort/Filter Model"));
|
||||
resize(500, 450);
|
||||
|
||||
proxyView->sortByColumn(1, Qt::AscendingOrder);
|
||||
filterColumnComboBox->setCurrentIndex(1);
|
||||
|
||||
filterPatternLineEdit->setText("Andy|Grace");
|
||||
filterCaseSensitivityCheckBox->setChecked(true);
|
||||
sortCaseSensitivityCheckBox->setChecked(true);
|
||||
}
|
||||
|
||||
void Window::setSourceModel(QAbstractItemModel *model)
|
||||
{
|
||||
proxyModel->setSourceModel(model);
|
||||
sourceView->setModel(model);
|
||||
}
|
||||
|
||||
void Window::filterRegularExpressionChanged()
|
||||
{
|
||||
Syntax s = Syntax(filterSyntaxComboBox->itemData(filterSyntaxComboBox->currentIndex()).toInt());
|
||||
QString pattern = filterPatternLineEdit->text();
|
||||
switch (s) {
|
||||
case Wildcard:
|
||||
pattern = QRegularExpression::wildcardToRegularExpression(pattern);
|
||||
break;
|
||||
case FixedString:
|
||||
pattern = QRegularExpression::escape(pattern);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
|
||||
if (!filterCaseSensitivityCheckBox->isChecked())
|
||||
options |= QRegularExpression::CaseInsensitiveOption;
|
||||
QRegularExpression regularExpression(pattern, options);
|
||||
|
||||
if (regularExpression.isValid()) {
|
||||
filterPatternLineEdit->setToolTip(QString());
|
||||
proxyModel->setFilterRegularExpression(regularExpression);
|
||||
setTextColor(filterPatternLineEdit, textColor(style()->standardPalette()));
|
||||
} else {
|
||||
filterPatternLineEdit->setToolTip(regularExpression.errorString());
|
||||
proxyModel->setFilterRegularExpression(QRegularExpression());
|
||||
setTextColor(filterPatternLineEdit, Qt::red);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::filterColumnChanged()
|
||||
{
|
||||
proxyModel->setFilterKeyColumn(filterColumnComboBox->currentIndex());
|
||||
}
|
||||
|
||||
void Window::sortChanged()
|
||||
{
|
||||
proxyModel->setSortCaseSensitivity(
|
||||
sortCaseSensitivityCheckBox->isChecked() ? Qt::CaseSensitive
|
||||
: Qt::CaseInsensitive);
|
||||
}
|
57
examples/widgets/itemviews/basicsortfiltermodel/window.h
Normal file
57
examples/widgets/itemviews/basicsortfiltermodel/window.h
Normal file
@ -0,0 +1,57 @@
|
||||
// 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 QAbstractItemModel;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QSortFilterProxyModel;
|
||||
class QTreeView;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
void setSourceModel(QAbstractItemModel *model);
|
||||
|
||||
private slots:
|
||||
void filterRegularExpressionChanged();
|
||||
void filterColumnChanged();
|
||||
void sortChanged();
|
||||
|
||||
private:
|
||||
QSortFilterProxyModel *proxyModel;
|
||||
|
||||
QGroupBox *sourceGroupBox;
|
||||
QGroupBox *proxyGroupBox;
|
||||
QTreeView *sourceView;
|
||||
QTreeView *proxyView;
|
||||
QCheckBox *filterCaseSensitivityCheckBox;
|
||||
QCheckBox *sortCaseSensitivityCheckBox;
|
||||
QLabel *filterPatternLabel;
|
||||
QLabel *filterSyntaxLabel;
|
||||
QLabel *filterColumnLabel;
|
||||
QLineEdit *filterPatternLineEdit;
|
||||
enum Syntax {
|
||||
RegularExpression,
|
||||
Wildcard,
|
||||
FixedString
|
||||
};
|
||||
|
||||
QComboBox *filterSyntaxComboBox;
|
||||
QComboBox *filterColumnComboBox;
|
||||
};
|
||||
|
||||
#endif // WINDOW_H
|
56
examples/widgets/itemviews/chart/CMakeLists.txt
Normal file
56
examples/widgets/itemviews/chart/CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(chart LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/chart")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(chart
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
pieview.cpp pieview.h
|
||||
)
|
||||
|
||||
set_target_properties(chart PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(chart PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(chart_resource_files
|
||||
"qtdata.cht"
|
||||
)
|
||||
|
||||
qt_add_resources(chart "chart"
|
||||
PREFIX
|
||||
"/Charts"
|
||||
FILES
|
||||
${chart_resource_files}
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORKS)
|
||||
target_link_libraries(chart PRIVATE
|
||||
m
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS chart
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
14
examples/widgets/itemviews/chart/chart.pro
Normal file
14
examples/widgets/itemviews/chart/chart.pro
Normal file
@ -0,0 +1,14 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(filedialog))
|
||||
|
||||
HEADERS = mainwindow.h \
|
||||
pieview.h
|
||||
RESOURCES = chart.qrc
|
||||
SOURCES = main.cpp \
|
||||
mainwindow.cpp \
|
||||
pieview.cpp
|
||||
unix:!mac:!vxworks:!integrity:!haiku:LIBS += -lm
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/chart
|
||||
INSTALLS += target
|
5
examples/widgets/itemviews/chart/chart.qrc
Normal file
5
examples/widgets/itemviews/chart/chart.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/Charts" >
|
||||
<file>qtdata.cht</file>
|
||||
</qresource>
|
||||
</RCC>
|
16
examples/widgets/itemviews/chart/main.cpp
Normal file
16
examples/widgets/itemviews/chart/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// 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[])
|
||||
{
|
||||
Q_INIT_RESOURCE(chart);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
136
examples/widgets/itemviews/chart/mainwindow.cpp
Normal file
136
examples/widgets/itemviews/chart/mainwindow.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "pieview.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
QMenu *fileMenu = new QMenu(tr("&File"), this);
|
||||
QAction *openAction = fileMenu->addAction(tr("&Open..."));
|
||||
openAction->setShortcuts(QKeySequence::Open);
|
||||
QAction *saveAction = fileMenu->addAction(tr("&Save As..."));
|
||||
saveAction->setShortcuts(QKeySequence::SaveAs);
|
||||
QAction *quitAction = fileMenu->addAction(tr("E&xit"));
|
||||
quitAction->setShortcuts(QKeySequence::Quit);
|
||||
|
||||
setupModel();
|
||||
setupViews();
|
||||
|
||||
connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
|
||||
connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
|
||||
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
|
||||
|
||||
menuBar()->addMenu(fileMenu);
|
||||
statusBar();
|
||||
|
||||
loadFile(":/Charts/qtdata.cht");
|
||||
|
||||
setWindowTitle(tr("Chart"));
|
||||
resize(870, 550);
|
||||
}
|
||||
|
||||
void MainWindow::setupModel()
|
||||
{
|
||||
model = new QStandardItemModel(8, 2, this);
|
||||
model->setHeaderData(0, Qt::Horizontal, tr("Label"));
|
||||
model->setHeaderData(1, Qt::Horizontal, tr("Quantity"));
|
||||
}
|
||||
|
||||
void MainWindow::setupViews()
|
||||
{
|
||||
QSplitter *splitter = new QSplitter;
|
||||
QTableView *table = new QTableView;
|
||||
pieChart = new PieView;
|
||||
splitter->addWidget(table);
|
||||
splitter->addWidget(pieChart);
|
||||
splitter->setStretchFactor(0, 0);
|
||||
splitter->setStretchFactor(1, 1);
|
||||
|
||||
table->setModel(model);
|
||||
pieChart->setModel(model);
|
||||
|
||||
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
|
||||
table->setSelectionModel(selectionModel);
|
||||
pieChart->setSelectionModel(selectionModel);
|
||||
|
||||
QHeaderView *headerView = table->horizontalHeader();
|
||||
headerView->setStretchLastSection(true);
|
||||
|
||||
setCentralWidget(splitter);
|
||||
}
|
||||
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
const QString fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Choose a data file"), "", "*.cht");
|
||||
if (!fileName.isEmpty())
|
||||
loadFile(fileName);
|
||||
}
|
||||
|
||||
void MainWindow::loadFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return;
|
||||
|
||||
QTextStream stream(&file);
|
||||
|
||||
model->removeRows(0, model->rowCount(QModelIndex()), QModelIndex());
|
||||
|
||||
int row = 0;
|
||||
while (!stream.atEnd()) {
|
||||
const QString line = stream.readLine();
|
||||
if (!line.isEmpty()) {
|
||||
model->insertRows(row, 1, QModelIndex());
|
||||
|
||||
const QStringList pieces = line.split(QLatin1Char(','), Qt::SkipEmptyParts);
|
||||
if (pieces.size() < 3)
|
||||
continue;
|
||||
model->setData(model->index(row, 0, QModelIndex()),
|
||||
pieces.value(0));
|
||||
model->setData(model->index(row, 1, QModelIndex()),
|
||||
pieces.value(1));
|
||||
model->setData(model->index(row, 0, QModelIndex()),
|
||||
QColor(pieces.value(2)), Qt::DecorationRole);
|
||||
row++;
|
||||
}
|
||||
};
|
||||
|
||||
file.close();
|
||||
statusBar()->showMessage(tr("Loaded %1").arg(fileName), 2000);
|
||||
}
|
||||
|
||||
void MainWindow::saveFile()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this,
|
||||
tr("Save file as"), "", "*.cht");
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text))
|
||||
return;
|
||||
|
||||
QTextStream stream(&file);
|
||||
for (int row = 0; row < model->rowCount(QModelIndex()); ++row) {
|
||||
|
||||
QStringList pieces;
|
||||
|
||||
pieces.append(model->data(model->index(row, 0, QModelIndex()),
|
||||
Qt::DisplayRole).toString());
|
||||
pieces.append(model->data(model->index(row, 1, QModelIndex()),
|
||||
Qt::DisplayRole).toString());
|
||||
pieces.append(model->data(model->index(row, 0, QModelIndex()),
|
||||
Qt::DecorationRole).toString());
|
||||
|
||||
stream << pieces.join(',') << "\n";
|
||||
}
|
||||
|
||||
file.close();
|
||||
statusBar()->showMessage(tr("Saved %1").arg(fileName), 2000);
|
||||
}
|
34
examples/widgets/itemviews/chart/mainwindow.h
Normal file
34
examples/widgets/itemviews/chart/mainwindow.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemModel;
|
||||
class QAbstractItemView;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void openFile();
|
||||
void saveFile();
|
||||
|
||||
private:
|
||||
void setupModel();
|
||||
void setupViews();
|
||||
void loadFile(const QString &path);
|
||||
|
||||
QAbstractItemModel *model = nullptr;
|
||||
QAbstractItemView *pieChart = nullptr;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
506
examples/widgets/itemviews/chart/pieview.cpp
Normal file
506
examples/widgets/itemviews/chart/pieview.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "pieview.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
PieView::PieView(QWidget *parent)
|
||||
: QAbstractItemView(parent)
|
||||
{
|
||||
horizontalScrollBar()->setRange(0, 0);
|
||||
verticalScrollBar()->setRange(0, 0);
|
||||
}
|
||||
|
||||
void PieView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QList<int> &roles)
|
||||
{
|
||||
QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
|
||||
|
||||
if (!roles.contains(Qt::DisplayRole))
|
||||
return;
|
||||
|
||||
validItems = 0;
|
||||
totalValue = 0.0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index, Qt::DisplayRole).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
totalValue += value;
|
||||
validItems++;
|
||||
}
|
||||
}
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
bool PieView::edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
return QAbstractItemView::edit(index, trigger, event);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the item that covers the coordinate given in the view.
|
||||
*/
|
||||
|
||||
QModelIndex PieView::indexAt(const QPoint &point) const
|
||||
{
|
||||
if (validItems == 0)
|
||||
return QModelIndex();
|
||||
|
||||
// Transform the view coordinates into contents widget coordinates.
|
||||
int wx = point.x() + horizontalScrollBar()->value();
|
||||
int wy = point.y() + verticalScrollBar()->value();
|
||||
|
||||
if (wx < totalSize) {
|
||||
double cx = wx - totalSize / 2;
|
||||
double cy = totalSize / 2 - wy; // positive cy for items above the center
|
||||
|
||||
// Determine the distance from the center point of the pie chart.
|
||||
double d = std::sqrt(std::pow(cx, 2) + std::pow(cy, 2));
|
||||
|
||||
if (d == 0 || d > pieSize / 2)
|
||||
return QModelIndex();
|
||||
|
||||
// Determine the angle of the point.
|
||||
double angle = qRadiansToDegrees(std::atan2(cy, cx));
|
||||
if (angle < 0)
|
||||
angle = 360 + angle;
|
||||
|
||||
// Find the relevant slice of the pie.
|
||||
double startAngle = 0.0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double sliceAngle = 360 * value / totalValue;
|
||||
|
||||
if (angle >= startAngle && angle < (startAngle + sliceAngle))
|
||||
return model()->index(row, 1, rootIndex());
|
||||
|
||||
startAngle += sliceAngle;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
double itemHeight = QFontMetrics(option.font).height();
|
||||
int listItem = int((wy - margin) / itemHeight);
|
||||
int validRow = 0;
|
||||
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
if (model()->data(index).toDouble() > 0.0) {
|
||||
|
||||
if (listItem == validRow)
|
||||
return model()->index(row, 0, rootIndex());
|
||||
|
||||
// Update the list index that corresponds to the next valid row.
|
||||
++validRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool PieView::isIndexHidden(const QModelIndex & /*index*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the rectangle of the item at position \a index in the
|
||||
model. The rectangle is in contents coordinates.
|
||||
*/
|
||||
|
||||
QRect PieView::itemRect(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QRect();
|
||||
|
||||
// Check whether the index's row is in the list of rows represented
|
||||
// by slices.
|
||||
QModelIndex valueIndex;
|
||||
|
||||
if (index.column() != 1)
|
||||
valueIndex = model()->index(index.row(), 1, rootIndex());
|
||||
else
|
||||
valueIndex = index;
|
||||
|
||||
if (model()->data(valueIndex).toDouble() <= 0.0)
|
||||
return QRect();
|
||||
|
||||
int listItem = 0;
|
||||
for (int row = index.row()-1; row >= 0; --row) {
|
||||
if (model()->data(model()->index(row, 1, rootIndex())).toDouble() > 0.0)
|
||||
listItem++;
|
||||
}
|
||||
|
||||
switch (index.column()) {
|
||||
case 0: {
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
const qreal itemHeight = QFontMetricsF(option.font).height();
|
||||
return QRect(totalSize,
|
||||
qRound(margin + listItem * itemHeight),
|
||||
totalSize - margin, qRound(itemHeight));
|
||||
}
|
||||
case 1:
|
||||
return viewport()->rect();
|
||||
}
|
||||
return QRect();
|
||||
}
|
||||
|
||||
QRegion PieView::itemRegion(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QRegion();
|
||||
|
||||
if (index.column() != 1)
|
||||
return itemRect(index);
|
||||
|
||||
if (model()->data(index).toDouble() <= 0.0)
|
||||
return QRegion();
|
||||
|
||||
double startAngle = 0.0;
|
||||
for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
|
||||
QModelIndex sliceIndex = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(sliceIndex).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double angle = 360 * value / totalValue;
|
||||
|
||||
if (sliceIndex == index) {
|
||||
QPainterPath slicePath;
|
||||
slicePath.moveTo(totalSize / 2, totalSize / 2);
|
||||
slicePath.arcTo(margin, margin, margin + pieSize, margin + pieSize,
|
||||
startAngle, angle);
|
||||
slicePath.closeSubpath();
|
||||
|
||||
return QRegion(slicePath.toFillPolygon().toPolygon());
|
||||
}
|
||||
|
||||
startAngle += angle;
|
||||
}
|
||||
}
|
||||
|
||||
return QRegion();
|
||||
}
|
||||
|
||||
int PieView::horizontalOffset() const
|
||||
{
|
||||
return horizontalScrollBar()->value();
|
||||
}
|
||||
|
||||
void PieView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractItemView::mousePressEvent(event);
|
||||
origin = event->position().toPoint();
|
||||
if (!rubberBand)
|
||||
rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport());
|
||||
rubberBand->setGeometry(QRect(origin, QSize()));
|
||||
rubberBand->show();
|
||||
}
|
||||
|
||||
void PieView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (rubberBand)
|
||||
rubberBand->setGeometry(QRect(origin, event->position().toPoint()).normalized());
|
||||
QAbstractItemView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void PieView::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractItemView::mouseReleaseEvent(event);
|
||||
if (rubberBand)
|
||||
rubberBand->hide();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
QModelIndex PieView::moveCursor(QAbstractItemView::CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers /*modifiers*/)
|
||||
{
|
||||
QModelIndex current = currentIndex();
|
||||
|
||||
switch (cursorAction) {
|
||||
case MoveLeft:
|
||||
case MoveUp:
|
||||
if (current.row() > 0)
|
||||
current = model()->index(current.row() - 1, current.column(),
|
||||
rootIndex());
|
||||
else
|
||||
current = model()->index(0, current.column(), rootIndex());
|
||||
break;
|
||||
case MoveRight:
|
||||
case MoveDown:
|
||||
if (current.row() < rows(current) - 1)
|
||||
current = model()->index(current.row() + 1, current.column(),
|
||||
rootIndex());
|
||||
else
|
||||
current = model()->index(rows(current) - 1, current.column(),
|
||||
rootIndex());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
viewport()->update();
|
||||
return current;
|
||||
}
|
||||
|
||||
void PieView::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QItemSelectionModel *selections = selectionModel();
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
|
||||
QBrush background = option.palette.base();
|
||||
QPen foreground(option.palette.color(QPalette::WindowText));
|
||||
|
||||
QPainter painter(viewport());
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
painter.fillRect(event->rect(), background);
|
||||
painter.setPen(foreground);
|
||||
|
||||
// Viewport rectangles
|
||||
QRect pieRect = QRect(margin, margin, pieSize, pieSize);
|
||||
|
||||
if (validItems <= 0)
|
||||
return;
|
||||
|
||||
painter.save();
|
||||
painter.translate(pieRect.x() - horizontalScrollBar()->value(),
|
||||
pieRect.y() - verticalScrollBar()->value());
|
||||
painter.drawEllipse(0, 0, pieSize, pieSize);
|
||||
double startAngle = 0.0;
|
||||
int row;
|
||||
|
||||
for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
double angle = 360 * value / totalValue;
|
||||
|
||||
QModelIndex colorIndex = model()->index(row, 0, rootIndex());
|
||||
QColor color = QColor(model()->data(colorIndex, Qt::DecorationRole).toString());
|
||||
|
||||
if (currentIndex() == index)
|
||||
painter.setBrush(QBrush(color, Qt::Dense4Pattern));
|
||||
else if (selections->isSelected(index))
|
||||
painter.setBrush(QBrush(color, Qt::Dense3Pattern));
|
||||
else
|
||||
painter.setBrush(QBrush(color));
|
||||
|
||||
painter.drawPie(0, 0, pieSize, pieSize, int(startAngle*16), int(angle*16));
|
||||
|
||||
startAngle += angle;
|
||||
}
|
||||
}
|
||||
painter.restore();
|
||||
|
||||
for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
QModelIndex labelIndex = model()->index(row, 0, rootIndex());
|
||||
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
|
||||
option.rect = visualRect(labelIndex);
|
||||
if (selections->isSelected(labelIndex))
|
||||
option.state |= QStyle::State_Selected;
|
||||
if (currentIndex() == labelIndex)
|
||||
option.state |= QStyle::State_HasFocus;
|
||||
itemDelegate()->paint(&painter, option, labelIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PieView::resizeEvent(QResizeEvent * /* event */)
|
||||
{
|
||||
updateGeometries();
|
||||
}
|
||||
|
||||
int PieView::rows(const QModelIndex &index) const
|
||||
{
|
||||
return model()->rowCount(model()->parent(index));
|
||||
}
|
||||
|
||||
void PieView::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||
{
|
||||
for (int row = start; row <= end; ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
|
||||
if (value > 0.0) {
|
||||
totalValue += value;
|
||||
++validItems;
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractItemView::rowsInserted(parent, start, end);
|
||||
}
|
||||
|
||||
void PieView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
||||
{
|
||||
for (int row = start; row <= end; ++row) {
|
||||
QModelIndex index = model()->index(row, 1, rootIndex());
|
||||
double value = model()->data(index).toDouble();
|
||||
if (value > 0.0) {
|
||||
totalValue -= value;
|
||||
--validItems;
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
|
||||
}
|
||||
|
||||
void PieView::scrollContentsBy(int dx, int dy)
|
||||
{
|
||||
viewport()->scroll(dx, dy);
|
||||
}
|
||||
|
||||
void PieView::scrollTo(const QModelIndex &index, ScrollHint)
|
||||
{
|
||||
QRect area = viewport()->rect();
|
||||
QRect rect = visualRect(index);
|
||||
|
||||
if (rect.left() < area.left()) {
|
||||
horizontalScrollBar()->setValue(
|
||||
horizontalScrollBar()->value() + rect.left() - area.left());
|
||||
} else if (rect.right() > area.right()) {
|
||||
horizontalScrollBar()->setValue(
|
||||
horizontalScrollBar()->value() + qMin(
|
||||
rect.right() - area.right(), rect.left() - area.left()));
|
||||
}
|
||||
|
||||
if (rect.top() < area.top()) {
|
||||
verticalScrollBar()->setValue(
|
||||
verticalScrollBar()->value() + rect.top() - area.top());
|
||||
} else if (rect.bottom() > area.bottom()) {
|
||||
verticalScrollBar()->setValue(
|
||||
verticalScrollBar()->value() + qMin(
|
||||
rect.bottom() - area.bottom(), rect.top() - area.top()));
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/*
|
||||
Find the indices corresponding to the extent of the selection.
|
||||
*/
|
||||
|
||||
void PieView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
// Use content widget coordinates because we will use the itemRegion()
|
||||
// function to check for intersections.
|
||||
|
||||
QRect contentsRect = rect.translated(
|
||||
horizontalScrollBar()->value(),
|
||||
verticalScrollBar()->value()).normalized();
|
||||
|
||||
int rows = model()->rowCount(rootIndex());
|
||||
int columns = model()->columnCount(rootIndex());
|
||||
QModelIndexList indexes;
|
||||
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
for (int column = 0; column < columns; ++column) {
|
||||
QModelIndex index = model()->index(row, column, rootIndex());
|
||||
QRegion region = itemRegion(index);
|
||||
if (region.intersects(contentsRect))
|
||||
indexes.append(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (indexes.size() > 0) {
|
||||
int firstRow = indexes.at(0).row();
|
||||
int lastRow = firstRow;
|
||||
int firstColumn = indexes.at(0).column();
|
||||
int lastColumn = firstColumn;
|
||||
|
||||
for (int i = 1; i < indexes.size(); ++i) {
|
||||
firstRow = qMin(firstRow, indexes.at(i).row());
|
||||
lastRow = qMax(lastRow, indexes.at(i).row());
|
||||
firstColumn = qMin(firstColumn, indexes.at(i).column());
|
||||
lastColumn = qMax(lastColumn, indexes.at(i).column());
|
||||
}
|
||||
|
||||
QItemSelection selection(
|
||||
model()->index(firstRow, firstColumn, rootIndex()),
|
||||
model()->index(lastRow, lastColumn, rootIndex()));
|
||||
selectionModel()->select(selection, command);
|
||||
} else {
|
||||
QModelIndex noIndex;
|
||||
QItemSelection selection(noIndex, noIndex);
|
||||
selectionModel()->select(selection, command);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PieView::updateGeometries()
|
||||
{
|
||||
horizontalScrollBar()->setPageStep(viewport()->width());
|
||||
horizontalScrollBar()->setRange(0, qMax(0, 2 * totalSize - viewport()->width()));
|
||||
verticalScrollBar()->setPageStep(viewport()->height());
|
||||
verticalScrollBar()->setRange(0, qMax(0, totalSize - viewport()->height()));
|
||||
}
|
||||
|
||||
int PieView::verticalOffset() const
|
||||
{
|
||||
return verticalScrollBar()->value();
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the position of the item in viewport coordinates.
|
||||
*/
|
||||
|
||||
QRect PieView::visualRect(const QModelIndex &index) const
|
||||
{
|
||||
QRect rect = itemRect(index);
|
||||
if (!rect.isValid())
|
||||
return rect;
|
||||
|
||||
return QRect(rect.left() - horizontalScrollBar()->value(),
|
||||
rect.top() - verticalScrollBar()->value(),
|
||||
rect.width(), rect.height());
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a region corresponding to the selection in viewport coordinates.
|
||||
*/
|
||||
|
||||
QRegion PieView::visualRegionForSelection(const QItemSelection &selection) const
|
||||
{
|
||||
int ranges = selection.count();
|
||||
|
||||
if (ranges == 0)
|
||||
return QRect();
|
||||
|
||||
QRegion region;
|
||||
for (int i = 0; i < ranges; ++i) {
|
||||
const QItemSelectionRange &range = selection.at(i);
|
||||
for (int row = range.top(); row <= range.bottom(); ++row) {
|
||||
for (int col = range.left(); col <= range.right(); ++col) {
|
||||
QModelIndex index = model()->index(row, col, rootIndex());
|
||||
region += visualRect(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return region;
|
||||
}
|
66
examples/widgets/itemviews/chart/pieview.h
Normal file
66
examples/widgets/itemviews/chart/pieview.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef PIEVIEW_H
|
||||
#define PIEVIEW_H
|
||||
|
||||
#include <QAbstractItemView>
|
||||
|
||||
//! [0]
|
||||
class PieView : public QAbstractItemView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PieView(QWidget *parent = nullptr);
|
||||
|
||||
QRect visualRect(const QModelIndex &index) const override;
|
||||
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
QModelIndex indexAt(const QPoint &point) const override;
|
||||
|
||||
protected slots:
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QList<int> &roles = QList<int>()) override;
|
||||
void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
|
||||
protected:
|
||||
bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event) override;
|
||||
QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
int horizontalOffset() const override;
|
||||
int verticalOffset() const override;
|
||||
|
||||
bool isIndexHidden(const QModelIndex &index) const override;
|
||||
|
||||
void setSelection(const QRect&, QItemSelectionModel::SelectionFlags command) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void scrollContentsBy(int dx, int dy) override;
|
||||
|
||||
QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
|
||||
private:
|
||||
QRect itemRect(const QModelIndex &item) const;
|
||||
QRegion itemRegion(const QModelIndex &index) const;
|
||||
int rows(const QModelIndex &index = QModelIndex()) const;
|
||||
void updateGeometries() override;
|
||||
|
||||
int margin = 0;
|
||||
int totalSize = 300;
|
||||
int pieSize = totalSize - 2 * margin;
|
||||
int validItems = 0;
|
||||
double totalValue = 0.0;
|
||||
QRubberBand *rubberBand = nullptr;
|
||||
QPoint origin;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // PIEVIEW_H
|
14
examples/widgets/itemviews/chart/qtdata.cht
Normal file
14
examples/widgets/itemviews/chart/qtdata.cht
Normal file
@ -0,0 +1,14 @@
|
||||
Scientific Research,21,#99e600
|
||||
Engineering & Design,18,#99cc00
|
||||
Automotive,14,#99b300
|
||||
Aerospace,13,#9f991a
|
||||
Automation & Machine Tools,13,#a48033
|
||||
Medical & Bioinformatics,13,#a9664d
|
||||
Imaging & Special Effects,12,#ae4d66
|
||||
Defense,11,#b33380
|
||||
Test & Measurement Systems,9,#a64086
|
||||
Oil & Gas,9,#994d8d
|
||||
Entertainment & Broadcasting,7,#8d5a93
|
||||
Financial,6,#806699
|
||||
Consumer Electronics,4,#8073a6
|
||||
Other,38,#8080b3
|
38
examples/widgets/itemviews/coloreditorfactory/CMakeLists.txt
Normal file
38
examples/widgets/itemviews/coloreditorfactory/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(coloreditorfactory LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/coloreditorfactory")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(coloreditorfactory
|
||||
colorlisteditor.cpp colorlisteditor.h
|
||||
main.cpp
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(coloreditorfactory PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(coloreditorfactory PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS coloreditorfactory
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -0,0 +1,12 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(combobox))
|
||||
|
||||
HEADERS = colorlisteditor.h \
|
||||
window.h
|
||||
SOURCES = colorlisteditor.cpp \
|
||||
window.cpp \
|
||||
main.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/coloreditorfactory
|
||||
INSTALLS += target
|
@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "colorlisteditor.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
ColorListEditor::ColorListEditor(QWidget *widget) : QComboBox(widget)
|
||||
{
|
||||
populateList();
|
||||
}
|
||||
|
||||
//! [0]
|
||||
QColor ColorListEditor::color() const
|
||||
{
|
||||
return qvariant_cast<QColor>(itemData(currentIndex(), Qt::DecorationRole));
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
void ColorListEditor::setColor(const QColor &color)
|
||||
{
|
||||
setCurrentIndex(findData(color, Qt::DecorationRole));
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
void ColorListEditor::populateList()
|
||||
{
|
||||
const QStringList colorNames = QColor::colorNames();
|
||||
|
||||
for (int i = 0; i < colorNames.size(); ++i) {
|
||||
QColor color(colorNames[i]);
|
||||
|
||||
insertItem(i, colorNames[i]);
|
||||
setItemData(i, color, Qt::DecorationRole);
|
||||
}
|
||||
}
|
||||
//! [2]
|
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef COLORLISTEDITOR_H
|
||||
#define COLORLISTEDITOR_H
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QColor;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
//! [0]
|
||||
class ColorListEditor : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor USER true)
|
||||
|
||||
public:
|
||||
ColorListEditor(QWidget *widget = nullptr);
|
||||
|
||||
public:
|
||||
QColor color() const;
|
||||
void setColor(const QColor &color);
|
||||
|
||||
private:
|
||||
void populateList();
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
16
examples/widgets/itemviews/coloreditorfactory/main.cpp
Normal file
16
examples/widgets/itemviews/coloreditorfactory/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
int main(int argv, char **args)
|
||||
{
|
||||
QApplication app(argv, args);
|
||||
|
||||
Window window;
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
55
examples/widgets/itemviews/coloreditorfactory/window.cpp
Normal file
55
examples/widgets/itemviews/coloreditorfactory/window.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
#include "colorlisteditor.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
Window::Window()
|
||||
{
|
||||
QItemEditorFactory *factory = new QItemEditorFactory;
|
||||
|
||||
QItemEditorCreatorBase *colorListCreator =
|
||||
new QStandardItemEditorCreator<ColorListEditor>();
|
||||
|
||||
factory->registerEditor(QMetaType::QColor, colorListCreator);
|
||||
|
||||
QItemEditorFactory::setDefaultFactory(factory);
|
||||
|
||||
createGUI();
|
||||
}
|
||||
//! [0]
|
||||
|
||||
void Window::createGUI()
|
||||
{
|
||||
const QList<QPair<QString, QColor>> list = { { tr("Alice"), QColor("aliceblue") },
|
||||
{ tr("Neptun"), QColor("aquamarine") },
|
||||
{ tr("Ferdinand"), QColor("springgreen") } };
|
||||
|
||||
QTableWidget *table = new QTableWidget(3, 2);
|
||||
table->setHorizontalHeaderLabels({ tr("Name"), tr("Hair Color") });
|
||||
table->verticalHeader()->setVisible(false);
|
||||
table->resize(150, 50);
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const QPair<QString, QColor> &pair = list.at(i);
|
||||
|
||||
QTableWidgetItem *nameItem = new QTableWidgetItem(pair.first);
|
||||
QTableWidgetItem *colorItem = new QTableWidgetItem;
|
||||
colorItem->setData(Qt::DisplayRole, pair.second);
|
||||
|
||||
table->setItem(i, 0, nameItem);
|
||||
table->setItem(i, 1, colorItem);
|
||||
}
|
||||
table->resizeColumnToContents(0);
|
||||
table->horizontalHeader()->setStretchLastSection(true);
|
||||
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
layout->addWidget(table, 0, 0);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
setWindowTitle(tr("Color Editor Factory"));
|
||||
}
|
20
examples/widgets/itemviews/coloreditorfactory/window.h
Normal file
20
examples/widgets/itemviews/coloreditorfactory/window.h
Normal file
@ -0,0 +1,20 @@
|
||||
// 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>
|
||||
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
private:
|
||||
void createGUI();
|
||||
};
|
||||
|
||||
#endif
|
37
examples/widgets/itemviews/combowidgetmapper/CMakeLists.txt
Normal file
37
examples/widgets/itemviews/combowidgetmapper/CMakeLists.txt
Normal 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(combowidgetmapper LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/combowidgetmapper")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(combowidgetmapper
|
||||
main.cpp
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(combowidgetmapper PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(combowidgetmapper PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS combowidgetmapper
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -0,0 +1,11 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(combobox))
|
||||
|
||||
HEADERS = window.h
|
||||
SOURCES = main.cpp \
|
||||
window.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/combowidgetmapper
|
||||
INSTALLS += target
|
||||
|
14
examples/widgets/itemviews/combowidgetmapper/main.cpp
Normal file
14
examples/widgets/itemviews/combowidgetmapper/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
Window window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
99
examples/widgets/itemviews/combowidgetmapper/window.cpp
Normal file
99
examples/widgets/itemviews/combowidgetmapper/window.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "window.h"
|
||||
|
||||
//! [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();
|
||||
typeLabel = new QLabel(tr("&Type:"));
|
||||
typeComboBox = new QComboBox();
|
||||
nextButton = new QPushButton(tr("&Next"));
|
||||
previousButton = new QPushButton(tr("&Previous"));
|
||||
|
||||
nameLabel->setBuddy(nameEdit);
|
||||
addressLabel->setBuddy(addressEdit);
|
||||
typeLabel->setBuddy(typeComboBox);
|
||||
|
||||
typeComboBox->setModel(typeModel);
|
||||
//! [Set up widgets]
|
||||
|
||||
//! [Set up the mapper]
|
||||
mapper = new QDataWidgetMapper(this);
|
||||
mapper->setModel(model);
|
||||
mapper->addMapping(nameEdit, 0);
|
||||
mapper->addMapping(addressEdit, 1);
|
||||
mapper->addMapping(typeComboBox, 2, "currentIndex");
|
||||
//! [Set up the mapper]
|
||||
|
||||
//! [Set up connections and layouts]
|
||||
connect(previousButton, &QAbstractButton::clicked,
|
||||
mapper, &QDataWidgetMapper::toPrevious);
|
||||
connect(nextButton, &QAbstractButton::clicked,
|
||||
mapper, &QDataWidgetMapper::toNext);
|
||||
connect(mapper, &QDataWidgetMapper::currentIndexChanged,
|
||||
this, &Window::updateButtons);
|
||||
|
||||
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(typeLabel, 3, 0, 1, 1);
|
||||
layout->addWidget(typeComboBox, 3, 1, 1, 1);
|
||||
setLayout(layout);
|
||||
|
||||
setWindowTitle(tr("Delegate Widget Mapper"));
|
||||
mapper->toFirst();
|
||||
}
|
||||
//! [Set up connections and layouts]
|
||||
|
||||
//! [Set up the model]
|
||||
void Window::setupModel()
|
||||
{
|
||||
QStringList items;
|
||||
items << tr("Home") << tr("Work") << tr("Other");
|
||||
typeModel = new QStringListModel(items, this);
|
||||
|
||||
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 types;
|
||||
types << "0" << "1" << "2" << "0" << "2";
|
||||
|
||||
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(types[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]
|
49
examples/widgets/itemviews/combowidgetmapper/window.h
Normal file
49
examples/widgets/itemviews/combowidgetmapper/window.h
Normal file
@ -0,0 +1,49 @@
|
||||
// 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 QComboBox;
|
||||
class QDataWidgetMapper;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
class QStandardItemModel;
|
||||
class QStringListModel;
|
||||
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 *typeLabel;
|
||||
QLineEdit *nameEdit;
|
||||
QTextEdit *addressEdit;
|
||||
QComboBox *typeComboBox;
|
||||
QPushButton *nextButton;
|
||||
QPushButton *previousButton;
|
||||
|
||||
QStandardItemModel *model;
|
||||
QStringListModel *typeModel;
|
||||
QDataWidgetMapper *mapper;
|
||||
};
|
||||
//! [Window definition]
|
||||
|
||||
#endif // WINDOW_H
|
@ -0,0 +1,51 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(customsortfiltermodel LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/customsortfiltermodel")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(customsortfiltermodel
|
||||
filterwidget.cpp filterwidget.h
|
||||
main.cpp
|
||||
mysortfilterproxymodel.cpp mysortfilterproxymodel.h
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(customsortfiltermodel PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(customsortfiltermodel PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(customsortfiltermodel_resource_files
|
||||
"images/find.png"
|
||||
)
|
||||
|
||||
qt_add_resources(customsortfiltermodel "customsortfiltermodel"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${customsortfiltermodel_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS customsortfiltermodel
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -0,0 +1,16 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(treeview))
|
||||
|
||||
HEADERS = mysortfilterproxymodel.h \
|
||||
window.h \
|
||||
filterwidget.h
|
||||
SOURCES = main.cpp \
|
||||
mysortfilterproxymodel.cpp \
|
||||
window.cpp \
|
||||
filterwidget.cpp
|
||||
|
||||
RESOURCES += customsortfiltermodel.qrc
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/customsortfiltermodel
|
||||
INSTALLS += target
|
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/">
|
||||
<file>images/find.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -0,0 +1,88 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "filterwidget.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
#include <QToolButton>
|
||||
#include <QWidgetAction>
|
||||
|
||||
FilterWidget::FilterWidget(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
, m_patternGroup(new QActionGroup(this))
|
||||
{
|
||||
setClearButtonEnabled(true);
|
||||
connect(this, &QLineEdit::textChanged, this, &FilterWidget::filterChanged);
|
||||
|
||||
QMenu *menu = new QMenu(this);
|
||||
m_caseSensitivityAction = menu->addAction(tr("Case Sensitive"));
|
||||
m_caseSensitivityAction->setCheckable(true);
|
||||
connect(m_caseSensitivityAction, &QAction::toggled, this, &FilterWidget::filterChanged);
|
||||
|
||||
menu->addSeparator();
|
||||
m_patternGroup->setExclusive(true);
|
||||
QAction *patternAction = menu->addAction("Regular Expression");
|
||||
patternAction->setCheckable(true);
|
||||
patternAction->setChecked(true);
|
||||
patternAction->setData(QVariant(int(RegularExpression)));
|
||||
m_patternGroup->addAction(patternAction);
|
||||
patternAction = menu->addAction("Wildcard");
|
||||
patternAction->setCheckable(true);
|
||||
patternAction->setData(QVariant(int(Wildcard)));
|
||||
m_patternGroup->addAction(patternAction);
|
||||
patternAction = menu->addAction("Fixed String");
|
||||
patternAction->setData(QVariant(int(FixedString)));
|
||||
patternAction->setCheckable(true);
|
||||
m_patternGroup->addAction(patternAction);
|
||||
connect(m_patternGroup, &QActionGroup::triggered, this, &FilterWidget::filterChanged);
|
||||
|
||||
const QIcon icon = QIcon(QPixmap(":/images/find.png"));
|
||||
QToolButton *optionsButton = new QToolButton;
|
||||
#ifndef QT_NO_CURSOR
|
||||
optionsButton->setCursor(Qt::ArrowCursor);
|
||||
#endif
|
||||
optionsButton->setFocusPolicy(Qt::NoFocus);
|
||||
optionsButton->setStyleSheet("* { border: none; }");
|
||||
optionsButton->setIcon(icon);
|
||||
optionsButton->setMenu(menu);
|
||||
optionsButton->setPopupMode(QToolButton::InstantPopup);
|
||||
|
||||
QWidgetAction *optionsAction = new QWidgetAction(this);
|
||||
optionsAction->setDefaultWidget(optionsButton);
|
||||
addAction(optionsAction, QLineEdit::LeadingPosition);
|
||||
}
|
||||
|
||||
Qt::CaseSensitivity FilterWidget::caseSensitivity() const
|
||||
{
|
||||
return m_caseSensitivityAction->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||||
}
|
||||
|
||||
void FilterWidget::setCaseSensitivity(Qt::CaseSensitivity cs)
|
||||
{
|
||||
m_caseSensitivityAction->setChecked(cs == Qt::CaseSensitive);
|
||||
}
|
||||
|
||||
static inline FilterWidget::PatternSyntax patternSyntaxFromAction(const QAction *a)
|
||||
{
|
||||
return static_cast<FilterWidget::PatternSyntax>(a->data().toInt());
|
||||
}
|
||||
|
||||
FilterWidget::PatternSyntax FilterWidget::patternSyntax() const
|
||||
{
|
||||
return patternSyntaxFromAction(m_patternGroup->checkedAction());
|
||||
}
|
||||
|
||||
void FilterWidget::setPatternSyntax(PatternSyntax s)
|
||||
{
|
||||
const QList<QAction*> actions = m_patternGroup->actions();
|
||||
for (QAction *a : actions) {
|
||||
if (patternSyntaxFromAction(a) == s) {
|
||||
a->setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef FILTERWIDGET_H
|
||||
#define FILTERWIDGET_H
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class FilterWidget : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity)
|
||||
Q_PROPERTY(PatternSyntax patternSyntax READ patternSyntax WRITE setPatternSyntax)
|
||||
public:
|
||||
explicit FilterWidget(QWidget *parent = nullptr);
|
||||
|
||||
Qt::CaseSensitivity caseSensitivity() const;
|
||||
void setCaseSensitivity(Qt::CaseSensitivity);
|
||||
|
||||
enum PatternSyntax {
|
||||
RegularExpression,
|
||||
Wildcard,
|
||||
FixedString
|
||||
};
|
||||
Q_ENUM(PatternSyntax)
|
||||
|
||||
PatternSyntax patternSyntax() const;
|
||||
void setPatternSyntax(PatternSyntax);
|
||||
|
||||
signals:
|
||||
void filterChanged();
|
||||
|
||||
private:
|
||||
QAction *m_caseSensitivityAction;
|
||||
QActionGroup *m_patternGroup;
|
||||
};
|
||||
|
||||
#endif // FILTERWIDGET_H
|
BIN
examples/widgets/itemviews/customsortfiltermodel/images/find.png
Normal file
BIN
examples/widgets/itemviews/customsortfiltermodel/images/find.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 737 B |
58
examples/widgets/itemviews/customsortfiltermodel/main.cpp
Normal file
58
examples/widgets/itemviews/customsortfiltermodel/main.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
void addMail(QAbstractItemModel *model, const QString &subject,
|
||||
const QString &sender, const QDateTime &date)
|
||||
{
|
||||
model->insertRow(0);
|
||||
model->setData(model->index(0, 0), subject);
|
||||
model->setData(model->index(0, 1), sender);
|
||||
model->setData(model->index(0, 2), date);
|
||||
}
|
||||
|
||||
QAbstractItemModel *createMailModel(QObject *parent)
|
||||
{
|
||||
QStandardItemModel *model = new QStandardItemModel(0, 3, parent);
|
||||
|
||||
model->setHeaderData(0, Qt::Horizontal, QObject::tr("Subject"));
|
||||
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Sender"));
|
||||
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Date"));
|
||||
|
||||
addMail(model, "Happy New Year!", "Grace K. <grace@software-inc.com>",
|
||||
QDateTime(QDate(2006, 12, 31), QTime(17, 03)));
|
||||
addMail(model, "Radically new concept", "Grace K. <grace@software-inc.com>",
|
||||
QDateTime(QDate(2006, 12, 22), QTime(9, 44)));
|
||||
addMail(model, "Accounts", "pascale@nospam.com",
|
||||
QDateTime(QDate(2006, 12, 31), QTime(12, 50)));
|
||||
addMail(model, "Expenses", "Joe Bloggs <joe@bloggs.com>",
|
||||
QDateTime(QDate(2006, 12, 25), QTime(11, 39)));
|
||||
addMail(model, "Re: Expenses", "Andy <andy@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 02), QTime(16, 05)));
|
||||
addMail(model, "Re: Accounts", "Joe Bloggs <joe@bloggs.com>",
|
||||
QDateTime(QDate(2007, 01, 03), QTime(14, 18)));
|
||||
addMail(model, "Re: Accounts", "Andy <andy@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 03), QTime(14, 26)));
|
||||
addMail(model, "Sports", "Linda Smith <linda.smith@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(11, 33)));
|
||||
addMail(model, "AW: Sports", "Rolf Newschweinstein <rolfn@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(12, 00)));
|
||||
addMail(model, "RE: Sports", "Petra Schmidt <petras@nospam.com>",
|
||||
QDateTime(QDate(2007, 01, 05), QTime(12, 01)));
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
//! [0]
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
Window window;
|
||||
window.setSourceModel(createMailModel(&window));
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
||||
//! [0]
|
@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mysortfilterproxymodel.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
void MySortFilterProxyModel::setFilterMinimumDate(QDate date)
|
||||
{
|
||||
minDate = date;
|
||||
invalidateFilter();
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
void MySortFilterProxyModel::setFilterMaximumDate(QDate date)
|
||||
{
|
||||
maxDate = date;
|
||||
invalidateFilter();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
|
||||
const QModelIndex &sourceParent) const
|
||||
{
|
||||
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
|
||||
QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);
|
||||
|
||||
return (sourceModel()->data(index0).toString().contains(filterRegularExpression())
|
||||
|| sourceModel()->data(index1).toString().contains(filterRegularExpression()))
|
||||
&& dateInRange(sourceModel()->data(index2).toDate());
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4] //! [5]
|
||||
bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
QVariant leftData = sourceModel()->data(left);
|
||||
QVariant rightData = sourceModel()->data(right);
|
||||
//! [4]
|
||||
|
||||
//! [6]
|
||||
if (leftData.userType() == QMetaType::QDateTime) {
|
||||
return leftData.toDateTime() < rightData.toDateTime();
|
||||
} else {
|
||||
static const QRegularExpression emailPattern("[\\w\\.]*@[\\w\\.]*");
|
||||
|
||||
QString leftString = leftData.toString();
|
||||
if (left.column() == 1) {
|
||||
const QRegularExpressionMatch match = emailPattern.match(leftString);
|
||||
if (match.hasMatch())
|
||||
leftString = match.captured(0);
|
||||
}
|
||||
QString rightString = rightData.toString();
|
||||
if (right.column() == 1) {
|
||||
const QRegularExpressionMatch match = emailPattern.match(rightString);
|
||||
if (match.hasMatch())
|
||||
rightString = match.captured(0);
|
||||
}
|
||||
|
||||
return QString::localeAwareCompare(leftString, rightString) < 0;
|
||||
}
|
||||
}
|
||||
//! [5] //! [6]
|
||||
|
||||
//! [7]
|
||||
bool MySortFilterProxyModel::dateInRange(QDate date) const
|
||||
{
|
||||
return (!minDate.isValid() || date > minDate)
|
||||
&& (!maxDate.isValid() || date < maxDate);
|
||||
}
|
||||
//! [7]
|
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MYSORTFILTERPROXYMODEL_H
|
||||
#define MYSORTFILTERPROXYMODEL_H
|
||||
|
||||
#include <QDate>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
//! [0]
|
||||
class MySortFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MySortFilterProxyModel(QObject *parent = nullptr);
|
||||
|
||||
QDate filterMinimumDate() const { return minDate; }
|
||||
void setFilterMinimumDate(QDate date);
|
||||
|
||||
QDate filterMaximumDate() const { return maxDate; }
|
||||
void setFilterMaximumDate(QDate date);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
private:
|
||||
bool dateInRange(QDate date) const;
|
||||
|
||||
QDate minDate;
|
||||
QDate maxDate;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // MYSORTFILTERPROXYMODEL_H
|
131
examples/widgets/itemviews/customsortfiltermodel/window.cpp
Normal file
131
examples/widgets/itemviews/customsortfiltermodel/window.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
#include "mysortfilterproxymodel.h"
|
||||
#include "filterwidget.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
Window::Window()
|
||||
{
|
||||
proxyModel = new MySortFilterProxyModel(this);
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
sourceView = new QTreeView;
|
||||
sourceView->setRootIsDecorated(false);
|
||||
sourceView->setAlternatingRowColors(true);
|
||||
//! [1]
|
||||
|
||||
QHBoxLayout *sourceLayout = new QHBoxLayout;
|
||||
//! [2]
|
||||
sourceLayout->addWidget(sourceView);
|
||||
sourceGroupBox = new QGroupBox(tr("Original Model"));
|
||||
sourceGroupBox->setLayout(sourceLayout);
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
filterWidget = new FilterWidget;
|
||||
filterWidget->setText(tr("Grace|Sports"));
|
||||
connect(filterWidget, &FilterWidget::filterChanged, this, &Window::textFilterChanged);
|
||||
|
||||
filterPatternLabel = new QLabel(tr("&Filter pattern:"));
|
||||
filterPatternLabel->setBuddy(filterWidget);
|
||||
|
||||
fromDateEdit = new QDateEdit;
|
||||
fromDateEdit->setDate(QDate(1970, 01, 01));
|
||||
fromLabel = new QLabel(tr("F&rom:"));
|
||||
fromLabel->setBuddy(fromDateEdit);
|
||||
|
||||
toDateEdit = new QDateEdit;
|
||||
toDateEdit->setDate(QDate(2099, 12, 31));
|
||||
toLabel = new QLabel(tr("&To:"));
|
||||
toLabel->setBuddy(toDateEdit);
|
||||
|
||||
connect(filterWidget, &QLineEdit::textChanged,
|
||||
this, &Window::textFilterChanged);
|
||||
connect(fromDateEdit, &QDateTimeEdit::dateChanged,
|
||||
this, &Window::dateFilterChanged);
|
||||
connect(toDateEdit, &QDateTimeEdit::dateChanged,
|
||||
//! [3] //! [4]
|
||||
this, &Window::dateFilterChanged);
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
proxyView = new QTreeView;
|
||||
proxyView->setRootIsDecorated(false);
|
||||
proxyView->setAlternatingRowColors(true);
|
||||
proxyView->setModel(proxyModel);
|
||||
proxyView->setSortingEnabled(true);
|
||||
proxyView->sortByColumn(1, Qt::AscendingOrder);
|
||||
|
||||
QGridLayout *proxyLayout = new QGridLayout;
|
||||
proxyLayout->addWidget(proxyView, 0, 0, 1, 3);
|
||||
proxyLayout->addWidget(filterPatternLabel, 1, 0);
|
||||
proxyLayout->addWidget(filterWidget, 1, 1);
|
||||
proxyLayout->addWidget(fromLabel, 3, 0);
|
||||
proxyLayout->addWidget(fromDateEdit, 3, 1, 1, 2);
|
||||
proxyLayout->addWidget(toLabel, 4, 0);
|
||||
proxyLayout->addWidget(toDateEdit, 4, 1, 1, 2);
|
||||
|
||||
proxyGroupBox = new QGroupBox(tr("Sorted/Filtered Model"));
|
||||
proxyGroupBox->setLayout(proxyLayout);
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(sourceGroupBox);
|
||||
mainLayout->addWidget(proxyGroupBox);
|
||||
setLayout(mainLayout);
|
||||
|
||||
setWindowTitle(tr("Custom Sort/Filter Model"));
|
||||
resize(500, 450);
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
void Window::setSourceModel(QAbstractItemModel *model)
|
||||
{
|
||||
proxyModel->setSourceModel(model);
|
||||
sourceView->setModel(model);
|
||||
|
||||
for (int i = 0; i < proxyModel->columnCount(); ++i)
|
||||
proxyView->resizeColumnToContents(i);
|
||||
for (int i = 0; i < model->columnCount(); ++i)
|
||||
sourceView->resizeColumnToContents(i);
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
void Window::textFilterChanged()
|
||||
{
|
||||
FilterWidget::PatternSyntax s = filterWidget->patternSyntax();
|
||||
QString pattern = filterWidget->text();
|
||||
switch (s) {
|
||||
case FilterWidget::Wildcard:
|
||||
pattern = QRegularExpression::wildcardToRegularExpression(pattern);
|
||||
break;
|
||||
case FilterWidget::FixedString:
|
||||
pattern = QRegularExpression::escape(pattern);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
|
||||
if (filterWidget->caseSensitivity() == Qt::CaseInsensitive)
|
||||
options |= QRegularExpression::CaseInsensitiveOption;
|
||||
QRegularExpression regularExpression(pattern, options);
|
||||
proxyModel->setFilterRegularExpression(regularExpression);
|
||||
}
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
void Window::dateFilterChanged()
|
||||
{
|
||||
proxyModel->setFilterMinimumDate(fromDateEdit->date());
|
||||
proxyModel->setFilterMaximumDate(toDateEdit->date());
|
||||
}
|
||||
//! [9]
|
51
examples/widgets/itemviews/customsortfiltermodel/window.h
Normal file
51
examples/widgets/itemviews/customsortfiltermodel/window.h
Normal file
@ -0,0 +1,51 @@
|
||||
// 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 QAbstractItemModel;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDateEdit;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QTreeView;
|
||||
QT_END_NAMESPACE
|
||||
class MySortFilterProxyModel;
|
||||
class FilterWidget;
|
||||
//! [0]
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
void setSourceModel(QAbstractItemModel *model);
|
||||
|
||||
private slots:
|
||||
void textFilterChanged();
|
||||
void dateFilterChanged();
|
||||
|
||||
private:
|
||||
MySortFilterProxyModel *proxyModel;
|
||||
|
||||
QGroupBox *sourceGroupBox;
|
||||
QGroupBox *proxyGroupBox;
|
||||
QTreeView *sourceView;
|
||||
QTreeView *proxyView;
|
||||
QLabel *filterPatternLabel;
|
||||
QLabel *fromLabel;
|
||||
QLabel *toLabel;
|
||||
FilterWidget *filterWidget;
|
||||
QDateEdit *fromDateEdit;
|
||||
QDateEdit *toDateEdit;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // WINDOW_H
|
36
examples/widgets/itemviews/dirview/CMakeLists.txt
Normal file
36
examples/widgets/itemviews/dirview/CMakeLists.txt
Normal 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}"
|
||||
)
|
8
examples/widgets/itemviews/dirview/dirview.pro
Normal file
8
examples/widgets/itemviews/dirview/dirview.pro
Normal file
@ -0,0 +1,8 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(treeview))
|
||||
|
||||
SOURCES = main.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/dirview
|
||||
INSTALLS += target
|
62
examples/widgets/itemviews/dirview/main.cpp
Normal file
62
examples/widgets/itemviews/dirview/main.cpp
Normal 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();
|
||||
}
|
51
examples/widgets/itemviews/editabletreemodel/CMakeLists.txt
Normal file
51
examples/widgets/itemviews/editabletreemodel/CMakeLists.txt
Normal 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(editabletreemodel LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/editabletreemodel")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(editabletreemodel
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h mainwindow.ui
|
||||
treeitem.cpp treeitem.h
|
||||
treemodel.cpp treemodel.h
|
||||
)
|
||||
|
||||
set_target_properties(editabletreemodel PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(editabletreemodel PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(editabletreemodel_resource_files
|
||||
"default.txt"
|
||||
)
|
||||
|
||||
qt_add_resources(editabletreemodel "editabletreemodel"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${editabletreemodel_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS editabletreemodel
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
40
examples/widgets/itemviews/editabletreemodel/default.txt
Normal file
40
examples/widgets/itemviews/editabletreemodel/default.txt
Normal file
@ -0,0 +1,40 @@
|
||||
Getting Started How to familiarize yourself with Qt Designer
|
||||
Launching Designer Running the Qt Designer application
|
||||
The User Interface How to interact with Qt Designer
|
||||
|
||||
Designing a Component Creating a GUI for your application
|
||||
Creating a Dialog How to create a dialog
|
||||
Composing the Dialog Putting widgets into the dialog example
|
||||
Creating a Layout Arranging widgets on a form
|
||||
Signal and Slot Connections Making widget communicate with each other
|
||||
|
||||
Using a Component in Your Application Generating code from forms
|
||||
The Direct Approach Using a form without any adjustments
|
||||
The Single Inheritance Approach Subclassing a form's base class
|
||||
The Multiple Inheritance Approach Subclassing the form itself
|
||||
Automatic Connections Connecting widgets using a naming scheme
|
||||
A Dialog Without Auto-Connect How to connect widgets without a naming scheme
|
||||
A Dialog With Auto-Connect Using automatic connections
|
||||
|
||||
Form Editing Mode How to edit a form in Qt Designer
|
||||
Managing Forms Loading and saving forms
|
||||
Editing a Form Basic editing techniques
|
||||
The Property Editor Changing widget properties
|
||||
The Object Inspector Examining the hierarchy of objects on a form
|
||||
Layouts Objects that arrange widgets on a form
|
||||
Applying and Breaking Layouts Managing widgets in layouts
|
||||
Horizontal and Vertical Layouts Standard row and column layouts
|
||||
The Grid Layout Arranging widgets in a matrix
|
||||
Previewing Forms Checking that the design works
|
||||
|
||||
Using Containers How to group widgets together
|
||||
General Features Common container features
|
||||
Frames QFrame
|
||||
Group Boxes QGroupBox
|
||||
Stacked Widgets QStackedWidget
|
||||
Tab Widgets QTabWidget
|
||||
Toolbox Widgets QToolBox
|
||||
|
||||
Connection Editing Mode Connecting widgets together with signals and slots
|
||||
Connecting Objects Making connections in Qt Designer
|
||||
Editing Connections Changing existing connections
|
@ -0,0 +1,16 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(treeview))
|
||||
|
||||
FORMS = mainwindow.ui
|
||||
HEADERS = mainwindow.h \
|
||||
treeitem.h \
|
||||
treemodel.h
|
||||
RESOURCES = editabletreemodel.qrc
|
||||
SOURCES = mainwindow.cpp \
|
||||
treeitem.cpp \
|
||||
treemodel.cpp \
|
||||
main.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/editabletreemodel
|
||||
INSTALLS += target
|
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>default.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
16
examples/widgets/itemviews/editabletreemodel/main.cpp
Normal file
16
examples/widgets/itemviews/editabletreemodel/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// 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[])
|
||||
{
|
||||
Q_INIT_RESOURCE(editabletreemodel);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
137
examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
Normal file
137
examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "treemodel.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
const QStringList headers({tr("Title"), tr("Description")});
|
||||
|
||||
QFile file(":/default.txt");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
TreeModel *model = new TreeModel(headers, file.readAll(), this);
|
||||
file.close();
|
||||
|
||||
view->setModel(model);
|
||||
for (int column = 0; column < model->columnCount(); ++column)
|
||||
view->resizeColumnToContents(column);
|
||||
|
||||
connect(exitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
|
||||
|
||||
connect(view->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &MainWindow::updateActions);
|
||||
|
||||
connect(actionsMenu, &QMenu::aboutToShow, this, &MainWindow::updateActions);
|
||||
connect(insertRowAction, &QAction::triggered, this, &MainWindow::insertRow);
|
||||
connect(insertColumnAction, &QAction::triggered, this, &MainWindow::insertColumn);
|
||||
connect(removeRowAction, &QAction::triggered, this, &MainWindow::removeRow);
|
||||
connect(removeColumnAction, &QAction::triggered, this, &MainWindow::removeColumn);
|
||||
connect(insertChildAction, &QAction::triggered, this, &MainWindow::insertChild);
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::insertChild()
|
||||
{
|
||||
const QModelIndex index = view->selectionModel()->currentIndex();
|
||||
QAbstractItemModel *model = view->model();
|
||||
|
||||
if (model->columnCount(index) == 0) {
|
||||
if (!model->insertColumn(0, index))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!model->insertRow(0, index))
|
||||
return;
|
||||
|
||||
for (int column = 0; column < model->columnCount(index); ++column) {
|
||||
const QModelIndex child = model->index(0, column, index);
|
||||
model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
|
||||
if (!model->headerData(column, Qt::Horizontal).isValid())
|
||||
model->setHeaderData(column, Qt::Horizontal, QVariant(tr("[No header]")), Qt::EditRole);
|
||||
}
|
||||
|
||||
view->selectionModel()->setCurrentIndex(model->index(0, 0, index),
|
||||
QItemSelectionModel::ClearAndSelect);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
bool MainWindow::insertColumn()
|
||||
{
|
||||
QAbstractItemModel *model = view->model();
|
||||
int column = view->selectionModel()->currentIndex().column();
|
||||
|
||||
// Insert a column in the parent item.
|
||||
bool changed = model->insertColumn(column + 1);
|
||||
if (changed)
|
||||
model->setHeaderData(column + 1, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);
|
||||
|
||||
updateActions();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void MainWindow::insertRow()
|
||||
{
|
||||
const QModelIndex index = view->selectionModel()->currentIndex();
|
||||
QAbstractItemModel *model = view->model();
|
||||
|
||||
if (!model->insertRow(index.row()+1, index.parent()))
|
||||
return;
|
||||
|
||||
updateActions();
|
||||
|
||||
for (int column = 0; column < model->columnCount(index.parent()); ++column) {
|
||||
const QModelIndex child = model->index(index.row() + 1, column, index.parent());
|
||||
model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::removeColumn()
|
||||
{
|
||||
QAbstractItemModel *model = view->model();
|
||||
const int column = view->selectionModel()->currentIndex().column();
|
||||
|
||||
// Insert columns in each child of the parent item.
|
||||
const bool changed = model->removeColumn(column);
|
||||
if (changed)
|
||||
updateActions();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void MainWindow::removeRow()
|
||||
{
|
||||
const QModelIndex index = view->selectionModel()->currentIndex();
|
||||
QAbstractItemModel *model = view->model();
|
||||
if (model->removeRow(index.row(), index.parent()))
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
const bool hasSelection = !view->selectionModel()->selection().isEmpty();
|
||||
removeRowAction->setEnabled(hasSelection);
|
||||
removeColumnAction->setEnabled(hasSelection);
|
||||
|
||||
const bool hasCurrent = view->selectionModel()->currentIndex().isValid();
|
||||
insertRowAction->setEnabled(hasCurrent);
|
||||
insertColumnAction->setEnabled(hasCurrent);
|
||||
|
||||
if (hasCurrent) {
|
||||
view->closePersistentEditor(view->selectionModel()->currentIndex());
|
||||
|
||||
const int row = view->selectionModel()->currentIndex().row();
|
||||
const int column = view->selectionModel()->currentIndex().column();
|
||||
if (view->selectionModel()->currentIndex().parent().isValid())
|
||||
statusBar()->showMessage(tr("Position: (%1,%2)").arg(row).arg(column));
|
||||
else
|
||||
statusBar()->showMessage(tr("Position: (%1,%2) in top level").arg(row).arg(column));
|
||||
}
|
||||
}
|
29
examples/widgets/itemviews/editabletreemodel/mainwindow.h
Normal file
29
examples/widgets/itemviews/editabletreemodel/mainwindow.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void updateActions();
|
||||
|
||||
private slots:
|
||||
void insertChild();
|
||||
bool insertColumn();
|
||||
void insertRow();
|
||||
bool removeColumn();
|
||||
void removeRow();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
128
examples/widgets/itemviews/editabletreemodel/mainwindow.ui
Normal file
128
examples/widgets/itemviews/editabletreemodel/mainwindow.ui
Normal file
@ -0,0 +1,128 @@
|
||||
<ui version="4.0" >
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>573</width>
|
||||
<height>468</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Editable Tree Model</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeView" name="view" >
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode" >
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="animated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>573</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="fileMenu" >
|
||||
<property name="title" >
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="exitAction" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="actionsMenu" >
|
||||
<property name="title" >
|
||||
<string>&Actions</string>
|
||||
</property>
|
||||
<addaction name="insertRowAction" />
|
||||
<addaction name="insertColumnAction" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="removeRowAction" />
|
||||
<addaction name="removeColumnAction" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="insertChildAction" />
|
||||
</widget>
|
||||
<addaction name="fileMenu" />
|
||||
<addaction name="actionsMenu" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar" />
|
||||
<action name="exitAction" >
|
||||
<property name="text" >
|
||||
<string>E&xit</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertRowAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Row</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+I, R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="removeRowAction" >
|
||||
<property name="text" >
|
||||
<string>Remove Row</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+R, R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertColumnAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Column</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+I, C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="removeColumnAction" >
|
||||
<property name="text" >
|
||||
<string>Remove Column</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+R, C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertChildAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Child</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+N</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="editabletreemodel.qrc" />
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
141
examples/widgets/itemviews/editabletreemodel/treeitem.cpp
Normal file
141
examples/widgets/itemviews/editabletreemodel/treeitem.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
/*
|
||||
treeitem.cpp
|
||||
|
||||
A container for items of data supplied by the simple tree model.
|
||||
*/
|
||||
|
||||
#include "treeitem.h"
|
||||
|
||||
//! [0]
|
||||
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
|
||||
: itemData(data), parentItem(parent)
|
||||
{}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
TreeItem::~TreeItem()
|
||||
{
|
||||
qDeleteAll(childItems);
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
TreeItem *TreeItem::child(int number)
|
||||
{
|
||||
if (number < 0 || number >= childItems.size())
|
||||
return nullptr;
|
||||
return childItems.at(number);
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
int TreeItem::childCount() const
|
||||
{
|
||||
return childItems.count();
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
int TreeItem::childNumber() const
|
||||
{
|
||||
if (parentItem)
|
||||
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
|
||||
return 0;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
int TreeItem::columnCount() const
|
||||
{
|
||||
return itemData.count();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QVariant TreeItem::data(int column) const
|
||||
{
|
||||
if (column < 0 || column >= itemData.size())
|
||||
return QVariant();
|
||||
return itemData.at(column);
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
bool TreeItem::insertChildren(int position, int count, int columns)
|
||||
{
|
||||
if (position < 0 || position > childItems.size())
|
||||
return false;
|
||||
|
||||
for (int row = 0; row < count; ++row) {
|
||||
QList<QVariant> data(columns);
|
||||
TreeItem *item = new TreeItem(data, this);
|
||||
childItems.insert(position, item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
bool TreeItem::insertColumns(int position, int columns)
|
||||
{
|
||||
if (position < 0 || position > itemData.size())
|
||||
return false;
|
||||
|
||||
for (int column = 0; column < columns; ++column)
|
||||
itemData.insert(position, QVariant());
|
||||
|
||||
for (TreeItem *child : std::as_const(childItems))
|
||||
child->insertColumns(position, columns);
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
TreeItem *TreeItem::parent()
|
||||
{
|
||||
return parentItem;
|
||||
}
|
||||
//! [9]
|
||||
|
||||
//! [10]
|
||||
bool TreeItem::removeChildren(int position, int count)
|
||||
{
|
||||
if (position < 0 || position + count > childItems.size())
|
||||
return false;
|
||||
|
||||
for (int row = 0; row < count; ++row)
|
||||
delete childItems.takeAt(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [10]
|
||||
|
||||
bool TreeItem::removeColumns(int position, int columns)
|
||||
{
|
||||
if (position < 0 || position + columns > itemData.size())
|
||||
return false;
|
||||
|
||||
for (int column = 0; column < columns; ++column)
|
||||
itemData.remove(position);
|
||||
|
||||
for (TreeItem *child : std::as_const(childItems))
|
||||
child->removeColumns(position, columns);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! [11]
|
||||
bool TreeItem::setData(int column, const QVariant &value)
|
||||
{
|
||||
if (column < 0 || column >= itemData.size())
|
||||
return false;
|
||||
|
||||
itemData[column] = value;
|
||||
return true;
|
||||
}
|
||||
//! [11]
|
36
examples/widgets/itemviews/editabletreemodel/treeitem.h
Normal file
36
examples/widgets/itemviews/editabletreemodel/treeitem.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef TREEITEM_H
|
||||
#define TREEITEM_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QList>
|
||||
|
||||
//! [0]
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
explicit TreeItem(const QList<QVariant> &data, TreeItem *parent = nullptr);
|
||||
~TreeItem();
|
||||
|
||||
TreeItem *child(int number);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
bool insertChildren(int position, int count, int columns);
|
||||
bool insertColumns(int position, int columns);
|
||||
TreeItem *parent();
|
||||
bool removeChildren(int position, int count);
|
||||
bool removeColumns(int position, int columns);
|
||||
int childNumber() const;
|
||||
bool setData(int column, const QVariant &value);
|
||||
|
||||
private:
|
||||
QList<TreeItem *> childItems;
|
||||
QList<QVariant> itemData;
|
||||
TreeItem *parentItem;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // TREEITEM_H
|
256
examples/widgets/itemviews/editabletreemodel/treemodel.cpp
Normal file
256
examples/widgets/itemviews/editabletreemodel/treemodel.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "treemodel.h"
|
||||
#include "treeitem.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
TreeModel::TreeModel(const QStringList &headers, const QString &data, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
QList<QVariant> rootData;
|
||||
for (const QString &header : headers)
|
||||
rootData << header;
|
||||
|
||||
rootItem = new TreeItem(rootData);
|
||||
setupModelData(data.split('\n'), rootItem);
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
TreeModel::~TreeModel()
|
||||
{
|
||||
delete rootItem;
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role != Qt::DisplayRole && role != Qt::EditRole)
|
||||
return QVariant();
|
||||
|
||||
TreeItem *item = getItem(index);
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
//! [3]
|
||||
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
TreeItem *TreeModel::getItem(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return rootItem;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
//! [5]
|
||||
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() != 0)
|
||||
return QModelIndex();
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
return QModelIndex();
|
||||
}
|
||||
//! [6]
|
||||
|
||||
bool TreeModel::insertColumns(int position, int columns, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertColumns(parent, position, position + columns - 1);
|
||||
const bool success = rootItem->insertColumns(position, columns);
|
||||
endInsertColumns();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TreeModel::insertRows(int position, int rows, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return false;
|
||||
|
||||
beginInsertRows(parent, position, position + rows - 1);
|
||||
const bool success = parentItem->insertChildren(position,
|
||||
rows,
|
||||
rootItem->columnCount());
|
||||
endInsertRows();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//! [7]
|
||||
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = getItem(index);
|
||||
TreeItem *parentItem = childItem ? childItem->parent() : nullptr;
|
||||
|
||||
if (parentItem == rootItem || !parentItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->childNumber(), 0, parentItem);
|
||||
}
|
||||
//! [7]
|
||||
|
||||
bool TreeModel::removeColumns(int position, int columns, const QModelIndex &parent)
|
||||
{
|
||||
beginRemoveColumns(parent, position, position + columns - 1);
|
||||
const bool success = rootItem->removeColumns(position, columns);
|
||||
endRemoveColumns();
|
||||
|
||||
if (rootItem->columnCount() == 0)
|
||||
removeRows(0, rowCount());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TreeModel::removeRows(int position, int rows, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return false;
|
||||
|
||||
beginRemoveRows(parent, position, position + rows - 1);
|
||||
const bool success = parentItem->removeChildren(position, rows);
|
||||
endRemoveRows();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//! [8]
|
||||
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
const TreeItem *parentItem = getItem(parent);
|
||||
|
||||
return parentItem ? parentItem->childCount() : 0;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
TreeItem *item = getItem(index);
|
||||
bool result = item->setData(index.column(), value);
|
||||
|
||||
if (result)
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TreeModel::setHeaderData(int section, Qt::Orientation orientation,
|
||||
const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole || orientation != Qt::Horizontal)
|
||||
return false;
|
||||
|
||||
const bool result = rootItem->setData(section, value);
|
||||
|
||||
if (result)
|
||||
emit headerDataChanged(orientation, section, section);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
|
||||
{
|
||||
QList<TreeItem *> parents;
|
||||
QList<int> indentations;
|
||||
parents << parent;
|
||||
indentations << 0;
|
||||
|
||||
int number = 0;
|
||||
|
||||
while (number < lines.count()) {
|
||||
int position = 0;
|
||||
while (position < lines[number].length()) {
|
||||
if (lines[number].at(position) != ' ')
|
||||
break;
|
||||
++position;
|
||||
}
|
||||
|
||||
const QString lineData = lines[number].mid(position).trimmed();
|
||||
|
||||
if (!lineData.isEmpty()) {
|
||||
// Read the column data from the rest of the line.
|
||||
const QStringList columnStrings =
|
||||
lineData.split(QLatin1Char('\t'), Qt::SkipEmptyParts);
|
||||
QList<QVariant> columnData;
|
||||
columnData.reserve(columnStrings.size());
|
||||
for (const QString &columnString : columnStrings)
|
||||
columnData << columnString;
|
||||
|
||||
if (position > indentations.last()) {
|
||||
// The last child of the current parent is now the new parent
|
||||
// unless the current parent has no children.
|
||||
|
||||
if (parents.last()->childCount() > 0) {
|
||||
parents << parents.last()->child(parents.last()->childCount()-1);
|
||||
indentations << position;
|
||||
}
|
||||
} else {
|
||||
while (position < indentations.last() && parents.count() > 0) {
|
||||
parents.pop_back();
|
||||
indentations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Append a new item to the current parent's list of children.
|
||||
TreeItem *parent = parents.last();
|
||||
parent->insertChildren(parent->childCount(), 1, rootItem->columnCount());
|
||||
for (int column = 0; column < columnData.size(); ++column)
|
||||
parent->child(parent->childCount() - 1)->setData(column, columnData[column]);
|
||||
}
|
||||
++number;
|
||||
}
|
||||
}
|
60
examples/widgets/itemviews/editabletreemodel/treemodel.h
Normal file
60
examples/widgets/itemviews/editabletreemodel/treemodel.h
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef TREEMODEL_H
|
||||
#define TREEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
|
||||
class TreeItem;
|
||||
|
||||
//! [0]
|
||||
class TreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TreeModel(const QStringList &headers, const QString &data,
|
||||
QObject *parent = nullptr);
|
||||
~TreeModel();
|
||||
//! [0] //! [1]
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) 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 &index) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
bool setHeaderData(int section, Qt::Orientation orientation,
|
||||
const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
bool insertColumns(int position, int columns,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool removeColumns(int position, int columns,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool insertRows(int position, int rows,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool removeRows(int position, int rows,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
void setupModelData(const QStringList &lines, TreeItem *parent);
|
||||
TreeItem *getItem(const QModelIndex &index) const;
|
||||
|
||||
TreeItem *rootItem;
|
||||
};
|
||||
//! [2]
|
||||
|
||||
#endif // TREEMODEL_H
|
38
examples/widgets/itemviews/fetchmore/CMakeLists.txt
Normal file
38
examples/widgets/itemviews/fetchmore/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(fetchmore LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/fetchmore")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(fetchmore
|
||||
filelistmodel.cpp filelistmodel.h
|
||||
main.cpp
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(fetchmore PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(fetchmore PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS fetchmore
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
12
examples/widgets/itemviews/fetchmore/fetchmore.pro
Normal file
12
examples/widgets/itemviews/fetchmore/fetchmore.pro
Normal file
@ -0,0 +1,12 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(listview))
|
||||
|
||||
HEADERS = filelistmodel.h \
|
||||
window.h
|
||||
SOURCES = filelistmodel.cpp \
|
||||
main.cpp \
|
||||
window.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/fetchmore
|
||||
INSTALLS += target
|
95
examples/widgets/itemviews/fetchmore/filelistmodel.cpp
Normal file
95
examples/widgets/itemviews/fetchmore/filelistmodel.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "filelistmodel.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QDir>
|
||||
#include <QPalette>
|
||||
|
||||
static const int batchSize = 100;
|
||||
|
||||
FileListModel::FileListModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{}
|
||||
|
||||
//![4]
|
||||
int FileListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : fileCount;
|
||||
}
|
||||
|
||||
QVariant FileListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
const int row = index.row();
|
||||
if (row >= fileList.size() || row < 0)
|
||||
return {};
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return fileList.at(row).fileName();
|
||||
case Qt::BackgroundRole: {
|
||||
const int batch = row / batchSize;
|
||||
const QPalette &palette = QGuiApplication::palette();
|
||||
return (batch % 2) != 0 ? palette.alternateBase() : palette.base();
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
return iconProvider.icon(fileList.at(row));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//![4]
|
||||
|
||||
QFileInfo FileListModel::fileInfoAt(const QModelIndex &index) const
|
||||
{
|
||||
return fileList.at(index.row());
|
||||
}
|
||||
|
||||
//![1]
|
||||
bool FileListModel::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return false;
|
||||
return (fileCount < fileList.size());
|
||||
}
|
||||
//![1]
|
||||
|
||||
//![2]
|
||||
void FileListModel::fetchMore(const QModelIndex &parent)
|
||||
{
|
||||
if (parent.isValid())
|
||||
return;
|
||||
const int start = fileCount;
|
||||
const int remainder = int(fileList.size()) - start;
|
||||
const int itemsToFetch = qMin(batchSize, remainder);
|
||||
|
||||
if (itemsToFetch <= 0)
|
||||
return;
|
||||
|
||||
beginInsertRows(QModelIndex(), start, start + itemsToFetch - 1);
|
||||
|
||||
fileCount += itemsToFetch;
|
||||
|
||||
endInsertRows();
|
||||
|
||||
emit numberPopulated(path, start, itemsToFetch, int(fileList.size()));
|
||||
}
|
||||
//![2]
|
||||
|
||||
//![0]
|
||||
void FileListModel::setDirPath(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
|
||||
beginResetModel();
|
||||
this->path = path;
|
||||
fileList = dir.entryInfoList(QDir::NoDot | QDir::AllEntries, QDir::Name);
|
||||
fileCount = 0;
|
||||
endResetModel();
|
||||
}
|
||||
//![0]
|
||||
|
42
examples/widgets/itemviews/fetchmore/filelistmodel.h
Normal file
42
examples/widgets/itemviews/fetchmore/filelistmodel.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef FILELISTMODEL_H
|
||||
#define FILELISTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QFileInfoList>
|
||||
#include <QFileIconProvider>
|
||||
|
||||
//![0]
|
||||
class FileListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FileListModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QFileInfo fileInfoAt(const QModelIndex &) const;
|
||||
|
||||
signals:
|
||||
void numberPopulated(const QString &path, int start, int number, int total);
|
||||
|
||||
public slots:
|
||||
void setDirPath(const QString &path);
|
||||
|
||||
protected:
|
||||
bool canFetchMore(const QModelIndex &parent) const override;
|
||||
void fetchMore(const QModelIndex &parent) override;
|
||||
|
||||
private:
|
||||
QFileInfoList fileList;
|
||||
QString path;
|
||||
QFileIconProvider iconProvider;
|
||||
int fileCount = 0;
|
||||
};
|
||||
//![0]
|
||||
|
||||
#endif // FILELISTMODEL_H
|
14
examples/widgets/itemviews/fetchmore/main.cpp
Normal file
14
examples/widgets/itemviews/fetchmore/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
Window window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
51
examples/widgets/itemviews/fetchmore/window.cpp
Normal file
51
examples/widgets/itemviews/fetchmore/window.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
#include "filelistmodel.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
Window::Window(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
model = new FileListModel(this);
|
||||
model->setDirPath(QDir::rootPath());
|
||||
|
||||
view = new QListView;
|
||||
view->setModel(model);
|
||||
|
||||
logViewer = new QPlainTextEdit(this);
|
||||
logViewer->setReadOnly(true);
|
||||
logViewer->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,
|
||||
QSizePolicy::Preferred));
|
||||
|
||||
connect(model, &FileListModel::numberPopulated,
|
||||
this, &Window::updateLog);
|
||||
connect(view, &QAbstractItemView::activated,
|
||||
this, &Window::activated);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(view);
|
||||
layout->addWidget(logViewer);
|
||||
|
||||
setWindowTitle(tr("Fetch More Example"));
|
||||
}
|
||||
|
||||
void Window::updateLog(const QString &path, int start, int number, int total)
|
||||
{
|
||||
const int last = start + number - 1;
|
||||
const QString nativePath = QDir::toNativeSeparators(path);
|
||||
const QString message = tr("%1..%2/%3 items from \"%4\" added.")
|
||||
.arg(start).arg(last).arg(total).arg(nativePath);
|
||||
logViewer->appendPlainText(message);
|
||||
}
|
||||
|
||||
void Window::activated(const QModelIndex &index)
|
||||
{
|
||||
const QFileInfo fi = model->fileInfoAt(index);
|
||||
if (fi.isDir()) {
|
||||
logViewer->clear();
|
||||
model->setDirPath(fi.absoluteFilePath());
|
||||
}
|
||||
}
|
34
examples/widgets/itemviews/fetchmore/window.h
Normal file
34
examples/widgets/itemviews/fetchmore/window.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
class QListView;
|
||||
class QPlainTextEdit;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class FileListModel;
|
||||
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void updateLog(const QString &path, int start, int number, int total);
|
||||
void activated(const QModelIndex &);
|
||||
|
||||
private:
|
||||
QPlainTextEdit *logViewer;
|
||||
FileListModel *model;
|
||||
QListView *view;
|
||||
};
|
||||
|
||||
#endif // WINDOW_H
|
36
examples/widgets/itemviews/flattreeview/CMakeLists.txt
Normal file
36
examples/widgets/itemviews/flattreeview/CMakeLists.txt
Normal 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(flattreeview LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/flattreeview")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(flattreeview
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(flattreeview PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(flattreeview PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS flattreeview
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
7
examples/widgets/itemviews/flattreeview/flattreeview.pro
Normal file
7
examples/widgets/itemviews/flattreeview/flattreeview.pro
Normal file
@ -0,0 +1,7 @@
|
||||
QT += widgets
|
||||
|
||||
SOURCES = main.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/flattreeview
|
||||
INSTALLS += target
|
37
examples/widgets/itemviews/flattreeview/main.cpp
Normal file
37
examples/widgets/itemviews/flattreeview/main.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2017 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
/*
|
||||
main.cpp
|
||||
|
||||
A simple example that shows a multi-column list using QTreeView.
|
||||
The data is not a tree, so the first column was made movable.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QHeaderView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTreeView>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QStandardItemModel model(4, 2);
|
||||
QTreeView treeView;
|
||||
treeView.setModel(&model);
|
||||
treeView.setRootIsDecorated(false);
|
||||
treeView.header()->setFirstSectionMovable(true);
|
||||
treeView.header()->setStretchLastSection(true);
|
||||
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int column = 0; column < 2; ++column) {
|
||||
QModelIndex index = model.index(row, column, QModelIndex());
|
||||
model.setData(index, QVariant((row + 1) * (column + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
treeView.setWindowTitle(QObject::tr("Flat Tree View"));
|
||||
treeView.show();
|
||||
return app.exec();
|
||||
}
|
49
examples/widgets/itemviews/frozencolumn/CMakeLists.txt
Normal file
49
examples/widgets/itemviews/frozencolumn/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(frozencolumn LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/frozencolumn")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(frozencolumn
|
||||
freezetablewidget.cpp freezetablewidget.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(frozencolumn PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(frozencolumn PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(grades_resource_files
|
||||
"grades.txt"
|
||||
)
|
||||
|
||||
qt_add_resources(frozencolumn "grades"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${grades_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS frozencolumn
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
126
examples/widgets/itemviews/frozencolumn/freezetablewidget.cpp
Normal file
126
examples/widgets/itemviews/frozencolumn/freezetablewidget.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "freezetablewidget.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QHeaderView>
|
||||
|
||||
//! [constructor]
|
||||
FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model)
|
||||
{
|
||||
setModel(model);
|
||||
frozenTableView = new QTableView(this);
|
||||
|
||||
init();
|
||||
|
||||
//connect the headers and scrollbars of both tableviews together
|
||||
connect(horizontalHeader(),&QHeaderView::sectionResized, this,
|
||||
&FreezeTableWidget::updateSectionWidth);
|
||||
connect(verticalHeader(),&QHeaderView::sectionResized, this,
|
||||
&FreezeTableWidget::updateSectionHeight);
|
||||
|
||||
connect(frozenTableView->verticalScrollBar(), &QAbstractSlider::valueChanged,
|
||||
verticalScrollBar(), &QAbstractSlider::setValue);
|
||||
connect(verticalScrollBar(), &QAbstractSlider::valueChanged,
|
||||
frozenTableView->verticalScrollBar(), &QAbstractSlider::setValue);
|
||||
|
||||
|
||||
}
|
||||
//! [constructor]
|
||||
|
||||
FreezeTableWidget::~FreezeTableWidget()
|
||||
{
|
||||
delete frozenTableView;
|
||||
}
|
||||
|
||||
//! [init part1]
|
||||
void FreezeTableWidget::init()
|
||||
{
|
||||
frozenTableView->setModel(model());
|
||||
frozenTableView->setFocusPolicy(Qt::NoFocus);
|
||||
frozenTableView->verticalHeader()->hide();
|
||||
frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
|
||||
viewport()->stackUnder(frozenTableView);
|
||||
//! [init part1]
|
||||
|
||||
//! [init part2]
|
||||
frozenTableView->setStyleSheet("QTableView { border: none;"
|
||||
"background-color: #8EDE21;"
|
||||
"selection-background-color: #999}"); //for demo purposes
|
||||
frozenTableView->setSelectionModel(selectionModel());
|
||||
for (int col = 1; col < model()->columnCount(); ++col)
|
||||
frozenTableView->setColumnHidden(col, true);
|
||||
|
||||
frozenTableView->setColumnWidth(0, columnWidth(0) );
|
||||
|
||||
frozenTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
frozenTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
frozenTableView->show();
|
||||
|
||||
updateFrozenTableGeometry();
|
||||
|
||||
setHorizontalScrollMode(ScrollPerPixel);
|
||||
setVerticalScrollMode(ScrollPerPixel);
|
||||
frozenTableView->setVerticalScrollMode(ScrollPerPixel);
|
||||
}
|
||||
//! [init part2]
|
||||
|
||||
|
||||
//! [sections]
|
||||
void FreezeTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize)
|
||||
{
|
||||
if (logicalIndex == 0){
|
||||
frozenTableView->setColumnWidth(0, newSize);
|
||||
updateFrozenTableGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void FreezeTableWidget::updateSectionHeight(int logicalIndex, int /* oldSize */, int newSize)
|
||||
{
|
||||
frozenTableView->setRowHeight(logicalIndex, newSize);
|
||||
}
|
||||
//! [sections]
|
||||
|
||||
|
||||
//! [resize]
|
||||
void FreezeTableWidget::resizeEvent(QResizeEvent * event)
|
||||
{
|
||||
QTableView::resizeEvent(event);
|
||||
updateFrozenTableGeometry();
|
||||
}
|
||||
//! [resize]
|
||||
|
||||
|
||||
//! [navigate]
|
||||
QModelIndex FreezeTableWidget::moveCursor(CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
QModelIndex current = QTableView::moveCursor(cursorAction, modifiers);
|
||||
|
||||
if (cursorAction == MoveLeft && current.column() > 0
|
||||
&& visualRect(current).topLeft().x() < frozenTableView->columnWidth(0) ){
|
||||
const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x()
|
||||
- frozenTableView->columnWidth(0);
|
||||
horizontalScrollBar()->setValue(newValue);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
//! [navigate]
|
||||
|
||||
void FreezeTableWidget::scrollTo (const QModelIndex & index, ScrollHint hint){
|
||||
if (index.column() > 0)
|
||||
QTableView::scrollTo(index, hint);
|
||||
}
|
||||
|
||||
//! [geometry]
|
||||
void FreezeTableWidget::updateFrozenTableGeometry()
|
||||
{
|
||||
frozenTableView->setGeometry(verticalHeader()->width() + frameWidth(),
|
||||
frameWidth(), columnWidth(0),
|
||||
viewport()->height()+horizontalHeader()->height());
|
||||
}
|
||||
//! [geometry]
|
||||
|
||||
|
35
examples/widgets/itemviews/frozencolumn/freezetablewidget.h
Normal file
35
examples/widgets/itemviews/frozencolumn/freezetablewidget.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef FREEZETABLEWIDGET_H
|
||||
#define FREEZETABLEWIDGET_H
|
||||
|
||||
#include <QTableView>
|
||||
|
||||
//! [Widget definition]
|
||||
class FreezeTableWidget : public QTableView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FreezeTableWidget(QAbstractItemModel * model);
|
||||
~FreezeTableWidget();
|
||||
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override;
|
||||
void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible) override;
|
||||
|
||||
private:
|
||||
QTableView *frozenTableView;
|
||||
void init();
|
||||
void updateFrozenTableGeometry();
|
||||
|
||||
|
||||
private slots:
|
||||
void updateSectionWidth(int logicalIndex, int oldSize, int newSize);
|
||||
void updateSectionHeight(int logicalIndex, int oldSize, int newSize);
|
||||
|
||||
};
|
||||
//! [Widget definition]
|
||||
#endif // FREEZETABLEWIDGET_H
|
11
examples/widgets/itemviews/frozencolumn/frozencolumn.pro
Normal file
11
examples/widgets/itemviews/frozencolumn/frozencolumn.pro
Normal file
@ -0,0 +1,11 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(tableview))
|
||||
|
||||
HEADERS += freezetablewidget.h
|
||||
SOURCES += main.cpp freezetablewidget.cpp
|
||||
RESOURCES += grades.qrc
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/frozencolumn
|
||||
INSTALLS += target
|
||||
|
5
examples/widgets/itemviews/frozencolumn/grades.qrc
Normal file
5
examples/widgets/itemviews/frozencolumn/grades.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>grades.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
36
examples/widgets/itemviews/frozencolumn/grades.txt
Normal file
36
examples/widgets/itemviews/frozencolumn/grades.txt
Normal file
@ -0,0 +1,36 @@
|
||||
France , Norway , YDS , UK(tech.), UK(adj.) , UIAA , Ger , Australia , Finland , Brazil
|
||||
|
||||
1, , 5.2, , , I , I , , , Isup
|
||||
2, , 5.3, , , II , II , 11, , II
|
||||
3, 3, 5.4, , , III , III , 12, , IIsup
|
||||
4, 4, 5.5, 4a , VD , IV , IV , 12, , III
|
||||
5a , 5-, 5.6, , S , V- , V , 13, 5-, IIIsup
|
||||
5b , 5, 5.7, 4b , HS , V , VI , 14, 5, IV
|
||||
, , , 4c , , V+ , , 15, ,
|
||||
5c , 5+, 5.8, , VS , VI- , VIIa , 16, 5, IVsup
|
||||
6a , 6-, 5.9, 5a , HVS , VI , VIIb , 17, , V
|
||||
6a+ , 6-/6 , 5.10a , , E1 , VI+ , VIIc , 18, 6-, VI
|
||||
6b , , 5.10b , 5b , , , , 19, , VI/VI+
|
||||
6b+ , 6, 5.10c , , E2 , VII- , VIIIa , 20, 6, VIsup/VI+
|
||||
6c , 6+, 5.10d , 5c , , VII , VIIIb , 21, , VIsup
|
||||
6c+ , 7-, 5.11a , , E3 , VII+ , VIIIc , 22, 6, 7a
|
||||
6c+ , 7, 5.11b , , , , , 23, , 7b
|
||||
7a , 7+, 5.11c , 6a , E4 , VIII- , IXa , 24, 7-, 7c
|
||||
7a , 7+/8- , 5.11d , , , VIII , IXb , , , 7c
|
||||
7a+ , 8-, 5.12a , , E5 , VIII+ , IXc , 25, 7, 8a
|
||||
7b , 8, 5.12b , 6b , , , , 26, 8-, 8b
|
||||
7b+ , 8/8+ , 5.12c , , E6 , IX- , Xa , 27, 8, 8c
|
||||
7c , 8+, 5.12d , 6c , , IX , Xb , 28, 8, 9a
|
||||
7c+ , 9-, 5.13a , , E7 , IX+ , Xc , 29, 9-, 9b
|
||||
8a , , 5.13b , , , , , , 9, 9c
|
||||
8a+ , 9-/9 , 5.13c , 7a , , X- , , 30, 9, 10a
|
||||
8b , 9, 5.13d , , E8 , X , , 31, 10-, 10b
|
||||
8b+ , 9/9+ , 5.14a , , , X+ , , 32, 10, 10c
|
||||
8c , 9+, 5.14b , 7b , , , , 33, 10, 11a
|
||||
8c+ , 10-, 5.14c , , E9 , XI- , , 34, 11-, 11b
|
||||
9a , 10, 5.14d , 7c , , XI , , 35, 11, 11c
|
||||
9a+ , , 5.15a , , , XI+ , , , , 12a
|
||||
9b , , 5.15b , , , , , , , 12b
|
||||
|
||||
# Wikipedia contributors. Grade (climbing). Wikipedia, The Free Encyclopedia. May 15, 2009, 20:42 UTC.
|
||||
# Available at: http://en.wikipedia.org/w/index.php?title=Grade_(climbing)&oldid=290165724. Accessed May 28, 2009.
|
49
examples/widgets/itemviews/frozencolumn/main.cpp
Normal file
49
examples/widgets/itemviews/frozencolumn/main.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStandardItemModel>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "freezetablewidget.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(grades);
|
||||
|
||||
QApplication app( argc, argv );
|
||||
QStandardItemModel *model=new QStandardItemModel();
|
||||
|
||||
QFile file(":/grades.txt");
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
|
||||
QString line = stream.readLine();
|
||||
QStringList list = line.simplified().split(',');
|
||||
model->setHorizontalHeaderLabels(list);
|
||||
|
||||
int row = 0;
|
||||
QStandardItem *newItem = nullptr;
|
||||
while (!stream.atEnd()) {
|
||||
line = stream.readLine();
|
||||
if (!line.startsWith('#') && line.contains(',')) {
|
||||
list = line.simplified().split(',');
|
||||
for (int col = 0; col < list.length(); ++col){
|
||||
newItem = new QStandardItem(list.at(col));
|
||||
model->setItem(row, col, newItem);
|
||||
}
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
FreezeTableWidget *tableView = new FreezeTableWidget(model);
|
||||
|
||||
tableView->setWindowTitle(QObject::tr("Frozen Column Example"));
|
||||
tableView->resize(560, 680);
|
||||
tableView->show();
|
||||
return app.exec();
|
||||
}
|
||||
|
51
examples/widgets/itemviews/interview/CMakeLists.txt
Normal file
51
examples/widgets/itemviews/interview/CMakeLists.txt
Normal 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}"
|
||||
)
|
2
examples/widgets/itemviews/interview/README
Normal file
2
examples/widgets/itemviews/interview/README
Normal file
@ -0,0 +1,2 @@
|
||||
The interview example shows the same model and selection being shared
|
||||
between three different views.
|
BIN
examples/widgets/itemviews/interview/images/folder.png
Normal file
BIN
examples/widgets/itemviews/interview/images/folder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
examples/widgets/itemviews/interview/images/interview.png
Normal file
BIN
examples/widgets/itemviews/interview/images/interview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
examples/widgets/itemviews/interview/images/services.png
Normal file
BIN
examples/widgets/itemviews/interview/images/services.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
16
examples/widgets/itemviews/interview/interview.pro
Normal file
16
examples/widgets/itemviews/interview/interview.pro
Normal 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
|
7
examples/widgets/itemviews/interview/interview.qrc
Normal file
7
examples/widgets/itemviews/interview/interview.qrc
Normal 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>
|
57
examples/widgets/itemviews/interview/main.cpp
Normal file
57
examples/widgets/itemviews/interview/main.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// 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[])
|
||||
{
|
||||
Q_INIT_RESOURCE(interview);
|
||||
|
||||
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();
|
||||
}
|
110
examples/widgets/itemviews/interview/model.cpp
Normal file
110
examples/widgets/itemviews/interview/model.cpp
Normal 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;
|
||||
}
|
53
examples/widgets/itemviews/interview/model.h
Normal file
53
examples/widgets/itemviews/interview/model.h
Normal 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
|
24
examples/widgets/itemviews/itemviews.pro
Normal file
24
examples/widgets/itemviews/itemviews.pro
Normal file
@ -0,0 +1,24 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = addressbook \
|
||||
basicsortfiltermodel \
|
||||
chart \
|
||||
coloreditorfactory \
|
||||
combowidgetmapper \
|
||||
customsortfiltermodel \
|
||||
dirview \
|
||||
editabletreemodel \
|
||||
fetchmore \
|
||||
flattreeview \
|
||||
frozencolumn \
|
||||
interview \
|
||||
pixelator \
|
||||
puzzle \
|
||||
simpledommodel \
|
||||
simpletreemodel \
|
||||
simplewidgetmapper \
|
||||
spinboxdelegate \
|
||||
spreadsheet \
|
||||
stardelegate \
|
||||
storageview
|
||||
!qtConfig(draganddrop): SUBDIRS -= puzzle
|
||||
!qtHaveModule(xml): SUBDIRS -= simpledommodel
|
58
examples/widgets/itemviews/pixelator/CMakeLists.txt
Normal file
58
examples/widgets/itemviews/pixelator/CMakeLists.txt
Normal 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}"
|
||||
)
|
53
examples/widgets/itemviews/pixelator/imagemodel.cpp
Normal file
53
examples/widgets/itemviews/pixelator/imagemodel.cpp
Normal 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]
|
31
examples/widgets/itemviews/pixelator/imagemodel.h
Normal file
31
examples/widgets/itemviews/pixelator/imagemodel.h
Normal 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
|
5
examples/widgets/itemviews/pixelator/images.qrc
Normal file
5
examples/widgets/itemviews/pixelator/images.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>images/qt.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
examples/widgets/itemviews/pixelator/images/qt.png
Normal file
BIN
examples/widgets/itemviews/pixelator/images/qt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user