2 #include "preferences.h"
5 #include <QApplication>
10 #include <QScrollArea>
13 const int GAP_LINE_TEXT = 1;
14 const int MARGIN_RIGHT = 1;
16 ///////////////////////////////////////////////////////////////////////////////
17 /// \brief TextView::TextView
18 /// \param parent 親ウィジェット
22 TextView::TextView(QScrollArea *parent) :
25 m_scrollArea = parent;
26 m_scrollArea->setWidget(this);
27 setObjectName("textView");
28 setCursor(Qt::IBeamCursor);
33 ///////////////////////////////////////////////////////////////////////////////
34 /// \brief TextView::setData
39 void TextView::setData(const QByteArray &data)
43 std::string code = detectCode(data.left(1024));
44 convertFrom(code.c_str());
47 ///////////////////////////////////////////////////////////////////////////////
48 /// \brief TextView::adjust
52 void TextView::adjust()
57 for (; offset < m_data.size(); ++offset) {
58 if (m_data[offset] == '\r') {
59 if (offset + 1 < m_data.size() && m_data[offset + 1] == '\n') {
64 else if (m_data[offset] == '\n') {
70 int lineNumWidth = m_charWidth * lineNumChars(lineNum);
72 int xPosText = lineNumWidth + GAP_LINE_TEXT * m_charWidth;
74 setMinimumWidth(xPosText + m_charWidth * 4);
77 m_viewPositions.clear();
82 const int lineMaxWidth = width() - xPosText - MARGIN_RIGHT * m_charWidth;
83 for (lineNum = 1, offset = 0; offset < m_data.size(); ++offset) {
85 if (m_data[offset] == '\r') {
87 if (offset < m_data.size() - 1 && m_data[offset + 1] == '\n') {
91 if (m_data[offset] == '\n') {
96 vPos.lineNum = lineNum;
99 int charWidth = fontMetrics().width(m_data.mid(offset, 1));
102 charWidth = fontMetrics().width(0x21B5);
104 else if (m_data[offset] == '\t') {
105 tabIndent = ((lineWidth + m_tabWidth) / m_tabWidth) * m_tabWidth - lineWidth;
106 charWidth = fontMetrics().width("^");
109 if (x + charWidth >= lineMaxWidth) {
114 vPos.x = xPosText + x;
115 vPos.y = y + wrapLine * m_charHeight;
116 m_viewPositions << vPos;
121 y += (wrapLine + 1) * m_charHeight;
126 if (m_data[offset] == '\t') {
128 if (x > lineMaxWidth) {
129 x = x - lineMaxWidth;
136 lineWidth += charWidth + tabIndent;
140 if (!m_viewPositions.isEmpty()) {
141 setMinimumHeight(m_viewPositions.last().y + m_charHeight);
145 ///////////////////////////////////////////////////////////////////////////////
146 /// \brief TextView::convertFrom
147 /// \param code 文字コード
151 void TextView::convertFrom(const char *code)
153 QTextCodec *codec = QTextCodec::codecForName(code);
154 m_data = codec->toUnicode(m_source);
159 emit statusChanged(code);
162 ///////////////////////////////////////////////////////////////////////////////
163 /// \brief TextView::cursorPos
164 /// \param pos カーソル位置
165 /// \return カーソル位置に該当するViewPositionのインデックスを返します。
167 int TextView::cursorPos(const QPoint &pos)
171 for (n = 0; n < m_viewPositions.size(); n++) {
172 if (pos.y() < m_viewPositions[n].y) {
173 y = m_viewPositions[n].y;
178 for(; n < m_viewPositions.size(); n++) {
179 if (pos.x() < m_viewPositions[n].x) {
182 if (y < m_viewPositions[n].y) {
190 ///////////////////////////////////////////////////////////////////////////////
191 /// \brief TextView::lineNumChars
193 /// \return 行番号の表示に必要な桁数を返します。
195 int TextView::lineNumChars(int lines) const
198 if (m_viewPositions.isEmpty()) {
201 lines = m_viewPositions.last().lineNum;
203 return QString("%1").arg(lines).size() + 1;
206 ///////////////////////////////////////////////////////////////////////////////
207 /// \brief TextView::resetSelection
208 /// \param index ViewPositionのインデックス
212 void TextView::resetSelection(int index)
214 m_selectionInit = index;
215 m_selectionBegin = index;
216 m_selectionEnd = index;
218 emit copyAvailable(false);
221 ///////////////////////////////////////////////////////////////////////////////
222 /// \brief TextView::setSelection
223 /// \param index ViewPositionのインデックス
227 void TextView::setSelection(int index)
229 if (index > m_selectionInit) {
230 m_selectionBegin = m_selectionInit;
231 m_selectionEnd = index;
234 m_selectionBegin = index;
235 m_selectionEnd = m_selectionInit;
238 emit copyAvailable(m_selectionBegin != m_selectionEnd);
241 ///////////////////////////////////////////////////////////////////////////////
242 /// \brief TextView::onConvertFromEUC
244 /// EUC-JPからUnicodeへ変換します。
246 void TextView::onConvertFromEUC()
248 convertFrom("EUC-JP");
251 ///////////////////////////////////////////////////////////////////////////////
252 /// \brief TextView::onConvertFromJIS
254 /// ISO-2022-JP(JIS)からUnicodeへ変換します。
256 void TextView::onConvertFromJIS()
258 convertFrom("ISO 2022-JP");
261 ///////////////////////////////////////////////////////////////////////////////
262 /// \brief TextView::onConvertFromSJIS
264 /// Shift-JIS(SJIS)からUnicodeへ変換します。
266 void TextView::onConvertFromSJIS()
268 convertFrom("Shift-JIS");
271 ///////////////////////////////////////////////////////////////////////////////
272 /// \brief TextView::onConvertFromUTF8
274 /// UTF-8からUnicodeへ変換します。
276 void TextView::onConvertFromUTF8()
278 convertFrom("UTF-8");
281 ///////////////////////////////////////////////////////////////////////////////
282 /// \brief TextView::onConvertFromUTF16
284 /// UTF-16からUnicodeへ変換します。
286 void TextView::onConvertFromUTF16()
288 convertFrom("UTF-16");
291 ///////////////////////////////////////////////////////////////////////////////
292 /// \brief TextView::onConvertFromUTF16BE
294 /// UTF-16BEからUnicodeへ変換します。
296 void TextView::onConvertFromUTF16BE()
298 convertFrom("UTF-16BE");
301 ///////////////////////////////////////////////////////////////////////////////
302 /// \brief TextView::onConvertFromUTF16LE
304 /// UTF-16LEからUnicodeへ変換します。
306 void TextView::onConvertFromUTF16LE()
308 convertFrom("UTF-16LE");
311 ///////////////////////////////////////////////////////////////////////////////
312 /// \brief TextView::onCopy
314 /// 選択領域をクリップボードにコピーします。
316 void TextView::onCopy()
319 int length = m_viewPositions[m_selectionEnd].offset -
320 m_viewPositions[m_selectionBegin].offset;
322 selected = m_data.mid(m_viewPositions[m_selectionBegin].offset, length);
324 QClipboard *clipboard = qApp->clipboard();
325 clipboard->setText(selected);
328 ///////////////////////////////////////////////////////////////////////////////
329 /// \brief TextView::onScaleDown
333 void TextView::onScaleDown()
335 Preferences prefs(this);
336 QFont font = prefs.getTextViewFont();
337 font.setPointSize(font.pointSize() - 1);
338 prefs.setTextViewFont(font);
345 ///////////////////////////////////////////////////////////////////////////////
346 /// \brief TextView::onScaleUp
350 void TextView::onScaleUp()
352 Preferences prefs(this);
353 QFont font = prefs.getTextViewFont();
354 font.setPointSize(font.pointSize() + 1);
355 prefs.setTextViewFont(font);
362 ///////////////////////////////////////////////////////////////////////////////
363 /// \brief TextView::onSelectAll
367 void TextView::onSelectAll()
370 m_selectionBegin = 0;
371 m_selectionEnd = m_viewPositions.size();
374 ///////////////////////////////////////////////////////////////////////////////
375 /// \brief TextView::setVisible
376 /// \param visible 表示(true)/非表示(false)
380 void TextView::setVisible(bool visible)
383 Preferences prefs(this);
384 QPalette pal = this->palette();
385 pal.setColor(this->backgroundRole(), prefs.getTextViewBgColor());
386 pal.setColor(this->foregroundRole(), prefs.getTextViewFgColor());
387 pal.setBrush(QPalette::BrightText, prefs.getTextViewCtrlColor());
388 this->setPalette(pal);
389 this->setAutoFillBackground(true);
390 this->setFont(prefs.getTextViewFont());
392 m_charHeight = fontMetrics().height() * prefs.getTextViewLineHeight();
393 m_charWidth = fontMetrics().width('9');
394 m_tabWidth = 8 * m_charWidth;
397 QWidget::setVisible(visible);
400 ///////////////////////////////////////////////////////////////////////////////
401 /// \brief TextView::mousePressEvent
402 /// \param e マウスイベントオブジェクト
404 /// マウスクリック時の処理を行います。
406 void TextView::mousePressEvent(QMouseEvent *e)
408 if (e->button() == Qt::LeftButton) {
409 int cPos = cursorPos(e->pos());
410 resetSelection(cPos);
416 ///////////////////////////////////////////////////////////////////////////////
417 /// \brief TextView::mouseDoubleClickEvent
418 /// \param e マウスイベントオブジェクト
420 /// ダブルクリック時の処理を行います。
422 void TextView::mouseDoubleClickEvent(QMouseEvent *e)
424 if (e->button() == Qt::LeftButton) {
425 int cPos = cursorPos(e->pos());
426 if (cPos >= m_viewPositions.size()) {
427 cPos = m_viewPositions.size() - 1;
429 int y = m_viewPositions[cPos].y;
432 for (n = cPos; n >= 0; n--) {
433 if (m_viewPositions[n].y != y) {
440 for (n = cPos; n < m_viewPositions.size(); n++) {
441 if (m_viewPositions[n].y != y) {
451 ///////////////////////////////////////////////////////////////////////////////
452 /// \brief TextView::mouseMoveEvent
453 /// \param e マウスイベントオブジェクト
457 void TextView::mouseMoveEvent(QMouseEvent *e)
459 m_scrollArea->ensureVisible(e->x(), e->y());
461 int cPos = cursorPos(e->pos());
466 ///////////////////////////////////////////////////////////////////////////////
467 /// \brief TextView::paintEvent
468 /// \param e ペイントイベントオブジェクト
472 void TextView::paintEvent(QPaintEvent *e)
474 QPainter painter(this);
477 QRect lineNumRect(e->rect());
478 lineNumRect.setLeft(0);
479 lineNumRect.setWidth(m_charWidth * lineNumChars());
480 painter.fillRect(lineNumRect, Qt::gray);
485 idx < m_viewPositions.size() &&
486 m_viewPositions[idx].y < e->rect().top();
489 prevLine = m_viewPositions[idx].lineNum;
492 painter.setPen(this->palette().color(this->foregroundRole()));
494 idx < m_viewPositions.size() &&
495 m_viewPositions[idx].y <= e->rect().bottom() + m_charHeight;
498 const ViewPosition &vPos = m_viewPositions[idx];
501 if (vPos.lineNum != prevLine) {
502 prevLine = vPos.lineNum;
503 painter.setPen(Qt::black);
504 painter.setBackgroundMode(Qt::TransparentMode);
505 QString lineNumber = QString("%1").arg(vPos.lineNum);
507 lineNumRect.right() - fontMetrics().width(lineNumber),
512 if (m_selectionBegin <= idx && idx < m_selectionEnd) {
513 painter.setBackground(this->palette().highlight());
514 painter.setBackgroundMode(Qt::OpaqueMode);
515 painter.setPen(this->palette().highlightedText().color());
518 painter.setPen(this->palette().color(this->foregroundRole()));
519 painter.setBackgroundMode(Qt::TransparentMode);
522 QString ch = m_data.mid(vPos.offset, 1);
523 if (ch == "\r" || ch == "\n") {
524 painter.setPen(this->palette().color(QPalette::BrightText));
525 painter.drawText(vPos.x, vPos.y, QChar(0x21B5));
526 painter.setPen(this->palette().color(this->foregroundRole()));
528 else if (ch == "\t") {
529 // painter.setPen(this->palette().color(QPalette::BrightText));
530 // painter.drawText(vPos.x, vPos.y, "^");
531 // painter.setPen(this->palette().color(this->foregroundRole()));
534 painter.drawText(vPos.x, vPos.y, ch);
539 ///////////////////////////////////////////////////////////////////////////////
540 /// \brief TextView::resizeEvent
541 /// \param e リサイズイベントオブジェクト
545 void TextView::resizeEvent(QResizeEvent *e)
547 QWidget::resizeEvent(e);