Advertisement
Guest User

Untitled

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