Commit a2f42037 authored by hjk's avatar hjk
Browse files

Debugger: Tooltip timing workarounds.



There's some bad interaction between the delayed hide,
the deleteLater() from CloseOnDelete, and the async
evaluation. Work around by start from scratch for each
tooltip. On the downside we have more flicker.

Change-Id: I4801368c07895b652e10fe1d173b21cef7869ed0
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 1101e556
......@@ -71,6 +71,12 @@ void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w, con
instance()->showInternal(pos, content, w, rect);
}
void ToolTip::move(const QPoint &pos, QWidget *w)
{
if (isVisible())
instance()->placeTip(pos, w);
}
void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w)
{
show(pos, content, w, QRect());
......
......@@ -73,6 +73,7 @@ public:
static void show(const QPoint &pos, const TipContent &content, QWidget *w = 0);
static void show(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect);
static void move(const QPoint &pos, QWidget *w);
static void hide();
static bool isVisible();
......
......@@ -709,14 +709,21 @@ public:
//
/////////////////////////////////////////////////////////////////////////
enum DebuggerTootipState
{
New, // All new, widget not shown, not async (yet)
PendingUnshown, // Widget not (yet) shown, async.
PendingShown, // Widget shown, async
Acquired, // Widget shown, engine attached
Released // Widget shown, engine released
};
class DebuggerToolTipHolder : public QObject
{
public:
DebuggerToolTipHolder(const DebuggerToolTipContext &context);
~DebuggerToolTipHolder();
enum State { New, Pending, Acquired, Released };
void acquireEngine();
void releaseEngine();
......@@ -728,7 +735,8 @@ public:
void handleItemIsExpanded(const QModelIndex &sourceIdx);
void updateTooltip(const StackFrame &frame);
void setState(State newState);
void setState(DebuggerTootipState newState);
void destroy();
public:
QPointer<DebuggerToolTipWidget> widget;
......@@ -738,8 +746,7 @@ public:
TooltipFilterModel filterModel; //!< Pointing to a valid watchModel
QStandardItemModel defaultModel;
State state;
bool showNeeded;
DebuggerTootipState state;
};
static void hideAllToolTips()
......@@ -851,7 +858,6 @@ DebuggerToolTipHolder::DebuggerToolTipHolder(const DebuggerToolTipContext &conte
context.creationDate = QDate::currentDate();
state = New;
showNeeded = true;
filterModel.m_iname = context.iname;
......@@ -871,6 +877,14 @@ DebuggerToolTipHolder::~DebuggerToolTipHolder()
delete widget; widget.clear();
}
// This is called back from the engines after they populated the
// WatchModel. If the populating result from evaluation of this
// tooltip here, we are in "PendingUnshown" state (no Widget show yet),
// or "PendingShown" state (old widget reused).
//
// If we are in "Acquired" or "Released", this is an update
// after normal WatchModel update.
void DebuggerToolTipHolder::updateTooltip(const StackFrame &frame)
{
const bool sameFrame = context.matchesFrame(frame);
......@@ -879,21 +893,21 @@ void DebuggerToolTipHolder::updateTooltip(const StackFrame &frame)
<< "SHOW NEEDED: " << widget->isPinned
<< "SAME FRAME: " << sameFrame);
if (state == Pending) {
if (state == PendingUnshown) {
const Utils::WidgetContent widgetContent(widget, true);
Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow());
setState(PendingShown);
}
if (state == PendingShown) {
acquireEngine();
Utils::ToolTip::move(context.mousePosition, Internal::mainWindow());
} else if (state == Acquired && !sameFrame) {
releaseEngine();
} else if (state == Released && sameFrame) {
acquireEngine();
}
if (showNeeded) {
showNeeded = false;
DEBUG("INITIAL SHOW");
const Utils::WidgetContent widgetContent(widget, true);
Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow());
}
if (state == Acquired) {
// Save data to stream and restore to the backup m_defaultModel.
// Doing it on releaseEngine() is too later.
......@@ -906,17 +920,18 @@ void DebuggerToolTipHolder::updateTooltip(const StackFrame &frame)
}
}
void DebuggerToolTipHolder::setState(DebuggerToolTipHolder::State newState)
void DebuggerToolTipHolder::setState(DebuggerTootipState newState)
{
bool ok = (state == New && newState == Pending)
|| (state == Pending && (newState == Acquired || newState == Released))
bool ok = (state == New && newState == PendingUnshown)
|| (state == PendingUnshown && newState == PendingShown)
|| (state == PendingShown && newState == Acquired)
|| (state == Acquired && (newState == Released))
|| (state == Released && (newState == Acquired));
// FIXME: These happen when a tooltip is re-used in findOrCreate.
ok = ok
|| (state == Acquired && newState == Pending)
|| (state == Released && newState == Pending);
|| (state == Acquired && newState == PendingShown)
|| (state == Released && newState == PendingShown);
DEBUG("TRANSITION STATE FROM " << state << " TO " << newState);
QTC_ASSERT(ok, qDebug() << "Unexpected tooltip state transition from "
......@@ -925,6 +940,14 @@ void DebuggerToolTipHolder::setState(DebuggerToolTipHolder::State newState)
state = newState;
}
void DebuggerToolTipHolder::destroy()
{
if (widget) {
widget->close();
widget = 0;
}
}
void DebuggerToolTipHolder::acquireEngine()
{
DEBUG("ACQUIRE ENGINE: STATE " << state);
......@@ -981,15 +1004,19 @@ void DebuggerToolTipHolder::positionShow(const TextEditorWidget *editorWidget)
}
}
static DebuggerToolTipHolder *findOrCreateTooltip(const DebuggerToolTipContext &context)
static DebuggerToolTipHolder *findOrCreateTooltip(const DebuggerToolTipContext &context, bool allowReuse = true)
{
purgeClosedToolTips();
for (int i = 0, n = m_tooltips.size(); i != n; ++i) {
DebuggerToolTipHolder *tooltip = m_tooltips.at(i);
if (tooltip->context.isSame(context))
return tooltip;
if (tooltip->context.isSame(context)) {
if (allowReuse)
return tooltip;
tooltip->destroy();
}
}
purgeClosedToolTips();
auto newTooltip = new DebuggerToolTipHolder(context);
m_tooltips.push_back(newTooltip);
......@@ -1227,8 +1254,8 @@ void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine)
// FIXME: For now remove all.
purgeClosedToolTips();
foreach (const DebuggerToolTipHolder *tooltip, m_tooltips)
tooltip->widget->close();
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
tooltip->destroy();
purgeClosedToolTips();
return;
......@@ -1287,7 +1314,7 @@ void DebuggerToolTipManager::saveSessionData()
void DebuggerToolTipManager::closeAllToolTips()
{
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
tooltip->widget->close();
tooltip->destroy();
m_tooltips.clear();
}
......@@ -1316,7 +1343,6 @@ static void slotTooltipOverrideRequested
context.engineType = engine->objectName();
context.fileName = editorWidget->textDocument()->filePath();
context.position = pos;
context.mousePosition = point;
editorWidget->convertPosition(pos, &context.line, &context.column);
QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column,
&context.function, &context.scopeFromLine, &context.scopeToLine);
......@@ -1324,7 +1350,7 @@ static void slotTooltipOverrideRequested
if (context.expression.isEmpty()) {
const Utils::TextContent text(DebuggerToolTipManager::tr("No valid expression"));
Utils::ToolTip::show(context.mousePosition, text, Internal::mainWindow());
Utils::ToolTip::show(point, text, Internal::mainWindow());
*handled = true;
return;
}
......@@ -1340,31 +1366,43 @@ static void slotTooltipOverrideRequested
context.iname = "tooltip." + context.expression.toLatin1().toHex();
}
DebuggerToolTipHolder *tooltip = findOrCreateTooltip(context);
if (tooltip->state == DebuggerToolTipHolder::Pending) {
bool allowReuse = false;
DebuggerToolTipHolder *tooltip = findOrCreateTooltip(context, allowReuse);
tooltip->context.mousePosition = point;
if (tooltip->state == PendingUnshown || tooltip->state == PendingShown) {
DEBUG("FOUND PENDING TOOLTIP, WAITING...");
*handled = true;
return;
}
tooltip->filterModel.setSourceModel(engine->watchHandler()->model());
tooltip->widget->titleLabel->setText(DebuggerToolTipManager::tr("Updating"));
tooltip->setState(DebuggerToolTipHolder::Pending);
if (localVariable) {
tooltip->acquireEngine();
DEBUG("SYNC IN STATE" << tooltip->state);
tooltip->showNeeded = false;
const Utils::WidgetContent widgetContent(tooltip->widget, true);
Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow());
if (tooltip->state == New) {
tooltip->setState(PendingUnshown);
tooltip->setState(PendingShown);
tooltip->acquireEngine();
const Utils::WidgetContent widgetContent(tooltip->widget, true);
Utils::ToolTip::show(point, widgetContent, Internal::mainWindow());
} else {
tooltip->acquireEngine();
Utils::ToolTip::move(point, Internal::mainWindow());
}
*handled = true;
} else {
DEBUG("ASYNC TIP IN STATE" << tooltip->state);
if (tooltip->state == New)
tooltip->setState(PendingUnshown);
else if (tooltip->state == Acquired || tooltip->state == Released)
tooltip->setState(PendingShown);
else
QTC_CHECK(false);
*handled = engine->setToolTipExpression(editorWidget, context);
if (!*handled) {
const Utils::TextContent text(DebuggerToolTipManager::tr("Expression too complex"));
Utils::ToolTip::show(context.mousePosition, text, Internal::mainWindow());
tooltip->widget->close();
Utils::ToolTip::show(point, text, Internal::mainWindow());
tooltip->destroy();
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment