@ -13,6 +13,10 @@
const int CELL_HEIGHT = 26 ;
inline int get_bit_index ( const QModelIndex & index , bool little_endian ) {
return index . row ( ) * 8 + ( little_endian ? 7 - index . column ( ) : index . column ( ) ) ;
}
BinaryView : : BinaryView ( QWidget * parent ) : QTableView ( parent ) {
model = new BinaryViewModel ( this ) ;
setModel ( model ) ;
@ -37,31 +41,49 @@ void BinaryView::highlight(const Signal *sig) {
}
void BinaryView : : setSelection ( const QRect & rect , QItemSelectionModel : : SelectionFlags flags ) {
QModelIndex tl = indexAt ( { qMin ( rect . left ( ) , rect . right ( ) ) , qMin ( rect . top ( ) , rect . bottom ( ) ) } ) ;
QModelIndex br = indexAt ( { qMax ( rect . left ( ) , rect . right ( ) ) , qMax ( rect . top ( ) , rect . bottom ( ) ) } ) ;
if ( ! tl . isValid ( ) | | ! br . isValid ( ) )
auto index = indexAt ( viewport ( ) - > mapFromGlobal ( QCursor : : pos ( ) ) ) ;
if ( ! anchor_index . isValid ( ) | | ! index . isValid ( ) )
return ;
if ( tl < anchor_index ) {
br = anchor_index ;
} else if ( anchor_index < br ) {
tl = anchor_index ;
}
QItemSelection selection ;
for ( int row = tl . row ( ) ; row < = br . row ( ) ; + + row ) {
int left_col = ( row = = tl . row ( ) ) ? tl . column ( ) : 0 ;
int right_col = ( row = = br . row ( ) ) ? br . column ( ) : 7 ;
selection . merge ( { model - > index ( row , left_col ) , model - > index ( row , right_col ) } , flags ) ;
auto [ tl , br ] = std : : minmax ( anchor_index , index ) ;
if ( ( resize_sig & & resize_sig - > is_little_endian ) | | ( ! resize_sig & & index < anchor_index ) ) {
// little_endian selection
if ( tl . row ( ) = = br . row ( ) ) {
selection . merge ( { model - > index ( tl . row ( ) , tl . column ( ) ) , model - > index ( tl . row ( ) , br . column ( ) ) } , flags ) ;
} else {
for ( int row = tl . row ( ) ; row < = br . row ( ) ; + + row ) {
int left_col = ( row = = br . row ( ) ) ? br . column ( ) : 0 ;
int right_col = ( row = = tl . row ( ) ) ? tl . column ( ) : 7 ;
selection . merge ( { model - > index ( row , left_col ) , model - > index ( row , right_col ) } , flags ) ;
}
}
} else {
// big endian selection
for ( int row = tl . row ( ) ; row < = br . row ( ) ; + + row ) {
int left_col = ( row = = tl . row ( ) ) ? tl . column ( ) : 0 ;
int right_col = ( row = = br . row ( ) ) ? br . column ( ) : 7 ;
selection . merge ( { model - > index ( row , left_col ) , model - > index ( row , right_col ) } , flags ) ;
}
}
selectionModel ( ) - > select ( selection , flags ) ;
}
void BinaryView : : mousePressEvent ( QMouseEvent * event ) {
delegate - > setSelectionColor ( style ( ) - > standardPalette ( ) . color ( QPalette : : Active , QPalette : : Highlight ) ) ;
anchor_index = indexAt ( event - > pos ( ) ) ;
if ( getResizingSignal ( ) ! = nullptr ) {
if ( auto index = indexAt ( event - > pos ( ) ) ; index . isValid ( ) & & index . column ( ) ! = 8 ) {
anchor_index = index ;
auto item = ( const BinaryViewModel : : Item * ) anchor_index . internalPointer ( ) ;
delegate - > setSelectionColor ( item - > bg_color ) ;
if ( item & & item - > sigs . size ( ) > 0 ) {
int bit_idx = get_bit_index ( anchor_index , true ) ;
for ( auto s : item - > sigs ) {
if ( bit_idx = = s - > lsb | | bit_idx = = s - > msb ) {
resize_sig = s ;
delegate - > setSelectionColor ( item - > bg_color ) ;
break ;
}
}
}
}
QTableView : : mousePressEvent ( event ) ;
}
@ -80,23 +102,35 @@ void BinaryView::mouseMoveEvent(QMouseEvent *event) {
void BinaryView : : mouseReleaseEvent ( QMouseEvent * event ) {
QTableView : : mouseReleaseEvent ( event ) ;
if ( auto indexes = selectedIndexes ( ) ; ! indexes . isEmpty ( ) ) {
int from = indexes . first ( ) . row ( ) * 8 + indexes . first ( ) . column ( ) ;
int to = indexes . back ( ) . row ( ) * 8 + indexes . back ( ) . column ( ) ;
if ( auto sig = getResizingSignal ( ) ) {
auto [ sig_from , sig_to ] = getSignalRange ( sig ) ;
if ( from > = sig_from & & to < = sig_to ) { // reduce size
emit ( from = = sig_from ? resizeSignal ( sig , std : : min ( to + 1 , sig_to ) , sig_to )
: resizeSignal ( sig , sig_from , std : : max ( from - 1 , sig_from ) ) ) ;
} else { // increase size
emit resizeSignal ( sig , std : : min ( from , sig_from ) , std : : max ( to , sig_to ) ) ;
auto release_index = indexAt ( event - > pos ( ) ) ;
if ( release_index . isValid ( ) & & anchor_index . isValid ( ) ) {
if ( release_index . column ( ) = = 8 ) {
release_index = model - > index ( release_index . row ( ) , 7 ) ;
}
bool little_endian = ( resize_sig & & resize_sig - > is_little_endian ) | | ( ! resize_sig & & release_index < anchor_index ) ;
int release_bit_idx = get_bit_index ( release_index , little_endian ) ;
int archor_bit_idx = get_bit_index ( anchor_index , little_endian ) ;
if ( resize_sig ) {
auto [ sig_from , sig_to ] = getSignalRange ( resize_sig ) ;
int start_bit , end_bit ;
if ( archor_bit_idx = = sig_from ) {
std : : tie ( start_bit , end_bit ) = std : : minmax ( release_bit_idx , sig_to ) ;
if ( start_bit > = sig_from & & start_bit < = sig_to )
start_bit = std : : min ( start_bit + 1 , sig_to ) ;
} else {
std : : tie ( start_bit , end_bit ) = std : : minmax ( release_bit_idx , sig_from ) ;
if ( end_bit > = sig_from & & end_bit < = sig_to )
end_bit = std : : max ( end_bit - 1 , sig_from ) ;
}
emit resizeSignal ( resize_sig , start_bit , end_bit - start_bit + 1 ) ;
} else {
emit addSignal ( from , to ) ;
auto [ sart_bit , end_bit ] = std : : minmax ( archor_bit_idx , release_bit_idx ) ;
emit addSignal ( sart_bit , end_bit - sart_bit + 1 , little_endian ) ;
}
clearSelection ( ) ;
}
clearSelection ( ) ;
anchor_index = QModelIndex ( ) ;
resize_sig = nullptr ;
}
void BinaryView : : leaveEvent ( QEvent * event ) {
@ -107,34 +141,17 @@ void BinaryView::leaveEvent(QEvent *event) {
void BinaryView : : setMessage ( const QString & message_id ) {
model - > setMessage ( message_id ) ;
clearSelection ( ) ;
anchor_index = QModelIndex ( ) ;
resize_sig = nullptr ;
hovered_sig = nullptr ;
updateState ( ) ;
}
const Signal * BinaryView : : getResizingSignal ( ) const {
if ( anchor_index . isValid ( ) ) {
auto item = ( const BinaryViewModel : : Item * ) anchor_index . internalPointer ( ) ;
if ( item & & item - > sigs . size ( ) > 0 ) {
int archor_pos = anchor_index . row ( ) * 8 + anchor_index . column ( ) ;
for ( auto s : item - > sigs ) {
auto [ sig_from , sig_to ] = getSignalRange ( s ) ;
if ( archor_pos = = sig_from | | archor_pos = = sig_to )
return s ;
}
}
}
return nullptr ;
}
QSet < const Signal * > BinaryView : : getOverlappingSignals ( ) const {
QSet < const Signal * > overlapping ;
for ( int i = 0 ; i < model - > rowCount ( ) ; + + i ) {
for ( int j = 0 ; j < model - > columnCount ( ) - 1 ; + + j ) {
auto item = ( const BinaryViewModel : : Item * ) model - > index ( i , j ) . internalPointer ( ) ;
if ( item & & item - > sigs . size ( ) > 1 ) {
for ( auto s : item - > sigs )
overlapping . insert ( s ) ;
}
}
for ( auto & item : model - > items ) {
if ( item . sigs . size ( ) > 1 )
for ( auto s : item . sigs ) overlapping + = s ;
}
return overlapping ;
}
@ -142,53 +159,37 @@ QSet<const Signal *> BinaryView::getOverlappingSignals() const {
// BinaryViewModel
void BinaryViewModel : : setMessage ( const QString & message_id ) {
msg_id = message_id ;
beginResetModel ( ) ;
msg_id = message_id ;
items . clear ( ) ;
row_count = 0 ;
dbc_msg = dbc ( ) - > msg ( msg_id ) ;
if ( dbc_msg ) {
if ( ( dbc_msg = dbc ( ) - > msg ( msg_id ) ) ) {
row_count = dbc_msg - > size ;
items . resize ( row_count * column_count ) ;
for ( int i = 0 ; i < dbc_msg - > sigs . size ( ) ; + + i ) {
const auto & sig = dbc_msg - > sigs [ i ] ;
auto [ start , end ] = getSignalRange ( & sig ) ;
for ( int j = start ; j < = end ; + + j ) {
int idx = column_count * ( j / 8 ) + j % 8 ;
int bit_index = sig . is_little_endian ? bigEndianBitIndex ( j ) : j ;
int idx = column_count * ( bit_index / 8 ) + bit_index % 8 ;
if ( idx > = items . size ( ) ) {
qWarning ( ) < < " signal " < < sig . name . c_str ( ) < < " out of bounds.start_bit: " < < sig . start_bit < < " size: " < < sig . size ;
break ;
}
if ( j = = start ) {
sig . is_little_endian ? items [ idx ] . is_lsb = true : items [ idx ] . is_msb = true ;
} else if ( j = = end ) {
sig . is_little_endian ? items [ idx ] . is_msb = true : items [ idx ] . is_lsb = true ;
}
if ( j = = start ) sig . is_little_endian ? items [ idx ] . is_lsb = true : items [ idx ] . is_msb = true ;
if ( j = = end ) sig . is_little_endian ? items [ idx ] . is_msb = true : items [ idx ] . is_lsb = true ;
items [ idx ] . bg_color = getColor ( i ) ;
items [ idx ] . sigs . push_back ( & dbc_msg - > sigs [ i ] ) ;
items [ idx ] . sigs . push_back ( & sig ) ;
}
}
} else {
row_count = can - > lastMessage ( msg_id ) . dat . size ( ) ;
items . resize ( row_count * column_count ) ;
}
endResetModel ( ) ;
}
QModelIndex BinaryViewModel : : index ( int row , int column , const QModelIndex & parent ) const {
return createIndex ( row , column , ( void * ) & items [ row * column_count + column ] ) ;
}
Qt : : ItemFlags BinaryViewModel : : flags ( const QModelIndex & index ) const {
return ( index . column ( ) = = column_count - 1 ) ? Qt : : ItemIsEnabled : Qt : : ItemIsEnabled | Qt : : ItemIsSelectable ;
}
void BinaryViewModel : : updateState ( ) {
auto prev_items = items ;
const auto & binary = can - > lastMessage ( msg_id ) . dat ;
// data size may changed.
if ( ! dbc_msg & & binary . size ( ) ! = row_count ) {
@ -198,7 +199,6 @@ void BinaryViewModel::updateState() {
items . resize ( row_count * column_count ) ;
endResetModel ( ) ;
}
char hex [ 3 ] = { ' \0 ' } ;
for ( int i = 0 ; i < std : : min ( binary . size ( ) , row_count ) ; + + i ) {
for ( int j = 0 ; j < column_count - 1 ; + + j ) {
@ -248,9 +248,8 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
BinaryView * bin_view = ( BinaryView * ) parent ( ) ;
painter - > save ( ) ;
bool hover = std : : find_if ( item - > sigs . begin ( ) , item - > sigs . end ( ) , [ = ] ( auto s ) { return s = = bin_view - > hoveredSignal ( ) ; } ) ! =
item - > sigs . end ( ) ;
// background
bool hover = item - > sigs . contains ( bin_view - > hoveredSignal ( ) ) ;
QColor bg_color = hover ? hoverColor ( item - > bg_color ) : item - > bg_color ;
if ( option . state & QStyle : : State_Selected ) {
bg_color = selection_color ;
@ -258,7 +257,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
painter - > fillRect ( option . rect , bg_color ) ;
// text
if ( index . column ( ) = = 8 ) { // hex column
if ( index . column ( ) = = 8 ) { // hex column
painter - > setFont ( hex_font ) ;
} else if ( hover ) {
painter - > setPen ( Qt : : white ) ;