Unregister shortcuts when closing windows that registered shortcuts

* This prevents leaking for cases where new widgets are created (and
  the small chance a widget pointer could be re-used and cause serious
  problems), and multiple-registration errors for global shortcuts.
This commit is contained in:
baldurk
2017-11-22 16:07:14 +00:00
parent cadc0f3855
commit 38acc56084
5 changed files with 68 additions and 1 deletions
+13 -1
View File
@@ -125,11 +125,23 @@ will be invoked, if it exists.
:param QWidget widget: A handle to the widget to use as the context for this shortcut, or ``None``
for a global shortcut. Note that if an existing global shortcut exists the new one will not be
registered.
:rtype: ``str``
)");
virtual void RegisterShortcut(const QString &shortcut, QWidget *widget,
ShortcutCallback callback) = 0;
DOCUMENT(R"(Unregister a callback for a particular key shortcut, made in a previous call to
:meth:`RegisterShortcut`.
See the documentation for :meth:`RegisterShortcut` for what these shortcuts are for.
:param str shortcut: The text string representing the shortcut, e.g. 'Ctrl+S'. To unregister all
shortcuts for a particular widget, you can pass an empty string here. In this case,
:param:`widget` must not be ``None``.
:param QWidget widget: A handle to the widget used as the context for the shortcut, or ``None``
if referring to a global shortcut.
)");
virtual void UnregisterShortcut(const QString &shortcut, QWidget *widget) = 0;
protected:
IMainWindow() = default;
~IMainWindow() = default;
+20
View File
@@ -165,6 +165,26 @@ EventBrowser::EventBrowser(ICaptureContext &ctx, QWidget *parent)
EventBrowser::~EventBrowser()
{
// unregister any shortcuts we registered
Qt::Key keys[] = {
Qt::Key_1, Qt::Key_2, Qt::Key_3, Qt::Key_4, Qt::Key_5,
Qt::Key_6, Qt::Key_7, Qt::Key_8, Qt::Key_9, Qt::Key_0,
};
for(int i = 0; i < 10; i++)
{
m_Ctx.GetMainWindow()->UnregisterShortcut(
QKeySequence(keys[i] | Qt::ControlModifier).toString(), NULL);
}
m_Ctx.GetMainWindow()->UnregisterShortcut(
QKeySequence(Qt::Key_Left | Qt::ControlModifier).toString(), NULL);
m_Ctx.GetMainWindow()->UnregisterShortcut(
QKeySequence(Qt::Key_Right | Qt::ControlModifier).toString(), NULL);
m_Ctx.GetMainWindow()->UnregisterShortcut(QString(), ui->findStrip);
m_Ctx.GetMainWindow()->UnregisterShortcut(QString(), ui->jumpStrip);
m_Ctx.BuiltinWindowClosed(this);
m_Ctx.RemoveCaptureViewer(this);
delete ui;
+31
View File
@@ -249,6 +249,12 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
MainWindow::~MainWindow()
{
// explicitly delete our children here, so that the MainWindow is still alive while they are
// closing.
setUpdatesEnabled(false);
qDeleteAll(findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly));
m_RemoteProbeSemaphore.acquire();
m_RemoteProbe->wait();
m_RemoteProbe->deleteLater();
@@ -1376,6 +1382,31 @@ void MainWindow::RegisterShortcut(const QString &shortcut, QWidget *widget, Shor
}
}
void MainWindow::UnregisterShortcut(const QString &shortcut, QWidget *widget)
{
if(widget)
{
if(shortcut.isEmpty())
{
// if no shortcut is specified, remove all shortcuts for this widget
for(QMap<QWidget *, ShortcutCallback> &sh : m_WidgetShortcutCallbacks)
sh.remove(widget);
}
else
{
QKeySequence ks = QKeySequence::fromString(shortcut);
m_WidgetShortcutCallbacks[ks].remove(widget);
}
}
else
{
QKeySequence ks = QKeySequence::fromString(shortcut);
m_GlobalShortcutCallbacks.remove(ks);
}
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if(event->type() == QEvent::ShortcutOverride)
+1
View File
@@ -53,6 +53,7 @@ public:
// IMainWindow
QWidget *Widget() override { return this; }
void RegisterShortcut(const QString &shortcut, QWidget *widget, ShortcutCallback callback) override;
void UnregisterShortcut(const QString &shortcut, QWidget *widget) override;
// ICaptureViewer
void OnCaptureLoaded() override;
void OnCaptureClosed() override;
+3
View File
@@ -585,6 +585,9 @@ ShaderViewer::~ShaderViewer()
// don't want to async invoke while using 'this', so save the trace separately
ShaderDebugTrace *trace = m_Trace;
// unregister any shortcuts on this window
m_Ctx.GetMainWindow()->UnregisterShortcut(QString(), this);
m_Ctx.Replay().AsyncInvoke([trace](IReplayController *r) { r->FreeTrace(trace); });
if(m_CloseCallback)