Commit a632cd52 authored by Marcel Wiesweg's avatar Marcel Wiesweg
Browse files

Add a class PersistentWidgetDelegateOverlay with some additional behavior for overlays

which provide user interaction and keyboard focus
- when a "persistent" mode is entered, the overlay stays on its index and
  is not moved by mouse hover to other places or hidden
- when an overlay widget had focus, it is restored

CCBUG: 265025
parent 3808ac57
......@@ -126,7 +126,12 @@ bool ImageDelegateOverlay::affectsMultiple(const QModelIndex& index) const
return false;
}
QItemSelection selection = selectionModel->selection();
return viewHasMultiSelection();
}
bool ImageDelegateOverlay::viewHasMultiSelection() const
{
QItemSelection selection = view()->selectionModel()->selection();
if (selection.size() > 1)
{
......@@ -254,22 +259,32 @@ void AbstractWidgetDelegateOverlay::slotEntered(const QModelIndex& index)
{
hide();
if (!index.isValid())
if (!checkIndexOnEnter(index))
{
return;
}
m_widget->show();
}
bool AbstractWidgetDelegateOverlay::checkIndexOnEnter(const QModelIndex& index) const
{
if (!index.isValid())
{
return false;
}
if (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier))
{
return;
return false;
}
if (!checkIndex(index))
{
return;
return false;
}
m_widget->show();
return true;
}
bool AbstractWidgetDelegateOverlay::checkIndex(const QModelIndex& index) const
......@@ -447,6 +462,193 @@ void HoverButtonDelegateOverlay::slotEntered(const QModelIndex& index)
// -----------------------------------------------------------------------------------
class PersistentWidgetDelegateOverlay::PersistentWidgetDelegateOverlayPriv
{
public:
PersistentWidgetDelegateOverlayPriv()
: persistent(false),
restoreFocus(false)
{
}
bool persistent;
bool restoreFocus;
QPersistentModelIndex index;
QPersistentModelIndex enteredIndex;
};
PersistentWidgetDelegateOverlay::PersistentWidgetDelegateOverlay(QObject* parent)
: AbstractWidgetDelegateOverlay(parent),
d(new PersistentWidgetDelegateOverlayPriv)
{
}
PersistentWidgetDelegateOverlay::~PersistentWidgetDelegateOverlay()
{
delete d;
}
QModelIndex PersistentWidgetDelegateOverlay::index() const
{
return d->index;
}
void PersistentWidgetDelegateOverlay::setActive(bool active)
{
d->persistent = false;
AbstractWidgetDelegateOverlay::setActive(active);
if (active)
{
connect(m_view->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(leavePersistentMode()));
connect(m_view, SIGNAL(viewportClicked(const QMouseEvent*)),
this, SLOT(leavePersistentMode()));
}
else
{
if (m_view)
{
disconnect(m_view->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(leavePersistentMode()));
disconnect(m_view, SIGNAL(viewportClicked(const QMouseEvent*)),
this, SLOT(leavePersistentMode()));
}
}
}
void PersistentWidgetDelegateOverlay::setPersistent(bool persistent)
{
if (d->persistent == persistent)
{
return;
}
d->persistent = persistent;
if (d->persistent && d->index.isValid())
{
showOnIndex(d->index);
}
else if (!d->persistent && d->enteredIndex.isValid())
{
slotEntered(d->enteredIndex);
}
}
void PersistentWidgetDelegateOverlay::enterPersistentMode()
{
setPersistent(true);
}
void PersistentWidgetDelegateOverlay::leavePersistentMode()
{
setPersistent(false);
}
bool PersistentWidgetDelegateOverlay::isPersistent() const
{
return d->persistent;
}
void PersistentWidgetDelegateOverlay::slotEntered(const QModelIndex& index)
{
d->enteredIndex = index;
if (d->persistent && m_widget->isVisible())
{
return;
}
hide();
if (!checkIndexOnEnter(index))
{
return;
}
m_widget->show();
showOnIndex(index);
}
void PersistentWidgetDelegateOverlay::slotReset()
{
setPersistent(false);
d->restoreFocus = false;
AbstractWidgetDelegateOverlay::slotReset();
}
void PersistentWidgetDelegateOverlay::slotViewportEntered()
{
d->enteredIndex = QModelIndex();
if (!d->persistent)
{
AbstractWidgetDelegateOverlay::slotViewportEntered();
}
}
void PersistentWidgetDelegateOverlay::viewportLeaveEvent(QObject* obj, QEvent* event)
{
setPersistent(false);
d->restoreFocus = false;
AbstractWidgetDelegateOverlay::viewportLeaveEvent(obj, event);
}
void PersistentWidgetDelegateOverlay::slotRowsRemoved(const QModelIndex& parent, int begin, int end)
{
AbstractWidgetDelegateOverlay::slotRowsRemoved(parent, begin, end);
setPersistent(false);
}
void PersistentWidgetDelegateOverlay::slotLayoutChanged()
{
AbstractWidgetDelegateOverlay::slotLayoutChanged();
setPersistent(false);
}
void PersistentWidgetDelegateOverlay::hide()
{
if (!d->restoreFocus && m_widget->isVisible())
{
QWidget* f = QApplication::focusWidget();
d->restoreFocus = f && m_widget->isAncestorOf(f);
}
AbstractWidgetDelegateOverlay::hide();
}
void PersistentWidgetDelegateOverlay::showOnIndex(const QModelIndex& index)
{
d->index = index;
restoreFocus();
}
void PersistentWidgetDelegateOverlay::storeFocus()
{
d->restoreFocus = true;
}
void PersistentWidgetDelegateOverlay::restoreFocus()
{
if (d->restoreFocus)
{
setFocusOnWidget();
d->restoreFocus = false;
}
}
void PersistentWidgetDelegateOverlay::setFocusOnWidget()
{
m_widget->setFocus();
}
// -----------------------------------------------------------------------------------
ImageDelegateOverlayContainer::~ImageDelegateOverlayContainer()
{
}
......
......@@ -94,6 +94,11 @@ protected:
QList<QModelIndex> affectedIndexes(const QModelIndex& index) const;
int numberOfAffectedIndexes(const QModelIndex& index) const;
/**
* Utility method
*/
bool viewHasMultiSelection() const;
protected:
QAbstractItemView* m_view;
......@@ -159,6 +164,11 @@ protected:
void widgetLeaveNotifyMultiple();
virtual QString notifyMultipleMessage(const QModelIndex&, int number);
/**
* Utility method called from slotEntered
*/
bool checkIndexOnEnter(const QModelIndex& index) const;
protected Q_SLOTS:
/** Default implementation shows the widget iff the index is valid and checkIndex returns true. */
......@@ -216,6 +226,74 @@ protected Q_SLOTS:
// -------------------------------------------------------------------------------------------
class DIGIKAM_EXPORT PersistentWidgetDelegateOverlay : public AbstractWidgetDelegateOverlay
{
Q_OBJECT
/**
* This class offers additional / modified behavior:
* When a "persistent" mode is entered, it will not move
* by mouse hover, but stay and only move on mouse click.
* If the overlay widget had focus, it will be restored on show.
*/
public:
PersistentWidgetDelegateOverlay(QObject* parent);
~PersistentWidgetDelegateOverlay();
virtual void setActive(bool active);
public Q_SLOTS:
/**
* Enters persistent mode.
* The overlay is moved because of mouse hover.
*/
void setPersistent(bool persistent);
void enterPersistentMode();
void leavePersistentMode();
bool isPersistent() const;
void storeFocus();
protected:
QModelIndex index() const;
/**
* Most overlays reimplement this slot to get the starting point
* for repositioning a widget etc.
* This class instead provides showOnIndex() which you shall
* use for this purpose.
*/
virtual void slotEntered(const QModelIndex& index);
virtual void slotReset();
virtual void slotViewportEntered();
virtual void slotRowsRemoved(const QModelIndex& parent, int start, int end);
virtual void slotLayoutChanged();
virtual void viewportLeaveEvent(QObject* obj, QEvent* event);
virtual void hide();
/**
* Reimplement to set the focus on the correct subwidget.
* Default implementation sets focus on widget()
*/
virtual void setFocusOnWidget();
/// see slotEntered()
virtual void showOnIndex(const QModelIndex& index);
void restoreFocus();
private:
class PersistentWidgetDelegateOverlayPriv;
PersistentWidgetDelegateOverlayPriv* const d;
};
// -------------------------------------------------------------------------------------------
class DIGIKAM_EXPORT ImageDelegateOverlayContainer
{
public:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment