diff --git a/global.pri b/global.pri index 1d1b794fc..8468a7ee1 100644 --- a/global.pri +++ b/global.pri @@ -15,6 +15,8 @@ # Build settings common to all projects in TrikRuntime. # Provides: # CONFIGURATION_SUFFIX variable that shall be consistently used in TARGET and LIBS variables in all projects. +# copyToDestdir function to copy arbitrary files and directories to DESTDIR +# uses function to automatically add a library to INCLUDEPATH and LIBS. CROSS_COMPILE = $$(CROSS_COMPILE) @@ -38,6 +40,11 @@ CONFIG(debug, debug | release) { DESTDIR = $$PWD/bin/$$CONFIGURATION +PROJECT_BASENAME = $$basename(_PRO_FILE_) +PROJECT_NAME = $$section(PROJECT_BASENAME, ".", 0, 0) + +TARGET = $$PROJECT_NAME$$CONFIGURATION_SUFFIX + equals(TEMPLATE, app) { !macx { QMAKE_LFLAGS += -Wl,-O1,-rpath,. @@ -50,11 +57,16 @@ MOC_DIR = .build/$$CONFIGURATION/.moc RCC_DIR = .build/$$CONFIGURATION/.rcc UI_DIR = .build/$$CONFIGURATION/.ui +INCLUDEPATH += $$_PRO_FILE_PWD_ \ + $$_PRO_FILE_PWD_/include/$$PROJECT_NAME \ + unix { target.path = $$[INSTALL_ROOT]/ INSTALLS += target } +GLOBAL_PWD = $$PWD + # Useful function to copy additional files to destination, # from http://stackoverflow.com/questions/3984104/qmake-how-to-copy-a-file-to-the-output defineTest(copyToDestdir) { @@ -77,3 +89,16 @@ defineTest(copyToDestdir) { export(QMAKE_POST_LINK) } + +defineTest(uses) { + LIBS += -L$$DESTDIR + PROJECTS = $$1 + + for(PROJECT, PROJECTS) { + LIBS += -l$$PROJECT$$CONFIGURATION_SUFFIX + INCLUDEPATH += $$GLOBAL_PWD/$$PROJECT/include + } + + export(LIBS) + export(INCLUDEPATH) +} diff --git a/trikCommunicator/trikCommunicator.pro b/trikCommunicator/trikCommunicator.pro index 3062eabbc..ab79aa6ed 100644 --- a/trikCommunicator/trikCommunicator.pro +++ b/trikCommunicator/trikCommunicator.pro @@ -12,29 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -TRIKKERNEL_DIR = ../trikKernel/ -TRIKCONTROL_DIR = ../trikControl/ -TRIKSCRIPTRUNNER_DIR = ../trikScriptRunner/ - -TEMPLATE = lib - -QT += network - -DEFINES += TRIKCOMMUNICATOR_LIBRARY - include(../global.pri) -TARGET = trikCommunicator$$CONFIGURATION_SUFFIX - -INCLUDEPATH = \ - $$PWD \ - $$PWD/include/trikCommunicator \ - $$TRIKSCRIPTRUNNER_DIR/include \ - $$TRIKCONTROL_DIR/include \ - $$TRIKKERNEL_DIR/include \ - -LIBS += -L$$DESTDIR -ltrikScriptRunner$$CONFIGURATION_SUFFIX -ltrikKernel$$CONFIGURATION_SUFFIX - HEADERS += \ $$PWD/include/trikCommunicator/trikCommunicator.h \ $$PWD/src/connection.h \ @@ -42,3 +21,16 @@ HEADERS += \ SOURCES += \ $$PWD/src/trikCommunicator.cpp \ $$PWD/src/connection.cpp \ + +TEMPLATE = lib + +QT += network + +DEFINES += TRIKCOMMUNICATOR_LIBRARY + +uses(trikScriptRunner trikControl trikKernel) + +INCLUDEPATH += \ + ../trikScriptRunner/include/ \ + ../trikControl/include/ \ + ../trikKernel/include/ \ diff --git a/trikControl/include/trikControl/sensor3d.h b/trikControl/include/trikControl/sensor3d.h index 60e4d6832..84f2a7db2 100644 --- a/trikControl/include/trikControl/sensor3d.h +++ b/trikControl/include/trikControl/sensor3d.h @@ -15,14 +15,16 @@ #pragma once #include -#include -#include +#include +#include #include #include "declSpec.h" namespace trikControl { +class Sensor3dWorker; + /// Sensor that returns 3d vector. class TRIKCONTROL_EXPORT Sensor3d : public QObject { @@ -35,20 +37,15 @@ class TRIKCONTROL_EXPORT Sensor3d : public QObject /// @param deviceFile - device file for this sensor. Sensor3d(int min, int max, QString const &deviceFile); + ~Sensor3d(); + public slots: /// Returns current raw reading of a sensor in a form of vector with 3 coordinates. - QVector const &read() const; - -private slots: - /// Updates current reading when new value is ready. - void readFile(); + QVector read() const; private: - QSharedPointer mSocketNotifier; - QVector mReading; - int mDeviceFileDescriptor; - int mMax; - int mMin; + QScopedPointer mSensor3dWorker; + QThread mWorkerThread; }; } diff --git a/trikControl/src/display.cpp b/trikControl/src/display.cpp index 58c78c5f5..3f52e88bd 100644 --- a/trikControl/src/display.cpp +++ b/trikControl/src/display.cpp @@ -33,6 +33,7 @@ Display::Display(QThread &guiThread, const QString &startDirPath) , mGuiWorker(new GuiWorker()) { mGuiWorker->moveToThread(&guiThread); + QMetaObject::invokeMethod(mGuiWorker, "init"); } Display::~Display() diff --git a/trikControl/src/guiWorker.cpp b/trikControl/src/guiWorker.cpp index ae4208244..3b33adf00 100644 --- a/trikControl/src/guiWorker.cpp +++ b/trikControl/src/guiWorker.cpp @@ -30,14 +30,22 @@ using namespace trikControl; GuiWorker::GuiWorker() - : mFontMetrics(mImageWidget.font()) { + +} + +void GuiWorker::init() +{ + mImageLabel.reset(new QLabel()); + mImageWidget.reset(new GraphicsWidget()); + mFontMetrics.reset(new QFontMetrics(mImageWidget->font())); + QHBoxLayout * const layout = new QHBoxLayout(); - mImageLabel.setScaledContents(true); - layout->addWidget(&mImageLabel); - mImageWidget.setLayout(layout); - mImageWidget.setWindowState(Qt::WindowFullScreen); - mImageWidget.setWindowFlags(mImageWidget.windowFlags() | Qt::WindowStaysOnTopHint); + mImageLabel->setScaledContents(true); + layout->addWidget(mImageLabel.data()); + mImageWidget->setLayout(layout); + mImageWidget->setWindowState(Qt::WindowFullScreen); + mImageWidget->setWindowFlags(mImageWidget->windowFlags() | Qt::WindowStaysOnTopHint); resetBackground(); } @@ -45,31 +53,31 @@ void GuiWorker::showImage(QString const &fileName) { if (!mImagesCache.contains(fileName)) { QPixmap pixmap(fileName); - pixmap = pixmap.scaled(mImageWidget.size() - QSize(20, 20), Qt::KeepAspectRatio); + pixmap = pixmap.scaled(mImageWidget->size() - QSize(20, 20), Qt::KeepAspectRatio); mImagesCache.insert(fileName, pixmap); } - mImageLabel.setPixmap(mImagesCache.value(fileName)); - mImageWidget.show(); + mImageLabel->setPixmap(mImagesCache.value(fileName)); + mImageWidget->show(); } void GuiWorker::addLabel(QString const &text, int x, int y) { QLabel *label = findLabel(x, y); - label = label ? label : new QLabel(&mImageWidget); + label = label ? label : new QLabel(mImageWidget.data()); label->setText(text); - label->setStyleSheet(QString("color: %1").arg(mImageWidget.currentPenColor().name())); + label->setStyleSheet(QString("color: %1").arg(mImageWidget->currentPenColor().name())); // There is no layout for the label, so its size cannot be set automatically. We set // it with QFontMetrics. - label->setGeometry(x, y, mFontMetrics.width(text), mFontMetrics.height()); + label->setGeometry(x, y, mFontMetrics->width(text), mFontMetrics->height()); label->show(); if (!mLabels.contains(x ^ y, label)) { mLabels.insertMulti(x ^ y, label); } - mImageWidget.show(); + mImageWidget->show(); } void GuiWorker::removeLabels() @@ -89,7 +97,7 @@ void GuiWorker::deleteWorker() void GuiWorker::setBackground(QString const &color) { - QPalette palette = mImageWidget.palette(); + QPalette palette = mImageWidget->palette(); if (color == tr("white")) { palette.setColor(QPalette::Window, Qt::white); @@ -129,41 +137,41 @@ void GuiWorker::setBackground(QString const &color) palette.setColor(QPalette::Window, QColor(color)); } - mImageWidget.setPalette(palette); - mImageWidget.show(); + mImageWidget->setPalette(palette); + mImageWidget->show(); } void GuiWorker::resetBackground() { - QPalette palette = mImageWidget.palette(); + QPalette palette = mImageWidget->palette(); palette.setColor(QPalette::Window, Qt::lightGray); - mImageWidget.setPalette(palette); + mImageWidget->setPalette(palette); } void GuiWorker::setPainterColor(QString const &color) { - mImageWidget.setPainterColor(color); + mImageWidget->setPainterColor(color); } void GuiWorker::setPainterWidth(int penWidth) { - mImageWidget.setPainterWidth(penWidth); + mImageWidget->setPainterWidth(penWidth); } void GuiWorker::clear() { - mImageWidget.deleteAllItems(); - mImageWidget.setPainterColor("black"); - mImageWidget.setPainterWidth(0); - mImageWidget.hide(); + mImageWidget->deleteAllItems(); + mImageWidget->setPainterColor("black"); + mImageWidget->setPainterWidth(1); + mImageWidget->hide(); removeLabels(); - mImageLabel.setPixmap(QPixmap()); + mImageLabel->setPixmap(QPixmap()); resetBackground(); } void GuiWorker::hide() { - mImageWidget.hide(); + mImageWidget->hide(); } QLabel *GuiWorker::findLabel(int x, int y) const @@ -179,35 +187,35 @@ QLabel *GuiWorker::findLabel(int x, int y) const void GuiWorker::drawPoint(int x, int y) { - mImageWidget.drawPoint(x, y); - mImageWidget.update(); - mImageWidget.show(); + mImageWidget->drawPoint(x, y); + mImageWidget->update(); + mImageWidget->show(); } void GuiWorker::drawLine(int x1, int y1, int x2, int y2) { - mImageWidget.drawLine(x1, y1, x2, y2); - mImageWidget.update(); - mImageWidget.show(); + mImageWidget->drawLine(x1, y1, x2, y2); + mImageWidget->update(); + mImageWidget->show(); } void GuiWorker::drawRect(int x, int y, int width, int height) { - mImageWidget.drawRect(x, y, width, height); - mImageWidget.update(); - mImageWidget.show(); + mImageWidget->drawRect(x, y, width, height); + mImageWidget->update(); + mImageWidget->show(); } void GuiWorker::drawEllipse(int x, int y, int width, int height) { - mImageWidget.drawEllipse(x, y, width, height); - mImageWidget.update(); - mImageWidget.show(); + mImageWidget->drawEllipse(x, y, width, height); + mImageWidget->update(); + mImageWidget->show(); } void GuiWorker::drawArc(int x, int y, int width, int height, int startAngle, int spanAngle) { - mImageWidget.drawArc(x, y, width, height, startAngle, spanAngle); - mImageWidget.update(); - mImageWidget.show(); + mImageWidget->drawArc(x, y, width, height, startAngle, spanAngle); + mImageWidget->update(); + mImageWidget->show(); } diff --git a/trikControl/src/guiWorker.h b/trikControl/src/guiWorker.h index b528e5302..caaf5e0ef 100644 --- a/trikControl/src/guiWorker.h +++ b/trikControl/src/guiWorker.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -109,17 +110,20 @@ public slots: /// @param spanAngle - end andle. void drawArc(int x, int y, int width, int height, int startAngle, int spanAngle); + /// Initializes widget. Shall be called when widget is moved to correct thread. Not supposed to be called from .qts. + void init(); + private: void resetBackground(); /// Returns existing label with given coordinates or NULL if no such label exists. QLabel *findLabel(int x, int y) const; - GraphicsWidget mImageWidget; - QLabel mImageLabel; + QScopedPointer mImageWidget; + QScopedPointer mImageLabel; QHash mImagesCache; QMultiHash mLabels; // Has ownership. - QFontMetrics mFontMetrics; + QScopedPointer mFontMetrics; }; } diff --git a/trikControl/src/linux/sensor3d.cpp b/trikControl/src/linux/sensor3dWorker.cpp similarity index 80% rename from trikControl/src/linux/sensor3d.cpp rename to trikControl/src/linux/sensor3dWorker.cpp index 3f4561288..b4a6b3d0e 100644 --- a/trikControl/src/linux/sensor3d.cpp +++ b/trikControl/src/linux/sensor3dWorker.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013 Matvey Bryksin, Yurii Litvinov +/* Copyright 2014 CyberTech Labs Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "sensor3d.h" +#include "src/sensor3dWorker.h" #include @@ -28,7 +28,7 @@ using namespace trikControl; -Sensor3d::Sensor3d(int min, int max, const QString &controlFile) +Sensor3dWorker::Sensor3dWorker(int min, int max, const QString &controlFile) : mDeviceFileDescriptor(0) , mMax(max) , mMin(min) @@ -41,7 +41,7 @@ Sensor3d::Sensor3d(int min, int max, const QString &controlFile) return; } - mSocketNotifier = QSharedPointer( + mSocketNotifier.reset( new QSocketNotifier(mDeviceFileDescriptor, QSocketNotifier::Read, this) ); @@ -49,7 +49,7 @@ Sensor3d::Sensor3d(int min, int max, const QString &controlFile) mSocketNotifier->setEnabled(true); } -void Sensor3d::readFile() +void Sensor3dWorker::readFile() { struct input_event event; int size = 0; @@ -63,13 +63,19 @@ void Sensor3d::readFile() case EV_ABS: switch (event.code) { case ABS_X: + mLock.lockForWrite(); mReading[0] = event.value; + mLock.unlock(); break; case ABS_Y: + mLock.lockForWrite(); mReading[1] = event.value; + mLock.unlock(); break; case ABS_Z: + mLock.lockForWrite(); mReading[2] = event.value; + mLock.unlock(); break; } break; @@ -78,7 +84,6 @@ void Sensor3d::readFile() } } - if (0 <= size && size < static_cast(sizeof(event))) { qDebug() << "incomplete data read"; } @@ -86,7 +91,10 @@ void Sensor3d::readFile() mSocketNotifier->setEnabled(true); } -QVector const &Sensor3d::read() const +QVector Sensor3dWorker::read() { - return mReading; + mLock.lockForRead(); + QVector const result = mReading; + mLock.unlock(); + return result; } diff --git a/trikControl/src/sensor3d.cpp b/trikControl/src/sensor3d.cpp new file mode 100644 index 000000000..6a0ffcfe2 --- /dev/null +++ b/trikControl/src/sensor3d.cpp @@ -0,0 +1,38 @@ +/* Copyright 2013-2014 Matvey Bryksin, Yurii Litvinov, CyberTech Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + +#include "sensor3d.h" + +#include "src/sensor3dWorker.h" + +using namespace trikControl; + +Sensor3d::Sensor3d(int min, int max, const QString &controlFile) + : mSensor3dWorker(new Sensor3dWorker(min, max, controlFile)) +{ + mSensor3dWorker->moveToThread(&mWorkerThread); + mWorkerThread.start(); +} + + +Sensor3d::~Sensor3d() +{ + mWorkerThread.quit(); + mWorkerThread.wait(); +} + +QVector Sensor3d::read() const +{ + return mSensor3dWorker->read(); +} diff --git a/trikControl/src/sensor3dWorker.h b/trikControl/src/sensor3dWorker.h new file mode 100644 index 000000000..0506c68b3 --- /dev/null +++ b/trikControl/src/sensor3dWorker.h @@ -0,0 +1,55 @@ +#pragma once + +/* Copyright 2014 CyberTech Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + +#include +#include +#include +#include +#include + +namespace trikControl { + +/// Handles events from sensor, intended to work in separate thread +class Sensor3dWorker : public QObject +{ + Q_OBJECT + +public: + /// Constructor. + /// @param min - minimal actual (physical) value returned by sensor. Used to normalize returned values. + /// @param max - maximal actual (physical) value returned by sensor. Used to normalize returned values. + /// @param deviceFile - device file for this sensor. + Sensor3dWorker(int min, int max, QString const &deviceFile); + +public slots: + /// Returns current raw reading of a sensor in a form of vector with 3 coordinates. + QVector read(); + +private slots: + /// Updates current reading when new value is ready. + void readFile(); + +private: + QScopedPointer mSocketNotifier; + QVector mReading; + int mDeviceFileDescriptor; + int mMax; + int mMin; + QReadWriteLock mLock; +}; + + +} diff --git a/trikControl/trikControl.pro b/trikControl/trikControl.pro index c534a3156..45c27963b 100644 --- a/trikControl/trikControl.pro +++ b/trikControl/trikControl.pro @@ -12,30 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -TEMPLATE = lib - -DEFINES += TRIKCONTROL_LIBRARY - -QT += xml gui network - -if (equals(QT_MAJOR_VERSION, 5)) { - QT += widgets -} - include(../global.pri) -copyToDestdir( \ - $$PWD/config.xml \ - $$PWD/config_capture.xml \ - $$PWD/../media/ \ -) - -TARGET = trikControl$$CONFIGURATION_SUFFIX - -INCLUDEPATH = \ - $$PWD \ - $$PWD/include/trikControl \ - win32 { PLATFORM = windows } else { @@ -58,42 +36,60 @@ HEADERS += \ $$PWD/include/trikControl/pwmCapture.h \ $$PWD/include/trikControl/motor.h \ $$PWD/include/trikControl/cameraLineDetectorSensor.h \ - $$PWD/src/cameraLineDetectorSensorWorker.h \ - $$PWD/src/powerMotor.h \ - $$PWD/src/servoMotor.h \ $$PWD/src/angularServoMotor.h \ - $$PWD/src/continiousRotationServoMotor.h \ + $$PWD/src/cameraLineDetectorSensorWorker.h \ $$PWD/src/configurer.h \ - $$PWD/src/i2cCommunicator.h \ + $$PWD/src/continiousRotationServoMotor.h \ + $$PWD/src/graphicsWidget.h \ $$PWD/src/guiWorker.h \ - $$PWD/src/tcpConnector.h \ + $$PWD/src/i2cCommunicator.h \ $$PWD/src/keysWorker.h \ - $$PWD/src/graphicsWidget.h + $$PWD/src/powerMotor.h \ + $$PWD/src/sensor3dWorker.h \ + $$PWD/src/servoMotor.h \ + $$PWD/src/tcpConnector.h \ SOURCES += \ $$PWD/src/analogSensor.cpp \ + $$PWD/src/angularServoMotor.cpp \ $$PWD/src/battery.cpp \ $$PWD/src/brick.cpp \ $$PWD/src/cameraLineDetectorSensor.cpp \ $$PWD/src/configurer.cpp \ + $$PWD/src/continiousRotationServoMotor.cpp \ $$PWD/src/digitalSensor.cpp \ $$PWD/src/display.cpp \ $$PWD/src/encoder.cpp \ $$PWD/src/gamepad.cpp \ + $$PWD/src/graphicsWidget.cpp \ $$PWD/src/guiWorker.cpp \ $$PWD/src/keys.cpp \ $$PWD/src/led.cpp \ $$PWD/src/powerMotor.cpp \ + $$PWD/src/pwmCapture.cpp \ + $$PWD/src/sensor3d.cpp \ $$PWD/src/servoMotor.cpp \ - $$PWD/src/angularServoMotor.cpp \ - $$PWD/src/continiousRotationServoMotor.cpp \ $$PWD/src/tcpConnector.cpp \ - $$PWD/src/pwmCapture.cpp \ $$PWD/src/$$PLATFORM/cameraLineDetectorSensorWorker.cpp \ $$PWD/src/$$PLATFORM/i2cCommunicator.cpp \ $$PWD/src/$$PLATFORM/keysWorker.cpp \ - $$PWD/src/$$PLATFORM/sensor3d.cpp \ - $$PWD/src/graphicsWidget.cpp + $$PWD/src/$$PLATFORM/sensor3dWorker.cpp \ OTHER_FILES += \ config.xml \ + +TEMPLATE = lib + +DEFINES += TRIKCONTROL_LIBRARY + +QT += xml gui network + +if (equals(QT_MAJOR_VERSION, 5)) { + QT += widgets +} + +copyToDestdir( \ + $$PWD/config.xml \ + $$PWD/config_capture.xml \ + $$PWD/../media/ \ +) diff --git a/trikGui/controller.cpp b/trikGui/controller.cpp index 55b7fbce6..6fdd82a84 100644 --- a/trikGui/controller.cpp +++ b/trikGui/controller.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include "runningWidget.h" using namespace trikGui; @@ -47,7 +49,7 @@ void Controller::runFile(QString const &filePath) QFileInfo const fileInfo(filePath); if (fileInfo.suffix() == "qts" || fileInfo.suffix() == "js") { scriptExecutionFromFileStarted(fileInfo.baseName()); - mScriptRunner.runFromFile(fileInfo.canonicalFilePath()); + mScriptRunner.run(trikKernel::FileUtils::readFromFile(fileInfo.canonicalFilePath())); } else if (fileInfo.suffix() == "wav" || fileInfo.suffix() == "mp3") { mRunningWidget = new RunningWidget(fileInfo.baseName(), *this); mRunningWidget->show(); @@ -74,7 +76,9 @@ void Controller::scriptExecutionCompleted() if (mRunningWidget) { mRunningWidget->releaseKeyboard(); mRunningWidget->close(); - delete mRunningWidget; + + // Here we can be inside handler of mRunningWidget key press event. + mRunningWidget->deleteLater(); mRunningWidget = NULL; } } diff --git a/trikGui/trikGui.pro b/trikGui/trikGui.pro index 68096dd03..a860506c5 100644 --- a/trikGui/trikGui.pro +++ b/trikGui/trikGui.pro @@ -12,10 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -TRIKCONTROL_DIR = ../trikControl/ -TRIKCOMMUNICATOR_DIR = ../trikCommunicator/ -TRIKSCRIPTRUNNER_DIR = ../trikScriptRunner/ -TRIKWIFI_DIR = ../trikWiFi/ +include(../global.pri) HEADERS += \ $$PWD/fileManagerWidget.h \ @@ -59,6 +56,8 @@ SOURCES += \ TRANSLATIONS = trikGui_ru.ts RESOURCES = trikGui.qrc +copyToDestdir(wpa-config.xml) + TEMPLATE = app QT += network @@ -67,20 +66,11 @@ if (equals(QT_MAJOR_VERSION, 5)) { QT += widgets } -include(../global.pri) - -copyToDestdir(wpa-config.xml) - -INCLUDEPATH = \ - $$PWD \ - $$TRIKCOMMUNICATOR_DIR/include \ - $$TRIKSCRIPTRUNNER_DIR/include \ - $$TRIKWIFI_DIR/include \ - $$TRIKCONTROL_DIR/include \ +uses(trikKernel trikControl trikCommunicator trikScriptRunner trikWiFi) -LIBS += \ - -L$$DESTDIR \ - -ltrikCommunicator$$CONFIGURATION_SUFFIX \ - -ltrikScriptRunner$$CONFIGURATION_SUFFIX \ - -ltrikWiFi$$CONFIGURATION_SUFFIX \ - -ltrikControl$$CONFIGURATION_SUFFIX \ +INCLUDEPATH += \ + ../trikKernel/include/ \ + ../trikControl/include/ \ + ../trikCommunicator/include/ \ + ../trikScriptRunner/include/ \ + ../trikWiFi/include/ \ diff --git a/trikKernel/include/trikKernel/debug.h b/trikKernel/include/trikKernel/debug.h new file mode 100644 index 000000000..bba53be60 --- /dev/null +++ b/trikKernel/include/trikKernel/debug.h @@ -0,0 +1,45 @@ +#pragma once + +/* Copyright 2014 CyberTech Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + +#include +#include +#include +#include +#include + +namespace trikKernel { + +/// Debug helper that logs function entry and exit. +class Debugger : public QObject +{ + Q_OBJECT + +public: + /// Constructor. + /// @param methodName - name of a method to be logged + Debugger(QString const &methodName); + + ~Debugger(); + +private: + QString const mMethodName; + static QHash mIndent; +}; + +} + +/// Macro to log method entry and exit. +#define L trikKernel::Debugger const debugger(Q_FUNC_INFO) diff --git a/trikKernel/include/trikKernel/fileUtils.h b/trikKernel/include/trikKernel/fileUtils.h index 9ccf15701..bfd6599ae 100644 --- a/trikKernel/include/trikKernel/fileUtils.h +++ b/trikKernel/include/trikKernel/fileUtils.h @@ -1,3 +1,5 @@ +#pragma once + /* Copyright 2013 - 2014 Yurii Litvinov, CyberTech Labs Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,8 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#pragma once - #include namespace trikKernel { diff --git a/trikKernel/src/debug.cpp b/trikKernel/src/debug.cpp new file mode 100644 index 000000000..f1f93c66d --- /dev/null +++ b/trikKernel/src/debug.cpp @@ -0,0 +1,44 @@ +/* Copyright 2014 CyberTech Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + +#include "debug.h" + +using namespace trikKernel; + +QHash Debugger::mIndent; + +Debugger::Debugger(QString const &methodName) + : mMethodName(methodName) +{ + QString const indent(mIndent[thread()], ' '); + QString const str = QString("%1(Thread %2) Entering %3") + .arg(indent) + .arg(reinterpret_cast(thread())) + .arg(mMethodName); + + qDebug() << str.toStdString().c_str(); + ++mIndent[thread()]; +} + +Debugger::~Debugger() +{ + --mIndent[thread()]; + QString const indent(mIndent[thread()], ' '); + QString const str = QString("%1(Thread %2) Exiting %3") + .arg(indent) + .arg(reinterpret_cast(thread())) + .arg(mMethodName); + + qDebug() << str.toStdString().c_str(); +} diff --git a/trikKernel/trikKernel.pro b/trikKernel/trikKernel.pro index 60b16b093..8fb265ec3 100644 --- a/trikKernel/trikKernel.pro +++ b/trikKernel/trikKernel.pro @@ -12,20 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -TEMPLATE = lib - -DEFINES += TRIKKERNEL_LIBRARY - include(../global.pri) -TARGET = trikKernel$$CONFIGURATION_SUFFIX - -INCLUDEPATH = \ - $$PWD \ - $$PWD/include/trikKernel \ - HEADERS += \ $$PWD/include/trikKernel/fileUtils.h \ + $$PWD/include/trikKernel/debug.h \ SOURCES += \ $$PWD/src/fileUtils.cpp \ + $$PWD/src/debug.cpp \ + +TEMPLATE = lib + +DEFINES += TRIKKERNEL_LIBRARY diff --git a/trikRun/main.cpp b/trikRun/main.cpp index 390596bce..d2cf6741a 100644 --- a/trikRun/main.cpp +++ b/trikRun/main.cpp @@ -25,6 +25,7 @@ #include #include +#include #include void printUsage() @@ -101,7 +102,7 @@ int main(int argc, char *argv[]) return 1; } - runner.runFromFile(args[1]); + runner.run(trikKernel::FileUtils::readFromFile(args[1])); } return app.exec(); diff --git a/trikRun/trikRun.pro b/trikRun/trikRun.pro index 1a5598ede..31bf23d35 100644 --- a/trikRun/trikRun.pro +++ b/trikRun/trikRun.pro @@ -12,14 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +include(../global.pri) + SOURCES += \ $$PWD/main.cpp \ OTHER_FILES += \ $$PWD/test.qts \ -TRIKCONTROL_DIR = ../trikControl/ -TRIKSCRIPTRUNNER_DIR = ../trikScriptRunner/ +copyToDestdir($$OTHER_FILES) + +uses(trikKernel trikControl trikScriptRunner) + +INCLUDEPATH += \ + ../trikKernel/include/ \ + ../trikControl/include/ \ + ../trikScriptRunner/include/ \ TEMPLATE = app CONFIG += console @@ -29,13 +37,3 @@ QT += gui if (equals(QT_MAJOR_VERSION, 5)) { QT += widgets } - -include(../global.pri) - -copyToDestdir(test.qts) - -INCLUDEPATH = \ - $$PWD \ - $$TRIKSCRIPTRUNNER_DIR/include \ - -LIBS += -L$$DESTDIR -ltrikScriptRunner$$CONFIGURATION_SUFFIX diff --git a/trikRuntime.pro b/trikRuntime.pro index 3f168aa59..648e69c03 100644 --- a/trikRuntime.pro +++ b/trikRuntime.pro @@ -26,6 +26,6 @@ SUBDIRS = \ trikScriptRunner.depends = trikControl trikKernel trikCommunicator.depends = trikScriptRunner -trikRun.depends = trikScriptRunner +trikRun.depends = trikScriptRunner trikKernel trikServer.depends = trikCommunicator -trikGui.depends = trikCommunicator trikScriptRunner trikWiFi +trikGui.depends = trikCommunicator trikScriptRunner trikWiFi trikKernel diff --git a/trikScriptRunner/include/trikScriptRunner/trikScriptRunner.h b/trikScriptRunner/include/trikScriptRunner/trikScriptRunner.h index 7ae4870cd..0495cf5b7 100644 --- a/trikScriptRunner/include/trikScriptRunner/trikScriptRunner.h +++ b/trikScriptRunner/include/trikScriptRunner/trikScriptRunner.h @@ -35,42 +35,33 @@ class TrikScriptRunner : public QObject ~TrikScriptRunner(); public slots: - /// Executes given script asynchronously. If some script is already executing, it will be aborted. + /// Executes given script asynchronously. If some script is already executing, it will be aborted (but no + /// completed() signal will be sent for it). Execution state will be reset (and robot fully stopped) before and + /// after script execution. For event-driven mode (where script has brick.run() command) script counts as finished + /// when it requests to quit by itself or was aborted. When script is finished, completed() signal will be emitted. /// @param script - script in Qt Script language to be executed. void run(QString const &script); - /// Reads a script from given file and asynchronously executes it. If some script is already executing, it will be - /// aborted. - /// @param fileName - name of a file with script. - void runFromFile(QString const &fileName); + /// Executes given script as direct command, so it will use existing script execution environment (or create one + /// if needed) and will not reset execution state before or after execution. Sequence of direct commands counts + /// as finished when one of them directly requests to quit (by brick.quit() command), then robot will be stopped, + /// execution state will reset and completed() signal will be emitted. + /// @param command - script in Qt Script to be executed as direct command. + void runDirectCommand(QString const &command); - /// Aborts script execution. + /// Aborts script execution. completed() signal will be emitted when script will be actually aborted, robot will + /// be stopped and execution state will be reset. Note that direct commands and scripts in event-driven mode will + /// be stopped as well. void abort(); - /// Returns true if a system is in event-driven running mode, so it shall wait for events when script is executed. - /// If it is false, script will exit immediately. - bool isInEventDrivenMode() const; - signals: - /// Fired when current script completes execution. + /// Emitted when current script completes execution (for event-driven mode it means that script requested to quit + /// or was aborted). void completed(); -private slots: - /// Called when script runner reports that it has finished execution. Used to stop robot. - void onScriptExecutionCompleted(); - private: - enum State { - idle - , running - , stopping - }; - /// Proxy for script engine thread. QScopedPointer mScriptRunnerProxy; - - /// Execution state of a runner. - State mExecutionState; }; } diff --git a/trikScriptRunner/src/scriptEngineWorker.cpp b/trikScriptRunner/src/scriptEngineWorker.cpp index ae77a9f73..fb2648d45 100644 --- a/trikScriptRunner/src/scriptEngineWorker.cpp +++ b/trikScriptRunner/src/scriptEngineWorker.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013 Yurii Litvinov +/* Copyright 2013 - 2014 Yurii Litvinov, CyberTech Labs Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,11 @@ #include #include +#include #include +#include + #include #include #include @@ -43,84 +46,75 @@ Q_DECLARE_METATYPE(Motor*) Q_DECLARE_METATYPE(Sensor*) Q_DECLARE_METATYPE(Sensor3d*) Q_DECLARE_METATYPE(CameraLineDetectorSensor*) +Q_DECLARE_METATYPE(QVector) -ScriptEngineWorker::ScriptEngineWorker(QString const &configFilePath, const QString &startDirPath) +ScriptEngineWorker::ScriptEngineWorker(QString const &configFilePath, QString const &startDirPath) : mEngine(NULL) - , mBrick(*this->thread(), configFilePath, startDirPath) + , mConfigFilePath(configFilePath) , mStartDirPath(startDirPath) + , mGuiThread(this->thread()) { - connect(&mBrick, SIGNAL(quitSignal()), this, SLOT(onScriptRequestingToQuit())); } -void ScriptEngineWorker::run(QString const &script) +void ScriptEngineWorker::reset() { - if (mEngine != NULL) { - if (mEngine->isEvaluating()) { - mEngine->abortEvaluation(); - } - - // Here we can safely delete mEngine, we're not in its stack. There's no way to call run() from Qt Script. - delete mEngine; - } - - initScriptEngine(); + Q_ASSERT(mEngine); - QScriptValue brickProxy = mEngine->newQObject(&mBrick); - mEngine->globalObject().setProperty("brick", brickProxy); - - if (QFile::exists(mStartDirPath + "system.js")) { - runAndReportException(trikKernel::FileUtils::readFromFile(mStartDirPath + "system.js")); - } + mEngine->abortEvaluation(); - runAndReportException(script); + QMetaObject::invokeMethod(this, "resetScriptEngine", Qt::QueuedConnection); - if (!mBrick.isInEventDrivenMode()) { + if (mBrick->isInEventDrivenMode()) { + mBrick->stop(); emit completed(); } } -void ScriptEngineWorker::abort() +void ScriptEngineWorker::init() { - if (mEngine != NULL) { - mEngine->abortEvaluation(); - - // We need to delete script engine to clear possible connections from inside Qt Script, but we can't do that - // right now because we can be in mEngine's call stack. Also we can not invoke it directly since we can be in - // another thread and deleting it on return to that thread's event loop will surely crash worker, and Qt docs - // are not clear whether deleteLater implementation is aware of that problem. - QMetaObject::invokeMethod(mEngine, "deleteLater"); - } + mBrick.reset(new Brick(*mGuiThread, mConfigFilePath, mStartDirPath)); + connect(mBrick.data(), SIGNAL(quitSignal()), this, SLOT(onScriptRequestingToQuit())); + + resetScriptEngine(); } -bool ScriptEngineWorker::isRunning() const +void ScriptEngineWorker::run(QString const &script, bool inEventDrivenMode) { - if (mEngine == NULL) { - return false; - } else { - return mEngine->isEvaluating(); + Q_ASSERT(mEngine); + + if (inEventDrivenMode) { + mBrick->run(); } -} -bool ScriptEngineWorker::isInEventDrivenMode() const -{ - return mBrick.isInEventDrivenMode(); + runAndReportException(script); + + if (!mBrick->isInEventDrivenMode()) { + mBrick->stop(); + resetScriptEngine(); + emit completed(); + } } void ScriptEngineWorker::onScriptRequestingToQuit() { - abort(); + if (!mBrick->isInEventDrivenMode()) { + // Somebody erroneously called brick.quit() before entering event loop, so we must force event loop for brick + // and only then quit, to send properly completed() signal. + mBrick->run(); + } - /// @todo Completed will be already sent by run() after abortExecution? - emit completed(); + reset(); } -void ScriptEngineWorker::initScriptEngine() +void ScriptEngineWorker::resetScriptEngine() { - mEngine = new QScriptEngine(); + if (mEngine) { + mEngine->deleteLater(); + } - connect(mEngine, SIGNAL(destroyed()), this, SLOT(onScriptEngineDestroyed())); + mEngine = new QScriptEngine(); - mBrick.reset(); + mBrick->reset(); qScriptRegisterMetaType(mEngine, batteryToScriptValue, batteryFromScriptValue); qScriptRegisterMetaType(mEngine, displayToScriptValue, displayFromScriptValue); @@ -132,13 +126,16 @@ void ScriptEngineWorker::initScriptEngine() qScriptRegisterMetaType(mEngine, sensorToScriptValue, sensorFromScriptValue); qScriptRegisterMetaType(mEngine, sensor3dToScriptValue, sensor3dFromScriptValue); qScriptRegisterMetaType(mEngine, cameraLineDetectorSensorToScriptValue, cameraLineDetectorSensorFromScriptValue); + qScriptRegisterSequenceMetaType >(mEngine); - mEngine->setProcessEventsInterval(1); -} + QScriptValue brickProxy = mEngine->newQObject(mBrick.data()); + mEngine->globalObject().setProperty("brick", brickProxy); -void ScriptEngineWorker::onScriptEngineDestroyed() -{ - mEngine = NULL; + if (QFile::exists(mStartDirPath + "system.js")) { + runAndReportException(trikKernel::FileUtils::readFromFile(mStartDirPath + "system.js")); + } + + mEngine->setProcessEventsInterval(1); } void ScriptEngineWorker::runAndReportException(QString const &script) diff --git a/trikScriptRunner/src/scriptEngineWorker.h b/trikScriptRunner/src/scriptEngineWorker.h index dcd9f24a9..36d5a9f08 100644 --- a/trikScriptRunner/src/scriptEngineWorker.h +++ b/trikScriptRunner/src/scriptEngineWorker.h @@ -36,43 +36,43 @@ class ScriptEngineWorker : public QObject /// @param startDirPath - path to the directory from which the application was executed. ScriptEngineWorker(QString const &configFilePath, QString const &startDirPath); - /// Returns true, if script engine is initialized and running. - bool isRunning() const; - - /// Aborts script execution. - void abort(); - - /// Returns true if a system is in event-driven running mode, so it shall wait for events when script is executed. - /// If it is false, script will exit immediately. - bool isInEventDrivenMode() const; + /// Stops script execution and resets execution state (including script engine and trikControl itself). Can be + /// called from another thread. + void reset(); signals: - /// Fired when current script execution completed. + /// Emitted when current script execution is completed or is aborted by reset() call. void completed(); public slots: + /// Initializes script engine and creates its own trikControl instance. + void init(); + /// Executes given script. - void run(QString const &script); + /// @param script - script to execute. + /// @param inEventDrivenMode - shall this script be executed in event-driven mode, i.e. not emit completed() signal + /// when it is finished. + void run(QString const &script, bool inEventDrivenMode); private slots: /// Abort script execution. void onScriptRequestingToQuit(); - /// Do cleanup when script engine finally is deleted. - void onScriptEngineDestroyed(); + /// Kill old script engine, create and reinit a new one. + void resetScriptEngine(); private: - - void initScriptEngine(); void runAndReportException(QString const &script); // Has ownership. No smart pointers here because we need to do manual memory managment // due to complicated mEngine lifecycle (see .cpp for more details). QScriptEngine *mEngine; - trikControl::Brick mBrick; + QScopedPointer mBrick; + QString const mConfigFilePath; QString const mStartDirPath; + QThread *mGuiThread; // Does not have ownership. }; } diff --git a/trikScriptRunner/src/scriptRunnerProxy.cpp b/trikScriptRunner/src/scriptRunnerProxy.cpp index c81763a9f..2a43f989a 100644 --- a/trikScriptRunner/src/scriptRunnerProxy.cpp +++ b/trikScriptRunner/src/scriptRunnerProxy.cpp @@ -33,26 +33,24 @@ ScriptRunnerProxy::ScriptRunnerProxy(QString const &configFilePath, QString cons connect(mEngineWorker, SIGNAL(completed()), this, SIGNAL(completed())); mWorkerThread.start(); + + QMetaObject::invokeMethod(mEngineWorker, "init"); } ScriptRunnerProxy::~ScriptRunnerProxy() { - mEngineWorker->abort(); + /// @todo Do not reset engine here, just shut it down. + mEngineWorker->reset(); QMetaObject::invokeMethod(&mWorkerThread, "quit"); mWorkerThread.wait(1000); } -void ScriptRunnerProxy::run(QString const &script) -{ - QMetaObject::invokeMethod(mEngineWorker, "run", Q_ARG(QString const &, script)); -} - -void ScriptRunnerProxy::abort() +void ScriptRunnerProxy::run(QString const &script, bool inEventDrivenMode) { - mEngineWorker->abort(); + QMetaObject::invokeMethod(mEngineWorker, "run", Q_ARG(QString const &, script), Q_ARG(bool, inEventDrivenMode)); } -bool ScriptRunnerProxy::isInEventDrivenMode() const +void ScriptRunnerProxy::reset() { - return mEngineWorker->isInEventDrivenMode(); + mEngineWorker->reset(); } diff --git a/trikScriptRunner/src/scriptRunnerProxy.h b/trikScriptRunner/src/scriptRunnerProxy.h index 9de18d481..bc115706a 100644 --- a/trikScriptRunner/src/scriptRunnerProxy.h +++ b/trikScriptRunner/src/scriptRunnerProxy.h @@ -39,14 +39,10 @@ class ScriptRunnerProxy : public QObject /// Executes given script asynchronously. If some script is already executing, it will be aborted. /// @param script - script in Qt Script language to be executed. - void run(QString const &script); + void run(QString const &script, bool inEventDrivenMode); /// Aborts script execution. - void abort(); - - /// Returns true if a system is in event-driven running mode, so it shall wait for events when script is executed. - /// If it is false, script will exit immediately. - bool isInEventDrivenMode() const; + void reset(); signals: /// Fired when current script completes execution. diff --git a/trikScriptRunner/src/trikScriptRunner.cpp b/trikScriptRunner/src/trikScriptRunner.cpp index 314ce9458..7b702c8c8 100644 --- a/trikScriptRunner/src/trikScriptRunner.cpp +++ b/trikScriptRunner/src/trikScriptRunner.cpp @@ -21,9 +21,8 @@ using namespace trikScriptRunner; TrikScriptRunner::TrikScriptRunner(QString const &configFilePath, QString const &startDirPath) : mScriptRunnerProxy(new ScriptRunnerProxy(configFilePath, startDirPath)) - , mExecutionState(idle) { - connect(mScriptRunnerProxy.data(), SIGNAL(completed()), this, SLOT(onScriptExecutionCompleted())); + connect(mScriptRunnerProxy.data(), SIGNAL(completed()), this, SIGNAL(completed())); } TrikScriptRunner::~TrikScriptRunner() @@ -32,33 +31,15 @@ TrikScriptRunner::~TrikScriptRunner() void TrikScriptRunner::run(QString const &script) { - mExecutionState = running; - mScriptRunnerProxy->run(script); + mScriptRunnerProxy->run(script, false); } -void TrikScriptRunner::runFromFile(QString const &fileName) +void TrikScriptRunner::runDirectCommand(QString const &command) { - mExecutionState = running; - mScriptRunnerProxy->run(trikKernel::FileUtils::readFromFile(fileName)); + mScriptRunnerProxy->run(command, true); } void TrikScriptRunner::abort() { - mScriptRunnerProxy->abort(); -} - -bool TrikScriptRunner::isInEventDrivenMode() const -{ - return mScriptRunnerProxy->isInEventDrivenMode(); -} - -void TrikScriptRunner::onScriptExecutionCompleted() -{ - if (mExecutionState == running) { - mExecutionState = stopping; - mScriptRunnerProxy->run("brick.stop()"); - } else { - mExecutionState = idle; - emit completed(); - } + mScriptRunnerProxy->reset(); } diff --git a/trikScriptRunner/trikScriptRunner.pro b/trikScriptRunner/trikScriptRunner.pro index a7d25241f..9d87aacb3 100644 --- a/trikScriptRunner/trikScriptRunner.pro +++ b/trikScriptRunner/trikScriptRunner.pro @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +include(../global.pri) + HEADERS += \ $$PWD/include/trikScriptRunner/trikScriptRunner.h \ $$PWD/src/scriptableParts.h \ @@ -27,23 +29,15 @@ SOURCES += \ OTHER_FILES += \ $$PWD/system.js \ -TRIKCONTROL_DIR = ../trikControl/ -TRIKKERNEL_DIR = ../trikKernel/ - TEMPLATE = lib QT += script DEFINES += TRIKSCRIPTRUNNER_LIBRARY -include(../global.pri) - copyToDestdir(system.js) -TARGET = trikScriptRunner$$CONFIGURATION_SUFFIX - -INCLUDEPATH = \ - $$PWD \ - $$TRIKCONTROL_DIR/include \ - $$TRIKKERNEL_DIR/include \ +uses(trikKernel trikControl) -LIBS += -L$$DESTDIR -ltrikControl$$CONFIGURATION_SUFFIX -ltrikKernel$$CONFIGURATION_SUFFIX +INCLUDEPATH += \ + $$PWD/../trikKernel/include/ \ + $$PWD/../trikControl/include/ \ diff --git a/trikServer/trikServer.pro b/trikServer/trikServer.pro index 8060e8727..2f6392c20 100644 --- a/trikServer/trikServer.pro +++ b/trikServer/trikServer.pro @@ -12,11 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +include(../global.pri) + SOURCES += \ $$PWD/main.cpp \ -TRIKCONTROL_DIR = ../trikControl/ -TRIKCOMMUNICATOR_DIR = ../trikCommunicator/ +uses(trikControl trikCommunicator) + +INCLUDEPATH += \ + ../trikControl/include/ \ + ../trikCommunicator/include/ \ TEMPLATE = app CONFIG += console @@ -26,11 +31,3 @@ QT += gui if (equals(QT_MAJOR_VERSION, 5)) { QT += widgets } - -include(../global.pri) - -INCLUDEPATH = \ - $$PWD \ - $$TRIKCOMMUNICATOR_DIR/include \ - -LIBS += -L$$DESTDIR -ltrikCommunicator$$CONFIGURATION_SUFFIX diff --git a/trikWiFi/trikWiFi.pro b/trikWiFi/trikWiFi.pro index 5b3b2efac..07a0d0da9 100644 --- a/trikWiFi/trikWiFi.pro +++ b/trikWiFi/trikWiFi.pro @@ -12,20 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +include(../global.pri) + TEMPLATE = lib QT += xml DEFINES += TRIKWIFI_LIBRARY -include(../global.pri) - -TARGET = trikWiFi$$CONFIGURATION_SUFFIX - -INCLUDEPATH = \ - $$PWD \ - $$PWD/include/trikWiFi \ - win32 { PLATFORM = windows } else {