qhexedit_p.cpp 24 KB

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