From a485f18a9415815ee7a0e2d435bdf08251bb8c4c Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 23 Mar 2023 11:04:54 +0100 Subject: [PATCH] Terminal: Make shortcuts configurable Fixes: QTCREATORBUG-28940 Change-Id: I1afe114c357243a8fa4f101b5eac80a766dc87b9 Reviewed-by: Cristian Adam --- src/plugins/terminal/CMakeLists.txt | 1 + src/plugins/terminal/terminalcommands.cpp | 132 ++++++++++++++++++++++ src/plugins/terminal/terminalcommands.h | 59 ++++++++++ src/plugins/terminal/terminalpane.cpp | 99 +++++++++------- src/plugins/terminal/terminalpane.h | 35 +++--- src/plugins/terminal/terminalwidget.cpp | 102 +++++------------ src/plugins/terminal/terminalwidget.h | 20 +--- 7 files changed, 298 insertions(+), 150 deletions(-) create mode 100644 src/plugins/terminal/terminalcommands.cpp create mode 100644 src/plugins/terminal/terminalcommands.h diff --git a/src/plugins/terminal/CMakeLists.txt b/src/plugins/terminal/CMakeLists.txt index 1250455378a..067cab8d1cd 100644 --- a/src/plugins/terminal/CMakeLists.txt +++ b/src/plugins/terminal/CMakeLists.txt @@ -10,6 +10,7 @@ add_qtc_plugin(Terminal shellintegration.cpp shellintegration.h shellmodel.cpp shellmodel.h terminal.qrc + terminalcommands.cpp terminalcommands.h terminalpane.cpp terminalpane.h terminalplugin.cpp terminalplugin.h terminalprocessimpl.cpp terminalprocessimpl.h diff --git a/src/plugins/terminal/terminalcommands.cpp b/src/plugins/terminal/terminalcommands.cpp new file mode 100644 index 00000000000..9f177720b3e --- /dev/null +++ b/src/plugins/terminal/terminalcommands.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "terminalcommands.h" + +#include +#include + +#include + +//#include + +using namespace Core; +using namespace Utils; + +namespace Terminal { + +constexpr char COPY[] = "Terminal.Copy"; +constexpr char PASTE[] = "Terminal.Paste"; +constexpr char CLEARSELECTION[] = "Terminal.ClearSelection"; + +constexpr char NEWTERMINAL[] = "Terminal.NewTerminal"; +constexpr char CLOSETERMINAL[] = "Terminal.CloseTerminal"; +constexpr char NEXTTERMINAL[] = "Terminal.NextTerminal"; +constexpr char PREVTERMINAL[] = "Terminal.PrevTerminal"; +constexpr char MINMAX[] = "Terminal.MinMax"; + +TerminalCommands &TerminalCommands::instance() +{ + static TerminalCommands instance; + return instance; +} + +TerminalCommands::TerminalCommands() {} + +void TerminalCommands::init(const Core::Context &context) +{ + initWidgetActions(context); + initPaneActions(context); + initGlobalCommands(); +} + +void TerminalCommands::initWidgetActions(const Core::Context &context) +{ + Command *command = ActionManager::instance()->registerAction(&m_widgetActions.copy, + COPY, + context); + command->setDefaultKeySequences( + {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+C") + : QLatin1String("Ctrl+Shift+C")), + QKeySequence(Qt::Key_Return)}); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_widgetActions.paste, PASTE, context); + command->setDefaultKeySequence(QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+V") : QLatin1String("Ctrl+Shift+V"))); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_widgetActions.clearSelection, + CLEARSELECTION); + command->setDefaultKeySequence(QKeySequence("Esc")); + m_commands.push_back(command); +} + +void TerminalCommands::initPaneActions(const Core::Context &context) +{ + Command *command = ActionManager::instance()->registerAction(&m_paneActions.newTerminal, + NEWTERMINAL, + context); + command->setDefaultKeySequence(QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") : QLatin1String("Ctrl+Shift+T"))); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_paneActions.closeTerminal, + CLOSETERMINAL, + context); + command->setDefaultKeySequence(QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+W") : QLatin1String("Ctrl+Shift+W"))); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_paneActions.nextTerminal, + NEXTTERMINAL, + context); + command->setDefaultKeySequences( + {QKeySequence("ALT+TAB"), + QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+[") + : QLatin1String("Ctrl+PgUp"))}); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_paneActions.prevTerminal, + PREVTERMINAL, + context); + command->setDefaultKeySequences( + {QKeySequence("ALT+SHIFT+TAB"), + QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+]") + : QLatin1String("Ctrl+PgDown"))}); + m_commands.push_back(command); + + command = ActionManager::instance()->registerAction(&m_paneActions.minMax, MINMAX, context); + command->setDefaultKeySequence(QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Return") : QLatin1String("Alt+Return"))); + m_commands.push_back(command); +} + +void TerminalCommands::initGlobalCommands() +{ + // Global commands we still want to allow + m_commands.push_back(ActionManager::command(Constants::ZOOM_IN)); + m_commands.push_back(ActionManager::command(Constants::ZOOM_OUT)); + m_commands.push_back(ActionManager::command(Constants::EXIT)); + m_commands.push_back(ActionManager::command(Constants::OPTIONS)); +} + +bool TerminalCommands::triggerAction(QKeyEvent *event) +{ + for (const auto &command : TerminalCommands::instance().m_commands) { + if (!command->action()->isEnabled()) + continue; + + for (const auto &shortcut : command->keySequences()) { + const auto result = shortcut.matches(QKeySequence(event->keyCombination())); + if (result == QKeySequence::ExactMatch) { + command->action()->trigger(); + return true; + } + } + } + + return false; +} + +} // namespace Terminal diff --git a/src/plugins/terminal/terminalcommands.h b/src/plugins/terminal/terminalcommands.h new file mode 100644 index 00000000000..11392f2dcfc --- /dev/null +++ b/src/plugins/terminal/terminalcommands.h @@ -0,0 +1,59 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "terminaltr.h" + +#include +#include + +namespace Core { +class Command; +class Context; +} + +namespace Terminal { + +struct WidgetActions +{ + QAction copy{Tr::tr("Copy")}; + QAction paste{Tr::tr("Paste")}; + QAction clearSelection{Tr::tr("Clear Selection")}; +}; + +struct PaneActions +{ + QAction newTerminal{Tr::tr("New Terminal")}; + QAction closeTerminal{Tr::tr("Close Terminal")}; + QAction nextTerminal{Tr::tr("Next Terminal")}; + QAction prevTerminal{Tr::tr("Previous Terminal")}; + QAction minMax{Tr::tr("Minimize/Maximize Terminal")}; +}; + +class TerminalCommands +{ +public: + TerminalCommands(); + + void init(const Core::Context &context); + static TerminalCommands &instance(); + static WidgetActions &widgetActions() { return instance().m_widgetActions; } + static PaneActions &paneActions() { return instance().m_paneActions; } + + static QList shortcutsFor(QAction *action); + + static bool triggerAction(QKeyEvent *event); + +protected: + void initWidgetActions(const Core::Context &context); + void initPaneActions(const Core::Context &context); + void initGlobalCommands(); + +private: + WidgetActions m_widgetActions; + PaneActions m_paneActions; + QList m_commands; +}; + +} // namespace Terminal diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index c2467ec71d4..cdf14c55e37 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -4,9 +4,9 @@ #include "terminalpane.h" #include "shellmodel.h" +#include "terminalcommands.h" #include "terminaltr.h" #include "terminalwidget.h" -#include "utils/terminalhooks.h" #include #include @@ -16,10 +16,12 @@ #include #include +#include #include #include #include +#include namespace Terminal { @@ -28,19 +30,33 @@ using namespace Utils::Terminal; TerminalPane::TerminalPane(QObject *parent) : Core::IOutputPane(parent) + , m_tabWidget(new QTabWidget) { - Core::Context context("Terminal.Window"); + setupContext("Terminal.Pane", m_tabWidget); + TerminalCommands::instance().init(Core::Context("Terminal.Pane")); - m_newTerminal.setIcon(Icons::PLUS_TOOLBAR.icon()); - m_newTerminal.setToolTip(Tr::tr("Create a new Terminal.")); + connect(this, &IOutputPane::zoomInRequested, this, [this] { + if (currentTerminal()) + currentTerminal()->zoomIn(); + }); + connect(this, &IOutputPane::zoomOutRequested, this, [this] { + if (currentTerminal()) + currentTerminal()->zoomOut(); + }); - connect(&m_newTerminal, &QAction::triggered, this, [this] { openTerminal({}); }); + QAction &newTerminal = TerminalCommands::instance().paneActions().newTerminal; + QAction &closeTerminal = TerminalCommands::instance().paneActions().closeTerminal; - m_closeTerminal.setIcon(Icons::CLOSE_TOOLBAR.icon()); - m_closeTerminal.setToolTip(Tr::tr("Close the current Terminal.")); - m_closeTerminal.setEnabled(false); + newTerminal.setIcon(Icons::PLUS_TOOLBAR.icon()); + newTerminal.setToolTip(Tr::tr("Create a new Terminal.")); - connect(&m_closeTerminal, &QAction::triggered, this, [this] { + connect(&newTerminal, &QAction::triggered, this, [this] { openTerminal({}); }); + + closeTerminal.setIcon(Icons::CLOSE_TOOLBAR.icon()); + closeTerminal.setToolTip(Tr::tr("Close the current Terminal.")); + closeTerminal.setEnabled(false); + + connect(&closeTerminal, &QAction::triggered, this, [this] { removeTab(m_tabWidget->currentIndex()); }); @@ -68,40 +84,40 @@ TerminalPane::TerminalPane(QObject *parent) addItems(shellModel->remote()); }); - m_newTerminal.setMenu(shellMenu); - m_newTerminal.setShortcut(QKeySequence( - HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") : QLatin1String("Ctrl+Shift+T"))); + newTerminal.setMenu(shellMenu); - m_newTerminalButton->setDefaultAction(&m_newTerminal); + m_newTerminalButton->setDefaultAction(&newTerminal); m_closeTerminalButton = new QToolButton(); - m_closeTerminalButton->setDefaultAction(&m_closeTerminal); + m_closeTerminalButton->setDefaultAction(&closeTerminal); - m_nextTerminal.setShortcut(QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+[") - : QLatin1String("Ctrl+PgUp"))); - m_prevTerminal.setShortcut(QKeySequence(HostOsInfo::isMacHost() - ? QLatin1String("Ctrl+Shift+]") - : QLatin1String("Ctrl+PgDown"))); + connect(&TerminalCommands::instance().paneActions().nextTerminal, + &QAction::triggered, + this, + [this] { + if (canNavigate()) + goToNext(); + }); + connect(&TerminalCommands::instance().paneActions().prevTerminal, + &QAction::triggered, + this, + [this] { + if (canPrevious()) + goToPrev(); + }); - connect(&m_nextTerminal, &QAction::triggered, this, [this] { - if (canNavigate()) - goToNext(); - }); - connect(&m_prevTerminal, &QAction::triggered, this, [this] { - if (canPrevious()) - goToPrev(); - }); - - m_minMaxAction.setShortcut(QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Return") - : QLatin1String("Alt+Return"))); - - connect(&m_minMaxAction, &QAction::triggered, this, []() { + connect(&TerminalCommands::instance().paneActions().minMax, &QAction::triggered, this, []() { Core::Command *minMaxCommand = Core::ActionManager::command("Coreplugin.OutputPane.minmax"); if (minMaxCommand) emit minMaxCommand->action()->triggered(); }); } +TerminalPane::~TerminalPane() +{ + delete m_tabWidget; +} + static std::optional startupProjectDirectory() { ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject(); @@ -132,7 +148,7 @@ void TerminalPane::openTerminal(const OpenTerminalParameters ¶meters) m_tabWidget->currentWidget()->setFocus(); - m_closeTerminal.setEnabled(m_tabWidget->count() > 1); + TerminalCommands::instance().paneActions().closeTerminal.setEnabled(m_tabWidget->count() > 1); emit navigateStateUpdate(); } @@ -142,7 +158,7 @@ void TerminalPane::addTerminal(TerminalWidget *terminal, const QString &title) m_tabWidget->setCurrentIndex(m_tabWidget->addTab(terminal, title)); setupTerminalWidget(terminal); - m_closeTerminal.setEnabled(m_tabWidget->count() > 1); + TerminalCommands::instance().paneActions().closeTerminal.setEnabled(m_tabWidget->count() > 1); emit navigateStateUpdate(); } @@ -161,9 +177,8 @@ TerminalWidget *TerminalPane::stoppedTerminalWithId(const Id &identifier) const QWidget *TerminalPane::outputWidget(QWidget *parent) { - if (!m_tabWidget) { - m_tabWidget = new QTabWidget(parent); - + if (!m_widgetInitialized) { + m_widgetInitialized = true; m_tabWidget->setTabBarAutoHide(true); m_tabWidget->setDocumentMode(true); m_tabWidget->setTabsClosable(true); @@ -192,7 +207,7 @@ void TerminalPane::removeTab(int index) if (m_tabWidget->count() > 1) delete m_tabWidget->widget(index); - m_closeTerminal.setEnabled(m_tabWidget->count() > 1); + TerminalCommands::instance().paneActions().closeTerminal.setEnabled(m_tabWidget->count() > 1); emit navigateStateUpdate(); } @@ -229,13 +244,15 @@ void TerminalPane::setupTerminalWidget(TerminalWidget *terminal) if (!terminal->shellName().isEmpty()) setTabText(terminal); - - terminal->addActions({&m_newTerminal, &m_nextTerminal, &m_prevTerminal, &m_minMaxAction}); } QList TerminalPane::toolBarWidgets() const { - return {m_newTerminalButton, m_closeTerminalButton}; + QList widgets = IOutputPane::toolBarWidgets(); + widgets.prepend(m_newTerminalButton); + widgets.prepend(m_closeTerminalButton); + + return widgets; } QString TerminalPane::displayName() const diff --git a/src/plugins/terminal/terminalpane.h b/src/plugins/terminal/terminalpane.h index ac3bed9a96c..fd902f9176a 100644 --- a/src/plugins/terminal/terminalpane.h +++ b/src/plugins/terminal/terminalpane.h @@ -20,21 +20,22 @@ class TerminalPane : public Core::IOutputPane Q_OBJECT public: TerminalPane(QObject *parent = nullptr); + ~TerminalPane() override; - virtual QWidget *outputWidget(QWidget *parent); - virtual QList toolBarWidgets() const; - virtual QString displayName() const; - virtual int priorityInStatusBar() const; - virtual void clearContents(); - virtual void visibilityChanged(bool visible); - virtual void setFocus(); - virtual bool hasFocus() const; - virtual bool canFocus() const; - virtual bool canNavigate() const; - virtual bool canNext() const; - virtual bool canPrevious() const; - virtual void goToNext(); - virtual void goToPrev(); + QWidget *outputWidget(QWidget *parent) override; + QList toolBarWidgets() const override; + QString displayName() const override; + int priorityInStatusBar() const override; + void clearContents() override; + void visibilityChanged(bool visible) override; + void setFocus() override; + bool hasFocus() const override; + bool canFocus() const override; + bool canNavigate() const override; + bool canNext() const override; + bool canPrevious() const override; + void goToNext() override; + void goToPrev() override; void openTerminal(const Utils::Terminal::OpenTerminalParameters ¶meters); void addTerminal(TerminalWidget *terminal, const QString &title); @@ -53,11 +54,7 @@ private: QToolButton *m_newTerminalButton{nullptr}; QToolButton *m_closeTerminalButton{nullptr}; - QAction m_newTerminal; - QAction m_closeTerminal; - QAction m_nextTerminal; - QAction m_prevTerminal; - QAction m_minMaxAction; + bool m_widgetInitialized{false}; }; } // namespace Terminal diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 12d696c69e2..5c099d96f8c 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -3,9 +3,9 @@ #include "terminalwidget.h" #include "glyphcache.h" +#include "terminalcommands.h" #include "terminalsettings.h" #include "terminalsurface.h" -#include "terminaltr.h" #include #include @@ -53,11 +53,6 @@ static constexpr std::chrono::milliseconds minRefreshInterval = 1s / 30; TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) : QAbstractScrollArea(parent) - , m_copyAction(Tr::tr("Copy")) - , m_pasteAction(Tr::tr("Paste")) - , m_clearSelectionAction(Tr::tr("Clear Selection")) - , m_zoomInAction(Tr::tr("Zoom In")) - , m_zoomOutAction(Tr::tr("Zoom Out")) , m_openParameters(openParameters) , m_lastFlush(std::chrono::system_clock::now()) , m_lastDoubleClick(std::chrono::system_clock::now()) @@ -224,27 +219,20 @@ void TerminalWidget::setupColors() void TerminalWidget::setupActions() { - m_copyAction.setEnabled(false); - m_copyAction.setShortcuts( - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+C") - : QLatin1String("Ctrl+Shift+C")), - QKeySequence(Qt::Key_Return)}); - m_pasteAction.setShortcut(QKeySequence( - HostOsInfo::isMacHost() ? QLatin1String("Ctrl+V") : QLatin1String("Ctrl+Shift+V"))); + WidgetActions &a = TerminalCommands::widgetActions(); - m_clearSelectionAction.setShortcut(QKeySequence("Esc")); + auto ifHasFocus = [this](void (TerminalWidget::*f)()) { + return [this, f] { + if (hasFocus()) + (this->*f)(); + }; + }; - m_zoomInAction.setShortcuts({QKeySequence("Ctrl++"), QKeySequence("Ctrl+Shift++")}); - m_zoomOutAction.setShortcut(QKeySequence("Ctrl+-")); - - connect(&m_copyAction, &QAction::triggered, this, &TerminalWidget::copyToClipboard); - connect(&m_pasteAction, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); - connect(&m_clearSelectionAction, &QAction::triggered, this, &TerminalWidget::clearSelection); - connect(&m_zoomInAction, &QAction::triggered, this, &TerminalWidget::zoomIn); - connect(&m_zoomOutAction, &QAction::triggered, this, &TerminalWidget::zoomOut); - - addActions( - {&m_copyAction, &m_pasteAction, &m_clearSelectionAction, &m_zoomInAction, &m_zoomOutAction}); + // clang-format off + connect(&a.copy, &QAction::triggered, this, ifHasFocus(&TerminalWidget::copyToClipboard)); + connect(&a.paste, &QAction::triggered, this, ifHasFocus(&TerminalWidget::pasteFromClipboard)); + connect(&a.clearSelection, &QAction::triggered, this, ifHasFocus(&TerminalWidget::clearSelection)); + // clang-format on } void TerminalWidget::writeToPty(const QByteArray &data) @@ -342,6 +330,14 @@ QColor TerminalWidget::toQColor(std::variant color) const return std::get(color); } +void TerminalWidget::updateCopyState() +{ + if (!hasFocus()) + return; + + TerminalCommands::widgetActions().copy.setEnabled(m_selection.has_value()); +} + void TerminalWidget::setFont(const QFont &font) { m_font = font; @@ -364,33 +360,10 @@ void TerminalWidget::setFont(const QFont &font) } } -QAction &TerminalWidget::copyAction() +void TerminalWidget::copyToClipboard() { - return m_copyAction; -} + QTC_ASSERT(m_selection.has_value(), return); -QAction &TerminalWidget::pasteAction() -{ - return m_pasteAction; -} - -QAction &TerminalWidget::clearSelectionAction() -{ - return m_clearSelectionAction; -} - -QAction &TerminalWidget::zoomInAction() -{ - return m_zoomInAction; -} - -QAction &TerminalWidget::zoomOutAction() -{ - return m_zoomOutAction; -} - -void TerminalWidget::copyToClipboard() const -{ QString text = textFromSelection(); qCDebug(selectionLog) << "Copied to clipboard: " << text; @@ -491,10 +464,10 @@ bool TerminalWidget::setSelection(const std::optional &selection) return false; } - m_copyAction.setEnabled(selection.has_value()); - m_selection = selection; + updateCopyState(); + if (m_selection && m_selection->final) { qCDebug(selectionLog) << "Copy enabled:" << selection.has_value(); @@ -958,25 +931,7 @@ void TerminalWidget::keyPressEvent(QKeyEvent *event) m_cursorBlinkState = true; } - bool actionTriggered = false; - for (const auto &action : actions()) { - if (!action->isEnabled()) - continue; - - for (const auto &shortcut : action->shortcuts()) { - const auto result = shortcut.matches(QKeySequence(event->keyCombination())); - if (result == QKeySequence::ExactMatch) { - action->trigger(); - actionTriggered = true; - break; - } - } - - if (actionTriggered) - break; - } - - if (actionTriggered) { + if (TerminalCommands::triggerAction(event)) { setSelection(std::nullopt); return; } @@ -1067,6 +1022,7 @@ void TerminalWidget::focusInEvent(QFocusEvent *) { updateViewport(); configBlinkTimer(); + updateCopyState(); } void TerminalWidget::focusOutEvent(QFocusEvent *) { @@ -1123,10 +1079,10 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event) updateViewport(); } else if (event->button() == Qt::RightButton) { if (m_selection) { - m_copyAction.trigger(); + copyToClipboard(); setSelection(std::nullopt); } else { - m_pasteAction.trigger(); + pasteFromClipboard(); } } } diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index d7aff0648b8..997abda13dd 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -29,15 +29,7 @@ public: void setFont(const QFont &font); - QAction ©Action(); - QAction &pasteAction(); - - QAction &clearSelectionAction(); - - QAction &zoomInAction(); - QAction &zoomOutAction(); - - void copyToClipboard() const; + void copyToClipboard(); void pasteFromClipboard(); void clearSelection(); @@ -168,6 +160,8 @@ protected: QColor toQColor(std::variant color) const; + void updateCopyState(); + private: std::unique_ptr m_process; std::unique_ptr m_surface; @@ -192,14 +186,6 @@ private: QPoint end; } m_activeMouseSelect; - QAction m_copyAction; - QAction m_pasteAction; - - QAction m_clearSelectionAction; - - QAction m_zoomInAction; - QAction m_zoomOutAction; - QTimer m_flushDelayTimer; QTimer m_scrollTimer;