I am using log4cxx with normal way, which provides a property file for log4cxx. Here we can find a reference:
log4cxx: configuring appender with arguments
Reading Property Info in Log4cxx
But if I want to set log4cxx in my C++ code without property file, what should I do? I check the log4cxx code and try to set properties by log4cxx::helpers::Properties, here is my sample code:
log4cxx::helpers::Properties properties;
properties.setProperty(L"log4j.rootLogger",L"DEBUG");
properties.setProperty(L"log4j.appender",L"ca");
properties.setProperty(L"log4j.appender",L"fa");
properties.setProperty(L"log4j.appender.fa",L"org.apache.log4j.FileAppender");
properties.setProperty(L"log4j.appender.fa.Append",L"false");
properties.setProperty(L"log4j.appender.fa.File",L"./test.log");
properties.setProperty(L"log4j.appender.fa.layout",L"org.apache.log4j.PatternLayout");
properties.setProperty(L"log4j.appender.fa.layout.ConversionPattern",L"%d [%t] %-5p %.16c - %m%n");
properties.setProperty(L"log4j.appender.ca",L"org.apache.log4j.ConsoleAppender");
properties.setProperty(L"log4j.appender.ca.layout",L"log4j.appender.ca.layout");
properties.setProperty(L"log4j.appender.ca.layout.ConversionPattern",L"%d [%t] %-5p %.16c - %m%n");
log4cxx::PropertyConfigurator::configure(properties);
But my sample code doesn't work. Why? Anyone knows how to initialize log4cxx logger without property file?
Thanks
Water Lin
I write a post about this:
http://bigbang.waterlin.org/bang/the-way-to-set-log4cxx-properties-without-using-property-file/
add more reference.
If you want to redirect log to file & console at the same time, please use following code:
#include <log4cxx/logger.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/simplelayout.h>
#include "log4cxx/consoleappender.h"
LoggerPtr logger;
int main() {
log4cxx::FileAppender * fileAppender = new log4cxx::FileAppender(log4cxx::LayoutPtr(new log4cxx::SimpleLayout()), L"logfile", false);
log4cxx::ConsoleAppender * consoleAppender = new log4cxx::ConsoleAppender(log4cxx::LayoutPtr(new log4cxx::SimpleLayout()));
log4cxx::helpers::Pool p;
fileAppender->activateOptions(p);
log4cxx::BasicConfigurator::configure(log4cxx::AppenderPtr(fileAppender));
log4cxx::BasicConfigurator::configure(log4cxx::AppenderPtr(consoleAppender));
log4cxx::Logger::getRootLogger()->setLevel(log4cxx::Level::getDebug());
log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("logger");
LOG4CXX_INFO(logger,"Created FileAppender appender");
return 0;
}
I found the code example in the log4cxx wiki helpful when facing the same challenge.
You can use ByteArrayInputStream to set up log4cxx
std::vector<byte> vc;
// copy property file content into vc
log4cxx::helpers::ByteArrayInputStreamPtr bais(
new log4cxx::helpers::ByteArrayInputStream(vc));
log4cxx::helpers::Properties pp;
pp.load(bais);
log4cxx::PropertyConfigurator::configure(pp);
Related
In the new Qt 5.15.0 there is a new declarative way to register C++ types for usage in QML. I followed the steps given in Qt Help (https://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html#registering-an-instantiable-object-type) but it givens to me the following error:
/.../randomnumbergenerator.h:10: error: ‘QML_ELEMENT’ does not name a type
QML_ELEMENT
^~~~~~~~~~~
The class's definition is, for the moment:
#ifndef RANDOMNUMBERGENERATOR_H
#define RANDOMNUMBERGENERATOR_H
#include <QObject>
#include <QRandomGenerator>
class RandomNumberGenerator : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
explicit RandomNumberGenerator(QObject *parent = nullptr);
signals:
};
#endif // RANDOMNUMBERGENERATOR_H
EDIT: I already added to the .pro file the following:
CONFIG += c++11 qmltypes
QML_IMPORT_NAME = SimpleRng
QML_IMPORT_MAJOR_VERSION = 1
As they point out in the Qt forum you have to include <qml.h> (or <QtQml>)
The preconditions section of the documentation you quoted states that
All the macros mentioned below are available from the qqml.h header. You need to add the following code to the files using them in order to make the macros available:
#include <QtQml/qqml.h>
That seems to be the canonical answer and may avoid the issues that #lateus mentioned in comments.
I have 4 qml files and one main.cpp to load qml file.
Is it possible for me to create 1 dll file for those 4 qml file.
And use it in different application if so how to do that.
As already said, there is no need for embedding qml files only in a library. But of course you have the right to do all you want, even that. I know at least 2 ways to do that:
1. Create binary resource file
Prepare resource file containing qml files and then compile it:
rcc -binary plugin.qrc -o plugin.rcc
Now you can include this file into your application :
QResource::registerResource("plugin.rcc");
and use it as regular qrc file:
QResource::registerResource(qApp->applicationDirPath() + "/plugin.rcc");
QQuickView *view = new QQuickView();
view->setSource(QUrl("qrc:/qml/myfile.qml"));
Here qml/ is prefix in resource file.
2. Shared libraryAnother way is to create a shared library containing the same resource file. For example your plugin's shared library implements following interface:
interface.h
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H
#include <QString>
#include <QObject>
class PluginInterface
{
public:
virtual ~PluginInterface() {}
virtual QByteArray getQML(const QString &name) = 0;
};
#define PluginInterface_iid "org.qt-project.PluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
#endif
and its implementation is:
QByteArray PluginImpl::getQML(const QString &name)
{
QFile file(":/qml/" + name);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return QByteArray();
return file.readAll();
}
Now, in your application you load your plugin and get its resource as a string:
QDir pluginsDir(qApp->applicationDirPath());
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath("plugin.dll"));
QObject *plugin = pluginLoader.instance();
if (plugin) {
PluginInterface *pluginInstance = qobject_cast<PluginInterface *>(plugin);
if (pluginInstance) {
QByteArray content = pluginInstance->getQML("file1.qml");
QQuickView *view = new QQuickView();
QQmlComponent component(view->engine());
component.setData(content, QUrl());
QQuickItem *childItem = qobject_cast<QQuickItem*>(component.create());
childItem->setParentItem(view->contentItem());
QWidget *container = QWidget::createWindowContainer(view);
container->setFocusPolicy(Qt::TabFocus);
ui->verticalLayout->addWidget(container);
}
}
But pay attention, when you deploy your application you anyway have to copy all qml system files, like #QTPATH/qml/QtQml, #QTPATH/qml/QtQuick.2, #QTPATH/qml/QtQuick.2 etc.
Links:
Resource compiler
Same theme
Plugin example
Have a look at the documentation for QML Modules
There are options for QML-only modules, C++ only and mixed mode.
I have 4 qml files and one main.cpp to load qml file.
Is it possible for me to create 1 dll file for those 4 qml file.
And use it in different application if so how to do that.
As already said, there is no need for embedding qml files only in a library. But of course you have the right to do all you want, even that. I know at least 2 ways to do that:
1. Create binary resource file
Prepare resource file containing qml files and then compile it:
rcc -binary plugin.qrc -o plugin.rcc
Now you can include this file into your application :
QResource::registerResource("plugin.rcc");
and use it as regular qrc file:
QResource::registerResource(qApp->applicationDirPath() + "/plugin.rcc");
QQuickView *view = new QQuickView();
view->setSource(QUrl("qrc:/qml/myfile.qml"));
Here qml/ is prefix in resource file.
2. Shared libraryAnother way is to create a shared library containing the same resource file. For example your plugin's shared library implements following interface:
interface.h
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H
#include <QString>
#include <QObject>
class PluginInterface
{
public:
virtual ~PluginInterface() {}
virtual QByteArray getQML(const QString &name) = 0;
};
#define PluginInterface_iid "org.qt-project.PluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
#endif
and its implementation is:
QByteArray PluginImpl::getQML(const QString &name)
{
QFile file(":/qml/" + name);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return QByteArray();
return file.readAll();
}
Now, in your application you load your plugin and get its resource as a string:
QDir pluginsDir(qApp->applicationDirPath());
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath("plugin.dll"));
QObject *plugin = pluginLoader.instance();
if (plugin) {
PluginInterface *pluginInstance = qobject_cast<PluginInterface *>(plugin);
if (pluginInstance) {
QByteArray content = pluginInstance->getQML("file1.qml");
QQuickView *view = new QQuickView();
QQmlComponent component(view->engine());
component.setData(content, QUrl());
QQuickItem *childItem = qobject_cast<QQuickItem*>(component.create());
childItem->setParentItem(view->contentItem());
QWidget *container = QWidget::createWindowContainer(view);
container->setFocusPolicy(Qt::TabFocus);
ui->verticalLayout->addWidget(container);
}
}
But pay attention, when you deploy your application you anyway have to copy all qml system files, like #QTPATH/qml/QtQml, #QTPATH/qml/QtQuick.2, #QTPATH/qml/QtQuick.2 etc.
Links:
Resource compiler
Same theme
Plugin example
Have a look at the documentation for QML Modules
There are options for QML-only modules, C++ only and mixed mode.
I am having problems with launching Nokia's own video player from my application that I just don't seem to be able to solve.
My first attempt included calling
Qt.openUrlExternally(url)
from QML and that seemed to do the trick just fine, except that it opened the browser every time and used it instead of the video-suite (native player).
Next I tried cuteTube -approach where I start new process like this:
QStringList args;
args << url;
QProcess *player = new QProcess();
connect(player, SIGNAL(finished(int, QProcess::ExitStatus)), player, SLOT(deleteLater()));
player->start("/usr/bin/video-suite", args);
That worked, except that it required video-suite to be closed upon calling player->start, otherwise it did nothing.
My third attempt involved starting the video-suite via QDBus, but that didn't work any better:
QList<QVariant> args;
QStringList urls;
urls << url;
args.append(urls);
QDBusMessage message = QDBusMessage::createMethodCall(
"com.nokia.VideoSuite",
"/",
"com.nokia.maemo.meegotouch.VideoSuiteInterface",
"play");
message.setArguments(args);
message.setAutoStartService(true);
QDBusConnection bus = QDBusConnection::sessionBus();
if (bus.isConnected()) {
bus.send(message);
} else {
qDebug() << "Error, QDBus is not connected";
}
The problem with this is that it requires video-suite to be up and running - autoStartService parameter didn't help either. If video-suite isn't running already, the call opens it just fine but, alas, no video starts to play.
Eventually I tried using also VideoSuiteInterface, but even having the program compile with it seemed to be difficult. When I eventually managed to compile and link all relevant libraries, the results didn't differ from option 3 above.
So, is there a way to use either VideoSuiteInterface directly or via DBus so that it would start video playback regardless of the current state of the application?
The solution was actually simpler than I really thought initially; the VideoSuiteInterface -approach worked after all. All it took was to use it properly. Here are the full sources should anyone want to try it themselves.
player.h:
#ifndef PLAYER_H
#define PLAYER_H
#include <QObject>
#include <maemo-meegotouch-interfaces/videosuiteinterface.h>
class Player : public QObject {
Q_OBJECT
private:
VideoSuiteInterface* videosuite;
public:
Player(QObject *parent = 0);
Q_INVOKABLE void play(QString url);
};
#endif // PLAYER_H
player.cpp:
#include "player.h"
#include <QObject>
#include <QStringList>
#include <QtDeclarative>
Player::Player(QObject *parent) : QObject(parent) {}
void Player::play(QString url) {
QList<QVariant> args;
QStringList urls;
urls << url;
args.append(urls);
videosuite = new VideoSuiteInterface();
videosuite->play(urls);
}
In addition you may want to connect some signals to make the UI more responsive, but basically that should do the trick.
Finally, you need to remember to add following to your .pro file and you are good to go:
CONFIG += videosuiteinterface-maemo-meegotouch
I'm developing an application for Symbian S60 phones using the Qt Nokia SDK, which sends requests and receives responses from a webservice in every view i have.
The problem with this, is that it always asks the user to choose a accesspoint.
So what i want is to choose an accesspoint when the application starts, and use that throughout the application.
So i found this example: http://wiki.forum.nokia.com/index.php/How_to_set_default_access_point_using_Qt_Mobility_APIs
but i got following error:
undefined reference to 'QtMobility::QNetworkConfigurationManager::QNetworkConfigurationManager(QObject*)
i'm also getting more of these errors from other classes from QMobillity, like:
undefined reference to 'QtMobility::QNetworkSession::open()
.pro file:
CONFIG += mobility
MOBILITY += bearer
header:
#include <qmobilityglobal.h>
#include <QtNetwork>
#include <QNetworkSession>
#include <QNetworkConfigurationManager>
QTM_USE_NAMESPACE;
cpp file:
QNetworkConfigurationManager manager;
const bool selectIap = (manager.capabilities()& QNetworkConfigurationManager::CanStartAndStopInterfaces);
QNetworkConfiguration defaultIap = manager.defaultConfiguration();
if(!defaultIap.isValid() && (!selectIap && defaultIap.state() != QNetworkConfiguration::Active))
{
qDebug() << "Network access point NOT found";
// let the user know that there is no access point available
msgBox->setText(tr("Error"));
msgBox->setInformativeText(tr("No default access point available"));
msgBox->setStandardButtons(QMessageBox::Ok);
msgBox->setDefaultButton(QMessageBox::Ok);
msgBox->topLevelWidget();
msgBox->exec();
}
else
{
qDebug() << "Network access point found and chosen";
}
session = new QNetworkSession(defaultIap,this);
session->open();
Anyone got an idea of what could be wrong?
Have you tried adding this to the .PRO file?
CONFIG += network