Merge branch '1.0'
[kdevelop:php-docs.git] / phpdocsmodel.cpp
1 /*  This file is part of KDevelop
2
3     Copyright 2009 Milian Wolff <mail@milianw.de>
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19 */
20
21 #include "phpdocsmodel.h"
22
23 #include <language/duchain/duchain.h>
24 #include <language/duchain/declaration.h>
25 #include <language/duchain/duchainlock.h>
26
27 #include <language/duchain/types/structuretype.h>
28
29 #include <interfaces/icore.h>
30 #include <interfaces/ilanguage.h>
31 #include <interfaces/ilanguagecontroller.h>
32 #include <language/backgroundparser/backgroundparser.h>
33 #include <language/backgroundparser/parsejob.h>
34
35 #include <KStandardDirs>
36
37 using namespace KDevelop;
38
39 PhpDocsModel::PhpDocsModel(QObject* parent)
40     : QAbstractListModel(parent), m_internalFunctionsFile(KStandardDirs::locate("data", "kdevphpsupport/phpfunctions.php.gz"))
41 {
42     // make sure the php plugin is loaded
43     ILanguage* phpLangPlugin = ICore::self()->languageController()->language("Php");
44     if ( !phpLangPlugin ) {
45         qWarning() << "could not load PHP language support plugin";
46         return;
47     }
48     fillModel();
49 }
50
51 PhpDocsModel::~PhpDocsModel()
52 {
53 }
54
55 const KDevelop::IndexedString& PhpDocsModel::internalFunctionFile() const
56 {
57     return m_internalFunctionsFile;
58 }
59
60 void PhpDocsModel::slotParseJobFinished( ParseJob* job )
61 {
62     if ( job->document() == m_internalFunctionsFile ) {
63         disconnect(ICore::self()->languageController()->backgroundParser(), SIGNAL(parseJobFinished(KDevelop::ParseJob*)),
64                    this, SLOT(slotParseJobFinished(KDevelop::ParseJob*)));
65         fillModel();
66     }
67 }
68
69 void PhpDocsModel::fillModel()
70 {
71     DUChainReadLocker lock(DUChain::self()->lock());
72
73     TopDUContext* top = DUChain::self()->chainForDocument(m_internalFunctionsFile);
74     if ( !top ) {
75         qWarning() << "could not find DUChain for internal function file, connecting to background parser";
76         connect(ICore::self()->languageController()->backgroundParser(), SIGNAL(parseJobFinished(KDevelop::ParseJob*)),
77                 this, SLOT(slotParseJobFinished(KDevelop::ParseJob*)));
78         return;
79     }
80
81     kDebug() << "filling model";
82     typedef QPair<Declaration*, int> DeclDepthPair;
83     foreach ( const DeclDepthPair& declpair, top->allDeclarations(top->range().end, top) ) {
84         if ( declpair.first->abstractType() && declpair.first->abstractType()->modifiers() & AbstractType::ConstModifier ) {
85             // filter global constants, since they are hard to find in the documentation
86             continue;
87         }
88         m_declarations << declpair.first;
89
90         if ( StructureType::Ptr type = declpair.first->type<StructureType>() ) {
91             foreach ( Declaration* dec, type->internalContext(top)->localDeclarations() ) {
92                 m_declarations << dec;
93             }
94         }
95     }
96 }
97
98 bool PhpDocsModel::hasChildren(const QModelIndex& parent) const
99 {
100     // only the top-level has children
101     return parent == QModelIndex();
102 }
103
104 QVariant PhpDocsModel::data(const QModelIndex& index, int role) const
105 {
106     switch ( role ) {
107         case Qt::DisplayRole:
108         case Qt::EditRole: {
109             Declaration* dec = declarationForIndex(index);
110             DUChainReadLocker lock(DUChain::self()->lock());
111             QString ret = dec->toString();
112             if ( dec->isFunctionDeclaration() ) {
113                 // remove function arguments
114                 ret = ret.replace(QRegExp("\\(.+\\)"), "()");
115                 // remove return type
116                 ret = ret.remove(QRegExp("^[^ ]+ "));
117             }
118             return ret;
119         }
120         case DeclarationRole: {
121             Declaration* dec = declarationForIndex(index);
122             return QVariant(QMetaType::VoidStar, &dec);
123         }
124         /*
125         case Qt::ToolTipRole:
126         case Qt::AccessibleTextRole:
127         case Qt::AccessibleDescriptionRole:
128         */
129         default:
130             return QVariant();
131     }
132 }
133
134 int PhpDocsModel::rowCount(const QModelIndex& parent) const
135 {
136     Q_UNUSED(parent);
137
138     return m_declarations.count();
139 }
140
141 bool PhpDocsModel::canFetchMore(const QModelIndex& parent) const
142 {
143     Q_UNUSED(parent);
144
145     return false;
146 }
147
148 Declaration* PhpDocsModel::declarationForIndex(const QModelIndex& index) const
149 {
150     Q_ASSERT(m_declarations.size() > index.row());
151
152     return m_declarations[index.row()];
153 }
154
155 #include "phpdocsmodel.moc"