Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
37b9bf84
Commit
37b9bf84
authored
Jan 05, 2011
by
hjk
Browse files
extensionsystem: "soft dependencies" infrastructure
Reviewed-by: con Reviewed-by: ckamm
parent
2c26c6b1
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/libs/extensionsystem/extensionsystem.pro
View file @
37b9bf84
...
...
@@ -10,6 +10,7 @@ DEFINES += IDE_TEST_DIR=\\\"$$IDE_SOURCE_TREE\\\"
HEADERS
+=
pluginerrorview
.
h
\
plugindetailsview
.
h
\
invoker
.
h
\
iplugin
.
h
\
iplugin_p
.
h
\
extensionsystem_global
.
h
\
...
...
@@ -23,6 +24,7 @@ HEADERS += pluginerrorview.h \
plugincollection
.
h
SOURCES
+=
pluginerrorview
.
cpp
\
plugindetailsview
.
cpp
\
invoker
.
cpp
\
iplugin
.
cpp
\
pluginmanager
.
cpp
\
pluginspec
.
cpp
\
...
...
src/libs/extensionsystem/invoker.cpp
0 → 100644
View file @
37b9bf84
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "invoker.h"
namespace
ExtensionSystem
{
InvokerBase
::
InvokerBase
()
{
lastArg
=
0
;
useRet
=
false
;
nag
=
true
;
success
=
true
;
target
=
0
;
}
InvokerBase
::~
InvokerBase
()
{
if
(
!
success
&&
nag
)
qWarning
(
"Could not invoke function '%s' in object of type '%s'."
,
sig
.
constData
(),
target
->
metaObject
()
->
className
());
}
bool
InvokerBase
::
wasSuccessful
()
const
{
nag
=
false
;
return
success
;
}
void
InvokerBase
::
invoke
(
QObject
*
t
,
const
char
*
slot
)
{
target
=
t
;
success
=
false
;
sig
.
append
(
slot
,
qstrlen
(
slot
));
sig
.
append
(
'('
);
for
(
int
paramCount
=
0
;
paramCount
<
lastArg
;
++
paramCount
)
{
if
(
paramCount
)
sig
.
append
(
','
);
const
char
*
type
=
arg
[
paramCount
].
name
();
sig
.
append
(
type
,
strlen
(
type
));
}
sig
.
append
(
')'
);
sig
.
append
(
'\0'
);
int
idx
=
target
->
metaObject
()
->
indexOfMethod
(
sig
.
constData
());
if
(
idx
<
0
)
return
;
QMetaMethod
method
=
target
->
metaObject
()
->
method
(
idx
);
if
(
useRet
)
success
=
method
.
invoke
(
target
,
ret
,
arg
[
0
],
arg
[
1
],
arg
[
2
],
arg
[
3
],
arg
[
4
],
arg
[
5
],
arg
[
6
],
arg
[
7
],
arg
[
8
],
arg
[
9
]);
else
success
=
method
.
invoke
(
target
,
arg
[
0
],
arg
[
1
],
arg
[
2
],
arg
[
3
],
arg
[
4
],
arg
[
5
],
arg
[
6
],
arg
[
7
],
arg
[
8
],
arg
[
9
]);
}
}
// namespace ExtensionSystem
src/libs/extensionsystem/invoker.h
0 → 100644
View file @
37b9bf84
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef EXTENSIONSYSTEM_INVOKER_H
#define EXTENSIONSYSTEM_INVOKER_H
#include "extensionsystem_global.h"
#include <QtCore/QMetaMethod>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaType>
#include <QtCore/QVarLengthArray>
namespace
ExtensionSystem
{
class
InvokerBase
{
public:
InvokerBase
();
~
InvokerBase
();
bool
wasSuccessful
()
const
;
template
<
class
T
>
void
addArgument
(
const
T
&
t
)
{
arg
[
lastArg
++
]
=
QGenericArgument
(
typeName
<
T
>
(),
&
t
);
}
template
<
class
T
>
void
setReturnValue
(
T
&
t
)
{
useRet
=
true
;
ret
=
QGenericReturnArgument
(
typeName
<
T
>
(),
&
t
);
}
void
invoke
(
QObject
*
target
,
const
char
*
slot
);
private:
InvokerBase
(
const
InvokerBase
&
);
// Unimplemented.
template
<
class
T
>
const
char
*
typeName
()
{
return
QMetaType
::
typeName
(
qMetaTypeId
<
T
>
());
}
QObject
*
target
;
QGenericArgument
arg
[
10
];
QGenericReturnArgument
ret
;
QVarLengthArray
<
char
,
512
>
sig
;
int
lastArg
;
bool
success
;
bool
useRet
;
mutable
bool
nag
;
};
template
<
class
Result
>
class
Invoker
:
public
InvokerBase
{
public:
Invoker
(
QObject
*
target
,
const
char
*
slot
)
{
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
)
{
setReturnValue
(
result
);
addArgument
(
t0
);
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
,
class
T1
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
)
{
setReturnValue
(
result
);
addArgument
(
t0
);
addArgument
(
t1
);
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
,
class
T1
,
class
T2
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
,
const
T2
&
t2
)
{
setReturnValue
(
result
);
addArgument
(
t0
);
addArgument
(
t1
);
addArgument
(
t2
);
InvokerBase
::
invoke
(
target
,
slot
);
}
operator
Result
()
const
{
return
result
;
}
private:
Result
result
;
};
template
<
>
class
Invoker
<
void
>
:
public
InvokerBase
{
public:
Invoker
(
QObject
*
target
,
const
char
*
slot
)
{
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
)
{
addArgument
(
t0
);
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
,
class
T1
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
)
{
addArgument
(
t0
);
addArgument
(
t1
);
InvokerBase
::
invoke
(
target
,
slot
);
}
template
<
class
T0
,
class
T1
,
class
T2
>
Invoker
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
,
const
T2
&
t2
)
{
addArgument
(
t0
);
addArgument
(
t1
);
addArgument
(
t2
);
InvokerBase
::
invoke
(
target
,
slot
);
}
};
template
<
class
Result
>
Result
invokeHelper
(
InvokerBase
&
in
,
QObject
*
target
,
const
char
*
slot
)
{
Result
result
;
in
.
setReturnValue
(
result
);
in
.
invoke
(
target
,
slot
);
return
result
;
}
template
<
>
inline
void
invokeHelper
<
void
>
(
InvokerBase
&
in
,
QObject
*
target
,
const
char
*
slot
)
{
in
.
invoke
(
target
,
slot
);
}
template
<
class
Result
>
Result
invoke
(
QObject
*
target
,
const
char
*
slot
)
{
InvokerBase
in
;
return
invokeHelper
<
Result
>
(
in
,
target
,
slot
);
}
template
<
class
Result
,
class
T0
>
Result
invoke
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
)
{
InvokerBase
in
;
in
.
addArgument
(
t0
);
return
invokeHelper
<
Result
>
(
in
,
target
,
slot
);
}
template
<
class
Result
,
class
T0
,
class
T1
>
Result
invoke
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
)
{
InvokerBase
in
;
in
.
addArgument
(
t0
);
in
.
addArgument
(
t1
);
return
invokeHelper
<
Result
>
(
in
,
target
,
slot
);
}
template
<
class
Result
,
class
T0
,
class
T1
,
class
T2
>
Result
invoke
(
QObject
*
target
,
const
char
*
slot
,
const
T0
&
t0
,
const
T1
&
t1
,
const
T2
&
t2
)
{
InvokerBase
in
;
in
.
addArgument
(
t0
);
in
.
addArgument
(
t1
);
in
.
addArgument
(
t2
);
return
invokeHelper
<
Result
>
(
in
,
target
,
slot
);
}
}
// namespace ExtensionSystem
#endif // EXTENSIONSYSTEM_INVOKER_H
src/libs/extensionsystem/pluginmanager.cpp
View file @
37b9bf84
...
...
@@ -39,14 +39,15 @@
#include "iplugin.h"
#include "plugincollection.h"
#include <QtCore/Q
MetaProperty
>
#include <QtCore/Q
DateTime
>
#include <QtCore/QDir>
#include <QtCore/QMetaProperty>
#include <QtCore/QSettings>
#include <QtCore/QTextStream>
#include <QtCore/QWriteLocker>
#include <QtCore/QTime>
#include <QtCore/Q
DateTime
>
#include <QtCore/Q
Settings
>
#include <QtDebug>
#include <QtCore/Q
WriteLocker
>
#include <QtCore/Q
tDebug
>
#ifdef WITH_TESTS
#include <QTest>
#endif
...
...
@@ -60,9 +61,10 @@ enum { debugLeaks = 0 };
/*!
\namespace ExtensionSystem
\brief The ExtensionSystem namespace provides classes that belong to the core plugin system.
\brief The ExtensionSystem namespace provides classes that belong to the
core plugin system.
The basic extension system contains
of
the plugin manager and its supporting classes,
The basic extension system contains the plugin manager and its supporting classes,
and the IPlugin interface that must be implemented by plugin providers.
*/
...
...
@@ -114,15 +116,83 @@ enum { debugLeaks = 0 };
be implemented and added to the object pool. The plugin that provides the
extension point looks for implementations of the class / interface in the object pool.
\code
//
p
lugin A provides a "MimeTypeHandler" extension point
//
P
lugin A provides a "MimeTypeHandler" extension point
// in plugin B:
MyMimeTypeHandler *handler = new MyMimeTypeHandler();
ExtensionSystem::PluginManager::instance()->addObject(handler);
//
i
n plugin A:
//
I
n plugin A:
QList<MimeTypeHandler *> mimeHandlers =
ExtensionSystem::PluginManager::instance()->getObjects<MimeTypeHandler>();
\endcode
The \c{ExtensionSystem::Invoker} class template provides "syntactic sugar"
for using "soft" extension points that may or may not be provided by an
object in the pool. This approach does neither require the "user" plugin being
linked against the "provider" plugin nor a common shared
header file. The exposed interface is implicitly given by the
invokable methods of the "provider" object in the object pool.
The \c{ExtensionSystem::invoke} function template encapsulates
{ExtensionSystem::Invoker} construction for the common case where
the success of the call is not checked.
\code
// In the "provide" plugin A:
namespace PluginA {
class SomeProvider : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE QString doit(const QString &msg, int n) {
{
qDebug() << "I AM DOING IT " << msg;
return QString::number(n);
}
};
} // namespace PluginA
// In the "user" plugin B:
int someFuntionUsingPluginA()
{
using namespace ExtensionSystem;
QObject *target = PluginManager::instance()
->getObjectByClassName("PluginA::SomeProvider");
if (target) {
// Some random argument.
QString msg = "REALLY.";
// Plain function call, no return value.
invoke<void>(target, "doit", msg, 2);
// Plain function with no return value.
qDebug() << "Result: " << invoke<QString>(target, "doit", msg, 21);
// Record success of function call with return value.
Invoker<QString> in1(target, "doit", msg, 21);
qDebug() << "Success: (expected)" << in1.wasSuccessful();
// Try to invoke a non-existing function.
Invoker<QString> in2(target, "doitWrong", msg, 22);
qDebug() << "Success (not expected):" << in2.wasSuccessful();
} else {
// We have to cope with plugin A's absence.
}
};
\endcode
\bold Note: The type of the parameters passed to the \c{invoke()} calls
is deduced from the parameters themselves and must match the type of
the arguments of the called functions \e{exactly}. No conversion or even
integer promotions are applicable, so to invoke a function with a \c{long}
parameter explicitly use \c{long(43)} or such.
\bold Note: The object pool manipulating functions are thread-safe.
*/
...
...
@@ -1095,3 +1165,38 @@ void PluginManagerPrivate::profilingReport(const char *what, const PluginSpec *s
}
}
}
/*!
\fn void PluginManager::getObjectByName()
Retrieves one object with a given name from the object pool.
\sa addObject()
*/
QObject
*
PluginManager
::
getObjectByName
(
const
QString
&
name
)
const
{
QReadLocker
lock
(
&
m_lock
);
QList
<
QObject
*>
all
=
allObjects
();
foreach
(
QObject
*
obj
,
all
)
{
if
(
obj
->
objectName
()
==
name
)
return
obj
;
}
return
0
;
}
/*!
\fn void PluginManager::getObjectByClassName()
Retrieves one object inheriting a class with a given name from the object pool.
\sa addObject()
*/
QObject
*
PluginManager
::
getObjectByClassName
(
const
QString
&
className
)
const
{
const
QByteArray
ba
=
className
.
toUtf8
();
QReadLocker
lock
(
&
m_lock
);
QList
<
QObject
*>
all
=
allObjects
();
foreach
(
QObject
*
obj
,
all
)
{
if
(
obj
->
inherits
(
ba
.
constData
()))
return
obj
;
}
return
0
;
}
src/libs/extensionsystem/pluginmanager.h
View file @
37b9bf84
...
...
@@ -38,8 +38,8 @@
#include <aggregation/aggregate.h>
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QReadWriteLock>
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
class
QTextStream
;
...
...
@@ -95,6 +95,9 @@ public:
return
result
;
}
QObject
*
getObjectByName
(
const
QString
&
name
)
const
;
QObject
*
getObjectByClassName
(
const
QString
&
className
)
const
;
// Plugin operations
QList
<
PluginSpec
*>
loadQueue
();
void
loadPlugins
();
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment