浏览代码

ENH: Removed low-level key processing from ctkConsolePrivate::keyPressEvent

We now use QKeySequence for determining what action the user initiated
on the terminal (instead of trying to figure out from low-level keypresses
and keypress modifiers).

Added Page up/down scrolling to the terminal window.
Andras Lasso 10 年之前
父节点
当前提交
b1f69f22f4
共有 2 个文件被更改,包括 189 次插入134 次删除
  1. 187 134
      Libs/Widgets/ctkConsole.cpp
  2. 2 0
      Libs/Widgets/ctkConsole_p.h

+ 187 - 134
Libs/Widgets/ctkConsole.cpp

@@ -148,6 +148,51 @@ void ctkConsolePrivate::init()
 }
 
 //-----------------------------------------------------------------------------
+bool ctkConsolePrivate::isMoveLeftWithinLine(QKeyEvent* e, QTextCursor::MoveOperation &moveOperation, QTextCursor::MoveMode &moveMode)
+{
+  if (e == QKeySequence::MoveToPreviousChar)
+    {
+    moveOperation = QTextCursor::Left;
+    moveMode = QTextCursor::MoveAnchor;
+    return true;
+    }
+  else if (e == QKeySequence::SelectPreviousChar)
+    {
+    moveOperation = QTextCursor::Left;
+    moveMode = QTextCursor::KeepAnchor;
+    return true;
+    }
+  else if (e == QKeySequence::MoveToPreviousWord)
+    {
+    moveOperation = QTextCursor::WordLeft;
+    moveMode = QTextCursor::MoveAnchor;
+    return true;
+    }
+  else if (e == QKeySequence::SelectPreviousWord)
+    {
+    moveOperation = QTextCursor::WordLeft;
+    moveMode = QTextCursor::KeepAnchor;
+    return true;
+    }
+  else if (e == QKeySequence::MoveToStartOfLine)
+    {
+    moveOperation = QTextCursor::StartOfLine;
+    moveMode = QTextCursor::MoveAnchor;
+    return true;
+    }
+  else if (e == QKeySequence::SelectStartOfLine)
+    {
+    moveOperation = QTextCursor::StartOfLine;
+    moveMode = QTextCursor::KeepAnchor;
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+}
+
+//-----------------------------------------------------------------------------
 void ctkConsolePrivate::keyPressEvent(QKeyEvent* e)
 {
   if (this->Completer && this->Completer->popup()->isVisible())
@@ -167,169 +212,177 @@ void ctkConsolePrivate::keyPressEvent(QKeyEvent* e)
       }
     }
 
-    QTextCursor text_cursor = this->textCursor();
+  QTextCursor text_cursor = this->textCursor();
 
-    // Set to true if there's a current selection
-    const bool selection = text_cursor.anchor() != text_cursor.position();
-    // Set to true if the cursor overlaps the history area
-    const bool history_area = this->isCursorInHistoryArea();
+  // Set to true if there's a current selection
+  const bool selection = text_cursor.anchor() != text_cursor.position();
+  // Set to true if the cursor overlaps the history area
+  const bool history_area = this->isCursorInHistoryArea();
 
-    // Allow copying anywhere in the console ...
-    if(e == QKeySequence::Copy)
+  // Allow copying anywhere in the console ...
+  if(e == QKeySequence::Copy)
+    {
+    if(selection)
       {
-      if(selection)
-        {
-        this->copy();
-        }
+      this->copy();
+      }
+    e->accept();
+    return;
+    }
 
-      e->accept();
-      return;
+  // Allow cut only if the selection is limited to the interactive area ...
+  if(e == QKeySequence::Cut)
+    {
+    if(selection && !history_area)
+      {
+      this->cut();
       }
+    e->accept();
+    return;
+    }
 
-    // Allow cut only if the selection is limited to the interactive area ...
-    if(e == QKeySequence::Cut)
+  // Paste to the end of document if in the history area
+  if(e == QKeySequence::Paste)
+    {
+    if(history_area)
       {
-      if(selection && !history_area)
-        {
-        this->cut();
-        }
+      text_cursor.setPosition(this->documentEnd());
+      this->setTextCursor(text_cursor);
+      }
+    this->paste();
+    e->accept();
+    return;
+    }
 
+  // Allow vertical scrolling using page up/down
+  if (e == QKeySequence::MoveToPreviousPage || e == QKeySequence::SelectPreviousPage
+    || e == QKeySequence::MoveToNextPage || e == QKeySequence::SelectNextPage)
+    {
+    if (e == QKeySequence::SelectPreviousPage || e == QKeySequence::SelectNextPage)
+      {
+      // ignore
       e->accept();
-      return;
       }
+    else
+      {
+      this->Superclass::keyPressEvent(e);
+      this->updateCommandBuffer();
+      }
+    return;
+    }
 
-    // Paste to the end of document if in the history area
-    if(e == QKeySequence::Paste)
+  // Force the cursor back to the interactive area if anything else than copy/paste or page up/down is done
+  if(history_area)
+    {
+    text_cursor.setPosition(this->documentEnd());
+    this->setTextCursor(text_cursor);
+    }
+
+  // Start of line should be the start of interactive area
+  QTextCursor::MoveOperation moveOperation = QTextCursor::NoMove;
+  QTextCursor::MoveMode moveMode = QTextCursor::MoveAnchor;
+  if(isMoveLeftWithinLine(e, moveOperation, moveMode))
+    {
+    text_cursor.movePosition(moveOperation, moveMode);
+    if (text_cursor.position() > this->InteractivePosition)
       {
-      if(history_area)
-        {
-        text_cursor.setPosition(this->documentEnd());
-        this->setTextCursor(text_cursor);  
-        }
-      this->paste();
+      this->Superclass::keyPressEvent(e);
+      }
+    else
+      {
+      text_cursor.setPosition(this->InteractivePosition, moveMode);
+      this->setTextCursor(text_cursor);
       e->accept();
-      return;
       }
+    return;
+    }
+
+  if (e == QKeySequence::Delete)
+    {
+    e->accept();
+    this->Superclass::keyPressEvent(e);
+    this->updateCommandBuffer();
+    return;
+    }
+
+  if (e == QKeySequence::Back)
+    {
+    e->accept();
+    if(text_cursor.position() > this->InteractivePosition)
+      {
+      this->Superclass::keyPressEvent(e);
+      this->updateCommandBuffer();
+      this->updateCompleterIfVisible();
+      }
+    return;
+    }
 
-    // Start of line should be the start of interactive area
-    if(e == QKeySequence::MoveToPreviousChar || e == QKeySequence::SelectPreviousChar
-      || e == QKeySequence::MoveToPreviousWord || e == QKeySequence::SelectPreviousWord
-      || e == QKeySequence::MoveToStartOfLine || e == QKeySequence::SelectStartOfLine)
+  if (e == QKeySequence::DeleteStartOfWord)
       {
-      QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
-      if (e == QKeySequence::SelectPreviousChar
-        || e == QKeySequence::SelectPreviousWord
-        || e == QKeySequence::SelectStartOfLine)
-        {
-        mode = QTextCursor::KeepAnchor;
-        }
-      QTextCursor::MoveOperation op = QTextCursor::Left;
-      if (e == QKeySequence::MoveToPreviousWord || e == QKeySequence::SelectPreviousWord)
-        {
-        op = QTextCursor::WordLeft;
-        }
-      else if (e == QKeySequence::MoveToStartOfLine || e == QKeySequence::SelectStartOfLine)
-        {
-        op = QTextCursor::StartOfLine;
-        }
-      text_cursor.movePosition(op, mode);
-      if (text_cursor.position() > this->InteractivePosition)
+      e->accept();
+      if(text_cursor.position() > this->InteractivePosition)
         {
         this->Superclass::keyPressEvent(e);
-        }
-      else
-        {
-        text_cursor.setPosition(this->InteractivePosition, mode);
-        this->setTextCursor(text_cursor);
-        e->accept();
+        this->updateCommandBuffer();
+        this->updateCompleterIfVisible();
         }
       return;
       }
 
-    // Force the cursor back to the interactive area if a letter key is pressed
-    if(history_area
-       && e->key() != Qt::Key_Control
-       && e->key() != Qt::Key_Meta
-       && e->key() != Qt::Key_Alt
-       && e->key() != Qt::Key_Shift
-       )
+  if (e == QKeySequence::MoveToPreviousLine || e == QKeySequence::SelectPreviousLine)
+    {
+    e->accept();
+    if (this->CommandPosition > 0)
       {
-      text_cursor.setPosition(this->documentEnd());
-      this->setTextCursor(text_cursor);
+      this->replaceCommandBuffer(this->CommandHistory[--this->CommandPosition]);
       }
+    return;
+    }
 
-    switch(e->key())
+  if (e == QKeySequence::MoveToNextLine || e == QKeySequence::SelectNextLine)
+    {
+    e->accept();
+    if (this->CommandPosition < this->CommandHistory.size() - 2)
       {
-      case Qt::Key_Up:
-        e->accept();
-
-        if (this->CommandPosition > 0)
-          {
-          this->replaceCommandBuffer(this->CommandHistory[--this->CommandPosition]);
-          }
-        break;
-
-      case Qt::Key_Down:
-        e->accept();
-
-        if (this->CommandPosition < this->CommandHistory.size() - 2)
-          {
-          this->replaceCommandBuffer(this->CommandHistory[++this->CommandPosition]);
-          }
-        else
-          {
-          this->CommandPosition = this->CommandHistory.size()-1;
-          this->replaceCommandBuffer("");
-          }
-        break;
-      case Qt::Key_Delete:
-        e->accept();
-        this->Superclass::keyPressEvent(e);
-        this->updateCommandBuffer();
-        break;
-
-      case Qt::Key_Backspace:
-        e->accept();
-        if(text_cursor.position() > this->InteractivePosition)
-          {
-          this->Superclass::keyPressEvent(e);
-          this->updateCommandBuffer();
-          this->updateCompleterIfVisible();
-          }
-        break;
-
-      case Qt::Key_Tab:
-        e->accept();
-        this->updateCompleter();
-        this->selectCompletion();
-        break;
+      this->replaceCommandBuffer(this->CommandHistory[++this->CommandPosition]);
+      }
+    else
+      {
+      this->CommandPosition = this->CommandHistory.size()-1;
+      this->replaceCommandBuffer("");
+      }
+    return;
+    }
 
-      case Qt::Key_Return:
-      case Qt::Key_Enter:
-        e->accept();
-
-        text_cursor.setPosition(this->documentEnd());
-        this->setTextCursor(text_cursor);
-
-        if (this->InputEventLoop.isNull())
-          {
-          this->internalExecuteCommand();
-          }
-        else
-          {
-          this->processInput();
-          }
-        break;
+  if (e == QKeySequence::InsertParagraphSeparator)
+    {
+    e->accept();
+    text_cursor.setPosition(this->documentEnd());
+    this->setTextCursor(text_cursor);
+    if (this->InputEventLoop.isNull())
+      {
+      this->internalExecuteCommand();
+      }
+    else
+      {
+      this->processInput();
+      }
+    return;
+    }
 
-      default:
-        e->accept();
-        this->switchToUserInputTextColor();
+  if (e->key() == Qt::Key_Tab)
+    {
+    e->accept();
+    this->updateCompleter();
+    this->selectCompletion();
+    return;
+    }
 
-        this->Superclass::keyPressEvent(e);
-        this->updateCommandBuffer();
-        this->updateCompleterIfVisible();
-        break;
-      }
+  e->accept();
+  this->switchToUserInputTextColor();
+  this->Superclass::keyPressEvent(e);
+  this->updateCommandBuffer();
+  this->updateCompleterIfVisible();
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 0
Libs/Widgets/ctkConsole_p.h

@@ -44,6 +44,8 @@ public:
 
   void init();
 
+  static bool isMoveLeftWithinLine(QKeyEvent* e, QTextCursor::MoveOperation &moveOperation, QTextCursor::MoveMode &moveMode);
+
   virtual void keyPressEvent(QKeyEvent* e);
 
   void switchToUserInputTextColor(QTextCursor* textCursorToUpdate = 0);