// This function overrides the QWidget::event() and should return true if the // event was recognized, otherwise it should return false. If the recognized // event was accepted (see QEvent::accepted), any further processing such as // event propagation to the parent widget stops. bool TCommandLine::event(QEvent* event) { const Qt::KeyboardModifiers allModifiers = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier | Qt::GroupSwitchModifier; if (event->type() == QEvent::KeyPress) { auto * ke = dynamic_cast<QKeyEvent*>(event); // Shortcut for keypad keys if ((ke->modifiers() & Qt::KeypadModifier) && mpKeyUnit->processDataStream(ke->key(), (int)ke->modifiers())) { ke->accept(); return true; } switch (ke->key()) { case Qt::Key_Space: if ((ke->modifiers() & (allModifiers & ~(Qt::ShiftModifier))) == Qt::NoModifier) { // Ignore the <SHIFT> modifier only - keeps some users happy! mTabCompletionCount = -1; mAutoCompletionCount = -1; mTabCompletionTyped.clear(); mAutoCompletionTyped.clear(); if (mpHost->mAutoClearCommandLineAfterSend) { mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } mLastCompletion.clear(); break; } else { // Process as a possible key binding if there are ANY modifiers // other than just a <SHIFT> one; may actaully be configured as // a non-breaking space when used with a modifier! return processPotentialKeyBinding(ke); } case Qt::Key_Backtab: // <BACKTAB> is usually internally generated by SHIFT used in // conjunction with TAB - so ignore just the SHIFT key: if ((ke->modifiers() & (allModifiers & ~(Qt::ShiftModifier))) == Qt::ControlModifier) { // Switch to PREVIOUS profile tab when used with <CTRL> (and // implicit <SHIFT>): int currentIndex = mudlet::self()->mpTabBar->currentIndex(); int count = mudlet::self()->mpTabBar->count(); if (currentIndex - 1 < 0) { mudlet::self()->mpTabBar->setCurrentIndex(count - 1); } else { mudlet::self()->mpTabBar->setCurrentIndex(currentIndex - 1); } ke->accept(); return true; } else if ((ke->modifiers() & (allModifiers & ~(Qt::ShiftModifier))) == Qt::NoModifier) { // Process as plain <BACKTAB> - (ignoring implicit <SHIFT>) handleTabCompletion(false); adjustHeight(); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers // other than just the ignored <SHIFT> and the possible <CTRL>: return processPotentialKeyBinding(ke); } case Qt::Key_Tab: if ((ke->modifiers() & allModifiers) == Qt::ControlModifier) { // Switch to NEXT profile tab int currentIndex = mudlet::self()->mpTabBar->currentIndex(); int count = mudlet::self()->mpTabBar->count(); if (currentIndex + 1 < count) { mudlet::self()->mpTabBar->setCurrentIndex(currentIndex + 1); } else { mudlet::self()->mpTabBar->setCurrentIndex(0); } ke->accept(); return true; } else if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { handleTabCompletion(true); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers // other than just the Ctrl one // CHECKME: What about system foreground application switching? return processPotentialKeyBinding(ke); } case Qt::Key_unknown: qWarning() << "ERROR: key unknown!"; break; case Qt::Key_Backspace: if ((ke->modifiers() & (allModifiers & ~(Qt::ControlModifier|Qt::ShiftModifier))) == Qt::NoModifier) { // Ignore state of <CTRL> and <SHIFT> keys if (mpHost->mAutoClearCommandLineAfterSend) { mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } if (mTabCompletionTyped.size() >= 1) { mTabCompletionTyped.chop(1); mAutoCompletionTyped.chop(1); } mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion.clear(); QPlainTextEdit::event(event); adjustHeight(); return true; } else { // Process as a possible key binding if there are ANY modifiers // other than <CTRL> and/or <SHIFT> return processPotentialKeyBinding(ke); } case Qt::Key_Delete: if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { if (mpHost->mAutoClearCommandLineAfterSend) { mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } if (mTabCompletionTyped.size() >= 1) { mTabCompletionTyped.chop(1); mAutoCompletionTyped.chop(1); } else { mTabCompletionTyped.clear(); mAutoCompletionTyped.clear(); mUserKeptOnTyping = false; } mAutoCompletionCount = -1; mTabCompletionCount = -1; mLastCompletion.clear(); QPlainTextEdit::event(event); adjustHeight(); return true; } else { // Process as a possible key binding if there are ANY modifiers return processPotentialKeyBinding(ke); } case Qt::Key_Return: // This is the main one (not the keypad) if ((ke->modifiers() & allModifiers) == Qt::ControlModifier) { // If Ctrl-Return is pressed - scroll to the bottom of text: mpConsole->mLowerPane->mCursorY = mpConsole->buffer.size(); mpConsole->mLowerPane->hide(); mpConsole->buffer.mCursorY = mpConsole->buffer.size(); mpConsole->mUpperPane->mCursorY = mpConsole->buffer.size(); mpConsole->mUpperPane->mIsTailMode = true; mpConsole->mUpperPane->updateScreenView(); mpConsole->mUpperPane->forceUpdate(); ke->accept(); return true; } else if ((ke->modifiers() & allModifiers) == Qt::ShiftModifier) { textCursor().insertBlock(); ke->accept(); return true; } else if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { // Do the normal return key stuff only if NO modifiers are used: enterCommand(ke); mAutoCompletionCount = -1; mAutoCompletionTyped.clear(); mLastCompletion.clear(); mTabCompletionTyped.clear(); mUserKeptOnTyping = false; mTabCompletionCount = -1; if (mpHost->mAutoClearCommandLineAfterSend) { clear(); mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } adjustHeight(); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, // other than just the Shift or just the Control modifiers return processPotentialKeyBinding(ke); } case Qt::Key_Enter: // This is usually the Keypad one, so may come with // the keypad modifier - but if so it may never be reached because // of the keypad modifier interception done before this switch... if ((ke->modifiers() & (allModifiers & ~(Qt::KeypadModifier))) == Qt::NoModifier) { // Do the "normal" return key action if no or just the keypad // modifier is present: enterCommand(ke); mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion.clear(); mTabCompletionTyped.clear(); mAutoCompletionTyped.clear(); mUserKeptOnTyping = false; if (mpHost->mAutoClearCommandLineAfterSend) { clear(); mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } adjustHeight(); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, // other than just the Keypad modifier return processPotentialKeyBinding(ke); } case Qt::Key_Down: #if defined(Q_OS_MACOS) if ((ke->modifiers() & allModifiers) == (Qt::ControlModifier|Qt::KeypadModifier)) { #else if ((ke->modifiers() & allModifiers) == Qt::ControlModifier) { #endif // If EXACTLY <Ctrl>-Down is pressed (special case for macOs - // also sets KeyPad modifier) moveCursor(QTextCursor::Down, QTextCursor::MoveAnchor); ke->accept(); return true; #if defined(Q_OS_MACOS) } else if ((ke->modifiers() & allModifiers) == Qt::KeypadModifier) { #else } else if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { #endif // If EXACTLY Down is pressed without modifiers (special case // for macOs - also sets KeyPad modifier) historyDown(ke); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, // other than just the Control modifier (or keypad modifier on // macOs) return processPotentialKeyBinding(ke); } case Qt::Key_Up: #if defined(Q_OS_MACOS) if ((ke->modifiers() & allModifiers) == (Qt::ControlModifier|Qt::KeypadModifier)) { #else if ((ke->modifiers() & allModifiers) == Qt::ControlModifier) { #endif // If EXACTLY <Ctrl>-Up is pressed (special case for macOs - // also sets KeyPad modifier) moveCursor(QTextCursor::Up, QTextCursor::MoveAnchor); ke->accept(); return true; #if defined(Q_OS_MACOS) } else if ((ke->modifiers() & allModifiers) == Qt::KeypadModifier) { #else } else if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { #endif // If EXACTLY Up is pressed without modifiers (special case for // macOs - also sets KeyPad modifier) historyUp(ke); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, // other than just the Control modifier (or keypad modifier on // macOs) return processPotentialKeyBinding(ke); } case Qt::Key_Escape: if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { // Escape from tab completion mode if used with NO modifiers selectAll(); mAutoCompletion = false; mTabCompletion = false; mTabCompletionTyped.clear(); mAutoCompletionTyped.clear(); mUserKeptOnTyping = false; mTabCompletionCount = -1; mAutoCompletionCount = -1; setPalette(mRegularPalette); if (mpHost->mAutoClearCommandLineAfterSend) { mHistoryBuffer = -1; } else { mHistoryBuffer = 0; } ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, return processPotentialKeyBinding(ke); } case Qt::Key_PageUp: if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { mpConsole->scrollUp(mpHost->mScreenHeight); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, return processPotentialKeyBinding(ke); } case Qt::Key_PageDown: if ((ke->modifiers() & allModifiers) == Qt::NoModifier) { mpConsole->scrollDown(mpHost->mScreenHeight); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, return processPotentialKeyBinding(ke); } case Qt::Key_C: if (((ke->modifiers() & allModifiers) == Qt::ControlModifier) && (mpConsole->mUpperPane->mSelectedRegion != QRegion(0, 0, 0, 0))) { // Only process as a Control-C if it is EXACTLY those two keys // and no other AND there is a selection active in the TConsole mpConsole->mUpperPane->slot_copySelectionToClipboard(); ke->accept(); return true; } else { // Process as a possible key binding if there are ANY modifiers, if (processPotentialKeyBinding(ke)) { return true; } else { processNormalKey(event); return false; } } default: // Process as a possible key binding if there are ANY modifiers, if (processPotentialKeyBinding(ke)) { return true; } else { processNormalKey(event); return false; } } } return QPlainTextEdit::event(event); } void TCommandLine::focusInEvent(QFocusEvent* event) { textCursor().movePosition(QTextCursor::Start); textCursor().movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, mSelectedText.length()); mpConsole->mUpperPane->forceUpdate(); mpConsole->mLowerPane->forceUpdate(); QPlainTextEdit::focusInEvent(event); }
bool TCommandLine::event( QEvent * event ) { if( event->type() == QEvent::KeyPress ) { QKeyEvent *ke = static_cast<QKeyEvent *>( event ); //qDebug()<<"modifier="<<ke->modifiers()<<" key="<<ke->key(); switch( ke->key() ) { case Qt::Key_Space: mTabCompletionCount = -1; mAutoCompletionCount = -1; mTabCompletionTyped = ""; mAutoCompletionTyped = ""; if( mpHost->mAutoClearCommandLineAfterSend ) mHistoryBuffer = -1; else mHistoryBuffer = 0; mLastCompletion = ""; break; case Qt::Key_Backtab: handleTabCompletion( false ); ke->accept(); adjustHeight(); return true; break; case Qt::Key_Tab: handleTabCompletion( true ); ke->accept(); return true; break; case Qt::Key_unknown: qWarning()<<"ERROR: key unknown!"; break; case Qt::Key_Backspace: if( mpHost->mAutoClearCommandLineAfterSend ) mHistoryBuffer = -1; else mHistoryBuffer = 0; if( mTabCompletionTyped.size() >= 1 ) { mTabCompletionTyped.chop(1); mAutoCompletionTyped.chop(1); mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; } else { mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; } QPlainTextEdit::event(event); adjustHeight(); return true; case Qt::Key_Delete: if( mpHost->mAutoClearCommandLineAfterSend ) mHistoryBuffer = -1; else mHistoryBuffer = 0; if( mTabCompletionTyped.size() >= 1 ) { mTabCompletionTyped.chop(1); mAutoCompletionTyped.chop(1); mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; } else { mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; mTabCompletionTyped = ""; mAutoCompletionTyped = ""; mUserKeptOnTyping = false; mTabCompletionCount = -1; mAutoCompletionCount = -1; } QPlainTextEdit::event(event); adjustHeight(); return true; break; case Qt::Key_Return: if( ke->modifiers() & Qt::ControlModifier ) { mpConsole->console2->mCursorY = mpConsole->buffer.size();// mpConsole->console2->hide(); mpConsole->buffer.mCursorY = mpConsole->buffer.size(); mpConsole->console->mCursorY = mpConsole->buffer.size();// mpConsole->console->mIsTailMode = true; mpConsole->console->updateScreenView(); mpConsole->console->forceUpdate(); ke->accept(); return true; } else if( ke->modifiers() & Qt::ShiftModifier ) { textCursor().insertBlock(); /*if( ! textCursor().movePosition(QTextCursor::Down, QTextCursor::KeepAnchor) ) { textCursor().insertBlock(); }*/ ke->accept(); return true; } else { enterCommand(ke); mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; mTabCompletionTyped = ""; mAutoCompletionTyped = ""; mUserKeptOnTyping = false; mTabCompletionCount = -1; mAutoCompletionCount = -1; if( mpHost->mAutoClearCommandLineAfterSend ) { clear(); mHistoryBuffer = -1; } else mHistoryBuffer = 0; adjustHeight(); ke->accept(); return true; } break; case Qt::Key_Enter: enterCommand(ke); mTabCompletionCount = -1; mAutoCompletionCount = -1; mLastCompletion = ""; mTabCompletionTyped = ""; mAutoCompletionTyped = ""; mUserKeptOnTyping = false; mTabCompletionCount = -1; mAutoCompletionCount = -1; if( mpHost->mAutoClearCommandLineAfterSend ) { clear(); mHistoryBuffer = -1; } else mHistoryBuffer = 0; adjustHeight(); ke->accept(); return true; break; case Qt::Key_Down: if( ke->modifiers() & Qt::ControlModifier ) { moveCursor(QTextCursor::Down, QTextCursor::MoveAnchor); ke->accept(); return true; } else { historyDown(ke); ke->accept(); return true; } break; case Qt::Key_Up: if( ke->modifiers() & Qt::ControlModifier ) { moveCursor(QTextCursor::Up, QTextCursor::MoveAnchor ); ke->accept(); return true; } else { historyUp(ke); ke->accept(); return true; } break; case Qt::Key_Escape: selectAll(); mAutoCompletion = false; mTabCompletion = false; mTabCompletionTyped = ""; mAutoCompletionTyped = ""; mUserKeptOnTyping = false; mTabCompletionCount = -1; mAutoCompletionCount = -1; setPalette( mRegularPalette ); if( mpHost->mAutoClearCommandLineAfterSend ) mHistoryBuffer = -1; else mHistoryBuffer = 0; ke->accept(); return true; break; case Qt::Key_PageUp: mpConsole->scrollUp( mpHost->mScreenHeight ); ke->accept(); return true; break; case Qt::Key_PageDown: mpConsole->scrollDown( mpHost->mScreenHeight ); ke->accept(); return true; break; case Qt::Key_C: if( ke->modifiers() & Qt::ControlModifier ) { if( mpConsole->console->mSelectedRegion != QRegion( 0, 0, 0, 0 ) ) { mpConsole->console->copySelectionToClipboard(); ke->accept(); return true; } } break; default: if( mpKeyUnit->processDataStream( ke->key(), (int)ke->modifiers() ) ) { ke->accept(); return true; } else { QPlainTextEdit::event( event ); adjustHeight(); if( mpHost->mAutoClearCommandLineAfterSend ) mHistoryBuffer = -1; else mHistoryBuffer = 0; if( mTabCompletionOld != toPlainText() )//text() ) { mUserKeptOnTyping = true; mAutoCompletionCount = -1; } else { mUserKeptOnTyping = false; } spellCheck(); return false; } } } return QPlainTextEdit::event( event ); }