diff --git a/krusader/Panel/PanelView/krinterview.cpp b/krusader/Panel/PanelView/krinterview.cpp index 3217bd23..004314fa 100644 --- a/krusader/Panel/PanelView/krinterview.cpp +++ b/krusader/Panel/PanelView/krinterview.cpp @@ -1,404 +1,402 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * * * * This file is part of Krusader [https://krusader.org]. * * * * Krusader is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 2 of the License, or * * (at your option) any later version. * * * * Krusader is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * *****************************************************************************/ #include "krinterview.h" #include #include "krmousehandler.h" #include "listmodel.h" #include "krviewitem.h" #include "../krpreviews.h" #include "../krcolorcache.h" #include "../FileSystem/dirlisterinterface.h" #include "../FileSystem/fileitem.h" KrInterView::KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView) : KrView(instance, cfg), _itemView(itemView), _mouseHandler(nullptr) { _model = new ListModel(this); // fix the context menu problem int j = QFontMetrics(_itemView->font()).height() * 2; _mouseHandler = new KrMouseHandler(this, j); } KrInterView::~KrInterView() { // any references to the model should be cleared ar this point, // but sometimes for some reason it is still referenced by // QPersistentModelIndex instances held by QAbstractItemView and/or QItemSelectionModel(child object) - // so schedule _model for later deletion _model->clear(false); _model->deleteLater(); _model = nullptr; delete _mouseHandler; _mouseHandler = nullptr; QHashIterator< FileItem *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); } void KrInterView::selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) { auto* file1 = (FileItem *)i1->getFileItem(); QModelIndex mi1 = _model->fileItemIndex(file1); auto* file2 = (FileItem *)i2->getFileItem(); QModelIndex mi2 = _model->fileItemIndex(file2); if (mi1.isValid() && mi2.isValid()) { int r1 = mi1.row(); int r2 = mi2.row(); if (r1 > r2) { int t = r1; r1 = r2; r2 = t; } op()->setMassSelectionUpdate(true); for (int row = r1; row <= r2; row++) setSelected(_model->fileItemAt(_model->index(row, 0)), select); op()->setMassSelectionUpdate(false); redraw(); } else if (mi1.isValid() && !mi2.isValid()) i1->setSelected(select); else if (mi2.isValid() && !mi1.isValid()) i2->setSelected(select); } void KrInterView::intSetSelected(const FileItem* item, bool select) { if(select) _selection.insert(item); else _selection.remove(item); } bool KrInterView::isSelected(const QModelIndex &ndx) { return isSelected(_model->fileItemAt(ndx)); } KrViewItem* KrInterView::findItemByName(const QString &name) { if (!_model->ready()) return nullptr; QModelIndex ndx = _model->nameIndex(name); if (!ndx.isValid()) return nullptr; return getKrViewItem(ndx); } KrViewItem *KrInterView::findItemByUrl(const QUrl &url) { if (!_model->ready()) return nullptr; const QModelIndex ndx = _model->indexFromUrl(url); if (!ndx.isValid()) return nullptr; return getKrViewItem(ndx); } QString KrInterView::getCurrentItem() const { if (!_model->ready()) return QString(); FileItem *fileItem = _model->fileItemAt(_itemView->currentIndex()); return fileItem ? fileItem->getName() : QString(); } KrViewItem* KrInterView::getCurrentKrViewItem() { if (!_model->ready()) return nullptr; return getKrViewItem(_itemView->currentIndex()); } KrViewItem* KrInterView::getFirst() { if (!_model->ready()) return nullptr; return getKrViewItem(_model->index(0, 0, QModelIndex())); } KrViewItem* KrInterView::getLast() { if (!_model->ready()) return nullptr; return getKrViewItem(_model->index(_model->rowCount() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getNext(KrViewItem *current) { auto* fileItem = (FileItem *)current->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileItem); if (ndx.row() >= _model->rowCount() - 1) return nullptr; return getKrViewItem(_model->index(ndx.row() + 1, 0, QModelIndex())); } KrViewItem* KrInterView::getPrev(KrViewItem *current) { auto* fileItem = (FileItem *)current->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileItem); if (ndx.row() <= 0) return nullptr; return getKrViewItem(_model->index(ndx.row() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getKrViewItemAt(const QPoint &vp) { if (!_model->ready()) return nullptr; return getKrViewItem(_itemView->indexAt(vp)); } KrViewItem * KrInterView::getKrViewItem(FileItem *fileItem) { QHash::iterator it = _itemHash.find(fileItem); if (it == _itemHash.end()) { auto * newItem = new KrViewItem(fileItem, this); _itemHash[ fileItem ] = newItem; return newItem; } return *it; } KrViewItem * KrInterView::getKrViewItem(const QModelIndex & ndx) { if (!ndx.isValid()) return nullptr; FileItem * fileitem = _model->fileItemAt(ndx); if (fileitem == nullptr) return nullptr; else return getKrViewItem(fileitem); } void KrInterView::makeCurrentVisible() { makeItemVisible(getCurrentKrViewItem()); } void KrInterView::makeItemVisible(const KrViewItem *item) { if (item == nullptr) return; auto* fileitem = (FileItem *)item->getFileItem(); 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 item && _itemView->viewport()->rect().contains(item->itemRect()); } void KrInterView::setCurrentItem(const QString &name, bool scrollToCurrent, const QModelIndex &fallbackToIndex) { // find index by given name and set it as current const QModelIndex index = _model->nameIndex(name); if (index.isValid()) { setCurrent(index, scrollToCurrent); } else if (fallbackToIndex.isValid()) { // 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 { setCurrentKrViewItem(getLast(), scrollToCurrent); } } else { // when given parameters fail, set the first item as current setCurrentKrViewItem(getFirst(), scrollToCurrent); } } void KrInterView::setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent) { if (!item) { setCurrent(QModelIndex(), scrollToCurrent); return; } auto* fileitem = (FileItem *)item->getFileItem(); 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); } } void KrInterView::sort() { _model->sort(); } void KrInterView::clear() { _selection.clear(); _itemView->clearSelection(); _itemView->setCurrentIndex(QModelIndex()); _model->clear(); QHashIterator< FileItem *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); KrView::clear(); } void KrInterView::populate(const QList &fileItems, FileItem *dummy) { _model->populate(fileItems, dummy); } KrViewItem* KrInterView::preAddItem(FileItem *fileitem) { const QModelIndex index = _model->addItem(fileitem); return getKrViewItem(index); } void KrInterView::preDeleteItem(KrViewItem *item) { + // update selection setSelected(item->getFileItem(), false); - // if the next item is current, current selection is lost on remove; preserve manually - KrViewItem *currentItem = getCurrentKrViewItem(); - KrViewItem *nextCurrentItem = currentItem && currentItem == getNext(item) ? currentItem : nullptr; + // close editor if it's opened for the item + auto file_item = (FileItem *)item->getFileItem(); + _itemView->closePersistentEditor(_model->fileItemIndex(file_item)); - _model->removeItem((FileItem *)item->getFileItem()); - - if (nextCurrentItem) - setCurrentKrViewItem(nextCurrentItem, false); - - _itemHash.remove((FileItem *)item->getFileItem()); + // remove the item from the structures + _model->removeItem(file_item); + _itemHash.remove(file_item); } void KrInterView::prepareForActive() { _focused = true; _itemView->setFocus(); } void KrInterView::prepareForPassive() { _focused = false; _mouseHandler->cancelTwoClickRename(); //if ( renameLineEdit() ->isVisible() ) //renameLineEdit() ->clearFocus(); } void KrInterView::redraw() { _itemView->viewport()->update(); } void KrInterView::refreshColors() { QPalette p(_itemView->palette()); KrColorGroup cg; KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, _focused, false, false)); p.setColor(QPalette::Text, cg.text()); p.setColor(QPalette::Base, cg.background()); _itemView->setPalette(p); redraw(); } void KrInterView::sortModeUpdated(int column, Qt::SortOrder order) { KrView::sortModeUpdated(static_cast(column), order == Qt::DescendingOrder); } KIO::filesize_t KrInterView::calcSize() { KIO::filesize_t size = 0; foreach(FileItem *fileitem, _model->fileItems()) { size += fileitem->getSize(); } return size; } KIO::filesize_t KrInterView::calcSelectedSize() { KIO::filesize_t size = 0; foreach(const FileItem *fileitem, _selection) { size += fileitem->getSize(); } return size; } QList KrInterView::selectedUrls() { QList list; foreach(const FileItem *fileitem, _selection) { list << fileitem->getUrl(); } return list; } void KrInterView::setSelectionUrls(const QList urls) { op()->setMassSelectionUpdate(true); _selection.clear(); foreach(const QUrl &url, urls) { const QModelIndex idx = _model->indexFromUrl(url); if(idx.isValid()) setSelected(_model->fileItemAt(idx), true); } op()->setMassSelectionUpdate(false); } diff --git a/krusader/Panel/PanelView/listmodel.cpp b/krusader/Panel/PanelView/listmodel.cpp index 3563757e..aa1a883a 100644 --- a/krusader/Panel/PanelView/listmodel.cpp +++ b/krusader/Panel/PanelView/listmodel.cpp @@ -1,540 +1,529 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * * * * This file is part of Krusader [https://krusader.org]. * * * * Krusader is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 2 of the License, or * * (at your option) any later version. * * * * Krusader is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * *****************************************************************************/ #include "listmodel.h" #include "krinterview.h" #include "krviewproperties.h" #include "../FileSystem/fileitem.h" #include "../defaults.h" #include "../krcolorcache.h" #include "../krglobal.h" #include "../krpanel.h" #include #include ListModel::ListModel(KrInterView *view) : QAbstractListModel(nullptr), _extensionEnabled(true), _view(view), _dummyFileItem(nullptr), _ready(false), _justForSizeHint(false), _alternatingTable(false) { KConfigGroup grpSvr(krConfig, "Look&Feel"); _defaultFont = grpSvr.readEntry("Filelist Font", _FilelistFont); } void ListModel::populate(const QList &files, FileItem *dummy) { _fileItems = files; _dummyFileItem = dummy; _ready = true; if(lastSortOrder() != KrViewProperties::NoColumn) sort(); else { emit layoutAboutToBeChanged(); for(int i = 0; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } emit layoutChanged(); } } ListModel::~ListModel() = default; void ListModel::clear(bool emitLayoutChanged) { if(!_fileItems.count()) return; emit layoutAboutToBeChanged(); // clear persistent indexes QModelIndexList oldPersistentList = persistentIndexList(); QModelIndexList newPersistentList; newPersistentList.reserve(oldPersistentList.size()); for (int i=0; i< oldPersistentList.size(); ++i) newPersistentList.append(QModelIndex()); changePersistentIndexList(oldPersistentList, newPersistentList); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); _dummyFileItem = nullptr; if (emitLayoutChanged) emit layoutChanged(); } int ListModel::rowCount(const QModelIndex& /*parent*/) const { return _fileItems.count(); } int ListModel::columnCount(const QModelIndex& /*parent*/) const { return KrViewProperties::MAX_COLUMNS; } QVariant ListModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= rowCount()) return QVariant(); FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == nullptr) return QVariant(); switch (role) { case Qt::FontRole: return _defaultFont; case Qt::EditRole: { if (index.column() == 0) { return fileitem->getName(); } return QVariant(); } case Qt::UserRole: { if (index.column() == 0) { return nameWithoutExtension(fileitem, false); } return QVariant(); } case Qt::ToolTipRole: { if (index.column() == KrViewProperties::Name) { return fileitem == _dummyFileItem ? QVariant() : toolTipText(fileitem); } #if __GNUC__ >= 7 [[gnu::fallthrough]]; #endif } case Qt::DisplayRole: { switch (index.column()) { case KrViewProperties::Name: { return nameWithoutExtension(fileitem); } case KrViewProperties::Ext: { QString nameOnly = nameWithoutExtension(fileitem); const QString& fileitemName = fileitem->getName(); return fileitemName.mid(nameOnly.length() + 1); } case KrViewProperties::Size: { if (fileitem->getUISize() == (KIO::filesize_t)-1) { //HACK add <> brackets AFTER translating - otherwise KUIT thinks it's a tag static QString label = QString("<") + i18nc("Show the string 'DIR' instead of file size in detailed view (for folders)", "DIR") + '>'; return label; } else return KrView::sizeText(properties(), fileitem->getUISize()); } case KrViewProperties::Type: { if (fileitem == _dummyFileItem) return QVariant(); const QString mimeType = KrView::mimeTypeText(fileitem); return mimeType.isEmpty() ? QVariant() : mimeType; } case KrViewProperties::Modified: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getModificationTime()); } case KrViewProperties::Changed: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getChangeTime()); } case KrViewProperties::Accessed: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getAccessTime()); } case KrViewProperties::Permissions: { if (fileitem == _dummyFileItem) return QVariant(); return KrView::permissionsText(properties(), fileitem); } case KrViewProperties::KrPermissions: { if (fileitem == _dummyFileItem) return QVariant(); return KrView::krPermissionText(fileitem); } case KrViewProperties::Owner: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getOwner(); } case KrViewProperties::Group: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getGroup(); } default: return QString(); } return QVariant(); } case Qt::DecorationRole: { switch (index.column()) { case KrViewProperties::Name: { if (properties()->displayIcons) { if (_justForSizeHint) return QPixmap(_view->fileIconSize(), _view->fileIconSize()); return _view->getIcon(fileitem); } break; } default: break; } return QVariant(); } case Qt::TextAlignmentRole: { switch (index.column()) { case KrViewProperties::Size: return QVariant(Qt::AlignRight | Qt::AlignVCenter); default: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); } return QVariant(); } case Qt::BackgroundRole: case Qt::ForegroundRole: { KrColorItemType colorItemType; colorItemType.m_activePanel = _view->isFocused(); int actRow = index.row(); if (_alternatingTable) { int itemNum = _view->itemsPerPage(); if (itemNum == 0) itemNum++; if ((itemNum & 1) == 0) actRow += (actRow / itemNum); } colorItemType.m_alternateBackgroundColor = (actRow & 1); colorItemType.m_currentItem = _view->getCurrentIndex().row() == index.row(); colorItemType.m_selectedItem = _view->isSelected(index); if (fileitem->isSymLink()) { if (fileitem->isBrokenLink()) colorItemType.m_fileType = KrColorItemType::InvalidSymlink; else colorItemType.m_fileType = KrColorItemType::Symlink; } else if (fileitem->isDir()) colorItemType.m_fileType = KrColorItemType::Directory; else if (fileitem->isExecutable()) colorItemType.m_fileType = KrColorItemType::Executable; else colorItemType.m_fileType = KrColorItemType::File; KrColorGroup cols; KrColorCache::getColorCache().getColors(cols, colorItemType); if (colorItemType.m_selectedItem) { if (role == Qt::ForegroundRole) return cols.highlightedText(); else return cols.highlight(); } if (role == Qt::ForegroundRole) return cols.text(); else return cols.background(); } default: return QVariant(); } } bool ListModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (role == Qt::EditRole && index.isValid()) { if (index.row() < rowCount() && index.row() >= 0) { FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == nullptr) return false; _view->op()->emitRenameItem(fileitem->getName(), value.toString()); } } if (role == Qt::UserRole && index.isValid()) { _justForSizeHint = value.toBool(); } return QAbstractListModel::setData(index, value, role); } void ListModel::sort(int column, Qt::SortOrder order) { _view->sortModeUpdated(column, order); if(lastSortOrder() == KrViewProperties::NoColumn) return; emit layoutAboutToBeChanged(); QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); sorter.sort(); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); bool sortOrderChanged = false; QHash changeMap; for (int i = 0; i < sorter.items().count(); ++i) { const KrSort::SortProps *props = sorter.items()[i]; _fileItems.append(props->fileitem()); changeMap[ props->originalIndex() ] = i; if (i != props->originalIndex()) sortOrderChanged = true; updateIndices(props->fileitem(), i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) newPersistentList << index(changeMap[ mndx.row()], mndx.column()); changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); if (sortOrderChanged) _view->makeItemVisible(_view->getCurrentKrViewItem()); } QModelIndex ListModel::addItem(FileItem *fileitem) { emit layoutAboutToBeChanged(); if (lastSortOrder() == KrViewProperties::NoColumn) { int idx = _fileItems.count(); _fileItems.append(fileitem); updateIndices(fileitem, idx); emit layoutChanged(); return index(idx, 0); } QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); const bool isDummy = fileitem == _dummyFileItem; const int insertIndex = sorter.insertIndex(fileitem, isDummy, customSortData(fileitem)); if (insertIndex != _fileItems.count()) _fileItems.insert(insertIndex, fileitem); else _fileItems.append(fileitem); for (int i = insertIndex; i < _fileItems.count(); ++i) { updateIndices(_fileItems[i], i); } QModelIndexList newPersistentList; foreach (const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow >= insertIndex) newRow++; newPersistentList << index(newRow, mndx.column()); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); return index(insertIndex, 0); } void ListModel::removeItem(FileItem *fileItem) { const int rowToRemove = _fileItems.indexOf(fileItem); if (rowToRemove < 0) return; - emit layoutAboutToBeChanged(); + beginRemoveRows(QModelIndex(), rowToRemove, rowToRemove); _fileItems.removeAt(rowToRemove); _fileItemNdx.remove(fileItem); _nameNdx.remove(fileItem->getName()); _urlNdx.remove(fileItem->getUrl()); - // update indices for fileItems following fileitem + + // update indices for fileItems following the removed fileitem for (int i = rowToRemove; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } - const QModelIndexList oldPersistentList = persistentIndexList(); - QModelIndexList newPersistentList; - foreach (const QModelIndex &mndx, oldPersistentList) { - int newRow = mndx.row(); - if (newRow > rowToRemove) - newRow--; - if (newRow != rowToRemove) - newPersistentList << index(newRow, mndx.column()); - else - newPersistentList << QModelIndex(); - } - changePersistentIndexList(oldPersistentList, newPersistentList); - emit layoutChanged(); + endRemoveRows(); } QVariant ListModel::headerData(int section, Qt::Orientation orientation, int role) const { // ignore anything that's not display, and not horizontal if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); switch (section) { case KrViewProperties::Name: return i18nc("File property", "Name"); case KrViewProperties::Ext: return i18nc("File property", "Ext"); case KrViewProperties::Size: return i18nc("File property", "Size"); case KrViewProperties::Type: return i18nc("File property", "Type"); case KrViewProperties::Modified: return i18nc("File property", "Modified"); case KrViewProperties::Changed: return i18nc("File property", "Changed"); case KrViewProperties::Accessed: return i18nc("File property", "Accessed"); case KrViewProperties::Permissions: return i18nc("File property", "Perms"); case KrViewProperties::KrPermissions: return i18nc("File property", "rwx"); case KrViewProperties::Owner: return i18nc("File property", "Owner"); case KrViewProperties::Group: return i18nc("File property", "Group"); } return QString(); } const KrViewProperties *ListModel::properties() const { return _view->properties(); } FileItem *ListModel::fileItemAt(const QModelIndex &index) { if (!index.isValid() || index.row() < 0 || index.row() >= _fileItems.count()) return nullptr; return _fileItems[ index.row()]; } const QModelIndex & ListModel::fileItemIndex(const FileItem *fileitem) { return _fileItemNdx[ (FileItem *) fileitem ]; } const QModelIndex & ListModel::nameIndex(const QString & st) { return _nameNdx[ st ]; } Qt::ItemFlags ListModel::flags(const QModelIndex & index) const { Qt::ItemFlags flags = QAbstractListModel::flags(index); if (!index.isValid()) return flags; if (index.row() >= rowCount()) return flags; FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == _dummyFileItem) { flags = (flags & (~Qt::ItemIsSelectable)) | Qt::ItemIsDropEnabled; } else flags = flags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; return flags; } Qt::SortOrder ListModel::lastSortDir() const { return (properties()->sortOptions & KrViewProperties::Descending) ? Qt::DescendingOrder : Qt::AscendingOrder; } int ListModel::lastSortOrder() const { return properties()->sortColumn; } QString ListModel::nameWithoutExtension(const FileItem *fileItem, bool checkEnabled) const { if ((checkEnabled && !_extensionEnabled) || fileItem->isDir()) return fileItem->getName(); // check if the file has an extension const QString& fileItemName = fileItem->getName(); int loc = fileItemName.lastIndexOf('.'); // avoid mishandling of .bashrc and friend // and virtfs / search result names like "/dir/.file" which would become "/dir/" if (loc > 0 && fileItemName.lastIndexOf('/') < loc) { // check if it has one of the predefined 'atomic extensions' for (const auto & atomicExtension : properties()->atomicExtensions) { if (fileItemName.endsWith(atomicExtension) && fileItemName != atomicExtension) { loc = fileItemName.length() - atomicExtension.length(); break; } } } else return fileItemName; return fileItemName.left(loc); } const QModelIndex &ListModel::indexFromUrl(const QUrl &url) { return _urlNdx[url]; } KrSort::Sorter ListModel::createSorter() { KrSort::Sorter sorter(_fileItems.count(), properties(), lessThanFunc(), greaterThanFunc()); for(int i = 0; i < _fileItems.count(); i++) sorter.addItem(_fileItems[i], _fileItems[i] == _dummyFileItem, i, customSortData(_fileItems[i])); return sorter; } void ListModel::updateIndices(FileItem *file, int i) { _fileItemNdx[file] = index(i, 0); _nameNdx[file->getName()] = index(i, 0); _urlNdx[file->getUrl()] = index(i, 0); } QString ListModel::toolTipText(FileItem *fileItem) const { //"

"; // disable automatic word-wrap QString text = "" + fileItem->getName() + "


"; if (fileItem->getUISize() != (KIO::filesize_t)-1) { const QString size = KrView::sizeText(properties(), fileItem->getUISize()); text += i18n("Size: %1", size) + "
"; } text += i18nc("File property", "Type: %1", KrView::mimeTypeText(fileItem)); text += "
" + i18nc("File property", "Modified: %1", dateText(fileItem->getModificationTime())); text += "
" + i18nc("File property", "Changed: %1", dateText(fileItem->getChangeTime())); text += "
" + i18nc("File property", "Last Access: %1", dateText(fileItem->getAccessTime())); text += "
" + i18nc("File property", "Permissions: %1", KrView::permissionsText(properties(), fileItem)); text += "
" + i18nc("File property", "Owner: %1", fileItem->getOwner()); text += "
" + i18nc("File property", "Group: %1", fileItem->getGroup()); if (fileItem->isSymLink()) { KLocalizedString ls; if (fileItem->isBrokenLink()) ls = ki18nc("File property; broken symbolic link", "Link to: %1 - (broken)"); else ls = ki18nc("File property", "Link to: %1"); text += "
" + ls.subs(fileItem->getSymDest()).toString(); } return text; } QString ListModel::dateText(time_t time) { if (time == -1) { // unknown time return QString(); } struct tm* t = localtime((time_t *) & time); const QDateTime dateTime(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); return QLocale().toString(dateTime, QLocale::ShortFormat); }