qhexedit_p.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. #include "qhexedit_p.h"
  2. #include "commands.h"
  3. const int HEXCHARS_IN_LINE = 47;
  4. const int GAP_ADR_HEX = 10;
  5. const int GAP_HEX_ASCII = 16;
  6. const int BYTES_PER_LINE = 16;
  7. QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent)
  8. {
  9. _undoStack = new QUndoStack(this);
  10. _scrollArea = parent;
  11. setAddressWidth(4);
  12. setAddressOffset(0);
  13. setAddressArea(true);
  14. setAsciiArea(true);
  15. setHighlighting(true);
  16. setOverwriteMode(true);
  17. setReadOnly(false);
  18. setAddressAreaColor(QColor(0xd4, 0xd4, 0xd4, 0xff));
  19. setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff));
  20. setSelectionColor(QColor(0x6d, 0x9e, 0xff, 0xff));
  21. setFont(QFont("Courier", 10));
  22. _size = 0;
  23. resetSelection(0);
  24. setFocusPolicy(Qt::StrongFocus);
  25. connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor()));
  26. _cursorTimer.setInterval(500);
  27. _cursorTimer.start();
  28. }
  29. void QHexEditPrivate::setAddressOffset(int offset)
  30. {
  31. _xData.setAddressOffset(offset);
  32. adjust();
  33. }
  34. int QHexEditPrivate::addressOffset()
  35. {
  36. return _xData.addressOffset();
  37. }
  38. void QHexEditPrivate::setData(const QByteArray &data)
  39. {
  40. _xData.setData(data);
  41. _undoStack->clear();
  42. adjust();
  43. setCursorPos(0);
  44. }
  45. QByteArray QHexEditPrivate::data()
  46. {
  47. return _xData.data();
  48. }
  49. void QHexEditPrivate::setAddressAreaColor(const QColor &color)
  50. {
  51. _addressAreaColor = color;
  52. update();
  53. }
  54. QColor QHexEditPrivate::addressAreaColor()
  55. {
  56. return _addressAreaColor;
  57. }
  58. void QHexEditPrivate::setHighlightingColor(const QColor &color)
  59. {
  60. _highlightingColor = color;
  61. update();
  62. }
  63. QColor QHexEditPrivate::highlightingColor()
  64. {
  65. return _highlightingColor;
  66. }
  67. void QHexEditPrivate::setSelectionColor(const QColor &color)
  68. {
  69. _selectionColor = color;
  70. update();
  71. }
  72. QColor QHexEditPrivate::selectionColor()
  73. {
  74. return _selectionColor;
  75. }
  76. void QHexEditPrivate::setReadOnly(bool readOnly)
  77. {
  78. _readOnly = readOnly;
  79. }
  80. bool QHexEditPrivate::isReadOnly()
  81. {
  82. return _readOnly;
  83. }
  84. XByteArray & QHexEditPrivate::xData()
  85. {
  86. return _xData;
  87. }
  88. int QHexEditPrivate::indexOf(const QByteArray & ba, int from)
  89. {
  90. if (from > (_xData.data().length() - 1))
  91. from = _xData.data().length() - 1;
  92. int idx = _xData.data().indexOf(ba, from);
  93. if (idx > -1)
  94. {
  95. int curPos = idx*2;
  96. setCursorPos(curPos + ba.length()*2);
  97. resetSelection(curPos);
  98. setSelection(curPos + ba.length()*2);
  99. ensureVisible();
  100. }
  101. return idx;
  102. }
  103. void QHexEditPrivate::insert(int index, const QByteArray & ba)
  104. {
  105. if (ba.length() > 0)
  106. {
  107. if (_overwriteMode)
  108. {
  109. QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
  110. _undoStack->push(arrayCommand);
  111. emit dataChanged();
  112. }
  113. else
  114. {
  115. QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::insert, index, ba, ba.length());
  116. _undoStack->push(arrayCommand);
  117. emit dataChanged();
  118. }
  119. }
  120. }
  121. void QHexEditPrivate::insert(int index, char ch)
  122. {
  123. QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::insert, index, ch);
  124. _undoStack->push(charCommand);
  125. emit dataChanged();
  126. }
  127. int QHexEditPrivate::lastIndexOf(const QByteArray & ba, int from)
  128. {
  129. from -= ba.length();
  130. if (from < 0)
  131. from = 0;
  132. int idx = _xData.data().lastIndexOf(ba, from);
  133. if (idx > -1)
  134. {
  135. int curPos = idx*2;
  136. setCursorPos(curPos);
  137. resetSelection(curPos);
  138. setSelection(curPos + ba.length()*2);
  139. ensureVisible();
  140. }
  141. return idx;
  142. }
  143. void QHexEditPrivate::remove(int index, int len)
  144. {
  145. if (len > 0)
  146. {
  147. if (len == 1)
  148. {
  149. if (_overwriteMode)
  150. {
  151. QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, char(0));
  152. _undoStack->push(charCommand);
  153. emit dataChanged();
  154. }
  155. else
  156. {
  157. QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::remove, index, char(0));
  158. _undoStack->push(charCommand);
  159. emit dataChanged();
  160. }
  161. }
  162. else
  163. {
  164. QByteArray ba = QByteArray(len, char(0));
  165. if (_overwriteMode)
  166. {
  167. QUndoCommand *arrayCommand = new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
  168. _undoStack->push(arrayCommand);
  169. emit dataChanged();
  170. }
  171. else
  172. {
  173. QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::remove, index, ba, len);
  174. _undoStack->push(arrayCommand);
  175. emit dataChanged();
  176. }
  177. }
  178. }
  179. }
  180. void QHexEditPrivate::replace(int index, char ch)
  181. {
  182. QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, ch);
  183. _undoStack->push(charCommand);
  184. resetSelection();
  185. emit dataChanged();
  186. }
  187. void QHexEditPrivate::replace(int index, const QByteArray & ba)
  188. {
  189. QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
  190. _undoStack->push(arrayCommand);
  191. resetSelection();
  192. emit dataChanged();
  193. }
  194. void QHexEditPrivate::replace(int pos, int len, const QByteArray &after)
  195. {
  196. QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, pos, after, len);
  197. _undoStack->push(arrayCommand);
  198. resetSelection();
  199. emit dataChanged();
  200. }
  201. void QHexEditPrivate::setAddressArea(bool addressArea)
  202. {
  203. _addressArea = addressArea;
  204. adjust();
  205. setCursorPos(_cursorPosition);
  206. }
  207. void QHexEditPrivate::setAddressWidth(int addressWidth)
  208. {
  209. _xData.setAddressWidth(addressWidth);
  210. setCursorPos(_cursorPosition);
  211. }
  212. void QHexEditPrivate::setAsciiArea(bool asciiArea)
  213. {
  214. _asciiArea = asciiArea;
  215. adjust();
  216. }
  217. void QHexEditPrivate::setFont(const QFont &font)
  218. {
  219. QWidget::setFont(font);
  220. adjust();
  221. }
  222. void QHexEditPrivate::setHighlighting(bool mode)
  223. {
  224. _highlighting = mode;
  225. update();
  226. }
  227. void QHexEditPrivate::setOverwriteMode(bool overwriteMode)
  228. {
  229. _overwriteMode = overwriteMode;
  230. }
  231. bool QHexEditPrivate::overwriteMode()
  232. {
  233. return _overwriteMode;
  234. }
  235. void QHexEditPrivate::redo()
  236. {
  237. _undoStack->redo();
  238. emit dataChanged();
  239. setCursorPos(_cursorPosition);
  240. update();
  241. }
  242. void QHexEditPrivate::undo()
  243. {
  244. _undoStack->undo();
  245. emit dataChanged();
  246. setCursorPos(_cursorPosition);
  247. update();
  248. }
  249. QString QHexEditPrivate::toRedableString()
  250. {
  251. return _xData.toRedableString();
  252. }
  253. QString QHexEditPrivate::selectionToReadableString()
  254. {
  255. return _xData.toRedableString(getSelectionBegin(), getSelectionEnd());
  256. }
  257. void QHexEditPrivate::keyPressEvent(QKeyEvent *event)
  258. {
  259. int charX = (_cursorX - _xPosHex) / _charWidth;
  260. int posX = (charX / 3) * 2 + (charX % 3);
  261. int posBa = (_cursorY / _charHeight) * BYTES_PER_LINE + posX / 2;
  262. /*****************************************************************************/
  263. /* Cursor movements */
  264. /*****************************************************************************/
  265. if (event->matches(QKeySequence::MoveToNextChar))
  266. {
  267. setCursorPos(_cursorPosition + 1);
  268. resetSelection(_cursorPosition);
  269. }
  270. if (event->matches(QKeySequence::MoveToPreviousChar))
  271. {
  272. setCursorPos(_cursorPosition - 1);
  273. resetSelection(_cursorPosition);
  274. }
  275. if (event->matches(QKeySequence::MoveToEndOfLine))
  276. {
  277. setCursorPos(_cursorPosition | (2 * BYTES_PER_LINE -1));
  278. resetSelection(_cursorPosition);
  279. }
  280. if (event->matches(QKeySequence::MoveToStartOfLine))
  281. {
  282. setCursorPos(_cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)));
  283. resetSelection(_cursorPosition);
  284. }
  285. if (event->matches(QKeySequence::MoveToPreviousLine))
  286. {
  287. setCursorPos(_cursorPosition - (2 * BYTES_PER_LINE));
  288. resetSelection(_cursorPosition);
  289. }
  290. if (event->matches(QKeySequence::MoveToNextLine))
  291. {
  292. setCursorPos(_cursorPosition + (2 * BYTES_PER_LINE));
  293. resetSelection(_cursorPosition);
  294. }
  295. if (event->matches(QKeySequence::MoveToNextPage))
  296. {
  297. setCursorPos(_cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
  298. resetSelection(_cursorPosition);
  299. }
  300. if (event->matches(QKeySequence::MoveToPreviousPage))
  301. {
  302. setCursorPos(_cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
  303. resetSelection(_cursorPosition);
  304. }
  305. if (event->matches(QKeySequence::MoveToEndOfDocument))
  306. {
  307. setCursorPos(_xData.size() * 2);
  308. resetSelection(_cursorPosition);
  309. }
  310. if (event->matches(QKeySequence::MoveToStartOfDocument))
  311. {
  312. setCursorPos(0);
  313. resetSelection(_cursorPosition);
  314. }
  315. /*****************************************************************************/
  316. /* Select commands */
  317. /*****************************************************************************/
  318. if (event->matches(QKeySequence::SelectAll))
  319. {
  320. resetSelection(0);
  321. setSelection(2*_xData.size() + 1);
  322. }
  323. if (event->matches(QKeySequence::SelectNextChar))
  324. {
  325. int pos = _cursorPosition + 1;
  326. setCursorPos(pos);
  327. setSelection(pos);
  328. }
  329. if (event->matches(QKeySequence::SelectPreviousChar))
  330. {
  331. int pos = _cursorPosition - 1;
  332. setSelection(pos);
  333. setCursorPos(pos);
  334. }
  335. if (event->matches(QKeySequence::SelectEndOfLine))
  336. {
  337. int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)) + (2 * BYTES_PER_LINE);
  338. setCursorPos(pos);
  339. setSelection(pos);
  340. }
  341. if (event->matches(QKeySequence::SelectStartOfLine))
  342. {
  343. int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE));
  344. setCursorPos(pos);
  345. setSelection(pos);
  346. }
  347. if (event->matches(QKeySequence::SelectPreviousLine))
  348. {
  349. int pos = _cursorPosition - (2 * BYTES_PER_LINE);
  350. setCursorPos(pos);
  351. setSelection(pos);
  352. }
  353. if (event->matches(QKeySequence::SelectNextLine))
  354. {
  355. int pos = _cursorPosition + (2 * BYTES_PER_LINE);
  356. setCursorPos(pos);
  357. setSelection(pos);
  358. }
  359. if (event->matches(QKeySequence::SelectNextPage))
  360. {
  361. int pos = _cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE);
  362. setCursorPos(pos);
  363. setSelection(pos);
  364. }
  365. if (event->matches(QKeySequence::SelectPreviousPage))
  366. {
  367. int pos = _cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE);
  368. setCursorPos(pos);
  369. setSelection(pos);
  370. }
  371. if (event->matches(QKeySequence::SelectEndOfDocument))
  372. {
  373. int pos = _xData.size() * 2;
  374. setCursorPos(pos);
  375. setSelection(pos);
  376. }
  377. if (event->matches(QKeySequence::SelectStartOfDocument))
  378. {
  379. int pos = 0;
  380. setCursorPos(pos);
  381. setSelection(pos);
  382. }
  383. /*****************************************************************************/
  384. /* Edit Commands */
  385. /*****************************************************************************/
  386. if (!_readOnly)
  387. {
  388. /* Hex input */
  389. int key = int(event->text()[0].toLatin1());
  390. if ((key>='0' && key<='9') || (key>='a' && key <= 'f'))
  391. {
  392. if (getSelectionBegin() != getSelectionEnd())
  393. {
  394. posBa = getSelectionBegin();
  395. remove(posBa, getSelectionEnd() - posBa);
  396. setCursorPos(2*posBa);
  397. resetSelection(2*posBa);
  398. }
  399. // If insert mode, then insert a byte
  400. if (_overwriteMode == false)
  401. if ((charX % 3) == 0)
  402. {
  403. insert(posBa, char(0));
  404. }
  405. // Change content
  406. if (_xData.size() > 0)
  407. {
  408. QByteArray hexValue = _xData.data().mid(posBa, 1).toHex();
  409. if ((charX % 3) == 0)
  410. hexValue[0] = key;
  411. else
  412. hexValue[1] = key;
  413. replace(posBa, QByteArray().fromHex(hexValue)[0]);
  414. setCursorPos(_cursorPosition + 1);
  415. resetSelection(_cursorPosition);
  416. }
  417. }
  418. /* Cut & Paste */
  419. if (event->matches(QKeySequence::Cut))
  420. {
  421. QString result = QString();
  422. for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++)
  423. {
  424. result += _xData.data().mid(idx, 1).toHex() + " ";
  425. if ((idx % 16) == 15)
  426. result.append("\n");
  427. }
  428. remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin());
  429. QClipboard *clipboard = QApplication::clipboard();
  430. clipboard->setText(result);
  431. setCursorPos(getSelectionBegin());
  432. resetSelection(getSelectionBegin());
  433. }
  434. if (event->matches(QKeySequence::Paste))
  435. {
  436. QClipboard *clipboard = QApplication::clipboard();
  437. QByteArray ba = QByteArray().fromHex(clipboard->text().toLatin1());
  438. insert(_cursorPosition / 2, ba);
  439. setCursorPos(_cursorPosition + 2 * ba.length());
  440. resetSelection(getSelectionBegin());
  441. }
  442. /* Delete char */
  443. if (event->matches(QKeySequence::Delete))
  444. {
  445. if (getSelectionBegin() != getSelectionEnd())
  446. {
  447. posBa = getSelectionBegin();
  448. remove(posBa, getSelectionEnd() - posBa);
  449. setCursorPos(2*posBa);
  450. resetSelection(2*posBa);
  451. }
  452. else
  453. {
  454. if (_overwriteMode)
  455. replace(posBa, char(0));
  456. else
  457. remove(posBa, 1);
  458. }
  459. }
  460. /* Backspace */
  461. if ((event->key() == Qt::Key_Backspace) && (event->modifiers() == Qt::NoModifier))
  462. {
  463. if (getSelectionBegin() != getSelectionEnd())
  464. {
  465. posBa = getSelectionBegin();
  466. remove(posBa, getSelectionEnd() - posBa);
  467. setCursorPos(2*posBa);
  468. resetSelection(2*posBa);
  469. }
  470. else
  471. {
  472. if (posBa > 0)
  473. {
  474. if (_overwriteMode)
  475. replace(posBa - 1, char(0));
  476. else
  477. remove(posBa - 1, 1);
  478. setCursorPos(_cursorPosition - 2);
  479. }
  480. }
  481. }
  482. /* undo */
  483. if (event->matches(QKeySequence::Undo))
  484. {
  485. undo();
  486. }
  487. /* redo */
  488. if (event->matches(QKeySequence::Redo))
  489. {
  490. redo();
  491. }
  492. }
  493. if (event->matches(QKeySequence::Copy))
  494. {
  495. QString result = QString();
  496. for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++)
  497. {
  498. result += _xData.data().mid(idx, 1).toHex() + " ";
  499. if ((idx % 16) == 15)
  500. result.append('\n');
  501. }
  502. QClipboard *clipboard = QApplication::clipboard();
  503. clipboard->setText(result);
  504. }
  505. // Switch between insert/overwrite mode
  506. if ((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier))
  507. {
  508. _overwriteMode = !_overwriteMode;
  509. setCursorPos(_cursorPosition);
  510. overwriteModeChanged(_overwriteMode);
  511. }
  512. ensureVisible();
  513. update();
  514. }
  515. void QHexEditPrivate::mouseMoveEvent(QMouseEvent * event)
  516. {
  517. _blink = false;
  518. update();
  519. int actPos = cursorPos(event->pos());
  520. setCursorPos(actPos);
  521. setSelection(actPos);
  522. }
  523. void QHexEditPrivate::mousePressEvent(QMouseEvent * event)
  524. {
  525. _blink = false;
  526. update();
  527. int cPos = cursorPos(event->pos());
  528. resetSelection(cPos);
  529. setCursorPos(cPos);
  530. }
  531. void QHexEditPrivate::paintEvent(QPaintEvent *event)
  532. {
  533. QPainter painter(this);
  534. // draw some patterns if needed
  535. painter.fillRect(event->rect(), this->palette().color(QPalette::Base));
  536. if (_addressArea)
  537. painter.fillRect(QRect(_xPosAdr, event->rect().top(), _xPosHex - GAP_ADR_HEX + 2, height()), _addressAreaColor);
  538. if (_asciiArea)
  539. {
  540. int linePos = _xPosAscii - (GAP_HEX_ASCII / 2);
  541. painter.setPen(Qt::gray);
  542. painter.drawLine(linePos, event->rect().top(), linePos, height());
  543. }
  544. painter.setPen(this->palette().color(QPalette::WindowText));
  545. // calc position
  546. int firstLineIdx = ((event->rect().top()/ _charHeight) - _charHeight) * BYTES_PER_LINE;
  547. if (firstLineIdx < 0)
  548. firstLineIdx = 0;
  549. int lastLineIdx = ((event->rect().bottom() / _charHeight) + _charHeight) * BYTES_PER_LINE;
  550. if (lastLineIdx > _xData.size())
  551. lastLineIdx = _xData.size();
  552. int yPosStart = ((firstLineIdx) / BYTES_PER_LINE) * _charHeight + _charHeight;
  553. // paint address area
  554. if (_addressArea)
  555. {
  556. for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
  557. {
  558. QString address = QString("%1")
  559. .arg(lineIdx + _xData.addressOffset(), _xData.realAddressNumbers(), 16, QChar('0'));
  560. painter.drawText(_xPosAdr, yPos, address);
  561. }
  562. }
  563. // paint hex area
  564. QByteArray hexBa(_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex());
  565. QBrush highLighted = QBrush(_highlightingColor);
  566. QPen colHighlighted = QPen(this->palette().color(QPalette::WindowText));
  567. QBrush selected = QBrush(_selectionColor);
  568. QPen colSelected = QPen(Qt::white);
  569. QPen colStandard = QPen(this->palette().color(QPalette::WindowText));
  570. painter.setBackgroundMode(Qt::TransparentMode);
  571. for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
  572. {
  573. QByteArray hex;
  574. int xPos = _xPosHex;
  575. for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < BYTES_PER_LINE)); colIdx++)
  576. {
  577. int posBa = lineIdx + colIdx;
  578. if ((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa))
  579. {
  580. painter.setBackground(selected);
  581. painter.setBackgroundMode(Qt::OpaqueMode);
  582. painter.setPen(colSelected);
  583. }
  584. else
  585. {
  586. if (_highlighting)
  587. {
  588. // hilight diff bytes
  589. painter.setBackground(highLighted);
  590. if (_xData.dataChanged(posBa))
  591. {
  592. painter.setPen(colHighlighted);
  593. painter.setBackgroundMode(Qt::OpaqueMode);
  594. }
  595. else
  596. {
  597. painter.setPen(colStandard);
  598. painter.setBackgroundMode(Qt::TransparentMode);
  599. }
  600. }
  601. }
  602. // render hex value
  603. if (colIdx == 0)
  604. {
  605. hex = hexBa.mid((lineIdx - firstLineIdx) * 2, 2);
  606. painter.drawText(xPos, yPos, hex);
  607. xPos += 2 * _charWidth;
  608. } else {
  609. hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2).prepend(" ");
  610. painter.drawText(xPos, yPos, hex);
  611. xPos += 3 * _charWidth;
  612. }
  613. }
  614. }
  615. painter.setBackgroundMode(Qt::TransparentMode);
  616. painter.setPen(this->palette().color(QPalette::WindowText));
  617. // paint ascii area
  618. if (_asciiArea)
  619. {
  620. for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
  621. {
  622. int xPosAscii = _xPosAscii;
  623. for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < BYTES_PER_LINE)); colIdx++)
  624. {
  625. painter.drawText(xPosAscii, yPos, _xData.asciiChar(lineIdx + colIdx));
  626. xPosAscii += _charWidth;
  627. }
  628. }
  629. }
  630. // paint cursor
  631. if (_blink && !_readOnly && hasFocus())
  632. {
  633. if (_overwriteMode)
  634. painter.fillRect(_cursorX, _cursorY + _charHeight - 2, _charWidth, 2, this->palette().color(QPalette::WindowText));
  635. else
  636. painter.fillRect(_cursorX, _cursorY, 2, _charHeight, this->palette().color(QPalette::WindowText));
  637. }
  638. if (_size != _xData.size())
  639. {
  640. _size = _xData.size();
  641. emit currentSizeChanged(_size);
  642. }
  643. }
  644. void QHexEditPrivate::setCursorPos(int position)
  645. {
  646. // delete cursor
  647. _blink = false;
  648. update();
  649. // cursor in range?
  650. if (_overwriteMode)
  651. {
  652. if (position > (_xData.size() * 2 - 1))
  653. position = _xData.size() * 2 - 1;
  654. } else {
  655. if (position > (_xData.size() * 2))
  656. position = _xData.size() * 2;
  657. }
  658. if (position < 0)
  659. position = 0;
  660. // calc position
  661. _cursorPosition = position;
  662. _cursorY = (position / (2 * BYTES_PER_LINE)) * _charHeight + 4;
  663. int x = (position % (2 * BYTES_PER_LINE));
  664. _cursorX = (((x / 2) * 3) + (x % 2)) * _charWidth + _xPosHex;
  665. // immiadately draw cursor
  666. _blink = true;
  667. update();
  668. emit currentAddressChanged(_cursorPosition/2);
  669. }
  670. int QHexEditPrivate::cursorPos(QPoint pos)
  671. {
  672. int result = -1;
  673. // find char under cursor
  674. if ((pos.x() >= _xPosHex) && (pos.x() < (_xPosHex + HEXCHARS_IN_LINE * _charWidth)))
  675. {
  676. int x = (pos.x() - _xPosHex) / _charWidth;
  677. if ((x % 3) == 0)
  678. x = (x / 3) * 2;
  679. else
  680. x = ((x / 3) * 2) + 1;
  681. int y = ((pos.y() - 3) / _charHeight) * 2 * BYTES_PER_LINE;
  682. result = x + y;
  683. }
  684. return result;
  685. }
  686. int QHexEditPrivate::cursorPos()
  687. {
  688. return _cursorPosition;
  689. }
  690. void QHexEditPrivate::resetSelection()
  691. {
  692. _selectionBegin = _selectionInit;
  693. _selectionEnd = _selectionInit;
  694. }
  695. void QHexEditPrivate::resetSelection(int pos)
  696. {
  697. if (pos < 0)
  698. pos = 0;
  699. pos = pos / 2;
  700. _selectionInit = pos;
  701. _selectionBegin = pos;
  702. _selectionEnd = pos;
  703. }
  704. void QHexEditPrivate::setSelection(int pos)
  705. {
  706. if (pos < 0)
  707. pos = 0;
  708. pos = pos / 2;
  709. if (pos >= _selectionInit)
  710. {
  711. _selectionEnd = pos;
  712. _selectionBegin = _selectionInit;
  713. }
  714. else
  715. {
  716. _selectionBegin = pos;
  717. _selectionEnd = _selectionInit;
  718. }
  719. }
  720. int QHexEditPrivate::getSelectionBegin()
  721. {
  722. return _selectionBegin;
  723. }
  724. int QHexEditPrivate::getSelectionEnd()
  725. {
  726. return _selectionEnd;
  727. }
  728. void QHexEditPrivate::updateCursor()
  729. {
  730. if (_blink)
  731. _blink = false;
  732. else
  733. _blink = true;
  734. update(_cursorX, _cursorY, _charWidth, _charHeight);
  735. }
  736. void QHexEditPrivate::adjust()
  737. {
  738. _charWidth = fontMetrics().width(QLatin1Char('9'));
  739. _charHeight = fontMetrics().height();
  740. _xPosAdr = 0;
  741. if (_addressArea)
  742. _xPosHex = _xData.realAddressNumbers()*_charWidth + GAP_ADR_HEX;
  743. else
  744. _xPosHex = 0;
  745. _xPosAscii = _xPosHex + HEXCHARS_IN_LINE * _charWidth + GAP_HEX_ASCII;
  746. // tell QAbstractScollbar, how big we are
  747. setMinimumHeight(((_xData.size()/16 + 1) * _charHeight) + 5);
  748. if(_asciiArea)
  749. setMinimumWidth(_xPosAscii + (BYTES_PER_LINE * _charWidth));
  750. else
  751. setMinimumWidth(_xPosHex + HEXCHARS_IN_LINE * _charWidth);
  752. update();
  753. }
  754. void QHexEditPrivate::ensureVisible()
  755. {
  756. // scrolls to cursorx, cusory (which are set by setCursorPos)
  757. // x-margin is 3 pixels, y-margin is half of charHeight
  758. _scrollArea->ensureVisible(_cursorX, _cursorY + _charHeight/2, 3, _charHeight/2 + 2);
  759. }