File indexing completed on 2024-05-12 16:36:48
0001 /* This file is part of the KDE project 0002 * 0003 * Copyright (C) 2011 Paul Mendez <paulestebanms@gmail.com> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KPrSlidesManagerView.h" 0022 0023 //Qt headers 0024 #include <qmath.h> 0025 #include <QPaintEvent> 0026 #include <QScrollBar> 0027 #include <QPainter> 0028 #include <QPen> 0029 #include <QDrag> 0030 0031 //KF5 headers 0032 #include <klocalizedstring.h> 0033 #include <kiconloader.h> 0034 0035 KPrSlidesManagerView::KPrSlidesManagerView(QWidget *parent) 0036 : QListView(parent) 0037 , m_draggingFlag(false) 0038 , margin(23) 0039 { 0040 setViewMode(QListView::IconMode); 0041 setFlow(QListView::LeftToRight); 0042 setWrapping(true); 0043 setResizeMode(QListView::Adjust); 0044 setDragEnabled(true); 0045 setAcceptDrops(true); 0046 setDropIndicatorShown(true); 0047 setSpacing(m_itemSize.width()/10); 0048 viewport()->installEventFilter(this); 0049 } 0050 0051 KPrSlidesManagerView::~KPrSlidesManagerView() 0052 { 0053 } 0054 0055 void KPrSlidesManagerView::paintEvent(QPaintEvent *event) 0056 { 0057 event->accept(); 0058 QListView::paintEvent(event); 0059 0060 // Paint the line where the slide should go 0061 if (isDragging()) { 0062 QSize size(itemSize().width() + spacing(), itemSize().height() + spacing()); 0063 QPair <int, int> m_pair = cursorRowAndColumn(); 0064 int numberColumn = m_pair.first; 0065 int numberRow = m_pair.second; 0066 int scrollBarValue = verticalScrollBar()->value(); 0067 0068 QPoint point1(numberColumn * size.width() + spacing() / 2, numberRow * size.height() + spacing() - scrollBarValue); 0069 QPoint point2(numberColumn * size.width() + spacing() / 2, (numberRow + 1) * size.height() - scrollBarValue); 0070 QLineF line(point1, point2); 0071 0072 QPainter painter(this->viewport()); 0073 QPen pen = QPen(palette().brush(QPalette::Highlight), spacing() / 4); 0074 pen.setCapStyle(Qt::RoundCap); 0075 painter.setPen(pen); 0076 painter.setOpacity(0.8); 0077 painter.drawLine(line); 0078 } 0079 } 0080 0081 void KPrSlidesManagerView::contextMenuEvent(QContextMenuEvent *event) 0082 { 0083 emit requestContextMenu(event); 0084 } 0085 0086 void KPrSlidesManagerView::mouseDoubleClickEvent(QMouseEvent *event) 0087 { 0088 event->accept(); 0089 // do not call QListView::mouseDoubleClickEvent(event); here as this triggers a rename command to be added 0090 emit slideDblClick(); 0091 } 0092 0093 void KPrSlidesManagerView::startDrag(Qt::DropActions supportedActions) 0094 { 0095 const QModelIndexList indexes = selectionModel()->selectedIndexes(); 0096 if (!indexes.isEmpty()) { 0097 QMimeData *data = model()->mimeData(indexes); 0098 if (!data) { 0099 return; 0100 } 0101 0102 QDrag *drag = new QDrag(this); 0103 drag->setPixmap(createDragPixmap()); 0104 drag->setMimeData(data); 0105 0106 //m_dragSource = this; 0107 drag->exec(supportedActions, Qt::CopyAction); 0108 } 0109 } 0110 0111 void KPrSlidesManagerView::dropEvent(QDropEvent *ev) 0112 { 0113 setDraggingFlag(false); 0114 ev->setDropAction(Qt::IgnoreAction); 0115 ev->accept(); 0116 0117 clearSelection(); 0118 0119 if (!model()) { 0120 return; 0121 } 0122 0123 int newIndex = cursorSlideIndex(); 0124 0125 if (newIndex >= model()->rowCount(QModelIndex())) { 0126 newIndex = -1; 0127 } 0128 0129 model()->dropMimeData(ev->mimeData(), Qt::MoveAction, newIndex, -1, QModelIndex()); 0130 } 0131 0132 void KPrSlidesManagerView::dragMoveEvent(QDragMoveEvent *ev) 0133 { 0134 ev->accept(); 0135 if (!model()) { 0136 return; 0137 } 0138 QListView::dragMoveEvent(ev); 0139 setDraggingFlag(); 0140 viewport()->update(); 0141 } 0142 0143 void KPrSlidesManagerView::dragEnterEvent(QDragEnterEvent *event) 0144 { 0145 event->setDropAction(Qt::MoveAction); 0146 event->accept(); 0147 } 0148 0149 void KPrSlidesManagerView::dragLeaveEvent(QDragLeaveEvent *e) 0150 { 0151 Q_UNUSED(e); 0152 setDraggingFlag(false); 0153 } 0154 0155 void KPrSlidesManagerView::focusOutEvent(QFocusEvent *event) 0156 { 0157 Q_UNUSED(event); 0158 emit focusLost(); 0159 } 0160 0161 void KPrSlidesManagerView::focusInEvent(QFocusEvent *event) 0162 { 0163 Q_UNUSED(event); 0164 emit focusGot(); 0165 } 0166 0167 void KPrSlidesManagerView::wheelEvent(QWheelEvent *event) 0168 { 0169 if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) { 0170 if (event->delta() > 0) { 0171 emit zoomIn(); 0172 } 0173 else { 0174 emit zoomOut(); 0175 } 0176 } 0177 else { 0178 QListView::wheelEvent(event); 0179 } 0180 } 0181 0182 void KPrSlidesManagerView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 0183 { 0184 if (!this->selectionModel()->selection().isEmpty()) { 0185 emit itemSelected(); 0186 } 0187 else { 0188 emit selectionCleared(); 0189 } 0190 QListView::selectionChanged(selected, deselected); 0191 } 0192 0193 QRect KPrSlidesManagerView::itemSize() const 0194 { 0195 if (model()) { 0196 return (this->visualRect(model()->index(0,0,QModelIndex()))); 0197 } 0198 else { 0199 return QRect(); 0200 } 0201 } 0202 0203 void KPrSlidesManagerView::setDraggingFlag(bool flag) 0204 { 0205 m_draggingFlag = flag; 0206 } 0207 0208 bool KPrSlidesManagerView::isDragging() const 0209 { 0210 return m_draggingFlag; 0211 } 0212 0213 bool KPrSlidesManagerView::eventFilter(QObject *watched, QEvent *event) 0214 { 0215 if (watched == viewport() && model()) { 0216 switch (event->type()) { 0217 case QEvent::MouseButtonPress: { 0218 QModelIndex item = indexAt(QWidget::mapFromGlobal(QCursor::pos())); 0219 QMouseEvent *mouseEv = static_cast<QMouseEvent *>(event); 0220 0221 //Left button is used to deselect, but right button needs a selected item for 0222 //context menu actions 0223 if ((item.row() < 0) && (mouseEv->button() != Qt::LeftButton)) { 0224 // Selects the last item of the row 0225 QModelIndex last_index = model()->index(qMin(cursorSlideIndex(), model()->rowCount(QModelIndex()) - 1), 0226 0, QModelIndex()); 0227 setCurrentIndex(last_index); 0228 emit indexChanged(last_index); 0229 } 0230 break; 0231 } 0232 default: 0233 break; 0234 } 0235 } 0236 return QObject::eventFilter(watched, event); 0237 } 0238 0239 QPixmap KPrSlidesManagerView::createDragPixmap() const 0240 { 0241 const QModelIndexList selectedIndexes = selectionModel()->selectedIndexes(); 0242 Q_ASSERT(!selectedIndexes.isEmpty()); 0243 0244 const int itemCount = selectedIndexes.count(); 0245 0246 // If more than one item is dragged, align the items inside a 0247 // rectangular grid. The maximum grid size is limited to 4 x 4 items. 0248 int xCount = 2; 0249 int size = (KIconLoader::SizeHuge + KIconLoader::SizeEnormous) / 2; 0250 if (itemCount > 9) { 0251 xCount = 4; 0252 size = KIconLoader::SizeMedium; 0253 } 0254 else if (itemCount > 4) { 0255 xCount = 3; 0256 size = KIconLoader::SizeLarge; 0257 } 0258 0259 if (itemCount < xCount) { 0260 xCount = itemCount; 0261 } 0262 0263 int yCount = itemCount / xCount; 0264 if (itemCount % xCount != 0) { 0265 ++yCount; 0266 } 0267 0268 if (yCount > xCount) { 0269 yCount = xCount; 0270 } 0271 0272 // Draw the selected items into the grid cells 0273 QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1); 0274 dragPixmap.fill(Qt::transparent); 0275 0276 QPainter painter(&dragPixmap); 0277 int x = 0; 0278 int y = 0; 0279 foreach (const QModelIndex &selectedIndex, selectedIndexes) { 0280 const QIcon icon = (model()->data(selectedIndex, Qt::DecorationRole)).value<QIcon>(); 0281 painter.drawPixmap(x, y, icon.pixmap(size, size)); 0282 0283 x += size + 1; 0284 if (x >= dragPixmap.width()) { 0285 x = 0; 0286 y += size + 1; 0287 } 0288 if (y >= dragPixmap.height()) { 0289 break; 0290 } 0291 } 0292 0293 return dragPixmap; 0294 } 0295 0296 int KPrSlidesManagerView::cursorSlideIndex() const 0297 { 0298 QPair <int, int> m_pair = cursorRowAndColumn(); 0299 int slidesNumber = qFloor((contentsRect().width() - (margin + spacing() - contentsMargins().right())) / 0300 (itemSize().width() + spacing())); 0301 slidesNumber = qMax(slidesNumber, 1); 0302 return (m_pair.second * slidesNumber + qMin(slidesNumber, m_pair.first)); 0303 } 0304 0305 QPair<int, int> KPrSlidesManagerView::cursorRowAndColumn() const 0306 { 0307 QSize size(itemSize().width() + spacing(), itemSize().height() + spacing()); 0308 int slidesNumber = qFloor((contentsRect().width() - (margin + spacing() - contentsMargins().right())) / size.width()); 0309 slidesNumber = qMax(slidesNumber, 1); 0310 int scrollBarValue = verticalScrollBar()->value(); 0311 QPoint cursorPosition = QWidget::mapFromGlobal(QCursor::pos()); 0312 int numberColumn = qFloor(cursorPosition.x() / size.width()); 0313 int numberRow = qCeil((cursorPosition.y() + scrollBarValue) / (qreal)size.height()) - 1; 0314 int numberMod = model()->rowCount(QModelIndex()) > 0 ? 0315 (numberColumn + slidesNumber * numberRow) % (model()->rowCount(QModelIndex())) : 0; 0316 0317 int totalRows = qCeil((model()->rowCount(QModelIndex())) / (qreal)slidesNumber); 0318 0319 if (numberColumn > slidesNumber) { 0320 numberColumn = slidesNumber; 0321 } 0322 0323 if ((numberColumn > numberMod) & (model()->rowCount(QModelIndex()) % slidesNumber != 0)) { 0324 numberColumn = model()->rowCount(QModelIndex()) % slidesNumber; 0325 } 0326 0327 if (numberRow > totalRows - 1) { 0328 numberRow = totalRows - 1; 0329 numberColumn = model()->rowCount(QModelIndex()) % slidesNumber != 0 ? 0330 model()->rowCount(QModelIndex()) % slidesNumber : slidesNumber; 0331 } 0332 0333 return QPair<int,int>(numberColumn, numberRow); 0334 }