/* This file is part of kdev-python, the python language plugin for KDevelop Copyright (C) 2012 Sven Brauch This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "variablecontroller.h" #include "variable.h" #include "debugsession.h" #include "pdbframestackmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "debuggerdebug.h" using namespace KDevelop; namespace Python { VariableController::VariableController(IDebugSession* parent) : IVariableController(parent) { } void VariableController::addWatch(KDevelop::Variable* variable) { variableCollection()->watches()->add(variable->expression()); } void VariableController::addWatchpoint(KDevelop::Variable* /*variable*/) { qCWarning(KDEV_PYTHON_DEBUGGER) << "addWatchpoint requested (not implemented)"; } void VariableController::handleEvent(IDebugSession::event_t event) { if ( event == IDebugSession::thread_or_frame_changed ) { DebugSession* s = static_cast(session()); PdbFrameStackModel* model = static_cast(s->frameStackModel()); int delta = model->currentFrame() - model->debuggerAtFrame(); model->setDebuggerAtFrame(model->currentFrame()); bool positive = delta > 0; qCDebug(KDEV_PYTHON_DEBUGGER) << "changing frame by" << delta; for ( int i = delta; i != 0; i += ( positive ? -1 : 1 ) ) { qCDebug(KDEV_PYTHON_DEBUGGER) << ( positive ? "up" : "down" ) << model->currentFrame() << model->debuggerAtFrame(); s->addSimpleInternalCommand(positive ? "up" : "down"); } } KDevelop::IVariableController::handleEvent(event); } KDevelop::Variable* VariableController::createVariable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent, const QString& expression, const QString& display) { return new Variable(model, parent, expression, display); } QString VariableController::expressionUnderCursor(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor) { QString prefix = ""; DUChainReadLocker lock; if ( ! doc->isModified() ) { if ( TopDUContext* context = DUChain::self()->chainForDocument(doc->url()) ) { DUContext* contextAtCursor = context->findContextAt(CursorInRevision(cursor.line(), cursor.column())); if ( contextAtCursor && contextAtCursor->type() == DUContext::Class ) { if ( contextAtCursor->owner() && ! contextAtCursor->owner()->identifier().isEmpty() ) { prefix = contextAtCursor->owner()->identifier().toString() + "."; } } } } else { qCDebug(KDEV_PYTHON_DEBUGGER) << "duchain unavailable for document" << doc->url() << "or document out of date"; } TextDocumentLazyLineFetcher linefetcher(doc); return prefix + CodeHelpers::expressionUnderCursor(linefetcher, cursor); } void VariableController::localsUpdateReady(QByteArray rawData) { QRegExp formatExtract("([a-zA-Z0-9_]+) \\=\\> (.*)"); QList data = rawData.split('\n'); qCDebug(KDEV_PYTHON_DEBUGGER) << "locals update:" << data; int i = 0; QStringList vars; QMap values; while ( i < data.length() ) { QByteArray d = data.at(i); if ( formatExtract.exactMatch(d) ) { QString key = formatExtract.capturedTexts().at(1); vars << key; values[key] = formatExtract.capturedTexts().at(2); } else qCWarning(KDEV_PYTHON_DEBUGGER) << "mismatch:" << d; i++; } QList variableObjects = KDevelop::ICore::self()->debugController()->variableCollection() ->locals()->updateLocals(vars); for ( int i = 0; i < variableObjects.length(); i++ ) { KDevelop::Variable* v = variableObjects[i]; v->setValue(values[v->expression()]); v->setHasMoreInitial(true); } } void VariableController::update() { qCDebug(KDEV_PYTHON_DEBUGGER) << "update requested"; DebugSession* d = static_cast(parent()); if (autoUpdate() & UpdateWatches) { variableCollection()->watches()->reinstall(); } if (autoUpdate() & UpdateLocals) { // TODO find a more elegant solution for this import! InternalPdbCommand* import = new InternalPdbCommand(0, 0, "import __kdevpython_debugger_utils\n"); InternalPdbCommand* cmd = new InternalPdbCommand(this, "localsUpdateReady", "__kdevpython_debugger_utils.format_locals(__kdevpython_debugger_utils.__kdevpython_builtin_locals())\n"); d->addCommand(import); d->addCommand(cmd); } } } #include "variablecontroller.moc"