From 99fdaf06a23ca15f7ac527a9c4b1bfc4229edb96 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Tue, 13 Jul 2010 15:57:34 +0200
Subject: [PATCH] debuygger: make snapshots using true parallel engines

---
 src/plugins/debugger/debugger.pro             |   3 +
 src/plugins/debugger/debuggerconstants.h      |   1 +
 src/plugins/debugger/debuggerengine.cpp       |  17 +--
 src/plugins/debugger/debuggerengine.h         |   6 +-
 src/plugins/debugger/debuggerplugin.cpp       |  76 +++++-------
 src/plugins/debugger/debuggerplugin.h         |   1 +
 src/plugins/debugger/gdb/abstractgdbadapter.h |   1 -
 src/plugins/debugger/gdb/classicgdbengine.cpp |   3 +-
 src/plugins/debugger/gdb/gdbengine.cpp        |  82 ++++---------
 src/plugins/debugger/gdb/gdbengine.h          |   3 -
 src/plugins/debugger/sessionengine.cpp        |  61 ++++++++++
 src/plugins/debugger/sessionengine.h          |  69 +++++++++++
 src/plugins/debugger/snapshothandler.cpp      | 113 ++++++++++--------
 src/plugins/debugger/snapshothandler.h        |  58 ++-------
 src/plugins/debugger/snapshotwindow.cpp       |  11 +-
 15 files changed, 278 insertions(+), 227 deletions(-)
 create mode 100644 src/plugins/debugger/sessionengine.cpp
 create mode 100644 src/plugins/debugger/sessionengine.h

diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 4579aa56b00..e7f6e0446d0 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -35,6 +35,7 @@ HEADERS += breakhandler.h \
     procinterrupt.h \
     registerhandler.h \
     registerwindow.h \
+    sessionengine.h \
     stackframe.h \
     stackhandler.h \
     stackwindow.h \
@@ -50,6 +51,7 @@ HEADERS += breakhandler.h \
     debuggeruiswitcher.h \
     debuggermainwindow.h \
     threadshandler.h
+
 SOURCES += breakhandler.cpp \
     breakwindow.cpp \
     breakwindow.h \
@@ -82,6 +84,7 @@ SOURCES += breakhandler.cpp \
     debuggeruiswitcher.cpp \
     debuggermainwindow.cpp \
     threadshandler.cpp \
+    sessionengine.cpp \
     stackframe.cpp
 
 FORMS += attachexternaldialog.ui \
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index e0bc2a89507..00f1aad5131 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -248,6 +248,7 @@ enum ModelRoles
     RequestReloadRegistersRole,
 
     // Snapshots
+    SnapshotCapabilityRole,
     RequestMakeSnapshotRole,
     RequestActivateSnapshotRole,
     RequestRemoveSnapshotRole,
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 0e29427e1b6..cf88ea2f081 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -224,7 +224,6 @@ public:
         m_commandHandler(engine),
         m_modulesHandler(engine),
         m_registerHandler(engine),
-        m_snapshotHandler(engine),
         m_sourceFilesHandler(engine),
         m_stackHandler(engine),
         m_threadsHandler(engine),
@@ -291,7 +290,6 @@ public:
     CommandHandler m_commandHandler;
     ModulesHandler m_modulesHandler;
     RegisterHandler m_registerHandler;
-    SnapshotHandler m_snapshotHandler;
     SourceFilesHandler m_sourceFilesHandler;
     StackHandler m_stackHandler;
     ThreadsHandler m_threadsHandler;
@@ -464,7 +462,7 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
             d->doShutdownInferior();
             break;
 
-        case RequestExecSnapshotRole:
+        case RequestMakeSnapshotRole:
             makeSnapshot();
             break;
 
@@ -575,10 +573,10 @@ WatchHandler *DebuggerEngine::watchHandler() const
     return &d->m_watchHandler;
 }
 
-SnapshotHandler *DebuggerEngine::snapshotHandler() const
-{
-    return &d->m_snapshotHandler;
-}
+//SnapshotHandler *DebuggerEngine::snapshotHandler() const
+//{
+//    return &d->m_snapshotHandler;
+//}
 
 SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
 {
@@ -625,11 +623,6 @@ QAbstractItemModel *DebuggerEngine::returnModel() const
     return d->m_watchHandler.model(ReturnWatch);
 }
 
-QAbstractItemModel *DebuggerEngine::snapshotModel() const
-{
-    return d->m_snapshotHandler.model();
-}
-
 QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
 {
     return d->m_sourceFilesHandler.model();
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index bdb6a45f3c5..fcd54a242f3 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -105,7 +105,6 @@ class ModulesHandler;
 class RegisterHandler;
 class StackHandler;
 class StackFrame;
-class SnapshotHandler;
 class SourceFilesHandler;
 class ThreadsHandler;
 class WatchHandler;
@@ -154,7 +153,7 @@ public:
     virtual QString qtNamespace() const { return QString(); }
 
     virtual void makeSnapshot() {}
-    virtual void activateSnapshot(int index) { Q_UNUSED(index); }
+    virtual void updateAll() {}
 
     virtual void attemptBreakpointSynchronization() {}
     virtual void selectThread(int index) { Q_UNUSED(index); }
@@ -197,7 +196,6 @@ public:
     StackHandler *stackHandler() const;
     ThreadsHandler *threadsHandler() const;
     WatchHandler *watchHandler() const;
-    SnapshotHandler *snapshotHandler() const;
     SourceFilesHandler *sourceFilesHandler() const;
 
     QAbstractItemModel *commandModel() const;
@@ -209,7 +207,7 @@ public:
     QAbstractItemModel *localsModel() const;
     QAbstractItemModel *watchersModel() const;
     QAbstractItemModel *returnModel() const;
-    QAbstractItemModel *snapshotModel() const;
+    //QAbstractItemModel *snapshotModel() const;
     QAbstractItemModel *sourceFilesModel() const;
 
     void handleFinished();
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 8525c89eb6e..3fa094c0928 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -53,8 +53,8 @@
 
 #include "watchutils.h"
 #include "breakhandler.h"
-#include "stackhandler.h"
-#include "watchhandler.h"
+#include "snapshothandler.h"
+#include "sessionengine.h"
 
 #ifdef Q_OS_WIN
 #  include "shared/peutils.h"
@@ -820,43 +820,6 @@ static bool isCurrentProjectCppBased()
 }
 
 
-///////////////////////////////////////////////////////////////////////
-//
-// SessionEngine
-//
-///////////////////////////////////////////////////////////////////////
-
-// This class contains data serving as a template for debugger engines
-// started during a session.
-
-class SessionEngine : public DebuggerEngine
-{
-public:
-    SessionEngine() : DebuggerEngine(DebuggerStartParameters()) {}
-
-    void setupEngine() {}
-    void setupInferior() {}
-    void runEngine() {}
-    void shutdownEngine() {}
-    void shutdownInferior() {}
-
-    bool isSessionEngine() const { return true; }
-
-    void loadSessionData()
-    {
-        breakHandler()->loadSessionData();
-        watchHandler()->loadSessionData();
-    }
-
-    void saveSessionData()
-    {
-        watchHandler()->saveSessionData();
-        breakHandler()->saveSessionData();
-    }
-
-};
-
-
 ///////////////////////////////////////////////////////////////////////
 //
 // DebuggerPluginPrivate
@@ -966,6 +929,7 @@ public slots:
 
     DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp);
     void startDebugger(ProjectExplorer::RunControl *runControl);
+    void displayDebugger(ProjectExplorer::RunControl *runControl);
 
     void dumpLog();
     void cleanupViews();
@@ -1146,6 +1110,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
 
     // Session related data
     m_sessionEngine = new SessionEngine;
+    m_snapshotWindow->setModel(m_sessionEngine->m_snapshotHandler->model());
 
     // Debug mode setup
     m_debugMode = new DebugMode(this);
@@ -1154,10 +1119,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
     connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
         this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
 
-    // Tooltip
-    qRegisterMetaType<WatchData>("WatchData");
-    qRegisterMetaType<StackCookie>("StackCookie");
-
     m_actions.continueAction = new QAction(tr("Continue"), this);
     QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png");
     continueIcon.addFile(":/debugger/images/debugger_continue.png");
@@ -1950,29 +1911,41 @@ DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp)
     return m_debuggerRunControlFactory->create(sp);
 }
 
+void DebuggerPluginPrivate::displayDebugger(ProjectExplorer::RunControl *rc)
+{
+    DebuggerRunControl *runControl = qobject_cast<DebuggerRunControl *>(rc);
+    QTC_ASSERT(runControl, return);
+    disconnectEngine();
+    connectEngine(runControl->engine());
+    runControl->engine()->updateAll();
+    updateState(runControl->engine());
+}
+
 void DebuggerPluginPrivate::startDebugger(ProjectExplorer::RunControl *rc)
 {
+    qDebug() << "START DEBUGGER 1";
     QTC_ASSERT(rc, return);
     DebuggerRunControl *runControl = qobject_cast<DebuggerRunControl *>(rc);
     QTC_ASSERT(runControl, return);
     activateDebugMode();
     connectEngine(runControl->engine());
+    //m_sessionEngine->m_snapshotHandler->appendSnapshot(runControl);
     ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE);
+    qDebug() << "START DEBUGGER 2";
 }
 
 void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
 {
-    //if (engine == m_sessionEngine)
-    //    qDebug() << "CONNECTING DUMMY ENGINE" << engine;
-    //else
-    //    qDebug() << "CONNECTING ENGINE " << engine;
+    if (engine == m_sessionEngine)
+        qDebug() << "CONNECTING DUMMY ENGINE" << engine;
+    else
+        qDebug() << "CONNECTING ENGINE " << engine;
     m_breakWindow->setModel(engine->breakModel());
     m_commandWindow->setModel(engine->commandModel());
     m_localsWindow->setModel(engine->localsModel());
     m_modulesWindow->setModel(engine->modulesModel());
     m_registerWindow->setModel(engine->registerModel());
     m_returnWindow->setModel(engine->returnModel());
-    m_snapshotWindow->setModel(engine->snapshotModel());
     m_sourceFilesWindow->setModel(engine->sourceFilesModel());
     m_stackWindow->setModel(engine->stackModel());
     m_threadsWindow->setModel(engine->threadsModel());
@@ -2666,6 +2639,11 @@ void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl)
     instance()->d->startDebugger(runControl);
 }
 
+void DebuggerPlugin::displayDebugger(ProjectExplorer::RunControl *runControl)
+{
+    instance()->d->displayDebugger(runControl);
+}
+
 void DebuggerPlugin::updateState(DebuggerEngine *engine)
 {
     d->updateState(engine);
@@ -2706,6 +2684,7 @@ void DebuggerPlugin::createNewDock(QWidget *widget)
 void DebuggerPlugin::runControlStarted(DebuggerRunControl *runControl)
 {
     d->connectEngine(runControl->engine());
+    d->m_sessionEngine->m_snapshotHandler->appendSnapshot(runControl);
 }
 
 void DebuggerPlugin::runControlFinished(DebuggerRunControl *runControl)
@@ -2724,6 +2703,7 @@ bool DebuggerPlugin::isRegisterViewVisible() const
     return d->m_registerDock->toggleViewAction()->isChecked();
 }
 
+
 //////////////////////////////////////////////////////////////////////
 //
 // Testing
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index b183c3c855f..e1c98444904 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -85,6 +85,7 @@ public:
 
     static DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp);
     static void startDebugger(ProjectExplorer::RunControl *runControl);
+    static void displayDebugger(ProjectExplorer::RunControl *runControl);
 
     QMessageBox *showMessageBox(int icon, const QString &title,
         const QString &text, int buttons = 0);
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h
index 116226f2e34..2a40e4ddd46 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.h
@@ -69,7 +69,6 @@ public:
     virtual void interruptInferior() = 0;
     virtual void shutdownInferior() = 0;
     virtual void shutdownAdapter() = 0;
-    //virtual const char *inferiorShutdownCommand() const;
     virtual AbstractGdbProcess *gdbProc() = 0;
 
     virtual DumperHandling dumperHandling() const = 0;
diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp
index 409ab165294..6a3d95264af 100644
--- a/src/plugins/debugger/gdb/classicgdbengine.cpp
+++ b/src/plugins/debugger/gdb/classicgdbengine.cpp
@@ -574,7 +574,8 @@ void GdbEngine::updateAllClassic()
 {
     PRECONDITION;
     PENDING_DEBUG("UPDATING ALL\n");
-    QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
+    QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk,
+        qDebug() << state());
     tryLoadDebuggingHelpersClassic();
     reloadModulesInternal();
     postCommand("-stack-list-frames", WatchUpdate,
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index cc46107b1b7..ed8a67bf918 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -35,6 +35,7 @@
 #include "debuggeruiswitcher.h"
 #include "debuggermainwindow.h"
 #include "debuggerplugin.h"
+#include "debuggerrunner.h"
 
 #include "attachgdbadapter.h"
 #include "coregdbadapter.h"
@@ -1831,7 +1832,7 @@ void GdbEngine::setupEngine()
 
 unsigned GdbEngine::debuggerCapabilities() const
 {
-    return ReverseSteppingCapability | SnapshotCapability
+    unsigned caps = ReverseSteppingCapability
         | AutoDerefPointersCapability | DisassemblerCapability
         | RegisterCapability | ShowMemoryCapability
         | JumpToLineCapability | ReloadModuleCapability
@@ -1840,6 +1841,11 @@ unsigned GdbEngine::debuggerCapabilities() const
         | CreateFullBacktraceCapability
         | WatchpointCapability
         | AddWatcherCapability;
+
+    if (startParameters().startMode == AttachCore)
+        return caps;
+
+    return caps | SnapshotCapability;
 }
 
 void GdbEngine::continueInferiorInternal()
@@ -2485,6 +2491,10 @@ void GdbEngine::attemptBreakpointSynchronization()
         qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
     showMessage(_("ATTEMPT BREAKPOINT SYNC"));
 
+    // We don't have breakpoints in core files.
+    if (startParameters().startMode == AttachCore)
+        return;
+
     switch (state()) {
     case InferiorSetupRequested:
     case InferiorRunRequested:
@@ -3030,11 +3040,19 @@ void GdbEngine::makeSnapshot()
 void GdbEngine::handleMakeSnapshot(const GdbResponse &response)
 {
     if (response.resultClass == GdbResultDone) {
-        SnapshotData snapshot;
-        snapshot.setDate(QDateTime::currentDateTime());
-        snapshot.setLocation(response.cookie.toString());
-        snapshot.setFrames(stackHandler()->frames());
-        snapshotHandler()->appendSnapshot(snapshot);
+        DebuggerStartParameters sp = startParameters();
+        sp.startMode = AttachCore;
+        sp.coreFile = response.cookie.toString();
+        //snapshot.setDate(QDateTime::currentDateTime());
+        StackFrames frames = stackHandler()->frames();
+        QString function = _("<unknown>");
+        if (!frames.isEmpty()) {
+            const StackFrame &frame = frames.at(0);
+            function = frame.function + _(":") + QString::number(frame.line);
+        }
+        sp.displayName = function + _(": ") + QDateTime::currentDateTime().toString();
+        DebuggerRunControl *rc = DebuggerPlugin::createDebugger(sp);
+        DebuggerPlugin::startDebugger(rc);
     } else {
         QByteArray msg = response.data.findChild("msg").data();
         showMessageBox(QMessageBox::Critical, tr("Snapshot Creation Error"),
@@ -3042,58 +3060,6 @@ void GdbEngine::handleMakeSnapshot(const GdbResponse &response)
     }
 }
 
-void GdbEngine::activateSnapshot(int index)
-{
-    SnapshotData snapshot = snapshotHandler()->setCurrentIndex(index);
-
-    DebuggerStartParameters &sp =
-        const_cast<DebuggerStartParameters &>(startParameters());
-    sp.startMode = AttachCore;
-    sp.coreFile = snapshot.location();
-
-    if (state() == InferiorUnrunnable) {
-        // All is well. We are looking at another core file.
-#if 0
-        // FIXME AAA
-        setState(EngineShutdownRequested);
-        setState(DebuggerNotReady);
-#endif
-        activateSnapshot2();
-    } else if (state() != DebuggerNotReady) {
-        QMessageBox *mb = showMessageBox(QMessageBox::Critical,
-            tr("Snapshot Reloading"),
-            tr("In order to load snapshots the debugged process needs "
-             "to be stopped. Continuation will not be possible afterwards.\n"
-             "Do you want to stop the debugged process and load the selected "
-             "snapshot?"), QMessageBox::Ok | QMessageBox::Cancel);
-        if (mb->exec() == QMessageBox::Cancel)
-            return;
-        showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER"));
-        delete m_gdbAdapter;
-        m_gdbAdapter = createAdapter();
-        postCommand("kill", NeedsStop, CB(handleActivateSnapshot));
-    } else {
-        activateSnapshot2();
-    }
-}
-
-void GdbEngine::handleActivateSnapshot(const GdbResponse &response)
-{
-    Q_UNUSED(response);
-    quitDebugger();
-}
-
-void GdbEngine::activateSnapshot2()
-{
-    // Otherwise the stack data might be stale.
-    // See http://sourceware.org/bugzilla/show_bug.cgi?id=1124.
-#if 0
-    setState(EngineSetupRequested);
-    postCommand("set stack-cache off");
-    handleAdapterStarted();
-#endif
-}
-
 
 //////////////////////////////////////////////////////////////////////
 //
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 48f85ea7e69..7728e2b3d54 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -378,9 +378,6 @@ private: ////////// View & Data Stuff //////////
     //
     virtual void makeSnapshot();
     void handleMakeSnapshot(const GdbResponse &response);
-    void handleActivateSnapshot(const GdbResponse &response);
-    void activateSnapshot(int index);
-    void activateSnapshot2();
 
     //
     // Register specific stuff
diff --git a/src/plugins/debugger/sessionengine.cpp b/src/plugins/debugger/sessionengine.cpp
new file mode 100644
index 00000000000..c3b0f7fa439
--- /dev/null
+++ b/src/plugins/debugger/sessionengine.cpp
@@ -0,0 +1,61 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sessionengine.h"
+#include "snapshothandler.h"
+#include "breakhandler.h"
+#include "watchhandler.h"
+
+namespace Debugger {
+namespace Internal {
+
+// This class contains data serving as a template for debugger engines
+// started during a session.
+
+SessionEngine::SessionEngine()
+    : DebuggerEngine(DebuggerStartParameters()),
+      m_snapshotHandler(new SnapshotHandler(this))
+{
+}
+
+void SessionEngine::loadSessionData()
+{
+    breakHandler()->loadSessionData();
+    watchHandler()->loadSessionData();
+}
+
+void SessionEngine::saveSessionData()
+{
+    watchHandler()->saveSessionData();
+    breakHandler()->saveSessionData();
+}
+
+} // namespace Internal
+} // namespace Debugger
+
diff --git a/src/plugins/debugger/sessionengine.h b/src/plugins/debugger/sessionengine.h
new file mode 100644
index 00000000000..c426c097c8f
--- /dev/null
+++ b/src/plugins/debugger/sessionengine.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_SESSIONENGINE_H
+#define DEBUGGER_SESSIONENGINE_H
+
+#include "debuggerengine.h"
+
+namespace Debugger {
+namespace Internal {
+
+class SnapshotHandler;
+
+// This class contains data serving as a template for debugger engines
+// started during a session.
+
+class SessionEngine : public DebuggerEngine
+{
+public:
+    SessionEngine();
+
+    void setupEngine() {}
+    void setupInferior() {}
+    void runEngine() {}
+    void shutdownEngine() {}
+    void shutdownInferior() {}
+
+    bool isSessionEngine() const { return true; }
+
+    void loadSessionData();
+    void saveSessionData();
+
+public:
+    // The global set of snapshots.
+    SnapshotHandler *m_snapshotHandler;
+    // The model serving as command dispatcher.
+};
+
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_SESSIONENGINE_H
diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp
index 2601b4a932c..6d05181296a 100644
--- a/src/plugins/debugger/snapshothandler.cpp
+++ b/src/plugins/debugger/snapshothandler.cpp
@@ -29,9 +29,12 @@
 
 #include "snapshothandler.h"
 
+#include "sessionengine.h"
 #include "debuggeractions.h"
 #include "debuggerconstants.h"
 #include "debuggerengine.h"
+#include "debuggerrunner.h"
+#include "debuggerplugin.h"
 
 #include <utils/qtcassert.h>
 #include <utils/savedaction.h>
@@ -44,6 +47,7 @@
 namespace Debugger {
 namespace Internal {
 
+#if 0
 SnapshotData::SnapshotData()
 {}
 
@@ -104,6 +108,7 @@ QDebug operator<<(QDebug d, const  SnapshotData &f)
     d.nospace() << res;
     return d;
 }
+#endif
 
 ////////////////////////////////////////////////////////////////////////
 //
@@ -111,20 +116,25 @@ QDebug operator<<(QDebug d, const  SnapshotData &f)
 //
 ////////////////////////////////////////////////////////////////////////
 
-SnapshotHandler::SnapshotHandler(DebuggerEngine *engine)
+SnapshotHandler::SnapshotHandler(SessionEngine *engine)
   : m_engine(engine),
     m_positionIcon(QIcon(":/debugger/images/location_16.png")),
     m_emptyIcon(QIcon(":/debugger/images/debugger_empty_14.png"))
 {
-    m_currentIndex = 0;
-    connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
-        this, SLOT(resetModel()));
+    m_currentIndex = -1;
 }
 
 SnapshotHandler::~SnapshotHandler()
 {
-    foreach (const SnapshotData &snapshot, m_snapshots)
-        QFile::remove(snapshot.location());
+    for (int i = m_snapshots.size(); --i >= 0; ) {
+        QString file = engineAt(i)->startParameters().coreFile;
+        QFile::remove(file);
+    }
+}
+
+DebuggerEngine *SnapshotHandler::engineAt(int i) const
+{
+    return m_snapshots.at(i)->engine();
 }
 
 int SnapshotHandler::rowCount(const QModelIndex &parent) const
@@ -135,7 +145,7 @@ int SnapshotHandler::rowCount(const QModelIndex &parent) const
 
 int SnapshotHandler::columnCount(const QModelIndex &parent) const
 {
-    return parent.isValid() ? 0 : 3;
+    return parent.isValid() ? 0 : 2;
 }
 
 QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
@@ -143,33 +153,25 @@ QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
     if (!index.isValid() || index.row() >= m_snapshots.size())
         return QVariant();
 
-    if (index.row() == m_snapshots.size()) {
-        if (role == Qt::DisplayRole && index.column() == 0)
-            return tr("...");
-        if (role == Qt::DisplayRole && index.column() == 1)
-            return tr("<More>");
-        if (role == Qt::DecorationRole && index.column() == 0)
-            return m_emptyIcon;
-        return QVariant();
-    }
-
-    const SnapshotData &snapshot = m_snapshots.at(index.row());
+    const DebuggerEngine *engine = engineAt(index.row());
+    const DebuggerStartParameters &sp = engine->startParameters();
 
     if (role == Qt::DisplayRole) {
         switch (index.column()) {
-        case 0: // Function name of topmost snapshot
-            return snapshot.function();
-        case 1: // Timestamp
-            return snapshot.date().toString();
-        case 2: // File name
-            return snapshot.location();
+        case 0:
+            return sp.displayName;
+        case 1:
+            return sp.coreFile.isEmpty() ? sp.executable : sp.coreFile;
         }
         return QVariant();
     }
 
+    if (role == SnapshotCapabilityRole)
+        return engine->debuggerCapabilities() & SnapshotCapability;
+
     if (role == Qt::ToolTipRole) {
         //: Tooltip for variable
-        return snapshot.toToolTip();
+        //return snapshot.toToolTip();
     }
 
     if (role == Qt::DecorationRole && index.column() == 0) {
@@ -177,9 +179,6 @@ QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
         return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
     }
 
-    //if (role == Qt::UserRole)
-    //    return QVariant::fromValue(snapshot);
-
     return QVariant();
 }
 
@@ -187,9 +186,8 @@ QVariant SnapshotHandler::headerData(int section, Qt::Orientation orientation, i
 {
     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
         switch (section) {
-            case 0: return tr("Function");
-            case 1: return tr("Date");
-            case 2: return tr("Location");
+            case 0: return tr("Name");
+            case 1: return tr("File");
         };
     }
     return QVariant();
@@ -201,45 +199,60 @@ Qt::ItemFlags SnapshotHandler::flags(const QModelIndex &index) const
         return 0;
     if (index.row() == m_snapshots.size())
         return QAbstractTableModel::flags(index);
-    //const SnapshotData &snapshot = m_snapshots.at(index.row());
     return true ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
 }
 
 bool SnapshotHandler::setData
     (const QModelIndex &index, const QVariant &value, int role)
 {
-    if (role == RequestMakeSnapshotRole) {
-        m_engine->makeSnapshot();
+    Q_UNUSED(value);
+    if (index.isValid() && role == RequestMakeSnapshotRole) {
+        engineAt(index.row())->makeSnapshot();
         return true;
     }
-    if (role == RequestActivateSnapshotRole) {
-        m_engine->activateSnapshot(value.toInt());
+    if (index.isValid() && role == RequestActivateSnapshotRole) {
+        m_currentIndex = index.row();
+        qDebug() << "ACTIVATING INDEX: " << m_currentIndex
+            << " OF " << size();
+        DebuggerPlugin::displayDebugger(m_snapshots.at(m_currentIndex));
+        reset();
         return true;
     }
-    if (role == RequestRemoveSnapshotRole) {
-        removeSnapshot(value.toInt());
-        return true;
-    }
-    return QAbstractTableModel::setData(index, value, role);
+    return false;
 }
 
+
+#if 0
+    // See http://sourceware.org/bugzilla/show_bug.cgi?id=11241.
+    setState(EngineSetupRequested);
+    postCommand("set stack-cache off");
+
+    QMessageBox *mb = showMessageBox(QMessageBox::Critical,
+        tr("Snapshot Reloading"),
+        tr("In order to load snapshots the debugged process needs "
+         "to be stopped. Continuation will not be possible afterwards.\n"
+         "Do you want to stop the debugged process and load the selected "
+         "snapshot?"), QMessageBox::Ok | QMessageBox::Cancel);
+    if (mb->exec() == QMessageBox::Cancel)
+#endif
+
 void SnapshotHandler::removeAll()
 {
     m_snapshots.clear();
-    m_currentIndex = 0;
+    m_currentIndex = -1;
     reset();
 }
 
-void SnapshotHandler::appendSnapshot(const SnapshotData &snapshot)
+void SnapshotHandler::appendSnapshot(DebuggerRunControl *rc)
 {
-    m_snapshots.append(snapshot);
-    m_currentIndex = m_snapshots.size() - 1;
+    m_snapshots.append(rc);
+    m_currentIndex = size() - 1;
     reset();
 }
 
 void SnapshotHandler::removeSnapshot(int index)
 {
-    QFile::remove(m_snapshots.at(index).location());
+    QFile::remove(engineAt(index)->startParameters().coreFile);
     m_snapshots.removeAt(index);
     if (index == m_currentIndex)
         m_currentIndex = -1;
@@ -248,16 +261,10 @@ void SnapshotHandler::removeSnapshot(int index)
     reset();
 }
 
-QList<SnapshotData> SnapshotHandler::snapshots() const
-{
-    return m_snapshots;
-}
-
-SnapshotData SnapshotHandler::setCurrentIndex(int index)
+void SnapshotHandler::setCurrentIndex(int index)
 {
     m_currentIndex = index;
     reset();
-    return m_snapshots.at(index);
 }
 
 } // namespace Internal
diff --git a/src/plugins/debugger/snapshothandler.h b/src/plugins/debugger/snapshothandler.h
index f77a0a1bfde..1f89c102a08 100644
--- a/src/plugins/debugger/snapshothandler.h
+++ b/src/plugins/debugger/snapshothandler.h
@@ -36,45 +36,14 @@
 #include <QtCore/QDateTime>
 
 namespace Debugger {
-namespace Internal {
-
-class DebuggerEngine;
 
-////////////////////////////////////////////////////////////////////////
-//
-// SnapshotData
-//
-////////////////////////////////////////////////////////////////////////
-
-/*! An entry in the snapshot model. */
-
-class SnapshotData
-{
-public:
-    SnapshotData();
+class DebuggerRunControl;
+class DebuggerStartParameters;
 
-    void clear();
-    QString toString() const;
-    QString toToolTip() const;
-
-    QDateTime date() const { return m_date; }
-    void setDate(const QDateTime &date) { m_date = date; }
-
-    void setLocation(const QString &location) { m_location = location; }
-    QString location() const { return m_location; }
-
-    void setFrames(const StackFrames &frames) { m_frames = frames; }
-    StackFrames frames() const { return m_frames; }
-
-    QString function() const; // Topmost entry.
-
-private:
-    QString m_location;       // Name of the core file.
-    QDateTime m_date;         // Date of the snapshot
-    StackFrames m_frames;     // Stack frames.
-};
+namespace Internal {
 
-typedef QList<SnapshotData> Snapshots;
+class SessionEngine;
+class DebuggerEngine;
 
 
 ////////////////////////////////////////////////////////////////////////
@@ -83,25 +52,23 @@ typedef QList<SnapshotData> Snapshots;
 //
 ////////////////////////////////////////////////////////////////////////
 
-/*! A model to represent the snapshot in a QTreeView. */
+/*! A model to represent the snapshots in a QTreeView. */
 class SnapshotHandler : public QAbstractTableModel
 {
     Q_OBJECT
 
 public:
-    explicit SnapshotHandler(DebuggerEngine *engine);
+    explicit SnapshotHandler(SessionEngine *engine);
     ~SnapshotHandler();
 
-    void setFrames(const Snapshots &snapshots, bool canExpand = false);
-    Snapshots snapshots() const;
-
     // Called from SnapshotHandler after a new snapshot has been added
     void removeAll();
     void removeSnapshot(int index);
     QAbstractItemModel *model() { return this; }
     int currentIndex() const { return m_currentIndex; }
-    void appendSnapshot(const SnapshotData &snapshot);
-    SnapshotData setCurrentIndex(int index);
+    void appendSnapshot(DebuggerRunControl *rc);
+    void setCurrentIndex(int index);
+    int size() const { return m_snapshots.size(); }
 
 private:
     // QAbstractTableModel
@@ -112,10 +79,11 @@ private:
     QVariant headerData(int section, Qt::Orientation orientation, int role) const;
     Qt::ItemFlags flags(const QModelIndex &index) const;
     Q_SLOT void resetModel() { reset(); }
+    DebuggerEngine *engineAt(int i) const;
 
-    DebuggerEngine *m_engine;
+    SessionEngine *m_engine;
     int m_currentIndex;
-    Snapshots m_snapshots;
+    QList<DebuggerRunControl *> m_snapshots;
     const QVariant m_positionIcon;
     const QVariant m_emptyIcon;
 };
diff --git a/src/plugins/debugger/snapshotwindow.cpp b/src/plugins/debugger/snapshotwindow.cpp
index ef538d6067e..557de59f167 100644
--- a/src/plugins/debugger/snapshotwindow.cpp
+++ b/src/plugins/debugger/snapshotwindow.cpp
@@ -128,10 +128,15 @@ void SnapshotWindow::keyPressEvent(QKeyEvent *ev)
 
 void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev)
 {
-    //QModelIndex idx = indexAt(ev->pos());
+    QModelIndex idx = indexAt(ev->pos());
 
     QMenu menu;
 
+    QAction *actCreate = menu.addAction(tr("Create Snapshot"));
+    actCreate->setEnabled(idx.data(SnapshotCapabilityRole).toBool());
+
+    menu.addSeparator();
+
     QAction *actAdjust = menu.addAction(tr("Adjust Column Widths to Contents"));
 
     QAction *actAlwaysAdjust =
@@ -145,7 +150,9 @@ void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QAction *act = menu.exec(ev->globalPos());
 
-    if (act == actAdjust)
+    if (act == actCreate)
+        model()->setData(idx, idx.row(), RequestMakeSnapshotRole);
+    else if (act == actAdjust)
         resizeColumnsToContents();
     else if (act == actAlwaysAdjust)
         setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
-- 
GitLab