1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "widgetpluginpath.h"
35 #include <iwidgetplugin.h>
36 #include <QtCore/QLibrary>
37 #include <QWeakPointer>
38 #include <QtCore/QPluginLoader>
39 #include <QtCore/QFileInfo>
40 #include <QtCore/QLibraryInfo>
41 #include <QtCore/QCoreApplication>
42 #include <QtCore/QObject>
43 #include <QtCore/QSharedData>
48 namespace QmlDesigner {
52 // Initialize and create instance of a plugin from scratch,
53 // that is, make sure the library is loaded and has an instance
54 // of the IPlugin type. Once something fails, mark it as failed
55 // ignore it from then on.
56 static IWidgetPlugin *instance(WidgetPluginData &p)
59 qDebug() << "Loading QmlDesigner plugin" << p.path << "...";
61 // Go stale once something fails
65 // Pull up the plugin, retrieve IPlugin instance.
66 if (!p.instanceGuard) {
68 QPluginLoader loader(p.path);
71 qDebug() << "guard" << p.path;
73 if (!(loader.isLoaded() || loader.load())) {
75 p.errorMessage = QCoreApplication::translate("WidgetPluginManager",
76 "Failed to create instance of file "
77 "'%1': %2").arg(p.path).arg(p.errorMessage);
78 qWarning() << p.errorMessage;
81 QObject *object = loader.instance();
84 p.errorMessage = QCoreApplication::translate("WidgetPluginManager",
85 "Failed to create instance of file '%1'."
87 qWarning() << p.errorMessage;
90 IWidgetPlugin *iplugin = qobject_cast<IWidgetPlugin *>(object);
93 p.errorMessage = QCoreApplication::translate("WidgetPluginManager",
94 "File '%1' is not a QmlDesigner plugin."
96 qWarning() << p.errorMessage;
100 p.instanceGuard = object;
101 p.instance = iplugin;
103 // Ensure it is initialized
104 /*if (!p.instance->isInitialized()) {
105 if (!p.instance->initialize(&p.errorMessage)) {
114 qDebug() << "QmlDesigner plugin" << p.path << "successfully loaded!";
118 WidgetPluginData::WidgetPluginData(const QString &p) :
126 WidgetPluginPath::WidgetPluginPath(const QDir &path) :
132 // Determine a unique list of library files in that directory
133 QStringList WidgetPluginPath::libraryFilePaths(const QDir &dir)
135 const QFileInfoList infoList = dir.entryInfoList(QDir::Files|QDir::Readable|QDir::NoDotAndDotDot);
136 if (infoList.empty())
137 return QStringList();
138 // Load symbolic links but make sure all file names are unique as not
139 // to fall for something like 'libplugin.so.1 -> libplugin.so'
141 const QFileInfoList::const_iterator icend = infoList.constEnd();
142 for (QFileInfoList::const_iterator it = infoList.constBegin(); it != icend; ++it) {
144 if (it->isSymLink()) {
145 const QFileInfo linkTarget = QFileInfo(it->symLinkTarget());
146 if (linkTarget.exists() && linkTarget.isFile())
147 fileName = linkTarget.absoluteFilePath();
149 fileName = it->absoluteFilePath();
151 if (!fileName.isEmpty() && QLibrary::isLibrary(fileName) && !result.contains(fileName))
156 qDebug() << "Library files in directory" << dir << ": " << result;
161 void WidgetPluginPath::clear()
167 void WidgetPluginPath::ensureLoaded()
170 const QStringList libraryFiles = libraryFilePaths(m_path);
172 qDebug() << "Checking " << libraryFiles.size() << " plugins " << m_path.absolutePath();
173 foreach (const QString &libFile, libraryFiles)
174 m_plugins.push_back(WidgetPluginData(libFile));
179 void WidgetPluginPath::getInstances(WidgetPluginManager::IWidgetPluginList *list)
182 // Compile list of instances
183 if (m_plugins.empty())
185 const PluginDataList::iterator end = m_plugins.end();
186 for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it)
187 if (IWidgetPlugin *i = instance(*it))
191 QStandardItem *WidgetPluginPath::createModelItem()
194 // Create a list of plugin lib files with classes.
195 // If there are failed ones, create a separate "Failed"
196 // category at the end
197 QStandardItem *pathItem = new QStandardItem(m_path.absolutePath());
198 QStandardItem *failedCategory = 0;
199 const PluginDataList::iterator end = m_plugins.end();
200 for (PluginDataList::iterator it = m_plugins.begin(); it != end; ++it) {
201 QStandardItem *pluginItem = new QStandardItem(QFileInfo(it->path).fileName());
203 pluginItem->appendRow(new QStandardItem(QString::fromLatin1(it->instanceGuard->metaObject()->className())));
204 pathItem->appendRow(pluginItem);
206 pluginItem->setToolTip(it->errorMessage);
207 if (!failedCategory) {
208 const QString failed = QCoreApplication::translate("PluginManager", "Failed Plugins");
209 failedCategory = new QStandardItem(failed);
211 failedCategory->appendRow(pluginItem);
215 pathItem->appendRow(failedCategory);
219 } // namespace Internal
220 } // namespace QmlDesigner