┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/kitemlistviewlayouter.cpp
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2012-04-11 16:06:18 +0200
committerPeter Penz <[email protected]>2012-04-11 16:08:32 +0200
commit6c3d9acbc22ea9463ba40ef84c9e8c8419dfacf3 (patch)
treee7ffd63acd5e28eb71a077f816a23534b06fcae2 /src/kitemviews/kitemlistviewlayouter.cpp
parentd9dbd3398a258d04ec4517fd13e795b437c869d6 (diff)
KItemViews: Internal directory restructuration
- Move all private headers from the kitemviews-directory into the 'private' subdirectory. - Get rid of DolphinDirLister and just use a directory-lister internally in KFileItemModel. - Minor interface-cleanups for signals
Diffstat (limited to 'src/kitemviews/kitemlistviewlayouter.cpp')
-rw-r--r--src/kitemviews/kitemlistviewlayouter.cpp630
1 files changed, 0 insertions, 630 deletions
diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp
deleted file mode 100644
index 405837d23..000000000
--- a/src/kitemviews/kitemlistviewlayouter.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Peter Penz <[email protected]> *
- * *
- * 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 program 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 program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
- ***************************************************************************/
-
-#include "kitemlistviewlayouter_p.h"
-
-#include "kitemmodelbase.h"
-#include "kitemlistsizehintresolver_p.h"
-
-#include <KDebug>
-
-// #define KITEMLISTVIEWLAYOUTER_DEBUG
-
-KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
- QObject(parent),
- m_dirty(true),
- m_visibleIndexesDirty(true),
- m_scrollOrientation(Qt::Vertical),
- m_size(),
- m_itemSize(128, 128),
- m_itemMargin(),
- m_headerHeight(0),
- m_model(0),
- m_sizeHintResolver(0),
- m_scrollOffset(0),
- m_maximumScrollOffset(0),
- m_itemOffset(0),
- m_maximumItemOffset(0),
- m_firstVisibleIndex(-1),
- m_lastVisibleIndex(-1),
- m_columnWidth(0),
- m_xPosInc(0),
- m_columnCount(0),
- m_groupItemIndexes(),
- m_groupHeaderHeight(0),
- m_groupHeaderMargin(0),
- m_itemInfos()
-{
-}
-
-KItemListViewLayouter::~KItemListViewLayouter()
-{
-}
-
-void KItemListViewLayouter::setScrollOrientation(Qt::Orientation orientation)
-{
- if (m_scrollOrientation != orientation) {
- m_scrollOrientation = orientation;
- m_dirty = true;
- }
-}
-
-Qt::Orientation KItemListViewLayouter::scrollOrientation() const
-{
- return m_scrollOrientation;
-}
-
-void KItemListViewLayouter::setSize(const QSizeF& size)
-{
- if (m_size != size) {
- m_size = size;
- m_dirty = true;
- }
-}
-
-QSizeF KItemListViewLayouter::size() const
-{
- return m_size;
-}
-
-void KItemListViewLayouter::setItemSize(const QSizeF& size)
-{
- if (m_itemSize != size) {
- m_itemSize = size;
- m_dirty = true;
- }
-}
-
-QSizeF KItemListViewLayouter::itemSize() const
-{
- return m_itemSize;
-}
-
-void KItemListViewLayouter::setItemMargin(const QSizeF& margin)
-{
- if (m_itemMargin != margin) {
- m_itemMargin = margin;
- m_dirty = true;
- }
-}
-
-QSizeF KItemListViewLayouter::itemMargin() const
-{
- return m_itemMargin;
-}
-
-void KItemListViewLayouter::setHeaderHeight(qreal height)
-{
- if (m_headerHeight != height) {
- m_headerHeight = height;
- m_dirty = true;
- }
-}
-
-qreal KItemListViewLayouter::headerHeight() const
-{
- return m_headerHeight;
-}
-
-void KItemListViewLayouter::setGroupHeaderHeight(qreal height)
-{
- if (m_groupHeaderHeight != height) {
- m_groupHeaderHeight = height;
- m_dirty = true;
- }
-}
-
-qreal KItemListViewLayouter::groupHeaderHeight() const
-{
- return m_groupHeaderHeight;
-}
-
-void KItemListViewLayouter::setGroupHeaderMargin(qreal margin)
-{
- if (m_groupHeaderMargin != margin) {
- m_groupHeaderMargin = margin;
- m_dirty = true;
- }
-}
-
-qreal KItemListViewLayouter::groupHeaderMargin() const
-{
- return m_groupHeaderMargin;
-}
-
-void KItemListViewLayouter::setScrollOffset(qreal offset)
-{
- if (m_scrollOffset != offset) {
- m_scrollOffset = offset;
- m_visibleIndexesDirty = true;
- }
-}
-
-qreal KItemListViewLayouter::scrollOffset() const
-{
- return m_scrollOffset;
-}
-
-qreal KItemListViewLayouter::maximumScrollOffset() const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- return m_maximumScrollOffset;
-}
-
-void KItemListViewLayouter::setItemOffset(qreal offset)
-{
- if (m_itemOffset != offset) {
- m_itemOffset = offset;
- m_visibleIndexesDirty = true;
- }
-}
-
-qreal KItemListViewLayouter::itemOffset() const
-{
- return m_itemOffset;
-}
-
-qreal KItemListViewLayouter::maximumItemOffset() const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- return m_maximumItemOffset;
-}
-
-void KItemListViewLayouter::setModel(const KItemModelBase* model)
-{
- if (m_model != model) {
- m_model = model;
- m_dirty = true;
- }
-}
-
-const KItemModelBase* KItemListViewLayouter::model() const
-{
- return m_model;
-}
-
-void KItemListViewLayouter::setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver)
-{
- if (m_sizeHintResolver != sizeHintResolver) {
- m_sizeHintResolver = sizeHintResolver;
- m_dirty = true;
- }
-}
-
-const KItemListSizeHintResolver* KItemListViewLayouter::sizeHintResolver() const
-{
- return m_sizeHintResolver;
-}
-
-int KItemListViewLayouter::firstVisibleIndex() const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- return m_firstVisibleIndex;
-}
-
-int KItemListViewLayouter::lastVisibleIndex() const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- return m_lastVisibleIndex;
-}
-
-QRectF KItemListViewLayouter::itemRect(int index) const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- if (index < 0 || index >= m_itemInfos.count()) {
- return QRectF();
- }
-
- if (m_scrollOrientation == Qt::Horizontal) {
- // Rotate the logical direction which is always vertical by 90°
- // to get the physical horizontal direction
- const QRectF& b = m_itemInfos[index].rect;
- QRectF bounds(b.y(), b.x(), b.height(), b.width());
- QPointF pos = bounds.topLeft();
- pos.rx() -= m_scrollOffset;
- bounds.moveTo(pos);
- return bounds;
- }
-
- QRectF bounds = m_itemInfos[index].rect;
- bounds.moveTo(bounds.topLeft() - QPointF(m_itemOffset, m_scrollOffset));
- return bounds;
-}
-
-QRectF KItemListViewLayouter::groupHeaderRect(int index) const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
-
- const QRectF firstItemRect = itemRect(index);
- QPointF pos = firstItemRect.topLeft();
- if (pos.isNull()) {
- return QRectF();
- }
-
- QSizeF size;
- if (m_scrollOrientation == Qt::Vertical) {
- pos.rx() = 0;
- pos.ry() -= m_groupHeaderHeight;
- size = QSizeF(m_size.width(), m_groupHeaderHeight);
- } else {
- pos.rx() -= m_itemMargin.width();
- pos.ry() = 0;
-
- // Determine the maximum width used in the
- // current column. As the scroll-direction is
- // Qt::Horizontal and m_itemRects is accessed directly,
- // the logical height represents the visual width.
- qreal width = minimumGroupHeaderWidth();
- const qreal y = m_itemInfos[index].rect.y();
- const int maxIndex = m_itemInfos.count() - 1;
- while (index <= maxIndex) {
- QRectF bounds = m_itemInfos[index].rect;
- if (bounds.y() != y) {
- break;
- }
-
- if (bounds.height() > width) {
- width = bounds.height();
- }
-
- ++index;
- }
-
- size = QSizeF(width, m_size.height());
- }
- return QRectF(pos, size);
-}
-
-int KItemListViewLayouter::itemColumn(int index) const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- if (index < 0 || index >= m_itemInfos.count()) {
- return -1;
- }
-
- return (m_scrollOrientation == Qt::Vertical)
- ? m_itemInfos[index].column
- : m_itemInfos[index].row;
-}
-
-int KItemListViewLayouter::itemRow(int index) const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- if (index < 0 || index >= m_itemInfos.count()) {
- return -1;
- }
-
- return (m_scrollOrientation == Qt::Vertical)
- ? m_itemInfos[index].row
- : m_itemInfos[index].column;
-}
-
-int KItemListViewLayouter::maximumVisibleItems() const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
-
- const int height = static_cast<int>(m_size.height());
- const int rowHeight = static_cast<int>(m_itemSize.height());
- int rows = height / rowHeight;
- if (height % rowHeight != 0) {
- ++rows;
- }
-
- return rows * m_columnCount;
-}
-
-bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
-{
- const_cast<KItemListViewLayouter*>(this)->doLayout();
- return m_groupItemIndexes.contains(itemIndex);
-}
-
-void KItemListViewLayouter::markAsDirty()
-{
- m_dirty = true;
-}
-
-
-#ifndef QT_NO_DEBUG
- bool KItemListViewLayouter::isDirty()
- {
- return m_dirty;
- }
-#endif
-
-void KItemListViewLayouter::doLayout()
-{
- if (m_dirty) {
-#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
- QElapsedTimer timer;
- timer.start();
-#endif
- m_visibleIndexesDirty = true;
-
- QSizeF itemSize = m_itemSize;
- QSizeF itemMargin = m_itemMargin;
- QSizeF size = m_size;
-
- const bool grouped = createGroupHeaders();
-
- const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
- if (horizontalScrolling) {
- // Flip everything so that the layout logically can work like having
- // a vertical scrolling
- itemSize.setWidth(m_itemSize.height());
- itemSize.setHeight(m_itemSize.width());
- itemMargin.setWidth(m_itemMargin.height());
- itemMargin.setHeight(m_itemMargin.width());
- size.setWidth(m_size.height());
- size.setHeight(m_size.width());
-
- if (grouped) {
- // In the horizontal scrolling case all groups are aligned
- // at the top, which decreases the available height. For the
- // flipped data this means that the width must be decreased.
- size.rwidth() -= m_groupHeaderHeight;
- }
- }
-
- m_columnWidth = itemSize.width() + itemMargin.width();
- const qreal widthForColumns = size.width() - itemMargin.width();
- m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
- m_xPosInc = itemMargin.width();
-
- const int itemCount = m_model->count();
- if (itemCount > m_columnCount && m_columnWidth >= 32) {
- // Apply the unused width equally to each column
- const qreal unusedWidth = widthForColumns - m_columnCount * m_columnWidth;
- if (unusedWidth > 0) {
- const qreal columnInc = unusedWidth / (m_columnCount + 1);
- m_columnWidth += columnInc;
- m_xPosInc += columnInc;
- }
- }
-
- int rowCount = itemCount / m_columnCount;
- if (itemCount % m_columnCount != 0) {
- ++rowCount;
- }
-
- m_itemInfos.reserve(itemCount);
-
- qreal y = m_headerHeight + itemMargin.height();
- int row = 0;
-
- int index = 0;
- while (index < itemCount) {
- qreal x = m_xPosInc;
- qreal maxItemHeight = itemSize.height();
-
- if (grouped) {
- if (horizontalScrolling) {
- // All group headers will always be aligned on the top and not
- // flipped like the other properties
- x += m_groupHeaderHeight;
- }
-
- if (m_groupItemIndexes.contains(index)) {
- // The item is the first item of a group.
- // Increase the y-position to provide space
- // for the group header.
- if (index > 0) {
- // Only add a margin if there has been added another
- // group already before
- y += m_groupHeaderMargin;
- } else if (!horizontalScrolling) {
- // The first group header should be aligned on top
- y -= itemMargin.height();
- }
-
- if (!horizontalScrolling) {
- y += m_groupHeaderHeight;
- }
- }
- }
-
- int column = 0;
- while (index < itemCount && column < m_columnCount) {
- qreal requiredItemHeight = itemSize.height();
- if (m_sizeHintResolver) {
- const QSizeF sizeHint = m_sizeHintResolver->sizeHint(index);
- const qreal sizeHintHeight = horizontalScrolling ? sizeHint.width() : sizeHint.height();
- if (sizeHintHeight > requiredItemHeight) {
- requiredItemHeight = sizeHintHeight;
- }
- }
-
- const QRectF bounds(x, y, itemSize.width(), requiredItemHeight);
- if (index < m_itemInfos.count()) {
- m_itemInfos[index].rect = bounds;
- m_itemInfos[index].column = column;
- m_itemInfos[index].row = row;
- } else {
- ItemInfo itemInfo;
- itemInfo.rect = bounds;
- itemInfo.column = column;
- itemInfo.row = row;
- m_itemInfos.append(itemInfo);
- }
-
- if (grouped && horizontalScrolling) {
- // When grouping is enabled in the horizontal mode, the header alignment
- // looks like this:
- // Header-1 Header-2 Header-3
- // Item 1 Item 4 Item 7
- // Item 2 Item 5 Item 8
- // Item 3 Item 6 Item 9
- // In this case 'requiredItemHeight' represents the column-width. We don't
- // check the content of the header in the layouter to determine the required
- // width, hence assure that at least a minimal width of 15 characters is given
- // (in average a character requires the halve width of the font height).
- //
- // TODO: Let the group headers provide a minimum width and respect this width here
- const qreal headerWidth = minimumGroupHeaderWidth();
- if (requiredItemHeight < headerWidth) {
- requiredItemHeight = headerWidth;
- }
- }
-
- maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
- x += m_columnWidth;
- ++index;
- ++column;
-
- if (grouped && m_groupItemIndexes.contains(index)) {
- // The item represents the first index of a group
- // and must aligned in the first column
- break;
- }
- }
-
- y += maxItemHeight + itemMargin.height();
- ++row;
- }
- if (m_itemInfos.count() > itemCount) {
- m_itemInfos.erase(m_itemInfos.begin() + itemCount,
- m_itemInfos.end());
- }
-
- if (itemCount > 0) {
- // Calculate the maximum y-range of the last row for m_maximumScrollOffset
- m_maximumScrollOffset = m_itemInfos.last().rect.bottom();
- const qreal rowY = m_itemInfos.last().rect.y();
-
- int index = m_itemInfos.count() - 2;
- while (index >= 0 && m_itemInfos[index].rect.bottom() >= rowY) {
- m_maximumScrollOffset = qMax(m_maximumScrollOffset, m_itemInfos[index].rect.bottom());
- --index;
- }
-
- m_maximumScrollOffset += itemMargin.height();
-
- m_maximumItemOffset = m_columnCount * m_columnWidth;
- } else {
- m_maximumScrollOffset = 0;
- m_maximumItemOffset = 0;
- }
-
-#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
- kDebug() << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
-#endif
- m_dirty = false;
- }
-
- updateVisibleIndexes();
-}
-
-void KItemListViewLayouter::updateVisibleIndexes()
-{
- if (!m_visibleIndexesDirty) {
- return;
- }
-
- Q_ASSERT(!m_dirty);
-
- if (m_model->count() <= 0) {
- m_firstVisibleIndex = -1;
- m_lastVisibleIndex = -1;
- m_visibleIndexesDirty = false;
- return;
- }
-
- const int maxIndex = m_model->count() - 1;
-
- // Calculate the first visible index that is fully visible
- int min = 0;
- int max = maxIndex;
- int mid = 0;
- do {
- mid = (min + max) / 2;
- if (m_itemInfos[mid].rect.top() < m_scrollOffset) {
- min = mid + 1;
- } else {
- max = mid - 1;
- }
- } while (min <= max);
-
- if (mid > 0) {
- // Include the row before the first fully visible index, as it might
- // be partly visible
- if (m_itemInfos[mid].rect.top() >= m_scrollOffset) {
- --mid;
- Q_ASSERT(m_itemInfos[mid].rect.top() < m_scrollOffset);
- }
-
- const qreal rowTop = m_itemInfos[mid].rect.top();
- while (mid > 0 && m_itemInfos[mid - 1].rect.top() == rowTop) {
- --mid;
- }
- }
- m_firstVisibleIndex = mid;
-
- // Calculate the last visible index that is (at least partly) visible
- const int visibleHeight = (m_scrollOrientation == Qt::Horizontal) ? m_size.width() : m_size.height();
- qreal bottom = m_scrollOffset + visibleHeight;
- if (m_model->groupedSorting()) {
- bottom += m_groupHeaderHeight;
- }
-
- min = m_firstVisibleIndex;
- max = maxIndex;
- do {
- mid = (min + max) / 2;
- if (m_itemInfos[mid].rect.y() <= bottom) {
- min = mid + 1;
- } else {
- max = mid - 1;
- }
- } while (min <= max);
-
- while (mid > 0 && m_itemInfos[mid].rect.y() > bottom) {
- --mid;
- }
- m_lastVisibleIndex = mid;
-
- m_visibleIndexesDirty = false;
-}
-
-bool KItemListViewLayouter::createGroupHeaders()
-{
- if (!m_model->groupedSorting()) {
- return false;
- }
-
- m_groupItemIndexes.clear();
-
- const QList<QPair<int, QVariant> > groups = m_model->groups();
- if (groups.isEmpty()) {
- return false;
- }
-
- for (int i = 0; i < groups.count(); ++i) {
- const int firstItemIndex = groups.at(i).first;
- m_groupItemIndexes.insert(firstItemIndex);
- }
-
- return true;
-}
-
-qreal KItemListViewLayouter::minimumGroupHeaderWidth() const
-{
- return 100;
-}
-
-#include "kitemlistviewlayouter_p.moc"