File indexing completed on 2024-12-22 04:13:08
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_categorized_list_view.h" 0008 #include "kis_categorized_list_model.h" 0009 #include <QMouseEvent> 0010 #include <QMenu> 0011 #include <QAction> 0012 #include <QShowEvent> 0013 #include <kconfig.h> 0014 #include <klocalizedstring.h> 0015 #include <kis_icon.h> 0016 #include "kis_debug.h" 0017 #include <KisKineticScroller.h> 0018 0019 KisCategorizedListView::KisCategorizedListView(QWidget* parent): 0020 QListView(parent) 0021 { 0022 connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(slotIndexChanged(QModelIndex))); 0023 0024 // Because this widget has a darker background, the checkbox borders get hidden with default palette 0025 // This palette update makes the checkboxes easier to see by starting with the text color 0026 QPalette newPall = palette(); 0027 newPall.setColor(QPalette::Active, QPalette::Window, palette().text().color() ); 0028 setPalette(newPall); 0029 0030 { 0031 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); 0032 if (scroller) { 0033 connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); 0034 } 0035 } 0036 } 0037 0038 KisCategorizedListView::~KisCategorizedListView() 0039 { 0040 } 0041 0042 void KisCategorizedListView::setModel(QAbstractItemModel* model) 0043 { 0044 QListView::setModel(model); 0045 updateRows(0, model->rowCount()); 0046 model->sort(0); 0047 } 0048 0049 QSize KisCategorizedListView::sizeHint() const 0050 { 0051 const QSize sh = QListView::sizeHint(); 0052 const int width = sizeHintForColumn(0); 0053 0054 return QSize(width, sh.height()); 0055 } 0056 0057 void KisCategorizedListView::setCompositeBoxControl(bool value) 0058 { 0059 isCompositeBoxControl = value; 0060 } 0061 0062 void KisCategorizedListView::updateRows(int begin, int end) 0063 { 0064 for(; begin!=end; ++begin) { 0065 QModelIndex index = model()->index(begin, 0); 0066 bool isHeader = model()->data(index, __CategorizedListModelBase::IsHeaderRole).toBool(); 0067 bool expanded = model()->data(index, __CategorizedListModelBase::ExpandCategoryRole).toBool(); 0068 setRowHidden(begin, !expanded && !isHeader); 0069 } 0070 } 0071 0072 void KisCategorizedListView::slotIndexChanged(const QModelIndex& index) 0073 { 0074 if(model()->data(index, __CategorizedListModelBase::IsHeaderRole).toBool()) { 0075 bool expanded = model()->data(index, __CategorizedListModelBase::ExpandCategoryRole).toBool(); 0076 model()->setData(index, !expanded, __CategorizedListModelBase::ExpandCategoryRole); 0077 emit sigCategoryToggled(index, !expanded); 0078 } 0079 } 0080 0081 void KisCategorizedListView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int> &roles) 0082 { 0083 QListView::dataChanged(topLeft, bottomRight); 0084 updateRows(topLeft.row(), bottomRight.row()+1); 0085 0086 // check to see if the data changed was a check box 0087 // if it is a checkbox tell the brush editor that the preset is now "dirty" 0088 int i = 0; 0089 for (QVector<int>::const_iterator iterator = roles.begin(); iterator != roles.end(); ++iterator) { 0090 0091 if (Qt::CheckStateRole == roles.at(i) ) { 0092 int row = topLeft.row(); 0093 int column = topLeft.column(); 0094 0095 emit sigEntryChecked(model()->index(row, column)); 0096 } else if (__CategorizedListModelBase::ExpandCategoryRole == roles.at(i)) { 0097 // logic to target the expand/contract menus if needed 0098 } 0099 0100 i++; 0101 } 0102 } 0103 0104 void KisCategorizedListView::rowsInserted(const QModelIndex& parent, int start, int end) 0105 { 0106 QListView::rowsInserted(parent, start, end); 0107 updateRows(0, model()->rowCount()); 0108 model()->sort(0); 0109 } 0110 0111 void KisCategorizedListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0112 { 0113 QListView::rowsAboutToBeRemoved(parent, start, end); 0114 model()->sort(0); 0115 } 0116 0117 void KisCategorizedListView::mousePressEvent(QMouseEvent* event) 0118 { 0119 QListView::mousePressEvent(event); 0120 0121 QModelIndex index = QListView::indexAt(event->pos()); 0122 0123 0124 // hack: the custom compositeop combo box has issues with events being sent 0125 // those widgets will run this extra code to help them know if a checkbox is clicked 0126 if (isCompositeBoxControl) { 0127 0128 if (index.isValid() && (event->pos().x() < 25) && (model()->flags(index) & Qt::ItemIsUserCheckable)) { 0129 QListView::mousePressEvent(event); 0130 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, 0131 event->pos(), 0132 event->globalPos(), 0133 event->button(), 0134 event->button() | event->buttons(), 0135 event->modifiers()); 0136 0137 QListView::mouseReleaseEvent(&releaseEvent); 0138 emit sigEntryChecked(index); 0139 0140 return; // don't worry about running the 'right' click logic below. that is not relevant with composite ops 0141 } 0142 } 0143 0144 0145 0146 if (event->button() == Qt::RightButton){ 0147 0148 QMenu menu(this); 0149 0150 if(index.data(__CategorizedListModelBase::isLockableRole).toBool() && index.isValid()) { 0151 0152 bool locked = index.data(__CategorizedListModelBase::isLockedRole).toBool(); 0153 0154 QIcon icon = locked ? KisIconUtils::loadIcon("unlocked") : KisIconUtils::loadIcon("locked"); 0155 0156 // Add an empty section so there's a bit more space before users accidentally press lock 0157 // See https://bugs.kde.org/show_bug.cgi?id=447367 0158 menu.addSection(" "); 0159 0160 QAction* action1 = menu.addAction(icon, locked ? i18n("Unlock (restore settings from preset)") 0161 : i18n("Lock")); 0162 0163 connect(action1, SIGNAL(triggered()), this, SIGNAL(rightClickedMenuDropSettingsTriggered())); 0164 0165 if (locked){ 0166 QAction* action2 = menu.addAction(icon, i18n("Unlock (keep current settings)")); 0167 connect(action2, SIGNAL(triggered()), this, SIGNAL(rightClickedMenuSaveSettingsTriggered())); 0168 } 0169 menu.exec(event->globalPos()); 0170 } 0171 } 0172 } 0173 0174 void KisCategorizedListView::mouseReleaseEvent(QMouseEvent* event) 0175 { 0176 QListView::mouseReleaseEvent(event); 0177 } 0178 0179 void KisCategorizedListView::slotScrollerStateChange(QScroller::State state) 0180 { 0181 KisKineticScroller::updateCursor(this, state); 0182 } 0183 0184 0185