File indexing completed on 2025-02-09 04:25:22
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2007-2008 Rafael Fernández López <ereslibre@kde.org> 0004 SPDX-FileCopyrightText: 2008 Kevin Ottens <ervin@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include <QAbstractItemView> 0010 #include <QApplication> 0011 #include <QDebug> 0012 #include <QLineEdit> 0013 #include <QListView> 0014 #include <QMainWindow> 0015 #include <QMenu> 0016 #include <QMessageBox> 0017 #include <QPaintEvent> 0018 #include <QPainter> 0019 #include <QPushButton> 0020 #include <QRadialGradient> 0021 #include <QStringListModel> 0022 #include <QToolButton> 0023 0024 #include <kwidgetitemdelegate.h> 0025 0026 #define HARDCODED_BORDER 10 0027 #define EQUALLY_SIZED_TOOLBUTTONS 1 0028 0029 #if EQUALLY_SIZED_TOOLBUTTONS 0030 #include <QStyleOptionToolButton> 0031 #endif 0032 0033 class TestWidget : public QWidget 0034 { 0035 Q_OBJECT 0036 0037 public: 0038 TestWidget(QWidget *parent = nullptr) 0039 : QWidget(parent) 0040 { 0041 setMouseTracking(true); 0042 setAttribute(Qt::WA_Hover); 0043 } 0044 0045 ~TestWidget() override 0046 { 0047 } 0048 0049 QSize sizeHint() const override 0050 { 0051 return QSize(30, 30); 0052 } 0053 0054 protected: 0055 void paintEvent(QPaintEvent *event) override 0056 { 0057 QPainter p(this); 0058 0059 QRadialGradient radialGrad(QPointF(event->rect().width() / 2, event->rect().height() / 2), qMin(event->rect().width() / 2, event->rect().height() / 2)); 0060 0061 if (underMouse()) { 0062 radialGrad.setColorAt(0, Qt::green); 0063 } else { 0064 radialGrad.setColorAt(0, Qt::red); 0065 } 0066 0067 radialGrad.setColorAt(1, Qt::transparent); 0068 0069 p.fillRect(event->rect(), radialGrad); 0070 0071 p.setPen(Qt::black); 0072 p.drawLine(0, 15, 30, 15); 0073 p.drawLine(15, 0, 15, 30); 0074 0075 p.end(); 0076 } 0077 0078 bool event(QEvent *event) override 0079 { 0080 if (event->type() == QEvent::MouseButtonPress) { 0081 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); 0082 0083 if (mouseEvent->pos().x() > 15 // 0084 && mouseEvent->pos().y() < 15) { 0085 qDebug() << "First quarter"; 0086 } else if (mouseEvent->pos().x() < 15 // 0087 && mouseEvent->pos().y() < 15) { 0088 qDebug() << "Second quarter"; 0089 } else if (mouseEvent->pos().x() < 15 // 0090 && mouseEvent->pos().y() > 15) { 0091 qDebug() << "Third quarter"; 0092 } else { 0093 qDebug() << "Forth quarter"; 0094 } 0095 } 0096 0097 return QWidget::event(event); 0098 } 0099 }; 0100 0101 class MyDelegate : public KWidgetItemDelegate 0102 { 0103 Q_OBJECT 0104 0105 public: 0106 MyDelegate(QAbstractItemView *itemView, QObject *parent = nullptr) 0107 : KWidgetItemDelegate(itemView, parent) 0108 { 0109 for (int i = 0; i < 100; i++) { 0110 installed[i] = i % 5; 0111 } 0112 } 0113 0114 ~MyDelegate() override 0115 { 0116 } 0117 0118 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override 0119 { 0120 Q_UNUSED(option); 0121 Q_UNUSED(index); 0122 0123 return sizeHint(); 0124 } 0125 0126 QSize sizeHint() const 0127 { 0128 return QSize(600, 60); 0129 } 0130 0131 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override 0132 { 0133 Q_UNUSED(index); 0134 painter->save(); 0135 0136 itemView()->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr); 0137 0138 if (option.state & QStyle::State_Selected) { 0139 painter->setPen(option.palette.highlightedText().color()); 0140 } 0141 0142 painter->restore(); 0143 } 0144 0145 QList<QWidget *> createItemWidgets(const QModelIndex &index) const override 0146 { 0147 Q_UNUSED(index); 0148 QPushButton *button = new QPushButton(); 0149 QToolButton *toolButton = new QToolButton(); 0150 0151 setBlockedEventTypes(button, QList<QEvent::Type>() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick); 0152 0153 setBlockedEventTypes(toolButton, QList<QEvent::Type>() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick); 0154 0155 connect(button, SIGNAL(clicked(bool)), this, SLOT(mySlot())); 0156 connect(toolButton, SIGNAL(triggered(QAction *)), this, SLOT(mySlot2())); 0157 connect(toolButton, SIGNAL(clicked(bool)), this, SLOT(mySlot3())); 0158 0159 return QList<QWidget *>() << button << new TestWidget() << new QLineEdit() << toolButton; 0160 } 0161 0162 void updateItemWidgets(const QList<QWidget *> &widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const override 0163 { 0164 QPushButton *button = static_cast<QPushButton *>(widgets[0]); 0165 button->setText(QStringLiteral("Test me")); 0166 button->setIcon(QIcon::fromTheme(QStringLiteral("kde"))); 0167 button->resize(button->sizeHint()); 0168 button->move(HARDCODED_BORDER, sizeHint().height() / 2 - button->height() / 2); 0169 0170 TestWidget *testWidget = static_cast<TestWidget *>(widgets[1]); 0171 0172 testWidget->resize(testWidget->sizeHint()); 0173 testWidget->move(2 * HARDCODED_BORDER + button->sizeHint().width(), // 0174 sizeHint().height() / 2 - testWidget->size().height() / 2); 0175 0176 // Hide the test widget when row can be divided by three 0177 testWidget->setVisible((index.row() % 3) != 0); 0178 0179 QLineEdit *lineEdit = static_cast<QLineEdit *>(widgets[2]); 0180 0181 lineEdit->setClearButtonEnabled(true); 0182 lineEdit->resize(lineEdit->sizeHint()); 0183 lineEdit->move(3 * HARDCODED_BORDER + button->sizeHint().width() + testWidget->sizeHint().width(), 0184 sizeHint().height() / 2 - lineEdit->size().height() / 2); 0185 0186 QToolButton *toolButton = static_cast<QToolButton *>(widgets[3]); 0187 0188 if (!toolButton->menu()) { 0189 QMenu *myMenu = new QMenu(toolButton); 0190 myMenu->addAction(QStringLiteral("Save")); 0191 myMenu->addAction(QStringLiteral("Load")); 0192 myMenu->addSeparator(); 0193 myMenu->addAction(QStringLiteral("Close")); 0194 toolButton->setMenu(myMenu); 0195 } 0196 0197 toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0198 toolButton->setPopupMode(QToolButton::MenuButtonPopup); 0199 0200 if (installed[index.row()]) { 0201 toolButton->setText(QStringLiteral("Uninstall")); 0202 } else { 0203 toolButton->setText(QStringLiteral("Install")); 0204 } 0205 0206 toolButton->resize(toolButton->sizeHint()); 0207 #if EQUALLY_SIZED_TOOLBUTTONS 0208 QStyleOptionToolButton toolButtonOpt; 0209 toolButtonOpt.initFrom(toolButton); 0210 toolButtonOpt.features = QStyleOptionToolButton::MenuButtonPopup; 0211 toolButtonOpt.arrowType = Qt::DownArrow; 0212 toolButtonOpt.toolButtonStyle = Qt::ToolButtonTextBesideIcon; 0213 0214 toolButtonOpt.text = "Install"; 0215 int widthInstall = QApplication::style() 0216 ->sizeFromContents(QStyle::CT_ToolButton, 0217 &toolButtonOpt, 0218 QSize(option.fontMetrics.boundingRect(QStringLiteral("Install")).width() + HARDCODED_BORDER * 3, 0219 option.fontMetrics.height()), 0220 toolButton) 0221 .width(); 0222 toolButtonOpt.text = "Uninstall"; 0223 int widthUninstall = QApplication::style() 0224 ->sizeFromContents(QStyle::CT_ToolButton, 0225 &toolButtonOpt, 0226 QSize(option.fontMetrics.boundingRect(QStringLiteral("Uninstall")).width() + HARDCODED_BORDER * 3, 0227 option.fontMetrics.height()), 0228 toolButton) 0229 .width(); 0230 0231 QSize size = toolButton->sizeHint(); 0232 size.setWidth(qMax(widthInstall, widthUninstall)); 0233 toolButton->resize(size); 0234 #endif 0235 toolButton->move(option.rect.width() - toolButton->size().width() - HARDCODED_BORDER, // 0236 sizeHint().height() / 2 - toolButton->size().height() / 2); 0237 0238 // Eat more space 0239 lineEdit->resize(option.rect.width() - toolButton->width() - testWidget->width() - button->width() - 5 * HARDCODED_BORDER, lineEdit->height()); 0240 } 0241 0242 private Q_SLOTS: 0243 void mySlot() 0244 { 0245 QMessageBox::information(nullptr, QStringLiteral("Button clicked"), QStringLiteral("The button in row %1 was clicked").arg(focusedIndex().row())); 0246 } 0247 0248 void mySlot2() 0249 { 0250 QMessageBox::information(nullptr, 0251 QStringLiteral("Toolbutton menu item clicked"), 0252 QStringLiteral("A menu item was triggered in row %1").arg(focusedIndex().row())); 0253 } 0254 0255 void mySlot3() 0256 { 0257 bool isInstalled = installed[focusedIndex().row()]; 0258 installed[focusedIndex().row()] = !isInstalled; 0259 const_cast<QAbstractItemModel *>(focusedIndex().model())->setData(focusedIndex(), QStringLiteral("makemodelbeupdated")); 0260 } 0261 0262 private: 0263 bool installed[100]; 0264 }; 0265 0266 int main(int argc, char **argv) 0267 { 0268 QApplication app(argc, argv); 0269 0270 QMainWindow *mainWindow = new QMainWindow(); 0271 mainWindow->setMinimumSize(640, 480); 0272 QListView *listView = new QListView(); 0273 QStringListModel *model = new QStringListModel(); 0274 0275 model->insertRows(0, 100); 0276 for (int i = 0; i < 100; ++i) { 0277 model->setData(model->index(i, 0), QString("Test " + QString::number(i)), Qt::DisplayRole); 0278 } 0279 0280 listView->setModel(model); 0281 MyDelegate *myDelegate = new MyDelegate(listView); 0282 listView->setItemDelegate(myDelegate); 0283 listView->setVerticalScrollMode(QListView::ScrollPerPixel); 0284 0285 mainWindow->setCentralWidget(listView); 0286 0287 mainWindow->show(); 0288 0289 model->removeRows(0, 95); 0290 0291 return app.exec(); 0292 } 0293 0294 #include "kwidgetitemdelegatetest.moc"