StackViewer.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "StackViewer.h"
  2. #include "OpenMSXConnection.h"
  3. #include "CommClient.h"
  4. #include "Settings.h"
  5. #include <QScrollBar>
  6. #include <QPaintEvent>
  7. #include <QPainter>
  8. #include <cmath>
  9. class StackRequest : public ReadDebugBlockCommand
  10. {
  11. public:
  12. StackRequest(unsigned offset_, unsigned size,
  13. unsigned char* target, StackViewer& viewer_)
  14. : ReadDebugBlockCommand("memory", offset_, size, target)
  15. , offset(offset_)
  16. , viewer(viewer_)
  17. {
  18. }
  19. virtual void replyOk(const QString& message)
  20. {
  21. copyData(message);
  22. viewer.memdataTransfered(this);
  23. }
  24. virtual void cancel()
  25. {
  26. viewer.transferCancelled(this);
  27. }
  28. // TODO public members are ugly!!
  29. unsigned offset;
  30. private:
  31. StackViewer& viewer;
  32. };
  33. StackViewer::StackViewer(QWidget* parent)
  34. : QFrame(parent)
  35. {
  36. setFrameStyle(WinPanel | Sunken);
  37. setFocusPolicy(Qt::StrongFocus);
  38. setBackgroundRole(QPalette::Base);
  39. setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred));
  40. setFont(Settings::get().font(Settings::HEX_FONT));
  41. stackPointer = 0;
  42. topAddress = 0;
  43. waitingForData = false;
  44. vertScrollBar = new QScrollBar(Qt::Vertical, this);
  45. vertScrollBar->hide();
  46. frameL = frameT = frameB = frameWidth();
  47. frameR = frameL + vertScrollBar->sizeHint().width();
  48. setMinimumHeight(frameT+frameB+fontMetrics().height());
  49. connect(vertScrollBar, SIGNAL(valueChanged(int)),
  50. this, SLOT(setLocation(int)));
  51. }
  52. QSize StackViewer::sizeHint() const
  53. {
  54. return QSize(frameL + 4 + fontMetrics().width("FFFFWFFFF ") + 4 + frameR,
  55. frameT + 8 * fontMetrics().height() + frameB);
  56. }
  57. void StackViewer::setScrollBarValues()
  58. {
  59. vertScrollBar->setMinimum(stackPointer);
  60. visibleLines = double(height() - frameT - frameB) / fontMetrics().height();
  61. int lines = (memoryLength - stackPointer) / 2;
  62. vertScrollBar->setMaximum(stackPointer + 2 * (lines - int(visibleLines)));
  63. vertScrollBar->setSingleStep(2);
  64. vertScrollBar->setPageStep(2 * int(visibleLines));
  65. }
  66. void StackViewer::resizeEvent(QResizeEvent* e)
  67. {
  68. QFrame::resizeEvent(e);
  69. setScrollBarValues();
  70. vertScrollBar->setGeometry(width() - frameR, frameT,
  71. vertScrollBar->sizeHint().width(),
  72. height() - frameT - frameB);
  73. vertScrollBar->show();
  74. // calc the number of lines that can be displayed
  75. // partial lines count as a whole
  76. }
  77. void StackViewer::paintEvent(QPaintEvent* e)
  78. {
  79. // call parent for drawing the actual frame
  80. QFrame::paintEvent(e);
  81. QPainter p(this);
  82. int h = fontMetrics().height();
  83. int d = fontMetrics().descent();
  84. // set font
  85. p.setPen(Qt::black);
  86. // calc and set drawing bounds
  87. QRect r(e->rect());
  88. if (r.left() < frameL) r.setLeft(frameL);
  89. if (r.top() < frameT) r.setTop (frameT);
  90. if (r.right() > width() - frameR - 1) r.setRight (width() - frameR - 1);
  91. if (r.bottom() > height() - frameB - 1) r.setBottom(height() - frameB - 1);
  92. p.setClipRect(r);
  93. // redraw background
  94. p.fillRect(r, palette().color(QPalette::Base));
  95. // calc layout (not optimal)
  96. int xAddr = frameL + 8;
  97. int xStack = xAddr + fontMetrics().width("FFFFF");
  98. int y = frameT + h - 1;
  99. int address = topAddress;
  100. for (int i = 0; i < int(ceil(visibleLines)); ++i) {
  101. // print address
  102. QString hexStr;
  103. hexStr.sprintf("%04X", address);
  104. p.drawText(xAddr, y - d, hexStr);
  105. hexStr.sprintf("%02X%02X", memory[address + 1], memory[address]);
  106. p.drawText(xStack, y - d, hexStr);
  107. y += h;
  108. address += 2;
  109. if (address >= memoryLength - 1) break;
  110. }
  111. }
  112. void StackViewer::setData(unsigned char* memPtr, int memLength)
  113. {
  114. memory = memPtr;
  115. memoryLength = memLength;
  116. setScrollBarValues();
  117. }
  118. void StackViewer::setLocation(int addr)
  119. {
  120. if (waitingForData) {
  121. // ignore
  122. return;
  123. }
  124. int start = (addr & ~1) | (stackPointer & 1);
  125. int size = 2 * int(ceil(visibleLines));
  126. if (start + size >= memoryLength) {
  127. size = memoryLength - start;
  128. }
  129. StackRequest* req = new StackRequest(start, size,
  130. &memory[start], *this);
  131. CommClient::instance().sendCommand(req);
  132. waitingForData = true;
  133. }
  134. void StackViewer::setStackPointer(quint16 addr)
  135. {
  136. stackPointer = addr;
  137. setScrollBarValues();
  138. vertScrollBar->setValue(addr);
  139. setLocation(addr);
  140. }
  141. void StackViewer::memdataTransfered(StackRequest* r)
  142. {
  143. topAddress = r->offset;
  144. update();
  145. waitingForData = false;
  146. delete r;
  147. // check whether a new value is available
  148. if ((topAddress & ~1) != (vertScrollBar->value() & ~1)) {
  149. setLocation(vertScrollBar->value());
  150. }
  151. }
  152. void StackViewer::transferCancelled(StackRequest* r)
  153. {
  154. waitingForData = false;
  155. delete r;
  156. }