]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistview.cpp
Make sure that KItemListSizeHintResolver is always consistent
[dolphin.git] / src / kitemviews / kitemlistview.cpp
index 72b3fd8fcbfbaa43660fac359320c8227ade9063..2ea6657a5a91962b37a758f093186698a78f9ce7 100644 (file)
@@ -23,6 +23,7 @@
 #include "kitemlistview.h"
 
 #include <KDebug>
+#include "kitemlistcontainer.h"
 #include "kitemlistcontroller.h"
 #include "kitemlistheader.h"
 #include "kitemlistselectionmanager.h"
@@ -43,6 +44,8 @@
 #include <QStyleOptionRubberBand>
 #include <QTimer>
 
+#include "kitemlistviewaccessible.h"
+
 namespace {
     // Time in ms until reaching the autoscroll margin triggers
     // an initial autoscrolling
@@ -52,6 +55,21 @@ namespace {
     const int RepeatingAutoScrollDelay = 1000 / 60;
 }
 
+#ifndef QT_NO_ACCESSIBILITY
+QAccessibleInterface* accessibleInterfaceFactory(const QString &key, QObject *object)
+{
+    Q_UNUSED(key)
+
+    if (KItemListContainer* container = qobject_cast<KItemListContainer*>(object)) {
+        return new KItemListContainerAccessible(container);
+    } else if (KItemListView* view = qobject_cast<KItemListView*>(object)) {
+        return new KItemListViewAccessible(view);
+    }
+
+    return 0;
+}
+#endif
+
 KItemListView::KItemListView(QGraphicsWidget* parent) :
     QGraphicsWidget(parent),
     m_enabledSelectionToggles(false),
@@ -110,6 +128,11 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
     m_headerWidget->setVisible(false);
 
     m_header = new KItemListHeader(this);
+
+#ifndef QT_NO_ACCESSIBILITY
+    QAccessible::installFactory(accessibleInterfaceFactory);
+#endif
+
 }
 
 KItemListView::~KItemListView()
@@ -185,6 +208,11 @@ qreal KItemListView::maximumItemOffset() const
     return m_layouter->maximumItemOffset();
 }
 
+int KItemListView::maximumVisibleItems() const
+{
+    return m_layouter->maximumVisibleItems();
+}
+
 void KItemListView::setVisibleRoles(const QList<QByteArray>& roles)
 {
     const QList<QByteArray> previousRoles = m_visibleRoles;
@@ -365,6 +393,15 @@ void KItemListView::setGeometry(const QRectF& rect)
     }
 }
 
+qreal KItemListView::verticalPageStep() const
+{
+    qreal headerHeight = 0;
+    if (m_headerWidget->isVisible()) {
+        headerHeight = m_headerWidget->size().height();
+    }
+    return size().height() - headerHeight;
+}
+
 int KItemListView::itemAt(const QPointF& pos) const
 {
     QHashIterator<int, KItemListWidget*> it(m_visibleItems);
@@ -641,6 +678,16 @@ void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
     }
 }
 
+QVariant KItemListView::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+    if (change == QGraphicsItem::ItemSceneHasChanged && scene()) {
+        if (!scene()->views().isEmpty()) {
+            m_styleOption.palette = scene()->views().at(0)->palette();
+        }
+    }
+    return QGraphicsItem::itemChange(change, value);
+}
+
 void KItemListView::setItemSize(const QSizeF& size)
 {
     const QSizeF previousSize = m_itemSize;
@@ -911,6 +958,8 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
 
     m_layouter->markAsDirty();
 
+    m_sizeHintResolver->itemsInserted(itemRanges);
+
     int previouslyInsertedCount = 0;
     foreach (const KItemRange& range, itemRanges) {
         // range.index is related to the model before anything has been inserted.
@@ -924,8 +973,6 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
         }
         previouslyInsertedCount += count;
 
-        m_sizeHintResolver->itemsInserted(index, count);
-
         // Determine which visible items must be moved
         QList<int> itemsToMove;
         QHashIterator<int, KItemListWidget*> it(m_visibleItems);
@@ -983,12 +1030,6 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
     }
 
     if (hasMultipleRanges) {
-#ifndef QT_NO_DEBUG
-        // Important: Don't read any m_layouter-property inside the for-loop in case if
-        // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is
-        // updated in each loop-cycle and has only a consistent state after the loop.
-        Q_ASSERT(m_layouter->isDirty());
-#endif
         m_endTransactionAnimationHint = NoAnimation;
         endTransaction();
 
@@ -1027,6 +1068,8 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
         removedItemsCount += itemRanges[i].count;
     }
 
+    m_sizeHintResolver->itemsRemoved(itemRanges);
+
     for (int i = itemRanges.count() - 1; i >= 0; --i) {
         const KItemRange& range = itemRanges[i];
         const int index = range.index;
@@ -1036,8 +1079,6 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
             continue;
         }
 
-        m_sizeHintResolver->itemsRemoved(index, count);
-
         const int firstRemovedIndex = index;
         const int lastRemovedIndex = index + count - 1;
         const int lastIndex = m_model->count() - 1 + removedItemsCount;
@@ -1106,12 +1147,6 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
     }
 
     if (hasMultipleRanges) {
-#ifndef QT_NO_DEBUG
-        // Important: Don't read any m_layouter-property inside the for-loop in case if
-        // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is
-        // updated in each loop-cycle and has only a consistent state after the loop.
-        Q_ASSERT(m_layouter->isDirty());
-#endif
         m_endTransactionAnimationHint = NoAnimation;
         endTransaction();
         updateSiblingsInformation();
@@ -1189,6 +1224,7 @@ void KItemListView::slotItemsChanged(const KItemRangeList& itemRanges,
             doLayout(NoAnimation);
         }
     }
+    QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged);
 }
 
 void KItemListView::slotGroupedSortingChanged(bool current)
@@ -1251,6 +1287,7 @@ void KItemListView::slotCurrentChanged(int current, int previous)
     if (currentWidget) {
         currentWidget->setCurrent(true);
     }
+    QAccessible::updateAccessibility(this, current+1, QAccessible::Focus);
 }
 
 void KItemListView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous)
@@ -1413,9 +1450,9 @@ void KItemListView::triggerAutoScrolling()
     const qreal newScrollOffset = qMin(scrollOffset() + m_autoScrollIncrement, maxVisibleOffset);
     setScrollOffset(newScrollOffset);
 
-   // Trigger the autoscroll timer which will periodically call
-   // triggerAutoScrolling()
-   m_autoScrollTimer->start(RepeatingAutoScrollDelay);
+    // Trigger the autoscroll timer which will periodically call
+    // triggerAutoScrolling()
+    m_autoScrollTimer->start(RepeatingAutoScrollDelay);
 }
 
 void KItemListView::slotGeometryOfGroupHeaderParentChanged()
@@ -1429,12 +1466,16 @@ void KItemListView::slotGeometryOfGroupHeaderParentChanged()
 
 void KItemListView::slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value)
 {
+    disconnectRoleEditingSignals(index);
+
     emit roleEditingCanceled(index, role, value);
     m_editingRole = false;
 }
 
 void KItemListView::slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value)
 {
+    disconnectRoleEditingSignals(index);
+
     emit roleEditingFinished(index, role, value);
     m_editingRole = false;
 }
@@ -1484,9 +1525,9 @@ void KItemListView::setModel(KItemModelBase* model)
                    this,    SLOT(slotSortOrderChanged(Qt::SortOrder,Qt::SortOrder)));
         disconnect(m_model, SIGNAL(sortRoleChanged(QByteArray,QByteArray)),
                    this,    SLOT(slotSortRoleChanged(QByteArray,QByteArray)));
-    }
 
-    m_sizeHintResolver->clearCache();
+        m_sizeHintResolver->itemsRemoved(KItemRangeList() << KItemRange(0, m_model->count()));
+    }
 
     m_model = model;
     m_layouter->setModel(model);
@@ -1510,7 +1551,6 @@ void KItemListView::setModel(KItemModelBase* model)
 
         const int itemCount = m_model->count();
         if (itemCount > 0) {
-            m_sizeHintResolver->itemsInserted(0, itemCount);
             slotItemsInserted(KItemRangeList() << KItemRange(0, itemCount));
         }
     }
@@ -2319,7 +2359,8 @@ int KItemListView::showDropIndicator(const QPointF& pos)
         const QRectF rect = itemRect(widget->index());
         if (mappedPos.y() >= 0 && mappedPos.y() <= rect.height()) {
             if (m_model->supportsDropping(widget->index())) {
-                const int gap = qMax(4, m_styleOption.padding);
+                // Keep 30% of the rectangle as the gap instead of always having a fixed gap
+                const int gap = qMax(4.0, 0.3 * rect.height());
                 if (mappedPos.y() >= gap && mappedPos.y() <= rect.height() - gap) {
                     return -1;
                 }
@@ -2505,6 +2546,17 @@ bool KItemListView::hasSiblingSuccessor(int index) const
     return hasSuccessor;
 }
 
+void KItemListView::disconnectRoleEditingSignals(int index)
+{
+    KItemListWidget* widget = m_visibleItems.value(index);
+    if (!widget) {
+        return;
+    }
+
+    widget->disconnect(SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), this);
+    widget->disconnect(SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), this);
+}
+
 int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
 {
     int inc = 0;