| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "qg_commandwidget.h" |
| |
|
| | #include <QDockWidget> |
| | #include <QFileDialog> |
| | #include <QKeyEvent> |
| |
|
| | #include "qc_applicationwindow.h" |
| | #include "qg_actionhandler.h" |
| | #include "rs_commands.h" |
| | #include "rs_settings.h" |
| | |
| | |
| | |
| | |
| | QG_CommandWidget::QG_CommandWidget(QG_ActionHandler* action_handler, QWidget* parent, const char* name, |
| | Qt::WindowFlags fl) |
| | : QWidget(parent, fl) |
| | , m_actionHandler(action_handler) { |
| | setObjectName(name); |
| | setupUi(this); |
| | connect(leCommand, &QG_CommandEdit::command, this, &QG_CommandWidget::handleCommand); |
| | connect(leCommand, &QG_CommandEdit::escape, this, &QG_CommandWidget::escape); |
| | connect(leCommand, &QG_CommandEdit::focusOut, this, &QG_CommandWidget::setNormalMode); |
| | connect(leCommand, &QG_CommandEdit::focusIn, this, &QG_CommandWidget::setCommandMode); |
| | connect(leCommand, &QG_CommandEdit::spacePressed, this, &QG_CommandWidget::spacePressed); |
| | connect(leCommand, &QG_CommandEdit::tabPressed, this, &QG_CommandWidget::tabPressed); |
| | connect(leCommand, &QG_CommandEdit::clearCommandsHistory, teHistory, &QG_CommandHistory::clear); |
| | connect(leCommand, &QG_CommandEdit::message, this, &QG_CommandWidget::appendHistory); |
| | connect(leCommand, &QG_CommandEdit::keycode, this, &QG_CommandWidget::handleKeycode); |
| |
|
| | auto a1 = new QAction(QObject::tr("Keycode mode"), this); |
| | a1->setObjectName("keycode_action"); |
| | a1->setCheckable(true); |
| | connect(a1, &QAction::toggled, this, &QG_CommandWidget::setKeycodeMode); |
| | options_button->addAction(a1); |
| |
|
| | if (LC_GET_ONE_BOOL("Widgets", "KeycodeMode", false)) { |
| | leCommand->m_keycode_mode = true; |
| | a1->setChecked(true); |
| | } |
| |
|
| | auto a2 = new QAction(QObject::tr("Load command file"), this); |
| | connect(a2, &QAction::triggered, this, &QG_CommandWidget::chooseCommandFile); |
| | options_button->addAction(a2); |
| |
|
| | auto a3 = new QAction(QObject::tr("Paste multiple commands"), this); |
| | connect(a3, &QAction::triggered, leCommand, &QG_CommandEdit::modifiedPaste); |
| | options_button->addAction(a3); |
| |
|
| | options_button->setStyleSheet("QToolButton::menu-indicator { image: none; }"); |
| |
|
| | |
| | |
| | |
| | m_docking = new QAction(tr("Dock"), this); |
| | addAction(m_docking); |
| | connect(m_docking, &QAction::triggered, this, &QG_CommandWidget::dockingButtonTriggered); |
| |
|
| | options_button->addAction(m_docking); |
| | } |
| |
|
| | |
| | |
| | |
| | QG_CommandWidget::~QG_CommandWidget() { |
| | auto action = findChild<QAction*>("keycode_action"); |
| | LC_SET_ONE("Widgets", "KeycodeMode", action->isChecked()); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void QG_CommandWidget::languageChange() { |
| | retranslateUi(this); |
| | } |
| |
|
| | bool QG_CommandWidget::eventFilter(QObject*, QEvent* event) { |
| | if (event != nullptr && event->type() == QEvent::KeyPress) { |
| | auto e = static_cast<QKeyEvent*>(event); |
| |
|
| | int key{e->key()}; |
| | switch (key) { |
| | case Qt::Key_Return: |
| | case Qt::Key_Enter: |
| | if (!leCommand->text().size()) |
| | return false; |
| | else |
| | break; |
| | case Qt::Key_Escape: |
| | return false; |
| | case Qt::Key_Space: |
| | if (!hasFocus() && LC_GET_BOOL("Keyboard/ToggleFreeSnapOnSpace", false)) { |
| | |
| | spacePressed(); |
| | e->accept(); |
| | return true; |
| | } |
| | break; |
| | default: |
| | break; |
| | } |
| |
|
| | |
| | |
| | Qt::KeyboardModifiers modifiers{e->modifiers()}; |
| | if (!(Qt::GroupSwitchModifier == modifiers && Qt::Key_At == key) |
| | && modifiers != Qt::KeypadModifier && modifiers & (Qt::KeyboardModifierMask ^ Qt::ShiftModifier) & (Qt::KeyboardModifierMask ^ Qt::ControlModifier)) { |
| | return false; |
| | } |
| | bool isGraphicViewEvent = (key != Qt::Key_Shift) && |
| | (key != Qt::Key_Control) && |
| | (key != Qt::Key_Up) && |
| | (key != Qt::Key_Left) && |
| | (key != Qt::Key_Right) && |
| | (key != Qt::Key_Down) && |
| | (key != Qt::Key_Plus) && |
| | (key != Qt::Key_Minus); |
| | |
| | if (isGraphicViewEvent) { |
| | setFocus(); |
| | QApplication::postEvent(leCommand, e->clone()); |
| | e->accept(); |
| | return true; |
| | } |
| | else { |
| | auto eventClone = e->clone(); |
| | QApplication::postEvent(QC_ApplicationWindow::getAppWindow().get(), eventClone); |
| | if (!eventClone->isAccepted()) { |
| | QApplication::postEvent(leCommand, e->clone()); |
| | } |
| | e->accept(); |
| | return true; |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | void QG_CommandWidget::setFocus() { |
| | if (!isActiveWindow()) |
| | activateWindow(); |
| |
|
| | auto newEvent = new QFocusEvent(QEvent::FocusIn); |
| | QApplication::postEvent(leCommand, newEvent); |
| | leCommand->setFocus(); |
| | } |
| |
|
| | void QG_CommandWidget::setCommand(const QString& cmd) { |
| | if (cmd.isEmpty()) { |
| | lCommand->setText(tr("Enter Command:")); |
| | } |
| | else { |
| | if (!cmd.endsWith(":")) { |
| | lCommand->setText(cmd + ":"); |
| | } |
| | else { |
| | lCommand->setText(cmd); |
| | } |
| | } |
| | } |
| |
|
| | void QG_CommandWidget::setInput(const QString& cmd) { |
| | leCommand->setText(cmd); |
| | leCommand->setFocus(); |
| | } |
| |
|
| | void QG_CommandWidget::appendHistory(const QString& msg) { |
| | teHistory->append(msg); |
| | } |
| |
|
| | void QG_CommandWidget::handleCommand(QString cmd) { |
| | cmd = cmd.simplified(); |
| | bool isAction = false; |
| | if (!cmd.isEmpty()) { |
| | appendHistory(cmd); |
| | } |
| |
|
| | if (m_actionHandler) { |
| | isAction = m_actionHandler->command(cmd); |
| | } |
| |
|
| | if (!isAction && !(cmd.contains(',') || cmd.at(0) == '@')) { |
| | appendHistory(tr("Unknown command: %1").arg(cmd)); |
| | } |
| |
|
| | leCommand->setText(""); |
| | } |
| |
|
| | void QG_CommandWidget::spacePressed() { |
| | if (m_actionHandler) |
| | m_actionHandler->command({}); |
| | } |
| |
|
| | |
| | |
| |
|
| | void QG_CommandWidget::tabPressed() { |
| | if (m_actionHandler) { |
| | QString typed = leCommand->text(); |
| |
|
| | |
| | QStringList choices = m_actionHandler->getAvailableCommands(); |
| | if (choices.empty()) { |
| | choices = RS_COMMANDS->complete(typed); |
| | } |
| |
|
| | QStringList reducedChoices; |
| | std::copy_if(choices.cbegin(), choices.cend(), std::back_inserter(reducedChoices), |
| | [&typed](const QString& cmd) { |
| | return typed.isEmpty() || cmd.startsWith(typed, Qt::CaseInsensitive); |
| | }); |
| |
|
| | |
| | if (reducedChoices.count() == 1) { |
| | leCommand->setText(reducedChoices.first()); |
| | } |
| | else if (!reducedChoices.isEmpty()) { |
| | const QString proposal = getRootCommand(reducedChoices, typed); |
| | appendHistory(reducedChoices.join(", ")); |
| | const QString aliasFile = RS_Commands::getAliasFile(); |
| | if (!aliasFile.isEmpty()) |
| | appendHistory(tr("Command Alias File: %1").arg(aliasFile)); |
| | leCommand->setText(proposal); |
| | } |
| | } |
| | } |
| |
|
| | void QG_CommandWidget::escape() { |
| | |
| | if (m_actionHandler) { |
| | m_actionHandler->command(QString(tr("escape", "escape, go back from action steps"))); |
| | } |
| | } |
| |
|
| | void QG_CommandWidget::setActionHandler(QG_ActionHandler* ah) { |
| | m_actionHandler = ah; |
| | } |
| |
|
| | void QG_CommandWidget::setCommandMode() { |
| | QPalette palette; |
| | palette.setColor(lCommand->foregroundRole(), Qt::blue); |
| | lCommand->setPalette(palette); |
| | } |
| |
|
| | void QG_CommandWidget::setNormalMode() { |
| | QPalette palette; |
| | palette.setColor(lCommand->foregroundRole(), Qt::black); |
| | lCommand->setPalette(palette); |
| | } |
| |
|
| | QString QG_CommandWidget::getRootCommand(const QStringList& cmdList, const QString& typed) { |
| | |
| | if (cmdList.empty()) |
| | return QString(); |
| |
|
| | |
| | auto const& shortestString = *std::min_element(cmdList.begin(), cmdList.end(), |
| | [](QString const& a, QString const& b) -> bool { |
| | return a.size() < b.size(); |
| | } |
| | ); |
| | int const lengthShortestString = shortestString.size(); |
| |
|
| | |
| | int low = typed.length(); |
| | int high = lengthShortestString + 1; |
| |
|
| | while (high > low + 1) { |
| | int mid = (high + low) / 2; |
| | bool common = true; |
| |
|
| | QString const& proposal = shortestString.left(mid); |
| | for (auto const& substring : cmdList) { |
| | if (!substring.startsWith(proposal)) { |
| | common = false; |
| | break; |
| | } |
| | } |
| | if (common) { |
| | low = mid; |
| | } |
| | else { |
| | high = mid; |
| | } |
| | } |
| |
|
| | |
| | |
| | return shortestString.left(low); |
| | } |
| |
|
| | void QG_CommandWidget::chooseCommandFile() { |
| | QString path = QFileDialog::getOpenFileName(this); |
| | if (!path.isEmpty()) { |
| | leCommand->readCommandFile(path); |
| | } |
| | } |
| |
|
| | void QG_CommandWidget::handleKeycode(QString code) { |
| | if (m_actionHandler->keycode(code)) { |
| | leCommand->clear(); |
| | } |
| | } |
| |
|
| | void QG_CommandWidget::setKeycodeMode(bool state) { |
| | leCommand->m_keycode_mode = state; |
| | } |
| |
|
| | void QG_CommandWidget::dockingButtonTriggered(bool ) { |
| | auto* cmd_dockwidget = QC_ApplicationWindow::getAppWindow()->findChild<QDockWidget*>("command_dockwidget"); |
| | cmd_dockwidget->setFloating(!cmd_dockwidget->isFloating()); |
| | m_docking->setText(cmd_dockwidget->isFloating() ? tr("Dock") : tr("Float")); |
| | setWindowTitle(cmd_dockwidget->isFloating() ? tr("Command Line") : tr("Cmd")); |
| | } |
| |
|