void Dropper::handleInternalDrag( QDropEvent* dropEvent, AbstractByteArrayView* sourceByteArrayView ) { // get drag origin AddressRange selection = sourceByteArrayView->tableRanges()->removeSelection(); ByteArrayTableCursor* tableCursor = mByteArrayView->tableCursor(); AbstractByteArrayModel* byteArrayModel = mByteArrayView->byteArrayModel(); Address insertIndex = tableCursor->realIndex(); // is this a move? if( dropEvent->proposedAction() == Qt::MoveAction ) { // ignore the copy hold in the event but only move Address newCursorIndex; // need to swap? if( selection.end() < insertIndex ) { newCursorIndex = insertIndex; const Address firstIndex = selection.start(); selection.set( selection.nextBehindEnd(), insertIndex-1 ); insertIndex = firstIndex; } else newCursorIndex = insertIndex + selection.width(); const bool success = byteArrayModel->swap( insertIndex, selection ); if( success ) { tableCursor->gotoCIndex( newCursorIndex ); emit mByteArrayView->cursorPositionChanged( tableCursor->realIndex() ); } } // is a copy else { // TODO: should this be a method of AbstractByteArrayModel, to reuse piece data? // get data const QByteArray data = dropEvent->mimeData()->data( QLatin1String(DropperOctetStreamFormatName) ); if( !data.isEmpty() ) { if( mByteArrayView->isOverwriteMode() ) { const Size length = mByteArrayView->layout()->length(); if( !tableCursor->isBehind() && length > 0 ) { AddressRange overwriteRange = AddressRange::fromWidth( insertIndex, data.size() ); overwriteRange.restrictEndTo( length-1 ); if( overwriteRange.isValid() ) byteArrayModel->replace( overwriteRange, reinterpret_cast<const Byte*>(data.constData()), overwriteRange.width() ); } } else byteArrayModel->insert( insertIndex, reinterpret_cast<const Byte*>(data.constData()), data.size() ); } } }
void MouseNavigator::handleMouseMove( const QPoint& point ) // handles the move of the mouse with pressed buttons { ByteArrayTableCursor* tableCursor = mView->tableCursor(); ByteArrayTableRanges* tableRanges = mView->tableRanges(); const bool oldHasSelection = tableRanges->hasSelection(); const int yOffset = mView->yOffset(); const int behindLastYOffset = yOffset + mView->visibleHeight(); // scrolltimer but inside of viewport? if( mScrollTimer->isActive() ) { if( yOffset <= point.y() && point.y() < behindLastYOffset ) mScrollTimer->stop(); } // no scrolltimer and outside of viewport? else { if( point.y() < yOffset || behindLastYOffset <= point.y() ) mScrollTimer->start( DefaultScrollTimerPeriod ); } mView->pauseCursor(); mView->placeCursor( point ); mView->ensureCursorVisible(); // do wordwise selection? if( mInLMBDoubleClick && tableRanges->hasFirstWordSelection() ) { Address newIndex = tableCursor->realIndex(); const AddressRange firstWordSelection = tableRanges->firstWordSelection(); const WordByteArrayService WBS( mView->byteArrayModel(), mView->charCodec() ); // are we before the selection? if( firstWordSelection.startsBehind(newIndex) ) { tableRanges->ensureWordSelectionForward( false ); newIndex = WBS.indexOfLeftWordSelect( newIndex ); } // or behind? else if( firstWordSelection.endsBefore(newIndex) ) { tableRanges->ensureWordSelectionForward( true ); newIndex = WBS.indexOfRightWordSelect( newIndex ); } // or inside? else { tableRanges->ensureWordSelectionForward( true ); newIndex = firstWordSelection.nextBehindEnd(); } tableCursor->gotoIndex( newIndex ); } if( tableRanges->selectionStarted() ) tableRanges->setSelectionEnd( mView->cursorPosition() ); mView->updateChanged(); mView->unpauseCursor(); const bool newHasSelection = tableRanges->hasSelection(); emit mView->cursorPositionChanged( mView->cursorPosition() ); emit mView->selectionChanged( tableRanges->selection() ); if( oldHasSelection != newHasSelection ) { if( ! mView->isOverwriteMode() ) emit mView->cutAvailable( newHasSelection ); emit mView->copyAvailable( newHasSelection ); emit mView->hasSelectedDataChanged( newHasSelection ); } }