I'm trying to create my own QtCreator Plugin by following this guide.
So I cloned this repo and checked the v2.8.1 tagged commit out (c3ed746c).
Then I copied my QtCreator 2.8.1 directory and created a new Qt Creator Plugin project.
Then I create a new file in my project directory called MyPlugin.json.
If I try to compile my plug in I get this error:
e:\qtprojects\build-myplugin-desktop_qt_5_1_1_msvc2012_32bit-debug\debug../../MyPlugin/mypluginplugin.h(6) : fatal error C1083: Cannot open include file: "extensionsystem/iplugin.h": No such file or directory
jom: E:\QtProjects\build-MyPlugin-Desktop_Qt_5_1_1_MSVC2012_32bit-Debug\Makefile.Debug [debug\moc_mypluginplugin.obj] Error 2
jom: E:\QtProjects\build-MyPlugin-Desktop_Qt_5_1_1_MSVC2012_32bit-Debug\Makefile [debug] Error 2
10:56:51: The process "E:\Qt\Qt5\Tools\QtCreator\bin\jom.exe" exited with code 2.
Error while building/deploying project myplugin (kit: Desktop Qt 5.1.1 MSVC2012 32bit)
When executing step 'Make'
10:56:51: Elapsed time: 00:01.
What do I have to do to make it work?
This are the source files:
myplugin.pro
DEFINES += MYPLUGIN_LIBRARY
# MyPlugin files
SOURCES += mypluginplugin.cpp
HEADERS += mypluginplugin.h \
myplugin_global.h \
mypluginconstants.h
# Qt Creator linking
## set the QTC_SOURCE environment variable to override the setting here
QTCREATOR_SOURCES = $$(QTC_SOURCE)
isEmpty(QTCREATOR_SOURCES):QTCREATOR_SOURCES=E:/QtProjects/_QtCreatorPlugIns/qt-creator
## set the QTC_BUILD environment variable to override the setting here
IDE_BUILD_TREE = $$(QTC_BUILD)
isEmpty(IDE_BUILD_TREE):IDE_BUILD_TREE=E:/QtProjects/_QtCreatorPlugIns/QtCreator
## uncomment to build plugin into user config directory
## <localappdata>/plugins/<ideversion>
## where <localappdata> is e.g.
## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux
## "~/Library/Application Support/QtProject/Qt Creator" on Mac
# USE_USER_DESTDIR = yes
PROVIDER = MyCompany
include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri)
myplugin_global.h
#ifndef MYPLUGIN_GLOBAL_H
#define MYPLUGIN_GLOBAL_H
#include <QtGlobal>
#if defined(MYPLUGIN_LIBRARY)
# define MYPLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYPLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYPLUGIN_GLOBAL_H
mypluginconstants.h
#ifndef MYPLUGINCONSTANTS_H
#define MYPLUGINCONSTANTS_H
namespace MyPlugin {
namespace Constants {
const char ACTION_ID[] = "MyPlugin.Action";
const char MENU_ID[] = "MyPlugin.Menu";
} // namespace MyPlugin
} // namespace Constants
#endif // MYPLUGINCONSTANTS_H
mypluginplugin.h
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include "myplugin_global.h"
#include <extensionsystem/iplugin.h>
namespace MyPlugin {
namespace Internal {
class MyPluginPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "MyPlugin.json")
public:
MyPluginPlugin();
~MyPluginPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
private slots:
void triggerAction();
};
} // namespace Internal
} // namespace MyPlugin
#endif // MYPLUGIN_H
mypluginplugin.cpp
#include "mypluginplugin.h"
#include "mypluginconstants.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>
#include <QtPlugin>
using namespace MyPlugin::Internal;
MyPluginPlugin::MyPluginPlugin()
{
// Create your members
}
MyPluginPlugin::~MyPluginPlugin()
{
// Unregister objects from the plugin manager's object pool
// Delete members
}
bool MyPluginPlugin::initialize(const QStringList &arguments, QString *errorString)
{
// Register objects in the plugin manager's object pool
// Load settings
// Add actions to menus
// Connect to other plugins' signals
// In the initialize method, a plugin can be sure that the plugins it
// depends on have initialized their members.
Q_UNUSED(arguments)
Q_UNUSED(errorString)
QAction *action = new QAction(tr("MyPlugin action"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, SIGNAL(triggered()), this, SLOT(triggerAction()));
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
menu->menu()->setTitle(tr("MyPlugin"));
menu->addAction(cmd);
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
return true;
}
void MyPluginPlugin::extensionsInitialized()
{
// Retrieve objects from the plugin manager's object pool
// In the extensionsInitialized method, a plugin can be sure that all
// plugins that depend on it are completely initialized.
}
ExtensionSystem::IPlugin::ShutdownFlag MyPluginPlugin::aboutToShutdown()
{
// Save settings
// Disconnect from signals that are not needed during shutdown
// Hide UI (if you add UI that is not in the main window directly)
return SynchronousShutdown;
}
void MyPluginPlugin::triggerAction()
{
QMessageBox::information(Core::ICore::mainWindow(),
tr("Action triggered"),
tr("This is an action from MyPlugin."));
}
Q_EXPORT_PLUGIN2(MyPlugin, MyPluginPlugin)
Directories
E:\QtProjects\_QtCreatorPlugIns> tree
├───qt-creator
│ ├───bin
│ ├───dist
│ ├───doc
│ ├───lib
│ ├───qbs
│ ├───scripts
│ ├───share
│ ├───srcn64interrupt
│ └───testsster
├───QtCreator
│ ├───bin
│ ├───lib0
│ └───share
If you're a linux user, you can download qtcreator-dev. But, i don't know how it works on Windows.
Open terminal
Type : sudo apt-get install qtcreator-dev
Done.
Related
I'm trying to write tests for a Qt application in visual studio. I've added a new test project to the existing solution that has the project I'm wanting to test, and added a reference to said project as shown here. When I try to run a test file, I get errors saying 'cannot open source file "x"' for a bunch of Qt and Qt generated files like QWidget and 'ui_x.h' (x is a placeholder). I'm using Google Test, but the same issue occurs when using the 'Native Unit Test Project' option.
Image of problem
Settings.h
#pragma once
#include <string>
#include <QWidget>
#include <QSettings>
#include <QFileDialog>
#include "ui_Settings.h"
extern const std::string MODS_FOLDER_PATH;
extern const std::string PROFILE_PATH;
class Settings : public QWidget
{
Q_OBJECT
public:
Settings(QWidget *parent = Q_NULLPTR, QString testHook = "");
QString getModsFolderPath();
public slots:
void browseProfilePath();
void browseModsPath();
void openSettingsWidget();
signals:
void modsFolderPathChanged(const QString &newPath);
void profilePathChanged();
private:
Ui::Options ui;
QString testHook;
QString fileBrowser(QFileDialog::FileMode fileMode, const std::string = "");
bool changeFileSetting(QLineEdit * const settingInput, const std::string setting, const QString &fileName);
void loadValuesFromSettings();
};
test.cpp
#include "pch.h"
#include "../FileOverwriteManager/Settings.h"
TEST(TestCaseName, TestName) {
EXPECT_EQ(1, 1);
EXPECT_TRUE(true);
}
I had to edit the 'Additional Include Directories' under 'C/C++' in the test project's properties as suggested by user vahancho. If you only include the directories where the .h files are, i.e. C:\Qt\5.10.0\msvc2017_64\include\QtCore for qsettings.h, then it complains like so, so you have to also include one directory higher, i.e. C:\Qt\5.10.0\msvc2017_64\include\
Let's consider an example QML plugin PluginExample (see C++ Plugins for QML) created in the directory $HOME/projects/org/example/PluginExample ($HOME/projects is in QML2_IMPORT_PATH).
pluginexample.pro:
TEMPLATE = lib
TARGET = PluginExample
QT += qml quick
CONFIG += qt plugin
TARGET = $$qtLibraryTarget($$TARGET)
uri = org.example.PluginExample
# Input
SOURCES += \
pluginexample_plugin.cc \
myitem.cc
HEADERS += \
pluginexample_plugin.hh \
myitem.hh
OTHER_FILES = qmldir
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
copy_qmldir.target = $$OUT_PWD/qmldir
copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
QMAKE_EXTRA_TARGETS += copy_qmldir
PRE_TARGETDEPS += $$copy_qmldir.target
}
qmldir.files = qmldir
unix {
installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
qmldir.path = $$installPath
target.path = $$installPath
INSTALLS += target qmldir
}
myitem.hh:
#ifndef MYITEM_H
#define MYITEM_H
#include <QQuickItem>
class MyItem : public QQuickItem
{
Q_OBJECT
Q_DISABLE_COPY(MyItem)
Q_PROPERTY(QString text READ text CONSTANT)
public:
MyItem(QQuickItem *parent = 0);
QString text() const;
~MyItem();
};
#endif // MYITEM_H
myitem.cc:
#include "myitem.hh"
MyItem::MyItem(QQuickItem *parent):
QQuickItem(parent)
{
}
MyItem::~MyItem()
{
}
QString MyItem::text() const
{
return "MyItem";
}
pluginexample_plugin.hh:
#ifndef PLUGINEXAMPLE_PLUGIN_H
#define PLUGINEXAMPLE_PLUGIN_H
#include <QQmlExtensionPlugin>
class PluginExamplePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char *uri);
};
#endif // PLUGINEXAMPLE_PLUGIN_H
pluginexample_plugin.cc:
#include "pluginexample_plugin.hh"
#include "myitem.hh"
#include <qqml.h>
void PluginExamplePlugin::registerTypes(const char *uri)
{
// #uri org.example.PluginExample
qmlRegisterType<MyItem>(uri, 1, 0, "MyItem");
}
qmldir:
module org.example.PluginExample
plugin PluginExample
The most part of the plugin's code was auto-generated by the project wizard.
It builds fine, but when I try to import org.example.PluginExample 1.0 from another project, I get this error:
module "org.example.PluginExample" plugin "PluginExample" not found
How can I fix that? Do I need to specify additional information to build/locate the plugin?
PS. Qt 5.3, Linux x86_64
EDIT 1:
I copied libPluginExample.so from the build directory (build-PluginExample-Desktop_Qt_5_3_0_GCC_64bit-Debug) to the source directory (PluginExample), and the error disappeared. Is this the best solution?
EDIT 2:
To avoid manual copying of the plugin library after each build, the following changes need to be applied to the *.pro file (unix-specific):
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
# ...
unix {
QMAKE_POST_LINK += $(COPY_FILE) $$quote($${OUT_PWD}/lib$${TARGET}.so) $$_PRO_FILE_PWD_
}
}
I'm composing a class which derives from QObject, and I want to export this class into a DLL file so other applications can use it. But I got some mysterious problem here:
The code is shown below:
mydll.h:
#ifndef MYDLL_H
#define MYDLL_H
#include "mydll_global.h"
#include <QObject>
#include <QDebug>
class MYDLLSHARED_EXPORT MyDll : public QObject
{
Q_OBJECT
public:
explicit MyDll(QObject * parent = 0);
void test() const;
};
#endif // MYDLL_H
mydll_global.h:
#ifndef MYDLL_GLOBAL_H
#define MYDLL_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYDLL_LIBRARY)
# define MYDLLSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYDLLSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYDLL_GLOBAL_H
mydll.cpp:
#include "mydll.h"
MyDll::MyDll(QObject * parent) :
QObject(parent)
{
}
void MyDll::test() const {
qDebug() << "Hello from dll!";
}
and the dll is used in another application. The dll is compiled successfully. I've add LIBS += "myDll.dll" in the .pro file of the application using this dll, and I've copied myDll.dll to the working directory of the application.
The compiler reports:
C4273: "MyDll::qt_static_metacall" : inconsistent dll linkage.
C2491: "MyDll::staticMetaObject": definition of dllimport static data member not allowed
What's the problem here?
Your code for mydll_global.h checks whether MYDLL_LIBRARY is defined, but none of the code you have posted defines MYDLL_LIBRARY. Is this declared in a file that you have not shared on the question? If not, you need to add a #define MYDLL_LIBRARY in your build project, or your PCH.
I'm trying to create plugin for Qt Creator, so I simply selected new file or project/Libraries/QtCreator plugin. I've specified the sources for Qt Creator as well as build of Qt Creator. When I've tried to build it I'm getting the following three errors:
*C:\...\mypluginplugin.cpp:20: error:
undefined reference to `vtable for MyPlugin::Internal::MyPluginPlugin'* //this is constructor
*C:\...\mypluginplugin.cpp:25: error:
undefined reference to `vtable for MyPlugin::Internal::MyPluginPlugin'* //this is destructor
C:\...\mypluginplugin.hpp:13: error:
undefined reference to `MyPlugin::Internal::MyPluginPlugin::staticMetaObject' //when I double click
on this error it moves me to my .hpp file to the Q_OBJECT macro:
This is my code:
namespace MyPlugin {
namespace Internal {
class MyPluginPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT// the last, third error moves me here
public:
MyPluginPlugin();
~MyPluginPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
private slots:
void triggerAction();
};
} // namespace Internal
} // namespace MyPlugin
Any idea how to solve this problem?
//EDIT
#include "mypluginplugin.hpp"
#include "mypluginconstants.hpp"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>
#include <QtPlugin>
using namespace MyPlugin::Internal;
MyPluginPlugin::MyPluginPlugin()
{
// Create your members
}
MyPluginPlugin::~MyPluginPlugin()
{
// Unregister objects from the plugin manager's object pool
// Delete members
}
bool MyPluginPlugin::initialize(const QStringList &arguments, QString *errorString)
{
// Register objects in the plugin manager's object pool
// Load settings
// Add actions to menus
// Connect to other plugins' signals
// In the initialize method, a plugin can be sure that the plugins it
// depends on have initialized their members.
Q_UNUSED(arguments)
Q_UNUSED(errorString)
QAction *action = new QAction(tr("MyPlugin action"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, SIGNAL(triggered()), this, SLOT(triggerAction()));
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
menu->menu()->setTitle(tr("MyPlugin"));
menu->addAction(cmd);
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
return true;
}
void MyPluginPlugin::extensionsInitialized()
{
// Retrieve objects from the plugin manager's object pool
// In the extensionsInitialized method, a plugin can be sure that all
// plugins that depend on it are completely initialized.
}
ExtensionSystem::IPlugin::ShutdownFlag MyPluginPlugin::aboutToShutdown()
{
// Save settings
// Disconnect from signals that are not needed during shutdown
// Hide UI (if you add UI that is not in the main window directly)
return SynchronousShutdown;
}
void MyPluginPlugin::triggerAction()
{
QMessageBox::information(Core::ICore::mainWindow(),
tr("Action triggered"),
tr("This is an action from MyPlugin."));
}
Q_EXPORT_PLUGIN2(MyPlugin, MyPluginPlugin)
I figured out what happened. Ok, here is the solution for others - qtcreator simply didn't attach .hpp files to the project, yet there were created. After adding those .hpp files via add existing files, it builds fine now.
I'm trying to use a Singleton Class (its a program-wide debug logger called 'PrisLog') across my Qt Application. The program also has plugins. I want to make my singleton class available to those plugins, but this doesn't work. From what I can tell, trying to use the class in the plugin results in another instance being created.
-The singleton class is just a *.cpp and *.h file, nothing else. I've linked both my main application and the plugin to these files individually... is this the right way to do it?
-I've attached my singleton class's code below, though I think I've created the class correctly. If I use it from within separate classes in my main application, it works as expected (one instance).
EDIT: Linking both the application and plugin to the same static lib (the singleton class) works. Here's how my qmake *.pro files looked:
MySingletonLib.pro
TEMPLATE = lib
CONFIG += staticlib
HEADERS += \
mysingletonlib.h
SOURCES += \
mysingletonlib.cpp
MyPlugin.pro (also incl #include mysingletonlib.h in myplugin.h)
INCLUDEPATH += path/to/MySingletonLib
LIBS += -Lpath/to/MySingletonLib -lMySingletonLib
MyPlugin.pro (also incl #include mysingletonlib.h in myapp.h)
INCLUDEPATH += path/to/MySingletonLib
LIBS += -Lpath/to/MySingletonLib -lMySingletonLib
And the original code:
#ifndef PRISLOG_H
#define PRISLOG_H
#include <QFile>
#include <QDir>
#include <QString>
#include <QMutex>
#include <QDebug>
#include <QMutexLocker>
#include <QTextStream>
#include <QDateTime>
// PrisLog (singleton) class definition
class PrisLog
{
public:
static PrisLog* Instance();
void SetLogsPath(QString);
QString GetLogsPath();
void SetDebugDestination(QString);
void SetElmRxDestination(QString);
void SetElmTxDestination(QString);
void SetDlgDestination(QString);
QTextStream* GetDebugStream();
QTextStream* GetElmRxStream();
QTextStream* GetElmTxStream();
QTextStream* GetDlgStream();
QMutex* GetDebugMutex();
private:
PrisLog(); // private constructor
PrisLog(const PrisLog&); // prevent copy constructor
PrisLog& operator=(const PrisLog&); // prevent assignment
static PrisLog* m_Instance;
static bool m_InitFlag;
QString m_appPath;
QFile m_DebugFile;
QTextStream m_DebugStream;
QMutex m_DebugMutex;
QFile m_ElmRxFile;
QTextStream m_ElmRxStream;
QFile m_ElmTxFile;
QTextStream m_ElmTxStream;
QFile m_DlgFile;
QTextStream m_DlgStream;
};
// thread-UNSAFE writer, but less expensive
// use: single stream <--> single thread!
class PrisLogWriter
{
public:
PrisLogWriter(QTextStream*);
~PrisLogWriter();
QTextStream* m_stream;
};
// thread-UNSAFE writer, but less expensive
// this version does not include any formatting
// use: single stream <--> single thread!
class PrisLogRawWriter
{
public:
PrisLogRawWriter(QTextStream*);
~PrisLogRawWriter();
QTextStream* m_stream;
};
// thread-safe writer
// use: single stream <--> many threads
class PrisLogSafeWriter
{
public:
PrisLogSafeWriter(QTextStream*, QMutex*);
~PrisLogSafeWriter();
QTextStream* m_stream;
private:
QMutex* m_mutex;
};
#define PRISLOGDEBUG (*(PrisLogSafeWriter(PrisLog::Instance()->GetDebugStream(), PrisLog::Instance()->GetDebugMutex()).m_stream))
#define PRISLOGELMRX (*(PrisLogWriter(PrisLog::Instance()->GetElmRxStream()).m_stream))
#define PRISLOGELMTX (*(PrisLogWriter(PrisLog::Instance()->GetElmTxStream()).m_stream))
#define PRISLOGDLG (*(PrisLogRawWriter(PrisLog::Instance()->GetDlgStream()).m_stream))
#endif // PRISLOG_H
I think you should take this class to a statically linked, but separeted shared dll/so.
If your host application does not use this class, the linker simply won't link it into the binary and your plugin could not use it. Additionally: your binary has no library class interface.
You need to make sure, that only one instance exists. The safest is, that the cpp is compiled only once in the overall exe.
To make sure that the other DLLs can call PrisLog::Instance, this class/function (i.e. all public methods if PrisLog) needs to be declared with __declspec(dllexport), even if it is located within the exe.
The DLLs can then dynamically find the object and method.
BTW: Why don't you use the logging from Qt?