Major improvements to D&D of curves.

This commit is contained in:
Gaute Lindkvist 2020-08-07 07:31:57 +02:00
parent 9393c27b13
commit 86a4f5613c
12 changed files with 194 additions and 83 deletions

View File

@ -1081,6 +1081,17 @@ RimViewWindow* RiaGuiApplication::activeViewWindow()
return viewWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuMainWindowBase* RiaGuiApplication::activeMainWindow()
{
QWidget* mainWindowWidget = RiaGuiApplication::activeWindow();
RiuMainWindowBase* mainWindow = dynamic_cast<RiuMainWindowBase*>( mainWindowWidget );
return mainWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -117,7 +117,8 @@ public:
RiuPlotMainWindow* mainPlotWindow();
RiuMainWindowBase* mainWindowByID( int mainWindowID );
static RimViewWindow* activeViewWindow();
static RimViewWindow* activeViewWindow();
static RiuMainWindowBase* activeMainWindow();
bool isMain3dWindowVisible() const;
bool isMainPlotWindowVisible() const;

View File

@ -36,8 +36,9 @@
void RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( RimWellLogTrack* destTrack,
const std::vector<RimWellLogCurve*>& curves,
RimWellLogCurve* curveToInsertBeforeOrAfter,
bool isSwapOperation )
int insertAtPosition )
{
CVF_ASSERT( insertAtPosition >= 0 );
CVF_ASSERT( destTrack );
std::set<RimWellLogTrack*> srcTracks;
@ -47,8 +48,6 @@ void RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( RimWellLogTra
{
RimWellLogCurve* curve = curves[cIdx];
if ( curve == curveToInsertBeforeOrAfter ) continue;
RimWellLogTrack* wellLogPlotTrack;
curve->firstAncestorOrThisOfType( wellLogPlotTrack );
if ( wellLogPlotTrack )
@ -61,24 +60,18 @@ void RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( RimWellLogTra
}
}
size_t insertionStartIndex = 0;
if ( curveToInsertBeforeOrAfter )
{
insertionStartIndex = destTrack->curveIndex( curveToInsertBeforeOrAfter );
if ( !isSwapOperation ) insertionStartIndex += 1;
}
for ( size_t cIdx = 0; cIdx < curves.size(); cIdx++ )
{
destTrack->insertCurve( curves[cIdx], insertionStartIndex + cIdx );
size_t position = (size_t)insertAtPosition + cIdx;
destTrack->insertCurve( curves[cIdx], position );
}
for ( auto track : srcTracks )
{
track->setAutoScaleXEnabled( true );
track->updateParentPlotZoom();
track->updateConnectedEditors();
track->updateStackedCurveData();
track->updateConnectedEditors();
}
for ( auto plot : srcPlots )

View File

@ -34,7 +34,7 @@ public:
static void moveCurvesToWellLogPlotTrack( RimWellLogTrack* dstTrack,
const std::vector<RimWellLogCurve*>& curves,
RimWellLogCurve* curveToInsertBeforeOrAfter,
bool isSwapOperation );
int insertAtPosition );
static void moveTracksToWellLogPlot( RimWellLogPlot* wellLogPlot,
const std::vector<RimWellLogTrack*>& tracks,
RimWellLogTrack* trackToInsertBeforeOrAfter,

View File

@ -437,6 +437,7 @@ RimSummaryPlotSourceStepping*
void RimSummaryCurveCollection::moveCurvesToCollection( RimSummaryCurveCollection* collection,
const std::vector<RimSummaryCurve*> curves,
RimSummaryCurve* curveToInsertBeforeOrAfter,
int insertAtPosition,
bool isSwapOperation )
{
CAF_ASSERT( collection );
@ -461,19 +462,21 @@ void RimSummaryCurveCollection::moveCurvesToCollection( RimSummaryCurveCollectio
collection->curvesAddedOrRemoved.send();
}
size_t insertionStartIndex = std::numeric_limits<size_t>::infinity();
if ( curveToInsertBeforeOrAfter )
if ( insertAtPosition == -1 )
{
insertionStartIndex = collection->m_curves.index( curveToInsertBeforeOrAfter );
}
if ( insertionStartIndex < collection->m_curves.size() && !isSwapOperation )
{
insertionStartIndex += 1;
if ( curveToInsertBeforeOrAfter )
{
insertAtPosition = (int)collection->m_curves.index( curveToInsertBeforeOrAfter );
if ( !isSwapOperation ) insertAtPosition += 1;
}
else
{
insertAtPosition = (int)collection->m_curves.size();
}
}
for ( size_t cIdx = 0; cIdx < curves.size(); ++cIdx )
{
collection->insertCurve( curves[cIdx], insertionStartIndex + cIdx );
collection->insertCurve( curves[cIdx], (size_t)insertAtPosition + cIdx );
}
collection->updateConnectedEditors();

View File

@ -83,6 +83,7 @@ public:
static void moveCurvesToCollection( RimSummaryCurveCollection* collection,
const std::vector<RimSummaryCurve*> curves,
RimSummaryCurve* curveToInsertBeforeOrAfter,
int insertAtPosition,
bool isSwapOperation );
private:

View File

@ -19,6 +19,8 @@
#include "RiuDragDrop.h"
#include "RiaGuiApplication.h"
#include "OperationsUsingObjReferences/RicPasteEclipseCasesFeature.h"
#include "RicCloseCaseFeature.h"
#include "WellLogCommands/RicNewWellLogFileCurveFeature.h"
@ -53,6 +55,33 @@
#include <QAbstractItemModel>
#include <QModelIndex>
//--------------------------------------------------------------------------------------------------
/// Utility class to enforce updates of the tree view after drop is complete.
/// Does the update on destruction of the object.
//--------------------------------------------------------------------------------------------------
class RiuDragAndDropTreeViewUpdater
{
public:
RiuDragAndDropTreeViewUpdater( caf::PdmUiTreeView* treeView,
const QModelIndex& indexToUpdate,
const std::vector<const caf::PdmUiItem*> draggedUiItems )
: m_treeView( treeView )
, m_indexToUpdate( indexToUpdate )
, m_draggedUiItems( draggedUiItems )
{
}
~RiuDragAndDropTreeViewUpdater()
{
m_treeView->updateSubTree( m_indexToUpdate );
m_treeView->selectItems( m_draggedUiItems );
}
private:
caf::PdmUiTreeView* m_treeView;
QModelIndex m_indexToUpdate;
std::vector<const caf::PdmUiItem*> m_draggedUiItems;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -151,9 +180,9 @@ Qt::ItemFlags RiuDragDrop::flags( const QModelIndex& index ) const
{
Qt::ItemFlags itemflags = nullptr;
if ( index.isValid() )
if ( index.isValid() && RiaGuiApplication::activeMainWindow() )
{
caf::PdmUiTreeView* uiTreeView = RiuMainWindow::instance()->projectTreeView();
caf::PdmUiTreeView* uiTreeView = RiaGuiApplication::activeMainWindow()->projectTreeView();
caf::PdmUiItem* uiItem = uiTreeView->uiItemFromModelIndex( index );
caf::PdmObject* pdmObj = dynamic_cast<caf::PdmObject*>( uiItem );
@ -216,7 +245,8 @@ Qt::ItemFlags RiuDragDrop::flags( const QModelIndex& index ) const
itemflags |= Qt::ItemIsDropEnabled;
}
}
else if ( dynamic_cast<RimSummaryCurve*>( uiItem ) || dynamic_cast<RimSummaryPlot*>( uiItem ) )
else if ( dynamic_cast<RimSummaryCurve*>( uiItem ) || dynamic_cast<RimSummaryPlot*>( uiItem ) ||
dynamic_cast<RimSummaryCurveCollection*>( uiItem ) )
{
if ( RiuTypedPdmObjects<RimSummaryCurve>::containsTypedObjects( m_dragItems ) )
{
@ -277,15 +307,15 @@ Qt::ItemFlags RiuDragDrop::flags( const QModelIndex& index ) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuDragDrop::isSwapOperation( const QModelIndexList& dragIndices, const QModelIndex& dropTargetIndex )
bool RiuDragDrop::isSwapOperation( int targetRow, const QModelIndexList& dragIndices, const QModelIndex& dropTargetIndex )
{
if ( dragIndices.size() == 1u )
if ( dragIndices.size() == 1u && targetRow == -1 ) // targetRow >= 0 means a drop between two other rows.
{
QModelIndex dragIndex = dragIndices.front();
bool sharesParent = dropTargetIndex.parent() == dragIndex.parent();
bool targetIsJustAbove = dropTargetIndex.row() >= 0 && dragIndex.row() >= 0 &&
( dragIndex.row() - dropTargetIndex.row() ) == 1;
return sharesParent && targetIsJustAbove;
QModelIndex dragIndex = dragIndices.front();
bool sharesParent = dropTargetIndex.parent() == dragIndex.parent();
bool targetIsJustAboveOrBelow = dropTargetIndex.row() >= 0 && dragIndex.row() >= 0 &&
std::abs( dragIndex.row() - dropTargetIndex.row() ) == 1;
return sharesParent && targetIsJustAboveOrBelow;
}
return false;
}
@ -293,17 +323,18 @@ bool RiuDragDrop::isSwapOperation( const QModelIndexList& dragIndices, const QMo
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& dropTargetIndex )
{
caf::PdmUiTreeView* uiTreeView = RiuMainWindow::instance()->projectTreeView();
caf::PdmUiItem* dropTargetUiItem = uiTreeView->uiItemFromModelIndex( parent );
CVF_ASSERT( RiaGuiApplication::activeMainWindow() );
caf::PdmUiTreeView* uiTreeView = RiaGuiApplication::activeMainWindow()->projectTreeView();
caf::PdmUiItem* dropTargetUiItem = uiTreeView->uiItemFromModelIndex( dropTargetIndex );
caf::PdmObjectHandle* dropTarget = dynamic_cast<caf::PdmObjectHandle*>( dropTargetUiItem );
if ( dropTarget )
{
caf::PdmObjectGroup draggedObjects;
const MimeDataWithIndexes* myMimeData = qobject_cast<const MimeDataWithIndexes*>( data );
if ( myMimeData && parent.isValid() )
if ( myMimeData && dropTargetIndex.isValid() )
{
QModelIndexList indices = myMimeData->indexes();
objectGroupFromModelIndexes( &draggedObjects, indices );
@ -313,6 +344,11 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in
return false;
}
RiuDragAndDropTreeViewUpdater updater( uiTreeView,
dropTargetIndex.parent(),
RiuTypedPdmObjects<const caf::PdmUiItem>::typedObjectsFromGroup(
draggedObjects ) );
RimIdenticalGridCaseGroup* gridCaseGroup;
dropTarget->firstAncestorOrThisOfType( gridCaseGroup );
if ( gridCaseGroup )
@ -327,7 +363,8 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in
return handleWellLogPlotCurveDrop( action,
draggedObjects,
wellLogPlotCurve,
isSwapOperation( myMimeData->indexes(), parent ) );
row,
isSwapOperation( row, myMimeData->indexes(), dropTargetIndex ) );
}
RimWellLogTrack* wellLogPlotTrack;
@ -338,7 +375,7 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in
draggedObjects,
wellLogPlotTrack,
row,
isSwapOperation( myMimeData->indexes(), parent ) );
isSwapOperation( row, myMimeData->indexes(), dropTargetIndex ) );
}
RimWellLogPlot* wellLogPlot;
@ -349,7 +386,7 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in
draggedObjects,
wellLogPlot,
row,
isSwapOperation( myMimeData->indexes(), parent ) );
isSwapOperation( row, myMimeData->indexes(), dropTargetIndex ) );
}
RimSummaryCurve* summaryCurve;
@ -359,14 +396,15 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in
return handleSummaryCurveDrop( action,
draggedObjects,
summaryCurve,
isSwapOperation( myMimeData->indexes(), parent ) );
row,
isSwapOperation( row, myMimeData->indexes(), dropTargetIndex ) );
}
RimSummaryPlot* summaryPlot;
dropTarget->firstAncestorOrThisOfType( summaryPlot );
if ( summaryPlot )
{
return handleSummaryPlotDrop( action, draggedObjects, summaryPlot );
return handleSummaryPlotDrop( action, draggedObjects, summaryPlot, row );
}
RimMultiPlot* multiPlot;
@ -498,6 +536,7 @@ bool RiuDragDrop::handleMultiPlotDrop( Qt::DropAction action,
bool RiuDragDrop::handleWellLogPlotCurveDrop( Qt::DropAction action,
caf::PdmObjectGroup& draggedObjects,
RimWellLogCurve* curveDropTarget,
int insertAtPosition,
bool isSwapOperation )
{
std::vector<RimWellLogCurve*> wellLogPlotCurves =
@ -507,12 +546,18 @@ bool RiuDragDrop::handleWellLogPlotCurveDrop( Qt::DropAction action,
if ( action == Qt::MoveAction )
{
RimWellLogTrack* wellLogPlotTrack;
curveDropTarget->firstAncestorOrThisOfType( wellLogPlotTrack );
curveDropTarget->firstAncestorOrThisOfTypeAsserted( wellLogPlotTrack );
if ( insertAtPosition == -1 )
{
insertAtPosition = (int)wellLogPlotTrack->curveIndex( curveDropTarget );
if ( !isSwapOperation ) insertAtPosition += 1;
}
RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( wellLogPlotTrack,
wellLogPlotCurves,
curveDropTarget,
isSwapOperation );
insertAtPosition );
return true;
}
}
@ -546,42 +591,22 @@ bool RiuDragDrop::handleWellLogPlotTrackDrop( Qt::DropAction action,
{
if ( action == Qt::MoveAction )
{
RimWellLogCurve* insertAfter = nullptr;
auto visibleCurves = trackTarget->visibleCurves();
if ( !visibleCurves.empty() )
RimWellLogCurve* insertBeforeOrAfter = nullptr;
auto visibleCurves = trackTarget->visibleCurves();
if ( insertAtPosition == -1 )
{
if ( insertAtPosition == -1 )
{
// If we are moving any curves to a new track, the curves should be appended
// but insertAtPosition will be -1.
std::set<RimWellLogTrack*> currentParentTracks;
for ( auto curve : wellLogPlotCurves )
{
RimWellLogTrack* track;
curve->firstAncestorOrThisOfTypeAsserted( track );
currentParentTracks.insert( track );
}
bool allMovedWithinSameTrack = currentParentTracks.size() > 1 ||
!currentParentTracks.count( trackTarget );
if ( !allMovedWithinSameTrack )
{
insertAtPosition = (int)visibleCurves.size() - 1;
}
}
if ( insertAtPosition > 0 )
{
auto visibleCurves = trackTarget->visibleCurves();
if ( !visibleCurves.empty() )
{
int insertAfterPosition = std::min( insertAtPosition - 1, (int)visibleCurves.size() - 1 );
insertAfter = visibleCurves[insertAfterPosition];
}
}
insertAtPosition = (int)visibleCurves.size();
if ( !visibleCurves.empty() ) insertBeforeOrAfter = visibleCurves.back();
}
else if ( insertAtPosition < (int)visibleCurves.size() )
{
insertBeforeOrAfter = visibleCurves[insertAtPosition];
}
RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( trackTarget,
wellLogPlotCurves,
insertAfter,
isSwapOperation );
insertBeforeOrAfter,
insertAtPosition );
return true;
}
}
@ -643,6 +668,7 @@ bool RiuDragDrop::handleWellLogPlotDrop( Qt::DropAction action,
bool RiuDragDrop::handleSummaryCurveDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
RimSummaryCurve* summaryCurveTarget,
int insertAtPosition,
bool isSwapOperation )
{
std::vector<RimSummaryCurve*> summaryCurves = RiuTypedPdmObjects<RimSummaryCurve>::typedObjectsFromGroup( objectGroup );
@ -656,6 +682,7 @@ bool RiuDragDrop::handleSummaryCurveDrop( Qt::DropAction action,
RimSummaryCurveCollection::moveCurvesToCollection( summaryCurveCollection,
summaryCurves,
summaryCurveTarget,
insertAtPosition,
isSwapOperation );
return true;
}
@ -666,7 +693,10 @@ bool RiuDragDrop::handleSummaryCurveDrop( Qt::DropAction action,
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuDragDrop::handleSummaryPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimSummaryPlot* summaryPlot )
bool RiuDragDrop::handleSummaryPlotDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
RimSummaryPlot* summaryPlot,
int insertAtPosition )
{
std::vector<RimSummaryCurve*> summaryCurves = RiuTypedPdmObjects<RimSummaryCurve>::typedObjectsFromGroup( objectGroup );
if ( summaryCurves.size() > 0 )
@ -676,6 +706,7 @@ bool RiuDragDrop::handleSummaryPlotDrop( Qt::DropAction action, caf::PdmObjectGr
RimSummaryCurveCollection::moveCurvesToCollection( summaryPlot->summaryCurveCollection(),
summaryCurves,
nullptr,
insertAtPosition,
false );
return true;
}

View File

@ -67,6 +67,7 @@ private:
bool handleWellLogPlotCurveDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
RimWellLogCurve* wellLogPlotCurve,
int insertAtPosition,
bool isSwapOperation = false );
bool handleWellLogPlotTrackDrop( Qt::DropAction action,
@ -84,9 +85,13 @@ private:
bool handleSummaryCurveDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
RimSummaryCurve* summaryCurveTarget,
int insertAtPosition,
bool isSwapOperation = false );
bool handleSummaryPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimSummaryPlot* summaryPlot );
bool handleSummaryPlotDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
RimSummaryPlot* summaryPlot,
int insertAtPosition );
bool handleMultiPlotDrop( Qt::DropAction action,
caf::PdmObjectGroup& objectGroup,
@ -101,7 +106,7 @@ private:
static void objectGroupFromModelIndexes( caf::PdmObjectGroup* objectGroup, const QModelIndexList& indexes );
static std::vector<caf::PdmPointer<caf::PdmObjectHandle>> objectHandlesFromSelection();
static bool isSwapOperation( const QModelIndexList& dragIndices, const QModelIndex& dropTargetIndex );
static bool isSwapOperation( int targetRow, const QModelIndexList& dragIndices, const QModelIndex& dropTargetIndex );
private:
mutable std::vector<caf::PdmPointer<caf::PdmObjectHandle>> m_dragItems;

View File

@ -88,6 +88,13 @@ protected:
{
}
/// Override to provide tree editor specific attributes for the field and uiConfigName
virtual void defineTreeEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
}
/// Override to provide editor specific data for the uiConfigName for the object
virtual void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) {}

View File

@ -200,6 +200,18 @@ QModelIndex PdmUiTreeView::findModelIndex( const PdmUiItem* object ) const
return m_treeViewEditor->findModelIndex( object );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeView::updateSubTree( const QModelIndex& index )
{
auto uiItem = uiItemFromModelIndex( index );
if ( uiItem )
{
m_treeViewEditor->updateSubTree( uiItem );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -82,8 +82,8 @@ public:
// the Pdm model directly.
PdmUiItem* uiItemFromModelIndex( const QModelIndex& index ) const;
QModelIndex findModelIndex( const PdmUiItem* object ) const;
void setDragDropInterface( PdmUiDragDropInterface* dragDropInterface );
void updateSubTree( const QModelIndex& index );
void setDragDropInterface( PdmUiDragDropInterface* dragDropInterface );
signals:
void selectionChanged();

View File

@ -56,6 +56,7 @@
#include <QMenu>
#include <QModelIndexList>
#include <QPainter>
#include <QProxyStyle>
#include <QSortFilterProxyModel>
#include <QStyleOptionViewItem>
#include <QTreeView>
@ -63,6 +64,49 @@
namespace caf
{
class PdmUiTreeViewStyle : public QProxyStyle
{
public:
void drawPrimitive( PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const override
{
if ( element == QStyle::PE_IndicatorItemViewItemDrop )
{
painter->setRenderHint( QPainter::Antialiasing, true );
if ( option->rect.height() == 0 )
{
QPalette palette;
QColor c = QApplication::palette().color( QPalette::Highlight ).darker( 150 );
QPen pen( c );
pen.setWidth( 2 );
QBrush brush( c );
painter->setPen( pen );
painter->setBrush( brush );
painter->drawEllipse( option->rect.topLeft(), 3, 3 );
painter->drawLine( QPoint( option->rect.topLeft().x() + 3, option->rect.topLeft().y() ),
option->rect.topRight() );
}
else
{
QPalette palette;
QColor c = QApplication::palette().color( QPalette::Highlight ).darker( 150 );
QPen pen( c );
pen.setWidth( 2 );
painter->setPen( pen );
painter->drawRoundedRect( option->rect, 4, 4 );
}
}
else
{
QProxyStyle::drawPrimitive( element, option, painter, widget );
}
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -70,7 +114,10 @@ class PdmUiTreeViewWidget : public QTreeView
{
public:
explicit PdmUiTreeViewWidget( QWidget* parent = nullptr )
: QTreeView( parent ){};
: QTreeView( parent )
{
setStyle( new PdmUiTreeViewStyle );
};
~PdmUiTreeViewWidget() override{};
bool isTreeItemEditWidgetActive() const { return state() == QAbstractItemView::EditingState; }