diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 7d9b6dcce907d3bfbc05014c6b144825757c8e77..4d365ae08336a6686da0f05c662ce2aefe78f23f 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -138,6 +138,43 @@ QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol)
     return names;
 }
 
+const Name *LookupContext::minimalName(const Name *name,
+                                       Scope *source,
+                                       ClassOrNamespace *target) const
+{
+    Q_ASSERT(name);
+    Q_ASSERT(source);
+    Q_ASSERT(target);
+
+    QList<Symbol *> symbols = lookup(name, source);
+    if (symbols.isEmpty())
+        return 0;
+
+    Symbol *canonicalSymbol = symbols.first();
+    std::vector<const Name *> fqNames = fullyQualifiedName(canonicalSymbol).toVector().toStdVector();
+    if (const QualifiedNameId *qId = name->asQualifiedNameId())
+        fqNames.push_back(qId->nameAt(qId->nameCount() - 1));
+    else
+        fqNames.push_back(name);
+
+    const QualifiedNameId *lastWorking = 0;
+    for (unsigned i = 0; i < fqNames.size(); ++i) {
+        const QualifiedNameId *newName = control()->qualifiedNameId(&fqNames[i],
+                                                                    fqNames.size() - i);
+        QList<Symbol *> candidates = target->lookup(newName);
+        if (candidates.contains(canonicalSymbol))
+            lastWorking = newName;
+        else
+            break;
+    }
+
+    if (lastWorking && lastWorking->nameCount() == 1)
+        return lastWorking->nameAt(0);
+    else
+        return lastWorking;
+}
+
+
 QSharedPointer<CreateBindings> LookupContext::bindings() const
 {
     if (! _bindings)
@@ -280,6 +317,19 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
     return candidates;
 }
 
+ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
+{
+    QList<const Name *> fqName = fullyQualifiedName(symbol);
+    ClassOrNamespace *binding = globalNamespace();
+    foreach (const Name *name, fqName) {
+        binding = binding->findType(name);
+        if (!binding)
+            return 0;
+    }
+
+    return binding;
+}
+
 ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
     : _factory(factory), _parent(parent), _templateId(0)
 {
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 73893a6670105106b236325c16b114a337a4bef6..82f180592ce0bf000e6d16717a53156599cdfd34 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -216,6 +216,7 @@ public:
     QList<Symbol *> lookup(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(Symbol *symbol) const;
+    ClassOrNamespace *lookupParent(Symbol *symbol) const;
 
     /// \internal
     QSharedPointer<CreateBindings> bindings() const;
@@ -227,6 +228,9 @@ public:
 
     static QList<const Name *> fullyQualifiedName(Symbol *symbol);
 
+    const Name *minimalName(const Name *name, Scope *source,
+                            ClassOrNamespace *target) const;
+
 private:
     // The current expression.
     Document::Ptr _expressionDocument;
diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp
index 37ec7d7e1db764bba517d263648584c89ac58281..48cdb009b75a0887477330de0ececb489373ec0e 100644
--- a/src/libs/cplusplus/Overview.cpp
+++ b/src/libs/cplusplus/Overview.cpp
@@ -30,6 +30,9 @@
 #include "Overview.h"
 #include "NamePrettyPrinter.h"
 #include "TypePrettyPrinter.h"
+
+#include <Control.h>
+#include <CoreTypes.h>
 #include <FullySpecifiedType.h>
 
 using namespace CPlusPlus;
@@ -145,3 +148,23 @@ QString Overview::prettyType(const FullySpecifiedType &ty,
     TypePrettyPrinter pp(this);
     return pp(ty, name);
 }
+
+/**
+ * Pretty-prints the given fully-specified type, but replacing the contained
+ * type with the given name.
+ *
+ * \param type the fully-specified type to convert to string
+ * \param the name for the named-type to use
+ * \param the control where the name is registered
+ * \return the pretty-printed name
+ */
+QString Overview::prettyTypeWithName(const FullySpecifiedType &type,
+                                     const Name *name,
+                                     Control *control)
+{
+    NamedType *namedTy = control->namedType(name);
+    FullySpecifiedType newTy = type;
+    newTy.setType(namedTy);
+
+    return prettyType(newTy);
+}
diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h
index 9cebefed01f456c81bab1a52a9fddb4c6f3edd03..7471f306a12d0903cec113bcfcfdbb14effd1294 100644
--- a/src/libs/cplusplus/Overview.h
+++ b/src/libs/cplusplus/Overview.h
@@ -79,6 +79,10 @@ public:
     QString prettyType(const FullySpecifiedType &type, const Name *name = 0) const;
     QString prettyType(const FullySpecifiedType &type, const QString &name) const;
 
+    QString prettyTypeWithName(const FullySpecifiedType &type,
+                               const Name *name,
+                               Control *control);
+
 private:
     unsigned _markedArgument;
     int _markedArgumentBegin;
diff --git a/src/plugins/cppeditor/cppdeclfromdef.cpp b/src/plugins/cppeditor/cppdeclfromdef.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a3c32d6f1d6fdda569b6bc95010248e10de787c0
--- /dev/null
+++ b/src/plugins/cppeditor/cppdeclfromdef.cpp
@@ -0,0 +1,249 @@
+/**************************************************************************
+**
+** 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 "cppdeclfromdef.h"
+
+#include <Literals.h> //### remove
+#include <QDebug> //###remove
+
+#include <AST.h>
+#include <ASTVisitor.h>
+#include <CoreTypes.h>
+#include <Names.h>
+#include <Symbols.h>
+#include <TranslationUnit.h>
+#include <cplusplus/ASTPath.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/Overview.h>
+
+#include <QtCore/QCoreApplication>
+
+using namespace CPlusPlus;
+using namespace CppEditor::Internal;
+using namespace CppTools;
+
+using CppEditor::CppRefactoringChanges;
+
+namespace {
+
+class InsertionPointFinder: public ASTVisitor
+{
+public:
+    InsertionPointFinder(Document::Ptr doc, const QString &className)
+        : ASTVisitor(doc->translationUnit())
+        , _doc(doc)
+        , _className(className)
+    {}
+
+    void operator()(int *line, int *column)
+    {
+        if (!line && !column)
+            return;
+        _line = 0;
+        _column = 0;
+
+        AST *ast = translationUnit()->ast();
+        accept(ast);
+
+        if (line)
+            *line = _line - 1;
+        if (column)
+            *column = _column - 1;
+    }
+
+protected:
+    using ASTVisitor::visit;
+
+    bool visit(ClassSpecifierAST *ast)
+    {
+        if (!ast->symbol || _className != QLatin1String(ast->symbol->identifier()->chars()))
+            return true;
+
+        unsigned currentVisibility = (tokenKind(ast->classkey_token) == T_CLASS) ? T_PUBLIC : T_PRIVATE;
+        unsigned insertBefore = 0;
+
+        for (DeclarationListAST *iter = ast->member_specifier_list; iter; iter = iter->next) {
+            DeclarationAST *decl = iter->value;
+            if (AccessDeclarationAST *xsDecl = decl->asAccessDeclaration()) {
+                const unsigned token = xsDecl->access_specifier_token;
+                const int kind = tokenKind(token);
+                if (kind == T_PUBLIC) {
+                    currentVisibility = T_PUBLIC;
+                } else if (kind == T_PROTECTED) {
+                    if (currentVisibility == T_PUBLIC) {
+                        insertBefore = token;
+                        break;
+                    } else {
+                        currentVisibility = T_PROTECTED;
+                    }
+                } else if (kind == T_PRIVATE) {
+                    if (currentVisibility == T_PUBLIC
+                            || currentVisibility == T_PROTECTED) {
+                        insertBefore = token;
+                        break;
+                    } else {
+                        currentVisibility = T_PRIVATE;
+                    }
+                }
+            }
+        }
+
+        if (!insertBefore)
+            insertBefore = ast->rbrace_token;
+
+        getTokenStartPosition(insertBefore, &_line, &_column);
+
+        return false;
+    }
+
+private:
+    Document::Ptr _doc;
+    QString _className;
+
+    unsigned _line;
+    unsigned _column;
+};
+
+QString prettyMinimalType(const FullySpecifiedType &ty,
+                          const LookupContext &context,
+                          Scope *source,
+                          ClassOrNamespace *target)
+{
+    Overview oo;
+
+    if (const NamedType *namedTy = ty->asNamedType())
+        return oo.prettyTypeWithName(ty, context.minimalName(namedTy->name(),
+                                                             source,
+                                                             target),
+                                     context.control().data());
+    else
+        return oo(ty);
+}
+
+} // anonymous namespace
+
+DeclFromDef::DeclFromDef(TextEditor::BaseTextEditor *editor)
+    : CppQuickFixOperation(editor)
+{}
+
+QString DeclFromDef::description() const
+{
+    return QCoreApplication::tr("Create Declaration from Definition", "DeclFromDef");
+}
+
+int DeclFromDef::match(const QList<CPlusPlus::AST *> &path)
+{
+    m_targetFileName.clear();
+    m_targetSymbolName.clear();
+    m_decl.clear();
+
+    FunctionDefinitionAST *funDef = 0;
+    int idx = 0;
+    for (; idx < path.size(); ++idx) {
+        AST *node = path.at(idx);
+        if (FunctionDefinitionAST *candidate = node->asFunctionDefinition())
+            if (!funDef)
+                funDef = candidate;
+        else if (node->asClassSpecifier())
+            return -1;
+    }
+
+    if (!funDef || !funDef->symbol)
+        return -1;
+
+    Function *method = funDef->symbol;
+    LookupContext context(document(), snapshot());
+
+    if (ClassOrNamespace *targetBinding = context.lookupParent(method)) {
+        foreach (Symbol *s, targetBinding->symbols()) {
+            if (Class *clazz = s->asClass()) {
+                m_targetFileName = QLatin1String(clazz->fileName());
+                m_targetSymbolName = QLatin1String(clazz->identifier()->chars());
+
+                m_decl = generateDeclaration(method, targetBinding);
+
+                return idx;
+            } // ### TODO: support insertion into namespaces
+        }
+    }
+
+    return -1;
+}
+
+void DeclFromDef::createChanges()
+{
+    CppRefactoringChanges *changes = refactoringChanges();
+
+    Document::Ptr targetDoc = changes->document(m_targetFileName);
+    InsertionPointFinder findInsertionPoint(targetDoc, m_targetSymbolName);
+    int line = 0, column = 0;
+    findInsertionPoint(&line, &column);
+
+    int targetPosition1 = changes->positionInFile(m_targetFileName, line, column);
+    int targetPosition2 = changes->positionInFile(m_targetFileName, line + 1, 0) - 1;
+
+    Utils::ChangeSet target;
+    target.insert(targetPosition1, m_decl);
+    changes->changeFile(m_targetFileName, target);
+
+    changes->reindent(m_targetFileName,
+                      Utils::ChangeSet::Range(targetPosition1, targetPosition2));
+
+    changes->openEditor(m_targetFileName, line, column);
+}
+
+QString DeclFromDef::generateDeclaration(Function *method, ClassOrNamespace *targetBinding)
+{
+    LookupContext context(document(), snapshot());
+    Overview oo;
+    QString decl;
+
+    decl.append(prettyMinimalType(method->returnType(),
+                                  context,
+                                  method->scope(),
+                                  targetBinding));
+
+    decl.append(QLatin1Char(' '));
+    decl.append(QLatin1String(method->name()->identifier()->chars()));
+    decl.append(QLatin1Char('('));
+    for (unsigned argIdx = 0; argIdx < method->argumentCount(); ++argIdx) {
+        if (argIdx > 0)
+            decl.append(QLatin1String(", "));
+        Argument *arg = method->argumentAt(argIdx)->asArgument();
+        decl.append(prettyMinimalType(arg->type(),
+                                      context,
+                                      method->members(),
+                                      targetBinding));
+        decl.append(QLatin1Char(' '));
+        decl.append(oo(arg->name()));
+    }
+    decl.append(QLatin1String(");\n\n"));
+
+    return decl;
+}
diff --git a/src/plugins/cppeditor/cppdeclfromdef.h b/src/plugins/cppeditor/cppdeclfromdef.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cbebc9271b3cd77777601e4da3254ac92cb4eff
--- /dev/null
+++ b/src/plugins/cppeditor/cppdeclfromdef.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** 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 CPPDECLFROMDEF_H
+#define CPPDECLFROMDEF_H
+
+#include "cppquickfix.h"
+
+#include <CPlusPlusForwardDeclarations.h>
+
+namespace CPlusPlus {
+class ClassOrNamespace;
+} // namespace CPlusPlus
+
+namespace CppEditor {
+namespace Internal {
+
+class DeclFromDef: public CppQuickFixOperation
+{
+public:
+    DeclFromDef(TextEditor::BaseTextEditor *editor);
+
+    virtual int match(const QList<CPlusPlus::AST *> &path);
+    virtual QString description() const;
+    virtual void createChanges();
+
+protected:
+    virtual QString generateDeclaration(CPlusPlus::Function *method,
+                                        CPlusPlus::ClassOrNamespace *targetBinding);
+
+private:
+    QString m_targetFileName;
+    QString m_targetSymbolName;
+    QString m_decl;
+};
+
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPDECLFROMDEF_H
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 49306644a2d5b80e856b96f1591d2fd79077c3fb..159f6442dec518d096ecfbf513f123ec52e2ffad 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -19,7 +19,8 @@ HEADERS += cppplugin.h \
     cpprefactoringchanges.h \
     cppcheckundefinedsymbols.h \
     cppsemanticinfo.h \
-    cppoutline.h
+    cppoutline.h \
+    cppdeclfromdef.h
 
 SOURCES += cppplugin.cpp \
     cppeditor.cpp \
@@ -31,7 +32,8 @@ SOURCES += cppplugin.cpp \
     cpprefactoringchanges.cpp \
     cppcheckundefinedsymbols.cpp \
     cppsemanticinfo.cpp \
-    cppoutline.cpp
+    cppoutline.cpp \
+    cppdeclfromdef.cpp
 
 RESOURCES += cppeditor.qrc
 
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index 00c6eb84ba0a964ab95fffaf020fb3eaedc9b325..5237e35773fc638d8144caa2e7fc2f0946a06bf9 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -29,6 +29,7 @@
 
 #include "cppquickfix.h"
 #include "cppeditor.h"
+#include "cppdeclfromdef.h"
 
 #include <cplusplus/ASTPath.h>
 #include <cplusplus/CppDocument.h>
@@ -1546,6 +1547,7 @@ QList<TextEditor::QuickFixOperation::Ptr> CppQuickFixFactory::quickFixOperations
     QSharedPointer<ConvertNumericToOctal> convertNumericToOctal(new ConvertNumericToOctal(editor));
     QSharedPointer<ConvertNumericToDecimal> convertNumericToDecimal(new ConvertNumericToDecimal(editor));
     QSharedPointer<CompleteSwitchCaseStatement> completeSwitchCaseStatement(new CompleteSwitchCaseStatement(editor));
+    QSharedPointer<DeclFromDef> declFromDef(new DeclFromDef(editor));
 
     quickFixOperations.append(rewriteLogicalAndOp);
     quickFixOperations.append(splitIfStatementOp);
@@ -1561,6 +1563,7 @@ QList<TextEditor::QuickFixOperation::Ptr> CppQuickFixFactory::quickFixOperations
     quickFixOperations.append(convertNumericToOctal);
     quickFixOperations.append(convertNumericToDecimal);
     quickFixOperations.append(completeSwitchCaseStatement);
+    quickFixOperations.append(declFromDef);
 
     if (editor->mimeType() == CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
         quickFixOperations.append(wrapCString);
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index 2bee7d79b0fee8318265754a1a3fcdbeb4105432..94e7a9d1e3741e4ad368833e7ffed36cd2068c4f 100644
--- a/src/plugins/texteditor/refactoringchanges.cpp
+++ b/src/plugins/texteditor/refactoringchanges.cpp
@@ -39,6 +39,11 @@
 
 using namespace TextEditor;
 
+RefactoringChanges::RefactoringChanges()
+    : m_lineToShow(0)
+    , m_columnToShow(0)
+{}
+
 RefactoringChanges::~RefactoringChanges()
 {}
 
@@ -149,12 +154,20 @@ QStringList RefactoringChanges::apply()
         // ###
     }
 
+    if (!m_fileNameToShow.isEmpty()) {
+        Core::EditorManager *editorManager = Core::EditorManager::instance();
+        BaseTextEditor *editor = editorForFile(m_fileNameToShow);
+        editorManager->activateEditor(editor->editableInterface());
+        if (m_lineToShow != -1)
+            editor->gotoLine(m_lineToShow + 1, m_columnToShow + 1);
+    }
+
     return changed.toList();
 }
 
 int RefactoringChanges::positionInFile(const QString &fileName, int line, int column) const
 {
-    if (BaseTextEditor *editor = editorForFile(fileName)) {
+    if (BaseTextEditor *editor = editorForFile(fileName, true)) {
         return editor->document()->findBlockByNumber(line).position() + column;
     } else {
         return -1;
@@ -191,3 +204,10 @@ BaseTextEditor *RefactoringChanges::editorForNewFile(const QString &fileName)
     f.close();
     return editorForFile(fileName, true);
 }
+
+void RefactoringChanges::openEditor(const QString &fileName, int line, int column)
+{
+    m_fileNameToShow = fileName;
+    m_lineToShow = line;
+    m_columnToShow = column;
+}
diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h
index 93b576496c427dff7c88ecfb6b560c05d95252ae..f111123acd75b524bb184c35bd3348e425423c17 100644
--- a/src/plugins/texteditor/refactoringchanges.h
+++ b/src/plugins/texteditor/refactoringchanges.h
@@ -46,6 +46,7 @@ public:
     typedef Utils::ChangeSet::Range Range;
 
 public:
+    RefactoringChanges();
     virtual ~RefactoringChanges();
 
     void createFile(const QString &fileName, const QString &contents);
@@ -63,10 +64,16 @@ public:
                                          bool openIfClosed = false);
     static BaseTextEditor *editorForNewFile(const QString &fileName);
 
+    /** line and column are zero-based */
+    void openEditor(const QString &fileName, int line, int column);
+
 private:
     QMap<QString, QString> m_contentsByCreatedFile;
     QMap<QString, Utils::ChangeSet> m_changesByFile;
     QMap<QString, QList<Range> > m_indentRangesByFile;
+    QString m_fileNameToShow;
+    int m_lineToShow;
+    int m_columnToShow;
 };
 
 } // namespace TextEditor