SymbolManager.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. #include "SymbolManager.h"
  2. #include "SymbolTable.h"
  3. #include "Settings.h"
  4. #include "Convert.h"
  5. #include <QFileDialog>
  6. #include <QMessageBox>
  7. #include <QHeaderView>
  8. SymbolManager::SymbolManager(SymbolTable& symtable, QWidget* parent)
  9. : QDialog(parent), symTable(symtable)
  10. {
  11. setupUi(this);
  12. // restore layout
  13. Settings& s = Settings::get();
  14. restoreGeometry(s.value("SymbolManager/WindowGeometry", saveGeometry()).toByteArray());
  15. treeFiles->header()->restoreState(s.value("SymbolManager/HeaderFiles",
  16. treeFiles->header()->saveState()).toByteArray());
  17. treeLabels->header()->restoreState(s.value("SymbolManager/HeaderSymbols",
  18. treeLabels->header()->saveState()).toByteArray());
  19. treeLabelsUpdateCount = 0;
  20. editColumn = -1;
  21. // put slot checkboxes in a convenience array
  22. chkSlots[ 0] = chk00; chkSlots[ 1] = chk01; chkSlots[ 2] = chk02; chkSlots[ 3] = chk03;
  23. chkSlots[ 4] = chk10; chkSlots[ 5] = chk11; chkSlots[ 6] = chk12; chkSlots[ 7] = chk13;
  24. chkSlots[ 8] = chk20; chkSlots[ 9] = chk21; chkSlots[10] = chk22; chkSlots[11] = chk23;
  25. chkSlots[12] = chk30; chkSlots[13] = chk31; chkSlots[14] = chk32; chkSlots[15] = chk33;
  26. chkRegs[ 0] = chkRegA; chkRegs[ 1] = chkRegB; chkRegs[ 2] = chkRegC; chkRegs[ 3] = chkRegD;
  27. chkRegs[ 4] = chkRegE; chkRegs[ 5] = chkRegH; chkRegs[ 6] = chkRegL; chkRegs[ 7] = chkRegBC;
  28. chkRegs[ 8] = chkRegDE; chkRegs[ 9] = chkRegHL; chkRegs[10] = chkRegIX; chkRegs[11] = chkRegIY;
  29. chkRegs[12] = chkRegIXL;chkRegs[13] = chkRegIXH;chkRegs[14] = chkRegIYL;chkRegs[15] = chkRegIYH;
  30. chkRegs[16] = chkRegOffset; chkRegs[17] = chkRegI;
  31. connect(treeFiles, SIGNAL(itemSelectionChanged()), this, SLOT(fileSelectionChange()));
  32. connect(btnAddFile, SIGNAL(clicked()), this, SLOT(addFile()));
  33. connect(btnRemoveFile, SIGNAL(clicked()), this, SLOT(removeFile()));
  34. connect(btnReloadFiles, SIGNAL(clicked()), this, SLOT(reloadFiles()));
  35. connect(treeLabels, SIGNAL(itemSelectionChanged()), this, SLOT(labelSelectionChanged()));
  36. connect(treeLabels, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
  37. this, SLOT(labelEdit(QTreeWidgetItem*, int)));
  38. connect(treeLabels, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
  39. this, SLOT(labelChanged(QTreeWidgetItem*, int)));
  40. connect(btnAddSymbol, SIGNAL(clicked()), this, SLOT(addLabel()));
  41. connect(btnRemoveSymbol, SIGNAL(clicked()), this, SLOT(removeLabel()));
  42. connect(radJump, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
  43. connect(radVar, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
  44. connect(radValue, SIGNAL(toggled(bool)), this, SLOT(changeType(bool)));
  45. connect(chk00, SIGNAL(stateChanged(int)), this, SLOT(changeSlot00(int)));
  46. connect(chk01, SIGNAL(stateChanged(int)), this, SLOT(changeSlot01(int)));
  47. connect(chk02, SIGNAL(stateChanged(int)), this, SLOT(changeSlot02(int)));
  48. connect(chk03, SIGNAL(stateChanged(int)), this, SLOT(changeSlot03(int)));
  49. connect(chk10, SIGNAL(stateChanged(int)), this, SLOT(changeSlot10(int)));
  50. connect(chk11, SIGNAL(stateChanged(int)), this, SLOT(changeSlot11(int)));
  51. connect(chk12, SIGNAL(stateChanged(int)), this, SLOT(changeSlot12(int)));
  52. connect(chk13, SIGNAL(stateChanged(int)), this, SLOT(changeSlot13(int)));
  53. connect(chk20, SIGNAL(stateChanged(int)), this, SLOT(changeSlot20(int)));
  54. connect(chk21, SIGNAL(stateChanged(int)), this, SLOT(changeSlot21(int)));
  55. connect(chk22, SIGNAL(stateChanged(int)), this, SLOT(changeSlot22(int)));
  56. connect(chk23, SIGNAL(stateChanged(int)), this, SLOT(changeSlot23(int)));
  57. connect(chk30, SIGNAL(stateChanged(int)), this, SLOT(changeSlot30(int)));
  58. connect(chk31, SIGNAL(stateChanged(int)), this, SLOT(changeSlot31(int)));
  59. connect(chk32, SIGNAL(stateChanged(int)), this, SLOT(changeSlot32(int)));
  60. connect(chk33, SIGNAL(stateChanged(int)), this, SLOT(changeSlot33(int)));
  61. connect(chkRegA, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterA(int)));
  62. connect(chkRegB, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterB(int)));
  63. connect(chkRegC, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterC(int)));
  64. connect(chkRegD, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterD(int)));
  65. connect(chkRegE, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterE(int)));
  66. connect(chkRegH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterH(int)));
  67. connect(chkRegL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterL(int)));
  68. connect(chkRegBC, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterBC(int)));
  69. connect(chkRegDE, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterDE(int)));
  70. connect(chkRegHL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterHL(int)));
  71. connect(chkRegIX, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIX(int)));
  72. connect(chkRegIY, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIY(int)));
  73. connect(chkRegIXL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIXL(int)));
  74. connect(chkRegIXH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIXH(int)));
  75. connect(chkRegIYL, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIYL(int)));
  76. connect(chkRegIYH, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterIYH(int)));
  77. connect(chkRegOffset, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterOffset(int)));
  78. connect(chkRegI, SIGNAL(stateChanged(int)), this, SLOT(changeRegisterI(int)));
  79. groupSlots->setEnabled(false);
  80. groupSegments->setEnabled(false);
  81. btnRemoveFile->setEnabled(false);
  82. btnRemoveSymbol->setEnabled(false);
  83. initFileList();
  84. initSymbolList();
  85. }
  86. void SymbolManager::closeEvent(QCloseEvent* e)
  87. {
  88. // store layout
  89. Settings& s = Settings::get();
  90. s.setValue("SymbolManager/WindowGeometry", saveGeometry());
  91. s.setValue("SymbolManager/HeaderFiles", treeFiles->header()->saveState());
  92. s.setValue("SymbolManager/HeaderSymbols", treeLabels->header()->saveState());
  93. QDialog::closeEvent(e);
  94. }
  95. /*
  96. * File list support functions
  97. */
  98. void SymbolManager::initFileList()
  99. {
  100. treeFiles->clear();
  101. for (int i = 0; i < symTable.symbolFilesSize(); ++i) {
  102. QTreeWidgetItem* item = new QTreeWidgetItem(treeFiles);
  103. item->setText(0, symTable.symbolFile(i));
  104. item->setText(1, symTable.symbolFileRefresh(i).toString(Qt::LocaleDate));
  105. }
  106. }
  107. void SymbolManager::addFile()
  108. {
  109. // create dialog
  110. QFileDialog* d = new QFileDialog(this);
  111. QStringList types;
  112. types << "All supported files (*.sym *.map *.symbol *.publics *.sys)"
  113. << "tniASM 0.x symbol files (*.sym)"
  114. << "tniASM 1.x symbol files (*.sym)"
  115. << "asMSX 0.x symbol files (*.sym)"
  116. << "HiTech C symbol files (*.sym)"
  117. << "HiTech C link map files (*.map)"
  118. << "pasmo symbol files (*.symbol *.publics *.sys)";
  119. d->setNameFilters(types);
  120. d->setAcceptMode(QFileDialog::AcceptOpen);
  121. d->setFileMode(QFileDialog::ExistingFile);
  122. // set default directory
  123. d->setDirectory(Settings::get().value("SymbolManager/OpenDir", QDir::currentPath()).toString());
  124. // run
  125. if (d->exec()) {
  126. QString f = d->selectedNameFilter();
  127. QString n = d->selectedFiles().at(0);
  128. // load file from the correct type
  129. bool read = false;
  130. if (f.startsWith("tniASM 0")) {
  131. read = symTable.readFile(n, SymbolTable::TNIASM0_FILE);
  132. } else if (f.startsWith("tniASM 1")) {
  133. read = symTable.readFile(n, SymbolTable::TNIASM1_FILE);
  134. } else if (f.startsWith("asMSX")) {
  135. read = symTable.readFile(n, SymbolTable::ASMSX_FILE);
  136. } else if (f.startsWith("HiTech C symbol")) {
  137. read = symTable.readFile(n, SymbolTable::HTC_FILE);
  138. } else if (f.startsWith("HiTech C link")) {
  139. read = symTable.readFile(n, SymbolTable::LINKMAP_FILE);
  140. } else if (f.startsWith("pasmo")) {
  141. read = symTable.readFile(n, SymbolTable::PASMO_FILE);
  142. } else {
  143. read = symTable.readFile(n);
  144. }
  145. // if read succesful, add it to the list
  146. if (read) {
  147. initFileList();
  148. initSymbolList();
  149. emit symbolTableChanged();
  150. }
  151. }
  152. // store last used path
  153. Settings::get().setValue("SymbolManager/OpenDir", d->directory().absolutePath());
  154. }
  155. void SymbolManager::removeFile()
  156. {
  157. int r = QMessageBox::question(
  158. this,
  159. tr("Remove symbol file(s)"),
  160. tr("When removing the symbol file(s), do you want keep or "
  161. "delete the attached symbols?"),
  162. "Keep symbols", "Delete symbols", "Cancel", 1, 2);
  163. if (r == 2) return;
  164. for (int i = 0; i < treeFiles->selectedItems().size(); ++i) {
  165. symTable.unloadFile(treeFiles->selectedItems().at(i)->text(0), r == 0);
  166. }
  167. initFileList();
  168. initSymbolList();
  169. emit symbolTableChanged();
  170. }
  171. void SymbolManager::reloadFiles()
  172. {
  173. symTable.reloadFiles();
  174. initFileList();
  175. initSymbolList();
  176. emit symbolTableChanged();
  177. }
  178. void SymbolManager::fileSelectionChange()
  179. {
  180. btnRemoveFile->setEnabled(treeFiles->selectedItems().size());
  181. }
  182. void SymbolManager::labelEdit(QTreeWidgetItem* item, int column)
  183. {
  184. // only symbol name and value are editable
  185. if (column == 0 || column == 2) {
  186. // open editor if manually added symbol
  187. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  188. if (sym->source() == 0) {
  189. // first close possible existing editor
  190. closeEditor();
  191. // open new editor
  192. treeLabels->openPersistentEditor(item, column);
  193. editItem = item;
  194. editColumn = column;
  195. }
  196. }
  197. }
  198. /*
  199. * Symbol support functions
  200. */
  201. void SymbolManager::initSymbolList()
  202. {
  203. treeLabels->clear();
  204. beginTreeLabelsUpdate();
  205. for (Symbol* sym = symTable.findFirstAddressSymbol(0);
  206. sym != 0;
  207. sym = symTable.findNextAddressSymbol()) {
  208. QTreeWidgetItem* item = new QTreeWidgetItem(treeLabels);
  209. // attach a pointer to the symbol object to the tree item
  210. item->setData(0L, Qt::UserRole, quintptr(sym));
  211. // update columns
  212. updateItemName(item);
  213. updateItemType(item);
  214. updateItemValue(item);
  215. updateItemSlots(item);
  216. updateItemSegments(item);
  217. updateItemRegisters(item);
  218. }
  219. endTreeLabelsUpdate();
  220. }
  221. void SymbolManager::beginTreeLabelsUpdate()
  222. {
  223. ++treeLabelsUpdateCount;
  224. }
  225. void SymbolManager::endTreeLabelsUpdate()
  226. {
  227. if (treeLabelsUpdateCount > 0) {
  228. --treeLabelsUpdateCount;
  229. }
  230. }
  231. void SymbolManager::closeEditor()
  232. {
  233. if (editColumn >= 0) {
  234. treeLabels->closePersistentEditor(editItem, editColumn);
  235. editColumn = -1;
  236. }
  237. }
  238. void SymbolManager::addLabel()
  239. {
  240. // create an empty symbol
  241. Symbol* sym = new Symbol(tr("New symbol"), 0);
  242. symTable.add(sym);
  243. beginTreeLabelsUpdate();
  244. QTreeWidgetItem* item = new QTreeWidgetItem(treeLabels);
  245. item->setData(0, Qt::UserRole, quintptr(sym));
  246. updateItemName(item);
  247. updateItemType(item);
  248. updateItemValue(item);
  249. updateItemSlots(item);
  250. updateItemSegments(item);
  251. updateItemRegisters(item);
  252. endTreeLabelsUpdate();
  253. closeEditor();
  254. treeLabels->setFocus();
  255. treeLabels->setCurrentItem(item, 0);
  256. treeLabels->scrollToItem(item);
  257. treeLabels->openPersistentEditor(item, 0);
  258. editItem = item;
  259. editColumn = 0;
  260. // emit notification that something has changed
  261. emit symbolTableChanged();
  262. }
  263. void SymbolManager::removeLabel()
  264. {
  265. QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
  266. // check for selection
  267. if (selection.empty()) return;
  268. // remove selected items
  269. bool deleted = false;
  270. for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
  271. selit != selection.end(); ++selit) {
  272. // get symbol
  273. Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
  274. // check if symbol is from symbol file
  275. if (!sym->source()) {
  276. // remove from table
  277. symTable.remove(sym);
  278. deleted = true;
  279. }
  280. }
  281. if (deleted) {
  282. // refresh tree
  283. initSymbolList();
  284. emit symbolTableChanged();
  285. }
  286. }
  287. void SymbolManager::labelChanged(QTreeWidgetItem* item, int column)
  288. {
  289. if (!treeLabelsUpdateCount) {
  290. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  291. // Set symbol text from tree item if any
  292. QString symText = item->text(0).trimmed();
  293. if (symText.isEmpty()) symText = "[unnamed]";
  294. sym->setText(symText);
  295. // set value TODO: proper decoding of value
  296. int value = stringToValue(item->text(2));
  297. if (value >= 0 && value < 65536) sym->setValue(value);
  298. treeLabels->closePersistentEditor(item, column);
  299. editColumn = -1;
  300. // update item name and value
  301. beginTreeLabelsUpdate();
  302. updateItemName(item);
  303. updateItemValue(item);
  304. endTreeLabelsUpdate();
  305. // notify change
  306. emit symbolTableChanged();
  307. }
  308. }
  309. void SymbolManager::labelSelectionChanged()
  310. {
  311. // remove possible editor
  312. closeEditor();
  313. QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
  314. // check if is available at all
  315. if (selection.empty()) {
  316. // disable everything
  317. btnRemoveSymbol->setEnabled(false);
  318. groupSlots->setEnabled(false);
  319. groupSegments->setEnabled(false);
  320. groupType->setEnabled(false);
  321. groupRegs8->setEnabled(false);
  322. groupRegs16->setEnabled(false);
  323. return;
  324. }
  325. // check selection for "manual insertion", identical slot mask,
  326. // identical register mask, identical types and value size
  327. bool removeButActive = true;
  328. bool anyEight = false;
  329. bool sameType = true;
  330. Symbol::SymbolType type;
  331. int slotMask, slotMaskMultiple = 0;
  332. int regMask, regMaskMultiple = 0;
  333. for (QList<QTreeWidgetItem *>::iterator selit = selection.begin();
  334. selit != selection.end(); ++selit) {
  335. // get symbol
  336. Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
  337. // check if symbol is from symbol file
  338. if (sym->source()) removeButActive = false;
  339. if (selit == selection.begin()) {
  340. // first item, reference for slotMask and regMask
  341. slotMask = sym->validSlots();
  342. regMask = sym->validRegisters();
  343. type = sym->type();
  344. } else {
  345. // other, set all different bits
  346. slotMaskMultiple |= slotMask ^ sym->validSlots();
  347. regMaskMultiple |= regMask ^ sym->validRegisters();
  348. // check for different type
  349. if (type != sym->type()) sameType = false;
  350. }
  351. // check for 8 bit values
  352. if ((sym->value() & 0xFF00) == 0) {
  353. anyEight = true;
  354. }
  355. }
  356. btnRemoveSymbol->setEnabled(removeButActive);
  357. groupSlots->setEnabled(true);
  358. groupType->setEnabled(true);
  359. groupRegs8->setEnabled(anyEight);
  360. groupRegs16->setEnabled(true);
  361. beginTreeLabelsUpdate();
  362. // set slot selection
  363. for (int i = 0; i < 16; ++i) {
  364. chkSlots[i]->setTristate(false);
  365. if (slotMaskMultiple & 1) {
  366. chkSlots[i]->setCheckState(Qt::PartiallyChecked);
  367. } else if (slotMask & 1) {
  368. chkSlots[i]->setCheckState(Qt::Checked);
  369. } else {
  370. chkSlots[i]->setCheckState(Qt::Unchecked);
  371. }
  372. slotMask >>= 1;
  373. slotMaskMultiple >>= 1;
  374. }
  375. // set register selection
  376. for (int i = 0; i < 18; ++i) {
  377. chkRegs[i]->setTristate(false);
  378. if (regMaskMultiple & 1) {
  379. chkRegs[i]->setCheckState(Qt::PartiallyChecked);
  380. } else if (regMask & 1) {
  381. chkRegs[i]->setCheckState(Qt::Checked);
  382. } else {
  383. chkRegs[i]->setCheckState(Qt::Unchecked);
  384. }
  385. regMask >>= 1;
  386. regMaskMultiple >>= 1;
  387. }
  388. // temporarily disable exclusive radiobuttons to be able to
  389. // deselect them all.
  390. radJump->setAutoExclusive (false);
  391. radVar->setAutoExclusive (false);
  392. radValue->setAutoExclusive(false);
  393. // set type radio buttons
  394. radJump->setChecked (sameType && type == Symbol::JUMPLABEL);
  395. radVar->setChecked (sameType && type == Symbol::VARIABLELABEL);
  396. radValue->setChecked(sameType && type == Symbol::VALUE);
  397. // enable exclusive radiobuttons (this won't immediately activate
  398. // one if none are active).
  399. radJump->setAutoExclusive (true);
  400. radVar->setAutoExclusive (true);
  401. radValue->setAutoExclusive(true);
  402. endTreeLabelsUpdate();
  403. }
  404. void SymbolManager::changeSlot(int id, int state)
  405. {
  406. if (treeLabelsUpdateCount) return;
  407. // disallow another tristate selection
  408. chkSlots[id]->setTristate(false);
  409. // get selected items
  410. QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
  411. // update items
  412. beginTreeLabelsUpdate();
  413. int bit = 1 << id;
  414. for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
  415. selit != selection.end(); ++selit) {
  416. Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
  417. // set or clear bit
  418. if (state == Qt::Checked) {
  419. sym->setValidSlots(sym->validSlots() | bit);
  420. } else {
  421. sym->setValidSlots(sym->validSlots() & ~bit);
  422. }
  423. // update item in treewidget
  424. updateItemSlots(*selit);
  425. }
  426. endTreeLabelsUpdate();
  427. // notify change
  428. emit symbolTableChanged();
  429. }
  430. void SymbolManager::changeRegister(int id, int state)
  431. {
  432. if (treeLabelsUpdateCount) return;
  433. // disallow another tristate selection
  434. chkRegs[id]->setTristate(false);
  435. // get selected items
  436. QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
  437. // update items
  438. beginTreeLabelsUpdate();
  439. int bit = 1 << id;
  440. for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
  441. selit != selection.end(); ++selit) {
  442. Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
  443. // set or clear bit
  444. if (state == Qt::Checked) {
  445. sym->setValidRegisters(sym->validRegisters() | bit);
  446. } else {
  447. sym->setValidRegisters(sym->validRegisters() & ~bit);
  448. }
  449. // update item in treewidget
  450. updateItemRegisters(*selit);
  451. }
  452. endTreeLabelsUpdate();
  453. // notify change
  454. emit symbolTableChanged();
  455. }
  456. void SymbolManager::changeType(bool /*checked*/)
  457. {
  458. if (treeLabelsUpdateCount) return;
  459. // determine selected type
  460. Symbol::SymbolType newType = Symbol::JUMPLABEL;
  461. if (radVar->isChecked()) {
  462. newType = Symbol::VARIABLELABEL;
  463. } else if (radValue->isChecked()) {
  464. newType = Symbol::VALUE;
  465. }
  466. // get selected items
  467. QList<QTreeWidgetItem*> selection = treeLabels->selectedItems();
  468. // update items
  469. beginTreeLabelsUpdate();
  470. for (QList<QTreeWidgetItem*>::iterator selit = selection.begin();
  471. selit != selection.end(); ++selit) {
  472. Symbol* sym = (Symbol*)((*selit)->data(0, Qt::UserRole).value<quintptr>());
  473. sym->setType(newType);
  474. updateItemType(*selit);
  475. }
  476. endTreeLabelsUpdate();
  477. // notify change
  478. emit symbolTableChanged();
  479. }
  480. /*
  481. * Symbol tree layout functions
  482. */
  483. void SymbolManager::updateItemName(QTreeWidgetItem* item)
  484. {
  485. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  486. // set text and icon
  487. item->setText(0, sym->text());
  488. if (sym->source()) {
  489. item->setIcon(0, QIcon(":/icons/symfil.png"));
  490. item->setText(6, *sym->source());
  491. } else {
  492. item->setIcon(0, QIcon(":/icons/symman.png"));
  493. }
  494. // set color based on status as well as status in 2nd column
  495. switch (sym->status()) {
  496. case Symbol::HIDDEN:
  497. item->setTextColor(0, QColor(128, 128, 128));
  498. break;
  499. case Symbol::LOST:
  500. item->setTextColor(0, QColor(128, 0, 0));
  501. break;
  502. default:
  503. break;
  504. }
  505. }
  506. void SymbolManager::updateItemType(QTreeWidgetItem* item)
  507. {
  508. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  509. // set symbol type in 2nd column
  510. switch (sym->type()) {
  511. case Symbol::JUMPLABEL:
  512. item->setText(1, tr("Jump label"));
  513. break;
  514. case Symbol::VARIABLELABEL:
  515. item->setText(1, tr("Variable label"));
  516. break;
  517. case Symbol::VALUE:
  518. item->setText(1, tr("Value"));
  519. break;
  520. }
  521. }
  522. void SymbolManager::updateItemValue(QTreeWidgetItem* item)
  523. {
  524. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  525. // symbol value in 3rd column
  526. // TODO: Custom prefix/postfix
  527. item->setText(2, QString("$%1").arg(sym->value(), 4, 16, QChar('0')));
  528. }
  529. void SymbolManager::updateItemSlots(QTreeWidgetItem* item)
  530. {
  531. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  532. QString slotText;
  533. int slotmask = sym->validSlots();
  534. // value represents 16 bits for 4 subslots in 4 slots
  535. if (slotmask == 0xFFFF) {
  536. slotText = tr("All");
  537. } else if (slotmask == 0) {
  538. slotText = tr("None");
  539. } else {
  540. // create a list of valid slots
  541. // loop over all primary slots
  542. for (int ps = 0; ps < 4; ++ps) {
  543. QString subText;
  544. int subslots = (slotmask >> (4 * ps)) & 15;
  545. if (subslots == 15) {
  546. // all subslots are ok
  547. subText = QString("%1-*").arg(ps);
  548. } else if (subslots) {
  549. // some subslots are ok
  550. if (subslots & 1) subText += "/0";
  551. if (subslots & 2) subText += "/1";
  552. if (subslots & 4) subText += "/2";
  553. if (subslots & 8) subText += "/3";
  554. subText = QString("%1-").arg(ps) + subText.mid(1);
  555. }
  556. // add to string if any subslots were ok
  557. if (!subText.isEmpty()) {
  558. if (!slotText.isEmpty()) slotText += ", ";
  559. slotText += subText;
  560. }
  561. }
  562. }
  563. // valid slots in 4th column
  564. item->setText(3, slotText);
  565. }
  566. void SymbolManager::updateItemSegments(QTreeWidgetItem* item)
  567. {
  568. item->data(0, Qt::UserRole).value<quintptr>();
  569. }
  570. void SymbolManager::updateItemRegisters(QTreeWidgetItem* item)
  571. {
  572. Symbol* sym = (Symbol*)(item->data(0, Qt::UserRole).value<quintptr>());
  573. QString regText;
  574. int regmask = sym->validRegisters();
  575. // value represents 16 bits for 4 subslots in 4 slots
  576. if (regmask == 0x3FFFF) {
  577. regText = tr("All");
  578. } else if (regmask == 0) {
  579. regText = tr("None");
  580. } else {
  581. if ((regmask & Symbol::REG_ALL8) == Symbol::REG_ALL8) {
  582. // all 8 bit registers selected
  583. regText = "All 8 bit, ";
  584. regmask ^= Symbol::REG_ALL8;
  585. } else if ((regmask & Symbol::REG_ALL16) == Symbol::REG_ALL16) {
  586. // all 16 bit registers selected
  587. regText = "All 16 bit, ";
  588. regmask ^= Symbol::REG_ALL16;
  589. }
  590. // register list for remaining registers
  591. static const char* const registers[] = {
  592. "A", "B", "C", "D", "E", "H", "L", "BC", "DE", "HL",
  593. "IX", "IY", "IXL", "IXH", "IYL", "IYH", "Offset", "I"
  594. };
  595. for (int i = 0; i < 18; ++i) {
  596. if (regmask & 1) {
  597. regText += QString("%1, ").arg(registers[i]);
  598. }
  599. regmask >>= 1;
  600. }
  601. regText.chop(2);
  602. }
  603. // valid slots in 4th column
  604. item->setText(5, regText);
  605. }
  606. // load of functions that shouldn't really be necessary
  607. void SymbolManager::changeSlot00(int state)
  608. {
  609. changeSlot(0, state);
  610. }
  611. void SymbolManager::changeSlot01(int state)
  612. {
  613. changeSlot(1, state);
  614. }
  615. void SymbolManager::changeSlot02(int state)
  616. {
  617. changeSlot(2, state);
  618. }
  619. void SymbolManager::changeSlot03(int state)
  620. {
  621. changeSlot(3, state);
  622. }
  623. void SymbolManager::changeSlot10(int state)
  624. {
  625. changeSlot(4, state);
  626. }
  627. void SymbolManager::changeSlot11(int state)
  628. {
  629. changeSlot(5, state);
  630. }
  631. void SymbolManager::changeSlot12(int state)
  632. {
  633. changeSlot(6, state);
  634. }
  635. void SymbolManager::changeSlot13(int state)
  636. {
  637. changeSlot(7, state);
  638. }
  639. void SymbolManager::changeSlot20(int state)
  640. {
  641. changeSlot(8, state);
  642. }
  643. void SymbolManager::changeSlot21(int state)
  644. {
  645. changeSlot(9, state);
  646. }
  647. void SymbolManager::changeSlot22(int state)
  648. {
  649. changeSlot(10, state);
  650. }
  651. void SymbolManager::changeSlot23(int state)
  652. {
  653. changeSlot(11, state);
  654. }
  655. void SymbolManager::changeSlot30(int state)
  656. {
  657. changeSlot(12, state);
  658. }
  659. void SymbolManager::changeSlot31(int state)
  660. {
  661. changeSlot(13, state);
  662. }
  663. void SymbolManager::changeSlot32(int state)
  664. {
  665. changeSlot(14, state);
  666. }
  667. void SymbolManager::changeSlot33(int state)
  668. {
  669. changeSlot(15, state);
  670. }
  671. void SymbolManager::changeRegisterA(int state)
  672. {
  673. changeRegister(0, state);
  674. }
  675. void SymbolManager::changeRegisterB(int state)
  676. {
  677. changeRegister(1, state);
  678. }
  679. void SymbolManager::changeRegisterC(int state)
  680. {
  681. changeRegister(2, state);
  682. }
  683. void SymbolManager::changeRegisterD(int state)
  684. {
  685. changeRegister(3, state);
  686. }
  687. void SymbolManager::changeRegisterE(int state)
  688. {
  689. changeRegister(4, state);
  690. }
  691. void SymbolManager::changeRegisterH(int state)
  692. {
  693. changeRegister(5, state);
  694. }
  695. void SymbolManager::changeRegisterL(int state)
  696. {
  697. changeRegister(6, state);
  698. }
  699. void SymbolManager::changeRegisterBC(int state)
  700. {
  701. changeRegister(7, state);
  702. }
  703. void SymbolManager::changeRegisterDE(int state)
  704. {
  705. changeRegister(8, state);
  706. }
  707. void SymbolManager::changeRegisterHL(int state)
  708. {
  709. changeRegister(9, state);
  710. }
  711. void SymbolManager::changeRegisterIX(int state)
  712. {
  713. changeRegister(10, state);
  714. }
  715. void SymbolManager::changeRegisterIY(int state)
  716. {
  717. changeRegister(11, state);
  718. }
  719. void SymbolManager::changeRegisterIXL(int state)
  720. {
  721. changeRegister(12, state);
  722. }
  723. void SymbolManager::changeRegisterIXH(int state)
  724. {
  725. changeRegister(13, state);
  726. }
  727. void SymbolManager::changeRegisterIYL(int state)
  728. {
  729. changeRegister(14, state);
  730. }
  731. void SymbolManager::changeRegisterIYH(int state)
  732. {
  733. changeRegister(15, state);
  734. }
  735. void SymbolManager::changeRegisterOffset(int state)
  736. {
  737. changeRegister(16, state);
  738. }
  739. void SymbolManager::changeRegisterI(int state)
  740. {
  741. changeRegister(17, state);
  742. }