File indexing completed on 2024-04-28 17:06:04
0001 /* 0002 SPDX-FileCopyrightText: 2008 Csaba Karai <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2008-2022 Krusader Krew <https://krusader.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "krtreewidget.h" 0009 #include "../compat.h" 0010 #include "krstyleproxy.h" 0011 0012 // QtGui 0013 #include <QContextMenuEvent> 0014 // QtWidgets 0015 #include <QApplication> 0016 #include <QHeaderView> 0017 #include <QStyleOptionViewItem> 0018 #include <QToolTip> 0019 0020 KrTreeWidget::KrTreeWidget(QWidget *parent) 0021 : QTreeWidget(parent) 0022 , _inResize(false) 0023 { 0024 setRootIsDecorated(false); 0025 setSortingEnabled(true); 0026 setAllColumnsShowFocus(true); 0027 0028 _stretchingColumn = -1; 0029 0030 auto *krstyle = new KrStyleProxy(); 0031 krstyle->setParent(this); 0032 setStyle(krstyle); 0033 } 0034 0035 bool KrTreeWidget::event(QEvent *event) 0036 { 0037 switch (event->type()) { 0038 // HACK: QT 4 Context menu key isn't handled properly 0039 case QEvent::ContextMenu: { 0040 auto *ce = dynamic_cast<QContextMenuEvent *>(event); 0041 0042 if (ce->reason() == QContextMenuEvent::Mouse) { 0043 QPoint pos = viewport()->mapFromGlobal(ce->globalPos()); 0044 0045 QTreeWidgetItem *item = itemAt(pos); 0046 int column = columnAt(pos.x()); 0047 0048 emit itemRightClicked(item, ce->globalPos(), column); 0049 return true; 0050 } else { 0051 if (currentItem()) { 0052 QRect r = visualItemRect(currentItem()); 0053 QPoint p = viewport()->mapToGlobal(QPoint(r.x() + 5, r.y() + 5)); 0054 0055 emit itemRightClicked(currentItem(), p, currentColumn()); 0056 return true; 0057 } 0058 } 0059 } break; 0060 case QEvent::KeyPress: { 0061 // HACK: QT 4 Ctrl+A bug fix: Ctrl+A doesn't work if QTreeWidget contains parent / child items 0062 // Insert doesn't change the selections for multi selection modes 0063 auto *ke = dynamic_cast<QKeyEvent *>(event); 0064 switch (ke->key()) { 0065 case Qt::Key_Insert: { 0066 if (ke->modifiers() != 0) 0067 break; 0068 0069 QAbstractItemView::SelectionMode mode = selectionMode(); 0070 0071 if (mode != QAbstractItemView::ContiguousSelection && mode != QAbstractItemView::ExtendedSelection && mode != QAbstractItemView::MultiSelection) 0072 break; 0073 0074 ke->accept(); 0075 0076 if (currentItem() == nullptr) 0077 return true; 0078 0079 currentItem()->setSelected(!currentItem()->isSelected()); 0080 return true; 0081 } 0082 case Qt::Key_A: 0083 if (ke->modifiers() == Qt::ControlModifier) { 0084 QAbstractItemView::SelectionMode mode = selectionMode(); 0085 0086 if (mode == QAbstractItemView::ContiguousSelection || mode == QAbstractItemView::ExtendedSelection 0087 || mode == QAbstractItemView::MultiSelection) { 0088 selectAll(); 0089 ke->accept(); 0090 return true; 0091 } 0092 } 0093 break; 0094 default: 0095 break; 0096 } 0097 } break; 0098 case QEvent::Resize: { 0099 auto *re = dynamic_cast<QResizeEvent *>(event); 0100 if (!_inResize && re->oldSize() != re->size()) { 0101 if (_stretchingColumn != -1 && columnCount()) { 0102 QList<int> columnsSizes; 0103 int oldSize = 0; 0104 0105 for (int i = 0; i != header()->count(); i++) { 0106 columnsSizes.append(header()->sectionSize(i)); 0107 oldSize += header()->sectionSize(i); 0108 } 0109 0110 bool res = QTreeWidget::event(event); 0111 0112 int newSize = viewport()->width(); 0113 int delta = newSize - oldSize; 0114 0115 if (delta) { 0116 _inResize = true; 0117 0118 for (int i = 0; i != header()->count(); i++) { 0119 if (i == _stretchingColumn) { 0120 int newNs = columnsSizes[i] + delta; 0121 if (newNs < 8) 0122 newNs = 8; 0123 header()->resizeSection(i, newNs); 0124 } else if (header()->sectionSize(i) != columnsSizes[i]) { 0125 header()->resizeSection(i, columnsSizes[i]); 0126 } 0127 } 0128 _inResize = false; 0129 } 0130 return res; 0131 } 0132 } 0133 break; 0134 } 0135 case QEvent::ToolTip: { 0136 auto *he = dynamic_cast<QHelpEvent *>(event); 0137 0138 if (viewport()) { 0139 QPoint pos = viewport()->mapFromGlobal(he->globalPos()); 0140 0141 QTreeWidgetItem *item = itemAt(pos); 0142 0143 int column = columnAt(pos.x()); 0144 0145 if (item) { 0146 if (!item->toolTip(column).isEmpty()) 0147 break; 0148 0149 QString tip = item->text(column); 0150 0151 int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; 0152 int requiredWidth = QFontMetrics(font()).horizontalAdvance(tip) + 2 * textMargin; 0153 0154 if (column == 0 && indentation()) { 0155 int level = 0; 0156 0157 QTreeWidgetItem *parent = item; 0158 0159 while ((parent = parent->parent())) 0160 level++; 0161 0162 if (rootIsDecorated()) 0163 level++; 0164 0165 requiredWidth += level * indentation(); 0166 } 0167 0168 QIcon icon = item->icon(column); 0169 if (!icon.isNull()) { 0170 QStyleOptionViewItem opts = viewOptions(); 0171 QSize iconSize = icon.actualSize(opts.decorationSize); 0172 requiredWidth += iconSize.width(); 0173 0174 int pixmapMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, this) + 1; 0175 requiredWidth += 2 * pixmapMargin; 0176 } 0177 0178 if (!tip.isEmpty() && (columnWidth(column) < requiredWidth)) 0179 QToolTip::showText(he->globalPos(), tip, this); 0180 return true; 0181 } 0182 } 0183 } break; 0184 default: 0185 break; 0186 } 0187 return QTreeWidget::event(event); 0188 }