Advertisement
Guest User

Untitled

a guest
Jun 28th, 2013
855
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "qpconsole.h"
  2.  
  3. #include <QApplication>
  4. #include <QTextBlock>
  5. #include <QTextDocument>
  6. #include <QTextCursor>
  7. #include <QClipboard>
  8.  
  9. QPConsole::QPConsole(QWidget *parent) :
  10.   QPlainTextEdit(parent),
  11.   mHistoryPos(-1),
  12.   mCommandLineReady(false)
  13. {
  14.   QPalette p = palette();
  15.   p.setColor(QPalette::Active, QPalette::Base, Qt::black);
  16.   p.setColor(QPalette::Inactive, QPalette::Base, Qt::black);
  17.   p.setColor(QPalette::Active, QPalette::Text, Qt::white);
  18.   p.setColor(QPalette::Inactive, QPalette::Text, Qt::white);
  19.   setPalette(p);
  20.  
  21.   QFont f;
  22. #ifdef Q_OS_LINUX
  23.   f.setFamily("Monospace");
  24.   f.setPointSize(10);
  25. #else
  26.   f.setFamily("Lucida Console");
  27.   f.setPointSize(10);
  28. #endif
  29.   f.setFixedPitch(true);
  30.   setFont(f);
  31.  
  32.   setCursorWidth(QFontMetrics(font()).width(QChar('x')));
  33.   setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  34.   setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  35.   setUndoRedoEnabled(false);
  36.   setLineWrapMode(QPlainTextEdit::NoWrap);
  37.   setWordWrapMode(QTextOption::NoWrap);
  38.   setBackgroundVisible(false);
  39.   setFrameStyle(QFrame::NoFrame);
  40.   setTabStopWidth(40);
  41.   setAcceptDrops(false);
  42.   setPrefix("terminal> ");
  43.   setPrefixColor(QColor(140, 255, 50));
  44.   f.setBold(true);
  45.   setPrefixFont(f);
  46.  
  47.   prepareCommandLine();
  48. }
  49.  
  50. void QPConsole::setPrefix(const QString &prefix)
  51. {
  52.   mPrefix = prefix;
  53. }
  54.  
  55. void QPConsole::setPrefixColor(const QColor &color)
  56. {
  57.   mPrefixColor = color;
  58. }
  59.  
  60. void QPConsole::setPrefixFont(const QFont &font)
  61. {
  62.   mPrefixFont = font;
  63. }
  64.  
  65. bool QPConsole::inCommandLine() const
  66. {
  67.   return mCommandLineReady && document()->blockCount()-1 == textCursor().blockNumber() && textCursor().positionInBlock() >= mPrefix.length();
  68. }
  69.  
  70. void QPConsole::processCommand()
  71. {
  72.   QString inputString = document()->lastBlock().text();
  73.   if (inputString.startsWith(mPrefix))
  74.     inputString.remove(0, mPrefix.length());
  75.   if (!inputString.trimmed().isEmpty())
  76.     mHistory.append(inputString);
  77.   mHistoryPos = -1;
  78.   inputString = inputString.trimmed();
  79.  
  80.   QStringList params;
  81.   QString cmd;
  82.   int p = inputString.indexOf(' ');
  83.   if (p > -1)
  84.   {
  85.     cmd = inputString.mid(0, p);
  86.     params = getParams(inputString.mid(p+1));
  87.   } else
  88.     cmd = inputString;
  89.  
  90.   QTextCursor cur(document()->lastBlock());
  91.   cur.movePosition(QTextCursor::EndOfBlock);
  92.   cur.insertBlock();
  93.   setTextCursor(cur);
  94.   mCommandLineReady = false;
  95.   emit command(cmd, params);
  96. }
  97.  
  98. QStringList QPConsole::getParams(QString str)
  99. {
  100.   QStringList result;
  101.   str = str.trimmed();
  102.   if (str.isEmpty())
  103.     return result;
  104.  
  105.   bool escaped = false;
  106.   bool quoted = false;
  107.   QString param;
  108.   int i = 0;
  109.   while (i < str.size())
  110.   {
  111.     if (escaped)
  112.     {
  113.       escaped = false;
  114.       param += str[i];
  115.     } else if (str[i] == '\\')
  116.     {
  117.       escaped = true;
  118.     } else if (str[i] == '"')
  119.     {
  120.       quoted = !quoted;
  121.       if (!param.isEmpty() && !(i+1>=str.size() || str[i+1]==' ')) // only add quote if not first and last, embracing a parameter
  122.         param += str[i];
  123.     } else if (str[i] == ' ')
  124.     {
  125.       if (quoted)
  126.       {
  127.         param += str[i];
  128.       } else if (!param.isEmpty())
  129.       {
  130.         result.append(param);
  131.         param.clear();
  132.       }
  133.     } else
  134.     {
  135.       param += str[i];
  136.     }
  137.     ++i;
  138.   }
  139.   if (!param.isEmpty())
  140.   {
  141.     result.append(param);
  142.     param.clear();
  143.   }
  144.   return result;
  145. }
  146.  
  147. void QPConsole::keyPressEvent(QKeyEvent *event)
  148. {
  149.   if (inCommandLine())
  150.   {
  151.     // clear selection that spans multiple blocks (or prefix characters) (would overwrite previous command lines):
  152.     QTextCursor cur = textCursor();
  153.     if (cur.hasSelection())
  154.     {
  155.       if (document()->findBlock(cur.selectionStart()) != document()->findBlock(cur.selectionEnd()) || // spans multiple blocks (including command line)
  156.           cur.selectionStart()-cur.block().position() < mPrefix.length() || // spans prefix
  157.           cur.selectionEnd()-cur.block().position() < mPrefix.length() ) // spans prefix
  158.       {
  159.         cur.clearSelection();
  160.         if (cur.positionInBlock() < mPrefix.length())
  161.           cur.setPosition(cur.block().position()+mPrefix.length());
  162.         setTextCursor(cur);
  163.       }
  164.     }
  165.     if (cur.positionInBlock() == mPrefix.length())
  166.     {
  167.       cur.setCharFormat(QTextCharFormat()); // make sure we don't pick up format from prefix
  168.       setTextCursor(cur);
  169.     }
  170.     // react to keystroke:
  171.     if (event->matches(QKeySequence::MoveToPreviousLine)) // history up
  172.     {
  173.       if (mHistory.isEmpty() || mHistoryPos >= mHistory.size()-1)
  174.         return;
  175.       ++mHistoryPos;
  176.       int index = mHistory.size()-mHistoryPos-1;
  177.       QTextCursor cur(document()->lastBlock());
  178.       cur.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mPrefix.length());
  179.       cur.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
  180.       cur.removeSelectedText();
  181.       cur.setCharFormat(QTextCharFormat());
  182.       cur.insertText(mHistory.at(index));
  183.       setTextCursor(cur);
  184.     } else if (event->matches(QKeySequence::MoveToNextLine)) // history down
  185.     {
  186.       if (mHistory.isEmpty() || mHistoryPos <= 0)
  187.         return;
  188.       --mHistoryPos;
  189.       int index = mHistory.size()-mHistoryPos-1;
  190.       QTextCursor cur(document()->lastBlock());
  191.       cur.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mPrefix.length());
  192.       cur.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
  193.       cur.removeSelectedText();
  194.       cur.setCharFormat(QTextCharFormat());
  195.       cur.insertText(mHistory.at(index));
  196.       setTextCursor(cur);
  197.     } else if (event->matches(QKeySequence::Paste)) // paste text, do it manually to remove text char formatting and newlines
  198.     {
  199.       QString pasteText = QApplication::clipboard()->text();
  200.       pasteText.replace("\n", "").replace("\r", "");
  201.       cur.setCharFormat(QTextCharFormat());
  202.       cur.insertText(pasteText);
  203.       setTextCursor(cur);
  204.     } else if (event->key() == Qt::Key_Return) // process command
  205.     {
  206.       processCommand();
  207.     } else if (event->key() == Qt::Key_Backspace) // only allow backspace if we wouldn't delete last char of prefix
  208.     {
  209.       if (cur.positionInBlock() > mPrefix.length())
  210.         QPlainTextEdit::keyPressEvent(event);
  211.     } else if (!event->matches(QKeySequence::Close) &&
  212.                !event->matches(QKeySequence::New) &&
  213.                !event->matches(QKeySequence::Open) &&
  214.                !event->matches(QKeySequence::Preferences) &&
  215.                !event->matches(QKeySequence::Bold) &&
  216.                !event->matches(QKeySequence::Italic) &&
  217.                !event->matches(QKeySequence::InsertLineSeparator) &&
  218.                !event->matches(QKeySequence::InsertParagraphSeparator) &&
  219.                !event->matches(QKeySequence::Redo) &&
  220.                !event->matches(QKeySequence::Undo) &&
  221.                !event->matches(QKeySequence::DeleteStartOfWord))
  222.     {
  223.       QPlainTextEdit::keyPressEvent(event);
  224.     }
  225.   } else // cursor position not in command line
  226.   {
  227.     if (event->matches(QKeySequence::MoveToEndOfDocument) ||
  228.         event->matches(QKeySequence::MoveToEndOfBlock) ||
  229.         event->matches(QKeySequence::MoveToEndOfLine) ||
  230.         event->matches(QKeySequence::MoveToStartOfDocument) ||
  231.         event->matches(QKeySequence::MoveToStartOfBlock) ||
  232.         event->matches(QKeySequence::MoveToStartOfLine) ||
  233.         event->matches(QKeySequence::MoveToNextLine) ||
  234.         event->matches(QKeySequence::MoveToNextWord) ||
  235.         event->matches(QKeySequence::MoveToNextChar) ||
  236.         event->matches(QKeySequence::MoveToPreviousLine) ||
  237.         event->matches(QKeySequence::MoveToPreviousWord) ||
  238.         event->matches(QKeySequence::MoveToPreviousChar) ||
  239.         event->matches(QKeySequence::SelectAll) ||
  240.         event->matches(QKeySequence::SelectEndOfDocument) ||
  241.         event->matches(QKeySequence::SelectEndOfBlock) ||
  242.         event->matches(QKeySequence::SelectEndOfLine) ||
  243.         event->matches(QKeySequence::SelectStartOfDocument) ||
  244.         event->matches(QKeySequence::SelectStartOfBlock) ||
  245.         event->matches(QKeySequence::SelectStartOfLine) ||
  246.         event->matches(QKeySequence::SelectNextLine) ||
  247.         event->matches(QKeySequence::SelectNextWord) ||
  248.         event->matches(QKeySequence::SelectNextChar) ||
  249.         event->matches(QKeySequence::SelectPreviousLine) ||
  250.         event->matches(QKeySequence::SelectPreviousWord) ||
  251.         event->matches(QKeySequence::SelectPreviousChar) ||
  252.         event->matches(QKeySequence::Copy) )
  253.       QPlainTextEdit::keyPressEvent(event);
  254.   }
  255. }
  256.  
  257. void QPConsole::print(QString str)
  258. {
  259.   QTextCursor cur(document()->lastBlock());
  260.   cur.setCharFormat(QTextCharFormat());
  261.   cur.insertText(str);
  262.   cur.movePosition(QTextCursor::EndOfBlock);
  263.   cur.insertBlock();
  264.   setTextCursor(cur);
  265.   mCommandLineReady = false;
  266. }
  267.  
  268. void QPConsole::prepareCommandLine()
  269. {
  270.   QTextCursor cur(document()->lastBlock());
  271.   if (!document()->lastBlock().text().isEmpty())
  272.   {
  273.     cur.movePosition(QTextCursor::EndOfBlock);
  274.     cur.insertBlock();
  275.   }
  276.   QTextCharFormat fmt;
  277.   fmt.setForeground(QBrush(mPrefixColor));
  278.   fmt.setFont(mPrefixFont);
  279.   cur.setCharFormat(fmt);
  280.   cur.insertText(mPrefix);
  281.   cur.setCharFormat(QTextCharFormat());
  282.   setTextCursor(cur);
  283.   mCommandLineReady = true;
  284. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement