@@ -355,37 +355,48 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
355355 // Get the row height
356356 m_rowHeight = fm.height () + 2 ;
357357
358- // Find the amount of visible rows
359- m_visibleRows = h / m_rowHeight;
358+ // Find the amount of visible disassembly rows. Minus 1 to not count column title row.
359+ m_visibleRows = h / m_rowHeight - 1 ;
360360
361361 m_disassemblyManager.analyze (m_visibleStart, m_disassemblyManager.getNthNextAddress (m_visibleStart, m_visibleRows) - m_visibleStart);
362362
363- // Draw the rows
363+ const u32 curPC = cpu ().getPC (); // Get the PC here, because it'll change when we are drawing and make it seem like there are two PCs
364+
365+ // Format and draw title line on first row
366+ const QString titleLineString = GetDisassemblyTitleLine ();
367+ const QColor titleLineColor = GetDisassemblyTitleLineColor ();
368+ painter.fillRect (0 , 0 * m_rowHeight, w, m_rowHeight, titleLineColor);
369+ painter.drawText (2 , 0 * m_rowHeight, w, m_rowHeight, Qt::AlignLeft, titleLineString);
370+
371+ // Prepare to draw the disassembly rows
364372 bool inSelectionBlock = false ;
365373 bool alternate = m_visibleStart % 8 ;
366374
367- const u32 curPC = cpu ().getPC (); // Get the PC here, because it'll change when we are drawing and make it seem like there are two PCs
368-
375+ // Draw visible disassembly rows
369376 for (u32 i = 0 ; i <= m_visibleRows; i++)
370377 {
378+ // Address of instruction being displayed on row
371379 const u32 rowAddress = (i * 4 ) + m_visibleStart;
372- // Row backgrounds
373380
381+ // Row will be drawn at row index+1 to offset past title row
382+ const u32 rowIndex = (i + 1 ) * m_rowHeight;
383+
384+ // Row backgrounds
374385 if (inSelectionBlock || (m_selectedAddressStart <= rowAddress && rowAddress <= m_selectedAddressEnd))
375386 {
376- painter.fillRect (0 , i * m_rowHeight , w, m_rowHeight, this ->palette ().highlight ());
387+ painter.fillRect (0 , rowIndex , w, m_rowHeight, this ->palette ().highlight ());
377388 inSelectionBlock = m_selectedAddressEnd != rowAddress;
378389 }
379390 else
380391 {
381- painter.fillRect (0 , i * m_rowHeight , w, m_rowHeight, alternate ? this ->palette ().base () : this ->palette ().alternateBase ());
392+ painter.fillRect (0 , rowIndex , w, m_rowHeight, alternate ? this ->palette ().base () : this ->palette ().alternateBase ());
382393 }
383394
384395 // Row text
385396 painter.setPen (GetAddressFunctionColor (rowAddress));
386397 QString lineString = DisassemblyStringFromAddress (rowAddress, painter.font (), curPC, rowAddress == m_selectedAddressStart);
387398
388- painter.drawText (2 , i * m_rowHeight , w, m_rowHeight, Qt::AlignLeft, lineString);
399+ painter.drawText (2 , rowIndex , w, m_rowHeight, Qt::AlignLeft, lineString);
389400
390401 // Breakpoint marker
391402 bool enabled;
@@ -394,11 +405,11 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
394405 if (enabled)
395406 {
396407 painter.setPen (Qt::green);
397- painter.drawText (2 , i * m_rowHeight , w, m_rowHeight, Qt::AlignLeft, " \u25A0 " );
408+ painter.drawText (2 , rowIndex , w, m_rowHeight, Qt::AlignLeft, " \u25A0 " );
398409 }
399410 else
400411 {
401- painter.drawText (2 , i * m_rowHeight , w, m_rowHeight, Qt::AlignLeft, " \u2612 " );
412+ painter.drawText (2 , rowIndex , w, m_rowHeight, Qt::AlignLeft, " \u2612 " );
402413 }
403414 }
404415 alternate = !alternate;
@@ -435,9 +446,10 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
435446 // Explaination
436447 // ((branchLine.first - m_visibleStart) -> Find the amount of bytes from the top of the view
437448 // / 4 -> Convert that into rowss in instructions
449+ // + 1 -> Offset 1 to account for column title row
438450 // * m_rowHeight -> convert that into rows in pixels
439451 // + (m_rowHeight / 2) -> Add half a row in pixels to center the arrow
440- top = (((branchLine.first - m_visibleStart) / 4 ) * m_rowHeight) + (m_rowHeight / 2 );
452+ top = (((branchLine.first - m_visibleStart) / 4 + 1 ) * m_rowHeight) + (m_rowHeight / 2 );
441453 }
442454
443455 if (branchLine.second < m_visibleStart)
@@ -450,7 +462,7 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
450462 }
451463 else
452464 {
453- bottom = (((branchLine.second - m_visibleStart) / 4 ) * m_rowHeight) + (m_rowHeight / 2 );
465+ bottom = (((branchLine.second - m_visibleStart) / 4 + 1 ) * m_rowHeight) + (m_rowHeight / 2 );
454466 }
455467
456468 branchCount++;
@@ -467,7 +479,8 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
467479 if (top < 0 ) // first is not visible, but second is
468480 {
469481 painter.drawLine (x - 2 , bottom, x + 2 , bottom);
470- painter.drawLine (x + 2 , bottom, x + 2 , 0 );
482+ // Draw to first visible disassembly row so branch line is not drawn on title line
483+ painter.drawLine (x + 2 , bottom, x + 2 , m_rowHeight);
471484
472485 if (branchLine.type == LINE_DOWN)
473486 {
@@ -515,40 +528,56 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
515528
516529void DisassemblyWidget::mousePressEvent (QMouseEvent* event)
517530{
518- const u32 selectedAddress = (static_cast <int >(event->position ().y ()) / m_rowHeight * 4 ) + m_visibleStart;
519- if (event->buttons () & Qt::LeftButton)
531+ // Calculate index of row that was clicked
532+ const u32 selectedRowIndex = static_cast <int >(event->position ().y ()) / m_rowHeight;
533+
534+ // Only process if a row other than the column title row was clicked
535+ if (selectedRowIndex > 0 )
520536 {
521- if (event->modifiers () & Qt::ShiftModifier)
537+ // Calculate address of selected row. Index minus one for title row.
538+ const u32 selectedAddress = ((selectedRowIndex - 1 ) * 4 ) + m_visibleStart;
539+ if (event->buttons () & Qt::LeftButton)
522540 {
523- if (selectedAddress < m_selectedAddressStart )
541+ if (event-> modifiers () & Qt::ShiftModifier )
524542 {
525- m_selectedAddressStart = selectedAddress;
543+ if (selectedAddress < m_selectedAddressStart)
544+ {
545+ m_selectedAddressStart = selectedAddress;
546+ }
547+ else if (selectedAddress > m_visibleStart)
548+ {
549+ m_selectedAddressEnd = selectedAddress;
550+ }
526551 }
527- else if (selectedAddress > m_visibleStart)
552+ else
528553 {
554+ m_selectedAddressStart = selectedAddress;
529555 m_selectedAddressEnd = selectedAddress;
530556 }
531557 }
532- else
533- {
534- m_selectedAddressStart = selectedAddress;
535- m_selectedAddressEnd = selectedAddress;
536- }
537- }
538- else if (event->buttons () & Qt::RightButton)
539- {
540- if (m_selectedAddressStart == m_selectedAddressEnd)
558+ else if (event->buttons () & Qt::RightButton)
541559 {
542- m_selectedAddressStart = selectedAddress;
543- m_selectedAddressEnd = selectedAddress;
560+ if (m_selectedAddressStart == m_selectedAddressEnd)
561+ {
562+ m_selectedAddressStart = selectedAddress;
563+ m_selectedAddressEnd = selectedAddress;
564+ }
544565 }
566+ this ->repaint ();
545567 }
546- this ->repaint ();
547568}
548569
549570void DisassemblyWidget::mouseDoubleClickEvent (QMouseEvent* event)
550571{
551- toggleBreakpoint ((static_cast <int >(event->position ().y ()) / m_rowHeight * 4 ) + m_visibleStart);
572+ // Calculate index of row that was double clicked
573+ const u32 selectedRowIndex = static_cast <int >(event->position ().y ()) / m_rowHeight;
574+
575+ // Only process if a row other than the column title row was double clicked
576+ if (selectedRowIndex > 0 )
577+ {
578+ // Calculate address of selected row. Index minus one for title row.
579+ toggleBreakpoint (((selectedRowIndex - 1 ) * 4 ) + m_visibleStart);
580+ }
552581}
553582
554583void DisassemblyWidget::wheelEvent (QWheelEvent* event)
@@ -641,6 +670,10 @@ void DisassemblyWidget::openContextMenu(QPoint pos)
641670 if (!cpu ().isAlive ())
642671 return ;
643672
673+ // Dont open context menu when used on column title row
674+ if (pos.y () / m_rowHeight == 0 )
675+ return ;
676+
644677 QMenu* menu = new QMenu (this );
645678 menu->setAttribute (Qt::WA_DeleteOnClose);
646679
@@ -743,6 +776,51 @@ void DisassemblyWidget::openContextMenu(QPoint pos)
743776 menu->popup (this ->mapToGlobal (pos));
744777}
745778
779+ QString DisassemblyWidget::GetDisassemblyTitleLine ()
780+ {
781+ // Disassembly column title line based on format created by DisassemblyStringFromAddress()
782+ QString title_line_string;
783+
784+ // Determine layout of disassembly row. Layout depends on user setting "Show Instruction Bytes".
785+ const bool show_instruction_bytes = m_showInstructionBytes && cpu ().isAlive ();
786+ if (show_instruction_bytes)
787+ {
788+ title_line_string = QCoreApplication::translate (" DisassemblyWidgetColumnTitle" , " %1 %2 %3 %4" );
789+ }
790+ else
791+ {
792+ title_line_string = QCoreApplication::translate (" DisassemblyWidgetColumnTitle" , " %1 %2 %3" );
793+ }
794+
795+ // First 2 chars in disassembly row is always for non-returning functions (NR)
796+ // Do not display column title for this field.
797+ title_line_string = title_line_string.arg (" " );
798+
799+ // Second column title is always address of instruction
800+ title_line_string = title_line_string.arg (QCoreApplication::translate (" DisassemblyWidgetColumnTitle" , " Location" ));
801+
802+ // If user specified to "Show Instruction Bytes", third column is opcode + args
803+ if (show_instruction_bytes)
804+ {
805+ title_line_string = title_line_string.arg (QCoreApplication::translate (" DisassemblyWidgetColumnTitle" , " Bytes " ));
806+ }
807+
808+ // Last column title is always disassembled instruction
809+ title_line_string = title_line_string.arg (QCoreApplication::translate (" DisassemblyWidgetColumnTitle" , " Instruction" ));
810+
811+ return title_line_string;
812+ }
813+
814+ QColor DisassemblyWidget::GetDisassemblyTitleLineColor ()
815+ {
816+ // Determine color of column title line. Based on QFusionStyle.
817+ QColor title_line_color = this ->palette ().button ().color ();
818+ const int title_line_color_val = qGray (title_line_color.rgb ());
819+ title_line_color = title_line_color.lighter (100 + qMax (1 , (180 - title_line_color_val) / 6 ));
820+ title_line_color.setHsv (title_line_color.hue (), title_line_color.saturation () * 0.75 , title_line_color.value ());
821+ return title_line_color.lighter (104 );
822+ }
823+
746824inline QString DisassemblyWidget::DisassemblyStringFromAddress (u32 address, QFont font, u32 pc, bool selected)
747825{
748826 DisassemblyLineInfo line;
0 commit comments