1 #include "preferences.h"
4 #include <QApplication>
11 const int HEXCHARS_IN_LINE = 3 * 16;
12 const int BYTES_PER_LINE = 16;
13 const int GAP_ADR_HEX = 1;
14 const int GAP_HEX_ASCII = 3;
16 ///////////////////////////////////////////////////////////////////////////////
17 /// \brief HexView::HexView
18 /// \param parent 親ウィジェット
22 HexView::HexView(QScrollArea *parent) :
25 m_scrollArea = parent;
26 m_scrollArea->setWidget(this);
27 setObjectName("hexView");
28 setCursor(Qt::IBeamCursor);
33 ///////////////////////////////////////////////////////////////////////////////
34 /// \brief HexView::setData
39 void HexView::setData(const QByteArray &data)
45 ///////////////////////////////////////////////////////////////////////////////
46 /// \brief HexView::addressChars
47 /// \return アドレスエリアの表示桁数を返します。
49 int HexView::addressChars() const
51 return QString("%1").arg(m_data.size(), 0, 16).length();
54 ///////////////////////////////////////////////////////////////////////////////
55 /// \brief HexView::adjust
59 void HexView::adjust()
61 int lines = (m_data.size() / BYTES_PER_LINE) + 1;
62 setMinimumHeight((lines + 1) * m_charHeight);
64 int addressArea = (addressChars() + GAP_ADR_HEX) * m_charWidth;
65 int hexArea = HEXCHARS_IN_LINE * m_charWidth;
66 int asciiArea = (GAP_HEX_ASCII + BYTES_PER_LINE) * m_charWidth;
67 setMinimumWidth(addressArea + hexArea + asciiArea);
70 ///////////////////////////////////////////////////////////////////////////////
71 /// \brief HexView::cursorPos
73 /// \return カーソル位置に対応するデータインデックスを返します。
75 int HexView::cursorPos(const QPoint &pos)
78 if (xPosHex() <= pos.x() && pos.x() < xPosAscii()) {
79 int x = (pos.x() - xPosHex()) / m_charWidth;
86 int y = pos.y() / m_charHeight;
88 result = x + y * BYTES_PER_LINE;
90 qDebug() << x << y << result;
96 ///////////////////////////////////////////////////////////////////////////////
97 /// \brief HexView::resetSelection
98 /// \param index データインデックス
102 void HexView::resetSelection(int index)
104 m_selectionBegin = index;
105 m_selectionEnd = index;
106 m_selectionInit = index;
108 emit copyAvailable(false);
111 ///////////////////////////////////////////////////////////////////////////////
112 /// \brief HexView::setSelection
113 /// \param index データインデックス
117 void HexView::setSelection(int index)
119 if (index > m_selectionInit) {
120 m_selectionBegin = m_selectionInit;
121 m_selectionEnd = index;
124 m_selectionBegin = index;
125 m_selectionEnd = m_selectionInit;
128 emit copyAvailable(m_selectionBegin != m_selectionEnd);
131 ///////////////////////////////////////////////////////////////////////////////
132 /// \brief HexView::xPosHex
133 /// \return 16進表示エリアの開始座標を返します。
135 int HexView::xPosHex() const
137 return m_charWidth * (addressChars() + GAP_ADR_HEX);
140 ///////////////////////////////////////////////////////////////////////////////
141 /// \brief HexView::xPosAscii
142 /// \return アスキー文字表示エリアの開始座標を返します。
144 int HexView::xPosAscii() const
146 return xPosHex() + m_charWidth * (HEXCHARS_IN_LINE + GAP_HEX_ASCII);
149 ///////////////////////////////////////////////////////////////////////////////
150 /// \brief HexView::onCopy
152 /// 選択範囲をクリップボードにコピーします。
154 void HexView::onCopy()
157 for (int idx = m_selectionBegin; idx < m_selectionEnd; ++idx) {
158 quint8 c = static_cast<quint8>(m_data[idx]);
159 selected.append(QString("%1 ").arg(c, 2, 16, QChar('0')));
162 QClipboard *clipboard = qApp->clipboard();
163 clipboard->setText(selected.trimmed());
166 ///////////////////////////////////////////////////////////////////////////////
167 /// \brief HexView::onScaleDown
171 void HexView::onScaleDown()
173 Preferences prefs(this);
174 QFont font = prefs.getHexViewFont();
175 font.setPointSize(font.pointSize() - 1);
176 prefs.setHexViewFont(font);
183 ///////////////////////////////////////////////////////////////////////////////
184 /// \brief HexView::onScaleUp
188 void HexView::onScaleUp()
190 Preferences prefs(this);
191 QFont font = prefs.getHexViewFont();
192 font.setPointSize(font.pointSize() + 1);
193 prefs.setHexViewFont(font);
200 ///////////////////////////////////////////////////////////////////////////////
201 /// \brief HexView::onSelectAll
205 void HexView::onSelectAll()
208 setSelection(m_data.size());
213 ///////////////////////////////////////////////////////////////////////////////
214 /// \brief HexView::setVisible
215 /// \param visible 表示(true)/非表示(false)
217 /// 表示状態になった場合の処理を行います。
219 void HexView::setVisible(bool visible)
222 Preferences prefs(this);
223 QPalette pal = this->palette();
224 pal.setColor(this->backgroundRole(), prefs.getHexViewBgColor());
225 pal.setColor(this->foregroundRole(), prefs.getHexViewFgColor());
226 this->setPalette(pal);
227 this->setAutoFillBackground(true);
228 this->setFont(prefs.getHexViewFont());
230 m_charHeight = fontMetrics().height();
231 m_charWidth = fontMetrics().width('9');
234 QWidget::setVisible(visible);
237 ///////////////////////////////////////////////////////////////////////////////
238 /// \brief HexView::mousePressEvent
239 /// \param e マウスイベントオブジェクト
241 /// マウスクリック時の処理を行います。
243 void HexView::mousePressEvent(QMouseEvent *e)
245 if (e->button() == Qt::LeftButton) {
246 int cPos = cursorPos(e->pos());
247 resetSelection(cPos);
253 ///////////////////////////////////////////////////////////////////////////////
254 /// \brief HexView::mouseDoubleClickEvent
255 /// \param e マウスイベントオブジェクト
257 /// ダブルクリック時の処理を行います。
259 void HexView::mouseDoubleClickEvent(QMouseEvent *e)
261 if (e->button() == Qt::LeftButton) {
262 int cPos = cursorPos(e->pos());
263 int lineHead = (cPos / BYTES_PER_LINE) * BYTES_PER_LINE;
264 resetSelection(lineHead);
265 setSelection(lineHead + BYTES_PER_LINE);
271 ///////////////////////////////////////////////////////////////////////////////
272 /// \brief HexView::mouseMoveEvent
273 /// \param e マウスイベントオブジェクト
277 void HexView::mouseMoveEvent(QMouseEvent *e)
279 m_scrollArea->ensureVisible(e->x(), e->y());
281 int cPos = cursorPos(e->pos());
288 ///////////////////////////////////////////////////////////////////////////////
289 /// \brief HexView::paintEvent
290 /// \param e 描画イベントオブジェクト
294 void HexView::paintEvent(QPaintEvent *e)
296 QPainter painter(this);
299 int firstLineIdx = ((e->rect().top() / m_charHeight) - m_charHeight) * BYTES_PER_LINE;
300 if (firstLineIdx < 0)
302 int lastLineIdx = ((e->rect().bottom() / m_charHeight) + m_charHeight) * BYTES_PER_LINE;
303 if (lastLineIdx > m_data.size())
304 lastLineIdx = m_data.size();
306 int yPosStart = (firstLineIdx / BYTES_PER_LINE) * m_charHeight + m_charHeight;
309 QRect addressRect(e->rect());
310 addressRect.setLeft(0);
311 addressRect.setWidth(m_charWidth * addressChars());
312 painter.fillRect(addressRect, Qt::gray);
313 painter.setPen(Qt::black);
314 for (int lineIdx = firstLineIdx, yPos = yPosStart;
315 lineIdx < lastLineIdx;
316 lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
318 QString address = QString("%1")
319 .arg(lineIdx, addressChars(), 16, QChar('0'));
320 painter.drawText(addressRect.left(), yPos, address);
324 for (int lineIdx = firstLineIdx, yPos = yPosStart;
325 lineIdx < lastLineIdx;
326 lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
328 int xPos = xPosHex();
330 lineIdx + colIdx < m_data.size() && colIdx < BYTES_PER_LINE;
331 colIdx++, xPos += m_charWidth * 3)
333 int Idx = lineIdx + colIdx;
334 if (m_selectionBegin <= Idx && Idx < m_selectionEnd) {
335 painter.setBackground(this->palette().highlight());
336 painter.setBackgroundMode(Qt::OpaqueMode);
337 painter.setPen(this->palette().highlightedText().color());
340 painter.setPen(this->palette().color(this->foregroundRole()));
341 painter.setBackgroundMode(Qt::TransparentMode);
344 quint8 ch = static_cast<quint8>(m_data[Idx]);
345 QString s = QString("%1").arg(ch, 2, 16, QChar('0'));
348 painter.drawText(xPos, yPos, s);
352 painter.drawText(xPos, yPos, s);
358 painter.setPen(this->palette().color(this->foregroundRole()));
359 painter.setBackgroundMode(Qt::TransparentMode);
360 for (int lineIdx = firstLineIdx, yPos = yPosStart;
361 lineIdx < lastLineIdx;
362 lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
364 int xPos = xPosAscii();
367 lineIdx + colIdx < m_data.size() && colIdx < BYTES_PER_LINE;
368 colIdx++, xPos += m_charWidth)
370 quint8 ch = static_cast<quint8>(m_data[lineIdx + colIdx]);
371 if (!::isprint(ch) && ch != ' ') {
374 QString s = QString(ch).toLatin1();
375 painter.drawText(xPos, yPos, s);