/***************************************************************************
* Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
* *
- * Based on the Itemviews NG project from Trolltech Labs: *
- * http://qt.gitorious.org/qt-labs/itemviews-ng *
+ * Based on the Itemviews NG project from Trolltech Labs *
* *
* 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 *
#include "kitemlistview.h"
-#include <KDebug>
+#include "dolphindebug.h"
#include "kitemlistcontainer.h"
#include "kitemlistcontroller.h"
#include "kitemlistheader.h"
#include "kitemlistselectionmanager.h"
-#include "kitemlistwidget.h"
+#include "kitemlistviewaccessible.h"
+#include "kstandarditemlistwidget.h"
#include "private/kitemlistheaderwidget.h"
#include "private/kitemlistrubberband.h"
#include "private/kitemlistsizehintresolver.h"
#include "private/kitemlistviewlayouter.h"
-#include "private/kitemlistviewanimation.h"
-#include <QCursor>
+#include <QElapsedTimer>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
-#include <QPainter>
-#include <QPropertyAnimation>
-#include <QStyle>
#include <QStyleOptionRubberBand>
#include <QTimer>
-#include <algorithm>
-
-#if 0
-#include "kitemlistviewaccessible.h"
-#else
-#define QT_NO_ACCESSIBILITY 1
-#pragma message("TODO: port accessibility to Qt5")
-#endif
namespace {
// Time in ms until reaching the autoscroll margin triggers
}
#ifndef QT_NO_ACCESSIBILITY
-QAccessibleInterface* accessibleInterfaceFactory(const QString &key, QObject *object)
+QAccessibleInterface* accessibleInterfaceFactory(const QString& key, QObject* object)
{
Q_UNUSED(key)
return new KItemListViewAccessible(view);
}
- return 0;
+ return nullptr;
}
#endif
m_activeTransactions(0),
m_endTransactionAnimationHint(Animation),
m_itemSize(),
- m_controller(0),
- m_model(0),
+ m_controller(nullptr),
+ m_model(nullptr),
m_visibleRoles(),
- m_widgetCreator(0),
- m_groupHeaderCreator(0),
+ m_widgetCreator(nullptr),
+ m_groupHeaderCreator(nullptr),
m_styleOption(),
m_visibleItems(),
m_visibleGroups(),
m_visibleCells(),
- m_sizeHintResolver(0),
- m_layouter(0),
- m_animation(0),
- m_layoutTimer(0),
+ m_sizeHintResolver(nullptr),
+ m_layouter(nullptr),
+ m_animation(nullptr),
+ m_layoutTimer(nullptr),
m_oldScrollOffset(0),
m_oldMaximumScrollOffset(0),
m_oldItemOffset(0),
m_oldMaximumItemOffset(0),
m_skipAutoScrollForRubberBand(false),
- m_rubberBand(0),
+ m_rubberBand(nullptr),
m_mousePos(),
m_autoScrollIncrement(0),
- m_autoScrollTimer(0),
- m_header(0),
- m_headerWidget(0),
+ m_autoScrollTimer(nullptr),
+ m_header(nullptr),
+ m_headerWidget(nullptr),
m_dropIndicator()
{
setAcceptHoverEvents(true);
// widgetCreator(). So it is mandatory to delete the group headers
// first.
delete m_groupHeaderCreator;
- m_groupHeaderCreator = 0;
+ m_groupHeaderCreator = nullptr;
delete m_widgetCreator;
- m_widgetCreator = 0;
+ m_widgetCreator = nullptr;
delete m_sizeHintResolver;
- m_sizeHintResolver = 0;
+ m_sizeHintResolver = nullptr;
}
void KItemListView::setScrollOffset(qreal offset)
m_autoScrollTimer->start(InitialAutoScrollDelay);
} else if (!enabled && m_autoScrollTimer) {
delete m_autoScrollTimer;
- m_autoScrollTimer = 0;
+ m_autoScrollTimer = nullptr;
}
}
bool KItemListView::autoScroll() const
{
- return m_autoScrollTimer != 0;
+ return m_autoScrollTimer != nullptr;
}
void KItemListView::setEnabledSelectionToggles(bool enabled)
void KItemListView::setWidgetCreator(KItemListWidgetCreatorBase* widgetCreator)
{
- if (m_widgetCreator) {
- delete m_widgetCreator;
- }
+ delete m_widgetCreator;
m_widgetCreator = widgetCreator;
}
void KItemListView::setGroupHeaderCreator(KItemListGroupHeaderCreatorBase* groupHeaderCreator)
{
- if (m_groupHeaderCreator) {
- delete m_groupHeaderCreator;
- }
+ delete m_groupHeaderCreator;
m_groupHeaderCreator = groupHeaderCreator;
}
return false;
}
+bool KItemListView::isAboveText(int index, const QPointF &pos) const
+{
+ const KItemListWidget* widget = m_visibleItems.value(index);
+ if (widget) {
+ const QRectF &textRect = widget->textRect();
+ if (!textRect.isEmpty()) {
+ const QPointF mappedPos = widget->mapFromItem(this, pos);
+ return textRect.contains(mappedPos);
+ }
+ }
+ return false;
+}
+
int KItemListView::firstVisibleIndex() const
{
return m_layouter->firstVisibleIndex();
--m_activeTransactions;
if (m_activeTransactions < 0) {
m_activeTransactions = 0;
- kWarning() << "Mismatch between beginTransaction()/endTransaction()";
+ qCWarning(DolphinDebug) << "Mismatch between beginTransaction()/endTransaction()";
}
if (m_activeTransactions == 0) {
KItemListWidget* item = m_visibleItems.value(indexes.first());
QGraphicsView* graphicsView = scene()->views()[0];
if (item && graphicsView) {
- pixmap = item->createDragPixmap(0, graphicsView);
+ pixmap = item->createDragPixmap(nullptr, graphicsView);
}
} else {
// TODO: Not implemented yet. Probably extend the interface
void KItemListView::editRole(int index, const QByteArray& role)
{
- KItemListWidget* widget = m_visibleItems.value(index);
+ KStandardItemListWidget* widget = qobject_cast<KStandardItemListWidget *>(m_visibleItems.value(index));
if (!widget || m_editingRole) {
return;
}
this, &KItemListView::slotRoleEditingCanceled);
connect(widget, &KItemListWidget::roleEditingFinished,
this, &KItemListView::slotRoleEditingFinished);
+
+ connect(this, &KItemListView::scrollOffsetChanged,
+ widget, &KStandardItemListWidget::finishRoleEditing);
}
void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
}
QStyleOptionRubberBand opt;
- opt.initFrom(widget);
+ initStyleOption(&opt);
opt.shape = QRubberBand::Rectangle;
opt.opaque = false;
opt.rect = rubberBandRect.toRect();
if (!m_dropIndicator.isEmpty()) {
const QRectF r = m_dropIndicator.toRect();
- QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color();
+ QColor color = palette().brush(QPalette::Normal, QPalette::Text).color();
painter->setPen(color);
// TODO: The following implementation works only for a vertical scroll-orientation
void KItemListView::setStyleOption(const KItemListStyleOption& option)
{
+ if (m_styleOption == option) {
+ return;
+ }
+
const KItemListStyleOption previousOption = m_styleOption;
m_styleOption = option;
KItemListWidgetCreatorBase* KItemListView::defaultWidgetCreator() const
{
- return 0;
+ return nullptr;
}
KItemListGroupHeaderCreatorBase* KItemListView::defaultGroupHeaderCreator() const
{
- return 0;
+ return nullptr;
}
void KItemListView::initializeItemListWidget(KItemListWidget* item)
{
- Q_UNUSED(item);
+ Q_UNUSED(item)
}
bool KItemListView::itemSizeHintUpdateRequired(const QSet<QByteArray>& changedRoles) const
{
- Q_UNUSED(changedRoles);
+ Q_UNUSED(changedRoles)
return true;
}
void KItemListView::onControllerChanged(KItemListController* current, KItemListController* previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onScrollOffsetChanged(qreal current, qreal previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onVisibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
}
void KItemListView::onSupportsItemExpandingChanged(bool supportsExpanding)
{
- Q_UNUSED(supportsExpanding);
+ Q_UNUSED(supportsExpanding)
}
void KItemListView::onTransactionBegin()
setAutoScroll(true);
}
-void KItemListView::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+void KItemListView::dragMoveEvent(QGraphicsSceneDragDropEvent* event)
{
QGraphicsWidget::dragMoveEvent(event);
}
}
-void KItemListView::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+void KItemListView::dragLeaveEvent(QGraphicsSceneDragDropEvent* event)
{
QGraphicsWidget::dragLeaveEvent(event);
setAutoScroll(false);
const int index = range.index + previouslyInsertedCount;
const int count = range.count;
if (index < 0 || count <= 0) {
- kWarning() << "Invalid item range (index:" << index << ", count:" << count << ")";
+ qCWarning(DolphinDebug) << "Invalid item range (index:" << index << ", count:" << count << ")";
continue;
}
previouslyInsertedCount += count;
// Update the indexes of all KItemListWidget instances that are located
// after the inserted items. It is important to adjust the indexes in the order
// from the highest index to the lowest index to prevent overlaps when setting the new index.
- qSort(itemsToMove);
+ std::sort(itemsToMove.begin(), itemsToMove.end());
for (int i = itemsToMove.count() - 1; i >= 0; --i) {
KItemListWidget* widget = m_visibleItems.value(itemsToMove[i]);
Q_ASSERT(widget);
const int index = range.index;
const int count = range.count;
if (index < 0 || count <= 0) {
- kWarning() << "Invalid item range (index:" << index << ", count:" << count << ")";
+ qCWarning(DolphinDebug) << "Invalid item range (index:" << index << ", count:" << count << ")";
continue;
}
const int firstRemovedIndex = index;
const int lastRemovedIndex = index + count - 1;
- // Remeber which items have to be moved because they are behind the removed range.
+ // Remember which items have to be moved because they are behind the removed range.
QVector<int> itemsToMove;
// Remove all KItemListWidget instances that got deleted
updateVisibleGroupHeaders();
doLayout(NoAnimation);
}
+
+ QAccessibleTableModelChangeEvent ev(this, QAccessibleTableModelChangeEvent::DataChanged);
+ ev.setFirstRow(itemRange.index);
+ ev.setLastRow(itemRange.index + itemRange.count);
+ QAccessible::updateAccessibility(&ev);
}
-#pragma message("TODO: port accessibility otherwise the following line asserts")
- //QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged);
}
void KItemListView::slotGroupsChanged()
void KItemListView::slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
if (m_grouped) {
updateVisibleGroupHeaders();
doLayout(NoAnimation);
void KItemListView::slotSortRoleChanged(const QByteArray& current, const QByteArray& previous)
{
- Q_UNUSED(current);
- Q_UNUSED(previous);
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
if (m_grouped) {
updateVisibleGroupHeaders();
doLayout(NoAnimation);
void KItemListView::slotCurrentChanged(int current, int previous)
{
- Q_UNUSED(previous);
+ Q_UNUSED(previous)
- KItemListWidget* previousWidget = m_visibleItems.value(previous, 0);
- if (previousWidget) {
- previousWidget->setCurrent(false);
- }
+ // In SingleSelection mode (e.g., in the Places Panel), the current item is
+ // always the selected item. It is not necessary to highlight the current item then.
+ if (m_controller->selectionBehavior() != KItemListController::SingleSelection) {
+ KItemListWidget* previousWidget = m_visibleItems.value(previous, nullptr);
+ if (previousWidget) {
+ previousWidget->setCurrent(false);
+ }
- KItemListWidget* currentWidget = m_visibleItems.value(current, 0);
- if (currentWidget) {
- currentWidget->setCurrent(true);
+ KItemListWidget* currentWidget = m_visibleItems.value(current, nullptr);
+ if (currentWidget) {
+ currentWidget->setCurrent(true);
+ }
}
-#pragma message("TODO: port accessibility otherwise the following line asserts")
- //QAccessible::updateAccessibility(this, current+1, QAccessible::Focus);
+
+ QAccessibleEvent ev(this, QAccessible::Focus);
+ ev.setChild(current);
+ QAccessible::updateAccessibility(&ev);
}
void KItemListView::slotSelectionChanged(const KItemSet& current, const KItemSet& previous)
{
- Q_UNUSED(previous);
+ Q_UNUSED(previous)
QHashIterator<int, KItemListWidget*> it(m_visibleItems);
while (it.hasNext()) {
qreal currentWidth,
qreal previousWidth)
{
- Q_UNUSED(role);
- Q_UNUSED(currentWidth);
- Q_UNUSED(previousWidth);
+ Q_UNUSED(role)
+ Q_UNUSED(currentWidth)
+ Q_UNUSED(previousWidth)
m_headerWidget->setAutomaticColumnResizing(false);
applyColumnWidthsFromHeader();
widget->setStyleOption(m_styleOption);
const KItemListSelectionManager* selectionManager = m_controller->selectionManager();
- widget->setCurrent(index == selectionManager->currentItem());
+
+ // In SingleSelection mode (e.g., in the Places Panel), the current item is
+ // always the selected item. It is not necessary to highlight the current item then.
+ if (m_controller->selectionBehavior() != KItemListController::SingleSelection) {
+ widget->setCurrent(index == selectionManager->currentItem());
+ }
widget->setSelected(selectionManager->isSelected(index));
widget->setHovered(false);
widget->setEnabledSelectionToggle(enabledSelectionToggles());
{
KItemListGroupHeader* header = m_visibleGroups.value(widget);
if (header) {
- header->setParentItem(0);
+ header->setParentItem(nullptr);
groupHeaderCreator()->recycle(header);
m_visibleGroups.remove(widget);
disconnect(widget, &KItemListWidget::geometryChanged, this, &KItemListView::slotGeometryOfGroupHeaderParentChanged);
if (mappedPos.y() >= 0 && mappedPos.y() <= rect.height()) {
if (m_model->supportsDropping(widget->index())) {
// 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());
+ const int gap = qMax(qreal(4.0), qreal(0.3) * rect.height());
if (mappedPos.y() >= gap && mappedPos.y() <= rect.height() - gap) {
return -1;
}
const int parents = m_model->expandedParentsCount(lastIndex + 1);
for (int i = lastIndex; i >= firstIndex; --i) {
if (m_model->expandedParentsCount(i) != parents) {
- widget = 0;
+ widget = nullptr;
break;
}
}
void KItemListView::disconnectRoleEditingSignals(int index)
{
- KItemListWidget* widget = m_visibleItems.value(index);
+ KStandardItemListWidget* widget = qobject_cast<KStandardItemListWidget *>(m_visibleItems.value(index));
if (!widget) {
return;
}
disconnect(widget, &KItemListWidget::roleEditingCanceled, this, nullptr);
disconnect(widget, &KItemListWidget::roleEditingFinished, this, nullptr);
+ disconnect(this, &KItemListView::scrollOffsetChanged, widget, nullptr);
}
int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
QGraphicsWidget* KItemListCreatorBase::popRecycleableWidget()
{
if (m_recycleableWidgets.isEmpty()) {
- return 0;
+ return nullptr;
}
QGraphicsWidget* widget = m_recycleableWidgets.takeLast();
void KItemListWidgetCreatorBase::recycle(KItemListWidget* widget)
{
- widget->setParentItem(0);
+ widget->setParentItem(nullptr);
widget->setOpacity(1.0);
pushRecycleableWidget(widget);
}
pushRecycleableWidget(header);
}
-#include "kitemlistview.moc"