BreakpointDialog.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include "BreakpointDialog.h"
  2. #include "DebugSession.h"
  3. #include "Convert.h"
  4. #include <QCompleter>
  5. #include <QStandardItemModel>
  6. BreakpointDialog::BreakpointDialog(const MemoryLayout& ml, DebugSession *session, QWidget* parent)
  7. : QDialog(parent), memLayout(ml), currentSymbol(0)
  8. {
  9. setupUi(this);
  10. value = valueEnd = -1;
  11. debugSession = session;
  12. if( session ) {
  13. // create address completer
  14. jumpCompleter = new QCompleter(session->symbolTable().labelList(), this);
  15. allCompleter = new QCompleter(session->symbolTable().labelList(true), this);
  16. jumpCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  17. allCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  18. connect(jumpCompleter, SIGNAL(activated(const QString&)), this, SLOT(addressChanged(const QString&)));
  19. connect(allCompleter, SIGNAL(activated(const QString&)), this, SLOT(addressChanged(const QString&)));
  20. }
  21. connect(edtAddress, SIGNAL(textEdited(const QString&)), this, SLOT(addressChanged(const QString&)));
  22. connect(edtAddressRange, SIGNAL(textEdited(const QString&)), this, SLOT(addressChanged(const QString&)));
  23. connect(cmbxType, SIGNAL(activated(int)), this, SLOT(typeChanged(int)));
  24. connect(cmbxSlot, SIGNAL(activated(int)), this, SLOT(slotChanged(int)));
  25. connect(cmbxSubslot, SIGNAL(activated(int)), this, SLOT(subslotChanged(int)));
  26. connect(cbCondition, SIGNAL(stateChanged(int)), this, SLOT(hasCondition(int)));
  27. typeChanged(0);
  28. slotChanged(0);
  29. idxSlot = idxSubSlot = 0;
  30. hasCondition(0);
  31. }
  32. BreakpointDialog::~BreakpointDialog()
  33. {
  34. delete jumpCompleter;
  35. delete allCompleter;
  36. }
  37. Breakpoints::Type BreakpointDialog::type()
  38. {
  39. return Breakpoints::Type(cmbxType->currentIndex());
  40. }
  41. int BreakpointDialog::address()
  42. {
  43. return value;
  44. }
  45. int BreakpointDialog::addressEndRange()
  46. {
  47. if (valueEnd < value)
  48. return value;
  49. else
  50. return valueEnd;
  51. }
  52. int BreakpointDialog::slot()
  53. {
  54. return cmbxSlot->currentIndex() - 1;
  55. }
  56. int BreakpointDialog::subslot()
  57. {
  58. return cmbxSubslot->currentIndex() - 1;
  59. }
  60. int BreakpointDialog::segment()
  61. {
  62. return cmbxSegment->currentIndex() - 1;
  63. }
  64. QString BreakpointDialog::condition()
  65. {
  66. if( cbCondition->checkState() == Qt::Checked )
  67. return txtCondition->toPlainText();
  68. else
  69. return QString();
  70. }
  71. void BreakpointDialog::setData(Breakpoints::Type type, int address, int ps, int ss, int segment,
  72. int addressEnd, QString condition)
  73. {
  74. // set type
  75. cmbxType->setCurrentIndex(int(type));
  76. typeChanged(cmbxType->currentIndex());
  77. // set address
  78. if (address >= 0) {
  79. edtAddress->setText( hexValue(address) );
  80. addressChanged(edtAddress->text());
  81. }
  82. // primary slot
  83. if (cmbxSlot->isEnabled() && ps >= 0) {
  84. cmbxSlot->setCurrentIndex(ps+1);
  85. slotChanged(cmbxSlot->currentIndex());
  86. }
  87. // secondary slot
  88. if (cmbxSubslot->isEnabled() && ss >= 0) {
  89. cmbxSubslot->setCurrentIndex(ss+1);
  90. subslotChanged(cmbxSubslot->currentIndex());
  91. }
  92. // segment
  93. if (cmbxSegment->isEnabled() && segment >= 0) {
  94. cmbxSegment->setCurrentIndex(segment+1);
  95. }
  96. // end address
  97. if (edtAddressRange->isEnabled() && addressEnd >= 0) {
  98. edtAddressRange->setText( hexValue(addressEnd) );
  99. addressChanged(edtAddressRange->text());
  100. }
  101. // condition
  102. condition = condition.trimmed();
  103. if (cbCondition->isChecked() == condition.isEmpty())
  104. cbCondition->setChecked(!condition.isEmpty());
  105. txtCondition->setText(condition);
  106. }
  107. void BreakpointDialog::addressChanged(const QString& text)
  108. {
  109. // determine source
  110. QLineEdit *ed;
  111. if (text == edtAddress->text())
  112. ed = edtAddress;
  113. else
  114. ed = edtAddressRange;
  115. bool first = ed == edtAddress;
  116. // convert value
  117. int v = stringToValue(text);
  118. if (v == -1 && debugSession) {
  119. Symbol *s = debugSession->symbolTable().getAddressSymbol(text);
  120. if (s) v = s->value();
  121. if (first) currentSymbol = s;
  122. }
  123. // assign address
  124. if (first)
  125. value = v;
  126. else {
  127. if (v > value)
  128. valueEnd = v;
  129. else {
  130. valueEnd = -1;
  131. v = -1;
  132. }
  133. }
  134. // adjust controls for (in)correct values
  135. QStandardItemModel* model = qobject_cast<QStandardItemModel*>(cmbxSlot->model());
  136. QPalette pal;
  137. if (v == -1) {
  138. // set line edit text to red for invalid values TODO: make configurable
  139. pal.setColor(QPalette::Normal, QPalette::Text, Qt::red);
  140. ed->setPalette(pal);
  141. if (first) {
  142. cmbxSlot->setCurrentIndex(0);
  143. cmbxSlot->setEnabled(false);
  144. }
  145. } else {
  146. //pal.setColor(QPalette::Normal, QPalette::Text, Qt::black);
  147. ed->setPalette(pal);
  148. if (!first) return;
  149. cmbxSlot->setEnabled(true);
  150. if(currentSymbol) {
  151. // enable allowed slots
  152. int s = currentSymbol->validSlots();
  153. int num = 0, last = 0;
  154. for(int i = 4; i >= 0; i--) {
  155. QModelIndex index = model->index(i, 0, cmbxSlot->rootModelIndex());
  156. if(i) {
  157. bool ena = (s & (15<<(4*(i-1)))) != 0;
  158. model->itemFromIndex(index)->setEnabled(ena);
  159. if(ena) {
  160. num++;
  161. last = i;
  162. }
  163. } else {
  164. model->itemFromIndex(index)->setEnabled( num == 4 );
  165. if(num == 4) last = 0;
  166. }
  167. }
  168. cmbxSlot->setCurrentIndex(last);
  169. } else {
  170. // enable everything
  171. for(int i = 0; i < 5; i++) {
  172. QModelIndex index = model->index(i, 0, cmbxSlot->rootModelIndex());
  173. model->itemFromIndex(index)->setEnabled(true);
  174. }
  175. cmbxSlot->setCurrentIndex(idxSlot);
  176. }
  177. }
  178. slotChanged(cmbxSlot->currentIndex());
  179. }
  180. void BreakpointDialog::typeChanged(int s)
  181. {
  182. switch(s) {
  183. case 1:
  184. case 2:
  185. lblAddress->setText(tr("Add watchpoint at memory address or range:"));
  186. edtAddressRange->setVisible(true);
  187. edtAddress->setCompleter(allCompleter);
  188. edtAddressRange->setCompleter(allCompleter);
  189. break;
  190. case 3:
  191. case 4:
  192. lblAddress->setText(tr("Add watchpoint on IO port or range:"));
  193. edtAddressRange->setVisible(true);
  194. edtAddress->setCompleter(0);
  195. edtAddressRange->setCompleter(0);
  196. break;
  197. default:
  198. lblAddress->setText(tr("Add breakpoint at address:"));
  199. edtAddressRange->setVisible(false);
  200. edtAddress->setCompleter(jumpCompleter);
  201. }
  202. switch(s) {
  203. case 1:
  204. case 2:
  205. lblInSlot->setText(tr("With address in"));
  206. break;
  207. default:
  208. lblInSlot->setText(tr("With PC in"));
  209. }
  210. if(s == 5) {
  211. lblAddress->setEnabled(false);
  212. edtAddress->setEnabled(false);
  213. lblSlot->setEnabled(false);
  214. lblSubslot->setEnabled(false);
  215. lblSegment->setEnabled(false);
  216. cmbxSlot->setEnabled(false);
  217. cmbxSubslot->setEnabled(false);
  218. cmbxSegment->setEnabled(false);
  219. cbCondition->setCheckState(Qt::Checked);
  220. cbCondition->setEnabled(false);
  221. } else {
  222. lblAddress->setEnabled(true);
  223. edtAddress->setEnabled(true);
  224. lblSlot->setEnabled(true);
  225. lblSubslot->setEnabled(true);
  226. lblSegment->setEnabled(true);
  227. addressChanged(edtAddress->text());
  228. cbCondition->setEnabled(true);
  229. cbCondition->setCheckState( txtCondition->toPlainText().isEmpty() ? Qt::Unchecked : Qt::Checked );
  230. }
  231. }
  232. void BreakpointDialog::slotChanged(int s)
  233. {
  234. if(!currentSymbol) idxSlot = s;
  235. if (s && memLayout.isSubslotted[s - 1]) {
  236. if(currentSymbol) {
  237. // enable subslots
  238. int v = (currentSymbol->validSlots() >> (4*(s-1))) & 15;
  239. int num = 0, last = 0;
  240. QStandardItemModel* model = qobject_cast<QStandardItemModel*>(cmbxSubslot->model());
  241. for(int i = 4; i >= 0; i--) {
  242. QModelIndex index = model->index(i, 0, cmbxSubslot->rootModelIndex());
  243. if(i) {
  244. bool ena = (v & (1<<(i-1))) != 0;
  245. model->itemFromIndex(index)->setEnabled(ena);
  246. if(ena) {
  247. num++;
  248. last = i;
  249. }
  250. } else {
  251. model->itemFromIndex(index)->setEnabled( num == 4 );
  252. if(num == 4) last = 0;
  253. }
  254. }
  255. cmbxSubslot->setCurrentIndex(last);
  256. } else {
  257. cmbxSubslot->setCurrentIndex(idxSubSlot);
  258. }
  259. cmbxSubslot->setEnabled(true);
  260. } else {
  261. cmbxSubslot->setEnabled(false);
  262. cmbxSubslot->setCurrentIndex(0);
  263. }
  264. subslotChanged(cmbxSubslot->currentIndex());
  265. }
  266. void BreakpointDialog::subslotChanged(int i)
  267. {
  268. if(!currentSymbol) idxSubSlot = i;
  269. int oldseg = cmbxSegment->currentIndex()-1;
  270. cmbxSegment->clear();
  271. cmbxSegment->addItem("any");
  272. int ps = cmbxSlot->currentIndex() - 1;
  273. int ss = i - 1;
  274. if (ps >=0 && !memLayout.isSubslotted[ps]) ss = 0;
  275. int mapsize;
  276. if (ps < 0 || ss < 0 || memLayout.mapperSize[ps][ss] == 0) {
  277. // no memory mapper, maybe rom mapper?
  278. if (value >= 0 && memLayout.romBlock[((value & 0xE000)>>13)] >= 0) {
  279. mapsize = 256; // TODO: determine real size
  280. } else {
  281. cmbxSegment->setEnabled(false);
  282. cmbxSegment->setCurrentIndex(0);
  283. return;
  284. }
  285. } else
  286. mapsize = memLayout.mapperSize[ps][ss];
  287. for (int s = 0; s < mapsize; ++s) {
  288. cmbxSegment->addItem(QString("%1").arg(s));
  289. }
  290. cmbxSegment->setEnabled(true);
  291. if (oldseg >= 0 && oldseg < mapsize)
  292. cmbxSegment->setCurrentIndex(oldseg+1);
  293. }
  294. void BreakpointDialog::hasCondition(int state)
  295. {
  296. if( state == Qt::Checked ) {
  297. txtCondition->setVisible(true);
  298. layout()->setSizeConstraint(QLayout::SetDefaultConstraint);
  299. resize( width(), conditionHeight );
  300. } else {
  301. conditionHeight = height();
  302. txtCondition->setVisible(false);
  303. resize( width(), sizeHint().height() );
  304. layout()->setSizeConstraint(QLayout::SetMaximumSize);
  305. }
  306. }