diff --git a/krusader/Panel/PanelView/krinterview.h b/krusader/Panel/PanelView/krinterview.h --- a/krusader/Panel/PanelView/krinterview.h +++ b/krusader/Panel/PanelView/krinterview.h @@ -60,12 +60,12 @@ KrViewItem* getPrev(KrViewItem *current) Q_DECL_OVERRIDE; KrViewItem* getCurrentKrViewItem() Q_DECL_OVERRIDE; KrViewItem* findItemByName(const QString &name) Q_DECL_OVERRIDE; - KrViewItem *findItemByFileItem(FileItem *fileitem) Q_DECL_OVERRIDE; KrViewItem *findItemByUrl(const QUrl &url) Q_DECL_OVERRIDE; QString getCurrentItem() const Q_DECL_OVERRIDE; - KrViewItem* getKrViewItemAt(const QPoint &vp) Q_DECL_OVERRIDE; - void setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex=QModelIndex()) Q_DECL_OVERRIDE; - void setCurrentKrViewItem(KrViewItem *item) Q_DECL_OVERRIDE; + KrViewItem *getKrViewItemAt(const QPoint &vp) Q_DECL_OVERRIDE; + void setCurrentItem(const QString &name, bool scrollToCurrent = true, + const QModelIndex &fallbackToIndex = QModelIndex()) Q_DECL_OVERRIDE; + void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) Q_DECL_OVERRIDE; void makeItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; bool isItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; void clear() Q_DECL_OVERRIDE; @@ -97,7 +97,10 @@ KIO::filesize_t calcSelectedSize() Q_DECL_OVERRIDE; void populate(const QList &fileItems, FileItem *dummy) Q_DECL_OVERRIDE; KrViewItem* preAddItem(FileItem *fileitem) Q_DECL_OVERRIDE; - void preDelItem(KrViewItem *item) Q_DECL_OVERRIDE; + /** + * Remove an item. Does not handle new current selection. + */ + void preDeleteItem(KrViewItem *item) Q_DECL_OVERRIDE; void intSetSelected(const FileItem* fileitem, bool select) Q_DECL_OVERRIDE; virtual QRect itemRect(const FileItem *fileitem) = 0; @@ -114,6 +117,8 @@ KrMouseHandler *_mouseHandler; QHash _itemHash; QSet _selection; +private: + void setCurrent(const QModelIndex &index, bool scrollToCurrent); }; #endif diff --git a/krusader/Panel/PanelView/krinterview.cpp b/krusader/Panel/PanelView/krinterview.cpp --- a/krusader/Panel/PanelView/krinterview.cpp +++ b/krusader/Panel/PanelView/krinterview.cpp @@ -131,10 +131,8 @@ if (!_model->ready()) return QString(); - FileItem *fileitem = _model->fileItemAt(_itemView->currentIndex()); - if (fileitem == 0) - return QString(); - return fileitem->getName(); + FileItem *fileItem = _model->fileItemAt(_itemView->currentIndex()); + return fileItem ? fileItem->getName() : QString(); } KrViewItem* KrInterView::getCurrentKrViewItem() @@ -187,10 +185,6 @@ return getKrViewItem(_itemView->indexAt(vp)); } -KrViewItem *KrInterView::findItemByFileItem(FileItem *fileItem) { - return getKrViewItem(fileItem); -} - KrViewItem * KrInterView::getKrViewItem(FileItem *fileItem) { QHash::iterator it = _itemHash.find(fileItem); @@ -215,59 +209,72 @@ void KrInterView::makeCurrentVisible() { - qDebug() << "scroll to current index=" << _itemView->currentIndex(); - _itemView->scrollTo(_itemView->currentIndex()); + makeItemVisible(getCurrentKrViewItem()); } void KrInterView::makeItemVisible(const KrViewItem *item) { if (item == 0) return; FileItem* fileitem = (FileItem *)item->getFileItem(); - QModelIndex ndx = _model->fileItemIndex(fileitem); - qDebug() << "scroll to item name=" << fileitem->getName(); - if (ndx.isValid()) - _itemView->scrollTo(ndx); + const QModelIndex index = _model->fileItemIndex(fileitem); + qDebug() << "scroll to item; name=" << fileitem->getName() << " index=" << index; + if (index.isValid()) + _itemView->scrollTo(index); } bool KrInterView::isItemVisible(const KrViewItem *item) { - return _itemView->viewport()->rect().contains(item->itemRect()); + return item && _itemView->viewport()->rect().contains(item->itemRect()); } -void KrInterView::setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex) +void KrInterView::setCurrentItem(const QString &name, bool scrollToCurrent, + const QModelIndex &fallbackToIndex) { // find index by given name and set it as current - QModelIndex ndx = _model->nameIndex(name); - if (ndx.isValid()) { - // also sets the scrolling position - _itemView->setCurrentIndex(ndx); + const QModelIndex index = _model->nameIndex(name); + if (index.isValid()) { + setCurrent(index, scrollToCurrent); } else if (fallbackToIndex.isValid()) { - // set fallback index as current index - // when fallback index is too big, set the last item as current - if (fallbackToIndex.row() >= _itemView->model()->rowCount()) { - setCurrentKrViewItem(getLast()); + // set fallback index as current if not too big, else set the last item as current + if (fallbackToIndex.row() < _itemView->model()->rowCount()) { + setCurrent(fallbackToIndex, scrollToCurrent); } else { - _itemView->setCurrentIndex(fallbackToIndex); + setCurrentKrViewItem(getLast(), scrollToCurrent); } } else { // when given parameters fail, set the first item as current - setCurrentKrViewItem(getFirst()); + setCurrentKrViewItem(getFirst(), scrollToCurrent); } } -void KrInterView::setCurrentKrViewItem(KrViewItem *item) +void KrInterView::setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent) { - if (item == 0) { - _itemView->setCurrentIndex(QModelIndex()); + if (!item) { + setCurrent(QModelIndex(), scrollToCurrent); return; } + FileItem* fileitem = (FileItem *)item->getFileItem(); - QModelIndex ndx = _model->fileItemIndex(fileitem); - if (ndx.isValid() && ndx.row() != _itemView->currentIndex().row()) { - _mouseHandler->cancelTwoClickRename(); - _itemView->setCurrentIndex(ndx); + const QModelIndex index = _model->fileItemIndex(fileitem); + if (index.isValid() && index.row() != _itemView->currentIndex().row()) { + setCurrent(index, scrollToCurrent); + } +} + +void KrInterView::setCurrent(const QModelIndex &index, bool scrollToCurrent) { + const bool disableAutoScroll = _itemView->hasAutoScroll() && !scrollToCurrent; + if (disableAutoScroll) { + // setCurrentIndex() scrolls to current if autoScroll is turned on + _itemView->setAutoScroll(false); + } + + _mouseHandler->cancelTwoClickRename(); + _itemView->setCurrentIndex(index); + + if (disableAutoScroll) { + _itemView->setAutoScroll(true); } } @@ -297,18 +304,23 @@ KrViewItem* KrInterView::preAddItem(FileItem *fileitem) { - QModelIndex idx = _model->addItem(fileitem); - if(_model->rowCount() == 1) // if this is the fist item to be added, make it current - _itemView->setCurrentIndex(idx); - return getKrViewItem(idx); + const QModelIndex index = _model->addItem(fileitem); + return getKrViewItem(index); } -void KrInterView::preDelItem(KrViewItem *item) +void KrInterView::preDeleteItem(KrViewItem *item) { setSelected(item->getFileItem(), false); - QModelIndex ndx = _model->removeItem((FileItem *)item->getFileItem()); - if (ndx.isValid()) - _itemView->setCurrentIndex(ndx); + + // if the next item is current, current selection is lost on remove; preserve manually + KrViewItem *currentItem = getCurrentKrViewItem(); + KrViewItem *nextCurrentItem = currentItem && currentItem == getNext(item) ? currentItem : 0; + + _model->removeItem((FileItem *)item->getFileItem()); + + if (nextCurrentItem) + setCurrentKrViewItem(nextCurrentItem, false); + _itemHash.remove((FileItem *)item->getFileItem()); } diff --git a/krusader/Panel/PanelView/krview.h b/krusader/Panel/PanelView/krview.h --- a/krusader/Panel/PanelView/krview.h +++ b/krusader/Panel/PanelView/krview.h @@ -211,12 +211,11 @@ virtual KrViewItem *getCurrentKrViewItem() = 0; virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0; virtual KrViewItem *findItemByName(const QString &name) = 0; - virtual KrViewItem *findItemByFileItem(FileItem *vf) = 0; virtual KrViewItem *findItemByUrl(const QUrl &url) = 0; virtual QString getCurrentItem() const = 0; - virtual void setCurrentItem(const QString &name, + virtual void setCurrentItem(const QString &name, bool scrollToCurrent = true, const QModelIndex &fallbackToIndex = QModelIndex()) = 0; - virtual void setCurrentKrViewItem(KrViewItem *item) = 0; + virtual void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) = 0; virtual void makeItemVisible(const KrViewItem *item) = 0; virtual bool isItemVisible(const KrViewItem *item) = 0; virtual void updateView() = 0; @@ -232,15 +231,16 @@ protected: virtual KrViewItem *preAddItem(FileItem *fileitem) = 0; - virtual void preDelItem(KrViewItem *item) = 0; + virtual void preDeleteItem(KrViewItem *item) = 0; virtual void copySettingsFrom(KrView *other) = 0; virtual void populate(const QList &fileItems, FileItem *dummy) = 0; virtual void intSetSelected(const FileItem *fileitem, bool select) = 0; virtual void clear(); - void addItem(FileItem *fileitem); + + void addItem(FileItem *fileItem, bool onUpdate = false); + void deleteItem(const QString &name, bool onUpdate = false); void updateItem(FileItem *newFileItem); - void delItem(const QString &name); public: ////////////////////////////////////////////////////// @@ -269,6 +269,12 @@ void applySettingsToOthers(); void setFiles(DirListerInterface *files); + + /** + * Refresh the file view items after the underlying file model changed. + * + * Tries to preserve current file and file selection if applicable. + */ void refresh(); bool changeSelection(const KRQuery &filter, bool select); diff --git a/krusader/Panel/PanelView/krview.cpp b/krusader/Panel/PanelView/krview.cpp --- a/krusader/Panel/PanelView/krview.cpp +++ b/krusader/Panel/PanelView/krview.cpp @@ -534,49 +534,48 @@ return iterator->name(); } -void KrView::delItem(const QString &name) +void KrView::deleteItem(const QString &name, bool onUpdate) { - KrViewItem *it = findItemByName(name); - if(!it) + KrViewItem *viewItem = findItemByName(name); + if (!viewItem) return; - if(_previews) - _previews->deletePreview(it); + if (_previews && !onUpdate) + _previews->deletePreview(viewItem); - preDelItem(it); + preDeleteItem(viewItem); - if (it->FILEITEM->isDir()) { + if (viewItem->FILEITEM->isDir()) { --_numDirs; } --_count; - delete it; + delete viewItem; - op()->emitSelectionChanged(); + if (!onUpdate) + op()->emitSelectionChanged(); } -void KrView::addItem(FileItem *fileitem) +void KrView::addItem(FileItem *fileItem, bool onUpdate) { - if (isFiltered(fileitem)) + if (isFiltered(fileItem)) return; - KrViewItem *item = preAddItem(fileitem); - if (!item) - return; // don't add it after all - if(_previews) - _previews->updatePreview(item); + KrViewItem *viewItem = preAddItem(fileItem); + if (!viewItem) + return; // not added + + if (_previews) + _previews->updatePreview(viewItem); - if (fileitem->isDir()) + if (fileItem->isDir()) ++_numDirs; ++_count; - if (item->name() == nameToMakeCurrent()) { - setCurrentKrViewItem(item); // dictionary based - quick - makeItemVisible(item); + if (!onUpdate) { + op()->emitSelectionChanged(); } - - op()->emitSelectionChanged(); } void KrView::updateItem(FileItem *newFileItem) @@ -591,16 +590,14 @@ const bool isSelected = selectedNames.contains(name); // delete old file item - delItem(name); + deleteItem(name, true); if (!isFiltered(newFileItem)) { - addItem(newFileItem); - if(_previews) - _previews->updatePreview(findItemByFileItem(newFileItem)); + addItem(newFileItem, true); } if (isCurrent) - setCurrentItem(name); + setCurrentItem(name, false); if (isSelected) setSelected(newFileItem, true); @@ -1125,9 +1122,14 @@ void KrView::refresh() { - QString currentItem = getCurrentItem(); - QList selection = selectedUrls(); - QModelIndex currentIndex = getCurrentIndex(); + const QString currentItem = !nameToMakeCurrent().isEmpty() ? // + nameToMakeCurrent() : + getCurrentItem(); + bool scrollToCurrent = !nameToMakeCurrent().isEmpty() || isItemVisible(getCurrentKrViewItem()); + setNameToMakeCurrent(QString()); + + const QModelIndex currentIndex = getCurrentIndex(); + const QList selection = selectedUrls(); clear(); @@ -1156,18 +1158,15 @@ if(!selection.isEmpty()) setSelectionUrls(selection); - if (!nameToMakeCurrent().isEmpty()) { - setCurrentItem(nameToMakeCurrent()); - setNameToMakeCurrent(""); - } else if (!currentItem.isEmpty()) { - if (currentItem == ".." && _count > 0 && + if (!currentItem.isEmpty()) { + if (currentItem == ".." && _count > 0 && // !_quickFilterMask.isEmpty() && _quickFilterMask.isValid()) { // In a filtered view we should never select the dummy entry if // there are real matches. setCurrentKrViewItem(getNext(getFirst())); + } else { + setCurrentItem(currentItem, scrollToCurrent, currentIndex); } - else - setCurrentItem(currentItem, currentIndex); } else { setCurrentKrViewItem(getFirst()); } diff --git a/krusader/Panel/PanelView/listmodel.h b/krusader/Panel/PanelView/listmodel.h --- a/krusader/Panel/PanelView/listmodel.h +++ b/krusader/Panel/PanelView/listmodel.h @@ -49,7 +49,7 @@ } void populate(const QList &files, FileItem *dummy); QModelIndex addItem(FileItem *); - QModelIndex removeItem(FileItem *); + void removeItem(FileItem *); int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; diff --git a/krusader/Panel/PanelView/listmodel.cpp b/krusader/Panel/PanelView/listmodel.cpp --- a/krusader/Panel/PanelView/listmodel.cpp +++ b/krusader/Panel/PanelView/listmodel.cpp @@ -316,7 +316,7 @@ { emit layoutAboutToBeChanged(); - if(lastSortOrder() == KrViewProperties::NoColumn) { + if (lastSortOrder() == KrViewProperties::NoColumn) { int idx = _fileItems.count(); _fileItems.append(fileitem); updateIndices(fileitem, idx); @@ -328,7 +328,8 @@ KrSort::Sorter sorter(createSorter()); - int insertIndex = sorter.insertIndex(fileitem, fileitem == _dummyFileItem, customSortData(fileitem)); + const bool isDummy = fileitem == _dummyFileItem; + const int insertIndex = sorter.insertIndex(fileitem, isDummy, customSortData(fileitem)); if (insertIndex != _fileItems.count()) _fileItems.insert(insertIndex, fileitem); else @@ -339,66 +340,50 @@ } QModelIndexList newPersistentList; - foreach(const QModelIndex &mndx, oldPersistentList) { + foreach (const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow >= insertIndex) newRow++; newPersistentList << index(newRow, mndx.column()); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); - _view->makeItemVisible(_view->getCurrentKrViewItem()); return index(insertIndex, 0); } -QModelIndex ListModel::removeItem(FileItem *fileitem) +void ListModel::removeItem(FileItem *fileItem) { - QModelIndex currIndex = _view->getCurrentIndex(); - int removeIdx = _fileItems.indexOf(fileitem); - if(removeIdx < 0) - return currIndex; + const int rowToRemove = _fileItems.indexOf(fileItem); + if (rowToRemove < 0) + return; emit layoutAboutToBeChanged(); - QModelIndexList oldPersistentList = persistentIndexList(); - QModelIndexList newPersistentList; - - _fileItems.removeAt(removeIdx); - if (currIndex.row() == removeIdx) { - if (_fileItems.count() == 0) - currIndex = QModelIndex(); - else if (removeIdx >= _fileItems.count()) - currIndex = index(_fileItems.count() - 1, 0); - else - currIndex = index(removeIdx, 0); - } else if (currIndex.row() > removeIdx) { - currIndex = index(currIndex.row() - 1, 0); - } + _fileItems.removeAt(rowToRemove); - _fileItemNdx.remove(fileitem); - _nameNdx.remove(fileitem->getName()); - _urlNdx.remove(fileitem->getUrl()); + _fileItemNdx.remove(fileItem); + _nameNdx.remove(fileItem->getName()); + _urlNdx.remove(fileItem->getUrl()); // update indices for fileItems following fileitem - for (int i = removeIdx; i < _fileItems.count(); i++) { + for (int i = rowToRemove; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } - foreach(const QModelIndex &mndx, oldPersistentList) { + const QModelIndexList oldPersistentList = persistentIndexList(); + QModelIndexList newPersistentList; + foreach (const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); - if (newRow > removeIdx) + if (newRow > rowToRemove) newRow--; - if (newRow != removeIdx) + if (newRow != rowToRemove) newPersistentList << index(newRow, mndx.column()); else newPersistentList << QModelIndex(); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); - _view->makeItemVisible(_view->getCurrentKrViewItem()); - - return currIndex; } QVariant ListModel::headerData(int section, Qt::Orientation orientation, int role) const diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp --- a/krusader/Panel/panelfunc.cpp +++ b/krusader/Panel/panelfunc.cpp @@ -298,15 +298,10 @@ panel->view->setFiles(files()); - if(!history->currentItem().isEmpty() && isEqualUrl) { - // if the url we're refreshing into is the current one, then the - // partial refresh will not generate the needed signals to actually allow the - // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch) - qDebug() << "setting current item=" << history->currentItem(); - panel->view->setCurrentItem(history->currentItem()); - panel->view->makeItemVisible(panel->view->getCurrentKrViewItem()); + if (!isEqualUrl || !panel->view->getCurrentKrViewItem()) { + // set current item after refresh from history, if there is none yet + panel->view->setNameToMakeCurrent(history->currentItem()); } - panel->view->setNameToMakeCurrent(history->currentItem()); // workaround for detecting panel deletion while filesystem is refreshing QPointer panelSave = panel;