2014-10-22 5 views
3

나는 일반적으로 터미널에 인쇄은 QTextEdit과 컬러 bash는 같은 출력 에뮬레이션

char const * text = "\e[1;33m" "some colored text" "\e[0m"; 

같은 텍스트에 이스케이프 시퀀스가 ​​있습니다. 하지만이 텍스트를 QTextEdit에 전달하고 싶습니다.

텍스트를 만드는 가장 간단한 방법은 무엇입니까 QTextEdit? 이스케이프 시퀀스의 필터링을 수행하는 방법, 즉 적절한 텍스트 형식으로 대체하는 방법

QSyntaxHighlighter -aided 솔루션이 있다고 생각하지만, 이스케이프 시퀀스 자체와 출력에서이를 숨기는 방법을 알지 못합니다.

+0

[ANSI 코드] (http://en.m.wikipedia.org/wiki/ANSI_escape_code)에서 Qt의 HTML 형식의 리치 텍스트 마크 업으로 변환하려면 뭔가 (아마 자신의 변환기 코드)가 필요합니다. – hyde

+1

@Hyde : 답변으로 작성하지 않으시겠습니까? – Silicomancer

+0

@Silicomancer 정말 답이 아니기 때문에 (그리고 나는 버스에서 전화로 편지를 썼다.) 그러나 나는 대답으로 지금 통과 할 무언가로 그것을 만드는 그것을 조금 확장 할 수 있었다고 생각한다. – hyde

답변

4

마지막으로, 나는 (이 QTextEdit::setReadOnly(true) 것을 이해) 접근 방식을 발견 :

// based on information: http://en.m.wikipedia.org/wiki/ANSI_escape_code http://misc.flogisoft.com/bash/tip_colors_and_formatting http://invisible-island.net/xterm/ctlseqs/ctlseqs.html 
void MainWindow::parseEscapeSequence(int attribute, QListIterator<QString> & i, QTextCharFormat & textCharFormat, QTextCharFormat const & defaultTextCharFormat) 
{ 
    switch (attribute) { 
    case 0 : { // Normal/Default (reset all attributes) 
     textCharFormat = defaultTextCharFormat; 
     break; 
    } 
    case 1 : { // Bold/Bright (bold or increased intensity) 
     textCharFormat.setFontWeight(QFont::Bold); 
     break; 
    } 
    case 2 : { // Dim/Faint (decreased intensity) 
     textCharFormat.setFontWeight(QFont::Light); 
     break; 
    } 
    case 3 : { // Italicized (italic on) 
     textCharFormat.setFontItalic(true); 
     break; 
    } 
    case 4 : { // Underscore (single underlined) 
     textCharFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline); 
     textCharFormat.setFontUnderline(true); 
     break; 
    } 
    case 5 : { // Blink (slow, appears as Bold) 
     textCharFormat.setFontWeight(QFont::Bold); 
     break; 
    } 
    case 6 : { // Blink (rapid, appears as very Bold) 
     textCharFormat.setFontWeight(QFont::Black); 
     break; 
    } 
    case 7 : { // Reverse/Inverse (swap foreground and background) 
     QBrush foregroundBrush = textCharFormat.foreground(); 
     textCharFormat.setForeground(textCharFormat.background()); 
     textCharFormat.setBackground(foregroundBrush); 
     break; 
    } 
    case 8 : { // Concealed/Hidden/Invisible (usefull for passwords) 
     textCharFormat.setForeground(textCharFormat.background()); 
     break; 
    } 
    case 9 : { // Crossed-out characters 
     textCharFormat.setFontStrikeOut(true); 
     break; 
    } 
    case 10 : { // Primary (default) font 
     textCharFormat.setFont(defaultTextCharFormat.font()); 
     break; 
    } 
    case 11 ... 19 : { 
     QFontDatabase fontDatabase; 
     QString fontFamily = textCharFormat.fontFamily(); 
     QStringList fontStyles = fontDatabase.styles(fontFamily); 
     int fontStyleIndex = attribute - 11; 
     if (fontStyleIndex < fontStyles.length()) { 
      textCharFormat.setFont(fontDatabase.font(fontFamily, fontStyles.at(fontStyleIndex), textCharFormat.font().pointSize())); 
     } 
     break; 
    } 
    case 20 : { // Fraktur (unsupported) 
     break; 
    } 
    case 21 : { // Set Bold off 
     textCharFormat.setFontWeight(QFont::Normal); 
     break; 
    } 
    case 22 : { // Set Dim off 
     textCharFormat.setFontWeight(QFont::Normal); 
     break; 
    } 
    case 23 : { // Unset italic and unset fraktur 
     textCharFormat.setFontItalic(false); 
     break; 
    } 
    case 24 : { // Unset underlining 
     textCharFormat.setUnderlineStyle(QTextCharFormat::NoUnderline); 
     textCharFormat.setFontUnderline(false); 
     break; 
    } 
    case 25 : { // Unset Blink/Bold 
     textCharFormat.setFontWeight(QFont::Normal); 
     break; 
    } 
    case 26 : { // Reserved 
     break; 
    } 
    case 27 : { // Positive (non-inverted) 
     QBrush backgroundBrush = textCharFormat.background(); 
     textCharFormat.setBackground(textCharFormat.foreground()); 
     textCharFormat.setForeground(backgroundBrush); 
     break; 
    } 
    case 28 : { 
     textCharFormat.setForeground(defaultTextCharFormat.foreground()); 
     textCharFormat.setBackground(defaultTextCharFormat.background()); 
     break; 
    } 
    case 29 : { 
     textCharFormat.setUnderlineStyle(QTextCharFormat::NoUnderline); 
     textCharFormat.setFontUnderline(false); 
     break; 
    } 
    case 30 ... 37 : { 
     int colorIndex = attribute - 30; 
     QColor color; 
     if (QFont::Normal < textCharFormat.fontWeight()) { 
      switch (colorIndex) { 
      case 0 : { 
       color = Qt::darkGray; 
       break; 
      } 
      case 1 : { 
       color = Qt::red; 
       break; 
      } 
      case 2 : { 
       color = Qt::green; 
       break; 
      } 
      case 3 : { 
       color = Qt::yellow; 
       break; 
      } 
      case 4 : { 
       color = Qt::blue; 
       break; 
      } 
      case 5 : { 
       color = Qt::magenta; 
       break; 
      } 
      case 6 : { 
       color = Qt::cyan; 
       break; 
      } 
      case 7 : { 
       color = Qt::white; 
       break; 
      } 
      default : { 
       Q_ASSERT(false); 
      } 
      } 
     } else { 
      switch (colorIndex) { 
      case 0 : { 
       color = Qt::black; 
       break; 
      } 
      case 1 : { 
       color = Qt::darkRed; 
       break; 
      } 
      case 2 : { 
       color = Qt::darkGreen; 
       break; 
      } 
      case 3 : { 
       color = Qt::darkYellow; 
       break; 
      } 
      case 4 : { 
       color = Qt::darkBlue; 
       break; 
      } 
      case 5 : { 
       color = Qt::darkMagenta; 
       break; 
      } 
      case 6 : { 
       color = Qt::darkCyan; 
       break; 
      } 
      case 7 : { 
       color = Qt::lightGray; 
       break; 
      } 
      default : { 
       Q_ASSERT(false); 
      } 
      } 
     } 
     textCharFormat.setForeground(color); 
     break; 
    } 
    case 38 : { 
     if (i.hasNext()) { 
      bool ok = false; 
      int selector = i.next().toInt(&ok); 
      Q_ASSERT(ok); 
      QColor color; 
      switch (selector) { 
      case 2 : { 
       if (!i.hasNext()) { 
        break; 
       } 
       int red = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       if (!i.hasNext()) { 
        break; 
       } 
       int green = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       if (!i.hasNext()) { 
        break; 
       } 
       int blue = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       color.setRgb(red, green, blue); 
       break; 
      } 
      case 5 : { 
       if (!i.hasNext()) { 
        break; 
       } 
       int index = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       switch (index) { 
       case 0x00 ... 0x07 : { // 0x00-0x07: standard colors (as in ESC [ 30..37 m) 
        return parseEscapeSequence(index - 0x00 + 30, i, textCharFormat, defaultTextCharFormat); 
       } 
       case 0x08 ... 0x0F : { // 0x08-0x0F: high intensity colors (as in ESC [ 90..97 m) 
        return parseEscapeSequence(index - 0x08 + 90, i, textCharFormat, defaultTextCharFormat); 
       } 
       case 0x10 ... 0xE7 : { // 0x10-0xE7: 6*6*6=216 colors: 16 + 36*r + 6*g + b (0≤r,g,b≤5) 
        index -= 0x10; 
        int red = index % 6; 
        index /= 6; 
        int green = index % 6; 
        index /= 6; 
        int blue = index % 6; 
        index /= 6; 
        Q_ASSERT(index == 0); 
        color.setRgb(red, green, blue); 
        break; 
       } 
       case 0xE8 ... 0xFF : { // 0xE8-0xFF: grayscale from black to white in 24 steps 
        qreal intensity = qreal(index - 0xE8)/(0xFF - 0xE8); 
        color.setRgbF(intensity, intensity, intensity); 
        break; 
       } 
       } 
       textCharFormat.setForeground(color); 
       break; 
      } 
      default : { 
       break; 
      } 
      } 
     } 
     break; 
    } 
    case 39 : { 
     textCharFormat.setForeground(defaultTextCharFormat.foreground()); 
     break; 
    } 
    case 40 ... 47 : { 
     int colorIndex = attribute - 40; 
     QColor color; 
     switch (colorIndex) { 
     case 0 : { 
      color = Qt::darkGray; 
      break; 
     } 
     case 1 : { 
      color = Qt::red; 
      break; 
     } 
     case 2 : { 
      color = Qt::green; 
      break; 
     } 
     case 3 : { 
      color = Qt::yellow; 
      break; 
     } 
     case 4 : { 
      color = Qt::blue; 
      break; 
     } 
     case 5 : { 
      color = Qt::magenta; 
      break; 
     } 
     case 6 : { 
      color = Qt::cyan; 
      break; 
     } 
     case 7 : { 
      color = Qt::white; 
      break; 
     } 
     default : { 
      Q_ASSERT(false); 
     } 
     } 
     textCharFormat.setBackground(color); 
     break; 
    } 
    case 48 : { 
     if (i.hasNext()) { 
      bool ok = false; 
      int selector = i.next().toInt(&ok); 
      Q_ASSERT(ok); 
      QColor color; 
      switch (selector) { 
      case 2 : { 
       if (!i.hasNext()) { 
        break; 
       } 
       int red = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       if (!i.hasNext()) { 
        break; 
       } 
       int green = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       if (!i.hasNext()) { 
        break; 
       } 
       int blue = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       color.setRgb(red, green, blue); 
       break; 
      } 
      case 5 : { 
       if (!i.hasNext()) { 
        break; 
       } 
       int index = i.next().toInt(&ok); 
       Q_ASSERT(ok); 
       switch (index) { 
       case 0x00 ... 0x07 : { // 0x00-0x07: standard colors (as in ESC [ 40..47 m) 
        return parseEscapeSequence(index - 0x00 + 40, i, textCharFormat, defaultTextCharFormat); 
       } 
       case 0x08 ... 0x0F : { // 0x08-0x0F: high intensity colors (as in ESC [ 100..107 m) 
        return parseEscapeSequence(index - 0x08 + 100, i, textCharFormat, defaultTextCharFormat); 
       } 
       case 0x10 ... 0xE7 : { // 0x10-0xE7: 6*6*6=216 colors: 16 + 36*r + 6*g + b (0≤r,g,b≤5) 
        index -= 0x10; 
        int red = index % 6; 
        index /= 6; 
        int green = index % 6; 
        index /= 6; 
        int blue = index % 6; 
        index /= 6; 
        Q_ASSERT(index == 0); 
        color.setRgb(red, green, blue); 
        break; 
       } 
       case 0xE8 ... 0xFF : { // 0xE8-0xFF: grayscale from black to white in 24 steps 
        qreal intensity = qreal(index - 0xE8)/(0xFF - 0xE8); 
        color.setRgbF(intensity, intensity, intensity); 
        break; 
       } 
       } 
       textCharFormat.setBackground(color); 
       break; 
      } 
      default : { 
       break; 
      } 
      } 
     } 
     break; 
    } 
    case 49 : { 
     textCharFormat.setBackground(defaultTextCharFormat.background()); 
     break; 
    } 
    case 90 ... 97 : { 
     int colorIndex = attribute - 90; 
     QColor color; 
     switch (colorIndex) { 
     case 0 : { 
      color = Qt::darkGray; 
      break; 
     } 
     case 1 : { 
      color = Qt::red; 
      break; 
     } 
     case 2 : { 
      color = Qt::green; 
      break; 
     } 
     case 3 : { 
      color = Qt::yellow; 
      break; 
     } 
     case 4 : { 
      color = Qt::blue; 
      break; 
     } 
     case 5 : { 
      color = Qt::magenta; 
      break; 
     } 
     case 6 : { 
      color = Qt::cyan; 
      break; 
     } 
     case 7 : { 
      color = Qt::white; 
      break; 
     } 
     default : { 
      Q_ASSERT(false); 
     } 
     } 
     color.setRedF(color.redF() * 0.8); 
     color.setGreenF(color.greenF() * 0.8); 
     color.setBlueF(color.blueF() * 0.8); 
     textCharFormat.setForeground(color); 
     break; 
    } 
    case 100 ... 107 : { 
     int colorIndex = attribute - 100; 
     QColor color; 
     switch (colorIndex) { 
     case 0 : { 
      color = Qt::darkGray; 
      break; 
     } 
     case 1 : { 
      color = Qt::red; 
      break; 
     } 
     case 2 : { 
      color = Qt::green; 
      break; 
     } 
     case 3 : { 
      color = Qt::yellow; 
      break; 
     } 
     case 4 : { 
      color = Qt::blue; 
      break; 
     } 
     case 5 : { 
      color = Qt::magenta; 
      break; 
     } 
     case 6 : { 
      color = Qt::cyan; 
      break; 
     } 
     case 7 : { 
      color = Qt::white; 
      break; 
     } 
     default : { 
      Q_ASSERT(false); 
     } 
     } 
     color.setRedF(color.redF() * 0.8); 
     color.setGreenF(color.greenF() * 0.8); 
     color.setBlueF(color.blueF() * 0.8); 
     textCharFormat.setBackground(color); 
     break; 
    } 
    default : { 
     break; 
    } 
    } 
} 

void MainWindow::setTextTermFormatting(QTextEdit * textEdit, QString const & text) 
{ 
    QTextDocument * document = textEdit->document(); 
    QRegExp const escapeSequenceExpression(R"(\x1B\[([\d;]+)m)"); 
    QTextCursor cursor(document); 
    QTextCharFormat const defaultTextCharFormat = cursor.charFormat(); 
    cursor.beginEditBlock(); 
    int offset = escapeSequenceExpression.indexIn(text); 
    cursor.insertText(text.mid(0, offset)); 
    QTextCharFormat textCharFormat = defaultTextCharFormat; 
    while (!(offset < 0)) { 
     int previousOffset = offset + escapeSequenceExpression.matchedLength(); 
     QStringList capturedTexts = escapeSequenceExpression.capturedTexts().back().split(';'); 
     QListIterator<QString> i(capturedTexts); 
     while (i.hasNext()) { 
      bool ok = false; 
      int attribute = i.next().toInt(&ok); 
      Q_ASSERT(ok); 
      parseEscapeSequence(attribute, i, textCharFormat, defaultTextCharFormat); 
     } 
     offset = escapeSequenceExpression.indexIn(text, previousOffset); 
     if (offset < 0) { 
      cursor.insertText(text.mid(previousOffset), textCharFormat); 
     } else { 
      cursor.insertText(text.mid(previousOffset, offset - previousOffset), textCharFormat); 
     } 
    } 
    cursor.setCharFormat(defaultTextCharFormat); 
    cursor.endEditBlock(); 
    //cursor.movePosition(QTextCursor::Start); 
    textEdit->setTextCursor(cursor); 
} 

완전히 순간에 테스트,하지만 확실히 실행할 수 없습니다. 그것은 내가 원하는 것입니다.

2

이들은 ANSI escape codes입니다. 그들은 특히 당신이 통제하는 작은 고정 하위 집합을 가지고 있다면, 분석하는 것은 매우 간단합니다. 아마 당신이 탈출 코드를 파싱하는 데 도움이 될 수있는 라이브러리가있을 것입니다. 그리고 단순한 색상보다 많은 코드를 지원해야 할 필요가 있다면 간단한 색상 코드가 필요하고 가득 차 있다면 원래 문자열을 제어 한 다음 직접 작성하는 것이 더 빠릅니다.

그래서해야 할 일은 문자열에서 이스케이프 코드를 구문 분석하고 HTML 마크 업의 하위 집합 인 Qt rich text markup으로 바꿉니다.


또 다른 방법은 반대를 할 수 있습니다 : 다음 색깔의 콘솔 출력에 대한 ANSI 코드에 그 변환, HTML (또는 다른) 마크 업을 사용하여 문자열을 저장합니다. 행운을 빌 자면 ANSI 이스케이프 코드를 사용하여 HTML을 텍스트로 변환 할 수있는 라이브러리를 찾을 수도 있습니다.