diff --git a/krusader/Panel/krinterview.cpp b/krusader/Panel/krinterview.cpp index 6930bbcc..399d0353 100644 --- a/krusader/Panel/krinterview.cpp +++ b/krusader/Panel/krinterview.cpp @@ -1,375 +1,388 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * * * This program 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. * * * * This package 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 this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterview.h" #include "krcolorcache.h" #include "krmousehandler.h" #include "krpreviews.h" #include "krvfsmodel.h" #include "krviewitem.h" #include "../VFS/vfilecontainer.h" KrInterView::KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView) : KrView(instance, cfg), _itemView(itemView), _mouseHandler(0) { _model = new KrVfsModel(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(); _model->deleteLater(); _model = 0; delete _mouseHandler; _mouseHandler = 0; QHashIterator< vfile *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); } void KrInterView::selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) { vfile* vf1 = (vfile *)i1->getVfile(); QModelIndex mi1 = _model->vfileIndex(vf1); vfile* vf2 = (vfile *)i2->getVfile(); QModelIndex mi2 = _model->vfileIndex(vf2); 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->vfileAt(_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 vfile* vf, bool select) { if(select) _selection.insert(vf); else _selection.remove(vf); } bool KrInterView::isSelected(const QModelIndex &ndx) { return isSelected(_model->vfileAt(ndx)); } KrViewItem* KrInterView::findItemByName(const QString &name) { if (!_model->ready()) return 0; QModelIndex ndx = _model->nameIndex(name); if (!ndx.isValid()) return 0; return getKrViewItem(ndx); } QString KrInterView::getCurrentItem() const { if (!_model->ready()) return QString(); vfile *vf = _model->vfileAt(_itemView->currentIndex()); if (vf == 0) return QString(); return vf->vfile_getName(); } KrViewItem* KrInterView::getCurrentKrViewItem() { if (!_model->ready()) return 0; return getKrViewItem(_itemView->currentIndex()); } KrViewItem* KrInterView::getFirst() { if (!_model->ready()) return 0; return getKrViewItem(_model->index(0, 0, QModelIndex())); } KrViewItem* KrInterView::getLast() { if (!_model->ready()) return 0; return getKrViewItem(_model->index(_model->rowCount() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getNext(KrViewItem *current) { vfile* vf = (vfile *)current->getVfile(); QModelIndex ndx = _model->vfileIndex(vf); if (ndx.row() >= _model->rowCount() - 1) return 0; return getKrViewItem(_model->index(ndx.row() + 1, 0, QModelIndex())); } KrViewItem* KrInterView::getPrev(KrViewItem *current) { vfile* vf = (vfile *)current->getVfile(); QModelIndex ndx = _model->vfileIndex(vf); if (ndx.row() <= 0) return 0; return getKrViewItem(_model->index(ndx.row() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getKrViewItemAt(const QPoint &vp) { if (!_model->ready()) return 0; return getKrViewItem(_itemView->indexAt(vp)); } KrViewItem *KrInterView::findItemByVfile(vfile *vf) { return getKrViewItem(vf); } KrViewItem * KrInterView::getKrViewItem(vfile *vf) { QHash::iterator it = _itemHash.find(vf); if (it == _itemHash.end()) { KrViewItem * newItem = new KrViewItem(vf, this); _itemHash[ vf ] = newItem; return newItem; } return *it; } KrViewItem * KrInterView::getKrViewItem(const QModelIndex & ndx) { if (!ndx.isValid()) return 0; vfile * vf = _model->vfileAt(ndx); if (vf == 0) return 0; else return getKrViewItem(vf); } void KrInterView::makeCurrentVisible() { _itemView->scrollTo(_itemView->currentIndex()); } void KrInterView::makeItemVisible(const KrViewItem *item) { if (item == 0) return; vfile* vf = (vfile *)item->getVfile(); QModelIndex ndx = _model->vfileIndex(vf); if (ndx.isValid()) _itemView->scrollTo(ndx); } bool KrInterView::isItemVisible(const KrViewItem *item) { return _itemView->viewport()->rect().contains(item->itemRect()); } -void KrInterView::setCurrentItem(const QString& name) +void KrInterView::setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex) { + // find index by given name and set it as current QModelIndex ndx = _model->nameIndex(name); - if (ndx.isValid()) + if (ndx.isValid()) { // also sets the scrolling position _itemView->setCurrentIndex(ndx); + } 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()); + } else { + _itemView->setCurrentIndex(fallbackToIndex); + } + } else { + // when given parameters fail, set the first item as current + setCurrentKrViewItem(getFirst()); + } } void KrInterView::setCurrentKrViewItem(KrViewItem *item) { if (item == 0) { _itemView->setCurrentIndex(QModelIndex()); return; } vfile* vf = (vfile *)item->getVfile(); QModelIndex ndx = _model->vfileIndex(vf); if (ndx.isValid() && ndx.row() != _itemView->currentIndex().row()) { _mouseHandler->cancelTwoClickRename(); _itemView->setCurrentIndex(ndx); } } void KrInterView::sort() { _model->sort(); } void KrInterView::clear() { _selection.clear(); _itemView->clearSelection(); _itemView->setCurrentIndex(QModelIndex()); _model->clear(); QHashIterator< vfile *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); KrView::clear(); } void KrInterView::populate(const QList &vfiles, vfile *dummy) { _model->populate(vfiles, dummy); } KrViewItem* KrInterView::preAddItem(vfile *vf) { QModelIndex idx = _model->addItem(vf); if(_model->rowCount() == 1) // if this is the fist item to be added, make it current _itemView->setCurrentIndex(idx); return getKrViewItem(idx); } void KrInterView::preDelItem(KrViewItem *item) { setSelected(item->getVfile(), false); QModelIndex ndx = _model->removeItem((vfile *)item->getVfile()); if (ndx.isValid()) _itemView->setCurrentIndex(ndx); _itemHash.remove((vfile *)item->getVfile()); } void KrInterView::preUpdateItem(vfile *vf) { _model->updateItem(vf); } void KrInterView::prepareForActive() { KrView::prepareForActive(); _itemView->setFocus(); KrViewItem * current = getCurrentKrViewItem(); if (current != 0) { QString desc = current->description(); op()->emitItemDescription(desc); } } void KrInterView::prepareForPassive() { KrView::prepareForPassive(); _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::showContextMenu(const QPoint &point) { showContextMenu(_itemView->viewport()->mapToGlobal(point)); } 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(vfile *vf, _model->vfiles()) { size += vf->vfile_getSize(); } return size; } KIO::filesize_t KrInterView::calcSelectedSize() { KIO::filesize_t size = 0; foreach(const vfile *vf, _selection) { size += vf->vfile_getSize(); } return size; } QList KrInterView::selectedUrls() { QList list; foreach(const vfile *vf, _selection) { list << vf->vfile_getUrl(); } return list; } void KrInterView::setSelectionUrls(const QList urls) { op()->setMassSelectionUpdate(true); _selection.clear(); foreach(const QUrl &url, urls) { QModelIndex idx = _model->indexFromUrl(url); if(idx.isValid()) setSelected(_model->vfileAt(idx), true); } op()->setMassSelectionUpdate(false); } diff --git a/krusader/Panel/krinterview.h b/krusader/Panel/krinterview.h index 391d0199..86e39f5b 100644 --- a/krusader/Panel/krinterview.h +++ b/krusader/Panel/krinterview.h @@ -1,119 +1,119 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * * * This program 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. * * * * This package 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 this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRINTERVIEW_H #define KRINTERVIEW_H // QtCore #include // QtWidgets #include #include "krview.h" class KrVfsModel; class KrMouseHandler; class KrViewItem; /** * @brief Abstract intermediate class between KrView and full view implementations. * * It contains the methods common to all implementing subclasses of KrView. */ class KrInterView : public KrView { friend class KrViewItem; public: KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView); virtual ~KrInterView(); virtual QModelIndex getCurrentIndex() Q_DECL_OVERRIDE { return _itemView->currentIndex(); } virtual bool isSelected(const QModelIndex &ndx) Q_DECL_OVERRIDE; virtual uint numSelected() const Q_DECL_OVERRIDE { return _selection.count(); } virtual QList selectedUrls() Q_DECL_OVERRIDE; virtual void setSelectionUrls(const QList urls) Q_DECL_OVERRIDE; virtual KrViewItem* getFirst() Q_DECL_OVERRIDE; virtual KrViewItem* getLast() Q_DECL_OVERRIDE; virtual KrViewItem* getNext(KrViewItem *current) Q_DECL_OVERRIDE; virtual KrViewItem* getPrev(KrViewItem *current) Q_DECL_OVERRIDE; virtual KrViewItem* getCurrentKrViewItem() Q_DECL_OVERRIDE; virtual KrViewItem* findItemByName(const QString &name) Q_DECL_OVERRIDE; virtual KrViewItem *findItemByVfile(vfile *vf) Q_DECL_OVERRIDE; virtual QString getCurrentItem() const Q_DECL_OVERRIDE; virtual KrViewItem* getKrViewItemAt(const QPoint &vp) Q_DECL_OVERRIDE; - virtual void setCurrentItem(const QString& name) Q_DECL_OVERRIDE; + virtual void setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex=QModelIndex()) Q_DECL_OVERRIDE; virtual void setCurrentKrViewItem(KrViewItem *item) Q_DECL_OVERRIDE; virtual void makeItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; virtual bool isItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; virtual void clear() Q_DECL_OVERRIDE; virtual void sort() Q_DECL_OVERRIDE; virtual void refreshColors() Q_DECL_OVERRIDE; virtual void redraw() Q_DECL_OVERRIDE; virtual void prepareForActive() Q_DECL_OVERRIDE; virtual void prepareForPassive() Q_DECL_OVERRIDE; virtual void showContextMenu(const QPoint & point = QPoint(0,0)) Q_DECL_OVERRIDE; virtual void selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) Q_DECL_OVERRIDE; void sortModeUpdated(int column, Qt::SortOrder order); void redrawItem(vfile *vf) { _itemView->viewport()->update(itemRect(vf)); } protected: class DummySelectionModel : public QItemSelectionModel { public: DummySelectionModel(QAbstractItemModel *model, QObject *parent) : QItemSelectionModel(model, parent) {} // do nothing - selection is managed by KrInterView virtual void select (const QModelIndex & index, QItemSelectionModel::SelectionFlags command) Q_DECL_OVERRIDE { Q_UNUSED(index); Q_UNUSED(command); } virtual void select(const QItemSelection & selection, QItemSelectionModel::SelectionFlags command) Q_DECL_OVERRIDE { Q_UNUSED(selection); Q_UNUSED(command); } }; virtual KIO::filesize_t calcSize() Q_DECL_OVERRIDE; virtual KIO::filesize_t calcSelectedSize() Q_DECL_OVERRIDE; virtual void populate(const QList &vfiles, vfile *dummy) Q_DECL_OVERRIDE; virtual KrViewItem* preAddItem(vfile *vf) Q_DECL_OVERRIDE; virtual void preDelItem(KrViewItem *item) Q_DECL_OVERRIDE; virtual void preUpdateItem(vfile *vf) Q_DECL_OVERRIDE; virtual void intSetSelected(const vfile* vf, bool select) Q_DECL_OVERRIDE; virtual QRect itemRect(const vfile *vf) = 0; KrViewItem * getKrViewItem(vfile *vf); KrViewItem * getKrViewItem(const QModelIndex &); bool isSelected(const vfile *vf) const { return _selection.contains(vf); } void makeCurrentVisible(); KrVfsModel *_model; QAbstractItemView *_itemView; KrMouseHandler *_mouseHandler; QHash _itemHash; QSet _selection; }; #endif diff --git a/krusader/Panel/krview.cpp b/krusader/Panel/krview.cpp index 5f4af1a6..a89f4b53 100644 --- a/krusader/Panel/krview.cpp +++ b/krusader/Panel/krview.cpp @@ -1,1199 +1,1200 @@ /*************************************************************************** krview.cpp ------------------- copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program 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. * * * ***************************************************************************/ #include "krview.h" #include "viewactions.h" #include "krviewfactory.h" #include "krviewitem.h" #include "krselectionmode.h" #include "krcolorcache.h" #include "krpreviews.h" #include "../kicons.h" #include "../krglobal.h" #include "../defaults.h" #include "../VFS/krpermhandler.h" #include "../VFS/vfilecontainer.h" #include "../Filter/filterdialog.h" // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include #include #include #define VF getVfile() KrView *KrViewOperator::_changedView = 0; KrViewProperties::PropertyType KrViewOperator::_changedProperties = KrViewProperties::NoProperty; // ----------------------------- operator KrViewOperator::KrViewOperator(KrView *view, QWidget *widget) : _view(view), _widget(widget), _massSelectionUpdate(false) { _saveDefaultSettingsTimer.setSingleShot(true); connect(&_saveDefaultSettingsTimer, SIGNAL(timeout()), SLOT(saveDefaultSettings())); } KrViewOperator::~KrViewOperator() { if(_changedView == _view) saveDefaultSettings(); } void KrViewOperator::startUpdate() { _view->refresh(); } void KrViewOperator::cleared() { _view->clear(); } void KrViewOperator::fileAdded(vfile *vf) { _view->addItem(vf); } void KrViewOperator::fileUpdated(vfile *vf) { _view->updateItem(vf); } void KrViewOperator::startDrag() { QStringList items; _view->getSelectedItems(&items); if (items.empty()) return ; // don't drag an empty thing QPixmap px; if (items.count() > 1 || _view->getCurrentKrViewItem() == 0) px = FL_LOADICON("queue"); // how much are we dragging else px = _view->getCurrentKrViewItem() ->icon(); emit letsDrag(items, px); } bool KrViewOperator::searchItem(const QString &text, bool caseSensitive, int direction) { KrViewItem * item = _view->getCurrentKrViewItem(); if (!item) { return false; } QRegExp rx(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); if (!direction) { if (rx.indexIn(item->name()) == 0) { return true; } direction = 1; } KrViewItem * startItem = item; while (true) { item = (direction > 0) ? _view->getNext(item) : _view->getPrev(item); if (!item) item = (direction > 0) ? _view->getFirst() : _view->getLast(); if (item == startItem) { return false; } if (rx.indexIn(item->name()) == 0) { _view->setCurrentKrViewItem(item); _view->makeItemVisible(item); return true; } } } bool KrViewOperator::filterSearch(const QString &text, bool caseSensitive) { _view->_quickFilterMask = QRegExp(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); _view->refresh(); return _view->_count || !_view->_files->numVfiles(); } void KrViewOperator::setMassSelectionUpdate(bool upd) { _massSelectionUpdate = upd; if (!upd) { emit selectionChanged(); _view->redraw(); } } void KrViewOperator::settingsChanged(KrViewProperties::PropertyType properties) { if(_view->_updateDefaultSettings) { if(_changedView != _view) saveDefaultSettings(); _changedView = _view; _changedProperties = static_cast(_changedProperties | properties); _saveDefaultSettingsTimer.start(100); } } void KrViewOperator::saveDefaultSettings() { _saveDefaultSettingsTimer.stop(); if(_changedView) _changedView->saveDefaultSettings(_changedProperties); _changedProperties = KrViewProperties::NoProperty; _changedView = 0; } // ----------------------------- krview const KrView::IconSizes KrView::iconSizes; KrView::KrView(KrViewInstance &instance, KConfig *cfg) : _instance(instance), _files(0), _config(cfg), _mainWindow(0), _widget(0), _nameToMakeCurrent(QString()), _properties(0), _focused(false), _previews(0), _fileIconSize(0), _updateDefaultSettings(false), _count(0), _numDirs(0), _dummyVfile(0) { } KrView::~KrView() { _instance.m_objects.removeOne(this); delete _previews; _previews = 0; delete _dummyVfile; _dummyVfile = 0; if (_properties) qFatal("A class inheriting KrView didn't delete _properties!"); if (_operator) qFatal("A class inheriting KrView didn't delete _operator!"); } void KrView::init() { // sanity checks: if (!_widget) qFatal("_widget must be set during construction of KrView inheritors"); // ok, continue initProperties(); _operator = createOperator(); setup(); restoreDefaultSettings(); KConfigGroup grp(_config, _instance.name()); enableUpdateDefaultSettings(true); _instance.m_objects.append(this); } void KrView::initProperties() { _properties = createViewProperties(); KConfigGroup grpSvr(_config, "Look&Feel"); KConfigGroup grpInstance(_config, _instance.name()); _properties->displayIcons = grpInstance.readEntry("With Icons", _WithIcons); _properties->numericPermissions = grpSvr.readEntry("Numeric permissions", _NumericPermissions); int sortOptions = _properties->sortOptions; if (grpSvr.readEntry("Show Directories First", true)) sortOptions |= KrViewProperties::DirsFirst; if(grpSvr.readEntry("Always sort dirs by name", false)) sortOptions |= KrViewProperties::AlwaysSortDirsByName; if (!grpSvr.readEntry("Case Sensative Sort", _CaseSensativeSort)) sortOptions |= KrViewProperties::IgnoreCase; if (grpSvr.readEntry("Locale Aware Sort", true)) sortOptions |= KrViewProperties::LocaleAwareSort; _properties->sortOptions = static_cast(sortOptions); _properties->sortMethod = static_cast( grpSvr.readEntry("Sort method", (int) _DefaultSortMethod)); _properties->humanReadableSize = grpSvr.readEntry("Human Readable Size", _HumanReadableSize); _properties->localeAwareCompareIsCaseSensitive = QString("a").localeAwareCompare("B") > 0; // see KDE bug #40131 QStringList defaultAtomicExtensions; defaultAtomicExtensions += ".tar.gz"; defaultAtomicExtensions += ".tar.bz2"; defaultAtomicExtensions += ".tar.lzma"; defaultAtomicExtensions += ".tar.xz"; defaultAtomicExtensions += ".moc.cpp"; QStringList atomicExtensions = grpSvr.readEntry("Atomic Extensions", defaultAtomicExtensions); for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end();) { QString & ext = *i; ext = ext.trimmed(); if (!ext.length()) { i = atomicExtensions.erase(i); continue; } if (!ext.startsWith('.')) ext.insert(0, '.'); ++i; } _properties->atomicExtensions = atomicExtensions; } void KrView::enableUpdateDefaultSettings(bool enable) { if(enable) { KConfigGroup grpStartup(_config, "Startup"); _updateDefaultSettings = grpStartup.readEntry("Update Default Panel Settings", _RememberPos) || grpStartup.readEntry("UI Save Settings", _UiSave); } else _updateDefaultSettings = false; } void KrView::showPreviews(bool show) { if(show) { if(!_previews) { _previews = new KrPreviews(this); _previews->update(); } } else { delete _previews; _previews = 0; } redraw(); // op()->settingsChanged(KrViewProperties::PropShowPreviews); op()->emitRefreshActions(); } void KrView::updatePreviews() { if(_previews) _previews->update(); } QPixmap KrView::processIcon(const QPixmap &icon, bool dim, const QColor & dimColor, int dimFactor, bool symlink) { QPixmap pixmap = icon; if (symlink) { const QStringList overlays = QStringList() << QString() << "emblem-symbolic-link"; KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); } if(!dim) return pixmap; QImage dimmed = pixmap.toImage(); QPainter p(&dimmed); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(0, 0, icon.width(), icon.height(), dimColor); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.setOpacity((qreal)dimFactor / (qreal)100); p.drawPixmap(0, 0, icon.width(), icon.height(), pixmap); return QPixmap::fromImage(dimmed, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); } QPixmap KrView::getIcon(vfile *vf, bool active, int size/*, KRListItem::cmpColor color*/) { // KConfigGroup ag( krConfig, "Advanced"); ////////////////////////////// QPixmap icon; QString icon_name = vf->vfile_getIcon(); QString cacheName; if(!size) size = _FilelistIconSize.toInt(); QColor dimColor; int dimFactor; bool dim = !active && KrColorCache::getColorCache().getDimSettings(dimColor, dimFactor); if (icon_name.isNull()) icon_name = ""; cacheName.append(QString::number(size)); if(vf->vfile_isSymLink()) cacheName.append("LINK_"); if(dim) cacheName.append("DIM_"); cacheName.append(icon_name); //QPixmapCache::setCacheLimit( ag.readEntry("Icon Cache Size",_IconCacheSize) ); // first try the cache if (!QPixmapCache::find(cacheName, icon)) { icon = processIcon(krLoader->loadIcon(icon_name, KIconLoader::Desktop, size), dim, dimColor, dimFactor, vf->vfile_isSymLink()); // insert it into the cache QPixmapCache::insert(cacheName, icon); } return icon; } QPixmap KrView::getIcon(vfile *vf) { if(_previews) { QPixmap icon; if(_previews->getPreview(vf, icon, _focused)) return icon; } return getIcon(vf, _focused, _fileIconSize); } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getItemsByMask(QString mask, QStringList* names, bool dirs, bool files) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if ((it->name() == "..") || !QDir::match(mask, it->name())) continue; // if we got here, than the item fits the mask if (it->getVfile()->vfile_isDir() && !dirs) continue; // do we need to skip folders? if (!it->getVfile()->vfile_isDir() && !files) continue; // do we need to skip files names->append(it->name()); } } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getSelectedItems(QStringList *names, bool ignoreJustFocused) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) names->append(it->name()); // if all else fails, take the current item if (!ignoreJustFocused) { QString item = getCurrentItem(); if (names->empty() && !item.isEmpty() && item != "..") { names->append(item); } } } void KrView::getSelectedKrViewItems(KrViewItemList *items) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) items->append(it); // if all else fails, take the current item QString item = getCurrentItem(); if (items->empty() && !item.isEmpty() && item != ".." && getCurrentKrViewItem() != 0) { items->append(getCurrentKrViewItem()); } } QString KrView::statistics() { KIO::filesize_t size = calcSize(); KIO::filesize_t selectedSize = calcSelectedSize(); QString tmp; KConfigGroup grp(_config, "Look&Feel"); if(grp.readEntry("Show Size In Bytes", false)) { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize in Bytes, \ %5=filesize of all items in folder,%6=filesize in Bytes", "%1 out of %2, %3 (%4) out of %5 (%6)", numSelected(), _count, KIO::convertSize(selectedSize), KRpermHandler::parseSize(selectedSize), KIO::convertSize(size), KRpermHandler::parseSize(size)); } else { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize of all items in folder", "%1 out of %2, %3 out of %4", numSelected(), _count, KIO::convertSize(selectedSize), KIO::convertSize(size)); } // notify if we're running a filtered view if (filter() != KrViewProperties::All) tmp = ">> [ " + filterMask().nameFilter() + " ] " + tmp; return tmp; } bool KrView::changeSelection(const KRQuery& filter, bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); return changeSelection(filter, select, grpSvr.readEntry("Mark Dirs", _MarkDirs), true); } bool KrView::changeSelection(const KRQuery& filter, bool select, bool includeDirs, bool makeVisible) { if (op()) op()->setMassSelectionUpdate(true); KrViewItem *temp = getCurrentKrViewItem(); KrViewItem *firstMatch = 0; for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getVfile()->vfile_isDir() && !includeDirs) continue; vfile * file = it->getMutableVfile(); // filter::match calls getMimetype which isn't const if (file == 0) continue; if (filter.match(file)) { it->setSelected(select); if (!firstMatch) firstMatch = it; } } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) { makeItemVisible(temp); } else if (makeVisible && firstMatch != 0) { // if no selected item is visible... KrViewItemList selectedItems; getSelectedKrViewItems(&selectedItems); bool anyVisible = false; for (KrViewItem *item : selectedItems) { if (isItemVisible(item)) { anyVisible = true; break; } } if (!anyVisible) { // ...scroll to fist selected item makeItemVisible(firstMatch); } } redraw(); return firstMatch != 0; // return if any file was selected } void KrView::invertSelection() { if (op()) op()->setMassSelectionUpdate(true); KConfigGroup grpSvr(_config, "Look&Feel"); bool markDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); KrViewItem *temp = getCurrentKrViewItem(); for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getVfile()->vfile_isDir() && !markDirs && !it->isSelected()) continue; it->setSelected(!it->isSelected()); } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) makeItemVisible(temp); } QString KrView::firstUnmarkedBelowCurrent() { if (getCurrentKrViewItem() == 0) return QString(); KrViewItem * iterator = getNext(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getNext(iterator); if (!iterator) { iterator = getPrev(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getPrev(iterator); } if (!iterator) return QString(); return iterator->name(); } void KrView::delItem(const QString &name) { KrViewItem *it = findItemByName(name); if(!it) return; if(_previews) _previews->deletePreview(it); preDelItem(it); if (it->VF->vfile_isDir()) { --_numDirs; } --_count; delete it; op()->emitSelectionChanged(); } void KrView::addItem(vfile *vf) { if (isFiltered(vf)) return; KrViewItem *item = preAddItem(vf); if (!item) return; // don't add it after all if(_previews) _previews->updatePreview(item); if (vf->vfile_isDir()) ++_numDirs; ++_count; if (item->name() == nameToMakeCurrent()) { setCurrentKrViewItem(item); // dictionary based - quick makeItemVisible(item); } op()->emitSelectionChanged(); } void KrView::updateItem(vfile *vf) { if (isFiltered(vf)) delItem(vf->vfile_getName()); else { preUpdateItem(vf); if(_previews) _previews->updatePreview(findItemByVfile(vf)); } op()->emitSelectionChanged(); } void KrView::clear() { if(_previews) _previews->clear(); _count = _numDirs = 0; delete _dummyVfile; _dummyVfile = 0; redraw(); } // good old dialog box void KrView::renameCurrentItem() { QString newName, fileName; KrViewItem *it = getCurrentKrViewItem(); if (it) fileName = it->name(); else return ; // quit if no current item available // don't allow anyone to rename .. if (fileName == "..") return ; bool ok = false; newName = QInputDialog::getText(_mainWindow, i18n("Rename"), i18n("Rename %1 to:", fileName), QLineEdit::Normal, fileName, &ok); // if the user canceled - quit if (!ok || newName == fileName) return ; op()->emitRenameItem(it->name(), newName); } bool KrView::handleKeyEvent(QKeyEvent *e) { bool res = handleKeyEventInt(e); // emit the new item description KrViewItem * current = getCurrentKrViewItem(); if (current != 0) { QString desc = current->description(); op()->emitItemDescription(desc); } return res; } bool KrView::handleKeyEventInt(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : { if (e->modifiers() & Qt::ControlModifier) // let the panel handle it e->ignore(); else { KrViewItem * i = getCurrentKrViewItem(); if (i == 0) return true; QString tmp = i->name(); op()->emitExecuted(tmp); } return true; } case Qt::Key_QuoteLeft : // Terminal Emulator bugfix if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitGoHome(); // ask krusader to move to the home directory } return true; case Qt::Key_Delete : // kill file op()->emitDeleteFiles(e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::ControlModifier); return true; case Qt::Key_Insert: { KrViewItem * i = getCurrentKrViewItem(); if (!i) return true; i->setSelected(!i->isSelected()); if (KrSelectionMode::getSelectionHandler()->insertMovesDown()) { KrViewItem * next = getNext(i); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); return true; } case Qt::Key_Space: { KrViewItem * viewItem = getCurrentKrViewItem(); if (viewItem != 0) { viewItem->setSelected(!viewItem->isSelected()); if (viewItem->name() != ".." && viewItem->getVfile()->vfile_isDir() && viewItem->getVfile()->vfile_getSize() <= 0 && KrSelectionMode::getSelectionHandler()->spaceCalculatesDiskSpace()) { op()->emitCalcSpace(viewItem); } if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) { KrViewItem * next = getNext(viewItem); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); } return true; } case Qt::Key_Backspace : // Terminal Emulator bugfix case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitDirUp(); // ask krusader to move up a directory } return true; // safety case Qt::Key_Right : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // just a normal click - do a lynx-like moving thing KrViewItem *i = getCurrentKrViewItem(); if (i) op()->emitGoInside(i->name()); } return true; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it - jump to the Location Bar e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getPrev(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // let the panel handle it - jump to command line e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getNext(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Home: { if (e->modifiers() & Qt::ShiftModifier) { /* Shift+Home */ bool select = true; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getLast(); KrViewItem *item = getFirst(); op()->setMassSelectionUpdate(true); while (item) { item->setSelected(select); if (item == pos) select = false; item = getNext(item); } op()->setMassSelectionUpdate(false); } KrViewItem * first = getFirst(); if (first) { setCurrentKrViewItem(first); makeItemVisible(first); } } return true; case Qt::Key_End: if (e->modifiers() & Qt::ShiftModifier) { bool select = false; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getFirst(); op()->setMassSelectionUpdate(true); KrViewItem *item = getFirst(); while (item) { if (item == pos) select = true; item->setSelected(select); item = getNext(item); } op()->setMassSelectionUpdate(false); } else { KrViewItem *last = getLast(); if (last) { setCurrentKrViewItem(last); makeItemVisible(last); } } return true; case Qt::Key_PageDown: { KrViewItem * current = getCurrentKrViewItem(); int downStep = itemsPerPage(); while (downStep != 0 && current) { KrViewItem * newCurrent = getNext(current); if (newCurrent == 0) break; current = newCurrent; downStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_PageUp: { KrViewItem * current = getCurrentKrViewItem(); int upStep = itemsPerPage(); while (upStep != 0 && current) { KrViewItem * newCurrent = getPrev(current); if (newCurrent == 0) break; current = newCurrent; upStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_Escape: e->ignore(); return true; // otherwise the selection gets lost??!?? // also it is needed by the panel case Qt::Key_A : // mark all if (e->modifiers() == Qt::ControlModifier) { //FIXME: shouldn't there also be a shortcut for unselecting everything ? selectAllIncludingDirs(); return true; } // default continues here !!!!!!!!!!! default: return false; } return false; } void KrView::zoomIn() { int idx = iconSizes.indexOf(_fileIconSize); if(idx >= 0 && (idx+1) < iconSizes.count()) setFileIconSize(iconSizes[idx+1]); } void KrView::zoomOut() { int idx = iconSizes.indexOf(_fileIconSize); if(idx > 0) setFileIconSize(iconSizes[idx-1]); } void KrView::setFileIconSize(int size) { if(iconSizes.indexOf(size) < 0) return; _fileIconSize = size; if(_previews) { _previews->clear(); _previews->update(); } redraw(); op()->emitRefreshActions(); } int KrView::defaultFileIconSize() { KConfigGroup grpSvr(_config, _instance.name()); return grpSvr.readEntry("IconSize", _FilelistIconSize).toInt(); } void KrView::saveDefaultSettings(KrViewProperties::PropertyType properties) { saveSettings(KConfigGroup(_config, _instance.name()), properties); op()->emitRefreshActions(); } void KrView::restoreDefaultSettings() { restoreSettings(KConfigGroup(_config, _instance.name())); } void KrView::saveSettings(KConfigGroup group, KrViewProperties::PropertyType properties) { if(properties & KrViewProperties::PropIconSize) group.writeEntry("IconSize", fileIconSize()); if(properties & KrViewProperties::PropShowPreviews) group.writeEntry("ShowPreviews", previewsShown()); if(properties & KrViewProperties::PropSortMode) saveSortMode(group); if(properties & KrViewProperties::PropFilter) { group.writeEntry("Filter", static_cast(_properties->filter)); group.writeEntry("FilterApplysToDirs", _properties->filterApplysToDirs); if(_properties->filterSettings.isValid()) _properties->filterSettings.save(KConfigGroup(&group, "FilterSettings")); } } void KrView::restoreSettings(KConfigGroup group) { bool tmp = _updateDefaultSettings; _updateDefaultSettings = false; doRestoreSettings(group); _updateDefaultSettings = tmp; refresh(); } void KrView::doRestoreSettings(KConfigGroup group) { restoreSortMode(group); setFileIconSize(group.readEntry("IconSize", defaultFileIconSize())); showPreviews(group.readEntry("ShowPreviews", false)); _properties->filter = static_cast(group.readEntry("Filter", static_cast(KrViewProperties::All))); _properties->filterApplysToDirs = group.readEntry("FilterApplysToDirs", false); _properties->filterSettings.load(KConfigGroup(&group, "FilterSettings")); _properties->filterMask = _properties->filterSettings.toQuery(); } void KrView::applySettingsToOthers() { for(int i = 0; i < _instance.m_objects.length(); i++) { KrView *view = _instance.m_objects[i]; if(this != view) { bool tmp = view->_updateDefaultSettings; view->_updateDefaultSettings = false; view->copySettingsFrom(this); view->_updateDefaultSettings = tmp; } } } void KrView::sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending) { if(sortColumn == _properties->sortColumn && descending == (bool) (_properties->sortOptions & KrViewProperties::Descending)) return; int options = _properties->sortOptions; if(descending) options |= KrViewProperties::Descending; else options &= ~KrViewProperties::Descending; _properties->sortColumn = sortColumn; _properties->sortOptions = static_cast(options); // op()->settingsChanged(KrViewProperties::PropSortMode); } void KrView::saveSortMode(KConfigGroup &group) { group.writeEntry("Sort Column", static_cast(_properties->sortColumn)); group.writeEntry("Descending Sort Order", _properties->sortOptions & KrViewProperties::Descending); } void KrView::restoreSortMode(KConfigGroup &group) { int column = group.readEntry("Sort Column", static_cast(KrViewProperties::Name)); bool isDescending = group.readEntry("Descending Sort Order", false); setSortMode(static_cast(column), isDescending); } QString KrView::krPermissionString(const vfile * vf) { QString tmp; switch (vf->vfile_isReadable()) { case ALLOWED_PERM: tmp+='r'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (vf->vfile_isWriteable()) { case ALLOWED_PERM: tmp+='w'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (vf->vfile_isExecutable()) { case ALLOWED_PERM: tmp+='x'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } return tmp; } bool KrView::isFiltered(vfile *vf) { if (_quickFilterMask.isValid() && _quickFilterMask.indexIn(vf->vfile_getName()) == -1) return true; bool filteredOut = false; bool isDir = vf->vfile_isDir(); if (!isDir || (isDir && properties()->filterApplysToDirs)) { switch (properties()->filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : if (!properties()->filterMask.match(vf)) filteredOut = true; break; case KrViewProperties::Dirs: if (!isDir) filteredOut = true; break; case KrViewProperties::Files: if (isDir) filteredOut = true; break; default: break; } } return filteredOut; } void KrView::setFiles(VfileContainer *files) { if(files != _files) { clear(); if(_files) QObject::disconnect(_files, 0, op(), 0); _files = files; } if(!_files) return; QObject::disconnect(_files, 0, op(), 0); QObject::connect(_files, SIGNAL(refreshDone(bool)), op(), SLOT(startUpdate())); QObject::connect(_files, SIGNAL(cleared()), op(), SLOT(cleared())); QObject::connect(_files, SIGNAL(addedVfile(vfile*)), op(), SLOT(fileAdded(vfile*))); QObject::connect(_files, SIGNAL(updatedVfile(vfile*)), op(), SLOT(fileUpdated(vfile*))); } void KrView::setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs) { _properties->filter = filter; _properties->filterSettings = customFilter; _properties->filterMask = customFilter.toQuery(); _properties->filterApplysToDirs = applyToDirs; refresh(); } void KrView::setFilter(KrViewProperties::FilterSpec filter) { KConfigGroup cfg(_config, "Look&Feel"); bool rememberSettings = cfg.readEntry("FilterDialogRemembersSettings", _FilterDialogRemembersSettings); bool applyToDirs = rememberSettings ? _properties->filterApplysToDirs : false; switch (filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : { FilterDialog dialog(_widget, i18n("Filter Files"), QStringList(i18n("Apply filter to folders")), false); dialog.checkExtraOption(i18n("Apply filter to folders"), applyToDirs); if(rememberSettings) dialog.applySettings(_properties->filterSettings); dialog.exec(); FilterSettings s(dialog.getSettings()); if(!s.isValid()) // if the user canceled - quit return; _properties->filterSettings = s; _properties->filterMask = s.toQuery(); applyToDirs = dialog.isExtraOptionChecked(i18n("Apply filter to folders")); } break; default: return; } _properties->filterApplysToDirs = applyToDirs; _properties->filter = filter; refresh(); } void KrView::customSelection(bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); bool includeDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); FilterDialog dialog(0, i18n("Select Files"), QStringList(i18n("Apply selection to folders")), false); dialog.checkExtraOption(i18n("Apply selection to folders"), includeDirs); dialog.exec(); KRQuery query = dialog.getQuery(); // if the user canceled - quit if (query.isNull()) return ; includeDirs = dialog.isExtraOptionChecked(i18n("Apply selection to folders")); changeSelection(query, select, includeDirs); } void KrView::refresh() { - QString current = getCurrentItem(); + QString currentItem = getCurrentItem(); QList selection = selectedUrls(); + QModelIndex currentIndex = getCurrentIndex(); clear(); if(!_files) return; QList vfiles; // if we are not at the root add the ".." entery if(!_files->isRoot()) { _dummyVfile = new vfile("..", 0, "drwxrwxrwx", 0, false, false, 0, 0, "", "", 0, -1); _dummyVfile->vfile_setIcon("go-up"); vfiles << _dummyVfile; } foreach(vfile *vf, _files->vfiles()) { if(!vf || isFiltered(vf)) continue; if(vf->vfile_isDir()) _numDirs++; _count++; vfiles << vf; } populate(vfiles, _dummyVfile); if(!selection.isEmpty()) setSelectionUrls(selection); if (!nameToMakeCurrent().isEmpty()) { setCurrentItem(nameToMakeCurrent()); setNameToMakeCurrent(""); - } else if (!current.isEmpty()) { - setCurrentItem(current); + } else if (!currentItem.isEmpty()) { + setCurrentItem(currentItem, currentIndex); } else { setCurrentKrViewItem(getFirst()); } updatePreviews(); redraw(); op()->emitSelectionChanged(); } void KrView::setSelected(const vfile* vf, bool select) { if(vf == _dummyVfile) return; if(select) clearSavedSelection(); intSetSelected(vf, select); } void KrView::saveSelection() { _savedSelection = selectedUrls(); op()->emitRefreshActions(); } void KrView::restoreSelection() { if(canRestoreSelection()) setSelectionUrls(_savedSelection); } void KrView::clearSavedSelection() { _savedSelection.clear(); op()->emitRefreshActions(); } void KrView::markSameBaseName() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("%1.*").arg(item->name(false))); changeSelection(query, true, false); } void KrView::markSameExtension() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("*.%1").arg(item->extension())); changeSelection(query, true, false); } diff --git a/krusader/Panel/krview.h b/krusader/Panel/krview.h index 4f7927e9..1e33fe9d 100644 --- a/krusader/Panel/krview.h +++ b/krusader/Panel/krview.h @@ -1,527 +1,527 @@ /*************************************************************************** krview.h ------------------- copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * This program 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. * * * ***************************************************************************/ #ifndef KRVIEW_H #define KRVIEW_H // QtCore #include #include #include #include #include #include // QtGui #include #include #include "../VFS/krquery.h" #include "../Filter/filtersettings.h" #define MAX_BRIEF_COLS 5 class KrView; class KrViewItem; class KrPreviews; class KrViewInstance; class VfileContainer; typedef QList KrViewItemList; // KrViewProperties // This class is an interface class between KrView and KrViewItem // In order for KrViewItem to be as independent as possible, KrView holds // an instance of this class, and fills it with the correct data. A reference // to this should be given to each KrViewItem, which then queries it for // information regarding how things should be displayed in the current view. // // Every property that the item needs to know about the view must be here! class KrViewProperties { public: KrViewProperties() : numericPermissions(false), displayIcons(false), sortColumn(Name), sortOptions(static_cast(0)), sortMethod(Alphabetical), filter(KrViewProperties::All), filterMask(KRQuery("*")), filterApplysToDirs(false), localeAwareCompareIsCaseSensitive(false), humanReadableSize(), numberOfColumns(1) {} enum PropertyType { NoProperty = 0x0, PropIconSize = 0x1, PropShowPreviews = 0x2, PropSortMode = 0x4, PropColumns = 0x8, PropFilter = 0x10, AllProperties = PropIconSize | PropShowPreviews | PropSortMode | PropColumns | PropFilter }; enum ColumnType { NoColumn = -1, Name = 0x0, Ext = 0x1, Size = 0x2, Type = 0x3, Modified = 0x4, Permissions = 0x5, KrPermissions = 0x6, Owner = 0x7, Group = 0x8, MAX_COLUMNS = 0x09 }; enum SortOptions { Descending = 0x200, DirsFirst = 0x400, IgnoreCase = 0x800, AlwaysSortDirsByName = 0x1000, LocaleAwareSort = 0x2000 }; enum SortMethod { Alphabetical = 0x1, AlphabeticalNumbers = 0x2, CharacterCode = 0x4, CharacterCodeNumbers = 0x8, Krusader = 0x10 }; enum FilterSpec { Dirs = 0x1, Files = 0x2, All = 0x3, Custom = 0x4 }; bool numericPermissions; // show full permission column as octal numbers bool displayIcons; // true if icons should be displayed in this view ColumnType sortColumn; SortOptions sortOptions; SortMethod sortMethod; // sort method for names and extensions FilterSpec filter; // what items to show (all, custom, exec) KRQuery filterMask; // what items to show (*.cpp, *.h etc) FilterSettings filterSettings; bool filterApplysToDirs; bool localeAwareCompareIsCaseSensitive; // mostly, it is not! depends on LC_COLLATE bool humanReadableSize; // display size as KB, MB or just as a long number QStringList atomicExtensions; // list of strings, which will be treated as one extension. Must start with a dot. int numberOfColumns; // the number of columns in the brief view }; // operator can handle two ways of doing things: // 1. if the view is a widget (inherits krview and klistview for example) // 2. if the view HAS A widget (a krview-son has a member of klistview) // this is done by specifying the view and the widget in the constructor, // even if they are actually the same object (specify it twice in that case) class KrViewOperator: public QObject { Q_OBJECT public: KrViewOperator(KrView *view, QWidget *widget); ~KrViewOperator(); KrView *view() const { return _view; } QWidget *widget() const { return _widget; } void startDrag(); void emitGotDrop(QDropEvent *e) { emit gotDrop(e); } void emitLetsDrag(QStringList items, QPixmap icon) { emit letsDrag(items, icon); } void emitItemDescription(QString &desc) { emit itemDescription(desc); } void emitContextMenu(const QPoint &point) { emit contextMenu(point); } void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); } void emitRenameItem(const QString &oldName, const QString &newName) { emit renameItem(oldName, newName); } void emitExecuted(const QString &name) { emit executed(name); } void emitGoInside(const QString &name) { emit goInside(name); } void emitNeedFocus() { emit needFocus(); } void emitMiddleButtonClicked(KrViewItem *item) { emit middleButtonClicked(item); } void emitCurrentChanged(KrViewItem *item) { emit currentChanged(item); } void emitPreviewJobStarted(KJob *job) { emit previewJobStarted(job); } void emitGoHome() { emit goHome(); } void emitDirUp() { emit dirUp(); } void emitDeleteFiles(bool reallyDelete) { emit deleteFiles(reallyDelete); } void emitCalcSpace(KrViewItem *item) { emit calcSpace(item); } void emitRefreshActions() { emit refreshActions(); } void emitGoBack() { emit goBack(); } void emitGoForward() { emit goForward(); } bool searchItem(const QString &, bool, int = 0); // search for item and set cursor bool filterSearch(const QString &, bool); // filter view items void setMassSelectionUpdate(bool upd); bool isMassSelectionUpdate() { return _massSelectionUpdate; } void settingsChanged(KrViewProperties::PropertyType properties); public slots: void emitSelectionChanged() { if (!_massSelectionUpdate) emit selectionChanged(); } signals: void selectionChanged(); void gotDrop(QDropEvent *e); void letsDrag(QStringList items, QPixmap icon); void itemDescription(QString &desc); void contextMenu(const QPoint &point); void emptyContextMenu(const QPoint& point); void renameItem(const QString &oldName, const QString &newName); void executed(const QString &name); void goInside(const QString &name); void needFocus(); void middleButtonClicked(KrViewItem *item); void currentChanged(KrViewItem *item); void previewJobStarted(KJob *job); void goHome(); void deleteFiles(bool reallyDelete); void dirUp(); void calcSpace(KrViewItem *item); void refreshActions(); void goBack(); void goForward(); protected slots: void saveDefaultSettings(); void startUpdate(); void cleared(); void fileAdded(vfile *vf); void fileUpdated(vfile *vf); protected: // never delete those KrView *_view; QWidget *_widget; private: bool _massSelectionUpdate; QTimer _saveDefaultSettingsTimer; static KrViewProperties::PropertyType _changedProperties; static KrView *_changedView; }; /**************************************************************************** * READ THIS FIRST: Using the view * * You always hold a pointer to KrView, thus you can only use functions declared * in this class. If you need something else, either this class is missing something * or you are ;-) * * The functions you'd usually want: * 1) getSelectedItems - returns all selected items, or (if none) the current item. * it never returns anything which includes the "..", and thus can return an empty list! * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems * 3) getCurrentItem, setCurrentItem - work with QString * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and * used to iterate through a list of items. note that getNext and getPrev accept a pointer * to the current item (used in detailedview for safe iterating), thus your loop should be: * for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; } * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString * * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!! */ class KrView { friend class KrViewItem; friend class KrViewOperator; public: class IconSizes : public QVector { public: IconSizes() : QVector() { *this << 12 << 16 << 22 << 32 << 48 << 64 << 128 << 256; } }; // instantiating a new view // 1. new KrView // 2. view->init() // notes: constructor does as little as possible, setup() does the rest. esp, note that // if you need something from operator or properties, move it into setup() virtual void init(); KrViewInstance *instance() { return &_instance; } static const IconSizes iconSizes; protected: virtual void initProperties(); virtual KrViewProperties * createViewProperties() { return new KrViewProperties(); } virtual KrViewOperator *createOperator() { return new KrViewOperator(this, _widget); } virtual void setup() = 0; /////////////////////////////////////////////////////// // Every view must implement the following functions // /////////////////////////////////////////////////////// public: // interview related functions virtual QModelIndex getCurrentIndex() { return QModelIndex(); } virtual bool isSelected(const QModelIndex &) { return false; } virtual bool ensureVisibilityAfterSelect() { return true; } virtual void selectRegion(KrViewItem *, KrViewItem *, bool) = 0; virtual uint numSelected() const = 0; virtual QList selectedUrls() = 0; virtual void setSelectionUrls(const QList urls) = 0; virtual KrViewItem *getFirst() = 0; virtual KrViewItem *getLast() = 0; virtual KrViewItem *getNext(KrViewItem *current) = 0; virtual KrViewItem *getPrev(KrViewItem *current) = 0; virtual KrViewItem *getCurrentKrViewItem() = 0; virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0; virtual KrViewItem *findItemByName(const QString &name) = 0; virtual KrViewItem *findItemByVfile(vfile *vf) = 0; virtual QString getCurrentItem() const = 0; - virtual void setCurrentItem(const QString& name) = 0; + virtual void setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex=QModelIndex()) = 0; virtual void setCurrentKrViewItem(KrViewItem *item) = 0; virtual void makeItemVisible(const KrViewItem *item) = 0; virtual bool isItemVisible(const KrViewItem *item) = 0; virtual void updateView() = 0; virtual void sort() = 0; virtual void refreshColors() = 0; virtual void redraw() = 0; virtual bool handleKeyEvent(QKeyEvent *e); virtual void prepareForActive() { _focused = true; } virtual void prepareForPassive() { _focused = false; } virtual void renameCurrentItem(); // Rename current item. returns immediately virtual int itemsPerPage() { return 0; } virtual void showContextMenu(const QPoint & point = QPoint(0,0)) = 0; protected: virtual KrViewItem *preAddItem(vfile *vf) = 0; virtual void preDelItem(KrViewItem *item) = 0; virtual void preUpdateItem(vfile *vf) = 0; virtual void copySettingsFrom(KrView *other) = 0; virtual void populate(const QList &vfiles, vfile *dummy) = 0; virtual void intSetSelected(const vfile* vf, bool select) = 0; virtual void updatePreviews(); virtual void clear(); virtual void addItem(vfile *vf); virtual void updateItem(vfile *vf); virtual void delItem(const QString &name); public: ////////////////////////////////////////////////////// // the following functions are already implemented, // // and normally - should NOT be re-implemented. // ////////////////////////////////////////////////////// virtual uint numFiles() const { return _count -_numDirs; } virtual uint numDirs() const { return _numDirs; } virtual uint count() const { return _count; } virtual void getSelectedItems(QStringList* names, bool ignoreJustFocused = false); virtual void getItemsByMask(QString mask, QStringList* names, bool dirs = true, bool files = true); virtual void getSelectedKrViewItems(KrViewItemList *items); virtual void selectAllIncludingDirs() { changeSelection(KRQuery("*"), true, true); } virtual void select(const KRQuery& filter = KRQuery("*")) { changeSelection(filter, true); } virtual void unselect(const KRQuery& filter = KRQuery("*")) { changeSelection(filter, false); } virtual void unselectAll() { changeSelection(KRQuery("*"), false, true); } virtual void invertSelection(); virtual QString nameToMakeCurrent() const { return _nameToMakeCurrent; } virtual void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; } virtual QString firstUnmarkedBelowCurrent(); virtual QString statistics(); virtual const KrViewProperties* properties() const { return _properties; } virtual KrViewOperator* op() const { return _operator; } virtual void showPreviews(bool show); virtual bool previewsShown() { return _previews != 0; } virtual void applySettingsToOthers(); virtual void setFiles(VfileContainer *files); virtual void refresh(); bool changeSelection(const KRQuery& filter, bool select); bool changeSelection(const KRQuery& filter, bool select, bool includeDirs, bool makeVisible = false); bool isFiltered(vfile *vf); void enableUpdateDefaultSettings(bool enable); void setSelected(const vfile* vf, bool select); ///////////////////////////////////////////////////////////// // the following functions have a default and minimalistic // // implementation, and may be re-implemented if needed // ///////////////////////////////////////////////////////////// virtual void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { sortModeUpdated(sortColumn, descending); } virtual const KRQuery& filterMask() const { return _properties->filterMask; } virtual KrViewProperties::FilterSpec filter() const { return _properties->filter; } virtual void setFilter(KrViewProperties::FilterSpec filter); virtual void setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs); virtual void customSelection(bool select); virtual int defaultFileIconSize(); virtual void setFileIconSize(int size); virtual void setDefaultFileIconSize() { setFileIconSize(defaultFileIconSize()); } virtual void zoomIn(); virtual void zoomOut(); // save this view's settings to be restored after restart virtual void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); inline QWidget *widget() { return _widget; } inline int fileIconSize() const { return _fileIconSize; } inline bool isFocused() const { return _focused; } QPixmap getIcon(vfile *vf); void setMainWindow(QWidget *mainWindow) { _mainWindow = mainWindow; } // save this view's settings as default for new views of this type void saveDefaultSettings(KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); // restore the default settings for this view type void restoreDefaultSettings(); // call this to restore this view's settings after restart void restoreSettings(KConfigGroup grp); void saveSelection(); void restoreSelection(); bool canRestoreSelection() { return !_savedSelection.isEmpty(); } void clearSavedSelection(); void markSameBaseName(); void markSameExtension(); // todo: what about selection modes ??? virtual ~KrView(); static QPixmap getIcon(vfile *vf, bool active, int size = 0); static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor & dimColor, int dimFactor, bool symlink); static QString krPermissionString(const vfile * vf); protected: KrView(KrViewInstance &instance, KConfig *cfg); virtual void doRestoreSettings(KConfigGroup grp); virtual KIO::filesize_t calcSize() = 0; virtual KIO::filesize_t calcSelectedSize() = 0; bool handleKeyEventInt(QKeyEvent *e); void sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending); void saveSortMode(KConfigGroup &group); void restoreSortMode(KConfigGroup &group); inline void setWidget(QWidget *w) { _widget = w; } KrViewInstance &_instance; VfileContainer *_files; KConfig *_config; QWidget *_mainWindow; QWidget *_widget; QList _savedSelection; QString _nameToMakeCurrent; KrViewProperties *_properties; KrViewOperator *_operator; bool _focused; KrPreviews *_previews; int _fileIconSize; bool _updateDefaultSettings; QRegExp _quickFilterMask; private: uint _count, _numDirs; vfile *_dummyVfile; }; #endif /* KRVIEW_H */