File indexing completed on 2024-05-12 17:22:01
0001 /* 0002 SPDX-FileCopyrightText: 2002 Shie Erlich <erlich@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2002 Rafi Yanai <yanai@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2010 Jan Lepper <dehtris@yahoo.de> 0005 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "krinterview.h" 0011 0012 #include <QDebug> 0013 0014 #include "../FileSystem/dirlisterinterface.h" 0015 #include "../FileSystem/fileitem.h" 0016 #include "../krcolorcache.h" 0017 #include "../krpreviews.h" 0018 #include "krmousehandler.h" 0019 #include "krviewitem.h" 0020 #include "listmodel.h" 0021 0022 KrInterView::KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView) 0023 : KrView(instance, cfg) 0024 , _itemView(itemView) 0025 , _mouseHandler(nullptr) 0026 { 0027 _model = new ListModel(this); 0028 0029 // fix the context menu problem 0030 int j = QFontMetrics(_itemView->font()).height() * 2; 0031 _mouseHandler = new KrMouseHandler(this, j); 0032 } 0033 0034 KrInterView::~KrInterView() 0035 { 0036 // any references to the model should be cleared ar this point, 0037 // but sometimes for some reason it is still referenced by 0038 // QPersistentModelIndex instances held by QAbstractItemView and/or QItemSelectionModel(child object) - 0039 // so schedule _model for later deletion 0040 _model->clear(false); 0041 _model->deleteLater(); 0042 _model = nullptr; 0043 delete _mouseHandler; 0044 _mouseHandler = nullptr; 0045 QHashIterator<FileItem *, KrViewItem *> it(_itemHash); 0046 while (it.hasNext()) 0047 delete it.next().value(); 0048 _itemHash.clear(); 0049 } 0050 0051 void KrInterView::selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) 0052 { 0053 auto *file1 = const_cast<FileItem *>(i1->getFileItem()); 0054 QModelIndex mi1 = _model->fileItemIndex(file1); 0055 auto *file2 = const_cast<FileItem *>(i2->getFileItem()); 0056 QModelIndex mi2 = _model->fileItemIndex(file2); 0057 0058 if (mi1.isValid() && mi2.isValid()) { 0059 int r1 = mi1.row(); 0060 int r2 = mi2.row(); 0061 0062 if (r1 > r2) { 0063 int t = r1; 0064 r1 = r2; 0065 r2 = t; 0066 } 0067 0068 op()->setMassSelectionUpdate(true); 0069 for (int row = r1; row <= r2; row++) 0070 setSelected(_model->fileItemAt(_model->index(row, 0)), select); 0071 op()->setMassSelectionUpdate(false); 0072 0073 redraw(); 0074 0075 } else if (mi1.isValid() && !mi2.isValid()) 0076 i1->setSelected(select); 0077 else if (mi2.isValid() && !mi1.isValid()) 0078 i2->setSelected(select); 0079 } 0080 0081 void KrInterView::intSetSelected(const FileItem *item, bool select) 0082 { 0083 if (select) 0084 _selection.insert(item); 0085 else 0086 _selection.remove(item); 0087 } 0088 0089 bool KrInterView::isSelected(const QModelIndex &ndx) 0090 { 0091 return isSelected(_model->fileItemAt(ndx)); 0092 } 0093 0094 KrViewItem *KrInterView::findItemByName(const QString &name) 0095 { 0096 if (!_model->ready()) 0097 return nullptr; 0098 0099 QModelIndex ndx = _model->nameIndex(name); 0100 if (!ndx.isValid()) 0101 return nullptr; 0102 return getKrViewItem(ndx); 0103 } 0104 0105 KrViewItem *KrInterView::findItemByUrl(const QUrl &url) 0106 { 0107 if (!_model->ready()) 0108 return nullptr; 0109 0110 const QModelIndex ndx = _model->indexFromUrl(url); 0111 if (!ndx.isValid()) 0112 return nullptr; 0113 0114 return getKrViewItem(ndx); 0115 } 0116 0117 QString KrInterView::getCurrentItem() const 0118 { 0119 if (!_model->ready()) 0120 return QString(); 0121 0122 FileItem *fileItem = _model->fileItemAt(_itemView->currentIndex()); 0123 return fileItem ? fileItem->getName() : QString(); 0124 } 0125 0126 KrViewItem *KrInterView::getCurrentKrViewItem() 0127 { 0128 if (!_model->ready()) 0129 return nullptr; 0130 0131 return getKrViewItem(_itemView->currentIndex()); 0132 } 0133 0134 KrViewItem *KrInterView::getFirst() 0135 { 0136 if (!_model->ready()) 0137 return nullptr; 0138 0139 return getKrViewItem(_model->index(0, 0, QModelIndex())); 0140 } 0141 0142 KrViewItem *KrInterView::getLast() 0143 { 0144 if (!_model->ready()) 0145 return nullptr; 0146 0147 return getKrViewItem(_model->index(_model->rowCount() - 1, 0, QModelIndex())); 0148 } 0149 0150 KrViewItem *KrInterView::getNext(KrViewItem *current) 0151 { 0152 auto *fileItem = const_cast<FileItem *>(current->getFileItem()); 0153 QModelIndex ndx = _model->fileItemIndex(fileItem); 0154 if (ndx.row() >= _model->rowCount() - 1) 0155 return nullptr; 0156 return getKrViewItem(_model->index(ndx.row() + 1, 0, QModelIndex())); 0157 } 0158 0159 KrViewItem *KrInterView::getPrev(KrViewItem *current) 0160 { 0161 auto *fileItem = const_cast<FileItem *>(current->getFileItem()); 0162 QModelIndex ndx = _model->fileItemIndex(fileItem); 0163 if (ndx.row() <= 0) 0164 return nullptr; 0165 return getKrViewItem(_model->index(ndx.row() - 1, 0, QModelIndex())); 0166 } 0167 0168 KrViewItem *KrInterView::getKrViewItemAt(const QPoint &vp) 0169 { 0170 if (!_model->ready()) 0171 return nullptr; 0172 0173 return getKrViewItem(_itemView->indexAt(vp)); 0174 } 0175 0176 KrViewItem *KrInterView::getKrViewItem(FileItem *fileItem) 0177 { 0178 QHash<FileItem *, KrViewItem *>::iterator it = _itemHash.find(fileItem); 0179 if (it == _itemHash.end()) { 0180 auto *newItem = new KrViewItem(fileItem, this); 0181 _itemHash[fileItem] = newItem; 0182 return newItem; 0183 } 0184 return *it; 0185 } 0186 0187 KrViewItem *KrInterView::getKrViewItem(const QModelIndex &ndx) 0188 { 0189 if (!ndx.isValid()) 0190 return nullptr; 0191 FileItem *fileitem = _model->fileItemAt(ndx); 0192 if (fileitem == nullptr) 0193 return nullptr; 0194 else 0195 return getKrViewItem(fileitem); 0196 } 0197 0198 void KrInterView::makeCurrentVisible() 0199 { 0200 makeItemVisible(getCurrentKrViewItem()); 0201 } 0202 0203 void KrInterView::makeItemVisible(const KrViewItem *item) 0204 { 0205 if (item == nullptr) 0206 return; 0207 0208 auto *fileitem = const_cast<FileItem *>(item->getFileItem()); 0209 const QModelIndex index = _model->fileItemIndex(fileitem); 0210 qDebug() << "scroll to item; name=" << fileitem->getName() << " index=" << index; 0211 if (index.isValid()) 0212 _itemView->scrollTo(index); 0213 } 0214 0215 bool KrInterView::isItemVisible(const KrViewItem *item) 0216 { 0217 return item && _itemView->viewport()->rect().contains(item->itemRect()); 0218 } 0219 0220 void KrInterView::setCurrentItem(const QString &name, bool scrollToCurrent, const QModelIndex &fallbackToIndex) 0221 { 0222 // find index by given name and set it as current 0223 const QModelIndex index = _model->nameIndex(name); 0224 if (index.isValid()) { 0225 setCurrent(index, scrollToCurrent); 0226 } else if (fallbackToIndex.isValid()) { 0227 // set fallback index as current if not too big, else set the last item as current 0228 if (fallbackToIndex.row() < _itemView->model()->rowCount()) { 0229 setCurrent(fallbackToIndex, scrollToCurrent); 0230 } else { 0231 setCurrentKrViewItem(getLast(), scrollToCurrent); 0232 } 0233 } else { 0234 // when given parameters fail, set the first item as current 0235 setCurrentKrViewItem(getFirst(), scrollToCurrent); 0236 } 0237 } 0238 0239 void KrInterView::setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent) 0240 { 0241 if (!item) { 0242 setCurrent(QModelIndex(), scrollToCurrent); 0243 return; 0244 } 0245 0246 auto *fileitem = const_cast<FileItem *>(item->getFileItem()); 0247 const QModelIndex index = _model->fileItemIndex(fileitem); 0248 if (index.isValid() && index.row() != _itemView->currentIndex().row()) { 0249 setCurrent(index, scrollToCurrent); 0250 } 0251 } 0252 0253 void KrInterView::setCurrent(const QModelIndex &index, bool scrollToCurrent) 0254 { 0255 const bool disableAutoScroll = _itemView->hasAutoScroll() && !scrollToCurrent; 0256 if (disableAutoScroll) { 0257 // setCurrentIndex() scrolls to current if autoScroll is turned on 0258 _itemView->setAutoScroll(false); 0259 } 0260 0261 _mouseHandler->cancelTwoClickRename(); 0262 _itemView->setCurrentIndex(index); 0263 0264 if (disableAutoScroll) { 0265 _itemView->setAutoScroll(true); 0266 } 0267 } 0268 0269 void KrInterView::sort() 0270 { 0271 _model->sort(); 0272 } 0273 0274 void KrInterView::clear() 0275 { 0276 _selection.clear(); 0277 _itemView->clearSelection(); 0278 _itemView->setCurrentIndex(QModelIndex()); 0279 _model->clear(); 0280 QHashIterator<FileItem *, KrViewItem *> it(_itemHash); 0281 while (it.hasNext()) 0282 delete it.next().value(); 0283 _itemHash.clear(); 0284 0285 KrView::clear(); 0286 } 0287 0288 void KrInterView::populate(const QList<FileItem *> &fileItems, FileItem *dummy) 0289 { 0290 _model->populate(fileItems, dummy); 0291 } 0292 0293 KrViewItem *KrInterView::preAddItem(FileItem *fileitem) 0294 { 0295 const QModelIndex index = _model->addItem(fileitem); 0296 return getKrViewItem(index); 0297 } 0298 0299 void KrInterView::preDeleteItem(KrViewItem *item) 0300 { 0301 // update selection 0302 setSelected(item->getFileItem(), false); 0303 0304 // close editor if it's opened for the item 0305 auto file_item = const_cast<FileItem *>(item->getFileItem()); 0306 _itemView->closePersistentEditor(_model->fileItemIndex(file_item)); 0307 0308 // remove the item from the structures 0309 _model->removeItem(file_item); 0310 _itemHash.remove(file_item); 0311 } 0312 0313 void KrInterView::prepareForActive() 0314 { 0315 _focused = true; 0316 _itemView->setFocus(); 0317 } 0318 0319 void KrInterView::prepareForPassive() 0320 { 0321 _focused = false; 0322 _mouseHandler->cancelTwoClickRename(); 0323 // if ( renameLineEdit() ->isVisible() ) 0324 // renameLineEdit() ->clearFocus(); 0325 } 0326 0327 void KrInterView::redraw() 0328 { 0329 _itemView->viewport()->update(); 0330 } 0331 0332 void KrInterView::refreshColors() 0333 { 0334 QPalette p(_itemView->palette()); 0335 KrColorGroup cg; 0336 KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, _focused, false, false)); 0337 p.setColor(QPalette::Text, cg.text()); 0338 p.setColor(QPalette::Base, cg.background()); 0339 _itemView->setPalette(p); 0340 redraw(); 0341 } 0342 0343 void KrInterView::sortModeUpdated(int column, Qt::SortOrder order) 0344 { 0345 KrView::sortModeUpdated(static_cast<KrViewProperties::ColumnType>(column), order == Qt::DescendingOrder); 0346 } 0347 0348 KIO::filesize_t KrInterView::calcSize() 0349 { 0350 KIO::filesize_t size = 0; 0351 foreach (FileItem *fileitem, _model->fileItems()) { 0352 size += fileitem->getSize(); 0353 } 0354 return size; 0355 } 0356 0357 KIO::filesize_t KrInterView::calcSelectedSize() 0358 { 0359 KIO::filesize_t size = 0; 0360 foreach (const FileItem *fileitem, _selection) { 0361 size += fileitem->getSize(); 0362 } 0363 return size; 0364 } 0365 0366 QList<QUrl> KrInterView::selectedUrls() 0367 { 0368 QList<QUrl> list; 0369 foreach (const FileItem *fileitem, _selection) { 0370 list << fileitem->getUrl(); 0371 } 0372 return list; 0373 } 0374 0375 void KrInterView::setSelectionUrls(const QList<QUrl> urls) 0376 { 0377 op()->setMassSelectionUpdate(true); 0378 0379 _selection.clear(); 0380 0381 foreach (const QUrl &url, urls) { 0382 const QModelIndex idx = _model->indexFromUrl(url); 0383 if (idx.isValid()) 0384 setSelected(_model->fileItemAt(idx), true); 0385 } 0386 0387 op()->setMassSelectionUpdate(false); 0388 }