diff --git a/GC-3.6.1-T1/README b/GC-3.6.1-T1/README new file mode 100644 index 0000000..b37c71f --- /dev/null +++ b/GC-3.6.1-T1/README @@ -0,0 +1,29 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Details on how to do this can be found here: +http://zapmaker.org/ + + +V3.6.1-T1 (LETARTARE proposals June 01, 2014) + +- 3.6.1 + +1- Improved to the same card 3 and 4 axis detection +2- Displays the line numbers of the file if no number exists +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, future 0.8c1 (0.8c to 4 axes) + + + + + + + diff --git a/GC-3.6.1-T1/buildWin.txt b/GC-3.6.1-T1/buildWin.txt new file mode 100644 index 0000000..3737a80 --- /dev/null +++ b/GC-3.6.1-T1/buildWin.txt @@ -0,0 +1,25 @@ +builWin.txt by LETARTARE + + +To build the executable under Windows, you must have +1- a 'Qt' version installed and compiled, the tests were performed with 'Qt-4.7.3'. +2- 'mingw32' installed to use 'mingw32-make.exe', the tests were performed with 'MinGw32-TDM-4.7.1' + +You have to adapt the file 'makeWin.bat' for the paths are correct. + +Example Qt4 : + set PATH_Qt=u:\DONNEES\SVN_COMPILE\qt\4.7.3 + set PATH_MINGW32=o:\DevCpp\MinGw32-TDM + +Example Qt5 : + set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ + set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +Open a DOS console and +1 - makeWin.bat +2 - execute.bat + +if you want the French translation +3 - translate.bat +4 - execute.bat diff --git a/GC-3.6.1-T1/clean.bat b/GC-3.6.1-T1/clean.bat new file mode 100644 index 0000000..6a4585c --- /dev/null +++ b/GC-3.6.1-T1/clean.bat @@ -0,0 +1,26 @@ +rem clean.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +clean.bat + + diff --git a/GC-3.6.1-T1/execute.bat b/GC-3.6.1-T1/execute.bat new file mode 100644 index 0000000..dbd9cf0 --- /dev/null +++ b/GC-3.6.1-T1/execute.bat @@ -0,0 +1,8 @@ +rem execute.bat +rem by LETARTARE + +cd src\release + +GrblController.exe + +cd ..\.. \ No newline at end of file diff --git a/GC-3.6.1-T1/mw.bat b/GC-3.6.1-T1/mw.bat new file mode 100644 index 0000000..bd60e58 --- /dev/null +++ b/GC-3.6.1-T1/mw.bat @@ -0,0 +1,24 @@ +rem makeWin.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +makeWin.bat + + diff --git a/.gitignore b/GC-3.6.1-T1/src/.gitignore similarity index 73% rename from .gitignore rename to GC-3.6.1-T1/src/.gitignore index f7d018c..f128f9d 100644 --- a/.gitignore +++ b/GC-3.6.1-T1/src/.gitignore @@ -11,3 +11,9 @@ settings ui_*.h Output/ android/ +GrblController +*.o +moc_*.cpp +qrc_*.cpp +*.stash +GrblController-local.iss diff --git a/GcodeSenderGUIthreads.pro b/GC-3.6.1-T1/src/GcodeSenderGUIthreads.pro similarity index 88% rename from GcodeSenderGUIthreads.pro rename to GC-3.6.1-T1/src/GcodeSenderGUIthreads.pro index 1cedb30..400cffe 100644 --- a/GcodeSenderGUIthreads.pro +++ b/GC-3.6.1-T1/src/GcodeSenderGUIthreads.pro @@ -1,10 +1,16 @@ #------------------------------------------------- # -# Project created by QtCreator 2012-02-13T17:48:40 +# Project created by QtCreator 2012-02-13 T17:48:40 # +# (fourth axis modifications and translation added by LETARTARE 2013-08-03) #------------------------------------------------- -QT += core gui widgets +QT += core gui + +# LETARTARE June 12, 2014 +contains(QT_VERSION, "^5.*") { + QT *= widgets +} TARGET = GrblController TEMPLATE = app @@ -99,3 +105,6 @@ OTHER_FILES += \ android/src/org/kde/necessitas/origo/QtApplication.java \ android/version.xml +# Translations + TRANSLATIONS += trlocale/GrblController_xx.ts + TRANSLATIONS += trlocale/GrblController_fr.ts diff --git a/GrblController.iss b/GC-3.6.1-T1/src/GrblController.iss similarity index 93% rename from GrblController.iss rename to GC-3.6.1-T1/src/GrblController.iss index 4c7dfb1..49dc801 100644 --- a/GrblController.iss +++ b/GC-3.6.1-T1/src/GrblController.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "Grbl Controller" -#define MyAppVersion "3.4.3" +#define MyAppVersion "3.6.1" #define MyAppPublisher "Zapmaker" #define MyAppURL "http://zapmaker.org" #define MyAppExeName "GrblController.exe" @@ -25,7 +25,7 @@ AllowNoIcons=yes LicenseFile=C:\dev\github\GrblHoming\winlicense.txt InfoBeforeFile=C:\dev\github\GrblHoming\wininfobefore.txt InfoAfterFile=C:\dev\github\GrblHoming\wininfoafter.txt -OutputBaseFilename=GrblController343Setup +OutputBaseFilename=GrblController361Setup Compression=lzma SolidCompression=yes @@ -38,6 +38,7 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip [Files] Source: "C:\dev\github\GrblHoming\release\GrblController.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\dev\github\GrblHoming\trlocale\*.qm"; DestDir: "{app}\trlocale"; Flags: ignoreversion Source: "C:\Qt\4.8.3\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Qt\4.8.3\bin\mingwm10.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Qt\4.8.3\bin\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion diff --git a/GrblController.qrc b/GC-3.6.1-T1/src/GrblController.qrc similarity index 100% rename from GrblController.qrc rename to GC-3.6.1-T1/src/GrblController.qrc diff --git a/LICENSE b/GC-3.6.1-T1/src/LICENSE similarity index 100% rename from LICENSE rename to GC-3.6.1-T1/src/LICENSE diff --git a/QextSerialPort/qextserialenumerator.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.cpp similarity index 87% rename from QextSerialPort/qextserialenumerator.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.cpp index 2a8f73d..ec1491a 100644 --- a/QextSerialPort/qextserialenumerator.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.cpp @@ -1,169 +1,163 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialenumerator.h" -#include "qextserialenumerator_p.h" - -#include -#include -#include - -QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator) - :q_ptr(enumrator) -{ - platformSpecificInit(); -} - -QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate() -{ - platformSpecificDestruct(); -} - -/*! - \class QextPortInfo - - \brief The QextPortInfo class containing port information. - - Structure containing port information. - - \code - QString portName; ///< Port name. - QString physName; ///< Physical name. - QString friendName; ///< Friendly name. - QString enumName; ///< Enumerator name. - int vendorID; ///< Vendor ID. - int productID; ///< Product ID - \endcode - */ - -/*! \class QextSerialEnumerator - - \brief The QextSerialEnumerator class provides list of ports available in the system. - - \section1 Usage - To poll the system for a list of connected devices, simply use getPorts(). Each - QextPortInfo structure will populated with information about the corresponding device. - - \bold Example - \code - QList ports = QextSerialEnumerator::getPorts(); - foreach( QextPortInfo port, ports ) { - // inspect port... - } - \endcode - - To enable event-driven notification of device connection events, first call - setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() - signals. Event-driven behavior is currently available only on Windows and OS X. - - \bold Example - \code - QextSerialEnumerator* enumerator = new QextSerialEnumerator(); - connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), - myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); - connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), - myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); - \endcode - - \section1 Credits - Windows implementation is based on Zach Gorman's work from - \l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp). - - OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html - - \bold author Michal Policht, Liam Staskawicz -*/ - -/*! - \fn void QextSerialEnumerator::deviceDiscovered( const QextPortInfo & info ) - A new device has been connected to the system. - - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - - \a info The device that has been discovered. -*/ - -/*! - \fn void QextSerialEnumerator::deviceRemoved( const QextPortInfo & info ); - A device has been disconnected from the system. - - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - - \a info The device that was disconnected. -*/ - -/*! - Constructs a QextSerialEnumerator object with the given \a parent. -*/ -QextSerialEnumerator::QextSerialEnumerator(QObject *parent) - :QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this)) -{ - if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) ) - qRegisterMetaType("QextPortInfo"); -} - -/*! - Destructs the QextSerialEnumerator object. -*/ -QextSerialEnumerator::~QextSerialEnumerator( ) -{ - delete d_ptr; -} - -/*! - Get list of ports. - - return list of ports currently available in the system. -*/ -QList QextSerialEnumerator::getPorts() -{ -#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) && !defined(Q_OS_MAC) - qCritical("Enumeration for POSIX systems (except Linux) is not implemented yet."); -#endif - return QextSerialEnumeratorPrivate::getPorts_sys(); -} - -/*! - Enable event-driven notifications of board discovery/removal. -*/ -void QextSerialEnumerator::setUpNotifications() -{ -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !(defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV)) - qCritical("Notifications for *Nix/FreeBSD are not implemented yet"); -#endif - Q_D(QextSerialEnumerator); - if (!d->setUpNotifications_sys(true)) - QESP_WARNING("Setup Notification Failed..."); -} - -#include "moc_qextserialenumerator.cpp" +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" + +#include +#include +#include + +QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator) + :q_ptr(enumrator) +{ + platformSpecificInit(); +} + +QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate() +{ + platformSpecificDestruct(); +} + +/*! + \class QextPortInfo + + \brief The QextPortInfo class containing port information. + + Structure containing port information. + + \code + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID + \endcode + */ + +/*! \class QextSerialEnumerator + + \brief The QextSerialEnumerator class provides list of ports available in the system. + + \section1 Usage + To poll the system for a list of connected devices, simply use getPorts(). Each + QextPortInfo structure will populated with information about the corresponding device. + + \bold Example + \code + QList ports = QextSerialEnumerator::getPorts(); + foreach (QextPortInfo port, ports) { + // inspect port... + } + \endcode + + To enable event-driven notification of device connection events, first call + setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() + signals. Event-driven behavior is currently available only on Windows and OS X. + + \bold Example + \code + QextSerialEnumerator *enumerator = new QextSerialEnumerator(); + connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), + myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); + connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), + myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); + \endcode + + \section1 Credits + Windows implementation is based on Zach Gorman's work from + \l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp). + + OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html + + \bold author Michal Policht, Liam Staskawicz +*/ + +/*! + \fn void QextSerialEnumerator::deviceDiscovered(const QextPortInfo &info) + A new device has been connected to the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that has been discovered. +*/ + +/*! + \fn void QextSerialEnumerator::deviceRemoved(const QextPortInfo &info); + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that was disconnected. +*/ + +/*! + Constructs a QextSerialEnumerator object with the given \a parent. +*/ +QextSerialEnumerator::QextSerialEnumerator(QObject *parent) + :QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this)) +{ + if (!QMetaType::isRegistered(QMetaType::type("QextPortInfo"))) + qRegisterMetaType("QextPortInfo"); +} + +/*! + Destructs the QextSerialEnumerator object. +*/ +QextSerialEnumerator::~QextSerialEnumerator() +{ + delete d_ptr; +} + +/*! + Get list of ports. + + return list of ports currently available in the system. +*/ +QList QextSerialEnumerator::getPorts() +{ + return QextSerialEnumeratorPrivate::getPorts_sys(); +} + +/*! + Enable event-driven notifications of board discovery/removal. +*/ +void QextSerialEnumerator::setUpNotifications() +{ + Q_D(QextSerialEnumerator); + if (!d->setUpNotifications_sys(true)) + QESP_WARNING("Setup Notification Failed..."); +} + +#include "moc_qextserialenumerator.cpp" diff --git a/QextSerialPort/qextserialenumerator.h b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.h similarity index 91% rename from QextSerialPort/qextserialenumerator.h rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.h index 7d83bd7..99f515d 100644 --- a/QextSerialPort/qextserialenumerator.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator.h @@ -1,72 +1,72 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _QEXTSERIALENUMERATOR_H_ -#define _QEXTSERIALENUMERATOR_H_ - -#include -#include -#include "qextserialport_global.h" - -struct QextPortInfo { - QString portName; ///< Port name. - QString physName; ///< Physical name. - QString friendName; ///< Friendly name. - QString enumName; ///< Enumerator name. - int vendorID; ///< Vendor ID. - int productID; ///< Product ID -}; - -class QextSerialEnumeratorPrivate; -class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QextSerialEnumerator) -public: - QextSerialEnumerator(QObject * parent=0); - ~QextSerialEnumerator(); - - static QList getPorts(); - void setUpNotifications(); - -Q_SIGNALS: - void deviceDiscovered(const QextPortInfo & info); - void deviceRemoved(const QextPortInfo & info); - -private: - Q_DISABLE_COPY(QextSerialEnumerator) -#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) - Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent()) -#endif - QextSerialEnumeratorPrivate *d_ptr; -}; - -#endif /*_QEXTSERIALENUMERATOR_H_*/ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALENUMERATOR_H_ +#define _QEXTSERIALENUMERATOR_H_ + +#include +#include +#include "qextserialport_global.h" + +struct QextPortInfo { + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID +}; + +class QextSerialEnumeratorPrivate; +class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialEnumerator) +public: + QextSerialEnumerator(QObject *parent=0); + ~QextSerialEnumerator(); + + static QList getPorts(); + void setUpNotifications(); + +Q_SIGNALS: + void deviceDiscovered(const QextPortInfo &info); + void deviceRemoved(const QextPortInfo &info); + +private: + Q_DISABLE_COPY(QextSerialEnumerator) +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent()) +#endif + QextSerialEnumeratorPrivate *d_ptr; +}; + +#endif /*_QEXTSERIALENUMERATOR_H_*/ diff --git a/QextSerialPort/qextserialenumerator_linux.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_linux.cpp similarity index 64% rename from QextSerialPort/qextserialenumerator_linux.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_linux.cpp index f2dd9a5..a57dfe6 100644 --- a/QextSerialPort/qextserialenumerator_linux.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_linux.cpp @@ -1,145 +1,210 @@ -/**************************************************************************** -** Copyright (c) 2012 Doug Brown -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialenumerator.h" -#include "qextserialenumerator_p.h" -#include - -void QextSerialEnumeratorPrivate::platformSpecificInit() -{ - monitor = NULL; - notifierFd = -1; - notifier = NULL; - - udev = udev_new(); - if (!udev) - qCritical() << "Unable to initialize udev notifications"; -} - -void QextSerialEnumeratorPrivate::platformSpecificDestruct() -{ - if (notifier) { - notifier->setEnabled(false); - delete notifier; - } - - if (monitor) - udev_monitor_unref(monitor); - - if (udev) - udev_unref(udev); -} - -static QextPortInfo portInfoFromDevice(struct udev_device *dev) -{ - QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID")); - QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID")); - - QextPortInfo pi; - pi.vendorID = vendor.toInt(0, 16); - pi.productID = product.toInt(0, 16); - pi.portName = QString::fromLatin1(udev_device_get_devnode(dev)); - pi.physName = pi.portName; - - return pi; -} - -QList QextSerialEnumeratorPrivate::getPorts_sys() -{ - QList returnVal; - struct udev *ud = udev_new(); - if (!ud) { - qCritical() << "Unable to enumerate ports because udev is not initialized."; - return returnVal; - } - - struct udev_enumerate *enumerate = udev_enumerate_new(ud); - udev_enumerate_add_match_subsystem(enumerate, "tty"); - udev_enumerate_scan_devices(enumerate); - struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); - struct udev_list_entry *entry; - udev_list_entry_foreach(entry, list) { - const char *path; - struct udev_device *dev; - - // Have to grab the actual udev device here... - path = udev_list_entry_get_name(entry); - dev = udev_device_new_from_syspath(ud, path); - - returnVal.append(portInfoFromDevice(dev)); - - // Done with this device - udev_device_unref(dev); - } - // Done with the list and this udev - udev_enumerate_unref(enumerate); - udev_unref(ud); - - return returnVal; -} - -bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) -{ - Q_UNUSED(setup); - Q_Q(QextSerialEnumerator); - if (!udev) { - qCritical() << "Unable to initialize notifications because udev is not initialized."; - return false; - } - - // Emit signals immediately for devices already connected (Windows version seems to behave - // this way) - foreach (QextPortInfo i, getPorts_sys()) - Q_EMIT q->deviceDiscovered(i); - - // Look for tty devices from udev. - monitor = udev_monitor_new_from_netlink(udev, "udev"); - udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL); - udev_monitor_enable_receiving(monitor); - notifierFd = udev_monitor_get_fd(monitor); - notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read); - q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent())); - notifier->setEnabled(true); - - return true; -} - -void QextSerialEnumeratorPrivate::_q_deviceEvent() -{ - Q_Q(QextSerialEnumerator); - struct udev_device *dev = udev_monitor_receive_device(monitor); - if (dev) { - QextPortInfo pi = portInfoFromDevice(dev); - - QLatin1String action(udev_device_get_action(dev)); - udev_device_unref(dev); - - if (action == QLatin1String("add")) - Q_EMIT q->deviceDiscovered(pi); - else if (action == QLatin1String("remove")) - Q_EMIT q->deviceRemoved(pi); - } -} +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifndef QESP_NO_UDEV + monitor = NULL; + notifierFd = -1; + notifier = NULL; + + udev = udev_new(); + if (!udev) + qCritical() << "Unable to initialize udev notifications"; +#endif +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifndef QESP_NO_UDEV + if (notifier) { + notifier->setEnabled(false); + delete notifier; + } + + if (monitor) + udev_monitor_unref(monitor); + + if (udev) + udev_unref(udev); +#endif +} + +#ifndef QESP_NO_UDEV +static QextPortInfo portInfoFromDevice(struct udev_device *dev) +{ + QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID")); + QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID")); + + QextPortInfo pi; + pi.vendorID = vendor.toInt(0, 16); + pi.productID = product.toInt(0, 16); + pi.portName = QString::fromLatin1(udev_device_get_devnode(dev)); + pi.physName = pi.portName; + + return pi; +} +#endif + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; +#ifndef QESP_NO_UDEV + struct udev *ud = udev_new(); + if (!ud) { + qCritical() << "Unable to enumerate ports because udev is not initialized."; + return infoList; + } + + struct udev_enumerate *enumerate = udev_enumerate_new(ud); + udev_enumerate_add_match_subsystem(enumerate, "tty"); + udev_enumerate_scan_devices(enumerate); + struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); + struct udev_list_entry *entry; + udev_list_entry_foreach(entry, list) { + const char *path; + struct udev_device *dev; + + // Have to grab the actual udev device here... + path = udev_list_entry_get_name(entry); + dev = udev_device_new_from_syspath(ud, path); + + infoList.append(portInfoFromDevice(dev)); + + // Done with this device + udev_device_unref(dev); + } + // Done with the list and this udev + udev_enumerate_unref(enumerate); + udev_unref(ud); +#else + QStringList portNamePrefixes, portNameList; + portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first + + QDir dir(QLatin1String("/dev")); + portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + // remove the values which are not serial ports for e.g. /dev/ttysa + for (int i = 0; i < portNameList.size(); i++) { + bool ok; + QString current = portNameList.at(i); + // remove the ttyS part, and check, if the other part is a number + current.remove(0,4).toInt(&ok, 10); + if (!ok) { + portNameList.removeAt(i); + i--; + } + } + + // get the non standard serial ports names + // (USB-serial, bluetooth-serial, 18F PICs, and so on) + // if you know an other name prefix for serial ports please let us know + portNamePrefixes.clear(); + portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); + portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + foreach (QString str , portNameList) { + QextPortInfo inf; + inf.physName = QLatin1String("/dev/")+str; + inf.portName = str; + + if (str.contains(QLatin1String("ttyS"))) { + inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); + } + else if (str.contains(QLatin1String("ttyUSB"))) { + inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); + } + else if (str.contains(QLatin1String("rfcomm"))) { + inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); + } + inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? + infoList.append(inf); + } +#endif + + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup); +#ifndef QESP_NO_UDEV + Q_Q(QextSerialEnumerator); + if (!udev) { + qCritical() << "Unable to initialize notifications because udev is not initialized."; + return false; + } + + // Emit signals immediately for devices already connected (Windows version seems to behave + // this way) + foreach (QextPortInfo i, getPorts_sys()) + Q_EMIT q->deviceDiscovered(i); + + // Look for tty devices from udev. + monitor = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL); + udev_monitor_enable_receiving(monitor); + notifierFd = udev_monitor_get_fd(monitor); + notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read); + q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent())); + notifier->setEnabled(true); + + return true; +#else + return false; +#endif +} + +#ifndef QESP_NO_UDEV +void QextSerialEnumeratorPrivate::_q_deviceEvent() +{ + Q_Q(QextSerialEnumerator); + struct udev_device *dev = udev_monitor_receive_device(monitor); + if (dev) { + QextPortInfo pi = portInfoFromDevice(dev); + + QLatin1String action(udev_device_get_action(dev)); + udev_device_unref(dev); + + if (action == QLatin1String("add")) + Q_EMIT q->deviceDiscovered(pi); + else if (action == QLatin1String("remove")) + Q_EMIT q->deviceRemoved(pi); + } +} +#endif diff --git a/QextSerialPort/qextserialenumerator_osx.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_osx.cpp similarity index 78% rename from QextSerialPort/qextserialenumerator_osx.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_osx.cpp index 60fac20..2dd0357 100644 --- a/QextSerialPort/qextserialenumerator_osx.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_osx.cpp @@ -1,313 +1,307 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialenumerator.h" -#include "qextserialenumerator_p.h" -#include -#include -#include -#include - -void QextSerialEnumeratorPrivate::platformSpecificInit() -{ -} - -void QextSerialEnumeratorPrivate::platformSpecificDestruct() -{ - IONotificationPortDestroy( notificationPortRef ); -} - -// static -QList QextSerialEnumeratorPrivate::getPorts_sys() -{ - QList infoList; - io_iterator_t serialPortIterator = 0; - kern_return_t kernResult = KERN_FAILURE; - CFMutableDictionaryRef matchingDictionary; - - // first try to get any serialbsd devices, then try any USBCDC devices - if( !(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue) ) ) { - QESP_WARNING("IOServiceMatching returned a NULL dictionary."); - return infoList; - } - CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); - - // then create the iterator with all the matching devices - if( IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS ) { - qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; - return infoList; - } - iterateServicesOSX(serialPortIterator, infoList); - IOObjectRelease(serialPortIterator); - serialPortIterator = 0; - - if( !(matchingDictionary = IOServiceNameMatching("AppleUSBCDC")) ) { - QESP_WARNING("IOServiceNameMatching returned a NULL dictionary."); - return infoList; - } - - if( IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS ) { - qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; - return infoList; - } - iterateServicesOSX(serialPortIterator, infoList); - IOObjectRelease(serialPortIterator); - - return infoList; -} - -void QextSerialEnumeratorPrivate::iterateServicesOSX(io_object_t service, QList & infoList) -{ - // Iterate through all modems found. - io_object_t usbService; - while( ( usbService = IOIteratorNext(service) ) ) - { - QextPortInfo info; - info.vendorID = 0; - info.productID = 0; - getServiceDetailsOSX( usbService, &info ); - infoList.append(info); - } -} - -bool QextSerialEnumeratorPrivate::getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo ) -{ - bool retval = true; - CFTypeRef bsdPathAsCFString = NULL; - CFTypeRef productNameAsCFString = NULL; - CFTypeRef vendorIdAsCFNumber = NULL; - CFTypeRef productIdAsCFNumber = NULL; - // check the name of the modem's callout device - bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey), - kCFAllocatorDefault, 0); - - // wander up the hierarchy until we find the level that can give us the - // vendor/product IDs and the product name, if available - io_registry_entry_t parent; - kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); - while( kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber ) - { - if(!productNameAsCFString) - productNameAsCFString = IORegistryEntrySearchCFProperty(parent, - kIOServicePlane, - CFSTR("Product Name"), - kCFAllocatorDefault, 0); - vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, - kIOServicePlane, - CFSTR(kUSBVendorID), - kCFAllocatorDefault, 0); - productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, - kIOServicePlane, - CFSTR(kUSBProductID), - kCFAllocatorDefault, 0); - io_registry_entry_t oldparent = parent; - kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent); - IOObjectRelease(oldparent); - } - - io_string_t ioPathName; - IORegistryEntryGetPath( service, kIOServicePlane, ioPathName ); - portInfo->physName = ioPathName; - - if( bsdPathAsCFString ) - { - char path[MAXPATHLEN]; - if( CFStringGetCString((CFStringRef)bsdPathAsCFString, path, - PATH_MAX, kCFStringEncodingUTF8) ) - portInfo->portName = path; - CFRelease(bsdPathAsCFString); - } - - if(productNameAsCFString) - { - char productName[MAXPATHLEN]; - if( CFStringGetCString((CFStringRef)productNameAsCFString, productName, - PATH_MAX, kCFStringEncodingUTF8) ) - portInfo->friendName = productName; - CFRelease(productNameAsCFString); - } - - if(vendorIdAsCFNumber) - { - SInt32 vID; - if(CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID)) - portInfo->vendorID = vID; - CFRelease(vendorIdAsCFNumber); - } - - if(productIdAsCFNumber) - { - SInt32 pID; - if(CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID)) - portInfo->productID = pID; - CFRelease(productIdAsCFNumber); - } - IOObjectRelease(service); - return retval; -} - -// IOKit callbacks registered via setupNotifications() -void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ) -{ - QextSerialEnumeratorPrivate* d = (QextSerialEnumeratorPrivate*)ctxt; - io_object_t serialService; - while ((serialService = IOIteratorNext(serialPortIterator))) - d->onDeviceDiscoveredOSX(serialService); -} - -void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ) -{ - QextSerialEnumeratorPrivate* d = (QextSerialEnumeratorPrivate*)ctxt; - io_object_t serialService; - while ((serialService = IOIteratorNext(serialPortIterator))) - d->onDeviceTerminatedOSX(serialService); -} - -/* - A device has been discovered via IOKit. - Create a QextPortInfo if possible, and emit the signal indicating that we've found it. -*/ -void QextSerialEnumeratorPrivate::onDeviceDiscoveredOSX( io_object_t service ) -{ - Q_Q(QextSerialEnumerator); - QextPortInfo info; - info.vendorID = 0; - info.productID = 0; - if( getServiceDetailsOSX( service, &info ) ) - Q_EMIT q->deviceDiscovered( info ); -} - -/* - Notification via IOKit that a device has been removed. - Create a QextPortInfo if possible, and emit the signal indicating that it's gone. -*/ -void QextSerialEnumeratorPrivate::onDeviceTerminatedOSX( io_object_t service ) -{ - Q_Q(QextSerialEnumerator); - QextPortInfo info; - info.vendorID = 0; - info.productID = 0; - if( getServiceDetailsOSX( service, &info ) ) - Q_EMIT q->deviceRemoved( info ); -} - -/* - Create matching dictionaries for the devices we want to get notifications for, - and add them to the current run loop. Invoke the callbacks that will be responding - to these notifications once to arm them, and discover any devices that - are currently connected at the time notifications are setup. -*/ -bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) -{ - kern_return_t kernResult; - mach_port_t masterPort; - CFRunLoopSourceRef notificationRunLoopSource; - CFMutableDictionaryRef classesToMatch; - CFMutableDictionaryRef cdcClassesToMatch; - io_iterator_t portIterator; - - kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); - if (KERN_SUCCESS != kernResult) { - qDebug() << "IOMasterPort returned:" << kernResult; - return false; - } - - classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); - if (classesToMatch == NULL) - qDebug("IOServiceMatching returned a NULL dictionary."); - else - CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); - - if( !(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC") ) ) { - QESP_WARNING("couldn't create cdc matching dict"); - return false; - } - - // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. - classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); - cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); - - notificationPortRef = IONotificationPortCreate(masterPort); - if(notificationPortRef == NULL) { - qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); - return false; - } - - notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); - if (notificationRunLoopSource == NULL) { - qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); - return false; - } - - CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); - - kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, - deviceDiscoveredCallbackOSX, this, &portIterator); - if (kernResult != KERN_SUCCESS) { - qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; - return false; - } - - // arm the callback, and grab any devices that are already connected - deviceDiscoveredCallbackOSX( this, portIterator ); - - kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, - deviceDiscoveredCallbackOSX, this, &portIterator); - if (kernResult != KERN_SUCCESS) { - qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; - return false; - } - - // arm the callback, and grab any devices that are already connected - deviceDiscoveredCallbackOSX( this, portIterator ); - - kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, - deviceTerminatedCallbackOSX, this, &portIterator); - if (kernResult != KERN_SUCCESS) { - qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; - return false; - } - - // arm the callback, and clear any devices that are terminated - deviceTerminatedCallbackOSX( this, portIterator ); - - kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, - deviceTerminatedCallbackOSX, this, &portIterator); - if (kernResult != KERN_SUCCESS) { - qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; - return false; - } - - // arm the callback, and clear any devices that are terminated - deviceTerminatedCallbackOSX( this, portIterator ); - return true; -} - +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ + IONotificationPortDestroy(notificationPortRef); +} + +// static +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + io_iterator_t serialPortIterator = 0; + kern_return_t kernResult = KERN_FAILURE; + CFMutableDictionaryRef matchingDictionary; + + // first try to get any serialbsd devices, then try any USBCDC devices + if (!(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue))) { + QESP_WARNING("IOServiceMatching returned a NULL dictionary."); + return infoList; + } + CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + // then create the iterator with all the matching devices + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + serialPortIterator = 0; + + if (!(matchingDictionary = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("IOServiceNameMatching returned a NULL dictionary."); + return infoList; + } + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + + return infoList; +} + +void QextSerialEnumeratorPrivate::iterateServicesOSX(io_object_t service, QList &infoList) +{ + // Iterate through all modems found. + io_object_t usbService; + while ((usbService = IOIteratorNext(service))) { + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + getServiceDetailsOSX(usbService, &info); + infoList.append(info); + } +} + +bool QextSerialEnumeratorPrivate::getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo) +{ + bool retval = true; + CFTypeRef bsdPathAsCFString = NULL; + CFTypeRef productNameAsCFString = NULL; + CFTypeRef vendorIdAsCFNumber = NULL; + CFTypeRef productIdAsCFNumber = NULL; + // check the name of the modem's callout device + bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, 0); + + // wander up the hierarchy until we find the level that can give us the + // vendor/product IDs and the product name, if available + io_registry_entry_t parent; + kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); + while (kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber) { + if (!productNameAsCFString) + productNameAsCFString = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR("Product Name"), + kCFAllocatorDefault, 0); + vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBVendorID), + kCFAllocatorDefault, 0); + productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBProductID), + kCFAllocatorDefault, 0); + io_registry_entry_t oldparent = parent; + kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent); + IOObjectRelease(oldparent); + } + + io_string_t ioPathName; + IORegistryEntryGetPath(service, kIOServicePlane, ioPathName); + portInfo->physName = ioPathName; + + if (bsdPathAsCFString) { + char path[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)bsdPathAsCFString, path, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->portName = path; + CFRelease(bsdPathAsCFString); + } + + if (productNameAsCFString) { + char productName[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)productNameAsCFString, productName, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->friendName = productName; + CFRelease(productNameAsCFString); + } + + if (vendorIdAsCFNumber) { + SInt32 vID; + if (CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID)) + portInfo->vendorID = vID; + CFRelease(vendorIdAsCFNumber); + } + + if (productIdAsCFNumber) { + SInt32 pID; + if (CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID)) + portInfo->productID = pID; + CFRelease(productIdAsCFNumber); + } + IOObjectRelease(service); + return retval; +} + +// IOKit callbacks registered via setupNotifications() +void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceDiscoveredOSX(serialService); +} + +void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceTerminatedOSX(serialService); +} + +/* + A device has been discovered via IOKit. + Create a QextPortInfo if possible, and emit the signal indicating that we've found it. +*/ +void QextSerialEnumeratorPrivate::onDeviceDiscoveredOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceDiscovered(info); +} + +/* + Notification via IOKit that a device has been removed. + Create a QextPortInfo if possible, and emit the signal indicating that it's gone. +*/ +void QextSerialEnumeratorPrivate::onDeviceTerminatedOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceRemoved(info); +} + +/* + Create matching dictionaries for the devices we want to get notifications for, + and add them to the current run loop. Invoke the callbacks that will be responding + to these notifications once to arm them, and discover any devices that + are currently connected at the time notifications are setup. +*/ +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool /*setup*/) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFRunLoopSourceRef notificationRunLoopSource; + CFMutableDictionaryRef classesToMatch; + CFMutableDictionaryRef cdcClassesToMatch; + io_iterator_t portIterator; + + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) { + qDebug() << "IOMasterPort returned:" << kernResult; + return false; + } + + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch == NULL) + qDebug("IOServiceMatching returned a NULL dictionary."); + else + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + if (!(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("couldn't create cdc matching dict"); + return false; + } + + // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. + classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); + cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); + + notificationPortRef = IONotificationPortCreate(masterPort); + if (notificationPortRef == NULL) { + qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); + return false; + } + + notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); + if (notificationRunLoopSource == NULL) { + qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); + return false; + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + return true; +} + diff --git a/QextSerialPort/qextserialenumerator_p.h b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_p.h similarity index 78% rename from QextSerialPort/qextserialenumerator_p.h rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_p.h index 50b9480..c69e925 100644 --- a/QextSerialPort/qextserialenumerator_p.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_p.h @@ -1,120 +1,126 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** Copyright (c) 2012 Doug Brown -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ -#ifndef _QEXTSERIALENUMERATOR_P_H_ -#define _QEXTSERIALENUMERATOR_P_H_ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the QESP API. It exists for the convenience -// of other QESP classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qextserialenumerator.h" - -#ifdef Q_OS_WIN -// needed for mingw to pull in appropriate dbt business... -// probably a better way to do this -// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html -# ifdef __MINGW32__ -# define _WIN32_WINNT 0x0500 -# define _WIN32_WINDOWS 0x0500 -# define WINVER 0x0500 +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef _QEXTSERIALENUMERATOR_P_H_ +#define _QEXTSERIALENUMERATOR_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialenumerator.h" + +#ifdef Q_OS_WIN +// needed for mingw to pull in appropriate dbt business... +// probably a better way to do this +// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html +# ifdef __MINGW32__ +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef _WIN32_WINDOWS +# define _WIN32_WINDOWS 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif # endif -# include -#endif /*Q_OS_WIN*/ - -#ifdef Q_OS_MAC -# include -#endif /*Q_OS_MAC*/ - -#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) -# include -extern "C" { -# include -} -#endif - -class QextSerialRegistrationWidget; -class QextSerialEnumeratorPrivate -{ - Q_DECLARE_PUBLIC(QextSerialEnumerator) -public: - QextSerialEnumeratorPrivate(QextSerialEnumerator * enumrator); - ~QextSerialEnumeratorPrivate(); - void platformSpecificInit(); - void platformSpecificDestruct(); - - static QList getPorts_sys(); - bool setUpNotifications_sys(bool setup); - -#ifdef Q_OS_WIN - LRESULT onDeviceChanged( WPARAM wParam, LPARAM lParam ); - bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); -# ifdef QT_GUI_LIB - QextSerialRegistrationWidget* notificationWidget; -# endif -#endif /*Q_OS_WIN*/ - -#ifdef Q_OS_MAC - /*! - * Search for serial ports using IOKit. - * \param infoList list with result. - */ - static void iterateServicesOSX(io_object_t service, QList & infoList); - static bool getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo ); - void onDeviceDiscoveredOSX( io_object_t service ); - void onDeviceTerminatedOSX( io_object_t service ); - friend void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ); - friend void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ); - - IONotificationPortRef notificationPortRef; -#endif // Q_OS_MAC - -#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) - QSocketNotifier *notifier; - int notifierFd; - struct udev *udev; - struct udev_monitor *monitor; - - void _q_deviceEvent(); -#endif - -private: - QextSerialEnumerator * q_ptr; -}; - -#endif //_QEXTSERIALENUMERATOR_P_H_ +# include +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC +# include +#endif /*Q_OS_MAC*/ + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) +# include +extern "C" { +# include +} +#endif + +class QextSerialRegistrationWidget; +class QextSerialEnumeratorPrivate +{ + Q_DECLARE_PUBLIC(QextSerialEnumerator) +public: + QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator); + ~QextSerialEnumeratorPrivate(); + void platformSpecificInit(); + void platformSpecificDestruct(); + + static QList getPorts_sys(); + bool setUpNotifications_sys(bool setup); + +#ifdef Q_OS_WIN + LRESULT onDeviceChanged(WPARAM wParam, LPARAM lParam); + bool matchAndDispatchChangedDevice(const QString &deviceID, const GUID &guid, WPARAM wParam); +# ifdef QT_GUI_LIB + QextSerialRegistrationWidget *notificationWidget; +# endif +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC + /*! + * Search for serial ports using IOKit. + * \param infoList list with result. + */ + static void iterateServicesOSX(io_object_t service, QList &infoList); + static bool getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo); + void onDeviceDiscoveredOSX(io_object_t service); + void onDeviceTerminatedOSX(io_object_t service); + friend void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + friend void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + + IONotificationPortRef notificationPortRef; +#endif // Q_OS_MAC + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + QSocketNotifier *notifier; + int notifierFd; + struct udev *udev; + struct udev_monitor *monitor; + + void _q_deviceEvent(); +#endif + +private: + QextSerialEnumerator *q_ptr; +}; + +#endif //_QEXTSERIALENUMERATOR_P_H_ diff --git a/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_unix.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_unix.cpp new file mode 100644 index 0000000..80a4ad4 --- /dev/null +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_unix.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +} + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet."); + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup) + QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet"); + return false; +} diff --git a/QextSerialPort/qextserialenumerator_win.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_win.cpp similarity index 68% rename from QextSerialPort/qextserialenumerator_win.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_win.cpp index 662708f..55b71aa 100644 --- a/QextSerialPort/qextserialenumerator_win.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialenumerator_win.cpp @@ -1,302 +1,320 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialenumerator.h" -#include "qextserialenumerator_p.h" -#include -#include -#include -#include -#include -#include -#include -#include "qextserialport.h" - -#ifdef QT_GUI_LIB -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) -#include -class QextSerialRegistrationWidget : public QWidget -#else -#include -class QextSerialRegistrationWidget : public QWindow -#endif -{ -public: - QextSerialRegistrationWidget(QextSerialEnumeratorPrivate* qese) { - this->qese = qese; - } - ~QextSerialRegistrationWidget() {} - -protected: - -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - bool winEvent( MSG* message, long* result ) { -#else - bool nativeEvent(const QByteArray & /*eventType*/, void *msg, long *result) { - MSG *message = static_cast(msg); -#endif - if ( message->message == WM_DEVICECHANGE ) { - qese->onDeviceChanged(message->wParam, message->lParam ); - *result = 1; - return true; - } - return false; - } -private: - QextSerialEnumeratorPrivate* qese; -}; - -#endif // QT_GUI_LIB - -void QextSerialEnumeratorPrivate::platformSpecificInit() -{ -#ifdef QT_GUI_LIB - notificationWidget = 0; -#endif // QT_GUI_LIB -} - -/*! - default -*/ -void QextSerialEnumeratorPrivate::platformSpecificDestruct() -{ -#ifdef QT_GUI_LIB - if( notificationWidget ) - delete notificationWidget; -#endif -} - -// see http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426(v=vs.85).aspx -// for list of GUID classes -#ifndef GUID_DEVCLASS_PORTS - DEFINE_GUID(GUID_DEVCLASS_PORTS, 0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 ); -#endif - -/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ -#ifdef UNICODE - #define QStringToTCHAR(x) (wchar_t*) x.utf16() - #define PQStringToTCHAR(x) (wchar_t*) x->utf16() - #define TCHARToQString(x) QString::fromUtf16((ushort*)(x)) - #define TCHARToQStringN(x,y) QString::fromUtf16((ushort*)(x),(y)) -#else - #define QStringToTCHAR(x) x.local8Bit().constData() - #define PQStringToTCHAR(x) x->local8Bit().constData() - #define TCHARToQString(x) QString::fromLocal8Bit((char*)(x)) - #define TCHARToQStringN(x,y) QString::fromLocal8Bit((char*)(x),(y)) -#endif /*UNICODE*/ - -/*! - \internal - Get value of specified property from the registry. - \a key handle to an open key. - \a property property name. - - return property value. -*/ -static QString getRegKeyValue(HKEY key, LPCTSTR property) -{ - DWORD size = 0; - DWORD type; - ::RegQueryValueEx(key, property, NULL, NULL, NULL, & size); - BYTE* buff = new BYTE[size]; - QString result; - if(::RegQueryValueEx(key, property, NULL, &type, buff, & size) == ERROR_SUCCESS ) - result = TCHARToQString(buff); - ::RegCloseKey(key); - delete [] buff; - return result; -} - -/*! - \internal - Get specific property from registry. - \a devInfo pointer to the device information set that contains the interface - and its underlying device. Returned by SetupDiGetClassDevs() function. - \a devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. - this is returned by SetupDiGetDeviceInterfaceDetail() function. - \a property registry property. One of defined SPDRP_* constants. - - return property string. - */ -static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) -{ - DWORD buffSize = 0; - ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, & buffSize); - BYTE* buff = new BYTE[buffSize]; - ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); - QString result = TCHARToQString(buff); - delete [] buff; - return result; -} - -/*! - \internal -*/ -static bool getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData - , WPARAM wParam = DBT_DEVICEARRIVAL) -{ - portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME); - if( wParam == DBT_DEVICEARRIVAL) - portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); - portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME); - QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID); - HKEY devKey = ::SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); - portInfo->portName = getRegKeyValue(devKey, TEXT("PortName")); - QRegExp idRx(QLatin1String("VID_(\\w+)&PID_(\\w+)")); - if(hardwareIDs.toUpper().contains(idRx)) { - bool dummy; - portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16); - portInfo->productID = idRx.cap(2).toInt(&dummy, 16); - //qDebug() << "got vid:" << vid << "pid:" << pid; - } - return true; -} - -/*! - \internal -*/ -static void enumerateDevicesWin( const GUID & guid, QList* infoList ) -{ - HDEVINFO devInfo; - if( (devInfo = ::SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE) { - SP_DEVINFO_DATA devInfoData; - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for(int i = 0; ::SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { - QextPortInfo info; - info.productID = info.vendorID = 0; - getDeviceDetailsWin( &info, devInfo, &devInfoData ); - infoList->append(info); - } - ::SetupDiDestroyDeviceInfoList(devInfo); - } -} - - -static bool lessThan(const QextPortInfo &s1, const QextPortInfo &s2) -{ - if (s1.portName.startsWith(QLatin1String("COM")) - && s2.portName.startsWith(QLatin1String("COM"))) { - return s1.portName.mid(3).toInt() QextSerialEnumeratorPrivate::getPorts_sys() -{ - QList ports; - enumerateDevicesWin(GUID_DEVCLASS_PORTS, &ports); - qSort(ports.begin(), ports.end(), lessThan); - return ports; -} - - -/* - Enable event-driven notifications of board discovery/removal. -*/ -bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) -{ -#ifndef QT_GUI_LIB - Q_UNUSED(setup) - QESP_WARNING("QextSerialEnumerator: GUI not enabled - can't register for device notifications."); - return false; -#else - Q_Q(QextSerialEnumerator); - if(setup && notificationWidget) //already setup - return true; - notificationWidget = new QextSerialRegistrationWidget(this); - - DEV_BROADCAST_DEVICEINTERFACE dbh; - ::ZeroMemory(&dbh, sizeof(dbh)); - dbh.dbcc_size = sizeof(dbh); - dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - ::CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID)); - if(::RegisterDeviceNotification((HWND)notificationWidget->winId(), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL) { - QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError(); - return false; - } - // setting up notifications doesn't tell us about devices already connected - // so get those manually - foreach(QextPortInfo port, getPorts_sys()) - Q_EMIT q->deviceDiscovered(port); - return true; -#endif // QT_GUI_LIB -} - -LRESULT QextSerialEnumeratorPrivate::onDeviceChanged( WPARAM wParam, LPARAM lParam ) -{ - if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) { - PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; - if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) { - PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; - // delimiters are different across APIs...change to backslash. ugh. - QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace(QLatin1String("#"), QLatin1String("\\")); - - matchAndDispatchChangedDevice(deviceID, GUID_DEVCLASS_PORTS, wParam); - } - } - return 0; -} - -bool QextSerialEnumeratorPrivate::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam) -{ - Q_Q(QextSerialEnumerator); - bool rv = false; - DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES; - HDEVINFO devInfo; - if( (devInfo = SetupDiGetClassDevs(&guid,NULL,NULL,dwFlag)) != INVALID_HANDLE_VALUE ) { - SP_DEVINFO_DATA spDevInfoData; - spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for(int i=0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++) { - DWORD nSize=0 ; - TCHAR buf[MAX_PATH]; - if ( SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && - deviceID.contains(TCHARToQString(buf))) { // we found a match - rv = true; - QextPortInfo info; - info.productID = info.vendorID = 0; - getDeviceDetailsWin( &info, devInfo, &spDevInfoData, wParam ); - if( wParam == DBT_DEVICEARRIVAL ) - Q_EMIT q->deviceDiscovered(info); - else if( wParam == DBT_DEVICEREMOVECOMPLETE ) - Q_EMIT q->deviceRemoved(info); - break; - } - } - SetupDiDestroyDeviceInfoList(devInfo); - } - return rv; -} +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "qextserialport.h" + +#ifdef QT_GUI_LIB +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +class QextSerialRegistrationWidget : public QWidget +#else +#include +class QextSerialRegistrationWidget : public QWindow +#endif +{ +public: + QextSerialRegistrationWidget(QextSerialEnumeratorPrivate *qese) { + this->qese = qese; + } + ~QextSerialRegistrationWidget() {} + +protected: + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + bool winEvent(MSG *message, long *result) { +#else + bool nativeEvent(const QByteArray & /*eventType*/, void *msg, long *result) { + MSG *message = static_cast(msg); +#endif + if (message->message == WM_DEVICECHANGE) { + qese->onDeviceChanged(message->wParam, message->lParam); + *result = 1; + return true; + } + return false; + } +private: + QextSerialEnumeratorPrivate *qese; +}; + +#endif // QT_GUI_LIB + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifdef QT_GUI_LIB + notificationWidget = 0; +#endif // QT_GUI_LIB +} + +/*! + default +*/ +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifdef QT_GUI_LIB + if (notificationWidget) + delete notificationWidget; +#endif +} + +// see http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426(v=vs.85).aspx +// for list of GUID classes +const GUID deviceClassGuids[] = +{ + // Ports (COM & LPT ports), Class = Ports + {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Modem, Class = Modem + {0x4D36E96D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Bluetooth Devices, Class = Bluetooth + {0xE0CBF06C, 0xCD8B, 0x4647, {0xBB, 0x8A, 0x26, 0x3B, 0x43, 0xF0, 0xF9, 0x74}}, + // Added by Arne Kristian Jansen, for use with com0com virtual ports (See Issue 54) + {0xDF799E12, 0x3C56, 0x421B, {0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78}} +}; + +/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ +#ifdef UNICODE + #define QStringToTCHAR(x) (wchar_t *) x.utf16() + #define PQStringToTCHAR(x) (wchar_t *) x->utf16() + #define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) + #define TCHARToQStringN(x,y) QString::fromUtf16((ushort *)(x),(y)) +#else + #define QStringToTCHAR(x) x.local8Bit().constData() + #define PQStringToTCHAR(x) x->local8Bit().constData() + #define TCHARToQString(x) QString::fromLocal8Bit((char *)(x)) + #define TCHARToQStringN(x,y) QString::fromLocal8Bit((char *)(x),(y)) +#endif /*UNICODE*/ + +/*! + \internal + Get value of specified property from the registry. + \a key handle to an open key. + \a property property name. + + return property value. +*/ +static QString getRegKeyValue(HKEY key, LPCTSTR property) +{ + DWORD size = 0; + DWORD type; + ::RegQueryValueEx(key, property, NULL, NULL, NULL, &size); + BYTE *buff = new BYTE[size]; + QString result; + if (::RegQueryValueEx(key, property, NULL, &type, buff, &size) == ERROR_SUCCESS) + result = TCHARToQString(buff); + ::RegCloseKey(key); + delete [] buff; + return result; +} + +/*! + \internal + Get specific property from registry. + \a devInfo pointer to the device information set that contains the interface + and its underlying device. Returned by SetupDiGetClassDevs() function. + \a devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. + this is returned by SetupDiGetDeviceInterfaceDetail() function. + \a property registry property. One of defined SPDRP_* constants. + + return property string. + */ +static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) +{ + DWORD buffSize = 0; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); + BYTE *buff = new BYTE[buffSize]; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); + QString result = TCHARToQString(buff); + delete [] buff; + return result; +} + +/*! + \internal +*/ +static bool getDeviceDetailsWin(QextPortInfo *portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData + , WPARAM wParam = DBT_DEVICEARRIVAL) +{ + portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME); + if (wParam == DBT_DEVICEARRIVAL) + portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); + portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME); + QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID); + HKEY devKey = ::SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + portInfo->portName = getRegKeyValue(devKey, TEXT("PortName")); + QRegExp idRx(QLatin1String("VID_(\\w+)&PID_(\\w+)")); + if (hardwareIDs.toUpper().contains(idRx)) { + bool dummy; + portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16); + portInfo->productID = idRx.cap(2).toInt(&dummy, 16); + //qDebug() << "got vid:" << vid << "pid:" << pid; + } + return true; +} + +/*! + \internal +*/ +static void enumerateDevicesWin(const GUID &guid, QList *infoList) +{ + HDEVINFO devInfo; + if ((devInfo = ::SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE) { + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for(int i = 0; ::SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + QextPortInfo info; + info.productID = info.vendorID = 0; + getDeviceDetailsWin(&info, devInfo, &devInfoData); + if (!info.portName.startsWith(QLatin1String("LPT"), Qt::CaseInsensitive)) + infoList->append(info); + } + ::SetupDiDestroyDeviceInfoList(devInfo); + } +} + + +static bool lessThan(const QextPortInfo &s1, const QextPortInfo &s2) +{ + if (s1.portName.startsWith(QLatin1String("COM")) + && s2.portName.startsWith(QLatin1String("COM"))) { + return s1.portName.mid(3).toInt() QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList ports; + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; iwinId(), &dbh, flags) == NULL) { + QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError(); + return false; + } + // setting up notifications doesn't tell us about devices already connected + // so get those manually + foreach (QextPortInfo port, getPorts_sys()) + Q_EMIT q->deviceDiscovered(port); + return true; +#endif // QT_GUI_LIB +} + +LRESULT QextSerialEnumeratorPrivate::onDeviceChanged(WPARAM wParam, LPARAM lParam) +{ + if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + // delimiters are different across APIs...change to backslash. ugh. + QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace(QLatin1String("#"), QLatin1String("\\")); + + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; ideviceDiscovered(info); + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + Q_EMIT q->deviceRemoved(info); + break; + } + } + SetupDiDestroyDeviceInfoList(devInfo); + } + return rv; +} diff --git a/QextSerialPort/qextserialport.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.cpp similarity index 90% rename from QextSerialPort/qextserialport.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport.cpp index c3d5fd8..119bef8 100644 --- a/QextSerialPort/qextserialport.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.cpp @@ -1,1011 +1,1011 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialport.h" -#include "qextserialport_p.h" -#include -#include -#include -#include - -/*! - \class PortSettings - - \brief The PortSettings class contain port settings - - Structure to contain port settings. - - \code - BaudRateType BaudRate; - DataBitsType DataBits; - ParityType Parity; - StopBitsType StopBits; - FlowType FlowControl; - long Timeout_Millisec; - \endcode -*/ - -QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q) - :lock(QReadWriteLock::Recursive), q_ptr(q) -{ - lastErr = E_NO_ERROR; - Settings.BaudRate = BAUD9600; - Settings.Parity = PAR_NONE; - Settings.FlowControl = FLOW_OFF; - Settings.DataBits = DATA_8; - Settings.StopBits = STOP_1; - Settings.Timeout_Millisec = 10; - settingsDirtyFlags = DFE_ALL; - - platformSpecificInit(); -} - -QextSerialPortPrivate::~QextSerialPortPrivate() -{ - platformSpecificDestruct(); -} - -void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update) -{ - switch (baudRate) { -#ifdef Q_OS_WIN - //Windows Special - case BAUD14400: - case BAUD56000: - case BAUD128000: - case BAUD256000: - QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<isOpen()) - updatePortSettings(); - break; -#ifndef Q_OS_WIN - default: - QESP_WARNING()<<"QextSerialPort does not support baudRate:"<isOpen()) - updatePortSettings(); -} - -void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update) -{ - switch(dataBits) { - - case DATA_5: - if (Settings.StopBits==STOP_2) { - QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); - } - else { - Settings.DataBits=dataBits; - settingsDirtyFlags |= DFE_DataBits; - } - break; - - case DATA_6: -#ifdef Q_OS_WIN - if (Settings.StopBits==STOP_1_5) { - QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); - } - else -#endif - { - Settings.DataBits=dataBits; - settingsDirtyFlags |= DFE_DataBits; - } - break; - - case DATA_7: -#ifdef Q_OS_WIN - if (Settings.StopBits==STOP_1_5) { - QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); - } - else -#endif - { - Settings.DataBits=dataBits; - settingsDirtyFlags |= DFE_DataBits; - } - break; - - case DATA_8: -#ifdef Q_OS_WIN - if (Settings.StopBits==STOP_1_5) { - QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); - } - else -#endif - { - Settings.DataBits=dataBits; - settingsDirtyFlags |= DFE_DataBits; - } - break; - default: - QESP_WARNING()<<"QextSerialPort does not support Data bits:"<isOpen()) - updatePortSettings(); -} - -void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update) -{ - switch (stopBits) { - - /*one stop bit*/ - case STOP_1: - Settings.StopBits = stopBits; - settingsDirtyFlags |= DFE_StopBits; - break; - -#ifdef Q_OS_WIN - /*1.5 stop bits*/ - case STOP_1_5: - QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); - if (Settings.DataBits!=DATA_5) { - QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); - } - else { - Settings.StopBits = stopBits; - settingsDirtyFlags |= DFE_StopBits; - } - break; -#endif - - /*two stop bits*/ - case STOP_2: - if (Settings.DataBits==DATA_5) { - QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits"); - } - else { - Settings.StopBits = stopBits; - settingsDirtyFlags |= DFE_StopBits; - } - break; - default: - QESP_WARNING()<<"QextSerialPort does not support stop bits: "<isOpen()) - updatePortSettings(); -} - -void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update) -{ - Settings.FlowControl=flow; - settingsDirtyFlags |= DFE_Flow; - if (update && q_func()->isOpen()) - updatePortSettings(); -} - -void QextSerialPortPrivate::setTimeout(long millisec, bool update) -{ - Settings.Timeout_Millisec = millisec; - settingsDirtyFlags |= DFE_TimeOut; - if (update && q_func()->isOpen()) - updatePortSettings(); -} - -void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update) -{ - setBaudRate(settings.BaudRate, false); - setDataBits(settings.DataBits, false); - setStopBits(settings.StopBits, false); - setParity(settings.Parity, false); - setFlowControl(settings.FlowControl, false); - setTimeout(settings.Timeout_Millisec, false); - settingsDirtyFlags = DFE_ALL; - if (update && q_func()->isOpen()) - updatePortSettings(); -} - - -void QextSerialPortPrivate::_q_canRead() -{ - qint64 maxSize = bytesAvailable_sys(); - if (maxSize > 0) { - char * writePtr = readBuffer.reserve(size_t(maxSize)); - qint64 bytesRead = readData_sys(writePtr, maxSize); - if (bytesRead < maxSize) - readBuffer.chop(maxSize - bytesRead); - Q_Q(QextSerialPort); - Q_EMIT q->readyRead(); - } -} - -/*! \class QextSerialPort - - \brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems. - - \section1 Usage - QextSerialPort offers both a polling and event driven API. Event driven - is typically easier to use, since you never have to worry about checking - for new data. - - \bold Example - \code - QextSerialPort* port = new QextSerialPort("COM1"); - connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable())); - port->open(); - - void MyClass::onDataAvailable() - { - QByteArray data = port->readAll(); - processNewData(usbdata); - } - \endcode - - \section1 Compatibility - The user will be notified of errors and possible portability conflicts at run-time - by default. - - For example, if a application has used BAUD1800, when it is runing under unix, you - will get following message. - - \code - QextSerialPort Portability Warning: Windows does not support baudRate:1800 - \endcode - - This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings) - or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project. - - - \bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang -*/ - -/*! - \enum QextSerialPort::QueryMode - - This enum type specifies query mode used in a serial port: - - \value Polling - asynchronously read and write - \value EventDriven - synchronously read and write -*/ - -/*! - \fn void QextSerialPort::dsrChanged(bool status) - This signal is emitted whenever dsr line has changed its state. You may - use this signal to check if device is connected. - - \a status true when DSR signal is on, false otherwise. - */ - - -/*! - \fn QueryMode QextSerialPort::queryMode() const - Get query mode. - */ - -/*! - Default constructor. Note that the name of the device used by a QextSerialPort is dependent on - your OS. Possible naming conventions and their associated OS are: - - \code - - OS Constant Used By Naming Convention - ------------- ------------- ------------------------ - Q_OS_WIN Windows COM1, COM2 - Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2 - Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0 - Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb - Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02 - Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1 - Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01 - Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1 - /dev/ttyS0, /dev/ttyS1 - \endcode - - This constructor assigns the device name to the name of the first port on the specified system. - See the other constructors if you need to open a different port. Default \a mode is EventDriven. - As a subclass of QObject, \a parent can be specified. -*/ - -QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent) - : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) -{ -#ifdef Q_OS_WIN - setPortName(QLatin1String("COM1")); - -#elif defined(Q_OS_IRIX) - setPortName(QLatin1String("/dev/ttyf1")); - -#elif defined(Q_OS_HPUX) - setPortName(QLatin1String("/dev/tty1p0")); - -#elif defined(Q_OS_SOLARIS) - setPortName(QLatin1String("/dev/ttya")); - -#elif defined(Q_OS_OSF) //formally DIGITAL UNIX - setPortName(QLatin1String("/dev/tty01")); - -#elif defined(Q_OS_FREEBSD) - setPortName(QLatin1String("/dev/ttyd1")); - -#elif defined(Q_OS_OPENBSD) - setPortName(QLatin1String("/dev/tty00")); - -#else - setPortName(QLatin1String("/dev/ttyS0")); -#endif - setQueryMode(mode); -} - -/*! - Constructs a serial port attached to the port specified by name. - \a name is the name of the device, which is windowsystem-specific, - e.g."COM1" or "/dev/ttyS0". \a mode -*/ -QextSerialPort::QextSerialPort(const QString & name, QextSerialPort::QueryMode mode, QObject *parent) - : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) -{ - setQueryMode(mode); - setPortName(name); -} - -/*! - Constructs a port with default name and specified \a settings. -*/ -QextSerialPort::QextSerialPort(const PortSettings& settings, QextSerialPort::QueryMode mode, QObject *parent) - : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) -{ - Q_D(QextSerialPort); - setQueryMode(mode); - d->setPortSettings(settings); -} - -/*! - Constructs a port with specified \a name , \a mode and \a settings. -*/ -QextSerialPort::QextSerialPort(const QString & name, const PortSettings& settings, QextSerialPort::QueryMode mode, QObject *parent) - : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) -{ - Q_D(QextSerialPort); - setPortName(name); - setQueryMode(mode); - d->setPortSettings(settings); -} - -/*! - Opens a serial port and sets its OpenMode to \a mode. - Note that this function does not specify which device to open. - Returns true if successful; otherwise returns false.This function has no effect - if the port associated with the class is already open. The port is also - configured to the current settings, as stored in the Settings structure. -*/ -bool QextSerialPort::open(OpenMode mode) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (mode != QIODevice::NotOpen && !isOpen()) - d->open_sys(mode); - - return isOpen(); -} - - -/*! \reimp - Closes a serial port. This function has no effect if the serial port associated with the class - is not currently open. -*/ -void QextSerialPort::close() -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (isOpen()) { - // Be a good QIODevice and call QIODevice::close() before really close() - // so the aboutToClose() signal is emitted at the proper time - QIODevice::close(); // mark ourselves as closed - d->close_sys(); - d->readBuffer.clear(); - } -} - -/*! - Flushes all pending I/O to the serial port. This function has no effect if the serial port - associated with the class is not currently open. -*/ -void QextSerialPort::flush() -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (isOpen()) - d->flush_sys(); -} - -/*! \reimp - Returns the number of bytes waiting in the port's receive queue. This function will return 0 if - the port is not currently open, or -1 on error. -*/ -qint64 QextSerialPort::bytesAvailable() const -{ - QWriteLocker locker(&d_func()->lock); - if (isOpen()) { - qint64 bytes = d_func()->bytesAvailable_sys(); - if (bytes != -1) { - return bytes + d_func()->readBuffer.size() - + QIODevice::bytesAvailable(); - } else { - return -1; - } - } - return 0; -} - -/*! \reimp - -*/ -bool QextSerialPort::canReadLine() const -{ - QReadLocker locker(&d_func()->lock); - return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine(); -} - -/*! - * Set desired serial communication handling style. You may choose from polling - * or event driven approach. This function does nothing when port is open; to - * apply changes port must be reopened. - * - * In event driven approach read() and write() functions are acting - * asynchronously. They return immediately and the operation is performed in - * the background, so they doesn't freeze the calling thread. - * To determine when operation is finished, QextSerialPort runs separate thread - * and monitors serial port events. Whenever the event occurs, adequate signal - * is emitted. - * - * When polling is set, read() and write() are acting synchronously. Signals are - * not working in this mode and some functions may not be available. The advantage - * of polling is that it generates less overhead due to lack of signals emissions - * and it doesn't start separate thread to monitor events. - * - * Generally event driven approach is more capable and friendly, although some - * applications may need as low overhead as possible and then polling comes. - * - * \a mode query mode. - */ -void QextSerialPort::setQueryMode(QueryMode mode) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (mode != d->_queryMode) { - d->_queryMode = mode; - } -} - -/*! - Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". -*/ -void QextSerialPort::setPortName(const QString & name) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - d->port = name; -} - -/*! - Returns the name set by setPortName(). -*/ -QString QextSerialPort::portName() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->port; -} - -QextSerialPort::QueryMode QextSerialPort::queryMode() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->_queryMode; -} - -/*! - Reads all available data from the device, and returns it as a QByteArray. - This function has no way of reporting errors; returning an empty QByteArray() - can mean either that no data was currently available for reading, or that an error occurred. -*/ -QByteArray QextSerialPort::readAll() -{ - int avail = this->bytesAvailable(); - return (avail > 0) ? this->read(avail) : QByteArray(); -} - -/*! - Returns the baud rate of the serial port. For a list of possible return values see - the definition of the enum BaudRateType. -*/ -BaudRateType QextSerialPort::baudRate() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->Settings.BaudRate; -} - -/*! - Returns the number of data bits used by the port. For a list of possible values returned by - this function, see the definition of the enum DataBitsType. -*/ -DataBitsType QextSerialPort::dataBits() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->Settings.DataBits; -} - -/*! - Returns the type of parity used by the port. For a list of possible values returned by - this function, see the definition of the enum ParityType. -*/ -ParityType QextSerialPort::parity() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->Settings.Parity; -} - -/*! - Returns the number of stop bits used by the port. For a list of possible return values, see - the definition of the enum StopBitsType. -*/ -StopBitsType QextSerialPort::stopBits() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->Settings.StopBits; -} - -/*! - Returns the type of flow control used by the port. For a list of possible values returned - by this function, see the definition of the enum FlowType. -*/ -FlowType QextSerialPort::flowControl() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->Settings.FlowControl; -} - -/*! - \reimp - Returns true if device is sequential, otherwise returns false. Serial port is sequential device - so this function always returns true. Check QIODevice::isSequential() documentation for more - information. -*/ -bool QextSerialPort::isSequential() const -{ - return true; -} - -/*! - Return the error number, or 0 if no error occurred. -*/ -ulong QextSerialPort::lastError() const -{ - QReadLocker locker(&d_func()->lock); - return d_func()->lastErr; -} - -/*! - Returns the line status as stored by the port function. This function will retrieve the states - of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines - can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned - long with specific bits indicating which lines are high. The following constants should be used - to examine the states of individual lines: - - \code - Mask Line - ------ ---- - LS_CTS CTS - LS_DSR DSR - LS_DCD DCD - LS_RI RI - LS_RTS RTS (POSIX only) - LS_DTR DTR (POSIX only) - LS_ST Secondary TXD (POSIX only) - LS_SR Secondary RXD (POSIX only) - \endcode - - This function will return 0 if the port associated with the class is not currently open. -*/ -unsigned long QextSerialPort::lineStatus() -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (isOpen()) - return d->lineStatus_sys(); - return 0; -} - -/*! - Returns a human-readable description of the last device error that occurred. -*/ -QString QextSerialPort::errorString() -{ - Q_D(QextSerialPort); - QReadLocker locker(&d->lock); - switch(d->lastErr) { - case E_NO_ERROR: - return tr("No Error has occurred"); - case E_INVALID_FD: - return tr("Invalid file descriptor (port was not opened correctly)"); - case E_NO_MEMORY: - return tr("Unable to allocate memory tables (POSIX)"); - case E_CAUGHT_NON_BLOCKED_SIGNAL: - return tr("Caught a non-blocked signal (POSIX)"); - case E_PORT_TIMEOUT: - return tr("Operation timed out (POSIX)"); - case E_INVALID_DEVICE: - return tr("The file opened by the port is not a valid device"); - case E_BREAK_CONDITION: - return tr("The port detected a break condition"); - case E_FRAMING_ERROR: - return tr("The port detected a framing error (usually caused by incorrect baud rate settings)"); - case E_IO_ERROR: - return tr("There was an I/O error while communicating with the port"); - case E_BUFFER_OVERRUN: - return tr("Character buffer overrun"); - case E_RECEIVE_OVERFLOW: - return tr("Receive buffer overflow"); - case E_RECEIVE_PARITY_ERROR: - return tr("The port detected a parity error in the received data"); - case E_TRANSMIT_OVERFLOW: - return tr("Transmit buffer overflow"); - case E_READ_FAILED: - return tr("General read operation failure"); - case E_WRITE_FAILED: - return tr("General write operation failure"); - case E_FILE_NOT_FOUND: - return tr("The %1 file doesn't exists").arg(this->portName()); - case E_PERMISSION_DENIED: - return tr("Permission denied"); - case E_AGAIN: - return tr("Device is already locked"); - default: - return tr("Unknown error: %1").arg(d->lastErr); - } -} - -/*! - Destructs the QextSerialPort object. -*/ -QextSerialPort::~QextSerialPort() -{ - if (isOpen()) { - close(); - } - delete d_ptr; -} - -/*! - Sets the flow control used by the port to \a flow. Possible values of flow are: - \code - FLOW_OFF No flow control - FLOW_HARDWARE Hardware (RTS/CTS) flow control - FLOW_XONXOFF Software (XON/XOFF) flow control - \endcode -*/ -void QextSerialPort::setFlowControl(FlowType flow) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.FlowControl != flow) - d->setFlowControl(flow, true); -} - -/*! - Sets the parity associated with the serial port to \a parity. The possible values of parity are: - \code - PAR_SPACE Space Parity - PAR_MARK Mark Parity - PAR_NONE No Parity - PAR_EVEN Even Parity - PAR_ODD Odd Parity - \endcode -*/ -void QextSerialPort::setParity(ParityType parity) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.Parity != parity) - d->setParity(parity, true); -} - -/*! - Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are: - \code - DATA_5 5 data bits - DATA_6 6 data bits - DATA_7 7 data bits - DATA_8 8 data bits - \endcode - - \bold note: - This function is subject to the following restrictions: - \list - \o 5 data bits cannot be used with 2 stop bits. - \o 1.5 stop bits can only be used with 5 data bits. - \o 8 data bits cannot be used with space parity on POSIX systems. - \endlist - */ -void QextSerialPort::setDataBits(DataBitsType dataBits) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.DataBits != dataBits) - d->setDataBits(dataBits, true); -} - -/*! - Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are: - \code - STOP_1 1 stop bit - STOP_1_5 1.5 stop bits - STOP_2 2 stop bits - \endcode - - \bold note: - This function is subject to the following restrictions: - \list - \o 2 stop bits cannot be used with 5 data bits. - \o 1.5 stop bits cannot be used with 6 or more data bits. - \o POSIX does not support 1.5 stop bits. - \endlist -*/ -void QextSerialPort::setStopBits(StopBitsType stopBits) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.StopBits != stopBits) - d->setStopBits(stopBits, true); -} - -/*! - Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on - all platforms. The following table shows translations of the various baud rate - constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * - are speeds that are usable on both Windows and POSIX. - \code - - RATE Windows Speed POSIX Speed - ----------- ------------- ----------- - BAUD50 X 50 - BAUD75 X 75 - *BAUD110 110 110 - BAUD134 X 134.5 - BAUD150 X 150 - BAUD200 X 200 - *BAUD300 300 300 - *BAUD600 600 600 - *BAUD1200 1200 1200 - BAUD1800 X 1800 - *BAUD2400 2400 2400 - *BAUD4800 4800 4800 - *BAUD9600 9600 9600 - BAUD14400 14400 X - *BAUD19200 19200 19200 - *BAUD38400 38400 38400 - BAUD56000 56000 X - *BAUD57600 57600 57600 - BAUD76800 X 76800 - *BAUD115200 115200 115200 - BAUD128000 128000 X - BAUD230400 X 230400 - BAUD256000 256000 X - BAUD460800 X 460800 - BAUD500000 X 500000 - BAUD576000 X 576000 - BAUD921600 X 921600 - BAUD1000000 X 1000000 - BAUD1152000 X 1152000 - BAUD1500000 X 1500000 - BAUD2000000 X 2000000 - BAUD2500000 X 2500000 - BAUD3000000 X 3000000 - BAUD3500000 X 3500000 - BAUD4000000 X 4000000 - \endcode -*/ - -void QextSerialPort::setBaudRate(BaudRateType baudRate) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.BaudRate != baudRate) - d->setBaudRate(baudRate, true); -} - -/*! - For Unix: - - Sets the read and write timeouts for the port to \a millisec milliseconds. - Note that this is a per-character timeout, i.e. the port will wait this long for each - individual character, not for the whole read operation. This timeout also applies to the - bytesWaiting() function. - - \bold note: - POSIX does not support millisecond-level control for I/O timeout values. Any - timeout set using this function will be set to the next lowest tenth of a second for - the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds - will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and - writing the port. However millisecond-level control is allowed by the select() system call, - so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for - the purpose of detecting available bytes in the read buffer. - - For Windows: - - Sets the read and write timeouts for the port to \a millisec milliseconds. - Setting 0 indicates that timeouts are not used for read nor write operations; - however read() and write() functions will still block. Set -1 to provide - non-blocking behaviour (read() and write() will return immediately). - - \bold note: this function does nothing in event driven mode. -*/ -void QextSerialPort::setTimeout(long millisec) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (d->Settings.Timeout_Millisec != millisec) - d->setTimeout(millisec, true); -} - -/*! - Sets DTR line to the requested state (\a set default to high). This function will have no effect if - the port associated with the class is not currently open. -*/ -void QextSerialPort::setDtr(bool set) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (isOpen()) - d->setDtr_sys(set); -} - -/*! - Sets RTS line to the requested state \a set (high by default). - This function will have no effect if - the port associated with the class is not currently open. -*/ -void QextSerialPort::setRts(bool set) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - if (isOpen()) - d->setRts_sys(set); -} - -/*! \reimp - Reads a block of data from the serial port. This function will read at most maxlen bytes from - the serial port and place them in the buffer pointed to by data. Return value is the number of - bytes actually read, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPort::readData(char *data, qint64 maxSize) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - qint64 bytesFromBuffer = 0; - if (!d->readBuffer.isEmpty()) { - bytesFromBuffer = d->readBuffer.read(data, maxSize); - if (bytesFromBuffer == maxSize) - return bytesFromBuffer; - } - qint64 bytesFromDevice = d->readData_sys(data+bytesFromBuffer, maxSize-bytesFromBuffer); - if (bytesFromDevice < 0) { - return -1; - } - return bytesFromBuffer + bytesFromDevice; -} - -/*! \reimp - Writes a block of data to the serial port. This function will write len bytes - from the buffer pointed to by data to the serial port. Return value is the number - of bytes actually written, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPort::writeData(const char *data, qint64 maxSize) -{ - Q_D(QextSerialPort); - QWriteLocker locker(&d->lock); - return d->writeData_sys(data, maxSize); -} - -#include "moc_qextserialport.cpp" +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include + +/*! + \class PortSettings + + \brief The PortSettings class contain port settings + + Structure to contain port settings. + + \code + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; + \endcode +*/ + +QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q) + :lock(QReadWriteLock::Recursive), q_ptr(q) +{ + lastErr = E_NO_ERROR; + settings.BaudRate = BAUD9600; + settings.Parity = PAR_NONE; + settings.FlowControl = FLOW_OFF; + settings.DataBits = DATA_8; + settings.StopBits = STOP_1; + settings.Timeout_Millisec = 10; + settingsDirtyFlags = DFE_ALL; + + platformSpecificInit(); +} + +QextSerialPortPrivate::~QextSerialPortPrivate() +{ + platformSpecificDestruct(); +} + +void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update) +{ + switch (baudRate) { +#ifdef Q_OS_WIN + //Windows Special + case BAUD14400: + case BAUD56000: + case BAUD128000: + case BAUD256000: + QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<isOpen()) + updatePortSettings(); + break; +#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC)) + default: + QESP_WARNING()<<"QextSerialPort does not support baudRate:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update) +{ + switch(dataBits) { + + case DATA_5: + if (settings.StopBits == STOP_2) { + QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); + } + else { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_6: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_7: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_8: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support Data bits:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update) +{ + switch (stopBits) { + + /*one stop bit*/ + case STOP_1: + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + break; + +#ifdef Q_OS_WIN + /*1.5 stop bits*/ + case STOP_1_5: + QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); + if (settings.DataBits != DATA_5) { + QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; +#endif + + /*two stop bits*/ + case STOP_2: + if (settings.DataBits == DATA_5) { + QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support stop bits: "<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update) +{ + settings.FlowControl = flow; + settingsDirtyFlags |= DFE_Flow; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setTimeout(long millisec, bool update) +{ + settings.Timeout_Millisec = millisec; + settingsDirtyFlags |= DFE_TimeOut; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update) +{ + setBaudRate(settings.BaudRate, false); + setDataBits(settings.DataBits, false); + setStopBits(settings.StopBits, false); + setParity(settings.Parity, false); + setFlowControl(settings.FlowControl, false); + setTimeout(settings.Timeout_Millisec, false); + settingsDirtyFlags = DFE_ALL; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + + +void QextSerialPortPrivate::_q_canRead() +{ + qint64 maxSize = bytesAvailable_sys(); + if (maxSize > 0) { + char *writePtr = readBuffer.reserve(size_t(maxSize)); + qint64 bytesRead = readData_sys(writePtr, maxSize); + if (bytesRead < maxSize) + readBuffer.chop(maxSize - bytesRead); + Q_Q(QextSerialPort); + Q_EMIT q->readyRead(); + } +} + +/*! \class QextSerialPort + + \brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems. + + \section1 Usage + QextSerialPort offers both a polling and event driven API. Event driven + is typically easier to use, since you never have to worry about checking + for new data. + + \bold Example + \code + QextSerialPort *port = new QextSerialPort("COM1"); + connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable())); + port->open(); + + void MyClass::onDataAvailable() + { + QByteArray data = port->readAll(); + processNewData(usbdata); + } + \endcode + + \section1 Compatibility + The user will be notified of errors and possible portability conflicts at run-time + by default. + + For example, if a application has used BAUD1800, when it is runing under unix, you + will get following message. + + \code + QextSerialPort Portability Warning: Windows does not support baudRate:1800 + \endcode + + This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings) + or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project. + + + \bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang +*/ + +/*! + \enum QextSerialPort::QueryMode + + This enum type specifies query mode used in a serial port: + + \value Polling + asynchronously read and write + \value EventDriven + synchronously read and write +*/ + +/*! + \fn void QextSerialPort::dsrChanged(bool status) + This signal is emitted whenever dsr line has changed its state. You may + use this signal to check if device is connected. + + \a status true when DSR signal is on, false otherwise. + */ + + +/*! + \fn QueryMode QextSerialPort::queryMode() const + Get query mode. + */ + +/*! + Default constructor. Note that the name of the device used by a QextSerialPort is dependent on + your OS. Possible naming conventions and their associated OS are: + + \code + + OS Constant Used By Naming Convention + ------------- ------------- ------------------------ + Q_OS_WIN Windows COM1, COM2 + Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2 + Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0 + Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb + Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02 + Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1 + Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01 + Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1 + /dev/ttyS0, /dev/ttyS1 + \endcode + + This constructor assigns the device name to the name of the first port on the specified system. + See the other constructors if you need to open a different port. Default \a mode is EventDriven. + As a subclass of QObject, \a parent can be specified. +*/ + +QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ +#ifdef Q_OS_WIN + setPortName(QLatin1String("COM1")); + +#elif defined(Q_OS_IRIX) + setPortName(QLatin1String("/dev/ttyf1")); + +#elif defined(Q_OS_HPUX) + setPortName(QLatin1String("/dev/tty1p0")); + +#elif defined(Q_OS_SOLARIS) + setPortName(QLatin1String("/dev/ttya")); + +#elif defined(Q_OS_OSF) //formally DIGITAL UNIX + setPortName(QLatin1String("/dev/tty01")); + +#elif defined(Q_OS_FREEBSD) + setPortName(QLatin1String("/dev/ttyd1")); + +#elif defined(Q_OS_OPENBSD) + setPortName(QLatin1String("/dev/tty00")); + +#else + setPortName(QLatin1String("/dev/ttyS0")); +#endif + setQueryMode(mode); +} + +/*! + Constructs a serial port attached to the port specified by name. + \a name is the name of the device, which is windowsystem-specific, + e.g."COM1" or "/dev/ttyS0". \a mode +*/ +QextSerialPort::QextSerialPort(const QString &name, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + setQueryMode(mode); + setPortName(name); +} + +/*! + Constructs a port with default name and specified \a settings. +*/ +QextSerialPort::QextSerialPort(const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Constructs a port with specified \a name , \a mode and \a settings. +*/ +QextSerialPort::QextSerialPort(const QString &name, const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setPortName(name); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Opens a serial port and sets its OpenMode to \a mode. + Note that this function does not specify which device to open. + Returns true if successful; otherwise returns false.This function has no effect + if the port associated with the class is already open. The port is also + configured to the current settings, as stored in the settings structure. +*/ +bool QextSerialPort::open(OpenMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != QIODevice::NotOpen && !isOpen()) + d->open_sys(mode); + + return isOpen(); +} + + +/*! \reimp + Closes a serial port. This function has no effect if the serial port associated with the class + is not currently open. +*/ +void QextSerialPort::close() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) { + // Be a good QIODevice and call QIODevice::close() before really close() + // so the aboutToClose() signal is emitted at the proper time + QIODevice::close(); // mark ourselves as closed + d->close_sys(); + d->readBuffer.clear(); + } +} + +/*! + Flushes all pending I/O to the serial port. This function has no effect if the serial port + associated with the class is not currently open. +*/ +void QextSerialPort::flush() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->flush_sys(); +} + +/*! \reimp + Returns the number of bytes waiting in the port's receive queue. This function will return 0 if + the port is not currently open, or -1 on error. +*/ +qint64 QextSerialPort::bytesAvailable() const +{ + QWriteLocker locker(&d_func()->lock); + if (isOpen()) { + qint64 bytes = d_func()->bytesAvailable_sys(); + if (bytes != -1) { + return bytes + d_func()->readBuffer.size() + + QIODevice::bytesAvailable(); + } else { + return -1; + } + } + return 0; +} + +/*! \reimp + +*/ +bool QextSerialPort::canReadLine() const +{ + QReadLocker locker(&d_func()->lock); + return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine(); +} + +/*! + * Set desired serial communication handling style. You may choose from polling + * or event driven approach. This function does nothing when port is open; to + * apply changes port must be reopened. + * + * In event driven approach read() and write() functions are acting + * asynchronously. They return immediately and the operation is performed in + * the background, so they doesn't freeze the calling thread. + * To determine when operation is finished, QextSerialPort runs separate thread + * and monitors serial port events. Whenever the event occurs, adequate signal + * is emitted. + * + * When polling is set, read() and write() are acting synchronously. Signals are + * not working in this mode and some functions may not be available. The advantage + * of polling is that it generates less overhead due to lack of signals emissions + * and it doesn't start separate thread to monitor events. + * + * Generally event driven approach is more capable and friendly, although some + * applications may need as low overhead as possible and then polling comes. + * + * \a mode query mode. + */ +void QextSerialPort::setQueryMode(QueryMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != d->queryMode) { + d->queryMode = mode; + } +} + +/*! + Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". +*/ +void QextSerialPort::setPortName(const QString &name) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + d->port = name; +} + +/*! + Returns the name set by setPortName(). +*/ +QString QextSerialPort::portName() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->port; +} + +QextSerialPort::QueryMode QextSerialPort::queryMode() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->queryMode; +} + +/*! + Reads all available data from the device, and returns it as a QByteArray. + This function has no way of reporting errors; returning an empty QByteArray() + can mean either that no data was currently available for reading, or that an error occurred. +*/ +QByteArray QextSerialPort::readAll() +{ + int avail = this->bytesAvailable(); + return (avail > 0) ? this->read(avail) : QByteArray(); +} + +/*! + Returns the baud rate of the serial port. For a list of possible return values see + the definition of the enum BaudRateType. +*/ +BaudRateType QextSerialPort::baudRate() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.BaudRate; +} + +/*! + Returns the number of data bits used by the port. For a list of possible values returned by + this function, see the definition of the enum DataBitsType. +*/ +DataBitsType QextSerialPort::dataBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.DataBits; +} + +/*! + Returns the type of parity used by the port. For a list of possible values returned by + this function, see the definition of the enum ParityType. +*/ +ParityType QextSerialPort::parity() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.Parity; +} + +/*! + Returns the number of stop bits used by the port. For a list of possible return values, see + the definition of the enum StopBitsType. +*/ +StopBitsType QextSerialPort::stopBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.StopBits; +} + +/*! + Returns the type of flow control used by the port. For a list of possible values returned + by this function, see the definition of the enum FlowType. +*/ +FlowType QextSerialPort::flowControl() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.FlowControl; +} + +/*! + \reimp + Returns true if device is sequential, otherwise returns false. Serial port is sequential device + so this function always returns true. Check QIODevice::isSequential() documentation for more + information. +*/ +bool QextSerialPort::isSequential() const +{ + return true; +} + +/*! + Return the error number, or 0 if no error occurred. +*/ +ulong QextSerialPort::lastError() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->lastErr; +} + +/*! + Returns the line status as stored by the port function. This function will retrieve the states + of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines + can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned + long with specific bits indicating which lines are high. The following constants should be used + to examine the states of individual lines: + + \code + Mask Line + ------ ---- + LS_CTS CTS + LS_DSR DSR + LS_DCD DCD + LS_RI RI + LS_RTS RTS (POSIX only) + LS_DTR DTR (POSIX only) + LS_ST Secondary TXD (POSIX only) + LS_SR Secondary RXD (POSIX only) + \endcode + + This function will return 0 if the port associated with the class is not currently open. +*/ +unsigned long QextSerialPort::lineStatus() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + return d->lineStatus_sys(); + return 0; +} + +/*! + Returns a human-readable description of the last device error that occurred. +*/ +QString QextSerialPort::errorString() +{ + Q_D(QextSerialPort); + QReadLocker locker(&d->lock); + switch(d->lastErr) { + case E_NO_ERROR: + return tr("No Error has occurred"); + case E_INVALID_FD: + return tr("Invalid file descriptor (port was not opened correctly)"); + case E_NO_MEMORY: + return tr("Unable to allocate memory tables (POSIX)"); + case E_CAUGHT_NON_BLOCKED_SIGNAL: + return tr("Caught a non-blocked signal (POSIX)"); + case E_PORT_TIMEOUT: + return tr("Operation timed out (POSIX)"); + case E_INVALID_DEVICE: + return tr("The file opened by the port is not a valid device"); + case E_BREAK_CONDITION: + return tr("The port detected a break condition"); + case E_FRAMING_ERROR: + return tr("The port detected a framing error (usually caused by incorrect baud rate settings)"); + case E_IO_ERROR: + return tr("There was an I/O error while communicating with the port"); + case E_BUFFER_OVERRUN: + return tr("Character buffer overrun"); + case E_RECEIVE_OVERFLOW: + return tr("Receive buffer overflow"); + case E_RECEIVE_PARITY_ERROR: + return tr("The port detected a parity error in the received data"); + case E_TRANSMIT_OVERFLOW: + return tr("Transmit buffer overflow"); + case E_READ_FAILED: + return tr("General read operation failure"); + case E_WRITE_FAILED: + return tr("General write operation failure"); + case E_FILE_NOT_FOUND: + return tr("The %1 file doesn't exists").arg(this->portName()); + case E_PERMISSION_DENIED: + return tr("Permission denied"); + case E_AGAIN: + return tr("Device is already locked"); + default: + return tr("Unknown error: %1").arg(d->lastErr); + } +} + +/*! + Destructs the QextSerialPort object. +*/ +QextSerialPort::~QextSerialPort() +{ + if (isOpen()) { + close(); + } + delete d_ptr; +} + +/*! + Sets the flow control used by the port to \a flow. Possible values of flow are: + \code + FLOW_OFF No flow control + FLOW_HARDWARE Hardware (RTS/CTS) flow control + FLOW_XONXOFF Software (XON/XOFF) flow control + \endcode +*/ +void QextSerialPort::setFlowControl(FlowType flow) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.FlowControl != flow) + d->setFlowControl(flow, true); +} + +/*! + Sets the parity associated with the serial port to \a parity. The possible values of parity are: + \code + PAR_SPACE Space Parity + PAR_MARK Mark Parity + PAR_NONE No Parity + PAR_EVEN Even Parity + PAR_ODD Odd Parity + \endcode +*/ +void QextSerialPort::setParity(ParityType parity) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Parity != parity) + d->setParity(parity, true); +} + +/*! + Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are: + \code + DATA_5 5 data bits + DATA_6 6 data bits + DATA_7 7 data bits + DATA_8 8 data bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 5 data bits cannot be used with 2 stop bits. + \o 1.5 stop bits can only be used with 5 data bits. + \o 8 data bits cannot be used with space parity on POSIX systems. + \endlist + */ +void QextSerialPort::setDataBits(DataBitsType dataBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.DataBits != dataBits) + d->setDataBits(dataBits, true); +} + +/*! + Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are: + \code + STOP_1 1 stop bit + STOP_1_5 1.5 stop bits + STOP_2 2 stop bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 2 stop bits cannot be used with 5 data bits. + \o 1.5 stop bits cannot be used with 6 or more data bits. + \o POSIX does not support 1.5 stop bits. + \endlist +*/ +void QextSerialPort::setStopBits(StopBitsType stopBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.StopBits != stopBits) + d->setStopBits(stopBits, true); +} + +/*! + Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on + all platforms. The following table shows translations of the various baud rate + constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * + are speeds that are usable on both Windows and POSIX. + \code + + RATE Windows Speed POSIX Speed + ----------- ------------- ----------- + BAUD50 X 50 + BAUD75 X 75 + *BAUD110 110 110 + BAUD134 X 134.5 + BAUD150 X 150 + BAUD200 X 200 + *BAUD300 300 300 + *BAUD600 600 600 + *BAUD1200 1200 1200 + BAUD1800 X 1800 + *BAUD2400 2400 2400 + *BAUD4800 4800 4800 + *BAUD9600 9600 9600 + BAUD14400 14400 X + *BAUD19200 19200 19200 + *BAUD38400 38400 38400 + BAUD56000 56000 X + *BAUD57600 57600 57600 + BAUD76800 X 76800 + *BAUD115200 115200 115200 + BAUD128000 128000 X + BAUD230400 X 230400 + BAUD256000 256000 X + BAUD460800 X 460800 + BAUD500000 X 500000 + BAUD576000 X 576000 + BAUD921600 X 921600 + BAUD1000000 X 1000000 + BAUD1152000 X 1152000 + BAUD1500000 X 1500000 + BAUD2000000 X 2000000 + BAUD2500000 X 2500000 + BAUD3000000 X 3000000 + BAUD3500000 X 3500000 + BAUD4000000 X 4000000 + \endcode +*/ + +void QextSerialPort::setBaudRate(BaudRateType baudRate) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.BaudRate != baudRate) + d->setBaudRate(baudRate, true); +} + +/*! + For Unix: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Note that this is a per-character timeout, i.e. the port will wait this long for each + individual character, not for the whole read operation. This timeout also applies to the + bytesWaiting() function. + + \bold note: + POSIX does not support millisecond-level control for I/O timeout values. Any + timeout set using this function will be set to the next lowest tenth of a second for + the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds + will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and + writing the port. However millisecond-level control is allowed by the select() system call, + so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for + the purpose of detecting available bytes in the read buffer. + + For Windows: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Setting 0 indicates that timeouts are not used for read nor write operations; + however read() and write() functions will still block. Set -1 to provide + non-blocking behaviour (read() and write() will return immediately). + + \bold note: this function does nothing in event driven mode. +*/ +void QextSerialPort::setTimeout(long millisec) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Timeout_Millisec != millisec) + d->setTimeout(millisec, true); +} + +/*! + Sets DTR line to the requested state (\a set default to high). This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setDtr(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setDtr_sys(set); +} + +/*! + Sets RTS line to the requested state \a set (high by default). + This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setRts(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setRts_sys(set); +} + +/*! \reimp + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::readData(char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + qint64 bytesFromBuffer = 0; + if (!d->readBuffer.isEmpty()) { + bytesFromBuffer = d->readBuffer.read(data, maxSize); + if (bytesFromBuffer == maxSize) + return bytesFromBuffer; + } + qint64 bytesFromDevice = d->readData_sys(data+bytesFromBuffer, maxSize-bytesFromBuffer); + if (bytesFromDevice < 0) { + return -1; + } + return bytesFromBuffer + bytesFromDevice; +} + +/*! \reimp + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::writeData(const char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + return d->writeData_sys(data, maxSize); +} + +#include "moc_qextserialport.cpp" diff --git a/QextSerialPort/qextserialport.h b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.h similarity index 89% rename from QextSerialPort/qextserialport.h rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport.h index ee7ca08..5334e94 100644 --- a/QextSerialPort/qextserialport.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.h @@ -1,243 +1,240 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _QEXTSERIALPORT_H_ -#define _QEXTSERIALPORT_H_ - -#include -#include "qextserialport_global.h" -#ifdef Q_OS_UNIX -#include -#endif -#ifdef Q_OS_ANDROID -#include "../termiosext.h" -#endif -/*line status constants*/ -// ### QESP2.0 move to enum -#define LS_CTS 0x01 -#define LS_DSR 0x02 -#define LS_DCD 0x04 -#define LS_RI 0x08 -#define LS_RTS 0x10 -#define LS_DTR 0x20 -#define LS_ST 0x40 -#define LS_SR 0x80 - -/*error constants*/ -// ### QESP2.0 move to enum -#define E_NO_ERROR 0 -#define E_INVALID_FD 1 -#define E_NO_MEMORY 2 -#define E_CAUGHT_NON_BLOCKED_SIGNAL 3 -#define E_PORT_TIMEOUT 4 -#define E_INVALID_DEVICE 5 -#define E_BREAK_CONDITION 6 -#define E_FRAMING_ERROR 7 -#define E_IO_ERROR 8 -#define E_BUFFER_OVERRUN 9 -#define E_RECEIVE_OVERFLOW 10 -#define E_RECEIVE_PARITY_ERROR 11 -#define E_TRANSMIT_OVERFLOW 12 -#define E_READ_FAILED 13 -#define E_WRITE_FAILED 14 -#define E_FILE_NOT_FOUND 15 -#define E_PERMISSION_DENIED 16 -#define E_AGAIN 17 - -enum BaudRateType -{ -#if defined(Q_OS_UNIX) || defined(qdoc) - BAUD50 = 50, //POSIX ONLY - BAUD75 = 75, //POSIX ONLY - BAUD134 = 134, //POSIX ONLY - BAUD150 = 150, //POSIX ONLY - BAUD200 = 200, //POSIX ONLY - BAUD1800 = 1800, //POSIX ONLY -# if defined(B76800) || defined(qdoc) - BAUD76800 = 76800, //POSIX ONLY -# endif -# if (defined(B230400) && defined(B4000000)) || defined(qdoc) - BAUD230400 = 230400, //POSIX ONLY - BAUD460800 = 460800, //POSIX ONLY - BAUD500000 = 500000, //POSIX ONLY - BAUD576000 = 576000, //POSIX ONLY - BAUD921600 = 921600, //POSIX ONLY - BAUD1000000 = 1000000, //POSIX ONLY - BAUD1152000 = 1152000, //POSIX ONLY - BAUD1500000 = 1500000, //POSIX ONLY - BAUD2000000 = 2000000, //POSIX ONLY - BAUD2500000 = 2500000, //POSIX ONLY - BAUD3000000 = 3000000, //POSIX ONLY - BAUD3500000 = 3500000, //POSIX ONLY - BAUD4000000 = 4000000, //POSIX ONLY -# endif -#endif //Q_OS_UNIX -#if defined(Q_OS_WIN) || defined(qdoc) - BAUD14400 = 14400, //WINDOWS ONLY - BAUD56000 = 56000, //WINDOWS ONLY - BAUD128000 = 128000, //WINDOWS ONLY - BAUD256000 = 256000, //WINDOWS ONLY -#endif //Q_OS_WIN - BAUD110 = 110, - BAUD300 = 300, - BAUD600 = 600, - BAUD1200 = 1200, - BAUD2400 = 2400, - BAUD4800 = 4800, - BAUD9600 = 9600, - BAUD19200 = 19200, - BAUD38400 = 38400, - BAUD57600 = 57600, - BAUD115200 = 115200 -}; - -enum DataBitsType -{ - DATA_5 = 5, - DATA_6 = 6, - DATA_7 = 7, - DATA_8 = 8 -}; - -enum ParityType -{ - PAR_NONE, - PAR_ODD, - PAR_EVEN, -#if defined(Q_OS_WIN) || defined(qdoc) - PAR_MARK, //WINDOWS ONLY -#endif - PAR_SPACE -}; - -enum StopBitsType -{ - STOP_1, -#if defined(Q_OS_WIN) || defined(qdoc) - STOP_1_5, //WINDOWS ONLY -#endif - STOP_2 -}; - -enum FlowType -{ - FLOW_OFF, - FLOW_HARDWARE, - FLOW_XONXOFF -}; - -/** - * structure to contain port settings - */ -struct PortSettings -{ - BaudRateType BaudRate; - DataBitsType DataBits; - ParityType Parity; - StopBitsType StopBits; - FlowType FlowControl; - long Timeout_Millisec; -}; - -class QextSerialPortPrivate; -class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QextSerialPort) - Q_ENUMS(QueryMode) - Q_PROPERTY(QString portName READ portName WRITE setPortName) - Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode) -public: - enum QueryMode { - Polling, - EventDriven - }; - - explicit QextSerialPort(QueryMode mode = EventDriven, QObject* parent = 0); - explicit QextSerialPort(const QString & name, QueryMode mode = EventDriven, QObject * parent = 0); - explicit QextSerialPort(const PortSettings & s, QueryMode mode = EventDriven, QObject * parent = 0); - QextSerialPort(const QString & name, const PortSettings& s, QueryMode mode = EventDriven, QObject *parent=0); - - ~QextSerialPort(); - - QString portName() const; - QueryMode queryMode() const; - BaudRateType baudRate() const; - DataBitsType dataBits() const; - ParityType parity() const; - StopBitsType stopBits() const; - FlowType flowControl() const; - - bool open(OpenMode mode); - bool isSequential() const; - void close(); - void flush(); - qint64 bytesAvailable() const; - bool canReadLine() const; - QByteArray readAll(); - - ulong lastError() const; - - ulong lineStatus(); - QString errorString(); - -public Q_SLOTS: - void setPortName(const QString & name); - void setQueryMode(QueryMode mode); - void setBaudRate(BaudRateType); - void setDataBits(DataBitsType); - void setParity(ParityType); - void setStopBits(StopBitsType); - void setFlowControl(FlowType); - void setTimeout(long); - - void setDtr(bool set=true); - void setRts(bool set=true); - -Q_SIGNALS: - void dsrChanged(bool status); - -protected: - qint64 readData(char * data, qint64 maxSize); - qint64 writeData(const char * data, qint64 maxSize); - -private: - Q_DISABLE_COPY(QextSerialPort) - -#ifdef Q_OS_WIN - Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE)) -#endif - Q_PRIVATE_SLOT(d_func(), void _q_canRead()) - - QextSerialPortPrivate * const d_ptr; -}; - -#endif +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_H_ +#define _QEXTSERIALPORT_H_ + +#include +#include "qextserialport_global.h" +#ifdef Q_OS_UNIX +#include +#endif +/*line status constants*/ +// ### QESP2.0 move to enum +#define LS_CTS 0x01 +#define LS_DSR 0x02 +#define LS_DCD 0x04 +#define LS_RI 0x08 +#define LS_RTS 0x10 +#define LS_DTR 0x20 +#define LS_ST 0x40 +#define LS_SR 0x80 + +/*error constants*/ +// ### QESP2.0 move to enum +#define E_NO_ERROR 0 +#define E_INVALID_FD 1 +#define E_NO_MEMORY 2 +#define E_CAUGHT_NON_BLOCKED_SIGNAL 3 +#define E_PORT_TIMEOUT 4 +#define E_INVALID_DEVICE 5 +#define E_BREAK_CONDITION 6 +#define E_FRAMING_ERROR 7 +#define E_IO_ERROR 8 +#define E_BUFFER_OVERRUN 9 +#define E_RECEIVE_OVERFLOW 10 +#define E_RECEIVE_PARITY_ERROR 11 +#define E_TRANSMIT_OVERFLOW 12 +#define E_READ_FAILED 13 +#define E_WRITE_FAILED 14 +#define E_FILE_NOT_FOUND 15 +#define E_PERMISSION_DENIED 16 +#define E_AGAIN 17 + +enum BaudRateType +{ +#if defined(Q_OS_UNIX) || defined(qdoc) + BAUD50 = 50, //POSIX ONLY + BAUD75 = 75, //POSIX ONLY + BAUD134 = 134, //POSIX ONLY + BAUD150 = 150, //POSIX ONLY + BAUD200 = 200, //POSIX ONLY + BAUD1800 = 1800, //POSIX ONLY +# if defined(B76800) || defined(qdoc) + BAUD76800 = 76800, //POSIX ONLY +# endif +# if (defined(B230400) && defined(B4000000)) || defined(qdoc) + BAUD230400 = 230400, //POSIX ONLY + BAUD460800 = 460800, //POSIX ONLY + BAUD500000 = 500000, //POSIX ONLY + BAUD576000 = 576000, //POSIX ONLY + BAUD921600 = 921600, //POSIX ONLY + BAUD1000000 = 1000000, //POSIX ONLY + BAUD1152000 = 1152000, //POSIX ONLY + BAUD1500000 = 1500000, //POSIX ONLY + BAUD2000000 = 2000000, //POSIX ONLY + BAUD2500000 = 2500000, //POSIX ONLY + BAUD3000000 = 3000000, //POSIX ONLY + BAUD3500000 = 3500000, //POSIX ONLY + BAUD4000000 = 4000000, //POSIX ONLY +# endif +#endif //Q_OS_UNIX +#if defined(Q_OS_WIN) || defined(qdoc) + BAUD14400 = 14400, //WINDOWS ONLY + BAUD56000 = 56000, //WINDOWS ONLY + BAUD128000 = 128000, //WINDOWS ONLY + BAUD256000 = 256000, //WINDOWS ONLY +#endif //Q_OS_WIN + BAUD110 = 110, + BAUD300 = 300, + BAUD600 = 600, + BAUD1200 = 1200, + BAUD2400 = 2400, + BAUD4800 = 4800, + BAUD9600 = 9600, + BAUD19200 = 19200, + BAUD38400 = 38400, + BAUD57600 = 57600, + BAUD115200 = 115200 +}; + +enum DataBitsType +{ + DATA_5 = 5, + DATA_6 = 6, + DATA_7 = 7, + DATA_8 = 8 +}; + +enum ParityType +{ + PAR_NONE, + PAR_ODD, + PAR_EVEN, +#if defined(Q_OS_WIN) || defined(qdoc) + PAR_MARK, //WINDOWS ONLY +#endif + PAR_SPACE +}; + +enum StopBitsType +{ + STOP_1, +#if defined(Q_OS_WIN) || defined(qdoc) + STOP_1_5, //WINDOWS ONLY +#endif + STOP_2 +}; + +enum FlowType +{ + FLOW_OFF, + FLOW_HARDWARE, + FLOW_XONXOFF +}; + +/** + * structure to contain port settings + */ +struct PortSettings +{ + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; +}; + +class QextSerialPortPrivate; +class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialPort) + Q_ENUMS(QueryMode) + Q_PROPERTY(QString portName READ portName WRITE setPortName) + Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode) +public: + enum QueryMode { + Polling, + EventDriven + }; + + explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0); + QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent=0); + + ~QextSerialPort(); + + QString portName() const; + QueryMode queryMode() const; + BaudRateType baudRate() const; + DataBitsType dataBits() const; + ParityType parity() const; + StopBitsType stopBits() const; + FlowType flowControl() const; + + bool open(OpenMode mode); + bool isSequential() const; + void close(); + void flush(); + qint64 bytesAvailable() const; + bool canReadLine() const; + QByteArray readAll(); + + ulong lastError() const; + + ulong lineStatus(); + QString errorString(); + +public Q_SLOTS: + void setPortName(const QString &name); + void setQueryMode(QueryMode mode); + void setBaudRate(BaudRateType); + void setDataBits(DataBitsType); + void setParity(ParityType); + void setStopBits(StopBitsType); + void setFlowControl(FlowType); + void setTimeout(long); + + void setDtr(bool set=true); + void setRts(bool set=true); + +Q_SIGNALS: + void dsrChanged(bool status); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(QextSerialPort) + +#ifdef Q_OS_WIN + Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE)) +#endif + Q_PRIVATE_SLOT(d_func(), void _q_canRead()) + + QextSerialPortPrivate *const d_ptr; +}; + +#endif diff --git a/GC-3.6.1-T1/src/QextSerialPort/qextserialport.pri b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.pri new file mode 100644 index 0000000..461d56f --- /dev/null +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +PUBLIC_HEADERS += $$PWD/qextserialport.h \ + $$PWD/qextserialenumerator.h \ + $$PWD/qextserialport_global.h + +HEADERS += $$PUBLIC_HEADERS \ + $$PWD/qextserialport_p.h \ + $$PWD/qextserialenumerator_p.h \ + +SOURCES += $$PWD/qextserialport.cpp \ + $$PWD/qextserialenumerator.cpp +unix { + SOURCES += $$PWD/qextserialport_unix.cpp + linux* { + SOURCES += $$PWD/qextserialenumerator_linux.cpp + } else:macx { + SOURCES += $$PWD/qextserialenumerator_osx.cpp + } else { + SOURCES += $$PWD/qextserialenumerator_unix.cpp + } +} +win32:SOURCES += $$PWD/qextserialport_win.cpp \ + $$PWD/qextserialenumerator_win.cpp + +linux*{ + !qesp_linux_udev:DEFINES += QESP_NO_UDEV + qesp_linux_udev: LIBS += -ludev +} + +macx:LIBS += -framework IOKit -framework CoreFoundation +win32:LIBS += -lsetupapi -ladvapi32 -luser32 + +# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work +linux*:DEFINES += __linux__ diff --git a/QextSerialPort/qextserialport_global.h b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_global.h similarity index 93% rename from QextSerialPort/qextserialport_global.h rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport_global.h index a00d5e1..824d455 100644 --- a/QextSerialPort/qextserialport_global.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_global.h @@ -1,72 +1,72 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#ifndef QEXTSERIALPORT_GLOBAL_H -#define QEXTSERIALPORT_GLOBAL_H - -#include - -#ifdef QEXTSERIALPORT_BUILD_SHARED -# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT -#elif defined(QEXTSERIALPORT_USING_SHARED) -# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT -#else -# define QEXTSERIALPORT_EXPORT -#endif - -// ### for compatible with old version. should be removed in QESP 2.0 -#ifdef _TTY_NOWARN_ -# define QESP_NO_WARN -#endif -#ifdef _TTY_NOWARN_PORT_ -# define QESP_NO_PORTABILITY_WARN -#endif - -/*if all warning messages are turned off, flag portability warnings to be turned off as well*/ -#ifdef QESP_NO_WARN -# define QESP_NO_PORTABILITY_WARN -#endif - -/*macros for warning and debug messages*/ -#ifdef QESP_NO_PORTABILITY_WARN -# define QESP_PORTABILITY_WARNING while(false)qWarning -#else -# define QESP_PORTABILITY_WARNING qWarning -#endif /*QESP_NOWARN_PORT*/ - -#ifdef QESP_NO_WARN -# define QESP_WARNING while(false)qWarning -#else -# define QESP_WARNING qWarning -#endif /*QESP_NOWARN*/ - -#endif // QEXTSERIALPORT_GLOBAL_H - +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTSERIALPORT_GLOBAL_H +#define QEXTSERIALPORT_GLOBAL_H + +#include + +#ifdef QEXTSERIALPORT_BUILD_SHARED +# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT +#elif defined(QEXTSERIALPORT_USING_SHARED) +# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT +#else +# define QEXTSERIALPORT_EXPORT +#endif + +// ### for compatible with old version. should be removed in QESP 2.0 +#ifdef _TTY_NOWARN_ +# define QESP_NO_WARN +#endif +#ifdef _TTY_NOWARN_PORT_ +# define QESP_NO_PORTABILITY_WARN +#endif + +/*if all warning messages are turned off, flag portability warnings to be turned off as well*/ +#ifdef QESP_NO_WARN +# define QESP_NO_PORTABILITY_WARN +#endif + +/*macros for warning and debug messages*/ +#ifdef QESP_NO_PORTABILITY_WARN +# define QESP_PORTABILITY_WARNING while (false)qWarning +#else +# define QESP_PORTABILITY_WARNING qWarning +#endif /*QESP_NOWARN_PORT*/ + +#ifdef QESP_NO_WARN +# define QESP_WARNING while (false)qWarning +#else +# define QESP_WARNING qWarning +#endif /*QESP_NOWARN*/ + +#endif // QEXTSERIALPORT_GLOBAL_H + diff --git a/QextSerialPort/qextserialport_p.h b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_p.h similarity index 83% rename from QextSerialPort/qextserialport_p.h rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport_p.h index a7c9aed..d278a17 100644 --- a/QextSerialPort/qextserialport_p.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_p.h @@ -1,257 +1,251 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _QEXTSERIALPORT_P_H_ -#define _QEXTSERIALPORT_P_H_ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the QESP API. It exists for the convenience -// of other QESP classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qextserialport.h" -#include -#ifdef Q_OS_UNIX -# include -#elif (defined Q_OS_WIN) -# include -#endif -#include - -// This is QextSerialPort's read buffer, needed by posix system. -// ref: QRingBuffer & QIODevicePrivateLinearBuffer -class QextReadBuffer -{ -public: - inline QextReadBuffer(size_t growth=4096) - : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { - } - - ~QextReadBuffer() { - delete [] buf; - } - - inline void clear() { - first = buf; - len = 0; - } - - inline int size() const { - return len; - } - - inline bool isEmpty() const { - return len == 0; - } - - inline int read(char* target, int size) { - int r = qMin(size, len); - if (r == 1) { - *target = *first; - --len; - ++first; - } else { - memcpy(target, first, r); - len -= r; - first += r; - } - return r; - } - - inline char* reserve(size_t size) { - if ((first - buf) + len + size > capacity) { - size_t newCapacity = qMax(capacity, basicBlockSize); - while (newCapacity < size) - newCapacity *= 2; - if (newCapacity > capacity) { - // allocate more space - char* newBuf = new char[newCapacity]; - memmove(newBuf, first, len); - delete [] buf; - buf = newBuf; - capacity = newCapacity; - } else { - // shift any existing data to make space - memmove(buf, first, len); - } - first = buf; - } - char* writePtr = first + len; - len += (int)size; - return writePtr; - } - - inline void chop(int size) { - if (size >= len) { - clear(); - } else { - len -= size; - } - } - - inline void squeeze() { - if (first != buf) { - memmove(buf, first, len); - first = buf; - } - size_t newCapacity = basicBlockSize; - while (newCapacity < size_t(len)) - newCapacity *= 2; - if (newCapacity < capacity) { - char * tmp = static_cast(realloc(buf, newCapacity)); - if (tmp) { - buf = tmp; - capacity = newCapacity; - } - } - } - - inline QByteArray readAll() { - char* f = first; - int l = len; - clear(); - return QByteArray(f, l); - } - - inline int readLine(char* target, int size) { - int r = qMin(size, len); - char* eol = static_cast(memchr(first, '\n', r)); - if (eol) - r = 1+(eol-first); - memcpy(target, first, r); - len -= r; - first += r; - return int(r); - } - - inline bool canReadLine() const { - return memchr(first, '\n', len); - } - -private: - int len; - char* first; - char* buf; - size_t capacity; - size_t basicBlockSize; -}; - -class QextWinEventNotifier; -class QWinEventNotifier; -class QReadWriteLock; -class QSocketNotifier; - -class QextSerialPortPrivate -{ - Q_DECLARE_PUBLIC(QextSerialPort) -public: - QextSerialPortPrivate(QextSerialPort * q); - ~QextSerialPortPrivate(); - enum DirtyFlagEnum - { - DFE_BaudRate = 0x0001, - DFE_Parity = 0x0002, - DFE_StopBits = 0x0004, - DFE_DataBits = 0x0008, - DFE_Flow = 0x0010, - DFE_TimeOut = 0x0100, - DFE_ALL = 0x0fff, - DFE_Settings_Mask = 0x00ff //without TimeOut - }; - mutable QReadWriteLock lock; - QString port; - PortSettings Settings; - QextReadBuffer readBuffer; - int settingsDirtyFlags; - ulong lastErr; - QextSerialPort::QueryMode _queryMode; - - // platform specific members -#ifdef Q_OS_UNIX - int fd; - QSocketNotifier *readNotifier; - struct termios Posix_CommConfig; - struct termios old_termios; -#elif (defined Q_OS_WIN) - HANDLE Win_Handle; - OVERLAPPED overlap; - COMMCONFIG Win_CommConfig; - COMMTIMEOUTS Win_CommTimeouts; -# ifndef QESP_NO_QT4_PRIVATE - QWinEventNotifier *winEventNotifier; -# else - QextWinEventNotifier *winEventNotifier; -# endif - DWORD eventMask; - QList pendingWrites; - QReadWriteLock* bytesToWriteLock; - qint64 _bytesToWrite; -#endif - - /*fill PortSettings*/ - void setBaudRate(BaudRateType baudRate, bool update=true); - void setDataBits(DataBitsType dataBits, bool update=true); - void setParity(ParityType parity, bool update=true); - void setStopBits(StopBitsType stopbits, bool update=true); - void setFlowControl(FlowType flow, bool update=true); - void setTimeout(long millisec, bool update=true); - void setPortSettings(const PortSettings& settings, bool update=true); - - void platformSpecificDestruct(); - void platformSpecificInit(); - void translateError(ulong error); - void updatePortSettings(); - - qint64 readData_sys(char * data, qint64 maxSize); - qint64 writeData_sys(const char * data, qint64 maxSize); - void setDtr_sys(bool set=true); - void setRts_sys(bool set=true); - bool open_sys(QIODevice::OpenMode mode); - bool close_sys(); - bool flush_sys(); - ulong lineStatus_sys(); - qint64 bytesAvailable_sys() const; - -#ifdef Q_OS_WIN - void _q_onWinEvent(HANDLE h); -#endif - void _q_canRead(); - - QextSerialPort * q_ptr; -}; - -#endif //_QEXTSERIALPORT_P_H_ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_P_H_ +#define _QEXTSERIALPORT_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialport.h" +#include +#ifdef Q_OS_UNIX +# include +#elif (defined Q_OS_WIN) +# include +#endif +#include + +// This is QextSerialPort's read buffer, needed by posix system. +// ref: QRingBuffer & QIODevicePrivateLinearBuffer +class QextReadBuffer +{ +public: + inline QextReadBuffer(size_t growth=4096) + : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { + } + + ~QextReadBuffer() { + delete [] buf; + } + + inline void clear() { + first = buf; + len = 0; + } + + inline int size() const { + return len; + } + + inline bool isEmpty() const { + return len == 0; + } + + inline int read(char *target, int size) { + int r = qMin(size, len); + if (r == 1) { + *target = *first; + --len; + ++first; + } else { + memcpy(target, first, r); + len -= r; + first += r; + } + return r; + } + + inline char *reserve(size_t size) { + if ((first - buf) + len + size > capacity) { + size_t newCapacity = qMax(capacity, basicBlockSize); + while (newCapacity < len + size) + newCapacity *= 2; + if (newCapacity > capacity) { + // allocate more space + char *newBuf = new char[newCapacity]; + memmove(newBuf, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf, first, len); + } + first = buf; + } + char *writePtr = first + len; + len += (int)size; + return writePtr; + } + + inline void chop(int size) { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + + inline void squeeze() { + if (first != buf) { + memmove(buf, first, len); + first = buf; + } + size_t newCapacity = basicBlockSize; + while (newCapacity < size_t(len)) + newCapacity *= 2; + if (newCapacity < capacity) { + char *tmp = static_cast(realloc(buf, newCapacity)); + if (tmp) { + buf = tmp; + capacity = newCapacity; + } + } + } + + inline QByteArray readAll() { + char *f = first; + int l = len; + clear(); + return QByteArray(f, l); + } + + inline int readLine(char *target, int size) { + int r = qMin(size, len); + char *eol = static_cast(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return int(r); + } + + inline bool canReadLine() const { + return memchr(first, '\n', len); + } + +private: + int len; + char *first; + char *buf; + size_t capacity; + size_t basicBlockSize; +}; + +class QWinEventNotifier; +class QReadWriteLock; +class QSocketNotifier; + +class QextSerialPortPrivate +{ + Q_DECLARE_PUBLIC(QextSerialPort) +public: + QextSerialPortPrivate(QextSerialPort *q); + ~QextSerialPortPrivate(); + enum DirtyFlagEnum + { + DFE_BaudRate = 0x0001, + DFE_Parity = 0x0002, + DFE_StopBits = 0x0004, + DFE_DataBits = 0x0008, + DFE_Flow = 0x0010, + DFE_TimeOut = 0x0100, + DFE_ALL = 0x0fff, + DFE_Settings_Mask = 0x00ff //without TimeOut + }; + mutable QReadWriteLock lock; + QString port; + PortSettings settings; + QextReadBuffer readBuffer; + int settingsDirtyFlags; + ulong lastErr; + QextSerialPort::QueryMode queryMode; + + // platform specific members +#ifdef Q_OS_UNIX + int fd; + QSocketNotifier *readNotifier; + struct termios currentTermios; + struct termios oldTermios; +#elif (defined Q_OS_WIN) + HANDLE handle; + OVERLAPPED overlap; + COMMCONFIG commConfig; + COMMTIMEOUTS commTimeouts; + QWinEventNotifier *winEventNotifier; + DWORD eventMask; + QList pendingWrites; + QReadWriteLock *bytesToWriteLock; +#endif + + /*fill PortSettings*/ + void setBaudRate(BaudRateType baudRate, bool update=true); + void setDataBits(DataBitsType dataBits, bool update=true); + void setParity(ParityType parity, bool update=true); + void setStopBits(StopBitsType stopbits, bool update=true); + void setFlowControl(FlowType flow, bool update=true); + void setTimeout(long millisec, bool update=true); + void setPortSettings(const PortSettings &settings, bool update=true); + + void platformSpecificDestruct(); + void platformSpecificInit(); + void translateError(ulong error); + void updatePortSettings(); + + qint64 readData_sys(char *data, qint64 maxSize); + qint64 writeData_sys(const char *data, qint64 maxSize); + void setDtr_sys(bool set=true); + void setRts_sys(bool set=true); + bool open_sys(QIODevice::OpenMode mode); + bool close_sys(); + bool flush_sys(); + ulong lineStatus_sys(); + qint64 bytesAvailable_sys() const; + +#ifdef Q_OS_WIN + void _q_onWinEvent(HANDLE h); +#endif + void _q_canRead(); + + QextSerialPort *q_ptr; +}; + +#endif //_QEXTSERIALPORT_P_H_ diff --git a/QextSerialPort/qextserialport_unix.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_unix.cpp similarity index 65% rename from QextSerialPort/qextserialport_unix.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport_unix.cpp index 3508fe1..4c02a20 100644 --- a/QextSerialPort/qextserialport_unix.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_unix.cpp @@ -1,455 +1,460 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialport.h" -#include "qextserialport_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void QextSerialPortPrivate::platformSpecificInit() -{ - fd = 0; - readNotifier = 0; -} - -/*! - Standard destructor. -*/ -void QextSerialPortPrivate::platformSpecificDestruct() -{ -} - -static QString fullPortName(const QString &name) -{ - if (name.startsWith(QLatin1Char('/'))) - return name; - return QLatin1String("/dev/")+name; -} - -bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) -{ - Q_Q(QextSerialPort); - //note: linux 2.6.21 seems to ignore O_NDELAY flag - if ((fd = ::open(fullPortName(port).toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { - - /*In the Private class, We can not call QIODevice::open()*/ - q->setOpenMode(mode); // Flag the port as opened - ::tcgetattr(fd, &old_termios); // Save the old termios - Posix_CommConfig = old_termios; // Make a working copy - ::cfmakeraw(&Posix_CommConfig); // Enable raw access - - /*set up other port settings*/ - Posix_CommConfig.c_cflag |= CREAD|CLOCAL; - Posix_CommConfig.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); - Posix_CommConfig.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); - Posix_CommConfig.c_oflag &= (~OPOST); - Posix_CommConfig.c_cc[VMIN] = 0; -#ifdef _POSIX_VDISABLE // Is a disable character available on this system? - // Some systems allow for per-device disable-characters, so get the - // proper value for the configured device - const long vdisable = ::fpathconf(fd, _PC_VDISABLE); - Posix_CommConfig.c_cc[VINTR] = vdisable; - Posix_CommConfig.c_cc[VQUIT] = vdisable; - Posix_CommConfig.c_cc[VSTART] = vdisable; - Posix_CommConfig.c_cc[VSTOP] = vdisable; - Posix_CommConfig.c_cc[VSUSP] = vdisable; -#endif //_POSIX_VDISABLE - settingsDirtyFlags = DFE_ALL; - updatePortSettings(); - - if (_queryMode == QextSerialPort::EventDriven) { - readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); - q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead())); - } - return true; - } else { - translateError(errno); - return false; - } -} - -bool QextSerialPortPrivate::close_sys() -{ - // Force a flush and then restore the original termios - flush_sys(); - // Using both TCSAFLUSH and TCSANOW here discards any pending input - ::tcsetattr(fd, TCSAFLUSH | TCSANOW, &old_termios); // Restore termios - ::close(fd); - if(readNotifier) { - delete readNotifier; - readNotifier = 0; - } - return true; -} - -bool QextSerialPortPrivate::flush_sys() -{ - ::tcdrain(fd); - return true; -} - -qint64 QextSerialPortPrivate::bytesAvailable_sys() const -{ - int bytesQueued; - if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) { - return (qint64)-1; - } - return bytesQueued; -} - -/*! - Translates a system-specific error code to a QextSerialPort error code. Used internally. -*/ -void QextSerialPortPrivate::translateError(ulong error) -{ - switch (error) { - case EBADF: - case ENOTTY: - lastErr = E_INVALID_FD; - break; - case EINTR: - lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL; - break; - case ENOMEM: - lastErr = E_NO_MEMORY; - break; - case EACCES: - lastErr = E_PERMISSION_DENIED; - break; - case EAGAIN: - lastErr = E_AGAIN; - break; - } -} - -void QextSerialPortPrivate::setDtr_sys(bool set) -{ - int status; - ::ioctl(fd, TIOCMGET, &status); - if (set) - status |= TIOCM_DTR; - else - status &= ~TIOCM_DTR; - ::ioctl(fd, TIOCMSET, &status); -} - -void QextSerialPortPrivate::setRts_sys(bool set) -{ - int status; - ::ioctl(fd, TIOCMGET, &status); - if (set) - status |= TIOCM_RTS; - else - status &= ~TIOCM_RTS; - ::ioctl(fd, TIOCMSET, &status); -} - -unsigned long QextSerialPortPrivate::lineStatus_sys() -{ - unsigned long Status=0, Temp=0; - ::ioctl(fd, TIOCMGET, &Temp); - if (Temp & TIOCM_CTS) Status |= LS_CTS; - if (Temp & TIOCM_DSR) Status |= LS_DSR; - if (Temp & TIOCM_RI ) Status |= LS_RI; - if (Temp & TIOCM_CD ) Status |= LS_DCD; - if (Temp & TIOCM_DTR) Status |= LS_DTR; - if (Temp & TIOCM_RTS) Status |= LS_RTS; - if (Temp & TIOCM_ST ) Status |= LS_ST; - if (Temp & TIOCM_SR ) Status |= LS_SR; - return Status; -} - -/*! - Reads a block of data from the serial port. This function will read at most maxSize bytes from - the serial port and place them in the buffer pointed to by data. Return value is the number of - bytes actually read, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPortPrivate::readData_sys(char * data, qint64 maxSize) -{ - int retVal = ::read(fd, data, maxSize); - if (retVal == -1) - lastErr = E_READ_FAILED; - - return retVal; -} - -/*! - Writes a block of data to the serial port. This function will write maxSize bytes - from the buffer pointed to by data to the serial port. Return value is the number - of bytes actually written, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPortPrivate::writeData_sys(const char * data, qint64 maxSize) -{ - int retVal = ::write(fd, data, maxSize); - if (retVal == -1) - lastErr = E_WRITE_FAILED; - - return (qint64)retVal; -} - -static void setBaudRate2Termios(termios *config, int baudRate) -{ -#ifdef CBAUD - config->c_cflag &= (~CBAUD); - config->c_cflag |= baudRate; -#else - ::cfsetispeed(config, baudRate); - ::cfsetospeed(config, baudRate); -#endif -} - -/* - All the platform settings was performed in this function. -*/ -void QextSerialPortPrivate::updatePortSettings() -{ - if (!q_func()->isOpen() || !settingsDirtyFlags) - return; - - if (settingsDirtyFlags & DFE_BaudRate) { - switch (Settings.BaudRate) { - case BAUD50: - setBaudRate2Termios(&Posix_CommConfig, B50); - break; - case BAUD75: - setBaudRate2Termios(&Posix_CommConfig, B75); - break; - case BAUD110: - setBaudRate2Termios(&Posix_CommConfig, B110); - break; - case BAUD134: - setBaudRate2Termios(&Posix_CommConfig, B134); - break; - case BAUD150: - setBaudRate2Termios(&Posix_CommConfig, B150); - break; - case BAUD200: - setBaudRate2Termios(&Posix_CommConfig, B200); - break; - case BAUD300: - setBaudRate2Termios(&Posix_CommConfig, B300); - break; - case BAUD600: - setBaudRate2Termios(&Posix_CommConfig, B600); - break; - case BAUD1200: - setBaudRate2Termios(&Posix_CommConfig, B1200); - break; - case BAUD1800: - setBaudRate2Termios(&Posix_CommConfig, B1800); - break; - case BAUD2400: - setBaudRate2Termios(&Posix_CommConfig, B2400); - break; - case BAUD4800: - setBaudRate2Termios(&Posix_CommConfig, B4800); - break; - case BAUD9600: - setBaudRate2Termios(&Posix_CommConfig, B9600); - break; - case BAUD19200: - setBaudRate2Termios(&Posix_CommConfig, B19200); - break; - case BAUD38400: - setBaudRate2Termios(&Posix_CommConfig, B38400); - break; - case BAUD57600: - setBaudRate2Termios(&Posix_CommConfig, B57600); - break; -#ifdef B76800 - case BAUD76800: - setBaudRate2Termios(&Posix_CommConfig, B76800); - break; -#endif - case BAUD115200: - setBaudRate2Termios(&Posix_CommConfig, B115200); - break; -#if defined(B230400) && defined(B4000000) - case BAUD230400: - setBaudRate2Termios(&Posix_CommConfig, B230400); - break; - case BAUD460800: - setBaudRate2Termios(&Posix_CommConfig, B460800); - break; - case BAUD500000: - setBaudRate2Termios(&Posix_CommConfig, B500000); - break; - case BAUD576000: - setBaudRate2Termios(&Posix_CommConfig, B576000); - break; - case BAUD921600: - setBaudRate2Termios(&Posix_CommConfig, B921600); - break; - case BAUD1000000: - setBaudRate2Termios(&Posix_CommConfig, B1000000); - break; - case BAUD1152000: - setBaudRate2Termios(&Posix_CommConfig, B1152000); - break; - case BAUD1500000: - setBaudRate2Termios(&Posix_CommConfig, B1500000); - break; - case BAUD2000000: - setBaudRate2Termios(&Posix_CommConfig, B2000000); - break; - case BAUD2500000: - setBaudRate2Termios(&Posix_CommConfig, B2500000); - break; - case BAUD3000000: - setBaudRate2Termios(&Posix_CommConfig, B3000000); - break; - case BAUD3500000: - setBaudRate2Termios(&Posix_CommConfig, B3500000); - break; - case BAUD4000000: - setBaudRate2Termios(&Posix_CommConfig, B4000000); - break; -#endif - } - } - if (settingsDirtyFlags & DFE_Parity) { - switch (Settings.Parity) { - case PAR_SPACE: - /*space parity not directly supported - add an extra data bit to simulate it*/ - settingsDirtyFlags |= DFE_DataBits; - break; - case PAR_NONE: - Posix_CommConfig.c_cflag &= (~PARENB); - break; - case PAR_EVEN: - Posix_CommConfig.c_cflag &= (~PARODD); - Posix_CommConfig.c_cflag |= PARENB; - break; - case PAR_ODD: - Posix_CommConfig.c_cflag |= (PARENB|PARODD); - break; - } - } - /*must after Parity settings*/ - if (settingsDirtyFlags & DFE_DataBits) { - if (Settings.Parity != PAR_SPACE) { - Posix_CommConfig.c_cflag &= (~CSIZE); - switch(Settings.DataBits) { - case DATA_5: - Posix_CommConfig.c_cflag |= CS5; - break; - case DATA_6: - Posix_CommConfig.c_cflag |= CS6; - break; - case DATA_7: - Posix_CommConfig.c_cflag |= CS7; - break; - case DATA_8: - Posix_CommConfig.c_cflag |= CS8; - break; - } - } else { - /*space parity not directly supported - add an extra data bit to simulate it*/ - Posix_CommConfig.c_cflag &= ~(PARENB|CSIZE); - switch(Settings.DataBits) { - case DATA_5: - Posix_CommConfig.c_cflag |= CS6; - break; - case DATA_6: - Posix_CommConfig.c_cflag |= CS7; - break; - case DATA_7: - Posix_CommConfig.c_cflag |= CS8; - break; - case DATA_8: - /*this will never happen, put here to Suppress an warning*/ - break; - } - } - } - if (settingsDirtyFlags & DFE_StopBits) { - switch (Settings.StopBits) { - case STOP_1: - Posix_CommConfig.c_cflag &= (~CSTOPB); - break; - case STOP_2: - Posix_CommConfig.c_cflag |= CSTOPB; - break; - } - } - if (settingsDirtyFlags & DFE_Flow) { - switch(Settings.FlowControl) { - case FLOW_OFF: - Posix_CommConfig.c_cflag &= (~CRTSCTS); - Posix_CommConfig.c_iflag &= (~(IXON|IXOFF|IXANY)); - break; - case FLOW_XONXOFF: - /*software (XON/XOFF) flow control*/ - Posix_CommConfig.c_cflag &= (~CRTSCTS); - Posix_CommConfig.c_iflag |= (IXON|IXOFF|IXANY); - break; - case FLOW_HARDWARE: - Posix_CommConfig.c_cflag |= CRTSCTS; - Posix_CommConfig.c_iflag &= (~(IXON|IXOFF|IXANY)); - break; - } - } - - /*if any thing in Posix_CommConfig changed, flush*/ - if (settingsDirtyFlags & DFE_Settings_Mask) - ::tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig); - - if (settingsDirtyFlags & DFE_TimeOut) { - int millisec = Settings.Timeout_Millisec; - if (millisec == -1) { - ::fcntl(fd, F_SETFL, O_NDELAY); - } - else { - //O_SYNC should enable blocking ::write() - //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2) - ::fcntl(fd, F_SETFL, O_SYNC); - } - ::tcgetattr(fd, & Posix_CommConfig); - Posix_CommConfig.c_cc[VTIME] = millisec/100; - ::tcsetattr(fd, TCSAFLUSH, & Posix_CommConfig); - } - - settingsDirtyFlags = 0; -} +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void QextSerialPortPrivate::platformSpecificInit() +{ + fd = 0; + readNotifier = 0; +} + +/*! + Standard destructor. +*/ +void QextSerialPortPrivate::platformSpecificDestruct() +{ +} + +static QString fullPortName(const QString &name) +{ + if (name.startsWith(QLatin1Char('/'))) + return name; + return QLatin1String("/dev/")+name; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + //note: linux 2.6.21 seems to ignore O_NDELAY flag + if ((fd = ::open(fullPortName(port).toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { + + /*In the Private class, We can not call QIODevice::open()*/ + q->setOpenMode(mode); // Flag the port as opened + ::tcgetattr(fd, &oldTermios); // Save the old termios + currentTermios = oldTermios; // Make a working copy + ::cfmakeraw(¤tTermios); // Enable raw access + + /*set up other port settings*/ + currentTermios.c_cflag |= CREAD|CLOCAL; + currentTermios.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + currentTermios.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + currentTermios.c_oflag &= (~OPOST); + currentTermios.c_cc[VMIN] = 0; +#ifdef _POSIX_VDISABLE // Is a disable character available on this system? + // Some systems allow for per-device disable-characters, so get the + // proper value for the configured device + const long vdisable = ::fpathconf(fd, _PC_VDISABLE); + currentTermios.c_cc[VINTR] = vdisable; + currentTermios.c_cc[VQUIT] = vdisable; + currentTermios.c_cc[VSTART] = vdisable; + currentTermios.c_cc[VSTOP] = vdisable; + currentTermios.c_cc[VSUSP] = vdisable; +#endif //_POSIX_VDISABLE + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + if (queryMode == QextSerialPort::EventDriven) { + readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); + q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead())); + } + return true; + } else { + translateError(errno); + return false; + } +} + +bool QextSerialPortPrivate::close_sys() +{ + // Force a flush and then restore the original termios + flush_sys(); + // Using both TCSAFLUSH and TCSANOW here discards any pending input + ::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios + ::close(fd); + if (readNotifier) { + delete readNotifier; + readNotifier = 0; + } + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + ::tcdrain(fd); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + int bytesQueued; + if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) { + return (qint64)-1; + } + return bytesQueued; +} + +/*! + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + switch (error) { + case EBADF: + case ENOTTY: + lastErr = E_INVALID_FD; + break; + case EINTR: + lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL; + break; + case ENOMEM: + lastErr = E_NO_MEMORY; + break; + case EACCES: + lastErr = E_PERMISSION_DENIED; + break; + case EAGAIN: + lastErr = E_AGAIN; + break; + } +} + +void QextSerialPortPrivate::setDtr_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_DTR; + else + status &= ~TIOCM_DTR; + ::ioctl(fd, TIOCMSET, &status); +} + +void QextSerialPortPrivate::setRts_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_RTS; + else + status &= ~TIOCM_RTS; + ::ioctl(fd, TIOCMSET, &status); +} + +unsigned long QextSerialPortPrivate::lineStatus_sys() +{ + unsigned long Status=0, Temp=0; + ::ioctl(fd, TIOCMGET, &Temp); + if (Temp & TIOCM_CTS) Status |= LS_CTS; + if (Temp & TIOCM_DSR) Status |= LS_DSR; + if (Temp & TIOCM_RI) Status |= LS_RI; + if (Temp & TIOCM_CD) Status |= LS_DCD; + if (Temp & TIOCM_DTR) Status |= LS_DTR; + if (Temp & TIOCM_RTS) Status |= LS_RTS; + if (Temp & TIOCM_ST) Status |= LS_ST; + if (Temp & TIOCM_SR) Status |= LS_SR; + return Status; +} + +/*! + Reads a block of data from the serial port. This function will read at most maxSize bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + int retVal = ::read(fd, data, maxSize); + if (retVal == -1) + lastErr = E_READ_FAILED; + + return retVal; +} + +/*! + Writes a block of data to the serial port. This function will write maxSize bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + int retVal = ::write(fd, data, maxSize); + if (retVal == -1) + lastErr = E_WRITE_FAILED; + + return (qint64)retVal; +} + +static void setBaudRate2Termios(termios *config, int baudRate) +{ +#ifdef CBAUD + config->c_cflag &= (~CBAUD); + config->c_cflag |= baudRate; +#else + ::cfsetispeed(config, baudRate); + ::cfsetospeed(config, baudRate); +#endif +} + +/* + All the platform settings was performed in this function. +*/ +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_func()->isOpen() || !settingsDirtyFlags) + return; + + if (settingsDirtyFlags & DFE_BaudRate) { + switch (settings.BaudRate) { + case BAUD50: + setBaudRate2Termios(¤tTermios, B50); + break; + case BAUD75: + setBaudRate2Termios(¤tTermios, B75); + break; + case BAUD110: + setBaudRate2Termios(¤tTermios, B110); + break; + case BAUD134: + setBaudRate2Termios(¤tTermios, B134); + break; + case BAUD150: + setBaudRate2Termios(¤tTermios, B150); + break; + case BAUD200: + setBaudRate2Termios(¤tTermios, B200); + break; + case BAUD300: + setBaudRate2Termios(¤tTermios, B300); + break; + case BAUD600: + setBaudRate2Termios(¤tTermios, B600); + break; + case BAUD1200: + setBaudRate2Termios(¤tTermios, B1200); + break; + case BAUD1800: + setBaudRate2Termios(¤tTermios, B1800); + break; + case BAUD2400: + setBaudRate2Termios(¤tTermios, B2400); + break; + case BAUD4800: + setBaudRate2Termios(¤tTermios, B4800); + break; + case BAUD9600: + setBaudRate2Termios(¤tTermios, B9600); + break; + case BAUD19200: + setBaudRate2Termios(¤tTermios, B19200); + break; + case BAUD38400: + setBaudRate2Termios(¤tTermios, B38400); + break; + case BAUD57600: + setBaudRate2Termios(¤tTermios, B57600); + break; +#ifdef B76800 + case BAUD76800: + setBaudRate2Termios(¤tTermios, B76800); + break; +#endif + case BAUD115200: + setBaudRate2Termios(¤tTermios, B115200); + break; +#if defined(B230400) && defined(B4000000) + case BAUD230400: + setBaudRate2Termios(¤tTermios, B230400); + break; + case BAUD460800: + setBaudRate2Termios(¤tTermios, B460800); + break; + case BAUD500000: + setBaudRate2Termios(¤tTermios, B500000); + break; + case BAUD576000: + setBaudRate2Termios(¤tTermios, B576000); + break; + case BAUD921600: + setBaudRate2Termios(¤tTermios, B921600); + break; + case BAUD1000000: + setBaudRate2Termios(¤tTermios, B1000000); + break; + case BAUD1152000: + setBaudRate2Termios(¤tTermios, B1152000); + break; + case BAUD1500000: + setBaudRate2Termios(¤tTermios, B1500000); + break; + case BAUD2000000: + setBaudRate2Termios(¤tTermios, B2000000); + break; + case BAUD2500000: + setBaudRate2Termios(¤tTermios, B2500000); + break; + case BAUD3000000: + setBaudRate2Termios(¤tTermios, B3000000); + break; + case BAUD3500000: + setBaudRate2Termios(¤tTermios, B3500000); + break; + case BAUD4000000: + setBaudRate2Termios(¤tTermios, B4000000); + break; +#endif +#ifdef Q_OS_MAC + default: + setBaudRate2Termios(¤tTermios, settings.BaudRate); + break; +#endif + } + } + if (settingsDirtyFlags & DFE_Parity) { + switch (settings.Parity) { + case PAR_SPACE: + /*space parity not directly supported - add an extra data bit to simulate it*/ + settingsDirtyFlags |= DFE_DataBits; + break; + case PAR_NONE: + currentTermios.c_cflag &= (~PARENB); + break; + case PAR_EVEN: + currentTermios.c_cflag &= (~PARODD); + currentTermios.c_cflag |= PARENB; + break; + case PAR_ODD: + currentTermios.c_cflag |= (PARENB|PARODD); + break; + } + } + /*must after Parity settings*/ + if (settingsDirtyFlags & DFE_DataBits) { + if (settings.Parity != PAR_SPACE) { + currentTermios.c_cflag &= (~CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS5; + break; + case DATA_6: + currentTermios.c_cflag |= CS6; + break; + case DATA_7: + currentTermios.c_cflag |= CS7; + break; + case DATA_8: + currentTermios.c_cflag |= CS8; + break; + } + } else { + /*space parity not directly supported - add an extra data bit to simulate it*/ + currentTermios.c_cflag &= ~(PARENB|CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS6; + break; + case DATA_6: + currentTermios.c_cflag |= CS7; + break; + case DATA_7: + currentTermios.c_cflag |= CS8; + break; + case DATA_8: + /*this will never happen, put here to Suppress an warning*/ + break; + } + } + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + currentTermios.c_cflag &= (~CSTOPB); + break; + case STOP_2: + currentTermios.c_cflag |= CSTOPB; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + case FLOW_OFF: + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + case FLOW_XONXOFF: + /*software (XON/XOFF) flow control*/ + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag |= (IXON|IXOFF|IXANY); + break; + case FLOW_HARDWARE: + currentTermios.c_cflag |= CRTSCTS; + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + } + } + + /*if any thing in currentTermios changed, flush*/ + if (settingsDirtyFlags & DFE_Settings_Mask) + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + + if (settingsDirtyFlags & DFE_TimeOut) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + ::fcntl(fd, F_SETFL, O_NDELAY); + } + else { + //O_SYNC should enable blocking ::write() + //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2) + ::fcntl(fd, F_SETFL, O_SYNC); + } + ::tcgetattr(fd, ¤tTermios); + currentTermios.c_cc[VTIME] = millisec/100; + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + } + + settingsDirtyFlags = 0; +} diff --git a/QextSerialPort/qextserialport_win.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_win.cpp similarity index 61% rename from QextSerialPort/qextserialport_win.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextserialport_win.cpp index db1eb14..6b13b52 100644 --- a/QextSerialPort/qextserialport_win.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextserialport_win.cpp @@ -1,429 +1,420 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialport.h" -#include "qextserialport_p.h" -#include -#include -#include -#include -#include -#include -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) -# include -# define WinEventNotifier QWinEventNotifier -#elif !defined(QESP_NO_QT4_PRIVATE) -# include -# define WinEventNotifier QWinEventNotifier -#else -# include "qextwineventnotifier_p.h" -# define WinEventNotifier QextWinEventNotifier -#endif -void QextSerialPortPrivate::platformSpecificInit() -{ - Win_Handle=INVALID_HANDLE_VALUE; - ZeroMemory(&overlap, sizeof(OVERLAPPED)); - overlap.hEvent = CreateEvent(NULL, true, false, NULL); - winEventNotifier = 0; - bytesToWriteLock = new QReadWriteLock; - _bytesToWrite = 0; -} - -void QextSerialPortPrivate::platformSpecificDestruct() { - CloseHandle(overlap.hEvent); - delete bytesToWriteLock; -} - - -/*! - \internal - COM ports greater than 9 need \\.\ prepended - - This is only need when open the port. -*/ -static QString fullPortNameWin(const QString & name) -{ - QRegExp rx(QLatin1String("^COM(\\d+)")); - QString fullName(name); - if(fullName.contains(rx)) - fullName.prepend(QLatin1String("\\\\.\\")); - return fullName; -} - -bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) -{ - Q_Q(QextSerialPort); - DWORD confSize = sizeof(COMMCONFIG); - Win_CommConfig.dwSize = confSize; - DWORD dwFlagsAndAttributes = 0; - if (_queryMode == QextSerialPort::EventDriven) - dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; - - /*open the port*/ - Win_Handle=CreateFileW((wchar_t*)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); - if (Win_Handle!=INVALID_HANDLE_VALUE) { - q->setOpenMode(mode); - /*configure port settings*/ - GetCommConfig(Win_Handle, &Win_CommConfig, &confSize); - GetCommState(Win_Handle, &(Win_CommConfig.dcb)); - - /*set up parameters*/ - Win_CommConfig.dcb.fBinary=TRUE; - Win_CommConfig.dcb.fInX=FALSE; - Win_CommConfig.dcb.fOutX=FALSE; - Win_CommConfig.dcb.fAbortOnError=FALSE; - Win_CommConfig.dcb.fNull=FALSE; - /* Dtr default to true. See Issue 122*/ - Win_CommConfig.dcb.fDtrControl=TRUE; - /*flush all settings*/ - settingsDirtyFlags = DFE_ALL; - updatePortSettings(); - - //init event driven approach - if (_queryMode == QextSerialPort::EventDriven) { - if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { - QESP_WARNING()<<"failed to set Comm Mask. Error code:"<("HANDLE"); - q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection); - WaitCommEvent(Win_Handle, &eventMask, &overlap); - } - return true; - } - return false; -} - -bool QextSerialPortPrivate::close_sys() -{ - flush_sys(); - CancelIo(Win_Handle); - if (CloseHandle(Win_Handle)) - Win_Handle = INVALID_HANDLE_VALUE; - if (winEventNotifier){ - winEventNotifier->setEnabled(false); - winEventNotifier->deleteLater(); - winEventNotifier = 0; - } - _bytesToWrite = 0; - - foreach(OVERLAPPED* o, pendingWrites) { - CloseHandle(o->hEvent); - delete o; - } - pendingWrites.clear(); - return true; -} - -bool QextSerialPortPrivate::flush_sys() -{ - FlushFileBuffers(Win_Handle); - return true; -} - -qint64 QextSerialPortPrivate::bytesAvailable_sys() const -{ - DWORD Errors; - COMSTAT Status; - if (ClearCommError(Win_Handle, &Errors, &Status)) { - return Status.cbInQue; - } - return (qint64)-1; -} - -/* - Translates a system-specific error code to a QextSerialPort error code. Used internally. -*/ -void QextSerialPortPrivate::translateError(ulong error) -{ - if (error&CE_BREAK) { - lastErr=E_BREAK_CONDITION; - } - else if (error&CE_FRAME) { - lastErr=E_FRAMING_ERROR; - } - else if (error&CE_IOE) { - lastErr=E_IO_ERROR; - } - else if (error&CE_MODE) { - lastErr=E_INVALID_FD; - } - else if (error&CE_OVERRUN) { - lastErr=E_BUFFER_OVERRUN; - } - else if (error&CE_RXPARITY) { - lastErr=E_RECEIVE_PARITY_ERROR; - } - else if (error&CE_RXOVER) { - lastErr=E_RECEIVE_OVERFLOW; - } - else if (error&CE_TXFULL) { - lastErr=E_TRANSMIT_OVERFLOW; - } -} - -/* - Reads a block of data from the serial port. This function will read at most maxlen bytes from - the serial port and place them in the buffer pointed to by data. Return value is the number of - bytes actually read, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) -{ - DWORD bytesRead = 0; - bool failed = false; - if (_queryMode == QextSerialPort::EventDriven) { - OVERLAPPED overlapRead; - ZeroMemory(&overlapRead, sizeof(OVERLAPPED)); - if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & bytesRead, & overlapRead)) { - if (GetLastError() == ERROR_IO_PENDING) - GetOverlappedResult(Win_Handle, & overlapRead, & bytesRead, true); - else - failed = true; - } - } else if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & bytesRead, NULL)) { - failed = true; - } - if (!failed) - return (qint64)bytesRead; - - lastErr = E_READ_FAILED; - return -1; -} - -/* - Writes a block of data to the serial port. This function will write len bytes - from the buffer pointed to by data to the serial port. Return value is the number - of bytes actually written, or -1 on error. - - \warning before calling this function ensure that serial port associated with this class - is currently open (use isOpen() function to check if port is open). -*/ -qint64 QextSerialPortPrivate:: writeData_sys(const char *data, qint64 maxSize) -{ - DWORD bytesWritten = 0; - bool failed = false; - if (_queryMode == QextSerialPort::EventDriven) { - OVERLAPPED* newOverlapWrite = new OVERLAPPED; - ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED)); - newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL); - if (WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & bytesWritten, newOverlapWrite)) { - CloseHandle(newOverlapWrite->hEvent); - delete newOverlapWrite; - } - else if (GetLastError() == ERROR_IO_PENDING) { - // writing asynchronously...not an error - QWriteLocker writelocker(bytesToWriteLock); - _bytesToWrite += maxSize; - pendingWrites.append(newOverlapWrite); - } - else { - QESP_WARNING()<<"QextSerialPort write error:"<hEvent)) - QESP_WARNING("QextSerialPort: couldn't cancel IO"); - if(!CloseHandle(newOverlapWrite->hEvent)) - QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle"); - delete newOverlapWrite; - } - } else if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & bytesWritten, NULL)) { - failed = true; - } - - if (!failed) - return (qint64)bytesWritten; - - lastErr = E_WRITE_FAILED; - return -1; -} - -void QextSerialPortPrivate::setDtr_sys(bool set) { - EscapeCommFunction(Win_Handle, set ? SETDTR : CLRDTR); -} - -void QextSerialPortPrivate::setRts_sys(bool set) { - EscapeCommFunction(Win_Handle, set ? SETRTS : CLRRTS); -} - -ulong QextSerialPortPrivate::lineStatus_sys(void) { - unsigned long Status=0, Temp=0; - GetCommModemStatus(Win_Handle, &Temp); - if (Temp & MS_CTS_ON) Status|=LS_CTS; - if (Temp & MS_DSR_ON) Status|=LS_DSR; - if (Temp & MS_RING_ON) Status|=LS_RI; - if (Temp & MS_RLSD_ON) Status|=LS_DCD; - return Status; -} - -/* - Triggered when there's activity on our HANDLE. -*/ -void QextSerialPortPrivate::_q_onWinEvent(HANDLE h) -{ - Q_Q(QextSerialPort); - if(h == overlap.hEvent) { - if (eventMask & EV_RXCHAR) { - if (q->sender() != q && bytesAvailable_sys() > 0) - _q_canRead(); - } - if (eventMask & EV_TXEMPTY) { - /* - A write completed. Run through the list of OVERLAPPED writes, and if - they completed successfully, take them off the list and delete them. - Otherwise, leave them on there so they can finish. - */ - qint64 totalBytesWritten = 0; - QList overlapsToDelete; - foreach(OVERLAPPED* o, pendingWrites) { - DWORD numBytes = 0; - if (GetOverlappedResult(Win_Handle, o, & numBytes, false)) { - overlapsToDelete.append(o); - totalBytesWritten += numBytes; - } else if( GetLastError() != ERROR_IO_INCOMPLETE ) { - overlapsToDelete.append(o); - QESP_WARNING()<<"CommEvent overlapped write error:" << GetLastError(); - } - } - - if (q->sender() != q && totalBytesWritten > 0) { - QWriteLocker writelocker(bytesToWriteLock); - Q_EMIT q->bytesWritten(totalBytesWritten); - _bytesToWrite = 0; - } - - foreach(OVERLAPPED* o, overlapsToDelete) { - OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o)); - CloseHandle(toDelete->hEvent); - delete toDelete; - } - } - if (eventMask & EV_DSR) { - if (lineStatus_sys() & LS_DSR) - Q_EMIT q->dsrChanged(true); - else - Q_EMIT q->dsrChanged(false); - } - } - WaitCommEvent(Win_Handle, &eventMask, &overlap); -} - -void QextSerialPortPrivate::updatePortSettings() -{ - if (!q_ptr->isOpen() || !settingsDirtyFlags) - return; - - //fill struct : COMMCONFIG - if (settingsDirtyFlags & DFE_BaudRate) { - Win_CommConfig.dcb.BaudRate = Settings.BaudRate; - } - if (settingsDirtyFlags & DFE_Parity) { - Win_CommConfig.dcb.Parity = (BYTE)Settings.Parity; - Win_CommConfig.dcb.fParity = (Settings.Parity == PAR_NONE) ? FALSE : TRUE; - } - if (settingsDirtyFlags & DFE_DataBits) { - Win_CommConfig.dcb.ByteSize = (BYTE)Settings.DataBits; - } - if (settingsDirtyFlags & DFE_StopBits) { - switch (Settings.StopBits) { - case STOP_1: - Win_CommConfig.dcb.StopBits = ONESTOPBIT; - break; - case STOP_1_5: - Win_CommConfig.dcb.StopBits = ONE5STOPBITS; - break; - case STOP_2: - Win_CommConfig.dcb.StopBits = TWOSTOPBITS; - break; - } - } - if (settingsDirtyFlags & DFE_Flow) { - switch(Settings.FlowControl) { - /*no flow control*/ - case FLOW_OFF: - Win_CommConfig.dcb.fOutxCtsFlow=FALSE; - Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE; - Win_CommConfig.dcb.fInX=FALSE; - Win_CommConfig.dcb.fOutX=FALSE; - break; - /*software (XON/XOFF) flow control*/ - case FLOW_XONXOFF: - Win_CommConfig.dcb.fOutxCtsFlow=FALSE; - Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE; - Win_CommConfig.dcb.fInX=TRUE; - Win_CommConfig.dcb.fOutX=TRUE; - break; - /*hardware flow control*/ - case FLOW_HARDWARE: - Win_CommConfig.dcb.fOutxCtsFlow=TRUE; - Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE; - Win_CommConfig.dcb.fInX=FALSE; - Win_CommConfig.dcb.fOutX=FALSE; - break; - } - } - - //fill struct : COMMTIMEOUTS - if (settingsDirtyFlags & DFE_TimeOut) { - if (_queryMode != QextSerialPort::EventDriven) { - int millisec = Settings.Timeout_Millisec; - if (millisec == -1) { - Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD; - Win_CommTimeouts.ReadTotalTimeoutConstant = 0; - } else { - Win_CommTimeouts.ReadIntervalTimeout = millisec; - Win_CommTimeouts.ReadTotalTimeoutConstant = millisec; - } - Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0; - // zapmaker fix for dropped sent packets on fast Windows computers - //Win_CommTimeouts.WriteTotalTimeoutMultiplier = millisec; - Win_CommTimeouts.WriteTotalTimeoutMultiplier = 500; - Win_CommTimeouts.WriteTotalTimeoutConstant = 0; - } - else { - Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD; - Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0; - Win_CommTimeouts.ReadTotalTimeoutConstant = 0; - Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0; - Win_CommTimeouts.WriteTotalTimeoutConstant = 0; - } - } - - - if (settingsDirtyFlags & DFE_Settings_Mask) - SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); - if ((settingsDirtyFlags & DFE_TimeOut)) - SetCommTimeouts(Win_Handle, &Win_CommTimeouts); - settingsDirtyFlags = 0; -} +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +# include +#else +# include +#endif +void QextSerialPortPrivate::platformSpecificInit() +{ + handle = INVALID_HANDLE_VALUE; + ZeroMemory(&overlap, sizeof(OVERLAPPED)); + overlap.hEvent = CreateEvent(NULL, true, false, NULL); + winEventNotifier = 0; + bytesToWriteLock = new QReadWriteLock; +} + +void QextSerialPortPrivate::platformSpecificDestruct() { + CloseHandle(overlap.hEvent); + delete bytesToWriteLock; +} + + +/*! + \internal + COM ports greater than 9 need \\.\ prepended + + This is only need when open the port. +*/ +static QString fullPortNameWin(const QString &name) +{ + QRegExp rx(QLatin1String("^COM(\\d+)")); + QString fullName(name); + if (fullName.contains(rx)) + fullName.prepend(QLatin1String("\\\\.\\")); + return fullName; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + DWORD confSize = sizeof(COMMCONFIG); + commConfig.dwSize = confSize; + DWORD dwFlagsAndAttributes = 0; + if (queryMode == QextSerialPort::EventDriven) + dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; + + /*open the port*/ + handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); + if (handle != INVALID_HANDLE_VALUE) { + q->setOpenMode(mode); + /*configure port settings*/ + GetCommConfig(handle, &commConfig, &confSize); + GetCommState(handle, &(commConfig.dcb)); + + /*set up parameters*/ + commConfig.dcb.fBinary = TRUE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + commConfig.dcb.fAbortOnError = FALSE; + commConfig.dcb.fNull = FALSE; + /* Dtr default to true. See Issue 122*/ + commConfig.dcb.fDtrControl = TRUE; + /*flush all settings*/ + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + //init event driven approach + if (queryMode == QextSerialPort::EventDriven) { + if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { + QESP_WARNING()<<"failed to set Comm Mask. Error code:"<("HANDLE"); + q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection); + WaitCommEvent(handle, &eventMask, &overlap); + } + return true; + } + return false; +} + +bool QextSerialPortPrivate::close_sys() +{ + flush_sys(); + CancelIo(handle); + if (CloseHandle(handle)) + handle = INVALID_HANDLE_VALUE; + if (winEventNotifier) { + winEventNotifier->setEnabled(false); + winEventNotifier->deleteLater(); + winEventNotifier = 0; + } + + foreach (OVERLAPPED *o, pendingWrites) { + CloseHandle(o->hEvent); + delete o; + } + pendingWrites.clear(); + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + FlushFileBuffers(handle); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + DWORD Errors; + COMSTAT Status; + if (ClearCommError(handle, &Errors, &Status)) { + return Status.cbInQue; + } + return (qint64)-1; +} + +/* + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + if (error & CE_BREAK) { + lastErr = E_BREAK_CONDITION; + } + else if (error & CE_FRAME) { + lastErr = E_FRAMING_ERROR; + } + else if (error & CE_IOE) { + lastErr = E_IO_ERROR; + } + else if (error & CE_MODE) { + lastErr = E_INVALID_FD; + } + else if (error & CE_OVERRUN) { + lastErr = E_BUFFER_OVERRUN; + } + else if (error & CE_RXPARITY) { + lastErr = E_RECEIVE_PARITY_ERROR; + } + else if (error & CE_RXOVER) { + lastErr = E_RECEIVE_OVERFLOW; + } + else if (error & CE_TXFULL) { + lastErr = E_TRANSMIT_OVERFLOW; + } +} + +/* + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + DWORD bytesRead = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED overlapRead; + ZeroMemory(&overlapRead, sizeof(OVERLAPPED)); + if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) { + if (GetLastError() == ERROR_IO_PENDING) + GetOverlappedResult(handle, &overlapRead, &bytesRead, true); + else + failed = true; + } + } else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) { + failed = true; + } + if (!failed) + return (qint64)bytesRead; + + lastErr = E_READ_FAILED; + return -1; +} + +/* + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + DWORD bytesWritten = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED *newOverlapWrite = new OVERLAPPED; + ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED)); + newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL); + if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) { + CloseHandle(newOverlapWrite->hEvent); + delete newOverlapWrite; + } + else if (GetLastError() == ERROR_IO_PENDING) { + // writing asynchronously...not an error + QWriteLocker writelocker(bytesToWriteLock); + pendingWrites.append(newOverlapWrite); + } + else { + QESP_WARNING()<<"QextSerialPort write error:"<hEvent)) + QESP_WARNING("QextSerialPort: couldn't cancel IO"); + if (!CloseHandle(newOverlapWrite->hEvent)) + QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle"); + delete newOverlapWrite; + } + } else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) { + failed = true; + } + + if (!failed) + return (qint64)bytesWritten; + + lastErr = E_WRITE_FAILED; + return -1; +} + +void QextSerialPortPrivate::setDtr_sys(bool set) { + EscapeCommFunction(handle, set ? SETDTR : CLRDTR); +} + +void QextSerialPortPrivate::setRts_sys(bool set) { + EscapeCommFunction(handle, set ? SETRTS : CLRRTS); +} + +ulong QextSerialPortPrivate::lineStatus_sys(void) { + unsigned long Status = 0, Temp = 0; + GetCommModemStatus(handle, &Temp); + if (Temp & MS_CTS_ON) Status |= LS_CTS; + if (Temp & MS_DSR_ON) Status |= LS_DSR; + if (Temp & MS_RING_ON) Status |= LS_RI; + if (Temp & MS_RLSD_ON) Status |= LS_DCD; + return Status; +} + +/* + Triggered when there's activity on our HANDLE. +*/ +void QextSerialPortPrivate::_q_onWinEvent(HANDLE h) +{ + Q_Q(QextSerialPort); + if (h == overlap.hEvent) { + if (eventMask & EV_RXCHAR) { + if (q->sender() != q && bytesAvailable_sys() > 0) + _q_canRead(); + } + if (eventMask & EV_TXEMPTY) { + /* + A write completed. Run through the list of OVERLAPPED writes, and if + they completed successfully, take them off the list and delete them. + Otherwise, leave them on there so they can finish. + */ + qint64 totalBytesWritten = 0; + QList overlapsToDelete; + foreach (OVERLAPPED *o, pendingWrites) { + DWORD numBytes = 0; + if (GetOverlappedResult(handle, o, &numBytes, false)) { + overlapsToDelete.append(o); + totalBytesWritten += numBytes; + } else if (GetLastError() != ERROR_IO_INCOMPLETE) { + overlapsToDelete.append(o); + QESP_WARNING()<<"CommEvent overlapped write error:" << GetLastError(); + } + } + + if (q->sender() != q && totalBytesWritten > 0) { + QWriteLocker writelocker(bytesToWriteLock); + Q_EMIT q->bytesWritten(totalBytesWritten); + } + + foreach (OVERLAPPED *o, overlapsToDelete) { + OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o)); + CloseHandle(toDelete->hEvent); + delete toDelete; + } + } + if (eventMask & EV_DSR) { + if (lineStatus_sys() & LS_DSR) + Q_EMIT q->dsrChanged(true); + else + Q_EMIT q->dsrChanged(false); + } + } + WaitCommEvent(handle, &eventMask, &overlap); +} + +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_ptr->isOpen() || !settingsDirtyFlags) + return; + + //fill struct : COMMCONFIG + if (settingsDirtyFlags & DFE_BaudRate) { + commConfig.dcb.BaudRate = settings.BaudRate; + } + if (settingsDirtyFlags & DFE_Parity) { + commConfig.dcb.Parity = (BYTE)settings.Parity; + commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE; + } + if (settingsDirtyFlags & DFE_DataBits) { + commConfig.dcb.ByteSize = (BYTE)settings.DataBits; + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + commConfig.dcb.StopBits = ONESTOPBIT; + break; + case STOP_1_5: + commConfig.dcb.StopBits = ONE5STOPBITS; + break; + case STOP_2: + commConfig.dcb.StopBits = TWOSTOPBITS; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + /*no flow control*/ + case FLOW_OFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + /*software (XON/XOFF) flow control*/ + case FLOW_XONXOFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = TRUE; + commConfig.dcb.fOutX = TRUE; + break; + /*hardware flow control*/ + case FLOW_HARDWARE: + commConfig.dcb.fOutxCtsFlow = TRUE; + commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + } + } + + //fill struct : COMMTIMEOUTS + if (settingsDirtyFlags & DFE_TimeOut) { + if (queryMode != QextSerialPort::EventDriven) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutConstant = 0; + } else { + commTimeouts.ReadIntervalTimeout = millisec; + commTimeouts.ReadTotalTimeoutConstant = millisec; + } + commTimeouts.ReadTotalTimeoutMultiplier = 0; + // zapmaker fix for dropped sent packets on fast Windows computers + //commTimeouts.WriteTotalTimeoutMultiplier = millisec; + commTimeouts.WriteTotalTimeoutMultiplier = 500; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + else { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutMultiplier = 0; + commTimeouts.ReadTotalTimeoutConstant = 0; + commTimeouts.WriteTotalTimeoutMultiplier = 0; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + } + + + if (settingsDirtyFlags & DFE_Settings_Mask) + SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG)); + if ((settingsDirtyFlags & DFE_TimeOut)) + SetCommTimeouts(handle, &commTimeouts); + settingsDirtyFlags = 0; +} diff --git a/QextSerialPort/qextwineventnotifier_p.cpp b/GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.cpp similarity index 96% rename from QextSerialPort/qextwineventnotifier_p.cpp rename to GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.cpp index 3756cd3..f029421 100644 --- a/QextSerialPort/qextwineventnotifier_p.cpp +++ b/GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.cpp @@ -1,247 +1,247 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextwineventnotifier_p.h" -#include -#include -#include -#include -#include -#include -#include - -class QextWinEventNotifierPrivate -{ - Q_DECLARE_PUBLIC(QextWinEventNotifier) -public: - QextWinEventNotifierPrivate(HANDLE hEvent, QextWinEventNotifier * q) - :handleToEvent(hEvent), enabled(false), q_ptr(q) - {} - - HANDLE handleToEvent; - bool enabled; -private: - QextWinEventNotifier * q_ptr; -}; - -/* - \internal - - \class QextWinEventNotifierThread - - This class works more or less like an EventDispatcher. - - The api function WaitForMultipleObjects() is used in the new thread - to wait for the registered handle. -*/ -class QextWinEventNotifierThread:public QThread -{ -public: - explicit QextWinEventNotifierThread(QObject * parent=0); - ~QextWinEventNotifierThread(); - void stop(); - bool registerEventNotifier(QextWinEventNotifier * notifier); - void unregisterEventNotifier(QextWinEventNotifier * notifier); -protected: - void run(); -private: - HANDLE hStopEvent; //stop thread when this event signaled. - HANDLE hUpdateEvent; //make sure eventlist updated. - QMutex mutex; - QList winEventNotifierList; -}; - -Q_GLOBAL_STATIC(QextWinEventNotifierThread, notifierThread) - -QextWinEventNotifierThread::QextWinEventNotifierThread(QObject * parent) - :QThread(parent) -{ - hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - hUpdateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - start(); -} - -QextWinEventNotifierThread::~QextWinEventNotifierThread() -{ - if (isRunning()) - stop(); - CloseHandle(hStopEvent); - CloseHandle(hUpdateEvent); -} - -void QextWinEventNotifierThread::stop() -{ - { - QMutexLocker locker(&mutex); - SetEvent(hStopEvent); - } - wait(); /// Is this an good idea? -} - -bool QextWinEventNotifierThread::registerEventNotifier(QextWinEventNotifier *notifier) -{ - QMutexLocker locker(&mutex); - if (!notifier) { - QESP_WARNING("QextWinEventNotifier: Internal error"); - return false; - } - if (winEventNotifierList.contains(notifier)) - return true; - if (winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 3) { - QESP_WARNING("QextWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 3); - return false; - } - winEventNotifierList.append(notifier); - SetEvent(hUpdateEvent); - return true; -} - -void QextWinEventNotifierThread::unregisterEventNotifier(QextWinEventNotifier *notifier) -{ - QMutexLocker locker(&mutex); - if (!notifier) { - QESP_WARNING("QextWinEventNotifier: Internal error"); - return; - } - - int idx = winEventNotifierList.indexOf(notifier); - if (idx != -1) { - winEventNotifierList.takeAt(idx); - SetEvent(hUpdateEvent); - } -} - -void QextWinEventNotifierThread::run() -{ - forever{ - HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; - DWORD nCount = 0; - { - QMutexLocker locker(&mutex); - nCount = winEventNotifierList.count(); - for (int i=0; i<(int)nCount; ++i) - pHandles[i] = winEventNotifierList.at(i)->handle(); - pHandles[nCount] = hUpdateEvent; - pHandles[nCount+1] = hStopEvent; - } - DWORD ret = WaitForMultipleObjects(nCount+2, pHandles, FALSE, INFINITE); - if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + nCount) { - QEvent *evt = new QEvent(QEvent::User); - QMutexLocker locker(&mutex); - ResetEvent(pHandles[ret-WAIT_OBJECT_0]); - QObject * notifier = winEventNotifierList[ret - WAIT_OBJECT_0]; - QCoreApplication::postEvent(notifier, evt); - } - else if (ret == WAIT_OBJECT_0 + nCount) { - //ResetEvent(hUpdateEvent); - } - else if (ret == WAIT_OBJECT_0 + nCount + 1) { - //qDebug()<<"quit..."; - return; - } - } -} - -/*! - \internal - \class QextWinEventNotifier - \brief The QextWinEventNotifier class provides support for the Windows Wait functions. - - The QextWinEventNotifier class makes it possible to use the wait - functions on windows in a asynchronous manner. With this class - you can register a HANDLE to an event and get notification when - that event becomes signalled. - - \bold Note: If it is a manual reset event ,it will be reset before - the notification. This is different from QWinEventNotifier. - - \bold Note: All the registered handles will be waited under a new thread. - This is different from QWinEventNotifier whose event handle will be waited - in its affinal thread. -*/ - -QextWinEventNotifier::QextWinEventNotifier(QObject *parent) - : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(0, this)) -{} - -QextWinEventNotifier::QextWinEventNotifier(HANDLE hEvent, QObject *parent) - : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(hEvent, this)) -{ - setEnabled(true); -} - -QextWinEventNotifier::~QextWinEventNotifier() -{ - setEnabled(false); -} - -void QextWinEventNotifier::setHandle(HANDLE hEvent) -{ - setEnabled(false); - Q_D(QextWinEventNotifier); - d->handleToEvent = hEvent; -} - -HANDLE QextWinEventNotifier::handle() const -{ - return d_func()->handleToEvent; -} - -bool QextWinEventNotifier::isEnabled() const -{ - return d_func()->enabled; -} - -void QextWinEventNotifier::setEnabled(bool enable) -{ - Q_D(QextWinEventNotifier); - - if (d->enabled == enable) - return; - d->enabled = enable; - - if (d->enabled) - notifierThread()->registerEventNotifier(this); - else - notifierThread()->unregisterEventNotifier(this); -} - -bool QextWinEventNotifier::event(QEvent * e) -{ - Q_D(QextWinEventNotifier); - QObject::event(e); - if (e->type() == QEvent::User) { - emit activated(d->handleToEvent); - return true; - } - return false; -} - +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextwineventnotifier_p.h" +#include +#include +#include +#include +#include +#include +#include + +class QextWinEventNotifierPrivate +{ + Q_DECLARE_PUBLIC(QextWinEventNotifier) +public: + QextWinEventNotifierPrivate(HANDLE hEvent, QextWinEventNotifier * q) + :handleToEvent(hEvent), enabled(false), q_ptr(q) + {} + + HANDLE handleToEvent; + bool enabled; +private: + QextWinEventNotifier * q_ptr; +}; + +/* + \internal + + \class QextWinEventNotifierThread + + This class works more or less like an EventDispatcher. + + The api function WaitForMultipleObjects() is used in the new thread + to wait for the registered handle. +*/ +class QextWinEventNotifierThread:public QThread +{ +public: + explicit QextWinEventNotifierThread(QObject * parent=0); + ~QextWinEventNotifierThread(); + void stop(); + bool registerEventNotifier(QextWinEventNotifier * notifier); + void unregisterEventNotifier(QextWinEventNotifier * notifier); +protected: + void run(); +private: + HANDLE hStopEvent; //stop thread when this event signaled. + HANDLE hUpdateEvent; //make sure eventlist updated. + QMutex mutex; + QList winEventNotifierList; +}; + +Q_GLOBAL_STATIC(QextWinEventNotifierThread, notifierThread) + +QextWinEventNotifierThread::QextWinEventNotifierThread(QObject * parent) + :QThread(parent) +{ + hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hUpdateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + start(); +} + +QextWinEventNotifierThread::~QextWinEventNotifierThread() +{ + if (isRunning()) + stop(); + CloseHandle(hStopEvent); + CloseHandle(hUpdateEvent); +} + +void QextWinEventNotifierThread::stop() +{ + { + QMutexLocker locker(&mutex); + SetEvent(hStopEvent); + } + wait(); /// Is this an good idea? +} + +bool QextWinEventNotifierThread::registerEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return false; + } + if (winEventNotifierList.contains(notifier)) + return true; + if (winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 3) { + QESP_WARNING("QextWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 3); + return false; + } + winEventNotifierList.append(notifier); + SetEvent(hUpdateEvent); + return true; +} + +void QextWinEventNotifierThread::unregisterEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return; + } + + int idx = winEventNotifierList.indexOf(notifier); + if (idx != -1) { + winEventNotifierList.takeAt(idx); + SetEvent(hUpdateEvent); + } +} + +void QextWinEventNotifierThread::run() +{ + forever{ + HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; + DWORD nCount = 0; + { + QMutexLocker locker(&mutex); + nCount = winEventNotifierList.count(); + for (int i=0; i<(int)nCount; ++i) + pHandles[i] = winEventNotifierList.at(i)->handle(); + pHandles[nCount] = hUpdateEvent; + pHandles[nCount+1] = hStopEvent; + } + DWORD ret = WaitForMultipleObjects(nCount+2, pHandles, FALSE, INFINITE); + if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + nCount) { + QEvent *evt = new QEvent(QEvent::User); + QMutexLocker locker(&mutex); + ResetEvent(pHandles[ret-WAIT_OBJECT_0]); + QObject * notifier = winEventNotifierList[ret - WAIT_OBJECT_0]; + QCoreApplication::postEvent(notifier, evt); + } + else if (ret == WAIT_OBJECT_0 + nCount) { + //ResetEvent(hUpdateEvent); + } + else if (ret == WAIT_OBJECT_0 + nCount + 1) { + //qDebug()<<"quit..."; + return; + } + } +} + +/*! + \internal + \class QextWinEventNotifier + \brief The QextWinEventNotifier class provides support for the Windows Wait functions. + + The QextWinEventNotifier class makes it possible to use the wait + functions on windows in a asynchronous manner. With this class + you can register a HANDLE to an event and get notification when + that event becomes signalled. + + \bold Note: If it is a manual reset event ,it will be reset before + the notification. This is different from QWinEventNotifier. + + \bold Note: All the registered handles will be waited under a new thread. + This is different from QWinEventNotifier whose event handle will be waited + in its affinal thread. +*/ + +QextWinEventNotifier::QextWinEventNotifier(QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(0, this)) +{} + +QextWinEventNotifier::QextWinEventNotifier(HANDLE hEvent, QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(hEvent, this)) +{ + setEnabled(true); +} + +QextWinEventNotifier::~QextWinEventNotifier() +{ + setEnabled(false); +} + +void QextWinEventNotifier::setHandle(HANDLE hEvent) +{ + setEnabled(false); + Q_D(QextWinEventNotifier); + d->handleToEvent = hEvent; +} + +HANDLE QextWinEventNotifier::handle() const +{ + return d_func()->handleToEvent; +} + +bool QextWinEventNotifier::isEnabled() const +{ + return d_func()->enabled; +} + +void QextWinEventNotifier::setEnabled(bool enable) +{ + Q_D(QextWinEventNotifier); + + if (d->enabled == enable) + return; + d->enabled = enable; + + if (d->enabled) + notifierThread()->registerEventNotifier(this); + else + notifierThread()->unregisterEventNotifier(this); +} + +bool QextWinEventNotifier::event(QEvent * e) +{ + Q_D(QextWinEventNotifier); + QObject::event(e); + if (e->type() == QEvent::User) { + emit activated(d->handleToEvent); + return true; + } + return false; +} + diff --git a/QextSerialPort/qextwineventnotifier_p.h b/GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.h similarity index 97% rename from QextSerialPort/qextwineventnotifier_p.h rename to GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.h index 4aeec32..38f1457 100644 --- a/QextSerialPort/qextwineventnotifier_p.h +++ b/GC-3.6.1-T1/src/QextSerialPort/qextwineventnotifier_p.h @@ -1,80 +1,80 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#ifndef QEXTWINEVENTNOTIFIER_P_H_ -#define QEXTWINEVENTNOTIFIER_P_H_ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the QESP API. It exists for the convenience -// of other QESP classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include "qextserialport_global.h" - -class QextWinEventNotifierPrivate; -class QEXTSERIALPORT_EXPORT QextWinEventNotifier : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QextWinEventNotifier) - -public: - explicit QextWinEventNotifier(QObject *parent = 0); - explicit QextWinEventNotifier(HANDLE hEvent, QObject *parent = 0); - ~QextWinEventNotifier(); - - void setHandle(HANDLE hEvent); - HANDLE handle() const; - - bool isEnabled() const; - -public Q_SLOTS: - void setEnabled(bool enable); - -Q_SIGNALS: - void activated(HANDLE hEvent); - -protected: - bool event(QEvent * e); - -private: - Q_DISABLE_COPY(QextWinEventNotifier) - QextWinEventNotifierPrivate * d_ptr; -}; - -#endif // QEXTWINEVENTNOTIFIER_P_H_ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTWINEVENTNOTIFIER_P_H_ +#define QEXTWINEVENTNOTIFIER_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qextserialport_global.h" + +class QextWinEventNotifierPrivate; +class QEXTSERIALPORT_EXPORT QextWinEventNotifier : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextWinEventNotifier) + +public: + explicit QextWinEventNotifier(QObject *parent = 0); + explicit QextWinEventNotifier(HANDLE hEvent, QObject *parent = 0); + ~QextWinEventNotifier(); + + void setHandle(HANDLE hEvent); + HANDLE handle() const; + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); + +Q_SIGNALS: + void activated(HANDLE hEvent); + +protected: + bool event(QEvent * e); + +private: + Q_DISABLE_COPY(QextWinEventNotifier) + QextWinEventNotifierPrivate * d_ptr; +}; + +#endif // QEXTWINEVENTNOTIFIER_P_H_ diff --git a/GC-3.6.1-T1/src/README b/GC-3.6.1-T1/src/README new file mode 100644 index 0000000..19f1807 --- /dev/null +++ b/GC-3.6.1-T1/src/README @@ -0,0 +1,477 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Version 3.0 is a near-complete rewrite of the C++ code fixing all known bugs. +The other major enhancement is native Mac OSX support (including older 32 bit Intel 10.5). + +The code was tested with real milling projects using the Shapeoko and works +pretty well. For a list of possible future enhancements, see file TODO. + +Prebuilt binaries/installers can be found on github's download section for this +project (GrblHoming). Alternately, if you download the (a) Qt SDK from Nokia or +(b) the Qt source from Qt Project along with the standalone Qt Creator, you can +build from source. + +Details on how to do this can be found here: +http://zapmaker.org/ + +V3.6.1->T1 (LETARTARE proposals) + +- Improved to the same card 3 and 4 axis detection +- Displays the line numbers of the file if no number exists +- Updating of the French translation +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, + 2- Four axes 0845, future 0.8c1 (0.8c1 to 4 axes) + +V3.6.1 +Executable release rollup + +IMPORTANT: Manual/Jog control defaults to new mode which doesn't update the position. +This was done to ensure that jog motions are as fast as possible. However, if you want +to have the original 3.5.1 and earlier behavior, go to Tools | Options | Display +and change radio button to "Always Request but without Idle Check". Sending files +still updates position, it is only manual/jog that does not. + +V3.6 +Enhancements +- Options dialog is now tabbed to better fit widgets +- Ability to handle 4th axis as either A, B, or C (requires correct grbl version for axis), + please see https://github.com/zapmaker/GrblHoming/issues/56 and + https://github.com/LETARTARE/Grbl_with_Arduino/tree/master/Grbl845Mega2560 + which is the A,B,C,U,V,W axes grbl variant. +- LETARTARE: Added UVW axes +- #45: Added ability to completely or partially turn off querying position from grbl to + help improve responsiveness. The new default is to disable waiting for idle before a + jog or manual command, which speeds up those operations. Additional, you can + completely turn it off position reporting during jog or manual control which will + result in light-greyed LCD numbers. A button to query the position has been + added, which will provided up-to-date position at the time the button is pushed. + Look in Options | Display tab for new button options. You can also set the rate + at which the query takes place from 0.5-10 seconds, if it is enabled. Setting a time + that is too long may result in the system waiting too long to retrieve the final position + before control is handed back. Also, the current position dot on the Visualizer turns + from red to green when the position is not accurately known to match the color of the path. +Bug fix +- Fixed fourth axis adjust buttons and coordinate display greyed out when they shouldn't + be (under specific operating circumstances). + +V3.5.1 +Enhancements +- Made subtle modifications to the command preload when sending a file so that the + command queue on grbl is as full as possible. Previously we were depleting the + queue and then filling it again. This has possible negative performance implications, + although testing shows them to be negligible, probably because we immediately send + a command after the last ok is received. +- The status list view now supports only a maximum of 200 items when active. This was + done for the slower processors like the raspberry pi to prevent excessive CPU usage + when many commands lines exist in a file. When the user grabs the scrollbar, all + items are restored back into the view. +- A new progress bar has been added showing the current items in the grbl queue during + a file send. If the number of items for some reason drops to 0 the label text will + flash red. For this 0 count to occur is a very rare event. +- Added the ability to set the delay between sending of characters to grbl. The theory + is that grbl can drop characters if the sending computer is very fast. There is still + some debate on whether this is happening, so I provided the ability to set this value + in the options from 0 to 20 ms. Note: The default of 0 ms delay is back, like in 3.4.6 + and unlike in 3.5 which has a hardcoded 10 ms delay. +Bug fix +- Modified the status window redraw to always ensure items show on the bottom when the + redraw timer expires. + +V3.5 +Bug fix +- For very fast computers, they send characters with virtually no delay between which + requires grbl to process the serial port as fast as it can. The problem is that + grbl has an interrupt service routine that can slow down the processing it does + of incoming characters on its serial port. This causes lost characters in its input + buffer, which results in hung gcode file processing or errors. To fix, I have added + a slight delay (10ms) after sending every character. This has been confirmed to + solve the lost character problem on grbl. + +V3.4.6 +Bug fix +- Scrolling of content now completes each time. Previously there were conditions where + auto-scrolling would fail and you would have to manually scroll to see some lines +- Fixes to support 4-axis Mega2560 (tested with actual Mega2560 running 0.81 c-axis). + Includes fix to command filter to support A/B/C axis commands +- Fixed minor issue where connecting with wrong baud rate can cause long delay before + you can again control the Open/Close button +- Incorporated more translations from LETARTARE + +V3.4.5 +Bug fix +- When modifying the ui files for auto widget rescaling, broke a number of programmatically + greyed out widgets, mainly, you couldn't reopen the port after closing it. Now those are fixed. + +Enhancement +- Incorporated LETARTARE's localization file for French so that it is possible to see + locale-specific text in the installed version of Grbl Controller (see trlocale subdir) + +V3.4.4 +Bug fix +- Incorporated LETARTARE's 4-axis (C-axis) implementation - thanks! (Issues #29 and #34) + (added option to enable/disable 4-axis mode) - potential issue that needs investigating: + Can this be enabled on the fly or if it requires restart of Grbl Controller? +- Incorporated LETARTARE's translation support (French) +- Incorporated LETARTARE's fix for command history (#26) +- Incorporated Kosme's fix to issue #17 (#33). Z axis slider now moves in 0.1 inch increments + when in inches mode. +- Incorporated Kosme's fix to issue #27. If work units are inches, now displays inches, + not mm. +Enhancements +- Ability to resize entire screen and widgets. Scales down to close to 600x400 pixels + for tiny displays; also remembers last size and position of screen. (#37) +- Incorporated Kosme's fix to issue #10 (#33). Popup appears to remind you to zero position + if starting a new job. + +V3.4.3 +Bug fix +- Unsupported G43/G44 commands include following Z command which causes problems when + left standalone. The entire line must be removed. +- Now treat M2 and M30 as unsupported as they cause grbl lockup when using aggressive + preloading. +- Moved program version define into its own header file so fewer files need recompiling + with a version change. + +V3.4.2 +Bug fix +- If a gcode command line is an arc with X,Y,Z and z-rate limiting enabled, fixed to + properly split the z rate to not use the G2 command and use G1 instead as grbl + was generating an error with the G2. + +V3.4.1 +Code sync +- Fixes to code now allows code to compile under Qt5 without error and also resolves + some localization issues. Continues to properly compile under Qt4 also. No normally + noticable functional differences. + +V3.4 +Enhancements +- Z-axis slider now allows rapid control of Z-axis positioning. This feature is still + being evaluated for proper behavior due to some user-interface issues. + If you run into trouble, please report a bug. +- All axis control buttons have been permanently enabled regardless of whether or not an + axis command is in progress - this allows more rapid updating. Note - there is no error + checking for the case of entering too many commands for the Grbl buffer. This is unlikely + but possible. +- Now supports setting of baud rates from 9600 to 115200 +- Aggressive preload enabled is now the default. If the user upgraded from an older + Grbl Controller and had it disabled, a popup will warn them that it is being enabled. + They still have the option to disable, if desired +- Logging is turned on by default (only for new installs) +- All detected errors are collected and displayed after a file is run in the status view +- If filtering unsupported commands, all commands filtered out are listed after the file + is run. +- Logging now gives the line number of each command sent from the file and the corresponding + ok or error also contains the line number. +- An option has been provided to reduce the precision of lines that exceed Grbl's line buffer, + which by default is 50 characters. The code removes the arguments with the greatest precision + first and ending with at least one decimal place of precision. Errors are generated if it + cannot remove sufficient precision for the available buffer space. The buffer size on Grbl + is configurable in the options, as older Grbls have 50 characters and newer have 70. + +Bug Fixes +- If Grbl stops responding (waiting for an ok), Soft Reset Grbl now functions correctly + (so you can soft reset without having to restart Grbl Controller). This affects aggressive + preload mode only. +- Commands to start/stop coolant coupled with dwell commands and aggressive preload cause + Grbl's modal logic to stop sending OK responses (on purpose). This was solved by waiting + for the OK of the coolant off before sending additional commands. It is not clear whether + this fixes all possible such modal problems, so use carefully and report any anomalies. + +V3.3.9 +Enhancement +- We now are able to remember and restore ports that are not visible to QextSerialEnumerator + so that user doesn't have to retype the ghost port every time they start Grbl Controller. + +V3.3.8 +Enhancement/Fix +- Modified code that detects presence of Grbl upon serial port opening, the original + assumption was that we would get the version string upon serial port open, but some + Arduino-compatible boards like the AlaMode did not behave this way. Fixed the code + so that if there is no response upon serial port open, we send a soft reset (Ctrl-X) + and wait for the version string. Tested to work with AlaMode and with traditional + Ardiuno Uno. + +V3.3.7 +Enhancement +- Made COM port field editable + +V3.3.6 +Bug Fixes +- Fixed decimal on the LCD display to always show three decimal points so that + it is easier to read the display (it doesn't jump around anymore). Tested to + hold up to 9999.999 and -9999.999, which should handle 20 x 20 meter Shapeokos. + +V3.3.5 +Bug Fixes +- Changed how we detect Grbl upon opening on COM port. + ** NOTE ** This change will probably break older V0.51 capability + Previously we sent out a linefeed to trigger a response, however, this caused problems + on some arduino variants and would not result in correct sync with the controller. + Fixed by no longer sending the linefeed and instead just watch the port for Grbl response. +- Changed the default "short" wait timeout to 2 seconds from 1 second in case of slow responses. + +V3.3.4 +Enhancements +- Added option checkbox to choose to filter gcode or send it as-is to the controller. The + filtering removes gcode that is not supported in v0.8 of Grbl, which reduces the error + reports from Grbl. Some files generate unexpected codes like G91.1 which can actually + affect the motion in unexpected ways- filtering helps prevent this from happening. + + IMPORTANT: The default is to not filter, which is different than previous versions! This + may result in unexpected command processing. If using advanced gcodes, perform an air run + first. + +Bug Fixes +- Mach3 files have no whitespace in the gcode. Fixed code to handle such files. Affects + the Visualizer only. +- The filtering logic was fixed to properly filter gcode when sending a file - previous + versions would filter out gcode that Grbl supported. +- Changed validator for double (i.e. float) values so that code compiles under older Qt + versions. +- Changed Visualizer display to say Width-X and Height-Y instead of Width and Depth to make + it less confusing. + +V3.3.3 +Bug Fix +- Modal G arc (where G2 or G3 is specified once followed by X/Y/I/J) was failing for certain + arc combinations in the visualizer due to resetting the cw to false with each line. Fixed + to not reset the cw variable and retain from previous lines. + +V3.3.2 +Bug Fix +- G-command can now be set once and multiple X/Y commands then issued on lines following + (Allows "ShapeOko_Calibration_Pattern_01b.ngc to be rendered) + +V3.3.1 +Bug Fixes +- Hardened the visualizer's file parser so that it supports spaces between positional + arguments and values +- No longer skips last line in file if that line contains a valid command +- No longer crashes if line contains one or more stray whilespace characters +- Also accepts semi-colon as a comment line (in addition to existing open paren and percent) + +V3.3 +Enhancemetns +- Added "Visualizer" feature. It is now possible to see top-down view of the + file to be milled. + * Shows actual file units (inches or millimeters) independent of coordinate display + * Auto-scaling + * Supports limited subset of commands (G0/G1/G2/G3) + * Visualizer on tab panel shared with Axis control + * Actual last spindle cutter position is shown; auto-scales to include both cutter + and file + * When file is being run, overlay of all commands sent to Grbl is shown in green + * Displays dimensions of design, along with design's width and depth in file's units + +V3.2 +Enhancements +- Support for "Aggressive Preload" of commands when sending file to Grbl + * File's lines are sent to Grbl as fast as Grbl can take it, allowing + Grbl to optimize acceleration. Some files have been observed to take + 1/3 the time to complete! + * Modeled after Grbl's own python script (computes/predicts how much + space is available in Grbl's input buffer) + * Due to the additional processing, CPU usage is greater than normal mode + and it has been optimized to run fine on a Raspberry Pi + * Normal (non-preload) mode is the default + * Response processing code now waits until a line has been received rather + than collect a long stream to behave like the python script + * LCD updates have been set to be roughly once every second independent + of rate of line sends/preloads +- Z-rate limit feature now includes default xy rate setting + * Z rate limiting only occurs during file sends. If z is included with x&y + then they are split into two commands automatically and the xy rate setting + is used for the xy portion + * Since feed rate is modal, code will fix any subsequent xy items that are + missing feed rate specifiers (cambam correctly adds them, but others may not) +- Replaced basic logging with Log4Qt logging capabilities. + * Support for error, warning, info, debug message types. All messages are timestamped. + * More diagnostic messages added, mainly around sending and receiving from com ports + * Only error and warning are displayed in release build, all are displayed in debug. + * If the user enables file logging, all messages are stored regardless of build type + * File is output to user's home folder + * If you enable or disable logging to file, you must restart Grbl Controller + * You can split out diagnostic from status messages by grepping for (DIAG) or (STATUS) +- Changed menus so that the first menu is File > Exit. Menus now use accelerators + +Bug Fixes +- Fixed problems with z-rate limit feature, previous version was not implemented correctly. +- Fixed subtle issues with sending bytes to COM port + * On really fast Windows PCs, the default timeout values would occasionally result in + a line not being sent. This was fixed by changing the write timeout from 10 to + 500 ms by hardcoding it into the QextSerialPort library. This was only observed in + aggressive preload mode, never in normal mode. + +Known issues +- New reponse line detect mode requires more processing because mainly of the faster + stream of status messages. To get around this, certain features have been disabled + in the status view so that CPU usage is manageable on the Raspberry Pi, specifically + the horizontal scroll bar is not available. Turn on file logging if you wish to see + the entire line. +- When using aggressive preload, any error messages returned by Grbl are not synced + to sent messages (they come back randomly). This can be confusing. +- If running preload, it can take longer for steppers to stop after a Stop command + due to the number of items in Grbl's queue. The only way to stop sooner is to + press Close / Reset button +- Under exteme CPU loads (unlikely to occur with recent optimizations), the "runtime" + display does not display accurate times, oddly, it displays the same time that would + occur if not under load + +Tested on cardboard using file provided by user: +- Windows 7 64bit, 0.8c, aggressive mode (~4 minute run) +- Windows 7 64bit, 0.8c, normal mode (~10 minute run) +- Windows 7 64bit, 0.8a, aggressive mode(~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode (~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode and z-limit (~6 minute run) + +V3.1.2 (unofficial release, optimizations for Raspberry Pi) +Enhancements +- Optimized multiline write to status window to use faster list-based approach +- Removed unnecessary main window repaint after every line added to status window +- Fixed options window text positioning so that it appears proper on the pi + +V3.1.1 (unofficial release, adjustments for Raspberry Pi) +Enhancements +- Changed measurement units in LCD from "inches" to "in" (cosmetic) +- Shortened text and adjusted main window layout for the text size on the pi + +V3.1 +Enhancements +- Supports Grbl 0.8c. Still supports 0.8a. 0.51 is supported but without LCDs. +- Grbl settings dialog is now a table of dynamic length depending on # of params. +- LCD position data is now obtained from Grbl and is *not* computed +- Added LCD displays for both machine and work coordinates +- Cycling of Grbl via COM port toggling has been completely removed, except + that Close button has now been renamed Close / Reset. +- Position data on Grbl is persisted as long as possible to allow for repositioning, etc. +- Zero work coordinates has been added (G92) +- Go-to-home feature added (lifts tool 5 mm and traverses to x=0, y=0) +- Option to put manual command (back) into absolute mode after jog button command +- Grbl Soft reset (Ctrl-X) button added +- Z-axis rate limiting capability added. Only affects file, not jog or manual commands. +- User is required to specify which measurement mode they are using, mm or inches: + * Default is millimeters + * Grbl is configured to operate in either mm or inches + * If a file is sent in inches and user is in mm, it will auto-restore to mm + after the file has been sent (and vice-versa, mm->inches) +- 0.8c enhancements: + * Displays current Grbl state (i.e. Run, Idle, etc.) + * LCDs display whether values are in inches or millimeters + * Unlock Grbl button added ($X) + * Determines and sets parser state for current mm/inch command mode ($G) + * Determines and sets coordinate units via $13 +- Removed annoying "No movement expected for command" message +- Flags that cross threads have been changed to use QAtomicInt +- Version is now shown in title bar +- A basic log file feature has been added +- Runs on the Raspberry Pi! + +Known Issues +- The registry key product name has been changed from GCodeSender to GrblController + *** WARNING: Old settings are not migrated **** +- Switching between millimeters and inches works, but has not been fully tested +- Go to home has not been fully tested with inches mode +- Manually issuing $13 or G20/G21 can confuse the program + +V3.0 +Enhancements +- Nearly a full code rewrite to ensure ease-of-use and robustness +- Percentage complete progress bar for files; also shows time elapsed sending file. +- Reset button now cycles COM port which causes Arduino to stop steppers and + reinitialize position to 0,0,0 (No more manual Auduino resets!) +- Settings configurations are now stored using QSettings class for platform independence. +- Only available COM ports are now shown. Uses third-party QextSerialPort library. +- App remembers last COM port used, last folder, last file extension used after restart +- Ability to configure wait-for-response time +- Status list window now shows both sent and received data +- Error responses are ignored during file send (nearly 100% of the time they are not important) +- Z-jog speed using buttons is configurable +- Radio buttons to select mode have been removed in favor of enabling/disabling widgets based + on current context. This simplifies usage. +- Popups have been removed in favor of writing errors to status list window + +Bug fixes +- Overall code hardening +- Properly implementing Qt signals and slots across the board + +Build verification +- Windows 7 64 bit using MinGW +- Inno Setup for Windows, installs successfully on Windows 7 +- Mac OSX Mountain Lion, target 64 bit and 32 bit executables +- Qt Mac installer successfully installs and runs on Mountain Lion and 10.5 32 bit Intel +- Linux: Builds successfully on Debian 6, Ubuntu 12.10 + +V2.1x1 + +NOTE: Changes were only focused on Arduino GRBL capabilities with the Shapeoko, so +things like Tool Change were not tested. + +Enhancements +- Improved handling of response code - this is the most significant change as it +ensures reliable send/response handling when sending a file to the Grbl processor. +- Manual command now allows hitting return and command is sent. No need to press Go. +- Default job step size changed from 0.01 to 1 mm +- Compiles and runs under Linux now (tested with Debian and latest Qt) +- Works with old 168 Arduino processor (except that old code is buggy and not recommended) +- Disabled "go to home at end of job". The arduino code doesn't handle it correctly +and mills straight back into and through your work. Checkbox in settings has no effect. + +Bug fixes +- Fixed crash when options file is not present the first time run +- Fixed crash when trying to get GRBL settings from device +- Settings work with 168 (8 settings) and 328 processors (10 settings) +- Fixed Stop to call proper routine stopsig - now Stop button works correctly + +------------------------------------------------------------- +Fork by Zapmaker at this rev +------------------------------------------------------------- +v2.1a + +Bug fixes + +- Corrected an issue that caused the program to crash if the g-code had blank lines. + +V2.1 + +New Features + +- Gcode that is valid but is not recognized by GRBL gets filtered and it is not sent. + +Bug fixes + +- Corrected an issue that prevented manually sent Gcode for being displayed correctly. +- Corrected an issue with the images not displaying. + +V2.0 Major release + +- Improved the port handling reducing opening and closing frecuency. +- Added the ability to type and send commands directly. +- Support for tool change instructions. If enabled it pauses execution, raises the spindle, goes to a fixed location for toolchange, waits for tool change, and continues excecution. +- Added About window. + +V1.0c Minor + +Bug fixes + +- Corrected a problem when adjusting axis that caused all axis to move at the same time. Caused by grbl starting in incremental programming. + +V1.0b Minor + +Bug fixes + +- Corrected a bug in the adjusting script. + +V1.0a Minor + +Bug fixes + +- Fixed a bug reading some file formats that avoided the dials from updating. + diff --git a/TODO b/GC-3.6.1-T1/src/TODO similarity index 100% rename from TODO rename to GC-3.6.1-T1/src/TODO diff --git a/about.cpp b/GC-3.6.1-T1/src/about.cpp similarity index 100% rename from about.cpp rename to GC-3.6.1-T1/src/about.cpp diff --git a/about.h b/GC-3.6.1-T1/src/about.h similarity index 100% rename from about.h rename to GC-3.6.1-T1/src/about.h diff --git a/about.ui b/GC-3.6.1-T1/src/about.ui similarity index 97% rename from about.ui rename to GC-3.6.1-T1/src/about.ui index 06e92d9..eef05b7 100644 --- a/about.ui +++ b/GC-3.6.1-T1/src/about.ui @@ -33,7 +33,7 @@ 10 - 20 + 30 151 61 @@ -52,7 +52,7 @@ 180 - 60 + 70 201 91 @@ -68,9 +68,9 @@ 180 - 30 + 10 211 - 31 + 51 @@ -101,7 +101,7 @@ 20 - 110 + 120 130 33 diff --git a/arcitem.cpp b/GC-3.6.1-T1/src/arcitem.cpp similarity index 96% rename from arcitem.cpp rename to GC-3.6.1-T1/src/arcitem.cpp index f9a527e..4f58670 100644 --- a/arcitem.cpp +++ b/GC-3.6.1-T1/src/arcitem.cpp @@ -88,12 +88,11 @@ void ArcItem::addToPath(QPainterPath& path) path.moveTo(screenX(ex), screenY(ey)); } -#pragma GCC diagnostic ignored "-Wunused-parameter" push void ArcItem::moveToFirst(QPainterPath& path) { // not applicable! generate error! + Q_UNUSED(path); } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop double ArcItem::getXScr() { diff --git a/arcitem.h b/GC-3.6.1-T1/src/arcitem.h similarity index 100% rename from arcitem.h rename to GC-3.6.1-T1/src/arcitem.h diff --git a/atomicintbool.cpp b/GC-3.6.1-T1/src/atomicintbool.cpp similarity index 100% rename from atomicintbool.cpp rename to GC-3.6.1-T1/src/atomicintbool.cpp diff --git a/atomicintbool.h b/GC-3.6.1-T1/src/atomicintbool.h similarity index 100% rename from atomicintbool.h rename to GC-3.6.1-T1/src/atomicintbool.h diff --git a/GC-3.6.1-T1/src/clean.bat b/GC-3.6.1-T1/src/clean.bat new file mode 100644 index 0000000..8a41d93 --- /dev/null +++ b/GC-3.6.1-T1/src/clean.bat @@ -0,0 +1,12 @@ +rem clean.bat +rem by LETARTARE + +mingw32-make clean + +del release\GrblController.exe + +del debug\GrblController.exe + +cd .. + + diff --git a/controlparams.cpp b/GC-3.6.1-T1/src/controlparams.cpp similarity index 54% rename from controlparams.cpp rename to GC-3.6.1-T1/src/controlparams.cpp index fc6aa79..7e7ed6a 100644 --- a/controlparams.cpp +++ b/GC-3.6.1-T1/src/controlparams.cpp @@ -5,6 +5,10 @@ ControlParams::ControlParams() useMm(true), zRateLimit(false), zRateLimitAmount(DEFAULT_Z_LIMIT_RATE), xyRateAmount(DEFAULT_XY_RATE), useAggressivePreload(false), filterFileCommands(false), - reducePrecision(false), grblLineBufferLen(DEFAULT_GRBL_LINE_BUFFER_LEN) + reducePrecision(false), grblLineBufferLen(DEFAULT_GRBL_LINE_BUFFER_LEN), + useFourAxis(false), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS), + fourthAxisType(FOURTH_AXIS_A), usePositionRequest(true), + positionRequestType(PREQ_ALWAYS_NO_IDLE_CHK), postionRequestTimeMilliSec(DEFAULT_POS_REQ_FREQ_MSEC), + waitForJogToComplete(true) { } diff --git a/controlparams.h b/GC-3.6.1-T1/src/controlparams.h similarity index 69% rename from controlparams.h rename to GC-3.6.1-T1/src/controlparams.h index a552618..0328f2d 100644 --- a/controlparams.h +++ b/GC-3.6.1-T1/src/controlparams.h @@ -22,6 +22,13 @@ class ControlParams bool filterFileCommands; bool reducePrecision; int grblLineBufferLen; + bool useFourAxis; + int charSendDelayMs; + char fourthAxisType; + bool usePositionRequest; + QString positionRequestType; + int postionRequestTimeMilliSec; + bool waitForJogToComplete; }; #endif // CONTROLPARAMS_H diff --git a/GC-3.6.1-T1/src/coord3d.cpp b/GC-3.6.1-T1/src/coord3d.cpp new file mode 100644 index 0000000..b89d175 --- /dev/null +++ b/GC-3.6.1-T1/src/coord3d.cpp @@ -0,0 +1,11 @@ +#include "coord3d.h" + +Coord3D::Coord3D() + : x(0.0), y(0.0), z(0.0), fourth(0.0), stoppedZ(true), sliderZIndex(0) +{ +} + +bool Coord3D::operator==(const Coord3D& rhs) +{ + return (x == rhs.x && y == rhs.y && z == rhs.z && fourth == rhs.fourth) ; +} diff --git a/coord3d.h b/GC-3.6.1-T1/src/coord3d.h similarity index 94% rename from coord3d.h rename to GC-3.6.1-T1/src/coord3d.h index 9b46a3a..aac648e 100644 --- a/coord3d.h +++ b/GC-3.6.1-T1/src/coord3d.h @@ -13,6 +13,7 @@ class Coord3D float x; float y; float z; + float fourth; bool stoppedZ; int sliderZIndex; }; diff --git a/definitions.h b/GC-3.6.1-T1/src/definitions.h similarity index 73% rename from definitions.h rename to GC-3.6.1-T1/src/definitions.h index 48c3457..1491d8e 100644 --- a/definitions.h +++ b/GC-3.6.1-T1/src/definitions.h @@ -22,6 +22,7 @@ #define DEFAULT_XY_RATE 2000.0 #define DEFAULT_GRBL_LINE_BUFFER_LEN 50 +#define DEFAULT_CHAR_SEND_DELAY_MS 0 #define MM_IN_AN_INCH 25.4 #define PRE_HOME_Z_ADJ_MM 5.0 @@ -40,6 +41,22 @@ #define LOG_MSG_TYPE_DIAG "DIAG" #define LOG_MSG_TYPE_STATUS "STATUS" +/// LETARTARE : one axis choice U or V or W or A or B or C +#define FOURTH_AXIS_U 'U' +#define FOURTH_AXIS_V 'V' +#define FOURTH_AXIS_W 'W' +/// <-- +#define FOURTH_AXIS_A 'A' +#define FOURTH_AXIS_B 'B' +#define FOURTH_AXIS_C 'C' + +#define PREQ_ALWAYS "always" +#define PREQ_ALWAYS_NO_IDLE_CHK "alwaysWithoutIdleChk" +#define PREQ_NOT_WHEN_MANUAL "notWhenManual" + +#define DEFAULT_POS_REQ_FREQ_SEC 1.0 +#define DEFAULT_POS_REQ_FREQ_MSEC 1000 + extern AtomicIntBool g_enableDebugLog; void status(const char *str, ...); diff --git a/fixqt4headers.pl b/GC-3.6.1-T1/src/fixqt4headers.pl similarity index 100% rename from fixqt4headers.pl rename to GC-3.6.1-T1/src/fixqt4headers.pl diff --git a/gcode.cpp b/GC-3.6.1-T1/src/gcode.cpp similarity index 70% rename from gcode.cpp rename to GC-3.6.1-T1/src/gcode.cpp index 910a602..c088466 100644 --- a/gcode.cpp +++ b/GC-3.6.1-T1/src/gcode.cpp @@ -1,1818 +1,2009 @@ -/**************************************************************** - * gcode.cpp - * GrblHoming - zapmaker fork on github - * - * 15 Nov 2012 - * GPL License (see LICENSE file) - * Software is provided AS-IS - ****************************************************************/ - -#include "gcode.h" - -GCode::GCode() - : errorCount(0), doubleDollarFormat(false), - incorrectMeasurementUnits(false), incorrectLcdDisplayUnits(false), - maxZ(0), motionOccurred(false), - sliderZCount(0) -{ - // use base class's timer - use it to capture random text from the controller - startTimer(1000); -} - -void GCode::openPort(QString commPortStr, QString baudRate) -{ - clearToHome(); - - currComPort = commPortStr; - - if (port.OpenComport(commPortStr, baudRate)) - { - emit portIsOpen(true); - } - else - { - emit portIsClosed(false); - QString msg = "Can't open COM port " + commPortStr; - sendMsg(msg); - addList(msg); - warn("%s", msg.toLocal8Bit().constData()); - - addList("-Is hardware connected to USB?"); - addList("-Is correct port chosen?"); - addList("-Does current user have sufficient permissions?"); -#if defined(Q_OS_LINUX) - addList("-Is current user in sudoers group?"); -#endif - //QMessageBox(QMessageBox::Critical,"Error","Could not open port.",QMessageBox::Ok).exec(); - } -} - -void GCode::closePort(bool reopen) -{ - port.CloseComport(); - emit portIsClosed(reopen); -} - -bool GCode::isPortOpen() -{ - return port.isPortOpen(); -} - -// Abort means stop file send after the end of this line -void GCode::setAbort() -{ - // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec - abortState.set(true); -} - -// Reset means immediately stop waiting for a response -void GCode::setReset() -{ - // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec - resetState.set(true); -} - -// Shutdown means app is shutting down - we give thread about .3 sec to exit what it is doing -void GCode::setShutdown() -{ - // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec - shutdownState.set(true); -} - -// Slot for interrupting current operation or doing a clean reset of grbl without changing position values -void GCode::sendGrblReset() -{ - clearToHome(); - - QString x(CTRL_X); - sendGcodeLocal(x, true, SHORT_WAIT_SEC); -} - -void GCode::sendGrblUnlock() -{ - sendGcodeLocal(SET_UNLOCK_STATE_V08c); -} - -// Slot for gcode-based 'zero out the current position values without motion' -void GCode::grblSetHome() -{ - clearToHome(); - - gotoXYZ("G92 x0 y0 z0"); -} - -void GCode::goToHome() -{ - if (!motionOccurred) - return; - - double maxZOver = maxZ; - - if (doubleDollarFormat) - { - maxZOver += (controlParams.useMm ? PRE_HOME_Z_ADJ_MM : (PRE_HOME_Z_ADJ_MM / MM_IN_AN_INCH)); - } - else - { - // all reporting is in mm - maxZOver += PRE_HOME_Z_ADJ_MM; - } - - QString zpos = QString::number(maxZOver); - - gotoXYZ(QString("G0 z").append(zpos)); - gotoXYZ(QString("G1 x0 y0")); - - maxZ -= maxZOver; - - motionOccurred = false; -} - -// Slot called from other threads (i.e. main window, grbl dialog, etc.) -void GCode::sendGcode(QString line) -{ - bool checkMeasurementUnits = false; - - // empty line means we have just opened the com port - if (line.length() == 0) - { - resetState.set(false); - - QString result; - if (!waitForStartupBanner(result, SHORT_WAIT_SEC, false)) - { - if (shutdownState.get() || resetState.get()) - return; - // it is possible that we are already connected and missed the - // signon banner. Force a reset (is this ok?) to get the banner - - emit addListOut("(CTRL-X)"); - - char buf[2] = {0}; - - buf[0] = CTRL_X; - - diag("SENDING: 0x%02X (CTRL-X) to check presence of Grbl\n", buf[0]); - - if (!port.SendBuf(buf, 1)) - { - QString msg = "Sending to port failed"; - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - emit sendMsg(msg); - return; - } - - if (!waitForStartupBanner(result, SHORT_WAIT_SEC, true)) - return; - } - - checkMeasurementUnits = true; - } - else - { - pollPosWaitForIdle(false); - - // normal send of actual commands - sendGcodeLocal(line, false); - } - - pollPosWaitForIdle(checkMeasurementUnits); -} - -// keep polling our position and state until we are done running -void GCode::pollPosWaitForIdle(bool checkMeasurementUnits) -{ - bool immediateQuit = false; - for (int i = 0; i < 10000; i++) - { - bool ret = sendGcodeLocal(REQUEST_CURRENT_POS); - if (!ret) - { - immediateQuit = true; - break; - } - - if (doubleDollarFormat) - { - if (lastState.compare("Run") != 0) - break; - } - else - { - if (machineCoordLastIdlePos == machineCoord - && workCoordLastIdlePos == workCoord) - { - break; - } - - machineCoordLastIdlePos = machineCoord; - workCoordLastIdlePos = workCoord; - } - - if (shutdownState.get()) - return; - } - - if (immediateQuit) - return; - - if (checkMeasurementUnits) - { - if (doubleDollarFormat) - checkAndSetCorrectMeasurementUnits(); - else - setOldFormatMeasurementUnitControl(); - } -} - -// Slot called from other thread that returns whatever text comes back from the controller -void GCode::sendGcodeAndGetResult(int id, QString line) -{ - QString result; - - emit sendMsg(""); - resetState.set(false); - if (!sendGcodeInternal(line, result, false, SHORT_WAIT_SEC, false)) - result.clear(); - - emit gcodeResult(id, result); -} - -// To be called only from this class, not from other threads. Use above two methods for that. -// Wraps sendGcodeInternal() to allow proper handling of failure cases, etc. -bool GCode::sendGcodeLocal(QString line, bool recordResponseOnFail /* = false */, int waitSec /* = -1 */, bool aggressive /* = false */, int currLine /* = 0 */) -{ - QString result; - sendMsg(""); - resetState.set(false); - - bool ret = sendGcodeInternal(line, result, recordResponseOnFail, waitSec, aggressive, currLine); - if (shutdownState.get()) - return false; - - if (!ret && (!recordResponseOnFail || resetState.get())) - { - if (!resetState.get()) - emit stopSending(); - - if (!ret && resetState.get()) - { - resetState.set(false); - port.Reset(); - } - } - else - { - if (checkGrbl(result)) - { - emit enableGrblDialogButton(); - } - } - resetState.set(false); - return ret; -} - -bool GCode::checkGrbl(const QString& result) -{ - if (result.contains("Grbl")) - { - QRegExp rx("Grbl (\\d+)\\.(\\d+)(\\w*)"); - if (rx.indexIn(result) != -1 && rx.captureCount() > 0) - { - doubleDollarFormat = false; - - QStringList list = rx.capturedTexts(); - if (list.size() >= 3) - { - int majorVer = list.at(1).toInt(); - int minorVer = list.at(2).toInt(); - char letter = 'a'; - if (list.size() == 4 && list.at(3).size() > 0) - { - letter = list.at(3).toLatin1().at(0); - } - - if (majorVer > 0 || (minorVer > 8 && minorVer < 51) || letter > 'a') - { - doubleDollarFormat = true; - } - - diag("Got Grbl Version (Parsed:) %d.%d%c ($$=%d)\n", - majorVer, minorVer, letter, doubleDollarFormat); - } - - if (!doubleDollarFormat) - setUnitsTypeDisplay(true); - } - return true; - } - return false; -} - -// Wrapped method. Should only be called from above method. -bool GCode::sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine /* = 0 */) -{ - if (!port.isPortOpen()) - { - QString msg = "Port not available yet"; - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - emit sendMsg(msg); - return false; - } - - bool ctrlX = line.size() > 0 ? (line.at(0).toLatin1() == CTRL_X) : false; - - bool sentReqForLocation = false; - bool sentReqForSettings = false; - bool sentReqForParserState = false; - - if (!line.compare(REQUEST_CURRENT_POS)) - { - sentReqForLocation = true; - } - else if (!line.compare(REQUEST_PARSER_STATE_V08c)) - { - sentReqForParserState = true; - } - else if (!line.compare(SETTINGS_COMMAND_V08a)) - { - if (doubleDollarFormat) - line = SETTINGS_COMMAND_V08c; - - sentReqForSettings = true; - } - else - motionOccurred = true; - - // adds to UI list, but prepends a > indicating a sent command - if (ctrlX) - { - emit addListOut("(CTRL-X)"); - } - else if (!sentReqForLocation)// if requesting location, don't add that "noise" to the output view - { - emit addListOut(line); - } - - if (line.size() == 0 || (!line.endsWith('\r') && !ctrlX)) - line.append('\r'); - - char buf[BUF_SIZE + 1] = {0}; - if (line.length() >= BUF_SIZE) - { - QString msg = "Buffer size too small"; - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - emit sendMsg(msg); - return false; - } - for (int i = 0; i < line.length(); i++) - buf[i] = line.at(i).toLatin1(); - - if (ctrlX) - diag("SENDING[%d]: 0x%02X (CTRL-X)\n", currLine, buf[0]); - else - diag("SENDING[%d]: %s\n", currLine, buf); - - int waitSecActual = waitSec == -1 ? controlParams.waitTime : waitSec; - - if (aggressive) - { - if (ctrlX) - sendCount.append(CmdResponse("(CTRL-X)", line.length(), currLine)); - else - sendCount.append(CmdResponse(buf, line.length(), currLine)); - - waitForOk(result, waitSecActual, false, false, aggressive); - - if (shutdownState.get()) - return false; - } - - if (!port.SendBuf(buf, line.length())) - { - QString msg = "Sending to port failed"; - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - emit sendMsg(msg); - return false; - } - else - { - sentI++; - if (!waitForOk(result, waitSecActual, sentReqForLocation, sentReqForParserState, aggressive)) - { - diag("WAITFOROK FAILED\n"); - if (shutdownState.get()) - return false; - - if (!recordResponseOnFail && !(resetState.get() || abortState.get())) - { - QString msg = "Wait for ok failed"; - emit addList(msg); - emit sendMsg(msg); - } - - return false; - } - else - { - if (sentReqForSettings) - { - QStringList list = result.split("$"); - for (int i = 0; i < list.size(); i++) - { - QString item = list.at(i); - const QRegExp rx(REGEXP_SETTINGS_LINE); - - if (rx.indexIn(item, 0) != -1 && rx.captureCount() == 3) - { - QStringList capList = rx.capturedTexts(); - if (!capList.at(1).compare("13")) - { - if (!capList.at(2).compare("0")) - { - if (!controlParams.useMm) - incorrectLcdDisplayUnits = true; - } - else - { - if (controlParams.useMm) - incorrectLcdDisplayUnits = true; - } - break; - } - } - } - - settingsItemCount.set(list.size()); - } - } - } - return true; -} - -bool GCode::waitForOk(QString& result, int waitSec, bool sentReqForLocation, bool sentReqForParserState, bool aggressive) -{ - if (aggressive) - { - if (!port.bytesAvailable()) - { - int total = 0; - bool haveWait = false; - foreach (CmdResponse cmdResp, sendCount) - { - total += cmdResp.count; - if (cmdResp.waitForMe) - { - haveWait = true; - } - } - - //printf("Total out (a): %d (%d) (%d)\n", total, sendCount.size(), haveWait); - - if (!haveWait) - { - if (total < (GRBL_RX_BUFFER_SIZE - 1)) - { - return true; - } - } - } - } - - char tmp[BUF_SIZE + 1] = {0}; - int count = 0; - int waitCount = waitSec * 10;// multiplier depends on sleep values below - bool status = true; - result.clear(); - while (!result.contains(RESPONSE_OK) && !result.contains(RESPONSE_ERROR) && !resetState.get()) - { - int n = port.PollComportLine(tmp, BUF_SIZE); - if (n == 0) - { - if (aggressive && sendCount.size() == 0) - return false; - - count++; - SLEEP(100); - } - else if (n < 0) - { - err("Error reading data from COM port\n"); - - if (aggressive && sendCount.size() == 0) - return false; - } - else - { - tmp[n] = 0; - result.append(tmp); - - QString tmpTrim(tmp); - int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); - if (pos != -1) - tmpTrim.remove(pos, port.getDetectedLineFeed().size()); - QString received(tmp); - - if (aggressive) - { - if (received.contains(RESPONSE_OK)) - { - if (sendCount.isEmpty()) - err("Unexpected: list is empty (o)!"); - else - { - CmdResponse cmdResp = sendCount.takeFirst(); - diag("GOT[%d]:%s for %s\n", cmdResp.line, tmpTrim.toLocal8Bit().constData(), cmdResp.cmd.toLocal8Bit().constData()); - } - rcvdI++; - } - else if (received.contains(RESPONSE_ERROR)) - { - QString orig("Error?"); - if (sendCount.isEmpty()) - err("Unexpected: list is empty (e)!"); - else - { - CmdResponse cmdResp = sendCount.takeFirst(); - orig = cmdResp.cmd; - diag("GOT[%d]:%s for %s\n", cmdResp.line, tmpTrim.toLocal8Bit().constData(), orig.toLocal8Bit().constData()); - } - errorCount++; - QString result; - QTextStream(&result) << received << " [for " << orig << "]"; - emit addList(result); - grblCmdErrors.append(result); - rcvdI++; - } - else - { - diag("GOT:%s\n", tmpTrim.toLocal8Bit().constData()); - parseCoordinates(received, aggressive); - } - - int total = 0; - foreach (CmdResponse cmdResp, sendCount) - { - total += cmdResp.count; - } - - //printf("Total out (b): %d (%d)\n", total, sendCount.size()); - //printf("SENT:%d RCVD:%d\n", sentI, rcvdI); - - if (port.bytesAvailable() || total >= (GRBL_RX_BUFFER_SIZE - 1)) - { - result.clear(); - continue; - } - else - { - return true; - } - } - else - { - diag("GOT:%s\n", tmpTrim.toLocal8Bit().constData()); - } - - if (!received.contains(RESPONSE_OK) && !received.contains(RESPONSE_ERROR)) - { - if (sentReqForParserState) - { - const QRegExp rx("\\[([\\s\\w\\.\\d]+)\\]"); - - if (rx.indexIn(received, 0) != -1 && rx.captureCount() == 1) - { - QStringList list = rx.capturedTexts(); - if (list.size() == 2) - { - QStringList items = list.at(1).split(" "); - if (items.contains("G20"))// inches - { - if (controlParams.useMm) - incorrectMeasurementUnits = true; - else - incorrectMeasurementUnits = false; - } - else if (items.contains("G21"))// millimeters - { - if (controlParams.useMm) - incorrectMeasurementUnits = false; - else - incorrectMeasurementUnits = true; - } - else - { - // not in list! - incorrectMeasurementUnits = true; - } - } - } - } - else - { - parseCoordinates(received, aggressive); - } - } - count = 0; - } - - SLEEP(100); - - if (count > waitCount) - { - // waited too long for a response, fail - status = false; - break; - } - } - - if (shutdownState.get()) - { - return false; - } - - if (status) - { - if (!aggressive) - SLEEP(100); - - if (resetState.get()) - { - QString msg("Wait interrupted by user"); - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - } - } - - if (result.contains(RESPONSE_ERROR)) - { - errorCount++; - // skip over errors - //status = false; - } - - QStringList list = QString(result).split(port.getDetectedLineFeed()); - QStringList listToSend; - for (int i = 0; i < list.size(); i++) - { - if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !sentReqForLocation) - listToSend.append(list.at(i)); - } - - sendStatusList(listToSend); - - if (resetState.get()) - { - // we have been told by the user to stop. - status = false; - } - - return status; -} - -bool GCode::waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound) -{ - char tmp[BUF_SIZE + 1] = {0}; - int count = 0; - int waitCount = waitSec * 10;// multiplier depends on sleep values below - bool status = true; - result.clear(); - while (!resetState.get()) - { - int n = port.PollComportLine(tmp, BUF_SIZE); - if (n == 0) - { - count++; - SLEEP(100); - } - else if (n < 0) - { - err("Error reading data from COM port\n"); - } - else - { - tmp[n] = 0; - result.append(tmp); - - QString tmpTrim(tmp); - int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); - if (pos != -1) - tmpTrim.remove(pos, port.getDetectedLineFeed().size()); - diag("GOT:%s\n", tmpTrim.toLocal8Bit().constData()); - - if (tmpTrim.length() > 0) - { - if (!checkGrbl(tmpTrim)) - { - if (failOnNoFound) - { - QString msg("Expecting Grbl version string. Unable to parse response."); - emit addList(msg); - emit sendMsg(msg); - - closePort(false); - } - } - else - { - emit enableGrblDialogButton(); - } - break; - } - } - - SLEEP(100); - - if (count > waitCount) - { - if (failOnNoFound) - { - // waited too long for a response, fail - - QString msg("No data from COM port after connect. Expecting Grbl version string."); - emit addList(msg); - emit sendMsg(msg); - - closePort(false); - } - - status = false; - break; - } - } - - if (shutdownState.get()) - { - return false; - } - - if (status) - { - if (resetState.get()) - { - QString msg("Wait interrupted by user (startup)"); - err("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - } - } - - if (result.contains(RESPONSE_ERROR)) - { - errorCount++; - // skip over errors - //status = false; - } - - QStringList list = QString(result).split(port.getDetectedLineFeed()); - QStringList listToSend; - for (int i = 0; i < list.size(); i++) - { - if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK) - listToSend.append(list.at(i)); - } - - sendStatusList(listToSend); - - if (resetState.get()) - { - // we have been told by the user to stop. - status = false; - } - - return status; -} - -void GCode::parseCoordinates(const QString& received, bool aggressive) -{ - if (aggressive) - { - int ms = parseCoordTimer.elapsed(); - if (ms < 500) - return; - - parseCoordTimer.restart(); - } - - QString state; - QString prepend; - QString append; - QString preamble = "([a-zA-Z]+),MPos:"; - int captureCount = 4; - - if (!doubleDollarFormat) - { - prepend = "\\["; - append = "\\]"; - preamble = "MPos:"; - captureCount = 3; - } - - const QString coordRegExp(prepend + "(-*\\d+\\.\\d+),(-*\\d+\\.\\d+),(-*\\d+\\.\\d+)" + append); - const QRegExp rxStateMPos(preamble + coordRegExp); - const QRegExp rxWPos("WPos:" + coordRegExp); - - if (rxStateMPos.indexIn(received, 0) != -1 && rxStateMPos.captureCount() == captureCount - && rxWPos.indexIn(received, 0) != -1 && rxWPos.captureCount() == 3) - { - QStringList list = rxStateMPos.capturedTexts(); - int index = 1; - - if (doubleDollarFormat) - state = list.at(index++); - - machineCoord.x = list.at(index++).toFloat(); - machineCoord.y = list.at(index++).toFloat(); - machineCoord.z = list.at(index++).toFloat(); - - list = rxWPos.capturedTexts(); - workCoord.x = list.at(1).toFloat(); - workCoord.y = list.at(2).toFloat(); - workCoord.z = list.at(3).toFloat(); - - if (state != "Run") - workCoord.stoppedZ = true; - else - workCoord.stoppedZ = false; - - workCoord.sliderZIndex = sliderZCount; - - diag("Decoded: State:%s MPos: %f,%f,%f WPos: %f,%f,%f\n", - state.toLocal8Bit().constData(), - machineCoord.x, machineCoord.y, machineCoord.z, - workCoord.x, workCoord.y, workCoord.z); - - if (workCoord.z > maxZ) - maxZ = workCoord.z; - - emit updateCoordinates(machineCoord, workCoord); - emit setLivePoint(workCoord.x, workCoord.y, controlParams.useMm); - emit setLastState(state); - - lastState = state; - return; - } - else if (received.indexOf("MPos:") != -1) - { - err("Error decoding position data!\n"); - } - lastState = ""; -} - -void GCode::sendStatusList(QStringList& listToSend) -{ - if (listToSend.size() > 1) - { - emit addListFull(listToSend); - } - else if (listToSend.size() == 1) - { - emit addList(listToSend.at(0)); - } -} - -// called once a second to capture any random strings that come from the controller -#pragma GCC diagnostic ignored "-Wunused-parameter" push -void GCode::timerEvent(QTimerEvent *event) -{ - if (port.isPortOpen()) - { - char tmp[BUF_SIZE + 1] = {0}; - QString result; - - for (int i = 0; i < 10 && !shutdownState.get() && !resetState.get(); i++) - { - int n = port.PollComport(tmp, BUF_SIZE); - if (n == 0) - break; - - tmp[n] = 0; - result.append(tmp); - diag("GOT-TE:%s\n", tmp); - } - - if (shutdownState.get()) - { - return; - } - - QStringList list = QString(result).split(port.getDetectedLineFeed()); - QStringList listToSend; - for (int i = 0; i < list.size(); i++) - { - if (list.at(i).length() > 0 && (list.at(i) != "ok" || (list.at(i) == "ok" && abortState.get()))) - listToSend.append(list.at(i)); - } - - sendStatusList(listToSend); - } -} -#pragma GCC diagnostic ignored "-Wunused-parameter" pop - -void GCode::sendFile(QString path) -{ - addList(QString("Sending file '%1'").arg(path)); - - // send something to be sure the controller is ready - //sendGcodeLocal("", true, SHORT_WAIT_SEC); - - setProgress(0); - grblCmdErrors.clear(); - grblFilteredCmds.clear(); - errorCount = 0; - abortState.set(false); - QFile file(path); - if (file.open(QFile::ReadOnly)) - { - float totalLineCount = 0; - QTextStream code(&file); - while ((code.atEnd() == false)) - { - totalLineCount++; - code.readLine(); - } - if (totalLineCount == 0) - totalLineCount = 1; - - code.seek(0); - - // set here once so that it doesn't change in the middle of a file send - bool aggressive = controlParams.useAggressivePreload; - if (aggressive) - sendCount.clear(); - - sentI = 0; - rcvdI = 0; - emit resetTimer(true); - - parseCoordTimer.restart(); - - QTime pollPosTimer; - pollPosTimer.start(); - - int currLine = 0; - bool xyRateSet = false; - - do - { - QString strline = code.readLine(); - - emit setVisCurrLine(currLine + 1); - - if (controlParams.filterFileCommands) - { - trimToEnd(strline, '('); - trimToEnd(strline, ';'); - trimToEnd(strline, '%'); - } - - strline = strline.trimmed(); - - if (strline.size() == 0) - {}//ignore comments - else - { - if (controlParams.filterFileCommands) - { - strline = strline.toUpper(); - strline.replace(QRegExp("([A-Z])"), " \\1"); - strline = removeUnsupportedCommands(strline); - } - - if (strline.size() != 0) - { - if (controlParams.reducePrecision) - { - strline = reducePrecision(strline); - } - - QString rateLimitMsg; - QStringList outputList; - if (controlParams.zRateLimit) - { - outputList = doZRateLimit(strline, rateLimitMsg, xyRateSet); - } - else - { - outputList.append(strline); - } - - bool ret = false; - if (outputList.size() == 1) - { - ret = sendGcodeLocal(outputList.at(0), false, -1, aggressive, currLine + 1); - } - else - { - foreach (QString outputLine, outputList) - { - ret = sendGcodeLocal(outputLine, false, -1, aggressive, currLine + 1); - - if (!ret) - break; - } - } - - if (rateLimitMsg.size() > 0) - addList(rateLimitMsg); - - if (!ret) - { - abortState.set(true); - break; - } - } - } - - float percentComplete = (currLine * 100.0) / totalLineCount; - setProgress((int)percentComplete); - - if (!aggressive) - { - sendGcodeLocal(REQUEST_CURRENT_POS); - } - else - { - int ms = pollPosTimer.elapsed(); - if (ms >= 1000) - { - pollPosTimer.restart(); - sendGcodeLocal(REQUEST_CURRENT_POS, false, -1, aggressive); - } - } - currLine++; - } while ((code.atEnd() == false) && (!abortState.get())); - file.close(); - - if (aggressive) - { - int limitCount = 5000; - while (sendCount.size() > 0 && limitCount) - { - QString result; - waitForOk(result, controlParams.waitTime, false, false, aggressive); - SLEEP(100); - - if (shutdownState.get()) - return; - - if (abortState.get()) - break; - - limitCount--; - } - - if (!limitCount) - { - err("Gave up waiting for OK\n"); - } - } - - sendGcodeLocal(REQUEST_CURRENT_POS); - - emit resetTimer(false); - - if (shutdownState.get()) - { - return; - } - - QString msg; - if (!abortState.get()) - { - setProgress(100); - if (errorCount > 0) - { - msg = QString("Code sent successfully with %1 error(s):").arg(QString::number(errorCount)); - emit sendMsg(msg); - emit addList(msg); - - foreach(QString errItem, grblCmdErrors) - { - emit sendMsg(errItem); - } - emit addListFull(grblCmdErrors); - } - else - { - msg = "Code sent successfully with no errors."; - emit sendMsg(msg); - emit addList(msg); - } - - if (grblFilteredCmds.size() > 0) - { - msg = QString("Filtered %1 commands:").arg(QString::number(grblFilteredCmds.size())); - emit sendMsg(msg); - emit addList(msg); - - foreach(QString errItem, grblFilteredCmds) - { - emit sendMsg(errItem); - } - emit addListFull(grblFilteredCmds); - } - } - else - { - msg = "Process interrupted."; - emit sendMsg(msg); - emit addList(msg); - } - } - - pollPosWaitForIdle(true); - - if (!resetState.get()) - { - emit stopSending(); - } -} - -void GCode::trimToEnd(QString& strline, QChar ch) -{ - int pos = strline.indexOf(ch); - if (pos != -1) - strline = strline.left(pos); -} - -QString GCode::removeUnsupportedCommands(QString line) -{ - QStringList components = line.split(" ", QString::SkipEmptyParts); - QString tmp; - QString s; - QString following; - bool toEndOfLine = false; - foreach (s, components) - { - if (toEndOfLine) - { - QString msg(QString("Removed unsupported command '%1' part of '%2'").arg(s).arg(following)); - warn("%s", msg.toLocal8Bit().constData()); - grblFilteredCmds.append(msg); - emit addList(msg); - continue; - } - - if (s.at(0) == 'G') - { - float value = s.mid(1,-1).toFloat(); - if (isGCommandValid(value, toEndOfLine)) - tmp.append(s).append(" "); - else - { - if (toEndOfLine) - following = s; - QString msg(QString("Removed unsupported G command '%1'").arg(s)); - warn("%s", msg.toLocal8Bit().constData()); - grblFilteredCmds.append(msg); - emit addList(msg); - } - } - else if (s.at(0) == 'M') - { - float value = s.mid(1,-1).toFloat(); - if (isMCommandValid(value)) - tmp.append(s).append(" "); - else - { - QString msg(QString("Removed unsupported M command '%1'").arg(s)); - warn("%s", msg.toLocal8Bit().constData()); - grblFilteredCmds.append(msg); - emit addList(msg); - } - } - else if (s.at(0) == 'N') - { - // skip line numbers - } - else if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'Z' - || s.at(0) == 'I' || s.at(0) == 'J' || s.at(0) == 'K' - || s.at(0) == 'F' || s.at(0) == 'L' || s.at(0) == 'S') - { - tmp.append(s).append(" "); - } - else - { - QString msg(QString("Removed unsupported command '%1'").arg(s)); - warn("%s", msg.toLocal8Bit().constData()); - grblFilteredCmds.append(msg); - emit addList(msg); - } - } - - return tmp.trimmed(); -} - -QString GCode::reducePrecision(QString line) -{ - // first remove all spaces to determine what are line length is - QStringList components = line.split(" ", QString::SkipEmptyParts); - QString result; - foreach(QString token, components) - { - result.append(token); - } - - if (result.length() == 0) - return line;// nothing to do - - if (!result.at(0).isLetter()) - return line;// leave as-is if not a command - - // find first comment and eliminate - int pos = result.indexOf('('); - if (pos >= 0) - result = result.left(pos); - - int charsToRemove = result.length() - controlParams.grblLineBufferLen; - - if (charsToRemove > 0) - { - // ok need to do something with precision - // split apart based on letter - pos = 0; - components.clear(); - int i; - for (i = 1; i < result.length(); i++) - { - if (result.at(i).isLetter()) - { - components.append(result.mid(pos, i - pos)); - pos = i; - } - } - - if (pos == 0) - { - // we get here if only one command - components.append(result); - } - else - { - // add last item - components.append(result.mid(pos, i)); - } - - QList items; - foreach (QString tmp, components) - { - items.append(DecimalFilter(tmp)); - } - - int totalDecCount = 0; - int eligibleArgumentCount = 0; - int largestDecCount = 0; - for (int j = 0; j < items.size(); j++) - { - DecimalFilter& item = items[j]; - pos = item.token.indexOf('.'); - if ((item.token.at(1).isDigit() || item.token.at(1) == '-' || item.token.at(1) == '.') && pos >= 0) - { - // candidate to modify - // count number of decimal places - int decPlaceCount = 0; - for (i = pos + 1; i < item.token.length(); i++, decPlaceCount++) - { - if (!item.token.at(i).isDigit()) - break; - } - - // skip commands that have a single decimal place - if (decPlaceCount > 1) - { - item.decimals = decPlaceCount; - totalDecCount += decPlaceCount - 1;// leave at least the last decimal place - eligibleArgumentCount++; - if (decPlaceCount > largestDecCount) - largestDecCount = decPlaceCount; - } - } - } - - bool failRemoveSufficientDecimals = false; - if (totalDecCount < charsToRemove) - { - // remove as many as possible, then grbl will truncate - charsToRemove = totalDecCount; - failRemoveSufficientDecimals = true; - } - - if (eligibleArgumentCount > 0) - { - for (int k = largestDecCount; k > 1 && charsToRemove > 0; k--) - { - for (int j = 0; j < items.size() && charsToRemove > 0; j++) - { - DecimalFilter& item = items[j]; - if (item.decimals == k) - { - item.token.chop(1); - item.decimals--; - charsToRemove--; - } - } - } - - //chk.clear(); - //chk.append("CORRECTED:"); - result.clear(); - foreach (DecimalFilter item, items) - { - result.append(item.token); - - //chk.append("["); - //chk.append(item.token); - //chk.append("]"); - } - //diag(chk.toLocal8Bit().constData()); - - err("Unable to remove enough decimal places for command (will be truncated): %s", line.toLocal8Bit().constData()); - - QString msg; - if (failRemoveSufficientDecimals) - msg = QString("Error, insufficent reduction '%1'").arg(result); - else - msg = QString("Precision reduced '%1'").arg(result); - - emit addList(msg); - emit sendMsg(msg); - } - } - - return result; -} - -bool GCode::isGCommandValid(float value, bool& toEndOfLine) -{ - toEndOfLine = false; - // supported values obtained from https://github.com/grbl/grbl/wiki - const static float supported[] = - { - 0, 1, 2, 3, 4, - 10, 17, 18, 19, 20, 21, 28, 28.1, 30, 30.1, - 53, 54, 55, 56, 57, 58, 59, - 80, 90, 91, 92, 92.1, 93, 94 - }; - - int len = sizeof(supported) / sizeof(float); - for (int i = 0; i < len; i++) - { - if (value == supported[i]) - return true; - } - - if (value == 43 || value == 44) - { - toEndOfLine = true; - } - return false; -} - -bool GCode::isMCommandValid(float value) -{ - // supported values obtained from https://github.com/grbl/grbl/wiki - - // NOTE: M2 and M30 are supported but they cause occasional grbl lockups - // and thus have been removed from the supported list. No harm is caused - // by their removal. - const static float supported[] = - { - 0, 3, 4, 5, 8, 9 - }; - - int len = sizeof(supported) / sizeof(float); - for (int i = 0; i < len; i++) - { - if (value == supported[i]) - return true; - } - return false; -} - -QStringList GCode::doZRateLimit(QString inputLine, QString& msg, bool& xyRateSet) -{ - // i.e. - //G00 Z1 => G01 Z1 F100 - //G01 Z1 F260 => G01 Z1 F100 - //G01 Z1 F30 => G01 Z1 F30 - //G01 X1 Y1 Z1 F200 -> G01 X1 Y1 & G01 Z1 F100 - QStringList list; - QString line = inputLine.toUpper(); - - if (line.count("Z") > 0) - { - QStringList components = line.split(" ", QString::SkipEmptyParts); - QString s; - bool foundFeed = false; - bool didLimit = false; - - // We need to build one or two command strings depending on input. - QString x, y, g, f; - - // First get all component parts - bool inLimit = false; - foreach (s, components) - { - if (s.at(0) == 'G') - { - g = s; - } - else if (s.at(0) == 'F') - { - f = s; - - double value = s.mid(1,-1).toDouble(); - if (value > controlParams.zRateLimitAmount) - inLimit = true; - } - else if (s.at(0) == 'X') - { - x = s; - } - else if (s.at(0) == 'Y') - { - y = s; - } - } - - // Determine whether we want to have one or two command lins - // 1 string: Have !G0 and F but not in limit - // 1 string: Have Z only - // 2 strings: All other conditions - QString line1; - QString line2; - if ((g != "G0" && f.size() > 0 && !inLimit) - || (x.size() == 0 && y.size() == 0)) - { - foreach (s, components) - { - if (s.at(0) == 'G') - { - int value = s.mid(1,-1).toInt(); - if (value == 0) - line1.append("G1"); - else - line1.append(s); - } - else if (s.at(0) == 'F') - { - double value = s.mid(1,-1).toDouble(); - if (value > controlParams.zRateLimitAmount) - { - line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); - didLimit = true; - } - else - line1.append(s); - - foundFeed = true; - } - else - { - line1.append(s); - } - line1.append(" "); - } - } - else - { - // two lines - foreach (s, components) - { - if (s.at(0) == 'G') - { - int value = s.mid(1,-1).toInt(); - if (value != 1) - line1.append("G1").append(" "); - else - line1.append(s).append(" "); - - line2.append(s).append(" "); - } - else if (s.at(0) == 'F') - { - double value = s.mid(1,-1).toDouble(); - if (value > controlParams.zRateLimitAmount) - { - line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); - didLimit = true; - } - else - line1.append(s).append(" "); - - line2.append(s).append(" "); - - foundFeed = true; - } - else if (s.at(0) == 'Z') - { - line1.append(s).append(" "); - } - else - { - line2.append(s).append(" "); - } - } - } - - if (!foundFeed) - { - line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); - didLimit = true; - } - - line1 = line1.trimmed(); - line2 = line2.trimmed(); - - if (didLimit) - { - if (line2.size() == 0) - { - msg = QString("Z-Rate Limit: [%1]=>[%2]").arg(inputLine).arg(line1); - xyRateSet = true; - } - else - { - msg = QString("Z-Rate Limit: [%1]=>[%2,%3]").arg(inputLine).arg(line1).arg(line2); - line2.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); - } - } - - list.append(line1); - if (line2.size() > 0) - list.append(line2); - return list; - } - else if (xyRateSet) - { - QStringList components = line.split(" ", QString::SkipEmptyParts); - QString s; - - bool addRateG = false; - bool addRateXY = false; - bool gotF = false; - foreach (s, components) - { - if (s.at(0) == 'G') - { - int value = s.mid(1,-1).toInt(); - if (value != 0) - { - addRateG = true; - } - } - else if (s.at(0) == 'F') - { - gotF = true; - } - else if (s.at(0) == 'X' || s.at(0) == 'Y') - { - addRateXY = true; - } - } - - if (addRateG && addRateXY) - { - if (!gotF) - { - QString line = inputLine; - line.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); - msg = QString("XY-Rate Limit FIX: [%1]=>[%2]").arg(inputLine).arg(line); - list.append(line); - } - else - { - list.append(inputLine); - } - - xyRateSet = false; - - return list; - } - } - - list.append(inputLine); - return list; - -} - -void GCode::gotoXYZ(QString line) -{ - pollPosWaitForIdle(false); - - if (sendGcodeLocal(line)) - { - line = line.toUpper(); - - bool moveDetected = false; - - QStringList list = line.split(QRegExp("[\\s]+")); - for (int i = 0; i < list.size(); i++) - { - QString item = getMoveAmountFromString("X", list.at(i)); - if (item.length() > 0) - { - moveDetected = true; - } - item = getMoveAmountFromString("Y", list.at(i)); - if (item.length() > 0) - { - moveDetected = true; - } - item = getMoveAmountFromString("Z", list.at(i)); - if (item.length() > 0) - { - moveDetected = true; - } - } - - if (!moveDetected) - { - //emit addList("No movement expected for command."); - } - - pollPosWaitForIdle(false); - } - else - { - QString msg(QString("Bad command: %1").arg(line)); - warn("%s", msg.toLocal8Bit().constData()); - emit addList(msg); - } - - emit setCommandText(""); -} - - -QString GCode::getMoveAmountFromString(QString prefix, QString item) -{ - int index = item.indexOf(prefix); - if (index != -1) - { - return item.mid(index + 1); - } - return ""; -} - -void GCode::axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sZC) -{ - if (inv) - { - coord =- coord; - } - - QString cmd = QString("G01 ").append(axis) - .append(QString::number(coord)); - - if (axis == 'Z') - { - cmd.append(" F").append(QString::number(controlParams.zJogRate)); - } - - SendJog(cmd, absoluteAfterAxisAdj); - - if (axis == 'Z') - sliderZCount = sZC; - - emit adjustedAxis(); -} - -bool GCode::SendJog(QString cmd, bool absoluteAfterAxisAdj) -{ - pollPosWaitForIdle(false); - - // G91 = distance relative to previous - bool ret = sendGcodeLocal("G91\r"); - - bool result = ret && sendGcodeLocal(cmd.append("\r")); - - if (result) - { - pollPosWaitForIdle(false); - } - - if (absoluteAfterAxisAdj) - sendGcodeLocal("G90\r"); - - return result; -} - -// settings change calls here -void GCode::setResponseWait(ControlParams controlParamsIn) -{ - bool oldMm = controlParams.useMm; - - controlParams = controlParamsIn; - - controlParams.useMm = oldMm; - - if ((oldMm != controlParamsIn.useMm) && isPortOpen() && doubleDollarFormat) - { - if (controlParamsIn.useMm) - { - setConfigureMmMode(true); - } - else - { - setConfigureInchesMode(true); - } - } - - controlParams.useMm = controlParamsIn.useMm; - - setUnitsTypeDisplay(controlParams.useMm); -} - -int GCode::getSettingsItemCount() -{ - return settingsItemCount.get(); -} - -// 0.8c and above only! -void GCode::checkAndSetCorrectMeasurementUnits() -{ - sendGcodeLocal(REQUEST_PARSER_STATE_V08c, false); - - if (incorrectMeasurementUnits) - { - if (controlParams.useMm) - { - emit addList("Options specify use mm but Grbl parser set for inches. Fixing."); - setConfigureMmMode(true); - } - else - { - emit addList("Options specify use inches but Grbl parser set for mm. Fixing."); - setConfigureInchesMode(true); - } - incorrectMeasurementUnits = false;// hope this is ok to do here - sendGcodeLocal(REQUEST_CURRENT_POS); - } - else - { - sendGcodeLocal(SETTINGS_COMMAND_V08c); - - if (incorrectLcdDisplayUnits) - { - if (controlParams.useMm) - { - emit addList("Options specify use mm but Grbl reporting set for inches. Fixing."); - setConfigureMmMode(false); - } - else - { - emit addList("Options specify use inches but Grbl reporting set for mm. Fixing."); - setConfigureInchesMode(false); - } - } - incorrectLcdDisplayUnits = false; - } -} - -void GCode::setOldFormatMeasurementUnitControl() -{ - if (controlParams.useMm) - sendGcodeLocal("G21"); - else - sendGcodeLocal("G20"); -} - -void GCode::setConfigureMmMode(bool setGrblUnits) -{ - sendGcodeLocal("$13=0"); - if (setGrblUnits) - sendGcodeLocal("G21"); - sendGcodeLocal(REQUEST_CURRENT_POS); -} - -void GCode::setConfigureInchesMode(bool setGrblUnits) -{ - sendGcodeLocal("$13=1"); - if (setGrblUnits) - sendGcodeLocal("G20"); - sendGcodeLocal(REQUEST_CURRENT_POS); -} - -void GCode::setUnitsTypeDisplay(bool millimeters) -{ - if (millimeters) - { - emit setUnitsWork("(mm)"); - emit setUnitsMachine("(mm)"); - } - else - { - emit setUnitsWork("(in)"); - emit setUnitsMachine("(in)"); - } -} - -void GCode::clearToHome() -{ - maxZ = 0; - motionOccurred = false; -} +/**************************************************************** + * gcode.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "gcode.h" + +#include + +GCode::GCode() + : errorCount(0), doubleDollarFormat(false), + incorrectMeasurementUnits(false), incorrectLcdDisplayUnits(false), + maxZ(0), motionOccurred(false), + sliderZCount(0), + positionValid(false), + numaxis(DEFAULT_AXIS_COUNT) +{ + // use base class's timer - use it to capture random text from the controller + startTimer(1000); + // for position polling + pollPosTimer.start(); +} + +void GCode::openPort(QString commPortStr, QString baudRate) +{ + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + clearToHome(); + + currComPort = commPortStr; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if (port.OpenComport(commPortStr, baudRate)) + { + emit portIsOpen(true); + } + else + { + emit portIsClosed(false); + QString msg = tr("Can't open COM port ") + commPortStr; + sendMsg(msg); + addList(msg); + warn("%s", qPrintable(msg)); + + addList(tr("-Is hardware connected to USB?") ); + addList(tr("-Is correct port chosen?") ); + addList(tr("-Does current user have sufficient permissions?") ); +#if defined(Q_OS_LINUX) + addList("-Is current user in sudoers group?"); +#endif + //QMessageBox(QMessageBox::Critical,"Error","Could not open port.",QMessageBox::Ok).exec(); + } +} + +void GCode::closePort(bool reopen) +{ + port.CloseComport(); + emit portIsClosed(reopen); +} + +bool GCode::isPortOpen() +{ + return port.isPortOpen(); +} + +// Abort means stop file send after the end of this line +void GCode::setAbort() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + abortState.set(true); +} + +// Reset means immediately stop waiting for a response +void GCode::setReset() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + resetState.set(true); +} + +// Shutdown means app is shutting down - we give thread about .3 sec to exit what it is doing +void GCode::setShutdown() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + shutdownState.set(true); +} + +// Slot for interrupting current operation or doing a clean reset of grbl without changing position values +void GCode::sendGrblReset() +{ + clearToHome(); + + QString x(CTRL_X); + sendGcodeLocal(x, true, SHORT_WAIT_SEC); +} + +void GCode::sendGrblUnlock() +{ + sendGcodeLocal(SET_UNLOCK_STATE_V08c); +} + +// Slot for gcode-based 'zero out the current position values without motion' +void GCode::grblSetHome() +{ + clearToHome(); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G92 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G92 x0 y0 z0"); +} + +void GCode::goToHome() +{ + if (!motionOccurred) + return; + + double maxZOver = maxZ; + + if (doubleDollarFormat) + { + maxZOver += (controlParams.useMm ? PRE_HOME_Z_ADJ_MM : (PRE_HOME_Z_ADJ_MM / MM_IN_AN_INCH)); + } + else + { + // all reporting is in mm + maxZOver += PRE_HOME_Z_ADJ_MM; + } + + QString zpos = QString::number(maxZOver); + + gotoXYZFourth(QString("G0 z").append(zpos)); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G1 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G1 x0 y0 z0"); + + maxZ -= maxZOver; + + motionOccurred = false; +} + +// Slot called from other threads (i.e. main window, grbl dialog, etc.) +void GCode::sendGcode(QString line) +{ + bool checkMeasurementUnits = false; + + // empty line means we have just opened the com port + if (line.length() == 0) + { + resetState.set(false); + + QString result; + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, false)) + { + if (shutdownState.get() || resetState.get()) + return; + // it is possible that we are already connected and missed the + // signon banner. Force a reset (is this ok?) to get the banner + + emit addListOut("(CTRL-X)"); + + char buf[2] = {0}; + + buf[0] = CTRL_X; + + diag(qPrintable(tr("SENDING: 0x%02X (CTRL-X) to check presence of Grbl\n")), buf[0]) ; + if (!port.SendBuf(buf, 1)) + { + QString msg = tr("Sending to port failed"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return; + } + + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, true)) + return; + } + + checkMeasurementUnits = true; + } + else + { + pollPosWaitForIdle(false); + // normal send of actual commands + sendGcodeLocal(line, false); + } + + pollPosWaitForIdle(checkMeasurementUnits); +} + +// keep polling our position and state until we are done running +void GCode::pollPosWaitForIdle(bool checkMeasurementUnits) +{ + if (controlParams.usePositionRequest + && (controlParams.positionRequestType == PREQ_ALWAYS_NO_IDLE_CHK + || controlParams.positionRequestType == PREQ_ALWAYS + || checkMeasurementUnits)) + { + bool immediateQuit = false; + for (int i = 0; i < 10000; i++) + { + GCode::PosReqStatus ret = positionUpdate(); + if (ret == POS_REQ_RESULT_ERROR || ret == POS_REQ_RESULT_UNAVAILABLE) + { + immediateQuit = true; + break; + } + else if (ret == POS_REQ_RESULT_TIMER_SKIP) + { + SLEEP(250); + continue; + } + + if (doubleDollarFormat) + { + if (lastState.compare("Run") != 0) + break; + } + else + { + if (machineCoordLastIdlePos == machineCoord + && workCoordLastIdlePos == workCoord) + { + break; + } + + machineCoordLastIdlePos = machineCoord; + workCoordLastIdlePos = workCoord; + } + + if (shutdownState.get()) + return; + } + + if (immediateQuit) + return; + + if (checkMeasurementUnits) + { + if (doubleDollarFormat) + checkAndSetCorrectMeasurementUnits(); + else + setOldFormatMeasurementUnitControl(); + } + } + else + { + setLivenessState(false); + } +} + +// Slot called from other thread that returns whatever text comes back from the controller +void GCode::sendGcodeAndGetResult(int id, QString line) +{ + QString result; + + emit sendMsg(""); + resetState.set(false); + if (!sendGcodeInternal(line, result, false, SHORT_WAIT_SEC, false)) + result.clear(); + + emit gcodeResult(id, result); +} + +// To be called only from this class, not from other threads. Use above two methods for that. +// Wraps sendGcodeInternal() to allow proper handling of failure cases, etc. +bool GCode::sendGcodeLocal(QString line, bool recordResponseOnFail /* = false */, int waitSec /* = -1 */, bool aggressive /* = false */, int currLine /* = 0 */) +{ + QString result; + sendMsg(""); + resetState.set(false); + + bool ret = sendGcodeInternal(line, result, recordResponseOnFail, waitSec, aggressive, currLine); + if (shutdownState.get()) + return false; + + if (!ret && (!recordResponseOnFail || resetState.get())) + { + if (!resetState.get()) + emit stopSending(); + + if (!ret && resetState.get()) + { + resetState.set(false); + port.Reset(); + } + } + else + { + if (checkGrbl(result)) + { + emit enableGrblDialogButton(); + } + } + resetState.set(false); + return ret; +} + +bool GCode::checkGrbl(const QString& result) +{ + if (result.contains("Grbl")) + { + QRegExp rx("Grbl (\\d+)\\.(\\d+)(\\w*)"); + if (rx.indexIn(result) != -1 && rx.captureCount() > 0) + { + doubleDollarFormat = false; + + QStringList list = rx.capturedTexts(); + if (list.size() >= 3) + { + int majorVer = list.at(1).toInt(); + int minorVer = list.at(2).toInt(); + char letter = ' '; + if (list.size() == 4 && list.at(3).size() > 0) + { + letter = list.at(3).toLatin1().at(0); + } + + if (majorVer > 0 || (minorVer > 8 && minorVer < 51) || letter > 'a') + { + doubleDollarFormat = true; + } + + diag(qPrintable(tr("Got Grbl Version (Parsed:) %d.%d%c ($$=%d)\n")), + majorVer, minorVer, letter, doubleDollarFormat); + } + + if (!doubleDollarFormat) + setUnitsTypeDisplay(true); + } + return true; + } + return false; +} + +// Wrapped method. Should only be called from above method. +bool GCode::sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine /* = 0 */) +{ + if (!port.isPortOpen()) + { + QString msg = tr("Port not available yet") ; + err("%s", msg.toLocal8Bit().constData()); + emit addList(msg); + emit sendMsg(msg); + return false; + } + + bool ctrlX = line.size() > 0 ? (line.at(0).toLatin1() == CTRL_X) : false; + + bool sentReqForLocation = false; + bool sentReqForSettings = false; + bool sentReqForParserState = false; + + if (checkForGetPosStr(line)) + { + sentReqForLocation = true; + setLivenessState(true); + } + else if (!line.compare(REQUEST_PARSER_STATE_V08c)) + { + sentReqForParserState = true; + } + else if (!line.compare(SETTINGS_COMMAND_V08a)) + { + if (doubleDollarFormat) + line = SETTINGS_COMMAND_V08c; + + sentReqForSettings = true; + } + else + motionOccurred = true; + + // adds to UI list, but prepends a > indicating a sent command + if (ctrlX) + { + emit addListOut("(CTRL-X)"); + } + else if (!sentReqForLocation)// if requesting location, don't add that "noise" to the output view + { +/// T1 + fix bug + QString nline(line); + if (currLine && (line.at(0).toLatin1() != 'N') ) + nline = "L" + QString().setNum(currLine) + " " + line; + /// <-- + emit addListOut(nline); + } + + if (line.size() == 0 || (!line.endsWith('\r') && !ctrlX)) + line.append('\r'); + + char buf[BUF_SIZE + 1] = {0}; + if (line.length() >= BUF_SIZE) + { + QString msg = tr("Buffer size too small"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + for (int i = 0; i < line.length(); i++) + buf[i] = line.at(i).toLatin1(); + + if (ctrlX) + diag(qPrintable(tr("SENDING[%d]: 0x%02X (CTRL-X)\n")), currLine, buf[0]); + else + // diag(qPrintable(tr("SENDING[%d]: %s\n")), currLine, buf); + diag(qPrintable(tr("SENDING[%d]: ->%s<-\n")), currLine, buf); + + int waitSecActual = waitSec == -1 ? controlParams.waitTime : waitSec; + + if (aggressive) + { + if (ctrlX) + sendCount.append(CmdResponse("(CTRL-X)", line.length(), currLine)); + else + sendCount.append(CmdResponse(buf, line.length(), currLine)); + + //diag("DG Buffer Add %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + + waitForOk(result, waitSecActual, false, false, aggressive, false); + + if (shutdownState.get()) + return false; + } + + if (!port.SendBuf(buf, line.length())) + { + QString msg = tr("Sending to port failed") ; + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + else + { + sentI++; + if (!waitForOk(result, waitSecActual, sentReqForLocation, sentReqForParserState, aggressive, false)) + { + diag(qPrintable(tr("WAITFOROK FAILED\n"))); + if (shutdownState.get()) + return false; + + if (!recordResponseOnFail && !(resetState.get() || abortState.get())) + { + QString msg = tr("Wait for ok failed"); + emit addList(msg); + emit sendMsg(msg); + } + + return false; + } + else + { + if (sentReqForSettings) + { + QStringList list = result.split("$"); + for (int i = 0; i < list.size(); i++) + { + QString item = list.at(i); + const QRegExp rx(REGEXP_SETTINGS_LINE); + + if (rx.indexIn(item, 0) != -1 && rx.captureCount() == 3) + { + QStringList capList = rx.capturedTexts(); + if (!capList.at(1).compare("13")) + { + if (!capList.at(2).compare("0")) + { + if (!controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + else + { + if (controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + break; + } + } + } + + settingsItemCount.set(list.size()); + } + } + } + return true; +} + +bool GCode::waitForOk(QString& result, int waitSec, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize) +{ + int okcount = 0; + + if (aggressive) + { + //if (!port.bytesAvailable()) //more conservative code + if (!finalize || !port.bytesAvailable()) + { + int total = 0; + bool haveWait = false; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + if (cmdResp.waitForMe) + { + haveWait = true; + } + } + + //printf("Total out (a): %d (%d) (%d)\n", total, sendCount.size(), haveWait); + + if (!haveWait) + { + if (total < (GRBL_RX_BUFFER_SIZE - 1)) + { + return true; + } + } + } + } + + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!result.contains(RESPONSE_OK) && !result.contains(RESPONSE_ERROR) && !resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + if (aggressive && sendCount.size() == 0) + return false; + + count++; + SLEEP(100); + } + else if (n < 0) + { + QString Mes(tr("Error reading data from COM port\n")) ; + err(qPrintable(Mes)); + + if (aggressive && sendCount.size() == 0) + return false; + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + QString received(tmp); + + if (aggressive) + { + if (received.contains(RESPONSE_OK)) + { + if (sendCount.isEmpty()) { + err(qPrintable(tr("Unexpected: list is empty (o)!"))); + } + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + diag(qPrintable(tr("GOT[%d]:%s for %s\n")), cmdResp.line, tmpTrim.toLocal8Bit().constData(), cmdResp.cmd.toLocal8Bit().constData()); + + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + rcvdI++; + okcount++; + } + else if (received.contains(RESPONSE_ERROR)) + { + QString orig(tr("Error?")); + if (sendCount.isEmpty()) + err(qPrintable(tr("Unexpected: list is empty (e)!"))); + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + orig = cmdResp.cmd; + diag(qPrintable(tr("GOT[%d]:%s for %s\n")), cmdResp.line, tmpTrim.toLocal8Bit().constData(), orig.toLocal8Bit().constData()); + + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + errorCount++; + QString result; + QTextStream(&result) << received << " [for " << orig << "]"; + emit addList(result); + grblCmdErrors.append(result); + rcvdI++; + } + else + { + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + parseCoordinates(received, aggressive); + } + + int total = 0; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + } + + //printf("Total out (b): %d (%d)\n", total, sendCount.size()); + //printf("SENT:%d RCVD:%d\n", sentI, rcvdI); + + if (total >= (GRBL_RX_BUFFER_SIZE - 1)) + { + //diag("DG Loop again\n"); + result.clear(); + continue; + } + else if (port.bytesAvailable()) + { + // comment out this block for more conservative approach + if (!finalize && okcount > 0) + { + //diag("DG Leave early\n"); + return true; + } + + result.clear(); + continue; + } + else + { + return true; + } + } + else + { + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + } + + if (!received.contains(RESPONSE_OK) && !received.contains(RESPONSE_ERROR)) + { + if (sentReqForParserState) + { + const QRegExp rx("\\[([\\s\\w\\.\\d]+)\\]"); + + if (rx.indexIn(received, 0) != -1 && rx.captureCount() == 1) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 2) + { + QStringList items = list.at(1).split(" "); + if (items.contains("G20"))// inches + { + if (controlParams.useMm) + incorrectMeasurementUnits = true; + else + incorrectMeasurementUnits = false; + } + else if (items.contains("G21"))// millimeters + { + if (controlParams.useMm) + incorrectMeasurementUnits = false; + else + incorrectMeasurementUnits = true; + } + else + { + // not in list! + incorrectMeasurementUnits = true; + } + } + } + } + else + { + parseCoordinates(received, aggressive); + } + } + count = 0; + } + + SLEEP(100); + + if (count > waitCount) + { + // waited too long for a response, fail + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (!aggressive) + SLEEP(100); + + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !sentReqForLocation && !list.at(i).startsWith("MPos:[")) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +bool GCode::waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound) +{ + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + count++; + SLEEP(100); + } + else if (n < 0) + { + err(qPrintable(tr("Error reading data from COM port\n")) ); + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + + if (tmpTrim.length() > 0) + { + if (!checkGrbl(tmpTrim)) + { + if (failOnNoFound) + { + QString msg(tr("Expecting Grbl version string. Unable to parse response.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + status = false; + } + else + { + emit enableGrblDialogButton(); + } + break; + } + } + + SLEEP(100); + + if (count > waitCount) + { + if (failOnNoFound) + { + // waited too long for a response, fail + + QString msg(tr("No data from COM port after connect. Expecting Grbl version string.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user (startup)")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +/// LETARTARE T1 +/* +/// May 13, 2014 + 1- frame1 : < 8c (3 axes), 0.845 (4 axes) -> $$==0 + received == "MPos:[....],WPos:[....]" + 2- frame2 : 0.8c1 or 0.8c2 (4 axes) -> $$==1 + received == "" + 3- frame2 : 0.8c (3 axes) -> $$==1 + received == "" + 4- frame3 : 0.9d (3 axes), 0.9d1 (4 axes) -> $$==1 + received == "" +*/ + +void GCode::parseCoordinates(const QString& received, bool aggressive) +{ + if (aggressive) + { + int ms = parseCoordTimer.elapsed(); + if (ms < 500) + return; + + parseCoordTimer.restart(); + } + + bool good = false ; + int captureCount ; + QString state; + QString prepend; + QString append; + QString preamble = "([a-zA-Z]+),MPos:"; + if (!doubleDollarFormat) + { + prepend = "\\["; + append = "\\]"; + preamble = "MPos:" ; + } + QString coordRegExp; + QRegExp rxStateMPos; + QRegExp rxWPos; +/// 1 axis + QString format1("(-*\\d+\\.\\d+)") ; + QString sep(","); + /// 3 axes + QString format3 = format1 + sep + format1 + sep + format1 ; + /// 4 axes + QString format4 = format3 + sep + format1 ; + QString format ; + int naxis ; + for (naxis = MAX_AXIS_COUNT; naxis >= DEFAULT_AXIS_COUNT; naxis--) { + if (!doubleDollarFormat) + captureCount = naxis ; + else + captureCount = naxis + 1 ; + + if (naxis == MAX_AXIS_COUNT ) + format = format4; + else + format = format3; + + coordRegExp = prepend + format + append ; + rxStateMPos = QRegExp(preamble + coordRegExp); + rxWPos = QRegExp(QString("WPos:") + coordRegExp); + good = rxStateMPos.indexIn(received, 0) != -1 + && rxStateMPos.captureCount() == captureCount + && rxWPos.indexIn(received, 0) != -1 + && rxWPos.captureCount() == naxis + ; + + // find naxis ... + if (good) + break; + } + if (good) { /// naxis contains number axis + if (numaxis <= DEFAULT_AXIS_COUNT) + { + if (naxis > DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + else + { + if (naxis <= DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + + numaxis = naxis; + QStringList list = rxStateMPos.capturedTexts(); + int index = 1; + + if (doubleDollarFormat) + state = list.at(index++); + + machineCoord.x = list.at(index++).toFloat(); + machineCoord.y = list.at(index++).toFloat(); + machineCoord.z = list.at(index++).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + machineCoord.fourth = list.at(index++).toFloat(); + list = rxWPos.capturedTexts(); + workCoord.x = list.at(1).toFloat(); + workCoord.y = list.at(2).toFloat(); + workCoord.z = list.at(3).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + workCoord.fourth = list.at(4).toFloat(); + if (state != "Run") + workCoord.stoppedZ = true; + else + workCoord.stoppedZ = false; + + workCoord.sliderZIndex = sliderZCount; + + if (doubleDollarFormat) + diag(qPrintable(tr("Decoded: State:%s")), qPrintable(state) ); + if (numaxis == DEFAULT_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f WPos: %f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, + workCoord.x, workCoord.y, workCoord.z + ); + else if (numaxis == MAX_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, machineCoord.fourth, + workCoord.x, workCoord.y, workCoord.z, workCoord.fourth + ); + + if (workCoord.z > maxZ) + maxZ = workCoord.z; + + emit updateCoordinates(machineCoord, workCoord); + emit setLivePoint(workCoord.x, workCoord.y, controlParams.useMm, positionValid); + emit setLastState(state); + + lastState = state; + return; + } + // TODO fix to print + //if (!good /*&& received.indexOf("MPos:") != -1*/) + // err(qPrintable(tr("Error decoding position data! [%s]\n")), qPrintable(received)); + + lastState = ""; +} + +void GCode::sendStatusList(QStringList& listToSend) +{ + if (listToSend.size() > 1) + { + emit addListFull(listToSend); + } + else if (listToSend.size() == 1) + { + emit addList(listToSend.at(0)); + } +} + +// called once a second to capture any random strings that come from the controller +void GCode::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (port.isPortOpen()) + { + char tmp[BUF_SIZE + 1] = {0}; + QString result; + + for (int i = 0; i < 10 && !shutdownState.get() && !resetState.get(); i++) + { + int n = port.PollComport(tmp, BUF_SIZE); + if (n == 0) + break; + + tmp[n] = 0; + result.append(tmp); + diag(qPrintable(tr("GOT-TE:%s\n")), tmp); + } + + if (shutdownState.get()) + { + return; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && (list.at(i) != "ok" || (list.at(i) == "ok" && abortState.get()))) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + } +} + +void GCode::sendFile(QString path) +{ + addList(QString(tr("Sending file '%1'")).arg(path)); + + // send something to be sure the controller is ready + //sendGcodeLocal("", true, SHORT_WAIT_SEC); + + setProgress(0); + emit setQueuedCommands(0, false); + grblCmdErrors.clear(); + grblFilteredCmds.clear(); + errorCount = 0; + abortState.set(false); + QFile file(path); + if (file.open(QFile::ReadOnly)) + { +/// LETARTARE T1 + int totalLineCount = 0; + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLineCount++; + code.readLine(); + } + if (totalLineCount == 0) + totalLineCount = 1; + + code.seek(0); + + // set here once so that it doesn't change in the middle of a file send + bool aggressive = controlParams.useAggressivePreload; + if (aggressive) + { + sendCount.clear(); + //if (sendCount.size() == 0) + //{ + // diag("DG Buffer 0 at start\n")); + //} + + emit setQueuedCommands(sendCount.size(), true); + } + + sentI = 0; + rcvdI = 0; + emit resetTimer(true); + + parseCoordTimer.restart(); + + int currLine = 0; + bool xyRateSet = false; +/// LETARTARE T1 + QString strline ; + do + { + strline = code.readLine(); + + emit setVisCurrLine(currLine + 1); + + if (controlParams.filterFileCommands) + { + trimToEnd(strline, '('); + trimToEnd(strline, ';'); + trimToEnd(strline, '%'); + } + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + if (controlParams.filterFileCommands) + { + strline = strline.toUpper(); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline = removeUnsupportedCommands(strline); + } + + if (strline.size() != 0) + { + if (controlParams.reducePrecision) + { + strline = reducePrecision(strline); + } + + QString rateLimitMsg; + QStringList outputList; + if (controlParams.zRateLimit) + { + outputList = doZRateLimit(strline, rateLimitMsg, xyRateSet); + } + else + { + outputList.append(strline); + } + + bool ret = false; + if (outputList.size() == 1) + { + ret = sendGcodeLocal(outputList.at(0), false, -1, aggressive, currLine + 1); + } + else + { + foreach (QString outputLine, outputList) + { + ret = sendGcodeLocal(outputLine, false, -1, aggressive, currLine + 1); + + if (!ret) + break; + } + } + + if (rateLimitMsg.size() > 0) + addList(rateLimitMsg); + + if (!ret) + { + abortState.set(true); + break; + } + } + } + + float percentComplete = (currLine * 100.0) / totalLineCount; + setProgress((int)percentComplete); + + positionUpdate(); + currLine++; + } while ((code.atEnd() == false) && (!abortState.get())); + file.close(); + + if (aggressive) + { + int limitCount = 5000; + while (sendCount.size() > 0 && limitCount) + { + QString result; + waitForOk(result, controlParams.waitTime, false, false, aggressive, true); + SLEEP(100); + + if (shutdownState.get()) + return; + + if (abortState.get()) + break; + + limitCount--; + } + + if (!limitCount) + { + err(qPrintable(tr("Gave up waiting for OK\n"))); + } + } + + positionUpdate(); + + emit resetTimer(false); + + if (shutdownState.get()) + { + return; + } + + QString msg; + if (!abortState.get()) + { + setProgress(100); + if (errorCount > 0) + { + msg = QString(tr("Code sent successfully with %1 error(s):")).arg(QString::number(errorCount)); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblCmdErrors) + { + emit sendMsg(errItem); + } + emit addListFull(grblCmdErrors); + } + else + { + msg = tr("Code sent successfully with no errors."); + emit sendMsg(msg); + emit addList(msg); + } + + if (grblFilteredCmds.size() > 0) + { + msg = QString(tr("Filtered %1 commands:")).arg(QString::number(grblFilteredCmds.size())); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblFilteredCmds) + { + emit sendMsg(errItem); + } + emit addListFull(grblFilteredCmds); + } + } + else + { + msg = tr("Process interrupted."); + emit sendMsg(msg); + emit addList(msg); + } + } + + pollPosWaitForIdle(true); + + if (!resetState.get()) + { + emit stopSending(); + } + + emit setQueuedCommands(0, false); +} + +void GCode::trimToEnd(QString& strline, QChar ch) +{ + int pos = strline.indexOf(ch); + if (pos != -1) + strline = strline.left(pos); +} + +QString GCode::removeUnsupportedCommands(QString line) +{ + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString tmp; + QString s; + QString following; + bool toEndOfLine = false; + foreach (s, components) + { + if (toEndOfLine) + { + QString msg(QString(tr("Removed unsupported command '%1' part of '%2'")).arg(s).arg(following)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + continue; + } + + if (s.at(0) == 'G') + { + float value = s.mid(1,-1).toFloat(); + if (isGCommandValid(value, toEndOfLine)) + tmp.append(s).append(" "); + else + { + if (toEndOfLine) + following = s; + QString msg(QString(tr("Removed unsupported G command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'M') + { + float value = s.mid(1,-1).toFloat(); + if (isMCommandValid(value)) + tmp.append(s).append(" "); + else + { + QString msg(QString(tr("Removed unsupported M command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'N') + { + // skip line numbers + } + else if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'Z' + || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C' +/// LETARTARE + || s.at(0) == 'U' || s.at(0) == 'V' || s.at(0) == 'W' +/// <-- + || s.at(0) == 'I' || s.at(0) == 'J' || s.at(0) == 'K' + || s.at(0) == 'F' || s.at(0) == 'L' || s.at(0) == 'S') + { + tmp.append(s).append(" "); + } + else + { + QString msg(QString(tr("Removed unsupported command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + + return tmp.trimmed(); +} + +QString GCode::reducePrecision(QString line) +{ + // first remove all spaces to determine what are line length is + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString result; + foreach(QString token, components) + { + result.append(token); + } + + if (result.length() == 0) + return line;// nothing to do + + if (!result.at(0).isLetter()) + return line;// leave as-is if not a command + + // find first comment and eliminate + int pos = result.indexOf('('); + if (pos >= 0) + result = result.left(pos); + + int charsToRemove = result.length() - (controlParams.grblLineBufferLen - 1);// subtract 1 to account for linefeed sent with command later + + if (charsToRemove > 0) + { + // ok need to do something with precision + // split apart based on letter + pos = 0; + components.clear(); + int i; + for (i = 1; i < result.length(); i++) + { + if (result.at(i).isLetter()) + { + components.append(result.mid(pos, i - pos)); + pos = i; + } + } + + if (pos == 0) + { + // we get here if only one command + components.append(result); + } + else + { + // add last item + components.append(result.mid(pos, i)); + } + + QList items; + foreach (QString tmp, components) + { + items.append(DecimalFilter(tmp)); + } + + int totalDecCount = 0; + int eligibleArgumentCount = 0; + int largestDecCount = 0; + for (int j = 0; j < items.size(); j++) + { + DecimalFilter& item = items[j]; + pos = item.token.indexOf('.'); + if ((item.token.at(1).isDigit() || item.token.at(1) == '-' || item.token.at(1) == '.') && pos >= 0) + { + // candidate to modify + // count number of decimal places + int decPlaceCount = 0; + for (i = pos + 1; i < item.token.length(); i++, decPlaceCount++) + { + if (!item.token.at(i).isDigit()) + break; + } + + // skip commands that have a single decimal place + if (decPlaceCount > 1) + { + item.decimals = decPlaceCount; + totalDecCount += decPlaceCount - 1;// leave at least the last decimal place + eligibleArgumentCount++; + if (decPlaceCount > largestDecCount) + largestDecCount = decPlaceCount; + } + } + } + + bool failRemoveSufficientDecimals = false; + if (totalDecCount < charsToRemove) + { + // remove as many as possible, then grbl will truncate + charsToRemove = totalDecCount; + failRemoveSufficientDecimals = true; + } + + if (eligibleArgumentCount > 0) + { + for (int k = largestDecCount; k > 1 && charsToRemove > 0; k--) + { + for (int j = 0; j < items.size() && charsToRemove > 0; j++) + { + DecimalFilter& item = items[j]; + if (item.decimals == k) + { + item.token.chop(1); + item.decimals--; + charsToRemove--; + } + } + } + + //chk.clear(); + //chk.append("CORRECTED:"); + result.clear(); + foreach (DecimalFilter item, items) + { + result.append(item.token); + + //chk.append("["); + //chk.append(item.token); + //chk.append("]"); + } + //diag(chk.toLocal8Bit().constData()); + + err(qPrintable(tr("Unable to remove enough decimal places for command (will be truncated): %s")), line.toLocal8Bit().constData()); + + QString msg; + if (failRemoveSufficientDecimals) + msg = QString(tr("Error, insufficent reduction '%1'")).arg(result); + else + msg = QString(tr("Precision reduced '%1'")).arg(result); + + emit addList(msg); + emit sendMsg(msg); + } + } + + return result; +} + +bool GCode::isGCommandValid(float value, bool& toEndOfLine) +{ + toEndOfLine = false; + // supported values obtained from https://github.com/grbl/grbl/wiki + const static float supported[] = + { + 0, 1, 2, 3, 4, + 10, 17, 18, 19, 20, 21, 28, 28.1, 30, 30.1, + 53, 54, 55, 56, 57, 58, 59, + 80, 90, 91, 92, 92.1, 93, 94 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + + if (value == 43 || value == 44) + { + toEndOfLine = true; + } + return false; +} + +bool GCode::isMCommandValid(float value) +{ + // supported values obtained from https://github.com/grbl/grbl/wiki + + // NOTE: M2 and M30 are supported but they cause occasional grbl lockups + // and thus have been removed from the supported list. No harm is caused + // by their removal. + const static float supported[] = + { + 0, 3, 4, 5, 8, 9 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + return false; +} + +QStringList GCode::doZRateLimit(QString inputLine, QString& msg, bool& xyRateSet) +{ + // i.e. + //G00 Z1 => G01 Z1 F100 + //G01 Z1 F260 => G01 Z1 F100 + //G01 Z1 F30 => G01 Z1 F30 + //G01 X1 Y1 Z1 F200 -> G01 X1 Y1 & G01 Z1 F100 + QStringList list; + QString line = inputLine.toUpper(); + + if (line.count("Z") > 0) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + bool foundFeed = false; + bool didLimit = false; + + // We need to build one or two command strings depending on input. + QString x, y, g, f; + + // First get all component parts + bool inLimit = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + g = s; + } + else if (s.at(0) == 'F') + { + f = s; + + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + inLimit = true; + } + else if (s.at(0) == 'X') + { + x = s; + } + else if (s.at(0) == 'Y') + { + y = s; + } + } + + // Determine whether we want to have one or two command lins + // 1 string: Have !G0 and F but not in limit + // 1 string: Have Z only + // 2 strings: All other conditions + QString line1; + QString line2; + if ((g != "G0" && f.size() > 0 && !inLimit) + || (x.size() == 0 && y.size() == 0)) + { + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value == 0) + line1.append("G1"); + else + line1.append(s); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s); + + foundFeed = true; + } + else + { + line1.append(s); + } + line1.append(" "); + } + } + else + { + // two lines + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 1) + line1.append("G1").append(" "); + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + + foundFeed = true; + } + else if (s.at(0) == 'Z') + { + line1.append(s).append(" "); + } + else + { + line2.append(s).append(" "); + } + } + } + + if (!foundFeed) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + + line1 = line1.trimmed(); + line2 = line2.trimmed(); + + if (didLimit) + { + if (line2.size() == 0) + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2]")).arg(inputLine).arg(line1); + xyRateSet = true; + } + else + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2,%3]")).arg(inputLine).arg(line1).arg(line2); + line2.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + } + } + + list.append(line1); + if (line2.size() > 0) + list.append(line2); + return list; + } + else if (xyRateSet) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + + bool addRateG = false; + bool addRateXY = false; + bool gotF = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 0) + { + addRateG = true; + } + } + else if (s.at(0) == 'F') + { + gotF = true; + } + else + if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C') + { + addRateXY = true; + } + } + + if (addRateG && addRateXY) + { + if (!gotF) + { + QString line = inputLine; + line.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + msg = QString(tr("XY-Rate Limit FIX: [%1]=>[%2]")).arg(inputLine).arg(line); + list.append(line); + } + else + { + list.append(inputLine); + } + + xyRateSet = false; + + return list; + } + } + + list.append(inputLine); + return list; + +} + +void GCode::gotoXYZFourth(QString line) +{ + bool queryPos = checkForGetPosStr(line); + if (!queryPos && controlParams.usePositionRequest + && controlParams.positionRequestType == PREQ_ALWAYS) + pollPosWaitForIdle(false); + + if (sendGcodeLocal(line)) + { + line = line.toUpper(); + + bool moveDetected = false; + + QStringList list = line.split(QRegExp("[\\s]+")); + for (int i = 0; i < list.size(); i++) + { + QString item = getMoveAmountFromString("X", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Y", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Z", list.at(i)); + moveDetected = item.length() > 0 ; + if (numaxis == MAX_AXIS_COUNT) { + item = getMoveAmountFromString(QString(controlParams.fourthAxisType), list.at(i)); + moveDetected = item.length() > 0; + } + } + + if (!moveDetected) + { + //emit addList("No movement expected for command."); + } + + if (!queryPos) + pollPosWaitForIdle(false); + } + else + { + QString msg(QString(tr("Bad command: %1")).arg(line)); + warn("%s", qPrintable(msg)); + emit addList(msg); + } + + emit setCommandText(""); +} + + +QString GCode::getMoveAmountFromString(QString prefix, QString item) +{ + int index = item.indexOf(prefix); + if (index != -1) + return item.mid(index + 1); + + return ""; +} + +void GCode::axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sZC) +{ + if (inv) + { + coord = (-coord); + } + + QString cmd = QString("G01 ").append(axis) + .append(QString::number(coord)); + + if (axis == 'Z') + { + cmd.append(" F").append(QString::number(controlParams.zJogRate)); + } + + SendJog(cmd, absoluteAfterAxisAdj); + + if (axis == 'Z') + sliderZCount = sZC; + + emit adjustedAxis(); +} + +bool GCode::SendJog(QString cmd, bool absoluteAfterAxisAdj) +{ + pollPosWaitForIdle(false); + + // G91 = distance relative to previous + bool ret = sendGcodeLocal("G91\r"); + + bool result = ret && sendGcodeLocal(cmd.append("\r")); + + if (result) + { + pollPosWaitForIdle(false); + } + + if (absoluteAfterAxisAdj) + sendGcodeLocal("G90\r"); + + return result; +} + +// settings change calls here +void GCode::setResponseWait(ControlParams controlParamsIn) +{ + bool oldMm = controlParams.useMm; + + controlParams = controlParamsIn; + + controlParams.useMm = oldMm; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if ((oldMm != controlParamsIn.useMm) && isPortOpen() && doubleDollarFormat) + { + if (controlParamsIn.useMm) + { + setConfigureMmMode(true); + } + else + { + setConfigureInchesMode(true); + } + } + + controlParams.useMm = controlParamsIn.useMm; + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + setUnitsTypeDisplay(controlParams.useMm); +} + +int GCode::getSettingsItemCount() +{ + return settingsItemCount.get(); +} + +// 0.8c and above only! +void GCode::checkAndSetCorrectMeasurementUnits() +{ + sendGcodeLocal(REQUEST_PARSER_STATE_V08c, false); + + if (incorrectMeasurementUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl parser set for inches. Fixing.")); + setConfigureMmMode(true); + } + else + { + emit addList(tr("Options specify use inches but Grbl parser set for mm. Fixing.") ); + setConfigureInchesMode(true); + } + incorrectMeasurementUnits = false;// hope this is ok to do here + positionUpdate(true); + } + else + { + sendGcodeLocal(SETTINGS_COMMAND_V08c); + + if (incorrectLcdDisplayUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl reporting set for inches. Fixing.")); + setConfigureMmMode(false); + } + else + { + emit addList(tr("Options specify use inches but Grbl reporting set for mm. Fixing.")); + setConfigureInchesMode(false); + } + } + incorrectLcdDisplayUnits = false; + } +} + +void GCode::setOldFormatMeasurementUnitControl() +{ + if (controlParams.useMm) + sendGcodeLocal("G21"); + else + sendGcodeLocal("G20"); +} + +void GCode::setConfigureMmMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=0"); + if (setGrblUnits) + sendGcodeLocal("G21"); + positionUpdate(true); +} + +void GCode::setConfigureInchesMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=1"); + if (setGrblUnits) + sendGcodeLocal("G20"); + positionUpdate(true); +} + +void GCode::setUnitsTypeDisplay(bool millimeters) +{ + if (millimeters) + { + emit setUnitsWork(tr("(mm)")); + emit setUnitsMachine(tr("(mm)")); + } + else + { + emit setUnitsWork(tr("(in)")); + emit setUnitsMachine(tr("(in)")); + } +} + +void GCode::clearToHome() +{ + maxZ = 0; + motionOccurred = false; +} + +int GCode:: getNumaxis() +{ + return numaxis; +} + +GCode::PosReqStatus GCode::positionUpdate(bool forceIfEnabled /* = false */) +{ + if (controlParams.usePositionRequest) + { + if (forceIfEnabled) + { + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + int ms = pollPosTimer.elapsed(); + if (ms >= controlParams.postionRequestTimeMilliSec) + { + pollPosTimer.restart(); + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + return POS_REQ_RESULT_TIMER_SKIP; + } + } + } + return POS_REQ_RESULT_UNAVAILABLE; +} + +bool GCode::checkForGetPosStr(QString& line) +{ + return (!line.compare(REQUEST_CURRENT_POS) + || (line.startsWith(REQUEST_CURRENT_POS) && line.endsWith('\r') && line.length() == 2)); +} + +void GCode::setLivenessState(bool valid) +{ + positionValid = valid; + emit setVisualLivenessCurrPos(valid); + emit setLcdState(valid); +} diff --git a/gcode.h b/GC-3.6.1-T1/src/gcode.h similarity index 85% rename from gcode.h rename to GC-3.6.1-T1/src/gcode.h index 5f906d8..73e2008 100644 --- a/gcode.h +++ b/GC-3.6.1-T1/src/gcode.h @@ -31,6 +31,9 @@ #define CTRL_X '\x18' +#define DEFAULT_AXIS_COUNT 3 +#define MAX_AXIS_COUNT 4 + class CmdResponse { public: @@ -70,6 +73,7 @@ class GCode : public QObject void setReset(); void setShutdown(); int getSettingsItemCount(); + int getNumaxis(); static void trimToEnd(QString& strline, QChar); @@ -85,14 +89,17 @@ class GCode : public QObject void adjustedAxis(); void gcodeResult(int id, QString result); void setProgress(int); + void setQueuedCommands(int, bool); void resetTimer(bool timeIt); void enableGrblDialogButton(); void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); void setLastState(QString state); void setUnitsWork(QString value); void setUnitsMachine(QString value); - void setLivePoint(double x, double y, bool isMM); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); void setVisCurrLine(int currLine); + void setLcdState(bool valid); + void setVisualLivenessCurrPos(bool isLiveCP); public slots: void openPort(QString commPortStr, QString baudRate); @@ -100,7 +107,7 @@ public slots: void sendGcode(QString line); void sendGcodeAndGetResult(int id, QString line); void sendFile(QString path); - void gotoXYZ(QString line); + void gotoXYZFourth(QString line); void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); void setResponseWait(ControlParams controlParams); void grblSetHome(); @@ -111,9 +118,17 @@ public slots: protected: void timerEvent(QTimerEvent *event); +private: + enum PosReqStatus + { + POS_REQ_RESULT_OK, + POS_REQ_RESULT_ERROR, + POS_REQ_RESULT_TIMER_SKIP, + POS_REQ_RESULT_UNAVAILABLE + }; private: bool sendGcodeLocal(QString line, bool recordResponseOnFail = false, int waitSec = -1, bool aggressive = false, int currLine = 0); - bool waitForOk(QString& result, int waitCount, bool sentReqForLocation, bool sentReqForParserState, bool aggressive); + bool waitForOk(QString& result, int waitCount, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize); bool waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound); bool sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine = 0); QString removeUnsupportedCommands(QString line); @@ -134,6 +149,9 @@ public slots: void sendStatusList(QStringList& listToSend); void clearToHome(); bool checkGrbl(const QString& result); + PosReqStatus positionUpdate(bool forceIfEnabled = false); + bool checkForGetPosStr(QString& line); + void setLivenessState(bool valid); private: RS232 port; @@ -157,9 +175,12 @@ public slots: int sliderZCount; QStringList grblCmdErrors; QStringList grblFilteredCmds; + QTime pollPosTimer; + bool positionValid; int sentI; int rcvdI; + int numaxis; }; #endif // GCODE_H diff --git a/grbl.ico b/GC-3.6.1-T1/src/grbl.ico similarity index 100% rename from grbl.ico rename to GC-3.6.1-T1/src/grbl.ico diff --git a/grbl.rc b/GC-3.6.1-T1/src/grbl.rc similarity index 100% rename from grbl.rc rename to GC-3.6.1-T1/src/grbl.rc diff --git a/grbldialog.cpp b/GC-3.6.1-T1/src/grbldialog.cpp similarity index 97% rename from grbldialog.cpp rename to GC-3.6.1-T1/src/grbldialog.cpp index 8d2cfe2..da7a5c8 100644 --- a/grbldialog.cpp +++ b/GC-3.6.1-T1/src/grbldialog.cpp @@ -127,16 +127,16 @@ void GrblDialog::Cancel() this->close(); } -#pragma GCC diagnostic ignored "-Wunused-parameter" push void GrblDialog::changeValues(int row, int col) { + Q_UNUSED(col); + if ((ui->table->item(row,0)->text() != originalValues.at(row)) && ui->table->item(row,0)->text().length() > 0) { changeFlags.replace(row, true); } } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop void GrblDialog::Ok() { diff --git a/grbldialog.h b/GC-3.6.1-T1/src/grbldialog.h similarity index 100% rename from grbldialog.h rename to GC-3.6.1-T1/src/grbldialog.h diff --git a/GC-3.6.1-T1/src/grbldialog.ui b/GC-3.6.1-T1/src/grbldialog.ui new file mode 100644 index 0000000..a85b809 --- /dev/null +++ b/GC-3.6.1-T1/src/grbldialog.ui @@ -0,0 +1,96 @@ + + + GrblDialog + + + + 0 + 0 + 440 + 438 + + + + + 0 + 0 + + + + Grbl Settings + + + + + 50 + 390 + 75 + 31 + + + + Apply + + + + + + 280 + 390 + 75 + 31 + + + + Close + + + + + + 10 + 20 + 411 + 351 + + + + + 10 + 0 + + + + Qt::ImhNone + + + 30 + + + true + + + 2 + + + true + + + 40 + + + 40 + + + true + + + 30 + + + + + + + + diff --git a/images.rcc b/GC-3.6.1-T1/src/images.rcc similarity index 100% rename from images.rcc rename to GC-3.6.1-T1/src/images.rcc diff --git a/img/Thumbs.db b/GC-3.6.1-T1/src/img/Thumbs.db similarity index 100% rename from img/Thumbs.db rename to GC-3.6.1-T1/src/img/Thumbs.db diff --git a/img/down.PNG b/GC-3.6.1-T1/src/img/down.PNG similarity index 100% rename from img/down.PNG rename to GC-3.6.1-T1/src/img/down.PNG diff --git a/img/down.gif b/GC-3.6.1-T1/src/img/down.gif similarity index 100% rename from img/down.gif rename to GC-3.6.1-T1/src/img/down.gif diff --git a/img/left.PNG b/GC-3.6.1-T1/src/img/left.PNG similarity index 100% rename from img/left.PNG rename to GC-3.6.1-T1/src/img/left.PNG diff --git a/img/left.gif b/GC-3.6.1-T1/src/img/left.gif similarity index 100% rename from img/left.gif rename to GC-3.6.1-T1/src/img/left.gif diff --git a/img/logotiny.PNG b/GC-3.6.1-T1/src/img/logotiny.PNG similarity index 100% rename from img/logotiny.PNG rename to GC-3.6.1-T1/src/img/logotiny.PNG diff --git a/img/logotiny.gif b/GC-3.6.1-T1/src/img/logotiny.gif similarity index 100% rename from img/logotiny.gif rename to GC-3.6.1-T1/src/img/logotiny.gif diff --git a/img/right.PNG b/GC-3.6.1-T1/src/img/right.PNG similarity index 100% rename from img/right.PNG rename to GC-3.6.1-T1/src/img/right.PNG diff --git a/img/right.gif b/GC-3.6.1-T1/src/img/right.gif similarity index 100% rename from img/right.gif rename to GC-3.6.1-T1/src/img/right.gif diff --git a/img/up.PNG b/GC-3.6.1-T1/src/img/up.PNG similarity index 100% rename from img/up.PNG rename to GC-3.6.1-T1/src/img/up.PNG diff --git a/img/up.gif b/GC-3.6.1-T1/src/img/up.gif similarity index 100% rename from img/up.gif rename to GC-3.6.1-T1/src/img/up.gif diff --git a/img/zapmaker-logo-130.png b/GC-3.6.1-T1/src/img/zapmaker-logo-130.png similarity index 100% rename from img/zapmaker-logo-130.png rename to GC-3.6.1-T1/src/img/zapmaker-logo-130.png diff --git a/GC-3.6.1-T1/src/itemtobase.cpp b/GC-3.6.1-T1/src/itemtobase.cpp new file mode 100644 index 0000000..5a9c087 --- /dev/null +++ b/GC-3.6.1-T1/src/itemtobase.cpp @@ -0,0 +1,28 @@ +#include "itemtobase.h" + +ItemToBase::ItemToBase(int index1) + : scale(1), height(100), offsetx(50), offsety(50), index(index1) +{ +} + +ItemToBase::~ItemToBase() +{ +} + +void ItemToBase::setParams(double scale1, double height1, double offsetx1, double offsety1) +{ + scale = scale1; + height = height1; + offsetx = offsetx1; + offsety = offsety1; +} + +double ItemToBase::screenX(double fx) +{ + return (fx * scale) + offsetx; +} + +double ItemToBase::screenY(double fy) +{ + return height - ((fy * scale) + offsety); +} diff --git a/itemtobase.h b/GC-3.6.1-T1/src/itemtobase.h similarity index 96% rename from itemtobase.h rename to GC-3.6.1-T1/src/itemtobase.h index 9c5d2b9..2ad8f25 100644 --- a/itemtobase.h +++ b/GC-3.6.1-T1/src/itemtobase.h @@ -8,6 +8,7 @@ class ItemToBase { public: ItemToBase(int index); + virtual ~ItemToBase() ; virtual void moveToFirst(QPainterPath& path) = 0; virtual void addToPath(QPainterPath& path) = 0; diff --git a/lineitem.cpp b/GC-3.6.1-T1/src/lineitem.cpp similarity index 100% rename from lineitem.cpp rename to GC-3.6.1-T1/src/lineitem.cpp diff --git a/lineitem.h b/GC-3.6.1-T1/src/lineitem.h similarity index 100% rename from lineitem.h rename to GC-3.6.1-T1/src/lineitem.h diff --git a/log4qt/appender.h b/GC-3.6.1-T1/src/log4qt/appender.h similarity index 100% rename from log4qt/appender.h rename to GC-3.6.1-T1/src/log4qt/appender.h diff --git a/log4qt/appenderskeleton.cpp b/GC-3.6.1-T1/src/log4qt/appenderskeleton.cpp similarity index 100% rename from log4qt/appenderskeleton.cpp rename to GC-3.6.1-T1/src/log4qt/appenderskeleton.cpp diff --git a/log4qt/appenderskeleton.h b/GC-3.6.1-T1/src/log4qt/appenderskeleton.h similarity index 100% rename from log4qt/appenderskeleton.h rename to GC-3.6.1-T1/src/log4qt/appenderskeleton.h diff --git a/log4qt/basicconfigurator.cpp b/GC-3.6.1-T1/src/log4qt/basicconfigurator.cpp similarity index 100% rename from log4qt/basicconfigurator.cpp rename to GC-3.6.1-T1/src/log4qt/basicconfigurator.cpp diff --git a/log4qt/basicconfigurator.h b/GC-3.6.1-T1/src/log4qt/basicconfigurator.h similarity index 100% rename from log4qt/basicconfigurator.h rename to GC-3.6.1-T1/src/log4qt/basicconfigurator.h diff --git a/log4qt/consoleappender.cpp b/GC-3.6.1-T1/src/log4qt/consoleappender.cpp similarity index 100% rename from log4qt/consoleappender.cpp rename to GC-3.6.1-T1/src/log4qt/consoleappender.cpp diff --git a/log4qt/consoleappender.h b/GC-3.6.1-T1/src/log4qt/consoleappender.h similarity index 100% rename from log4qt/consoleappender.h rename to GC-3.6.1-T1/src/log4qt/consoleappender.h diff --git a/log4qt/dailyrollingfileappender.cpp b/GC-3.6.1-T1/src/log4qt/dailyrollingfileappender.cpp similarity index 100% rename from log4qt/dailyrollingfileappender.cpp rename to GC-3.6.1-T1/src/log4qt/dailyrollingfileappender.cpp diff --git a/log4qt/dailyrollingfileappender.h b/GC-3.6.1-T1/src/log4qt/dailyrollingfileappender.h similarity index 100% rename from log4qt/dailyrollingfileappender.h rename to GC-3.6.1-T1/src/log4qt/dailyrollingfileappender.h diff --git a/log4qt/fileappender.cpp b/GC-3.6.1-T1/src/log4qt/fileappender.cpp similarity index 100% rename from log4qt/fileappender.cpp rename to GC-3.6.1-T1/src/log4qt/fileappender.cpp diff --git a/log4qt/fileappender.h b/GC-3.6.1-T1/src/log4qt/fileappender.h similarity index 100% rename from log4qt/fileappender.h rename to GC-3.6.1-T1/src/log4qt/fileappender.h diff --git a/log4qt/helpers/classlogger.cpp b/GC-3.6.1-T1/src/log4qt/helpers/classlogger.cpp similarity index 100% rename from log4qt/helpers/classlogger.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/classlogger.cpp diff --git a/log4qt/helpers/classlogger.h b/GC-3.6.1-T1/src/log4qt/helpers/classlogger.h similarity index 100% rename from log4qt/helpers/classlogger.h rename to GC-3.6.1-T1/src/log4qt/helpers/classlogger.h diff --git a/log4qt/helpers/configuratorhelper.cpp b/GC-3.6.1-T1/src/log4qt/helpers/configuratorhelper.cpp similarity index 100% rename from log4qt/helpers/configuratorhelper.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/configuratorhelper.cpp diff --git a/log4qt/helpers/configuratorhelper.h b/GC-3.6.1-T1/src/log4qt/helpers/configuratorhelper.h similarity index 100% rename from log4qt/helpers/configuratorhelper.h rename to GC-3.6.1-T1/src/log4qt/helpers/configuratorhelper.h diff --git a/log4qt/helpers/datetime.cpp b/GC-3.6.1-T1/src/log4qt/helpers/datetime.cpp similarity index 99% rename from log4qt/helpers/datetime.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/datetime.cpp index 8430f3d..6da69a2 100644 --- a/log4qt/helpers/datetime.cpp +++ b/GC-3.6.1-T1/src/log4qt/helpers/datetime.cpp @@ -161,7 +161,7 @@ namespace Log4Qt const QChar c = rToken.at(0); QString result; - int used; + int used = 0; // Qt data format strings if (rToken.startsWith(QLatin1String("dddd"))) diff --git a/log4qt/helpers/datetime.h b/GC-3.6.1-T1/src/log4qt/helpers/datetime.h similarity index 100% rename from log4qt/helpers/datetime.h rename to GC-3.6.1-T1/src/log4qt/helpers/datetime.h diff --git a/log4qt/helpers/factory.cpp b/GC-3.6.1-T1/src/log4qt/helpers/factory.cpp similarity index 100% rename from log4qt/helpers/factory.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/factory.cpp diff --git a/log4qt/helpers/factory.h b/GC-3.6.1-T1/src/log4qt/helpers/factory.h similarity index 100% rename from log4qt/helpers/factory.h rename to GC-3.6.1-T1/src/log4qt/helpers/factory.h diff --git a/log4qt/helpers/initialisationhelper.cpp b/GC-3.6.1-T1/src/log4qt/helpers/initialisationhelper.cpp similarity index 100% rename from log4qt/helpers/initialisationhelper.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/initialisationhelper.cpp diff --git a/log4qt/helpers/initialisationhelper.h b/GC-3.6.1-T1/src/log4qt/helpers/initialisationhelper.h similarity index 100% rename from log4qt/helpers/initialisationhelper.h rename to GC-3.6.1-T1/src/log4qt/helpers/initialisationhelper.h diff --git a/log4qt/helpers/logerror.cpp b/GC-3.6.1-T1/src/log4qt/helpers/logerror.cpp similarity index 100% rename from log4qt/helpers/logerror.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/logerror.cpp diff --git a/log4qt/helpers/logerror.h b/GC-3.6.1-T1/src/log4qt/helpers/logerror.h similarity index 100% rename from log4qt/helpers/logerror.h rename to GC-3.6.1-T1/src/log4qt/helpers/logerror.h diff --git a/log4qt/helpers/logobject.cpp b/GC-3.6.1-T1/src/log4qt/helpers/logobject.cpp similarity index 100% rename from log4qt/helpers/logobject.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/logobject.cpp diff --git a/log4qt/helpers/logobject.h b/GC-3.6.1-T1/src/log4qt/helpers/logobject.h similarity index 100% rename from log4qt/helpers/logobject.h rename to GC-3.6.1-T1/src/log4qt/helpers/logobject.h diff --git a/log4qt/helpers/logobjectptr.cpp b/GC-3.6.1-T1/src/log4qt/helpers/logobjectptr.cpp similarity index 100% rename from log4qt/helpers/logobjectptr.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/logobjectptr.cpp diff --git a/log4qt/helpers/logobjectptr.h b/GC-3.6.1-T1/src/log4qt/helpers/logobjectptr.h similarity index 100% rename from log4qt/helpers/logobjectptr.h rename to GC-3.6.1-T1/src/log4qt/helpers/logobjectptr.h diff --git a/log4qt/helpers/optionconverter.cpp b/GC-3.6.1-T1/src/log4qt/helpers/optionconverter.cpp similarity index 100% rename from log4qt/helpers/optionconverter.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/optionconverter.cpp diff --git a/log4qt/helpers/optionconverter.h b/GC-3.6.1-T1/src/log4qt/helpers/optionconverter.h similarity index 100% rename from log4qt/helpers/optionconverter.h rename to GC-3.6.1-T1/src/log4qt/helpers/optionconverter.h diff --git a/log4qt/helpers/patternformatter.cpp b/GC-3.6.1-T1/src/log4qt/helpers/patternformatter.cpp similarity index 99% rename from log4qt/helpers/patternformatter.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/patternformatter.cpp index e313f0c..1fd54f0 100644 --- a/log4qt/helpers/patternformatter.cpp +++ b/GC-3.6.1-T1/src/log4qt/helpers/patternformatter.cpp @@ -455,8 +455,8 @@ namespace Log4Qt State state = LITERAL_STATE; FormattingInfo formatting_info; QString literal; - int converter_start; - int option_start; + int converter_start = 0; + int option_start = 0; while (i < mPattern.length()) { // i points to the current character diff --git a/log4qt/helpers/patternformatter.h b/GC-3.6.1-T1/src/log4qt/helpers/patternformatter.h similarity index 100% rename from log4qt/helpers/patternformatter.h rename to GC-3.6.1-T1/src/log4qt/helpers/patternformatter.h diff --git a/log4qt/helpers/properties.cpp b/GC-3.6.1-T1/src/log4qt/helpers/properties.cpp similarity index 99% rename from log4qt/helpers/properties.cpp rename to GC-3.6.1-T1/src/log4qt/helpers/properties.cpp index 96d04d7..ec74978 100644 --- a/log4qt/helpers/properties.cpp +++ b/GC-3.6.1-T1/src/log4qt/helpers/properties.cpp @@ -186,8 +186,8 @@ namespace Log4Qt QString key; QString value; QString *p_string = &key; - uint ucs; - int ucs_digits; + uint ucs = 0; + int ucs_digits = 0; while (i < rProperty.length()) { // i points to the current character. diff --git a/log4qt/helpers/properties.h b/GC-3.6.1-T1/src/log4qt/helpers/properties.h similarity index 100% rename from log4qt/helpers/properties.h rename to GC-3.6.1-T1/src/log4qt/helpers/properties.h diff --git a/log4qt/hierarchy.cpp b/GC-3.6.1-T1/src/log4qt/hierarchy.cpp similarity index 99% rename from log4qt/hierarchy.cpp rename to GC-3.6.1-T1/src/log4qt/hierarchy.cpp index 283c7fd..ef93d55 100644 --- a/log4qt/hierarchy.cpp +++ b/GC-3.6.1-T1/src/log4qt/hierarchy.cpp @@ -75,6 +75,7 @@ namespace Log4Qt mThreshold(Level::NULL_INT), mpRootLogger(logger(QString())) { + Q_UNUSED(mHandleQtMessages); // Store root logger to allow rootLogger() to be const } diff --git a/log4qt/hierarchy.h b/GC-3.6.1-T1/src/log4qt/hierarchy.h similarity index 100% rename from log4qt/hierarchy.h rename to GC-3.6.1-T1/src/log4qt/hierarchy.h diff --git a/log4qt/layout.cpp b/GC-3.6.1-T1/src/log4qt/layout.cpp similarity index 100% rename from log4qt/layout.cpp rename to GC-3.6.1-T1/src/log4qt/layout.cpp diff --git a/log4qt/layout.h b/GC-3.6.1-T1/src/log4qt/layout.h similarity index 100% rename from log4qt/layout.h rename to GC-3.6.1-T1/src/log4qt/layout.h diff --git a/log4qt/level.cpp b/GC-3.6.1-T1/src/log4qt/level.cpp similarity index 100% rename from log4qt/level.cpp rename to GC-3.6.1-T1/src/log4qt/level.cpp diff --git a/log4qt/level.h b/GC-3.6.1-T1/src/log4qt/level.h similarity index 100% rename from log4qt/level.h rename to GC-3.6.1-T1/src/log4qt/level.h diff --git a/log4qt/log4qt.cpp b/GC-3.6.1-T1/src/log4qt/log4qt.cpp similarity index 100% rename from log4qt/log4qt.cpp rename to GC-3.6.1-T1/src/log4qt/log4qt.cpp diff --git a/log4qt/log4qt.h b/GC-3.6.1-T1/src/log4qt/log4qt.h similarity index 100% rename from log4qt/log4qt.h rename to GC-3.6.1-T1/src/log4qt/log4qt.h diff --git a/log4qt/log4qt.pri b/GC-3.6.1-T1/src/log4qt/log4qt.pri similarity index 100% rename from log4qt/log4qt.pri rename to GC-3.6.1-T1/src/log4qt/log4qt.pri diff --git a/log4qt/logger.cpp b/GC-3.6.1-T1/src/log4qt/logger.cpp similarity index 100% rename from log4qt/logger.cpp rename to GC-3.6.1-T1/src/log4qt/logger.cpp diff --git a/log4qt/logger.h b/GC-3.6.1-T1/src/log4qt/logger.h similarity index 100% rename from log4qt/logger.h rename to GC-3.6.1-T1/src/log4qt/logger.h diff --git a/log4qt/loggerrepository.cpp b/GC-3.6.1-T1/src/log4qt/loggerrepository.cpp similarity index 100% rename from log4qt/loggerrepository.cpp rename to GC-3.6.1-T1/src/log4qt/loggerrepository.cpp diff --git a/log4qt/loggerrepository.h b/GC-3.6.1-T1/src/log4qt/loggerrepository.h similarity index 100% rename from log4qt/loggerrepository.h rename to GC-3.6.1-T1/src/log4qt/loggerrepository.h diff --git a/log4qt/loggingevent.cpp b/GC-3.6.1-T1/src/log4qt/loggingevent.cpp similarity index 100% rename from log4qt/loggingevent.cpp rename to GC-3.6.1-T1/src/log4qt/loggingevent.cpp diff --git a/log4qt/loggingevent.h b/GC-3.6.1-T1/src/log4qt/loggingevent.h similarity index 100% rename from log4qt/loggingevent.h rename to GC-3.6.1-T1/src/log4qt/loggingevent.h diff --git a/log4qt/logmanager.cpp b/GC-3.6.1-T1/src/log4qt/logmanager.cpp similarity index 93% rename from log4qt/logmanager.cpp rename to GC-3.6.1-T1/src/log4qt/logmanager.cpp index 875f68f..2c5e9ba 100644 --- a/log4qt/logmanager.cpp +++ b/GC-3.6.1-T1/src/log4qt/logmanager.cpp @@ -1,503 +1,504 @@ -/****************************************************************************** - * - * package: Log4Qt - * file: logmanager.cpp - * created: September 2007 - * author: Martin Heinrich - * - * - * changes: Sep 2008, Martin Heinrich: - * - Resolved compilation problem with Microsoft Visual Studio 2005 - * Feb 2009, Martin Heinrich - * - Fixed VS 2008 unreferenced formal parameter warning by using - * Q_UNUSED in operator<<. - * - * - * Copyright 2007 - 2009 Martin Heinrich - * - * 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. - * - ******************************************************************************/ - - - -/****************************************************************************** - * Dependencies - ******************************************************************************/ - - -#include "log4qt/logmanager.h" - -#include -#include -#include -#include -#include -#include -#include "log4qt/consoleappender.h" -#include "log4qt/helpers/datetime.h" -#include "log4qt/helpers/initialisationhelper.h" -#include "log4qt/helpers/optionconverter.h" -#include "log4qt/hierarchy.h" -#include "log4qt/propertyconfigurator.h" -#include "log4qt/ttcclayout.h" -#include "log4qt/varia/denyallfilter.h" -#include "log4qt/varia/levelrangefilter.h" - - -namespace Log4Qt -{ - - - /************************************************************************** - * Declarations - **************************************************************************/ - - - - /************************************************************************** - * C helper functions - **************************************************************************/ - - - LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) - LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) - - - - /************************************************************************** - * Class implementation: LogManager - **************************************************************************/ - - - LogManager::LogManager() : - mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() - mpLoggerRepository(new Hierarchy()), - mHandleQtMessages(false), - mOldQtMsgHandler(0) - { - } - - - LogManager::~LogManager() - { - static_logger()->warn("Unexpected destruction of LogManager"); - - // doSetConfigureHandleQtMessages(false); - // delete mpLoggerRepository; - } - - - Logger *LogManager::rootLogger() - { - return instance()->mpLoggerRepository->rootLogger(); - } - - - QList LogManager::loggers() - { - return instance()->mpLoggerRepository->loggers(); - } - - - Level LogManager::threshold() - { - return instance()->mpLoggerRepository->threshold(); - } - - - void LogManager::setThreshold(Level level) - { - instance()->mpLoggerRepository->setThreshold(level); - } - - - bool LogManager::exists(const char *pName) - { - return instance()->mpLoggerRepository->exists(QLatin1String(pName)); - } - - - LogManager *LogManager::instance() - { - // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive - // to construct, an exit handler must be set and doStartup must be - // called. - - if (!mspInstance) - { - QMutexLocker locker(singleton_guard()); - if (!mspInstance) - { - mspInstance = new LogManager; - // qAddPostRoutine(shutdown); - atexit(shutdown); - mspInstance->doConfigureLogLogger(); - mspInstance->welcome(); - mspInstance->doStartup(); - } - } - return mspInstance; - } - - - Logger *LogManager::logger(const QString &rName) - { - return instance()->mpLoggerRepository->logger(rName); - } - - - void LogManager::resetConfiguration() - { - setHandleQtMessages(false); - instance()->mpLoggerRepository->resetConfiguration(); - configureLogLogger(); - } - - - const char* LogManager::version() - { - return LOG4QT_VERSION_STR; - } - - - void LogManager::shutdown() - { - instance()->mpLoggerRepository->shutdown(); - } - - - void LogManager::doSetHandleQtMessages(bool handleQtMessages) - { - QMutexLocker locker(&mObjectGuard); - - if (instance()->mHandleQtMessages == handleQtMessages) - return; - - instance()->mHandleQtMessages = handleQtMessages; - if (instance()->mHandleQtMessages) - { - static_logger()->trace("Activate Qt message handling"); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); -#else - instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); -#endif - } - else - { - static_logger()->trace("Deactivate Qt message handling"); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - qInstallMsgHandler(instance()->mOldQtMsgHandler); -#else - qInstallMessageHandler(instance()->mOldQtMsgHandler); -#endif - } - } - - - void LogManager::doConfigureLogLogger() - { - QMutexLocker locker(&instance()->mObjectGuard); - - // Level - QString value = InitialisationHelper::setting(QLatin1String("Debug"), - QLatin1String("ERROR")); - logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); - - // Common layout - TTCCLayout *p_layout = new TTCCLayout(); - p_layout->setName(QLatin1String("LogLog TTCC")); - p_layout->setContextPrinting(false); - p_layout->activateOptions(); - - // Common deny all filter - Filter *p_denyall = new DenyAllFilter(); - p_denyall->activateOptions(); - - // ConsoleAppender on stdout for all events <= INFO - ConsoleAppender *p_appender; - LevelRangeFilter *p_filter; - p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); - p_filter = new LevelRangeFilter(); - p_filter->setNext(p_denyall); - p_filter->setLevelMin(Level::NULL_INT); - p_filter->setLevelMax(Level::INFO_INT); - p_filter->activateOptions(); - p_appender->setName(QLatin1String("LogLog stdout")); - p_appender->addFilter(p_filter); - p_appender->activateOptions(); - logLogger()->addAppender(p_appender); - - // ConsoleAppender on stderr for all events >= WARN - p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); - p_filter = new LevelRangeFilter(); - p_filter->setNext(p_denyall); - p_filter->setLevelMin(Level::WARN_INT); - p_filter->setLevelMax(Level::OFF_INT); - p_filter->activateOptions(); - p_appender->setName(QLatin1String("LogLog stderr")); - p_appender->addFilter(p_filter); - p_appender->activateOptions(); - logLogger()->addAppender(p_appender); - } - - - void LogManager::doStartup() - { - QMutexLocker locker(&instance()->mObjectGuard); - - // Override - QString default_value = QLatin1String("false"); - QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), - default_value); - if (value != default_value) - { - static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); - return; - } - - // Configuration using setting Configuration - value = InitialisationHelper::setting(QLatin1String("Configuration")); - if (QFile::exists(value)) - { - static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); - PropertyConfigurator::configure(value); - return; - } - - // Configuration using setting - if (QCoreApplication::instance()) - { - const QLatin1String log4qt_group("Log4Qt"); - const QLatin1String properties_group("Properties"); - QSettings s; - s.beginGroup(log4qt_group); - if (s.childGroups().contains(properties_group)) - { - const QString group(QLatin1String("Log4Qt/Properties")); - static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); - s.beginGroup(properties_group); - PropertyConfigurator::configure(s); - return; - } - } - - // Configuration using default file - const QString default_file(QLatin1String("log4qt.properties")); - if (QFile::exists(default_file)) - { - static_logger()->debug("Default initialisation configures from default file '%1'", default_file); - PropertyConfigurator::configure(default_file); - return; - } - - static_logger()->debug("Default initialisation leaves package unconfigured"); - } - - - void LogManager::welcome() - { - static_logger()->info("Initialising Log4Qt %1", - QLatin1String(LOG4QT_VERSION_STR)); - - // Debug: Info - if (static_logger()->isDebugEnabled()) - { - // Create a nice timestamp with UTC offset - DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); - QString offset; - { - QDateTime utc = start_time.toUTC(); - QDateTime local = start_time.toLocalTime(); - QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); - int min = utc.secsTo(local_as_utc) / 60; - if (min < 0) - offset += QLatin1Char('-'); - else - offset += QLatin1Char('+'); - min = abs(min); - offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); - offset += QLatin1Char(':'); - offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); - } - static_logger()->debug("Program startup time is %1 (UTC%2)", - start_time.toString(QLatin1String("ISO8601")), - offset); - static_logger()->debug("Internal logging uses the level %1", - logLogger()->level().toString()); - } - - // Trace: Dump settings - if (static_logger()->isTraceEnabled()) - { - static_logger()->trace("Settings from the system environment:"); - QString entry; - Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) - static_logger()->trace(" %1: '%2'", - entry, - InitialisationHelper::environmentSettings().value(entry)); - - static_logger()->trace("Settings from the application settings:"); - if (QCoreApplication::instance()) - { - const QLatin1String log4qt_group("Log4Qt"); - const QLatin1String properties_group("Properties"); - static_logger()->trace(" %1:", log4qt_group); - QSettings s; - s.beginGroup(log4qt_group); - Q_FOREACH (entry, s.childKeys()) - static_logger()->trace(" %1: '%2'", - entry, - s.value(entry).toString()); - static_logger()->trace(" %1/%2:", log4qt_group, properties_group); - s.beginGroup(properties_group); - Q_FOREACH (entry, s.childKeys()) - static_logger()->trace(" %1: '%2'", - entry, - s.value(entry).toString()); - } else - static_logger()->trace(" QCoreApplication::instance() is not available"); - } - } - -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) - { - Level level; - switch (type) - { - case QtDebugMsg: - level = Level::DEBUG_INT; - break; - case QtWarningMsg: - level = Level::WARN_INT; - break; - case QtCriticalMsg: - level = Level::ERROR_INT; - break; - case QtFatalMsg: - level = Level::FATAL_INT; - break; - default: - level = Level::TRACE_INT; - } - instance()->qtLogger()->log(level, pMessage); - - // Qt fatal behaviour copied from global.cpp qt_message_output() - // begin { - - if ((type == QtFatalMsg) || - ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) - { -#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) - // get the current report mode - int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); - _CrtSetReportMode(_CRT_ERROR, reportMode); - int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); - if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) - return; // ignore - else if (ret == 1) - _CrtDbgBreak(); -#endif - -#if defined(Q_OS_UNIX) && defined(QT_DEBUG) - abort(); // trap; generates core dump -#else - exit(1); // goodbye cruel world -#endif - } - - // } end - } -#else - void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) - { - Level level; - switch (type) - { - case QtDebugMsg: - level = Level::DEBUG_INT; - break; - case QtWarningMsg: - level = Level::WARN_INT; - break; - case QtCriticalMsg: - level = Level::ERROR_INT; - break; - case QtFatalMsg: - level = Level::FATAL_INT; - break; - default: - level = Level::TRACE_INT; - } - instance()->qtLogger()->log(level, message); - - // Qt fatal behaviour copied from global.cpp qt_message_output() - // begin { - - if ((type == QtFatalMsg) || - ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) - { -#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) - // get the current report mode - int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); - _CrtSetReportMode(_CRT_ERROR, reportMode); - int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, message.toUtf8().constData()); - if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) - return; // ignore - else if (ret == 1) - _CrtDbgBreak(); -#endif - -#if defined(Q_OS_UNIX) && defined(QT_DEBUG) - abort(); // trap; generates core dump -#else - exit(1); // goodbye cruel world -#endif - } - - // } end - } -#endif - - - - LogManager *LogManager::mspInstance = 0; - - - - /************************************************************************** - * Implementation: Operators, Helper - **************************************************************************/ - - -#ifndef QT_NO_DEBUG_STREAM - QDebug operator<<(QDebug debug, const LogManager &rLogManager) - { - Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 - QList loggers = rLogManager.loggers(); - debug.nospace() << "LogManager(" - << "loggerrepository:" << *rLogManager.loggerRepository() - << "log-level:" << rLogManager.logLogger()->level().toString() - << "log-appenders:" << rLogManager.logLogger()->appenders().count() - << "qt-level:" << rLogManager.qtLogger()->level().toString() - << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() - << "handleqtmessages:" << rLogManager.handleQtMessages() - << ")"; - return debug.space(); - } -#endif // QT_NO_DEBUG_STREAM - - -} // namespace Log4Qt +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logmanager.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/hierarchy.h" +#include "log4qt/propertyconfigurator.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelrangefilter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) + LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) + + + + /************************************************************************** + * Class implementation: LogManager + **************************************************************************/ + + + LogManager::LogManager() : + mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() + mpLoggerRepository(new Hierarchy()), + mHandleQtMessages(false), + mOldQtMsgHandler(0) + { + } + + + LogManager::~LogManager() + { + static_logger()->warn("Unexpected destruction of LogManager"); + + // doSetConfigureHandleQtMessages(false); + // delete mpLoggerRepository; + } + + + Logger *LogManager::rootLogger() + { + return instance()->mpLoggerRepository->rootLogger(); + } + + + QList LogManager::loggers() + { + return instance()->mpLoggerRepository->loggers(); + } + + + Level LogManager::threshold() + { + return instance()->mpLoggerRepository->threshold(); + } + + + void LogManager::setThreshold(Level level) + { + instance()->mpLoggerRepository->setThreshold(level); + } + + + bool LogManager::exists(const char *pName) + { + return instance()->mpLoggerRepository->exists(QLatin1String(pName)); + } + + + LogManager *LogManager::instance() + { + // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive + // to construct, an exit handler must be set and doStartup must be + // called. + + if (!mspInstance) + { + QMutexLocker locker(singleton_guard()); + if (!mspInstance) + { + mspInstance = new LogManager; + // qAddPostRoutine(shutdown); + atexit(shutdown); + mspInstance->doConfigureLogLogger(); + mspInstance->welcome(); + mspInstance->doStartup(); + } + } + return mspInstance; + } + + + Logger *LogManager::logger(const QString &rName) + { + return instance()->mpLoggerRepository->logger(rName); + } + + + void LogManager::resetConfiguration() + { + setHandleQtMessages(false); + instance()->mpLoggerRepository->resetConfiguration(); + configureLogLogger(); + } + + + const char* LogManager::version() + { + return LOG4QT_VERSION_STR; + } + + + void LogManager::shutdown() + { + instance()->mpLoggerRepository->shutdown(); + } + + + void LogManager::doSetHandleQtMessages(bool handleQtMessages) + { + QMutexLocker locker(&mObjectGuard); + + if (instance()->mHandleQtMessages == handleQtMessages) + return; + + instance()->mHandleQtMessages = handleQtMessages; + if (instance()->mHandleQtMessages) + { + static_logger()->trace("Activate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); +#else + instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); +#endif + } + else + { + static_logger()->trace("Deactivate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + qInstallMsgHandler(instance()->mOldQtMsgHandler); +#else + qInstallMessageHandler(instance()->mOldQtMsgHandler); +#endif + } + } + + + void LogManager::doConfigureLogLogger() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Level + QString value = InitialisationHelper::setting(QLatin1String("Debug"), + QLatin1String("ERROR")); + logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); + + // Common layout + TTCCLayout *p_layout = new TTCCLayout(); + p_layout->setName(QLatin1String("LogLog TTCC")); + p_layout->setContextPrinting(false); + p_layout->activateOptions(); + + // Common deny all filter + Filter *p_denyall = new DenyAllFilter(); + p_denyall->activateOptions(); + + // ConsoleAppender on stdout for all events <= INFO + ConsoleAppender *p_appender; + LevelRangeFilter *p_filter; + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::NULL_INT); + p_filter->setLevelMax(Level::INFO_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stdout")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + + // ConsoleAppender on stderr for all events >= WARN + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::WARN_INT); + p_filter->setLevelMax(Level::OFF_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stderr")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + } + + + void LogManager::doStartup() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Override + QString default_value = QLatin1String("false"); + QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), + default_value); + if (value != default_value) + { + static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); + return; + } + + // Configuration using setting Configuration + value = InitialisationHelper::setting(QLatin1String("Configuration")); + if (QFile::exists(value)) + { + static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); + PropertyConfigurator::configure(value); + return; + } + + // Configuration using setting + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + QSettings s; + s.beginGroup(log4qt_group); + if (s.childGroups().contains(properties_group)) + { + const QString group(QLatin1String("Log4Qt/Properties")); + static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); + s.beginGroup(properties_group); + PropertyConfigurator::configure(s); + return; + } + } + + // Configuration using default file + const QString default_file(QLatin1String("log4qt.properties")); + if (QFile::exists(default_file)) + { + static_logger()->debug("Default initialisation configures from default file '%1'", default_file); + PropertyConfigurator::configure(default_file); + return; + } + + static_logger()->debug("Default initialisation leaves package unconfigured"); + } + + + void LogManager::welcome() + { + static_logger()->info(qPrintable(QObject::tr("Initialising Log4Qt %1")), + QLatin1String(LOG4QT_VERSION_STR)); + + // Debug: Info + if (static_logger()->isDebugEnabled()) + { + // Create a nice timestamp with UTC offset + DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); + QString offset; + { + QDateTime utc = start_time.toUTC(); + QDateTime local = start_time.toLocalTime(); + QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); + int min = utc.secsTo(local_as_utc) / 60; + if (min < 0) + offset += QLatin1Char('-'); + else + offset += QLatin1Char('+'); + min = abs(min); + offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); + offset += QLatin1Char(':'); + offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); + } + static_logger()->debug("Program startup time is %1 (UTC%2)", + start_time.toString(QLatin1String("ISO8601")), + offset); + static_logger()->debug("Internal logging uses the level %1", + logLogger()->level().toString()); + } + + // Trace: Dump settings + if (static_logger()->isTraceEnabled()) + { + static_logger()->trace("Settings from the system environment:"); + QString entry; + Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) + static_logger()->trace(" %1: '%2'", + entry, + InitialisationHelper::environmentSettings().value(entry)); + + static_logger()->trace("Settings from the application settings:"); + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + static_logger()->trace(" %1:", log4qt_group); + QSettings s; + s.beginGroup(log4qt_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + static_logger()->trace(" %1/%2:", log4qt_group, properties_group); + s.beginGroup(properties_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + } else + static_logger()->trace(" QCoreApplication::instance() is not available"); + } + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) + { + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, pMessage); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#else + void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) + { + Q_UNUSED(context); + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, message); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, message.toUtf8().constData()); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#endif + + + + LogManager *LogManager::mspInstance = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const LogManager &rLogManager) + { + Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 + QList loggers = rLogManager.loggers(); + debug.nospace() << "LogManager(" + << "loggerrepository:" << *rLogManager.loggerRepository() + << "log-level:" << rLogManager.logLogger()->level().toString() + << "log-appenders:" << rLogManager.logLogger()->appenders().count() + << "qt-level:" << rLogManager.qtLogger()->level().toString() + << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() + << "handleqtmessages:" << rLogManager.handleQtMessages() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/log4qt/logmanager.h b/GC-3.6.1-T1/src/log4qt/logmanager.h similarity index 100% rename from log4qt/logmanager.h rename to GC-3.6.1-T1/src/log4qt/logmanager.h diff --git a/log4qt/mdc.cpp b/GC-3.6.1-T1/src/log4qt/mdc.cpp similarity index 100% rename from log4qt/mdc.cpp rename to GC-3.6.1-T1/src/log4qt/mdc.cpp diff --git a/log4qt/mdc.h b/GC-3.6.1-T1/src/log4qt/mdc.h similarity index 100% rename from log4qt/mdc.h rename to GC-3.6.1-T1/src/log4qt/mdc.h diff --git a/log4qt/ndc.cpp b/GC-3.6.1-T1/src/log4qt/ndc.cpp similarity index 100% rename from log4qt/ndc.cpp rename to GC-3.6.1-T1/src/log4qt/ndc.cpp diff --git a/log4qt/ndc.h b/GC-3.6.1-T1/src/log4qt/ndc.h similarity index 100% rename from log4qt/ndc.h rename to GC-3.6.1-T1/src/log4qt/ndc.h diff --git a/log4qt/patternlayout.cpp b/GC-3.6.1-T1/src/log4qt/patternlayout.cpp similarity index 100% rename from log4qt/patternlayout.cpp rename to GC-3.6.1-T1/src/log4qt/patternlayout.cpp diff --git a/log4qt/patternlayout.h b/GC-3.6.1-T1/src/log4qt/patternlayout.h similarity index 100% rename from log4qt/patternlayout.h rename to GC-3.6.1-T1/src/log4qt/patternlayout.h diff --git a/log4qt/propertyconfigurator.cpp b/GC-3.6.1-T1/src/log4qt/propertyconfigurator.cpp similarity index 96% rename from log4qt/propertyconfigurator.cpp rename to GC-3.6.1-T1/src/log4qt/propertyconfigurator.cpp index 19b7113..76f3ee0 100644 --- a/log4qt/propertyconfigurator.cpp +++ b/GC-3.6.1-T1/src/log4qt/propertyconfigurator.cpp @@ -5,26 +5,26 @@ * created: September 2007 * author: Martin Heinrich * - * + * * changes Feb 2009, Martin Heinrich - * - Fixed VS 2008 unreferenced formal parameter warning by using + * - Fixed VS 2008 unreferenced formal parameter warning by using * Q_UNUSED in operator<<. * * * Copyright 2007 - 2009 Martin Heinrich - * + * * 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. - * + * ******************************************************************************/ @@ -53,47 +53,47 @@ namespace Log4Qt { - - + + /************************************************************************** * Declarations **************************************************************************/ - - - + + + /************************************************************************** * C helper functions **************************************************************************/ - - + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator) - - - + + + /************************************************************************** * Class implementation: PropertyConfigurator **************************************************************************/ - - bool PropertyConfigurator::doConfigure(const Properties &rProperties, - LoggerRepository *pLoggerRepository) + + bool PropertyConfigurator::doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository) { startCaptureErrors(); configureFromProperties(rProperties, pLoggerRepository); return stopCaptureErrors(); } - - - bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, + + + bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, LoggerRepository *pLoggerRepository) { startCaptureErrors(); configureFromFile(rConfigFileName, pLoggerRepository); return stopCaptureErrors(); } - - - bool PropertyConfigurator::doConfigure(const QSettings &rSettings, + + + bool PropertyConfigurator::doConfigure(const QSettings &rSettings, LoggerRepository *pLoggerRepository) { startCaptureErrors(); @@ -101,28 +101,28 @@ namespace Log4Qt return stopCaptureErrors(); } - + bool PropertyConfigurator::configure(const Properties &rProperties) { PropertyConfigurator configurator; return configurator.doConfigure(rProperties); } - - + + bool PropertyConfigurator::configure(const QString &rConfigFilename) { PropertyConfigurator configurator; return configurator.doConfigure(rConfigFilename); } - - + + bool PropertyConfigurator::configure(const QSettings &rSettings) { PropertyConfigurator configurator; return configurator.doConfigure(rSettings); } - - + + bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName) { // Stop an existing watch to avoid a possible concurrent configuration @@ -135,8 +135,8 @@ namespace Log4Qt ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure); return result; } - - + + void PropertyConfigurator::configureFromFile(const QString &rConfigFileName, LoggerRepository *pLoggerRepository) { @@ -165,21 +165,21 @@ namespace Log4Qt } configureFromProperties(properties, pLoggerRepository); } - - - void PropertyConfigurator::configureFromProperties(const Properties &rProperties, + + + void PropertyConfigurator::configureFromProperties(const Properties &rProperties, LoggerRepository *pLoggerRepository) { if (!pLoggerRepository) pLoggerRepository = LogManager::loggerRepository(); - + configureGlobalSettings(rProperties, pLoggerRepository); configureRootLogger(rProperties, pLoggerRepository); configureNonRootElements(rProperties, pLoggerRepository); mAppenderRegistry.clear(); } - - + + void PropertyConfigurator::configureFromSettings(const QSettings &rSettings, LoggerRepository *pLoggerRepository) { @@ -188,7 +188,7 @@ namespace Log4Qt configureFromProperties(properties, pLoggerRepository); } - + void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties, LoggerRepository *pLoggerRepository) const { @@ -205,7 +205,7 @@ namespace Log4Qt // - Debug: log4j.Debug, log4j.configDebug // - Threshold: log4j.threshold // - Handle Qt Messages: log4j.handleQtMessages - + // Reset QString value = rProperties.property(key_reset); if (!value.isEmpty() && OptionConverter::toBoolean(value, false)) @@ -215,7 +215,7 @@ namespace Log4Qt LogManager::resetConfiguration(); logger()->debug("Reset configuration"); } - + // Debug value = rProperties.property(key_debug); if (value.isNull()) @@ -232,16 +232,16 @@ namespace Log4Qt if (!ok) level = Level::DEBUG_INT; LogManager::logLogger()->setLevel(level); - logger()->debug("Set level for Log4Qt logging to %1", + logger()->debug("Set level for Log4Qt logging to %1", LogManager::logLogger()->level().toString()); } - + // Threshold value = rProperties.property(key_threshold); if (!value.isNull()) { pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT)); - logger()->debug("Set threshold for LoggerRepository to %1", + logger()->debug("Set threshold for LoggerRepository to %1", pLoggerRepository->threshold().toString()); } @@ -250,17 +250,17 @@ namespace Log4Qt if (!value.isNull()) { LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false)); - logger()->debug("Set handling of Qt messages LoggerRepository to %1", + logger()->debug("Set handling of Qt messages LoggerRepository to %1", QVariant(LogManager::handleQtMessages()).toString()); } } - - void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, + + void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, LoggerRepository *pLoggerRepository) { Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null."); - + const QString logger_prefix = QLatin1String("log4j.logger."); const QString category_prefix = QLatin1String("log4j.category."); @@ -269,7 +269,7 @@ namespace Log4Qt // - Convert JAVA class names to C++ ones // - Parse logger data (Level, Appender) // - Parse logger additivity - + QStringList keys = rProperties.propertyNames(); QString key; Q_FOREACH(key, keys) @@ -290,18 +290,18 @@ namespace Log4Qt } } - - void PropertyConfigurator::configureRootLogger(const Properties &rProperties, + + void PropertyConfigurator::configureRootLogger(const Properties &rProperties, LoggerRepository *pLoggerRepository) { Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null."); - + const QLatin1String key_root_logger("log4j.rootLogger"); const QLatin1String key_root_category("log4j.rootCategory"); - + // - Test for the logger/category prefix // - Parse logger data for root logger - + QString key = key_root_logger; QString value = OptionConverter::findAndSubst(rProperties, key); if (value.isNull()) @@ -314,22 +314,22 @@ namespace Log4Qt if (value.isNull()) logger()->debug("Could not find root logger information. Is this correct?"); - else + else parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value); } - + void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties, - Logger *pLogger, + Logger *pLogger, const QString &rLog4jName) const { Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null."); const QLatin1String additivity_prefix("log4j.additivity."); - + // - Lookup additivity key for logger // - Set additivity, if specified - + QString key = additivity_prefix + rLog4jName; QString value = OptionConverter::findAndSubst(rProperties, key); logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value); @@ -340,7 +340,7 @@ namespace Log4Qt pLogger->setAdditivity(additivity); } } - + LogObjectPtr PropertyConfigurator::parseAppender(const Properties &rProperties, const QString &rName) @@ -352,9 +352,9 @@ namespace Log4Qt // - Set properties // - Activate options // - Add appender to registry - + const QLatin1String appender_prefix("log4j.appender."); - + logger()->debug("Parsing appender named '%1'", rName); if (mAppenderRegistry.contains(rName)) @@ -377,7 +377,7 @@ namespace Log4Qt LogObjectPtr p_appender = Factory::createAppender(value); if (!p_appender) { - LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' namd '%2'"), + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"), CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, "Log4Qt::PropertyConfigurator"); e << value << rName; @@ -385,7 +385,7 @@ namespace Log4Qt return 0; } p_appender->setName(rName); - + if (p_appender->requiresLayout()) { LogObjectPtr p_layout = parseLayout(rProperties, key); @@ -394,19 +394,19 @@ namespace Log4Qt else return 0; } - + QStringList exclusions; exclusions << QLatin1String("layout"); setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender); AppenderSkeleton *p_appenderskeleton = qobject_cast(p_appender); - if (p_appenderskeleton) + if (p_appenderskeleton) p_appenderskeleton->activateOptions(); - + mAppenderRegistry.insert(rName, p_appender); return p_appender; } - - + + LogObjectPtr PropertyConfigurator::parseLayout(const Properties &rProperties, const QString &rAppenderKey) { @@ -418,7 +418,7 @@ namespace Log4Qt // - Activate options const QLatin1String layout_suffix(".layout"); - + logger()->debug("Parsing layout for appender named '%1'", rAppenderKey); QString key = rAppenderKey + layout_suffix; @@ -435,32 +435,32 @@ namespace Log4Qt LogObjectPtr p_layout = Factory::createLayout(value); if (!p_layout) { - LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layoput of class '%1' requested by appender '%2'"), + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layout of class '%1' requested by appender '%2'"), CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, "Log4Qt::PropertyConfigurator"); e << value << rAppenderKey; logger()->error(e); return 0; } - + QStringList exclusions; setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout); p_layout->activateOptions(); - + return p_layout; } - - - void PropertyConfigurator::parseLogger(const Properties &rProperties, + + + void PropertyConfigurator::parseLogger(const Properties &rProperties, Logger *pLogger, const QString &rKey, const QString &rValue) { Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null."); Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty."); - + const QLatin1String keyword_inherited("INHERITED"); - + // - Split value on comma // - If level value, is specified // - Test for NULL and INHERITED @@ -468,12 +468,12 @@ namespace Log4Qt // - Set level // - For each entry // - Create Appender - + logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue); QStringList appenders = rValue.split(QLatin1Char(',')); QStringListIterator i (appenders); - - // First entry is the level. There will be always one entry, even if the rValue is + + // First entry is the level. There will be always one entry, even if the rValue is // empty or does not contain a comma. QString value = i.next().trimmed(); if (!value.isEmpty()) @@ -488,11 +488,11 @@ namespace Log4Qt else { pLogger->setLevel(level); - logger()->debug("Set level for logger '%1' to '%2'", + logger()->debug("Set level for logger '%1' to '%2'", pLogger->name(), pLogger->level().toString()); } } - + pLogger->removeAllAppenders(); while(i.hasNext()) { @@ -504,8 +504,8 @@ namespace Log4Qt pLogger->addAppender(p_appender); } } - - + + void PropertyConfigurator::setProperties(const Properties &rProperties, const QString &rPrefix, const QStringList &rExclusions, @@ -513,17 +513,17 @@ namespace Log4Qt { Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty."); Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null."); - + // Iterate through all entries: // - Test for prefix to determine, if setting is for object // - Skip empty property name // - Skip property names in exclusion list // - Set property on object - + logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'", QLatin1String(pObject->metaObject()->className()), rPrefix); - + QStringList keys = rProperties.propertyNames(); QString key; Q_FOREACH(key, keys) @@ -540,49 +540,49 @@ namespace Log4Qt Factory::setObjectProperty(pObject, property, value); } } - - + + void PropertyConfigurator::startCaptureErrors() { Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty."); - + mpConfigureErrors = new ListAppender; mpConfigureErrors->setName(QLatin1String("PropertyConfigurator")); mpConfigureErrors->setConfiguratorList(true); mpConfigureErrors->setThreshold(Level::ERROR_INT); LogManager::logLogger()->addAppender(mpConfigureErrors); } - - + + bool PropertyConfigurator::stopCaptureErrors() { Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty."); - + LogManager::logLogger()->removeAppender(mpConfigureErrors); ConfiguratorHelper::setConfigureError(mpConfigureErrors->list()); bool result = (mpConfigureErrors->list().count() == 0); mpConfigureErrors = 0; return result; } - - - + + + /************************************************************************** * Implementation: Operators, Helper **************************************************************************/ - - + + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const PropertyConfigurator &rPropertyConfigurator) { Q_UNUSED(rPropertyConfigurator); - debug.nospace() << "PropertyConfigurator(" + debug.nospace() << "PropertyConfigurator(" << ")"; - return debug.space(); + return debug.space(); } #endif - - - + + + } // namespace Logging diff --git a/log4qt/propertyconfigurator.h b/GC-3.6.1-T1/src/log4qt/propertyconfigurator.h similarity index 100% rename from log4qt/propertyconfigurator.h rename to GC-3.6.1-T1/src/log4qt/propertyconfigurator.h diff --git a/log4qt/rollingfileappender.cpp b/GC-3.6.1-T1/src/log4qt/rollingfileappender.cpp similarity index 98% rename from log4qt/rollingfileappender.cpp rename to GC-3.6.1-T1/src/log4qt/rollingfileappender.cpp index 44f7bbe..f9fac5f 100644 --- a/log4qt/rollingfileappender.cpp +++ b/GC-3.6.1-T1/src/log4qt/rollingfileappender.cpp @@ -104,6 +104,11 @@ namespace Log4Qt setMaximumFileSize(max_file_size); } + QString RollingFileAppender::maxFileSize() + { + return QString("%1").arg(maximumFileSize()); + } + void RollingFileAppender::append(const LoggingEvent &rEvent) { diff --git a/log4qt/rollingfileappender.h b/GC-3.6.1-T1/src/log4qt/rollingfileappender.h similarity index 98% rename from log4qt/rollingfileappender.h rename to GC-3.6.1-T1/src/log4qt/rollingfileappender.h index 0f07ad9..47848a4 100644 --- a/log4qt/rollingfileappender.h +++ b/GC-3.6.1-T1/src/log4qt/rollingfileappender.h @@ -76,7 +76,7 @@ namespace Log4Qt * * \sa setMaxFileSize(), maximumFileSize() */ - Q_PROPERTY(QString maxFileSize WRITE setMaxFileSize) + Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize) public: RollingFileAppender(QObject *pParent = 0); @@ -97,6 +97,7 @@ namespace Log4Qt qint64 maximumFileSize() const; void setMaxBackupIndex(int maxBackupIndex); void setMaximumFileSize(qint64 maximumFileSize); + QString maxFileSize(); void setMaxFileSize(const QString &rMaxFileSize); protected: diff --git a/log4qt/simplelayout.cpp b/GC-3.6.1-T1/src/log4qt/simplelayout.cpp similarity index 100% rename from log4qt/simplelayout.cpp rename to GC-3.6.1-T1/src/log4qt/simplelayout.cpp diff --git a/log4qt/simplelayout.h b/GC-3.6.1-T1/src/log4qt/simplelayout.h similarity index 100% rename from log4qt/simplelayout.h rename to GC-3.6.1-T1/src/log4qt/simplelayout.h diff --git a/log4qt/spi/filter.cpp b/GC-3.6.1-T1/src/log4qt/spi/filter.cpp similarity index 100% rename from log4qt/spi/filter.cpp rename to GC-3.6.1-T1/src/log4qt/spi/filter.cpp diff --git a/log4qt/spi/filter.h b/GC-3.6.1-T1/src/log4qt/spi/filter.h similarity index 100% rename from log4qt/spi/filter.h rename to GC-3.6.1-T1/src/log4qt/spi/filter.h diff --git a/log4qt/ttcclayout.cpp b/GC-3.6.1-T1/src/log4qt/ttcclayout.cpp similarity index 100% rename from log4qt/ttcclayout.cpp rename to GC-3.6.1-T1/src/log4qt/ttcclayout.cpp diff --git a/log4qt/ttcclayout.h b/GC-3.6.1-T1/src/log4qt/ttcclayout.h similarity index 100% rename from log4qt/ttcclayout.h rename to GC-3.6.1-T1/src/log4qt/ttcclayout.h diff --git a/log4qt/varia/debugappender.cpp b/GC-3.6.1-T1/src/log4qt/varia/debugappender.cpp similarity index 98% rename from log4qt/varia/debugappender.cpp rename to GC-3.6.1-T1/src/log4qt/varia/debugappender.cpp index bc0f547..fbaa351 100644 --- a/log4qt/varia/debugappender.cpp +++ b/GC-3.6.1-T1/src/log4qt/varia/debugappender.cpp @@ -89,7 +89,7 @@ namespace Log4Qt OutputDebugStringA(message.toLocal8Bit().data()); }); #else - fprintf(stderr, message.toLocal8Bit().data()); + fprintf(stderr, "%s", message.toLocal8Bit().data()); fflush(stderr); #endif } diff --git a/log4qt/varia/debugappender.h b/GC-3.6.1-T1/src/log4qt/varia/debugappender.h similarity index 100% rename from log4qt/varia/debugappender.h rename to GC-3.6.1-T1/src/log4qt/varia/debugappender.h diff --git a/log4qt/varia/denyallfilter.cpp b/GC-3.6.1-T1/src/log4qt/varia/denyallfilter.cpp similarity index 100% rename from log4qt/varia/denyallfilter.cpp rename to GC-3.6.1-T1/src/log4qt/varia/denyallfilter.cpp diff --git a/log4qt/varia/denyallfilter.h b/GC-3.6.1-T1/src/log4qt/varia/denyallfilter.h similarity index 100% rename from log4qt/varia/denyallfilter.h rename to GC-3.6.1-T1/src/log4qt/varia/denyallfilter.h diff --git a/log4qt/varia/levelmatchfilter.cpp b/GC-3.6.1-T1/src/log4qt/varia/levelmatchfilter.cpp similarity index 100% rename from log4qt/varia/levelmatchfilter.cpp rename to GC-3.6.1-T1/src/log4qt/varia/levelmatchfilter.cpp diff --git a/log4qt/varia/levelmatchfilter.h b/GC-3.6.1-T1/src/log4qt/varia/levelmatchfilter.h similarity index 100% rename from log4qt/varia/levelmatchfilter.h rename to GC-3.6.1-T1/src/log4qt/varia/levelmatchfilter.h diff --git a/log4qt/varia/levelrangefilter.cpp b/GC-3.6.1-T1/src/log4qt/varia/levelrangefilter.cpp similarity index 100% rename from log4qt/varia/levelrangefilter.cpp rename to GC-3.6.1-T1/src/log4qt/varia/levelrangefilter.cpp diff --git a/log4qt/varia/levelrangefilter.h b/GC-3.6.1-T1/src/log4qt/varia/levelrangefilter.h similarity index 100% rename from log4qt/varia/levelrangefilter.h rename to GC-3.6.1-T1/src/log4qt/varia/levelrangefilter.h diff --git a/log4qt/varia/listappender.cpp b/GC-3.6.1-T1/src/log4qt/varia/listappender.cpp similarity index 100% rename from log4qt/varia/listappender.cpp rename to GC-3.6.1-T1/src/log4qt/varia/listappender.cpp diff --git a/log4qt/varia/listappender.h b/GC-3.6.1-T1/src/log4qt/varia/listappender.h similarity index 100% rename from log4qt/varia/listappender.h rename to GC-3.6.1-T1/src/log4qt/varia/listappender.h diff --git a/log4qt/varia/nullappender.cpp b/GC-3.6.1-T1/src/log4qt/varia/nullappender.cpp similarity index 100% rename from log4qt/varia/nullappender.cpp rename to GC-3.6.1-T1/src/log4qt/varia/nullappender.cpp diff --git a/log4qt/varia/nullappender.h b/GC-3.6.1-T1/src/log4qt/varia/nullappender.h similarity index 100% rename from log4qt/varia/nullappender.h rename to GC-3.6.1-T1/src/log4qt/varia/nullappender.h diff --git a/log4qt/varia/stringmatchfilter.cpp b/GC-3.6.1-T1/src/log4qt/varia/stringmatchfilter.cpp similarity index 100% rename from log4qt/varia/stringmatchfilter.cpp rename to GC-3.6.1-T1/src/log4qt/varia/stringmatchfilter.cpp diff --git a/log4qt/varia/stringmatchfilter.h b/GC-3.6.1-T1/src/log4qt/varia/stringmatchfilter.h similarity index 100% rename from log4qt/varia/stringmatchfilter.h rename to GC-3.6.1-T1/src/log4qt/varia/stringmatchfilter.h diff --git a/log4qt/writerappender.cpp b/GC-3.6.1-T1/src/log4qt/writerappender.cpp similarity index 100% rename from log4qt/writerappender.cpp rename to GC-3.6.1-T1/src/log4qt/writerappender.cpp diff --git a/log4qt/writerappender.h b/GC-3.6.1-T1/src/log4qt/writerappender.h similarity index 100% rename from log4qt/writerappender.h rename to GC-3.6.1-T1/src/log4qt/writerappender.h diff --git a/log4qtdef.h b/GC-3.6.1-T1/src/log4qtdef.h similarity index 100% rename from log4qtdef.h rename to GC-3.6.1-T1/src/log4qtdef.h diff --git a/main.cpp b/GC-3.6.1-T1/src/main.cpp similarity index 85% rename from main.cpp rename to GC-3.6.1-T1/src/main.cpp index e5ee7f1..0be6143 100644 --- a/main.cpp +++ b/GC-3.6.1-T1/src/main.cpp @@ -13,7 +13,6 @@ #include #endif - enum GC_LOG_TYPES { LOG_DEBUG_TYPE = 1, @@ -62,9 +61,33 @@ int main(int argc, char *argv[]) //Log4Qt::Logger::rootLogger()->addAppender(p_fappender); QApplication a(argc, argv); + + QString locale = QLocale::system().name().section('_', 0, 0); + QString dir = QDir::currentPath() + "/trlocale"; + QString file = QString("GrblController_") + locale; + QTranslator translator; + bool r = translator.load(file, dir); + if (!r) + { + dir = QDir::currentPath() + "/../GrblHoming/trlocale"; + translator.load(file, dir); + } + a.installTranslator(&translator); + + QString xlatpath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + file = QString("qt_") + locale ; + QTranslator qtTranslator; + r = qtTranslator.load(file , xlatpath); + if (!r) + { + xlatpath = QDir::currentPath() + "/trlocale"; + qtTranslator.load(file, xlatpath); + } + a.installTranslator(&qtTranslator); + MainWindow w; w.show(); - + int result = a.exec(); if (pDebugLogFile != NULL) @@ -119,7 +142,6 @@ void info(const char *str, ...) va_end(args); } -#pragma GCC diagnostic ignored "-Wunused-parameter" push void diag(const char *str, ...) { #ifndef QT_DEBUG @@ -134,7 +156,6 @@ void diag(const char *str, ...) } #endif } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop void logit(GC_LOG_TYPES type, const char *str, va_list args) { diff --git a/mainwindow.cpp b/GC-3.6.1-T1/src/mainwindow.cpp similarity index 59% rename from mainwindow.cpp rename to GC-3.6.1-T1/src/mainwindow.cpp index 0ac044e..bb7dd8c 100644 --- a/mainwindow.cpp +++ b/GC-3.6.1-T1/src/mainwindow.cpp @@ -1,1169 +1,1594 @@ -/**************************************************************** - * mainwindow.cpp - * GrblHoming - zapmaker fork on github - * - * 15 Nov 2012 - * GPL License (see LICENSE file) - * Software is provided AS-IS - ****************************************************************/ - -#include "mainwindow.h" -#include "version.h" -#include "ui_mainwindow.h" - -extern Log4Qt::FileAppender *p_fappender; - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - absoluteAfterAxisAdj(false), - checkLogWrite(false), - sliderPressed(false), - sliderTo(0), - sliderZCount(0) -{ - // Setup our application information to be used by QSettings - QCoreApplication::setOrganizationName(COMPANY_NAME); - QCoreApplication::setOrganizationDomain(DOMAIN_NAME); - QCoreApplication::setApplicationName(APPLICATION_NAME); - - // required if passing the object by reference into signals/slots - qRegisterMetaType("Coord3D"); - qRegisterMetaType("PosItem"); - qRegisterMetaType("ControlParams"); - - - ui->setupUi(this); - - readSettings(); - - info("%s has started", GRBL_CONTROLLER_NAME_AND_VERSION); - - // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/ - // The thread points out that the documentation for QThread is wrong :) and - // you should NOT subclass from QThread and override run(), rather, - // attach your QOBJECT to a thread and use events (signals/slots) to communicate. - gcode.moveToThread(&gcodeThread); - timer.moveToThread(&timerThread); - - ui->lcdWorkNumberX->setDigitCount(8); - ui->lcdMachNumberX->setDigitCount(8); - ui->lcdWorkNumberY->setDigitCount(8); - ui->lcdMachNumberY->setDigitCount(8); - ui->lcdWorkNumberZ->setDigitCount(8); - ui->lcdMachNumberZ->setDigitCount(8); - - //buttons - connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort())); - connect(ui->btnGRBL,SIGNAL(clicked()),this,SLOT(setGRBL())); - connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX())); - connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY())); - connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ())); - connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX())); - connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY())); - connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ())); - connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome())); - connect(ui->Command,SIGNAL(editingFinished()),this,SLOT(gotoXYZ())); - connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin())); - connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile())); - connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop())); - connect(ui->SpindleOn,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle())); - connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute())); - connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions())); - connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close())); - connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout())); - connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset())); - connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock())); - connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe())); - connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int))); - connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed())); - connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased())); - - connect(this, SIGNAL(sendFile(QString)), &gcode, SLOT(sendFile(QString))); - connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString))); - connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool))); - connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString))); - connect(this, SIGNAL(gotoXYZ(QString)), &gcode, SLOT(gotoXYZ(QString))); - connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int))); - connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams))); - connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit())); - connect(this, SIGNAL(shutdown()), &timerThread, SLOT(quit())); - connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); - connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); - connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome())); - connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset())); - connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock())); - connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome())); - connect(this, SIGNAL(setItems(QList)), ui->wgtVisualizer, SLOT(setItems(QList))); - - connect(&gcode, SIGNAL(sendMsg(QString)),this,SLOT(receiveMsg(QString))); - connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool))); - connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool))); - connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString))); - connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList))); - connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString))); - connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending())); - connect(&gcode, SIGNAL(setCommandText(QString)), ui->Command, SLOT(setText(QString))); - connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); - connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis())); - connect(&gcode, SIGNAL(resetTimer(bool)), &timer, SLOT(resetTimer(bool))); - connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton())); - connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D))); - connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString))); - connect(&gcode, SIGNAL(setUnitsWork(QString)), ui->outputUnitsWork, SLOT(setText(QString))); - connect(&gcode, SIGNAL(setUnitsMachine(QString)), ui->outputUnitsMachine, SLOT(setText(QString))); - connect(&gcode, SIGNAL(setLivePoint(double, double, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool))); - connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int))); - - connect(&timer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); - - timerThread.start(); - gcodeThread.start(); - - ui->comboStep->addItem("0.01"); - ui->comboStep->addItem("0.1"); - ui->comboStep->addItem("1"); - ui->comboStep->addItem("10"); - ui->comboStep->setCurrentIndex(2); - - ui->statusList->setUniformItemSizes(true); - // Does not work correctly for horizontal scrollbar: - //MyItemDelegate *scrollDelegate = new MyItemDelegate(ui->statusList); - //scrollDelegate->setWidth(600); - //ui->statusList->setItemDelegate(scrollDelegate); - - scrollStatusTimer.start(); - - // Cool utility class off Google code that enumerates COM ports in platform-independent manner - QList ports = QextSerialEnumerator::getPorts(); - - int portIndex = -1; - for (int i = 0; i < ports.size(); i++) - { - ui->cmbPort->addItem(ports.at(i).portName.toLocal8Bit().constData()); - - if (ports.at(i).portName == lastOpenPort) - portIndex = i; - - //diag("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData()); - //diag("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData()); - //diag("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData()); - //diag("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData()); - //diag("===================================\n\n"); - } - - if (portIndex >= 0) - { - // found matching port - ui->cmbPort->setCurrentIndex(portIndex); - } - else if (lastOpenPort.size() > 0) - { - // did not find matching port - // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator - ui->cmbPort->addItem(lastOpenPort.toLocal8Bit().constData()); - if (ports.size() > 0) - ui->cmbPort->setCurrentIndex(ports.size()); - else - ui->cmbPort->setCurrentIndex(0); - } - - int baudRates[] = { 9600, 19200, 38400, 57600, 115200 }; - int baudRateCount = sizeof baudRates / sizeof baudRates[0]; - int baudRateIndex = 0; - for (int i = 0; i < baudRateCount; i++) - { - QString baudRate = QString::number(baudRates[i]); - ui->comboBoxBaudRate->addItem(baudRate); - if (baudRate == lastBaudRate) - { - baudRateIndex = i; - } - } - - ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex); - - ui->tabAxisVisualizer->setEnabled(false); - ui->groupBoxSendFile->setEnabled(true); - ui->groupBoxManualGCode->setEnabled(false); - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - ui->btnGRBL->setEnabled(false); - ui->btnSetHome->setEnabled(false); - ui->btnResetGrbl->setEnabled(false); - ui->btnUnlockGrbl->setEnabled(false); - ui->btnGoHomeSafe->setEnabled(false); - styleSheet = ui->btnOpenPort->styleSheet(); - ui->statusList->setEnabled(true); - ui->openFile->setEnabled(true); - - this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION); - - QSettings settings; - QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); - controlParams.useAggressivePreload = useAggrPreload == "true"; - - if (!controlParams.useAggressivePreload && !promptedAggrPreload) - { - QMessageBox msgBox; - msgBox.setText("You appear to have upgraded to the latest version of Grbl Controller. " - "Please be aware that as of version 3.4 the default behavior of sending commands " - "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n" - "Your settings have been changed to enable this mode. Why? Because it provides the most " - "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n" - "What does this mean to you? " - "Arc commands will now run smoother and faster than before, which may " - "cause your spindle to work slightly harder, so please run some tests first. " - "Alternately, go to the Options dialog and manually disable Aggressive Preload"); - msgBox.exec(); - - controlParams.useAggressivePreload = true; - settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload); - } - - promptedAggrPreload = true; - - emit setResponseWait(controlParams); -} - -MainWindow::~MainWindow() -{ - delete ui; -} - -// called when user has clicked the close application button -void MainWindow::closeEvent(QCloseEvent *event) -{ - gcode.setShutdown(); - gcode.setAbort(); - gcode.setReset(); - - writeSettings(); - - info("%s has stopped", GRBL_CONTROLLER_NAME_AND_VERSION); - - SLEEP(300); - - emit shutdown(); - - event->accept(); -} - -void MainWindow::begin() -{ - //receiveList("Starting File Send."); - resetProgress(); - - ui->tabAxisVisualizer->setEnabled(false); - ui->groupBoxManualGCode->setEnabled(false); - - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(true); - ui->progressFileSend->setEnabled(true); - ui->outputRuntime->setEnabled(true); - ui->labelRuntime->setEnabled(true); - ui->openFile->setEnabled(false); - ui->btnGRBL->setEnabled(false); - ui->btnUnlockGrbl->setEnabled(false); - ui->btnSetHome->setEnabled(false); - ui->btnGoHomeSafe->setEnabled(false); - emit sendFile(ui->filePath->text()); -} - -void MainWindow::stop() -{ - gcode.setAbort(); - - // Reenable a bunch of UI - ui->Begin->setEnabled(true); - ui->Stop->setEnabled(false); - ui->btnGRBL->setEnabled(true); - ui->btnSetHome->setEnabled(true); - ui->btnResetGrbl->setEnabled(true); - ui->btnUnlockGrbl->setEnabled(true); - ui->btnGoHomeSafe->setEnabled(true); -} - -void MainWindow::grblReset() -{ - gcode.setAbort(); - gcode.setReset(); - emit sendGrblReset(); -} - -void MainWindow::grblUnlock() -{ - emit sendGrblUnlock(); -} - -void MainWindow::goHomeSafe() -{ - emit goToHome(); -} - -// slot called from GCode class to update our state -void MainWindow::stopSending() -{ - ui->tabAxisVisualizer->setEnabled(true); - ui->groupBoxManualGCode->setEnabled(true); - ui->Begin->setEnabled(true); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - ui->btnOpenPort->setEnabled(true); - ui->btnGRBL->setEnabled(true); - ui->btnSetHome->setEnabled(true); - ui->btnResetGrbl->setEnabled(true); - ui->btnUnlockGrbl->setEnabled(true); - ui->btnGoHomeSafe->setEnabled(true); - ui->openFile->setEnabled(true); -} - -// User has asked to open the port -void MainWindow::openPort() -{ - info("User clicked Port Open/Close"); - - openPortCtl(false); -} - -// User has asked to set current position as 'home' = 0,0,0 -void MainWindow::setHome() -{ - resetProgress(); - sendSetHome(); -} - -void MainWindow::resetProgress() -{ - setProgress(0); - setRuntime(""); -} - -// If the port isn't open, we ask to open it -// If the port is open, we close it, but if 'reopen' is -// true, we call back to this thread to reopen it which -// is done mainly to toggle the COM port state to reset -// the controller. -void MainWindow::openPortCtl(bool reopen) -{ - if (ui->btnOpenPort->text() == OPEN_BUTTON_TEXT) - { - // Port is closed if the button says 'Open' - QString portStr = ui->cmbPort->currentText(); - QString baudRate = ui->comboBoxBaudRate->currentText(); - - ui->btnOpenPort->setEnabled(false); - ui->comboBoxBaudRate->setEnabled(false); - emit openPort(portStr, baudRate); - } - else - { - if (!reopen) - resetProgress(); - - // presume button says 'Close' currently, meaning port is open - - // Tell gcode port thread to stop what it is doing immediately (within 0.1 sec) - gcode.setAbort(); - gcode.setReset(); - - // Disable a bunch of UI - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - ui->btnOpenPort->setEnabled(false); - ui->openFile->setEnabled(false); - - ui->tabAxisVisualizer->setEnabled(false); - ui->groupBoxSendFile->setEnabled(false); - ui->groupBoxManualGCode->setEnabled(false); - ui->cmbPort->setEnabled(false); - ui->comboBoxBaudRate->setEnabled(false); - ui->btnOpenPort->setEnabled(false); - ui->btnGRBL->setEnabled(false); - - // Send event to close the port - emit closePort(reopen); - } -} - -// slot telling us that port was closed successfully -// if 'reopen' is true, reopen our port to toggle -// so we reset the controller -void MainWindow::portIsClosed(bool reopen) -{ - SLEEP(100); - - ui->tabAxisVisualizer->setEnabled(false); - ui->groupBoxSendFile->setEnabled(false); - ui->groupBoxManualGCode->setEnabled(false); - ui->cmbPort->setEnabled(true); - ui->comboBoxBaudRate->setEnabled(true); - ui->btnOpenPort->setEnabled(true); - ui->btnOpenPort->setText(OPEN_BUTTON_TEXT); - ui->btnOpenPort->setStyleSheet(styleSheet); - ui->btnGRBL->setEnabled(false); - ui->btnSetHome->setEnabled(false); - ui->btnResetGrbl->setEnabled(false); - ui->btnUnlockGrbl->setEnabled(false); - ui->btnGoHomeSafe->setEnabled(false); - - if (reopen) - { - receiveList("Resetting port to restart controller"); - openPortCtl(false); - } -} - -// slot that tells us the gcode thread successfully opened the port -void MainWindow::portIsOpen(bool sendCode) -{ - // Comm port successfully opened - if (sendCode) - sendGcode(""); -} - -void MainWindow::adjustedAxis() -{ - ui->tabAxisVisualizer->setEnabled(true); - ui->groupBoxManualGCode->setEnabled(true); - - if (ui->filePath->text().length() > 0) - ui->Begin->setEnabled(true); - - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - - ui->btnOpenPort->setEnabled(true); - ui->openFile->setEnabled(true); - ui->btnGRBL->setEnabled(true); - ui->btnSetHome->setEnabled(true); - ui->btnResetGrbl->setEnabled(true); - ui->btnUnlockGrbl->setEnabled(true); - ui->btnGoHomeSafe->setEnabled(true); -} - -void MainWindow::disableAllButtons() -{ - //ui->tabAxisVisualizer->setEnabled(false); - ui->groupBoxManualGCode->setEnabled(false); - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - ui->openFile->setEnabled(false); - ui->btnGRBL->setEnabled(false); - ui->btnSetHome->setEnabled(false); - ui->btnResetGrbl->setEnabled(false); - ui->btnUnlockGrbl->setEnabled(false); - ui->btnGoHomeSafe->setEnabled(false); -} - -void MainWindow::enableGrblDialogButton() -{ - ui->openFile->setEnabled(true); - ui->btnOpenPort->setEnabled(true); - ui->btnOpenPort->setText(CLOSE_BUTTON_TEXT); - ui->btnOpenPort->setStyleSheet("* { background-color: rgb(255,125,100) }"); - ui->cmbPort->setEnabled(false); - ui->comboBoxBaudRate->setEnabled(false); - ui->tabAxisVisualizer->setEnabled(true); - ui->groupBoxSendFile->setEnabled(true); - ui->groupBoxManualGCode->setEnabled(true); - ui->btnSetHome->setEnabled(true); - ui->btnResetGrbl->setEnabled(true); - ui->btnUnlockGrbl->setEnabled(true); - ui->btnGoHomeSafe->setEnabled(true); - - if (ui->filePath->text().length() > 0) - { - ui->Begin->setEnabled(true); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - } - else - { - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - } - - ui->btnGRBL->setEnabled(true); -} - -void MainWindow::incX() -{ - float coord = ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('X', coord, invX, absoluteAfterAxisAdj, 0); -} - -void MainWindow::incY() -{ - float coord = ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('Y', coord, invY, absoluteAfterAxisAdj, 0); -} - -void MainWindow::incZ() -{ - float coord = ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('Z', coord, invZ, absoluteAfterAxisAdj, sliderZCount++); -} - -void MainWindow::decX() -{ - float coord = -ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('X', coord, invX, absoluteAfterAxisAdj, 0); -} - -void MainWindow::decY() -{ - float coord = -ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('Y', coord, invY, absoluteAfterAxisAdj, 0); -} - -void MainWindow::decZ() -{ - float coord = -ui->comboStep->currentText().toFloat(); - disableAllButtons(); - emit axisAdj('Z', coord, invZ, absoluteAfterAxisAdj, sliderZCount++); -} - -void MainWindow::getOptions() -{ - Options opt(this); - opt.exec(); -} - -void MainWindow::gotoXYZ() -{ - if (ui->Command->text().length() == 0) - return; - - QString line = ui->Command->text().append("\r"); - - emit gotoXYZ(line); -} - -void MainWindow::openFile() -{ - QFileDialog dialog(this, tr("Open File"), - directory, - tr("NC (*.nc);;All Files (*.*)")); - - dialog.setFileMode(QFileDialog::ExistingFile); - - if (nameFilter.size() > 0) - dialog.selectNameFilter(nameFilter); - - if (fileOpenDialogState.size() > 0) - dialog.restoreState(fileOpenDialogState); - - QString fileName; - QStringList fileNames; - if (dialog.exec()) - { - fileOpenDialogState = dialog.saveState(); - - fileNames = dialog.selectedFiles(); - if (fileNames.length() > 0) - fileName = fileNames.at(0); - - nameFilter = dialog.selectedNameFilter(); - - resetProgress(); - } - - int slash = fileName.lastIndexOf('/'); - if (slash == -1) - { - slash = fileName.lastIndexOf('\\'); - } - - directory = ""; - if (slash != -1) - { - directory = fileName.left(slash); - } - - ui->filePath->setText(fileName); - if(ui->filePath->text().length() > 0 && ui->btnOpenPort->text() == CLOSE_BUTTON_TEXT) - { - ui->Begin->setEnabled(true); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - } - else - { - ui->Begin->setEnabled(false); - ui->Stop->setEnabled(false); - ui->progressFileSend->setEnabled(false); - ui->outputRuntime->setEnabled(false); - ui->labelRuntime->setEnabled(false); - } - - if (ui->filePath->text().length() > 0) - { - // read in the file to process it - preProcessFile(ui->filePath->text()); - - if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) - { - emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); - } - } -} - -void MainWindow::preProcessFile(QString filepath) -{ - QFile file(filepath); - if (file.open(QFile::ReadOnly)) - { - posList.clear(); - - float totalLineCount = 0; - QTextStream code(&file); - while ((code.atEnd() == false)) - { - totalLineCount++; - code.readLine(); - } - if (totalLineCount == 0) - totalLineCount = 1; - - code.seek(0); - - double x = 0; - double y = 0; - double i = 0; - double j = 0; - bool arc = false; - bool cw = false; - bool mm = true; - int index = 0; - int g = 0; - - bool zeroInsert = false; - do - { - QString strline = code.readLine(); - - index++; - - GCode::trimToEnd(strline, '('); - GCode::trimToEnd(strline, ';'); - GCode::trimToEnd(strline, '%'); - - strline = strline.trimmed(); - - if (strline.size() == 0) - {}//ignore comments - else - { - strline = strline.toUpper(); - strline.replace("M6", "M06"); - strline.replace(QRegExp("([A-Z])"), " \\1"); - strline.replace(QRegExp("\\s+"), " "); - //if (strline.contains("G", Qt::CaseInsensitive)) - { - if (processGCode(strline, x, y, i, j, arc, cw, mm, g)) - { - if (!zeroInsert) - { - // insert 0,0 position - posList.append(PosItem(0, 0, 0, 0, false, false, mm, 0)); - zeroInsert = true; - } - posList.append(PosItem(x, y, i, j, arc, cw, mm, index)); - - //printf("Got G command:%s (%f,%f)\n", strline.toLocal8Bit().constData(), x, y); - } - } - } - } while (code.atEnd() == false); - - file.close(); - - emit setItems(posList); - } - else - printf("Can't open file\n"); -} - -bool MainWindow::processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g) -{ - QString line = inputLine.toUpper(); - - QStringList components = line.split(" ", QString::SkipEmptyParts); - QString s; - arc = false; - bool valid = false; - int nextIsValue = NO_ITEM; - foreach (s, components) - { - if (s.at(0) == 'G') - { - int value = s.mid(1,-1).toInt(); - if (value >= 0 && value <= 3) - { - g = value; - if (value == 2) - cw = true; - else if (value == 3) - cw = false; - } - else if (value == 20) - mm = false; - else if (value == 21) - mm = true; - } - else if (g >= 0 && g <= 3 && s.at(0) == 'X') - { - x = decodeLineItem(s, X_ITEM, valid, nextIsValue); - } - else if (g >= 0 && g <= 3 && s.at(0) == 'Y') - { - y = decodeLineItem(s, Y_ITEM, valid, nextIsValue); - } - else if ((g == 2 || g == 3) && s.at(0) == 'I') - { - i = decodeLineItem(s, I_ITEM, arc, nextIsValue); - } - else if ((g == 2 || g == 3) && s.at(0) == 'J') - { - j = decodeLineItem(s, J_ITEM, arc, nextIsValue); - } - else if (nextIsValue != NO_ITEM) - { - switch (nextIsValue) - { - case X_ITEM: - x = decodeDouble(s, valid); - break; - case Y_ITEM: - y = decodeDouble(s, valid); - break; - case I_ITEM: - i = decodeDouble(s, arc); - break; - case J_ITEM: - j = decodeDouble(s, arc); - break; - }; - nextIsValue = NO_ITEM; - } - } - - return valid; -} - -double MainWindow::decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue) -{ - if (item.size() == 1) - { - nextIsValue = next; - return 0; - } - else - { - nextIsValue = NO_ITEM; - return decodeDouble(item.mid(1,-1), valid); - } -} - -double MainWindow::decodeDouble(QString value, bool& valid) -{ - /* - QDoubleValidator v; - int pos = 0; - QValidator::State s = v.validate(value, pos); - if (s == QValidator::Invalid) - return 0; - */ - if (value.indexOf(QRegExp("^[+-]?[0-9]*\\.?[0-9]*$")) == -1) - return 0; - valid = true; - return value.toDouble(); -} - -void MainWindow::readSettings() -{ - // use platform-independent settings storage, i.e. registry under Windows - QSettings settings; - - fileOpenDialogState = settings.value(SETTINGS_FILE_OPEN_DIALOG_STATE).value(); - directory = settings.value(SETTINGS_DIRECTORY).value(); - nameFilter = settings.value(SETTINGS_NAME_FILTER).value(); - lastOpenPort = settings.value(SETTINGS_PORT).value(); - lastBaudRate = settings.value(SETTINGS_BAUD, QString::number(BAUD9600)).value(); - - promptedAggrPreload = settings.value(SETTINGS_PROMPTED_AGGR_PRELOAD, false).value(); - - updateSettingsFromOptionDlg(settings); -} - -// Slot called from settings dialog after user made a change. Reload settings from registry. -void MainWindow::setSettings() -{ - QSettings settings; - - updateSettingsFromOptionDlg(settings); - - // update gcode thread with latest values - emit setResponseWait(controlParams); -} - -void MainWindow::updateSettingsFromOptionDlg(QSettings& settings) -{ - QString sinvX = settings.value(SETTINGS_INVERSE_X, "false").value(); - QString sinvY = settings.value(SETTINGS_INVERSE_Y, "false").value(); - QString sinvZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); - - QString sdbgLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); - g_enableDebugLog.set(sdbgLog == "true"); - - // only enable/not enable file logging at startup. There are some kind of - // multithreaded issues turning on or off file logging at runtime causing - // crashes. - if (!checkLogWrite) - { - checkLogWrite = true; - - if (g_enableDebugLog.get()) - { - p_fappender->activateOptions(); - Log4Qt::Logger::rootLogger()->addAppender(p_fappender); - } - } - - invX = sinvX == "true"; - invY = sinvY == "true"; - invZ = sinvZ == "true"; - - controlParams.waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); - controlParams.zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); - QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); - controlParams.useMm = useMmManualCmds == "true"; - QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "false").value(); - controlParams.useAggressivePreload = useAggrPreload == "true"; - - QString absAfterAdj = settings.value(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, "false").value(); - absoluteAfterAxisAdj = absAfterAdj == "true"; - ui->chkRestoreAbsolute->setChecked(absoluteAfterAxisAdj); - - QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); - controlParams.zRateLimit = zRateLimit == "true"; - - QString ffCommands = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); - controlParams.filterFileCommands = ffCommands == "true"; - QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); - controlParams.reducePrecision = rPrecision == "true"; - controlParams.grblLineBufferLen = settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value(); - - controlParams.zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); - controlParams.xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); -} - -// save last state of settings -void MainWindow::writeSettings() -{ - QSettings settings; - - settings.setValue(SETTINGS_FILE_OPEN_DIALOG_STATE, fileOpenDialogState); - settings.setValue(SETTINGS_NAME_FILTER, nameFilter); - settings.setValue(SETTINGS_DIRECTORY, directory); - settings.setValue(SETTINGS_PORT, ui->cmbPort->currentText()); - settings.setValue(SETTINGS_BAUD, ui->comboBoxBaudRate->currentText()); - - settings.setValue(SETTINGS_PROMPTED_AGGR_PRELOAD, promptedAggrPreload); - - settings.setValue(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, ui->chkRestoreAbsolute->isChecked()); -} - -void MainWindow::receiveList(QString msg) -{ - addToStatusList(true, msg); -} - -void MainWindow::receiveListFull(QStringList list) -{ - addToStatusList(list); -} - -void MainWindow::receiveListOut(QString msg) -{ - addToStatusList(false, msg); -} - -void MainWindow::addToStatusList(bool in, QString msg) -{ - msg.trimmed(); - msg.remove('\r'); - msg.remove('\n'); - - if (msg.length() == 0) - return; - - QString nMsg(msg); - if (!in) - nMsg = "> " + msg; - ui->statusList->addItem(nMsg); - - status("%s", nMsg.toLocal8Bit().constData()); - - doScroll(); -} - -void MainWindow::addToStatusList(QStringList& list) -{ - QStringList cleanList; - foreach (QString msg, list) - { - msg.trimmed(); - msg.remove('\r'); - msg.remove('\n'); - - if (msg.length() == 0) - continue; - - cleanList.append(msg); - - status("%s", msg.toLocal8Bit().constData()); - } - - if (cleanList.size() == 0) - return; - - ui->statusList->addItems(cleanList); - - doScroll(); -} - -void MainWindow::doScroll() -{ - if (scrollStatusTimer.elapsed() > 1000) - { - ui->statusList->scrollToBottom(); - QApplication::processEvents(); - scrollStatusTimer.restart(); - } -} - -/* testing optimizing scrollbar, doesn't work -int MainWindow::computeListViewMinimumWidth(QAbstractItemView* view) -{ - int minWidth = 0; - QAbstractItemModel* model = view->model(); - - QStyleOptionViewItem option; - - int rowCount = model->rowCount(); - for (int row = 0; row < rowCount; ++row) - { - QModelIndex index = model->index(row, 0); - QSize size = view->itemDelegate()->sizeHint(option, index); - scrollDelegate = new MyItemDelegate(view); - view->setItemDelegate(scrollDelegate); - - minWidth = qMax(size.width(), minWidth); - } - - if (rowCount > 0) - { - if (scrollDelegate == NULL) - { - scrollDelegate = new MyItemDelegate(view); - QModelIndex index = model->index(0, 0); - view->setItemDelegate(scrollDelegate); - } - - scrollDelegate->setWidth(minWidth); - info("Width is %d\n", minWidth); - } - return minWidth; -} -*/ - -void MainWindow::receiveMsg(QString msg) -{ - ui->centralWidget->setStatusTip(msg); -} - -void MainWindow::setGRBL() -{ - GrblDialog dlg(this, &gcode); - dlg.setParent(this); - dlg.getSettings(); - dlg.exec(); -} - -void MainWindow::showAbout() -{ - About about(this); - about.exec(); -} - -void MainWindow::toggleSpindle() -{ - if (ui->SpindleOn->QAbstractButton::isChecked()) - { - sendGcode("M03\r"); - receiveList("Spindle On."); - } - else - { - sendGcode("M05\r"); - receiveList("Spindle Off."); - } -} - -void MainWindow::toggleRestoreAbsolute() -{ - absoluteAfterAxisAdj = ui->chkRestoreAbsolute->QAbstractButton::isChecked(); -} - -void MainWindow::updateCoordinates(Coord3D machineCoord, Coord3D workCoord) -{ - machineCoordinates = machineCoord; - workCoordinates = workCoord; -/* - if (workCoordinates.stoppedZ == false) - { - int newPos = workCoordinates.z + sliderTo; - - QString to; - to.sprintf("%d", newPos); - - ui->resultingZJogSliderPosition->setText(to); - } -*/ - refreshLcd(); -} - -void MainWindow::refreshLcd() -{ - lcdDisplay('X', true, workCoordinates.x); - lcdDisplay('Y', true, workCoordinates.y); - lcdDisplay('Z', true, workCoordinates.z); - lcdDisplay('X', false, machineCoordinates.x); - lcdDisplay('Y', false, machineCoordinates.y); - lcdDisplay('Z', false, machineCoordinates.z); -} - -void MainWindow::lcdDisplay(char axis, bool workCoord, float floatVal) -{ - QString value = QString::number(floatVal, 'f', 3); - switch (axis) - { - case 'X': - if (workCoord) - ui->lcdWorkNumberX->display(value); - else - ui->lcdMachNumberX->display(value); - break; - case 'Y': - if (workCoord) - ui->lcdWorkNumberY->display(value); - else - ui->lcdMachNumberY->display(value); - break; - case 'Z': - if (workCoord) - ui->lcdWorkNumberZ->display(value); - else - ui->lcdMachNumberZ->display(value); - break; - } -} - -void MainWindow::zJogSliderDisplay(int pos) -{ - QString str; - - pos -= CENTER_POS; - - if (pos > 0) - str.sprintf("+%d", pos); - else if (pos < 0) - str.sprintf("%d", pos); - else - str = "0"; - - ui->currentZJogSliderDelta->setText(str); - - int newPos = pos + sliderTo; - - QString to; - to.sprintf("%d", newPos); - - if (sliderPressed) - { - ui->resultingZJogSliderPosition->setText(to); - info("Usr chg: pos=%d new=%d\n", pos, newPos); - } - else - { - ui->verticalSliderZJog->setSliderPosition(CENTER_POS); - ui->currentZJogSliderDelta->setText("0"); - info("Usr chg no slider: %d\n", pos); - } -} - -void MainWindow::zJogSliderPressed() -{ - sliderPressed = true; - if (workCoordinates.stoppedZ && workCoordinates.sliderZIndex == sliderZCount) - { - info("Pressed and stopped\n"); - sliderTo = workCoordinates.z; - } - else - { - info("Pressed not stopped\n"); - } -} - -void MainWindow::zJogSliderReleased() -{ - info("Released\n"); - if (sliderPressed) - { - sliderPressed = false; - int value = ui->verticalSliderZJog->value(); - - ui->verticalSliderZJog->setSliderPosition(CENTER_POS); - ui->currentZJogSliderDelta->setText("0"); - - value -= CENTER_POS; - - if (value != 0) - { - sliderTo += value; - float setTo = value; - emit axisAdj('Z', setTo, invZ, absoluteAfterAxisAdj, sliderZCount++); - } - } - - - //ui->resultingZJogSliderPosition->setText("0"); -} +/**************************************************************** + * mainwindow.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "mainwindow.h" +#include "version.h" +#include "ui_mainwindow.h" + +extern Log4Qt::FileAppender *p_fappender; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + // open_button_text(tr(OPEN_BUTTON_TEXT)), + // close_button_text(tr(CLOSE_BUTTON_TEXT)), + open_button_text(tr("Open")), + close_button_text(tr("Close / Reset")), + absoluteAfterAxisAdj(false), + checkLogWrite(false), + sliderPressed(false), + sliderTo(0.0), + sliderZCount(0), + scrollRequireMove(true), scrollPressed(false), + queuedCommandsStarved(false), lastQueueCount(0), queuedCommandState(QCS_OK), + lastLcdStateValid(true) +{ + // Setup our application information to be used by QSettings + QCoreApplication::setOrganizationName(COMPANY_NAME); + QCoreApplication::setOrganizationDomain(DOMAIN_NAME); + QCoreApplication::setApplicationName(APPLICATION_NAME); + + // required if passing the object by reference into signals/slots + qRegisterMetaType("Coord3D"); + qRegisterMetaType("PosItem"); + qRegisterMetaType("ControlParams"); + + + ui->setupUi(this); + + readSettings(); + + info("%s has started", GRBL_CONTROLLER_NAME_AND_VERSION); + + // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/ + // The thread points out that the documentation for QThread is wrong :) and + // you should NOT subclass from QThread and override run(), rather, + // attach your QOBJECT to a thread and use events (signals/slots) to communicate. + gcode.moveToThread(&gcodeThread); + runtimeTimer.moveToThread(&runtimeTimerThread); + + ui->lcdWorkNumberX->setDigitCount(8); + ui->lcdMachNumberX->setDigitCount(8); + ui->lcdWorkNumberY->setDigitCount(8); + ui->lcdMachNumberY->setDigitCount(8); + ui->lcdWorkNumberZ->setDigitCount(8); + ui->lcdMachNumberZ->setDigitCount(8); + ui->lcdWorkNumberFourth->setDigitCount(8); + ui->lcdMachNumberFourth->setDigitCount(8); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + + //buttons + connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort())); + connect(ui->btnGRBL,SIGNAL(clicked()),this,SLOT(setGRBL())); + connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX())); + connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY())); + connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ())); + connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX())); + connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY())); + connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ())); + connect(ui->DecFourthBtn,SIGNAL(clicked()),this,SLOT(decFourth())); + connect(ui->IncFourthBtn,SIGNAL(clicked()),this,SLOT(incFourth())); + connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome())); + connect(ui->comboCommand->lineEdit(),SIGNAL(editingFinished()),this,SLOT(gotoXYZFourth())); + connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin())); + connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile())); + connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop())); + connect(ui->SpindleOn,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle())); + connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute())); + connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions())); + connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close())); + connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout())); + connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset())); + connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock())); + connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe())); + connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int))); + connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed())); + connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased())); + connect(ui->pushButtonRefreshPos,SIGNAL(clicked()),this,SLOT(refreshPosition())); + connect(ui->comboStep,SIGNAL(currentIndexChanged(QString)),this,SLOT(comboStepChanged(QString))); + + connect(this, SIGNAL(sendFile(QString)), &gcode, SLOT(sendFile(QString))); + connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString))); + connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool))); + connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString))); + connect(this, SIGNAL(gotoXYZFourth(QString)), &gcode, SLOT(gotoXYZFourth(QString))); + connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int))); + connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams))); + connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit())); + connect(this, SIGNAL(shutdown()), &runtimeTimerThread, SLOT(quit())); + connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); + connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome())); + connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset())); + connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock())); + connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome())); + connect(this, SIGNAL(setItems(QList)), ui->wgtVisualizer, SLOT(setItems(QList))); + + connect(&gcode, SIGNAL(sendMsg(QString)),this,SLOT(receiveMsg(QString))); + connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool))); + connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool))); + connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString))); + connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList))); + connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString))); + connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending())); + connect(&gcode, SIGNAL(setCommandText(QString)), ui->comboCommand->lineEdit(), SLOT(setText(QString))); + connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(&gcode, SIGNAL(setQueuedCommands(int, bool)), this, SLOT(setQueuedCommands(int, bool))); + connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis())); + connect(&gcode, SIGNAL(resetTimer(bool)), &runtimeTimer, SLOT(resetTimer(bool))); + connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton())); + connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D))); + connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsWork(QString)), ui->outputUnitsWork, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsMachine(QString)), ui->outputUnitsMachine, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setLivePoint(double, double, bool, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool, bool))); + connect(&gcode, SIGNAL(setVisualLivenessCurrPos(bool)), ui->wgtVisualizer, SLOT(setVisualLivenessCurrPos(bool))); + connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int))); + connect(&gcode, SIGNAL(setLcdState(bool)), this, SLOT(setLcdState(bool))); + + connect(&runtimeTimer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); + + // This code generates too many messages and chokes operation on raspberry pi. Do not use. + //connect(ui->statusList->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), ui->statusList, SLOT(scrollToBottom())); + + // instead, use this one second timer-based approach + scrollTimer = new QTimer(this); + connect(scrollTimer, SIGNAL(timeout()), this, SLOT(doScroll())); + scrollTimer->start(1000); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderPressed()), this, SLOT(statusSliderPressed())); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(statusSliderReleased())); + + runtimeTimerThread.start(); + gcodeThread.start(); + + // Don't use - it will not show horizontal scrollbar for small app size + //ui->statusList->setUniformItemSizes(true); + + // Does not work correctly for horizontal scrollbar: + //MyItemDelegate *scrollDelegate = new MyItemDelegate(ui->statusList); + //scrollDelegate->setWidth(600); + //ui->statusList->setItemDelegate(scrollDelegate); + + scrollStatusTimer.start(); + queuedCommandsEmptyTimer.start(); + queuedCommandsRefreshTimer.start(); + + // Cool utility class off Google code that enumerates COM ports in platform-independent manner + QList ports = QextSerialEnumerator::getPorts(); + + int portIndex = -1; + for (int i = 0; i < ports.size(); i++) + { + ui->cmbPort->addItem(ports.at(i).portName.toLocal8Bit().constData()); + + if (ports.at(i).portName == lastOpenPort) + portIndex = i; + + //diag("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData()); + //diag("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData()); + //diag("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData()); + //diag("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData()); + //diag("===================================\n\n"); + } + + if (portIndex >= 0) + { + // found matching port + ui->cmbPort->setCurrentIndex(portIndex); + } + else if (lastOpenPort.size() > 0) + { + // did not find matching port + // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator + ui->cmbPort->addItem(lastOpenPort.toLocal8Bit().constData()); + if (ports.size() > 0) + ui->cmbPort->setCurrentIndex(ports.size()); + else + ui->cmbPort->setCurrentIndex(0); + } + + int baudRates[] = { 9600, 19200, 38400, 57600, 115200 }; + int baudRateCount = sizeof baudRates / sizeof baudRates[0]; + int baudRateIndex = 0; + for (int i = 0; i < baudRateCount; i++) + { + QString baudRate = QString::number(baudRates[i]); + ui->comboBoxBaudRate->addItem(baudRate); + if (baudRate == lastBaudRate) + { + baudRateIndex = i; + } + } + + ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex); + + ui->tabAxisVisualizer->setEnabled(false); + if (!controlParams.useFourAxis) + { + ui->lcdWorkNumberFourth->setEnabled(false);; + ui->lcdMachNumberFourth->setEnabled(false);; + ui->IncFourthBtn->setEnabled(false); + ui->DecFourthBtn->setEnabled(false); + ui->lblFourthJog->setEnabled(false); + } + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + styleSheet = ui->btnOpenPort->styleSheet(); + ui->statusList->setEnabled(true); + ui->openFile->setEnabled(true); + + this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION); + this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + + QSettings settings; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + + if (!controlParams.useAggressivePreload && !promptedAggrPreload) + { + QMessageBox msgBox; + msgBox.setText(tr("You appear to have upgraded to the latest version of Grbl Controller. " + "Please be aware that as of version 3.4 the default behavior of sending commands " + "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n" + "Your settings have been changed to enable this mode. Why? Because it provides the most " + "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n" + "What does this mean to you? " + "Arc commands will now run smoother and faster than before, which may " + "cause your spindle to work slightly harder, so please run some tests first. " + "Alternately, go to the Options dialog and manually disable Aggressive Preload") ); + msgBox.exec(); + + controlParams.useAggressivePreload = true; + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload); + } + + promptedAggrPreload = true; + + emit setResponseWait(controlParams); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +// called when user has clicked the close application button +void MainWindow::closeEvent(QCloseEvent *event) +{ + gcode.setShutdown(); + gcode.setAbort(); + gcode.setReset(); + + writeSettings(); + + info("%s has stopped", GRBL_CONTROLLER_NAME_AND_VERSION); + + SLEEP(300); + + emit shutdown(); + + event->accept(); +} + +void MainWindow::begin() +{ + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + + //receiveList("Starting File Send."); + resetProgress(); + int ret = QMessageBox::No; + if((ui->lcdWorkNumberX->value()!=0)||(ui->lcdWorkNumberY->value()!=0)||(ui->lcdWorkNumberZ->value()!=0) + || (ui->lcdWorkNumberFourth->value()!=0)) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you want to zero the displayed position before proceeding?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Yes); + ret = msgBox.exec(); + if(ret ==QMessageBox::Yes) + setHome(); + } + if(ret!=QMessageBox::Cancel) + { + ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(true); + ui->progressFileSend->setEnabled(true); + ui->progressQueuedCommands->setEnabled(true); + ui->labelFileSendProgress->setEnabled(true); + ui->labelQueuedCommands->setEnabled(true); + ui->outputRuntime->setEnabled(true); + ui->labelRuntime->setEnabled(true); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + emit sendFile(ui->filePath->text()); + } +} + +void MainWindow::stop() +{ + gcode.setAbort(); + + // Reenable a bunch of UI + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::grblReset() +{ + gcode.setAbort(); + gcode.setReset(); + emit sendGrblReset(); +} + +void MainWindow::grblUnlock() +{ + emit sendGrblUnlock(); +} + +void MainWindow::goHomeSafe() +{ + emit goToHome(); +} + +// slot called from GCode class to update our state +void MainWindow::stopSending() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnOpenPort->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + ui->openFile->setEnabled(true); +} + +// User has asked to open the port +void MainWindow::openPort() +{ + QString Mes = tr("User clicked Port Open/Close"); + info(qPrintable(Mes) ); + + openPortCtl(false); +} + +// User has asked to set current position as 'home' = 0,0,0 +void MainWindow::setHome() +{ + resetProgress(); + sendSetHome(); +} + +void MainWindow::resetProgress() +{ + setProgress(0); + setQueuedCommands(0, false); + setRuntime(""); +} + +// If the port isn't open, we ask to open it +// If the port is open, we close it, but if 'reopen' is +// true, we call back to this thread to reopen it which +// is done mainly to toggle the COM port state to reset +// the controller. +void MainWindow::openPortCtl(bool reopen) +{ + if (ui->btnOpenPort->text() == open_button_text) + { + // Port is closed if the button says 'Open' + QString portStr = ui->cmbPort->currentText(); + QString baudRate = ui->comboBoxBaudRate->currentText(); + + ui->btnOpenPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + emit openPort(portStr, baudRate); + } + else + { + if (!reopen) + resetProgress(); + + // presume button says 'Close' currently, meaning port is open + + // Tell gcode port thread to stop what it is doing immediately (within 0.1 sec) + gcode.setAbort(); + gcode.setReset(); + + // Disable a bunch of UI + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->openFile->setEnabled(false); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + //ui->cmbPort->setEnabled(false); + //ui->comboBoxBaudRate->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->btnGRBL->setEnabled(false); + + // Send event to close the port + emit closePort(reopen); + } +} + +// slot telling us that port was closed successfully +// if 'reopen' is true, reopen our port to toggle +// so we reset the controller +void MainWindow::portIsClosed(bool reopen) +{ + SLEEP(100); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->cmbPort->setEnabled(true); + ui->comboBoxBaudRate->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(open_button_text); + ui->btnOpenPort->setStyleSheet(styleSheet); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + + if (reopen) + { + receiveList(tr("Resetting port to restart controller")); + openPortCtl(false); + } +} + +// slot that tells us the gcode thread successfully opened the port +void MainWindow::portIsOpen(bool sendCode) +{ + // Comm port successfully opened + if (sendCode) + sendGcode(""); +} + +void MainWindow::adjustedAxis() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + + if (ui->filePath->text().length() > 0) + ui->Begin->setEnabled(true); + + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + + ui->btnOpenPort->setEnabled(true); + ui->openFile->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::disableAllButtons() +{ + //ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); +} + +void MainWindow::enableGrblDialogButton() +{ + ui->openFile->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(close_button_text); + ui->btnOpenPort->setStyleSheet("* { background-color: rgb(255,125,100) }"); + ui->cmbPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + + if (ui->filePath->text().length() > 0) + { + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + ui->btnGRBL->setEnabled(true); +} + +void MainWindow::incX() +{ + disableAllButtons(); + emit axisAdj('X', jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incY() +{ + disableAllButtons(); + emit axisAdj('Y', jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incZ() +{ + disableAllButtons(); + emit axisAdj('Z', jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decX() +{ + disableAllButtons(); + emit axisAdj('X', -jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decY() +{ + disableAllButtons(); + emit axisAdj('Y', -jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decZ() +{ + disableAllButtons(); + emit axisAdj('Z', -jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, -jogStep, invFourth, absoluteAfterAxisAdj, 0); +} +void MainWindow::incFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, jogStep, invFourth, absoluteAfterAxisAdj, 0); +} + +void MainWindow::getOptions() +{ + Options opt(this); + opt.exec(); +} + +void MainWindow::gotoXYZFourth() +{ + if (ui->comboCommand->lineEdit()->text().length() == 0) + return; + + QString line = ui->comboCommand->lineEdit()->text().append("\r"); + + emit gotoXYZFourth(line); +} + +void MainWindow::openFile() +{ + QFileDialog dialog(this, tr("Open File"), + directory, + tr("NC (*.nc);;All Files (*.*)")); + + dialog.setFileMode(QFileDialog::ExistingFile); + + if (nameFilter.size() > 0) + dialog.selectNameFilter(nameFilter); + + if (fileOpenDialogState.size() > 0) + dialog.restoreState(fileOpenDialogState); + + QString fileName; + QStringList fileNames; + if (dialog.exec()) + { + fileOpenDialogState = dialog.saveState(); + + fileNames = dialog.selectedFiles(); + if (fileNames.length() > 0) + fileName = fileNames.at(0); + + nameFilter = dialog.selectedNameFilter(); + + resetProgress(); + } + + int slash = fileName.lastIndexOf('/'); + if (slash == -1) + { + slash = fileName.lastIndexOf('\\'); + } + + directory = ""; + if (slash != -1) + { + directory = fileName.left(slash); + } + + ui->filePath->setText(fileName); + if(ui->filePath->text().length() > 0 && ui->btnOpenPort->text() == close_button_text) + { + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + if (ui->filePath->text().length() > 0) + { + // read in the file to process it + preProcessFile(ui->filePath->text()); + + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + } +} + +void MainWindow::preProcessFile(QString filepath) +{ + QFile file(filepath); + if (file.open(QFile::ReadOnly)) + { + posList.clear(); + + float totalLineCount = 0; + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLineCount++; + code.readLine(); + } + if (totalLineCount == 0) + totalLineCount = 1; + + code.seek(0); + + double x = 0; + double y = 0; + double i = 0; + double j = 0; + bool arc = false; + bool cw = false; + bool mm = true; + int index = 0; + int g = 0; + + bool zeroInsert = false; + do + { + QString strline = code.readLine(); + + index++; + + GCode::trimToEnd(strline, '('); + GCode::trimToEnd(strline, ';'); + GCode::trimToEnd(strline, '%'); + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + strline = strline.toUpper(); + strline.replace("M6", "M06"); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline.replace(QRegExp("\\s+"), " "); + //if (strline.contains("G", Qt::CaseInsensitive)) + { + if (processGCode(strline, x, y, i, j, arc, cw, mm, g)) + { + if (!zeroInsert) + { + // insert 0,0 position + posList.append(PosItem(0, 0, 0, 0, false, false, mm, 0)); + zeroInsert = true; + } + posList.append(PosItem(x, y, i, j, arc, cw, mm, index)); + + //printf("Got G command:%s (%f,%f)\n", strline.toLocal8Bit().constData(), x, y); + } + } + } + } while (code.atEnd() == false); + + file.close(); + + emit setItems(posList); + } + else + printf("Can't open file\n"); +} + +bool MainWindow::processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g) +{ + QString line = inputLine.toUpper(); + + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + arc = false; + bool valid = false; + int nextIsValue = NO_ITEM; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value >= 0 && value <= 3) + { + g = value; + if (value == 2) + cw = true; + else if (value == 3) + cw = false; + } + else if (value == 20) + mm = false; + else if (value == 21) + mm = true; + } + else if (g >= 0 && g <= 3 && s.at(0) == 'X') + { + x = decodeLineItem(s, X_ITEM, valid, nextIsValue); + } + else if (g >= 0 && g <= 3 && s.at(0) == 'Y') + { + y = decodeLineItem(s, Y_ITEM, valid, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'I') + { + i = decodeLineItem(s, I_ITEM, arc, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'J') + { + j = decodeLineItem(s, J_ITEM, arc, nextIsValue); + } + else if (nextIsValue != NO_ITEM) + { + switch (nextIsValue) + { + case X_ITEM: + x = decodeDouble(s, valid); + break; + case Y_ITEM: + y = decodeDouble(s, valid); + break; + case I_ITEM: + i = decodeDouble(s, arc); + break; + case J_ITEM: + j = decodeDouble(s, arc); + break; + }; + nextIsValue = NO_ITEM; + } + } + + return valid; +} + +double MainWindow::decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue) +{ + if (item.size() == 1) + { + nextIsValue = next; + return 0; + } + else + { + nextIsValue = NO_ITEM; + return decodeDouble(item.mid(1,-1), valid); + } +} + +double MainWindow::decodeDouble(QString value, bool& valid) +{ + /* + QDoubleValidator v; + int pos = 0; + QValidator::State s = v.validate(value, pos); + if (s == QValidator::Invalid) + return 0; + */ + if (value.indexOf(QRegExp("^[+-]?[0-9]*\\.?[0-9]*$")) == -1) + return 0; + valid = true; + return value.toDouble(); +} + +void MainWindow::readSettings() +{ + // use platform-independent settings storage, i.e. registry under Windows + QSettings settings; + + fileOpenDialogState = settings.value(SETTINGS_FILE_OPEN_DIALOG_STATE).value(); + directory = settings.value(SETTINGS_DIRECTORY).value(); + nameFilter = settings.value(SETTINGS_NAME_FILTER).value(); + lastOpenPort = settings.value(SETTINGS_PORT).value(); + lastBaudRate = settings.value(SETTINGS_BAUD, QString::number(BAUD9600)).value(); + + promptedAggrPreload = settings.value(SETTINGS_PROMPTED_AGGR_PRELOAD, false).value(); + + QString absAfterAdj = settings.value(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, "false").value(); + absoluteAfterAxisAdj = (absAfterAdj == "true"); + ui->chkRestoreAbsolute->setChecked(absoluteAfterAxisAdj); + + jogStepStr = settings.value(SETTINGS_JOG_STEP, "1").value(); + jogStep = jogStepStr.toFloat(); + + int indexDesired = 0; + QString steps[] = { "0.01", "0.1", "1", "10", "100" }; + for (unsigned int i = 0; i < (sizeof (steps) / sizeof (steps[0])); i++) { + ui->comboStep->addItem(steps[i]); + if (jogStepStr == steps[i]) { + indexDesired = i; + } + } + ui->comboStep->setCurrentIndex(indexDesired); + + settings.beginGroup( "mainwindow" ); + + restoreGeometry(settings.value( "geometry", saveGeometry() ).toByteArray()); + restoreState(settings.value( "savestate", saveState() ).toByteArray()); + move(settings.value( "pos", pos() ).toPoint()); + resize(settings.value( "size", size() ).toSize()); + if ( settings.value( "maximized", isMaximized() ).toBool() ) + showMaximized(); + + settings.endGroup(); + + updateSettingsFromOptionDlg(settings); +} + +// Slot called from settings dialog after user made a change. Reload settings from registry. +void MainWindow::setSettings() +{ + QSettings settings; + + updateSettingsFromOptionDlg(settings); + + // update gcode thread with latest values + emit setResponseWait(controlParams); +} + +void MainWindow::updateSettingsFromOptionDlg(QSettings& settings) +{ + QString sinvX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString sinvY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString sinvZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + //QString smm = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS,"false").value(); + QString sinvFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + QString sdbgLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + g_enableDebugLog.set(sdbgLog == "true"); + + // only enable/not enable file logging at startup. There are some kind of + // multithreaded issues turning on or off file logging at runtime causing + // crashes. + if (!checkLogWrite) + { + checkLogWrite = true; + + if (g_enableDebugLog.get()) + { + p_fappender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + } + } + + invX = sinvX == "true"; + invY = sinvY == "true"; + invZ = sinvZ == "true"; + invFourth = sinvFourth == "true"; + + controlParams.waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + controlParams.zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + controlParams.useMm = useMmManualCmds == "true"; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + controlParams.waitForJogToComplete = waitForJogToComplete == "true"; + + QString useFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + controlParams.useFourAxis = useFourAxis == "true"; + if (controlParams.useFourAxis) + { + char type = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + controlParams.fourthAxisType = type; + } + + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + else + { + ui->DecFourthBtn->show(); + ui->IncFourthBtn->show(); + ui->lblFourthJog->show(); + ui->lcdWorkNumberFourth->show(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lcdMachNumberFourth->show(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->show(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->setText(QString(controlParams.fourthAxisType)); + + QString axisJog(tr("Z Jog"));// not correct, but a default placeholder we have a translation for already + char axis = controlParams.fourthAxisType; + if (axis == FOURTH_AXIS_A) + axisJog = tr("A Jog"); + else if (axis == FOURTH_AXIS_B) + axisJog = tr("B Jog"); + else if (axis == FOURTH_AXIS_C) + axisJog = tr("C Jog"); + else if (axis == FOURTH_AXIS_U) + axisJog = tr("U Jog"); + else if (axis == FOURTH_AXIS_V) + axisJog = tr("V Jog"); + else if (axis == FOURTH_AXIS_W) + axisJog = tr("W Jog"); + + ui->lblFourthJog->setText(axisJog); + } + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + controlParams.zRateLimit = zRateLimit == "true"; + + QString ffCommands = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + controlParams.filterFileCommands = ffCommands == "true"; + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + controlParams.reducePrecision = rPrecision == "true"; + controlParams.grblLineBufferLen = settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value(); + controlParams.charSendDelayMs = settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value(); + + controlParams.zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + controlParams.xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + controlParams.usePositionRequest = enPosReq == "true"; + controlParams.positionRequestType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_ALWAYS_NO_IDLE_CHK).value(); + double posReqFreq = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + controlParams.postionRequestTimeMilliSec = static_cast(posReqFreq) * 1000; + + setLcdState(controlParams.usePositionRequest); +} + +// save last state of settings +void MainWindow::writeSettings() +{ + QSettings settings; + + settings.setValue(SETTINGS_FILE_OPEN_DIALOG_STATE, fileOpenDialogState); + settings.setValue(SETTINGS_NAME_FILTER, nameFilter); + settings.setValue(SETTINGS_DIRECTORY, directory); + settings.setValue(SETTINGS_PORT, ui->cmbPort->currentText()); + settings.setValue(SETTINGS_BAUD, ui->comboBoxBaudRate->currentText()); + + settings.setValue(SETTINGS_PROMPTED_AGGR_PRELOAD, promptedAggrPreload); + settings.setValue(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, ui->chkRestoreAbsolute->isChecked()); + settings.setValue(SETTINGS_JOG_STEP, ui->comboStep->currentText()); + + // From http://stackoverflow.com/questions/74690/how-do-i-store-the-window-size-between-sessions-in-qt + settings.beginGroup("mainwindow"); + + settings.setValue( "geometry", saveGeometry() ); + settings.setValue( "savestate", saveState() ); + settings.setValue( "maximized", isMaximized() ); + if ( !isMaximized() ) { + settings.setValue( "pos", pos() ); + settings.setValue( "size", size() ); + } + + settings.endGroup(); +} + +void MainWindow::receiveList(QString msg) +{ + addToStatusList(true, msg); +} + +void MainWindow::receiveListFull(QStringList list) +{ + addToStatusList(list); +} + +void MainWindow::receiveListOut(QString msg) +{ + addToStatusList(false, msg); +} + +void MainWindow::addToStatusList(bool in, QString msg) +{ + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + return; + + QString nMsg(msg); + if (!in) + nMsg = "> " + msg; + + fullStatus.append(msg); + ui->statusList->addItem(nMsg); + + status("%s", nMsg.toLocal8Bit().constData()); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::addToStatusList(QStringList& list) +{ + QStringList cleanList; + foreach (QString msg, list) + { + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + continue; + + cleanList.append(msg); + + fullStatus.append(msg); + + status("%s", msg.toLocal8Bit().constData()); + } + + if (cleanList.size() == 0) + return; + + ui->statusList->addItems(cleanList); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::doScroll() +{ + if (!scrollPressed && scrollRequireMove)// && scrollStatusTimer.elapsed() > 1000) + { + ui->statusList->scrollToBottom(); + QApplication::processEvents(); + scrollStatusTimer.restart(); + scrollRequireMove = false; + } +} + +void MainWindow::statusSliderPressed() +{ + scrollPressed = true; + + if (scrollStatusTimer.elapsed() > 3000) + { + ui->statusList->clear(); + ui->statusList->addItems(fullStatus); + } +} + +void MainWindow::statusSliderReleased() +{ + scrollPressed = false; +} + +/* testing optimizing scrollbar, doesn't work +int MainWindow::computeListViewMinimumWidth(QAbstractItemView* view) +{ + int minWidth = 0; + QAbstractItemModel* model = view->model(); + + QStyleOptionViewItem option; + + int rowCount = model->rowCount(); + for (int row = 0; row < rowCount; ++row) + { + QModelIndex index = model->index(row, 0); + QSize size = view->itemDelegate()->sizeHint(option, index); + scrollDelegate = new MyItemDelegate(view); + view->setItemDelegate(scrollDelegate); + + minWidth = qMax(size.width(), minWidth); + } + + if (rowCount > 0) + { + if (scrollDelegate == NULL) + { + scrollDelegate = new MyItemDelegate(view); + QModelIndex index = model->index(0, 0); + view->setItemDelegate(scrollDelegate); + } + + scrollDelegate->setWidth(minWidth); + info("Width is %d\n", minWidth); + } + return minWidth; +} +*/ + +void MainWindow::receiveMsg(QString msg) +{ + ui->centralWidget->setStatusTip(msg); +} + +void MainWindow::setGRBL() +{ + GrblDialog dlg(this, &gcode); + dlg.setParent(this); + dlg.getSettings(); + dlg.exec(); +} + +void MainWindow::showAbout() +{ + About about(this); + about.exec(); +} + +void MainWindow::toggleSpindle() +{ + if (ui->SpindleOn->QAbstractButton::isChecked()) + { + sendGcode("M03\r"); + receiveList(tr("Spindle On.")); + } + else + { + sendGcode("M05\r"); + receiveList(tr("Spindle Off.")); + } +} + +void MainWindow::toggleRestoreAbsolute() +{ + absoluteAfterAxisAdj = ui->chkRestoreAbsolute->QAbstractButton::isChecked(); +} + +void MainWindow::updateCoordinates(Coord3D machineCoord, Coord3D workCoord) +{ + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + machineCoordinates = machineCoord; + workCoordinates = workCoord; +/* + if (workCoordinates.stoppedZ == false) + { + int newPos = workCoordinates.z + sliderTo; + + QString to; + to.sprintf("%d", newPos); + + ui->resultingZJogSliderPosition->setText(to); + } +*/ + refreshLcd(); +} + +void MainWindow::refreshLcd() +{ + lcdDisplay('X', true, workCoordinates.x); + lcdDisplay('Y', true, workCoordinates.y); + lcdDisplay('Z', true, workCoordinates.z); + lcdDisplay('X', false, machineCoordinates.x); + lcdDisplay('Y', false, machineCoordinates.y); + lcdDisplay('Z', false, machineCoordinates.z); + if (controlParams.useFourAxis) { + lcdDisplay(controlParams.fourthAxisType, true, workCoordinates.fourth); + lcdDisplay(controlParams.fourthAxisType, false, machineCoordinates.fourth); + } + else { + lcdDisplay(controlParams.fourthAxisType, true, 0); + lcdDisplay(controlParams.fourthAxisType, false, 0); + } +} + +void MainWindow::lcdDisplay(char axis, bool workCoord, float floatVal) +{ + QString value = QString::number(floatVal, 'f', 3); + switch (axis) + { + case 'X': + if (workCoord) + ui->lcdWorkNumberX->display(value); + else + ui->lcdMachNumberX->display(value); + break; + case 'Y': + if (workCoord) + ui->lcdWorkNumberY->display(value); + else + ui->lcdMachNumberY->display(value); + break; + case 'Z': + if (workCoord) + ui->lcdWorkNumberZ->display(value); + else + ui->lcdMachNumberZ->display(value); + break; + default: + if (axis == FOURTH_AXIS_A || axis == FOURTH_AXIS_B || axis == FOURTH_AXIS_C +/// LETARTARE + || axis == FOURTH_AXIS_U || axis == FOURTH_AXIS_V || axis == FOURTH_AXIS_W +/// <- + ) + { + if (workCoord) + ui->lcdWorkNumberFourth->display(value); + else + ui->lcdMachNumberFourth->display(value); + } + else + { + err("Unexpected type %c", axis); + } + break; + } +} + +void MainWindow::zJogSliderDisplay(int pos) +{ + QString str; + + pos -= CENTER_POS; + + if (pos > 0) + if(controlParams.useMm) + str.sprintf("+%d", pos); + else + str.sprintf("+%.1f",(double)pos/10); + else if (pos < 0) + if(controlParams.useMm) + str.sprintf("%d", pos); + else + str.sprintf("%.1f", (double)pos/10); + else + str = "0"; + + ui->currentZJogSliderDelta->setText(str); + + double newPos; + QString to; + if(controlParams.useMm) + newPos = pos + sliderTo; + else + newPos = (double)pos/10+sliderTo; + + if(controlParams.useMm) + to.sprintf("%.1f", newPos); + else + to.sprintf("%.1f", newPos); + + if (sliderPressed) + { + ui->resultingZJogSliderPosition->setText(to); + if(controlParams.useMm) + info("Usr chg: pos=%d new=%d\n", pos, newPos); + else + info("Usr chg: pos=%.1f new=%.1f\n", (double)pos/10, newPos); + } + else + { + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + if(controlParams.useMm) + info("Usr chg no slider: %d\n", pos); + else + info("Usr chg no slider: %.1f\n", (double) pos/10); + } +} + +void MainWindow::zJogSliderPressed() +{ + sliderPressed = true; + if (workCoordinates.stoppedZ && workCoordinates.sliderZIndex == sliderZCount) + { + info("Pressed and stopped\n"); + sliderTo = workCoordinates.z; + } + else + { + info("Pressed not stopped\n"); + } +} + +void MainWindow::zJogSliderReleased() +{ + info("Released\n"); + if (sliderPressed) + { + sliderPressed = false; + int value = ui->verticalSliderZJog->value(); + + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + + value -= CENTER_POS; + + if (value != 0) + { + if(controlParams.useMm) + sliderTo += value; + else + sliderTo += (double)value/10; + float setTo = value; + if(controlParams.useMm) + emit axisAdj('Z', setTo, invZ, absoluteAfterAxisAdj, sliderZCount++); + else + emit axisAdj('Z', setTo/10, invZ, absoluteAfterAxisAdj, sliderZCount++); + } + } + + + //ui->resultingZJogSliderPosition->setText("0"); +} + +void MainWindow::setQueuedCommands(int commandCount, bool running) +{ + if (running) + { + switch (queuedCommandState) + { + case QCS_OK: + if (lastQueueCount == 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 2000) + { + if (!queuedCommandsStarved) + { + //diag("DG >>>>Switch to red\n"); + + queuedCommandsStarved = true; + + ui->labelQueuedCommands->setStyleSheet("QLabel { background-color : rgb(255,0,0); color : white; }"); + + queuedCommandState = QCS_WAITING_FOR_ITEMS; + } + } + } + break; + case QCS_WAITING_FOR_ITEMS: + if (commandCount > 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 3000) + { + if (queuedCommandsStarved) + { + //diag("DG >>>>Switch to green\n"); + + queuedCommandsStarved = false; + + ui->labelQueuedCommands->setStyleSheet(""); + } + + queuedCommandsEmptyTimer.restart(); + + queuedCommandState = QCS_OK; + } + } + break; + } + + if (queuedCommandsRefreshTimer.elapsed() > 1000) + { + ui->progressQueuedCommands->setValue(commandCount); + queuedCommandsRefreshTimer.restart(); + } + } + else + { + queuedCommandsEmptyTimer.restart(); + queuedCommandState = QCS_OK; + ui->progressQueuedCommands->setValue(commandCount); + } + + lastQueueCount = commandCount; +} + +void MainWindow::setLcdState(bool valid) +{ + if (lastLcdStateValid != valid) + { + QString ss = ""; + if (!valid) + { + ss = "QLCDNumber { background-color: #F8F8F8; color: #F0F0F0; }"; + } + ui->lcdWorkNumberX->setStyleSheet(ss); + ui->lcdMachNumberX->setStyleSheet(ss); + ui->lcdWorkNumberY->setStyleSheet(ss); + ui->lcdMachNumberY->setStyleSheet(ss); + ui->lcdWorkNumberZ->setStyleSheet(ss); + ui->lcdMachNumberZ->setStyleSheet(ss); + ui->lcdWorkNumberFourth->setStyleSheet(ss); + ui->lcdMachNumberFourth->setStyleSheet(ss); + + lastLcdStateValid = valid; + } +} + +void MainWindow::refreshPosition() +{ + gotoXYZFourth(REQUEST_CURRENT_POS); +} + +void MainWindow::comboStepChanged(const QString& text) +{ + jogStepStr = text; + jogStep = jogStepStr.toFloat(); +} diff --git a/mainwindow.h b/GC-3.6.1-T1/src/mainwindow.h similarity index 83% rename from mainwindow.h rename to GC-3.6.1-T1/src/mainwindow.h index 0fdd007..6add884 100644 --- a/mainwindow.h +++ b/GC-3.6.1-T1/src/mainwindow.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "about.h" #include "definitions.h" @@ -34,9 +35,12 @@ #define TAB_AXIS_INDEX 0 #define TAB_VISUALIZER_INDEX 1 +#define TAB_ADVANCED_INDEX 2 #define CENTER_POS 40 +#define MAX_STATUS_LINES_WHEN_ACTIVE 200 + /* testing optimizing scrollbar, doesn't work right class MyItemDelegate : public QItemDelegate { @@ -80,7 +84,7 @@ class MainWindow; class MainWindow : public QMainWindow { Q_OBJECT - + public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); @@ -96,7 +100,7 @@ class MainWindow : public QMainWindow void shutdown(); void sendGcode(QString line, bool recordResponseOnFail = false, int waitCount = SHORT_WAIT_SEC); void sendFile(QString path); - void gotoXYZ(QString line); + void gotoXYZFourth(QString line); void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); void setResponseWait(ControlParams controlParams); void setProgress(int percent); @@ -115,12 +119,14 @@ private slots: void decX(); void decY(); void decZ(); + void decFourth(); + void incFourth(); void incX(); void incY(); void incZ(); void setHome(); //manual - void gotoXYZ(); + void gotoXYZFourth(); //send Gcode void begin(); void openFile(); @@ -154,6 +160,13 @@ private slots: void zJogSliderDisplay(int pos); void zJogSliderPressed(); void zJogSliderReleased(); + void doScroll(); + void statusSliderPressed(); + void statusSliderReleased(); + void setQueuedCommands(int commandCount, bool running); + void setLcdState(bool valid); + void refreshPosition(); + void comboStepChanged(const QString& text); private: // enums @@ -165,19 +178,30 @@ private slots: I_ITEM, J_ITEM, }; + enum + { + QCS_OK = 0, + QCS_WAITING_FOR_ITEMS + }; //objects Ui::MainWindow *ui; //FileSender fileSender; //QThread fileSenderThread; GCode gcode; QThread gcodeThread; - Timer timer; - QThread timerThread; + + Timer runtimeTimer; + QThread runtimeTimerThread; //variables bool invX; bool invY; bool invZ; + bool invFourth; + /// for translation + QString open_button_text ; + QString close_button_text ; + bool mm; QString styleSheet; QString directory; QString nameFilter; @@ -189,12 +213,24 @@ private slots: bool absoluteAfterAxisAdj; bool checkLogWrite; QTime scrollStatusTimer; + QTime queuedCommandsEmptyTimer; + QTime queuedCommandsRefreshTimer; QList posList; bool sliderPressed; - int sliderTo; + double sliderTo; int sliderZCount; bool promptedAggrPreload; ControlParams controlParams; + QTimer *scrollTimer; + bool scrollRequireMove; + bool scrollPressed; + bool queuedCommandsStarved; + int lastQueueCount; + int queuedCommandState; + QStringList fullStatus; + bool lastLcdStateValid; + float jogStep; + QString jogStepStr; //methods int SendJog(QString strline); @@ -208,7 +244,6 @@ private slots: void refreshLcd(); void lcdDisplay(char axis, bool workCoord, float value); void updateSettingsFromOptionDlg(QSettings& settings); - void doScroll(); int computeListViewMinimumWidth(QAbstractItemView* view); void preProcessFile(QString filepath); bool processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g); diff --git a/GC-3.6.1-T1/src/mainwindow.ui b/GC-3.6.1-T1/src/mainwindow.ui new file mode 100644 index 0000000..3cfbc95 --- /dev/null +++ b/GC-3.6.1-T1/src/mainwindow.ui @@ -0,0 +1,1828 @@ + + + MainWindow + + + Qt::NonModal + + + true + + + + 0 + 0 + 972 + 668 + + + + + 7 + 0 + + + + + 10000000 + 10000000 + + + + Grbl Controller + + + + + + + + 10 + + + 1 + + + 0 + + + + + 2 + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Port name + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + + + + + + + + + + 0 + 0 + + + + Open + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + + + + QFrame::NoFrame + + + Baud Rate + + + + + + + + + + + + + + Last State: + + + + + + + + + + + + + + + + + + + + + + false + + + Send File + + + + + + + + Stop + + + + + + + Qt::Horizontal + + + + 2 + 20 + + + + + + + + Choose file + + + + + + + Begin + + + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + 10 + + + 0 + + + %v + + + + + + + + 0 + 0 + + + + File progress + + + + + + + + 0 + 0 + + + + Queued Commands + + + + + + + + + + + false + + + Runtime: + + + + + + + false + + + + + + + + + + + + + + + + + Command + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + 12 + + + + + + + + + false + + + Qt::ScrollBarAsNeeded + + + 16 + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QListView::Static + + + false + + + QListView::Adjust + + + QListView::SinglePass + + + false + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + 2 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + X + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Work Coordinates + + + + + + + + + + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + Y + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 10 + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Box + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + Z + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + C + + + Qt::AlignCenter + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + 1 + + + 0 + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Machine Coordinates + + + + + + + + 100 + 16777215 + + + + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Axis Control + + + + + + QLayout::SetDefaultConstraint + + + + + QLayout::SetMaximumSize + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 18 + 17 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + + + + 10 + 75 + true + + + + C Jog + + + Qt::AlignCenter + + + + + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 30 + + + 30 + + + + + + 0 + 0 + + + + 80 + + + 40 + + + 40 + + + Qt::Vertical + + + false + + + false + + + QSlider::TicksBelow + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + 10 + 75 + true + + + + Z Jog + + + Qt::AlignCenter + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + + + + + + + + + + 0 + 0 + + + + Absolute coordinates after adjust + + + + + + + + 0 + 0 + + + + Spindle On + + + false + + + + + + + + + 0 + + + 4 + + + 0 + + + 5 + + + + + + 0 + 0 + + + + Step Size + + + + + + + + 0 + 0 + + + + + + + + + + + + + Visualizer + + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 244 + 237 + 187 + + + + + + + 244 + 237 + 187 + + + + + + + + true + + + + + + + + Advanced + + + + + 10 + 10 + 152 + 87 + + + + Reset Control + + + + + + + + + 0 + 0 + + + + Soft Reset Grbl + + + + + + + + 0 + 0 + + + + Unlock Grbl + + + + + + + + + + + 170 + 30 + 131 + 41 + + + + + 0 + 0 + + + + + 8 + + + + GRBL Settings + + + + + + + + + + + + 0 + 0 + + + + + 8 + + + + false + + + Zero Position + + + + + + + + 0 + 0 + + + + Go Home + + + + + + + Refresh Pos + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 0 + 0 + 972 + 21 + + + + + &Help + + + + + + &Tools + + + + + + &File + + + + + + + + + + + &About + + + + + &Options + + + + + E&xit + + + + + + + RenderArea + QWidget +
renderarea.h
+ 1 +
+
+ + + + +
diff --git a/GC-3.6.1-T1/src/makeWin.bat b/GC-3.6.1-T1/src/makeWin.bat new file mode 100644 index 0000000..0483953 --- /dev/null +++ b/GC-3.6.1-T1/src/makeWin.bat @@ -0,0 +1,18 @@ +rem May 30, 2014 +rem LETARTARE + +rem 3.6.1-Tx + +rem for release + +qmake -config release -spec win32-g++ GcodeSenderGUIthreads.pro +mingw32-make -fmakefile.release +rem release\GrblController.exe + +rem for debug + +rem qmake -config debug -spec win32-g++ GcodeSenderGUIthreads.pro +rem mingw32-make -fmakefile.debug +rem debug\GrblController.exe + +cd .. diff --git a/options.cpp b/GC-3.6.1-T1/src/options.cpp similarity index 50% rename from options.cpp rename to GC-3.6.1-T1/src/options.cpp index 392c8e7..54a4cae 100644 --- a/options.cpp +++ b/GC-3.6.1-T1/src/options.cpp @@ -18,6 +18,8 @@ Options::Options(QWidget *parent) : connect(ui->checkBoxUseMmManualCmds,SIGNAL(toggled(bool)),this,SLOT(toggleUseMm(bool))); connect(ui->chkLimitZRate,SIGNAL(toggled(bool)),this,SLOT(toggleLimitZRate(bool))); + connect(ui->checkBoxFourAxis,SIGNAL(toggled(bool)),this,SLOT(toggleFourAxis(bool))); + connect(ui->checkBoxPositionReportEnabled,SIGNAL(toggled(bool)),this,SLOT(togglePosReporting(bool))); QSettings settings; @@ -25,6 +27,8 @@ Options::Options(QWidget *parent) : QString invY = settings.value(SETTINGS_INVERSE_Y, "false").value(); QString invZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + QString invFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + ui->chkInvFourth->setChecked(invFourth == "true"); ui->chkInvX->setChecked(invX == "true"); ui->chkInvY->setChecked(invY == "true"); ui->chkInvZ->setChecked(invZ == "true"); @@ -33,11 +37,56 @@ Options::Options(QWidget *parent) : QString enDebugLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); // default aggressive preload behavior to 'true'! QString enAggressivePreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + QString enFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + char fourthAxisType = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + + if (enFourAxis == "false") + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + + ui->groupBoxFourthAxis->setEnabled(false); + } + else + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + + switch (fourthAxisType) + { + case FOURTH_AXIS_A: + default: + ui->radioButtonFourthAxisA->setChecked(true); + break; + case FOURTH_AXIS_B: + ui->radioButtonFourthAxisB->setChecked(true); + break; + case FOURTH_AXIS_C: + ui->radioButtonFourthAxisC->setChecked(true); + break; +/// LETARTARE + case FOURTH_AXIS_U: + ui->radioButtonFourthAxisU->setChecked(true); + break; + case FOURTH_AXIS_V: + ui->radioButtonFourthAxisV->setChecked(true); + break; + case FOURTH_AXIS_W: + ui->radioButtonFourthAxisW->setChecked(true); + break; +/// <-- + } + } ui->checkBoxEnableDebugLog->setChecked(enDebugLog == "true"); ui->chkAggressivePreload->setChecked(enAggressivePreload == "true"); + //ui->checkBoxWaitForJogToComplete->setChecked(waitForJogToComplete == "true"); + ui->checkBoxWaitForJogToComplete->hide(); ui->checkBoxUseMmManualCmds->setChecked(useMmManualCmds == "true"); + ui->checkBoxFourAxis->setChecked(enFourAxis == "true"); int waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); ui->spinResponseWaitSec->setValue(waitTime); @@ -64,6 +113,29 @@ Options::Options(QWidget *parent) : QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); ui->checkBoxReducePrecForLongLines->setChecked(rPrecision == "true"); ui->spinBoxGrblLineBufferSize->setValue(settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value()); + ui->spinBoxCharSendDelay->setValue(settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value()); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + QString posReqType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_NOT_WHEN_MANUAL).value(); + double posRateFreqSec = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + + ui->checkBoxPositionReportEnabled->setChecked(enPosReq == "true"); + ui->doubleSpinBoxPosRequestFreqSec->setValue(posRateFreqSec); + if (posReqType == PREQ_NOT_WHEN_MANUAL) + { + ui->radioButton_ReqNotDuringManual->setChecked(true); + } + else if (posReqType == PREQ_ALWAYS) + { + ui->radioButton_ReqAlways->setChecked(true); + } + else + { + ui->radioButton_ReqAlwaysNoIdleCheck->setChecked(true); + } + + togglePosReporting(enPosReq == "true"); + } Options::~Options() @@ -78,10 +150,13 @@ void Options::accept() settings.setValue(SETTINGS_INVERSE_X, ui->chkInvX->isChecked()); settings.setValue(SETTINGS_INVERSE_Y, ui->chkInvY->isChecked()); settings.setValue(SETTINGS_INVERSE_Z, ui->chkInvZ->isChecked()); - + settings.setValue(SETTINGS_INVERSE_FOURTH, ui->chkInvFourth->isChecked()); settings.setValue(SETTINGS_ENABLE_DEBUG_LOG, ui->checkBoxEnableDebugLog->isChecked()); settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, ui->chkAggressivePreload->isChecked()); + settings.setValue(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, ui->checkBoxWaitForJogToComplete->isChecked()); settings.setValue(SETTINGS_USE_MM_FOR_MANUAL_CMDS, ui->checkBoxUseMmManualCmds->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_USE, ui->checkBoxFourAxis->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_TYPE, getFourthAxisType()); settings.setValue(SETTINGS_RESPONSE_WAIT_TIME, ui->spinResponseWaitSec->value()); settings.setValue(SETTINGS_Z_JOG_RATE, ui->doubleSpinZJogRate->value()); @@ -93,6 +168,11 @@ void Options::accept() settings.setValue(SETTINGS_FILTER_FILE_COMMANDS, ui->chkFilterFileCommands->isChecked()); settings.setValue(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, ui->checkBoxReducePrecForLongLines->isChecked()); settings.setValue(SETTINGS_GRBL_LINE_BUFFER_LEN, ui->spinBoxGrblLineBufferSize->value()); + settings.setValue(SETTINGS_CHAR_SEND_DELAY_MS, ui->spinBoxCharSendDelay->value()); + + settings.setValue(SETTINGS_ENABLE_POS_REQ, ui->checkBoxPositionReportEnabled->isChecked()); + settings.setValue(SETTINGS_TYPE_POS_REQ, getPosReqType()); + settings.setValue(SETTINGS_POS_REQ_FREQ_SEC, ui->doubleSpinBoxPosRequestFreqSec->value()); connect(this, SIGNAL(setSettings()), parentWidget(), SLOT(setSettings())); @@ -125,3 +205,82 @@ void Options::toggleLimitZRate(bool limitZ) ui->doubleSpinZRateLimit->setEnabled(limitZ); ui->doubleSpinXYRate->setEnabled(limitZ); } + +void Options::toggleFourAxis(bool four) +{ + if (four) + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + } + else + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->groupBoxFourthAxis->setEnabled(false); + } + +} + +void Options::togglePosReporting(bool usePosReporting) +{ + if (usePosReporting) + { + ui->groupBox_ReqPos->setEnabled(true); + } + else + { + ui->groupBox_ReqPos->setEnabled(false); + } +} + +char Options::getFourthAxisType() +{ + char type = FOURTH_AXIS_A; + + if (ui->radioButtonFourthAxisA->isChecked()) + { + type = FOURTH_AXIS_A; + } + else + if (ui->radioButtonFourthAxisB->isChecked()) + { + type = FOURTH_AXIS_B; + } + else + if (ui->radioButtonFourthAxisC->isChecked()) + { + type = FOURTH_AXIS_C; + } +/// LETATARE + if (ui->radioButtonFourthAxisU->isChecked()) + { + type = FOURTH_AXIS_U; + } + else + if (ui->radioButtonFourthAxisV->isChecked()) + { + type = FOURTH_AXIS_V; + } + else + if (ui->radioButtonFourthAxisW->isChecked()) + { + type = FOURTH_AXIS_W; + } +/// <-- + return type; +} + +QString Options::getPosReqType() +{ + if (ui->radioButton_ReqAlways->isChecked()) + { + return PREQ_ALWAYS; + } + else if (ui->radioButton_ReqNotDuringManual->isChecked()) + { + return PREQ_NOT_WHEN_MANUAL; + } + return PREQ_ALWAYS_NO_IDLE_CHK; +} diff --git a/options.h b/GC-3.6.1-T1/src/options.h similarity index 74% rename from options.h rename to GC-3.6.1-T1/src/options.h index 022b9bd..c97ea62 100644 --- a/options.h +++ b/GC-3.6.1-T1/src/options.h @@ -18,6 +18,7 @@ #include "definitions.h" +#define SETTINGS_INVERSE_FOURTH "inverse.c"// leave as 'c' for backwards compat #define SETTINGS_INVERSE_X "inverse.x" #define SETTINGS_INVERSE_Y "inverse.y" #define SETTINGS_INVERSE_Z "inverse.z" @@ -25,11 +26,14 @@ #define SETTINGS_Z_JOG_RATE "zJogRate" #define SETTINGS_ENABLE_DEBUG_LOG "debugLog" #define SETTINGS_USE_AGGRESSIVE_PRELOAD "aggressivePreload" +#define SETTINGS_WAIT_FOR_JOG_TO_COMPLETE "waitForJogToComplete" #define SETTINGS_USE_MM_FOR_MANUAL_CMDS "useMMForManualCommands" #define SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ "absCoordForManualAfterAxisAdj" #define SETTINGS_Z_RATE_LIMIT "zRateLimit" #define SETTINGS_Z_RATE_LIMIT_AMOUNT "zRateLimitAmount" #define SETTINGS_XY_RATE_AMOUNT "xyRateAmount" +#define SETTINGS_FOUR_AXIS_USE "fourAxis" +#define SETTINGS_FOUR_AXIS_TYPE "fourAxisType" #define SETTINGS_FILE_OPEN_DIALOG_STATE "fileopendialogstate" #define SETTINGS_NAME_FILTER "namefilter" @@ -42,6 +46,12 @@ #define SETTINGS_FILTER_FILE_COMMANDS "filterFileCommands" #define SETTINGS_REDUCE_PREC_FOR_LONG_LINES "reducePrecisionForLongLines" #define SETTINGS_GRBL_LINE_BUFFER_LEN "grblLineBufferLen" +#define SETTINGS_CHAR_SEND_DELAY_MS "charSendDelayMs" +#define SETTINGS_JOG_STEP "jogStep" + +#define SETTINGS_ENABLE_POS_REQ "positionRequest" +#define SETTINGS_TYPE_POS_REQ "posRequestType" +#define SETTINGS_POS_REQ_FREQ_SEC "posReqFreqSec" namespace Ui { @@ -51,7 +61,7 @@ class Options; class Options : public QDialog { Q_OBJECT - + public: explicit Options(QWidget *parent = 0); ~Options(); @@ -63,7 +73,12 @@ class Options : public QDialog private slots: void toggleUseMm(bool useMm); void toggleLimitZRate(bool limitZ); + void toggleFourAxis(bool four); + void togglePosReporting(bool usePosReporting); +private: + char getFourthAxisType(); + QString getPosReqType(); private: Ui::Options *ui; //variables diff --git a/GC-3.6.1-T1/src/options.ui b/GC-3.6.1-T1/src/options.ui new file mode 100644 index 0000000..e4edec0 --- /dev/null +++ b/GC-3.6.1-T1/src/options.ui @@ -0,0 +1,711 @@ + + + Options + + + + 0 + 0 + 521 + 317 + + + + Options + + + + + 10 + 10 + 501 + 261 + + + + 0 + + + + General + + + + + 10 + 146 + 451 + 71 + + + + + + + Z-Jog Rate (inches or mm/min) + + + + + + + Seconds to Wait for Response + + + + + + + 1 + + + 1000 + + + 60 + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 260.000000000000000 + + + + + + + + + 10 + 10 + 451 + 121 + + + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + + + Use aggressive preload strategy for Grbl + + + + + + + false + + + Wait for each jog/manual command to complete (future feature) + + + + + + + Write debugging log to home folder (requires restart) + + + + + + + + + Filtering + + + + + 10 + 10 + 471 + 81 + + + + Z Rate Limiting + + + + + 20 + 20 + 451 + 53 + + + + + + + Limit Z Rate + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 100.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Z-Rate Limit (inches or mm/min) + + + + + + + XY Rate (inches or mm/min) + + + + + + + 2 + + + 0.100000000000000 + + + 999999.989999999990687 + + + 2000.000000000000000 + + + + + + + + + + 10 + 200 + 261 + 24 + + + + + + + Character send delay ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 100 + 461 + 61 + + + + Command Filtering + + + + + 30 + 20 + 431 + 17 + + + + Filter file commands before sending + + + + + + 30 + 40 + 431 + 17 + + + + Selectively reduce precision for excessively long lines + + + + + + + 10 + 170 + 261 + 24 + + + + + + + Grbl Line Buffer Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 270 + 200 + 50 + 22 + + + + 20 + + + 10 + + + + + + 270 + 170 + 50 + 22 + + + + 50 + + + + + + Axis + + + + + 10 + 111 + 451 + 60 + + + + Invert Axis + + + + + 20 + 20 + 431 + 31 + + + + + + + X Axis + + + + + + + Y Axis + + + + + + + Z Axis + + + + + + + Fourth Axis + + + + + + + + + + 10 + 41 + 451 + 51 + + + + Selecting the Fourth axis + + + + + 10 + 22 + 50 + 17 + + + + A + + + true + + + + + + 80 + 22 + 50 + 17 + + + + B + + + + + + 150 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + C + + + + + + 240 + 20 + 50 + 21 + + + + Qt::PreventContextMenu + + + U + + + + + + 310 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + V + + + + + + 380 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + W + + + + + + + 10 + 11 + 421 + 17 + + + + Enable 4-axis mode + + + + + + Display + + + + + 10 + 10 + 481 + 141 + + + + + + + Enable position request and report + + + + + + + Position Request + + + + + 10 + 20 + 461 + 93 + + + + + + + Always Request (most reliable/slightly slower jogging) + + + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + + + Not during manual control (no position update during jog/manual) + + + + + + + + + Request frequency (seconds) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0.500000000000000 + + + 10.000000000000000 + + + 0.500000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + + + + + 320 + 280 + 191 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + Options + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Options + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/pointitem.cpp b/GC-3.6.1-T1/src/pointitem.cpp similarity index 67% rename from pointitem.cpp rename to GC-3.6.1-T1/src/pointitem.cpp index 098efc2..c0a3db9 100644 --- a/pointitem.cpp +++ b/GC-3.6.1-T1/src/pointitem.cpp @@ -5,17 +5,15 @@ PointItem::PointItem(double x1, double y1) { } -#pragma GCC diagnostic ignored "-Wunused-parameter" push void PointItem::moveToFirst(QPainterPath& path) { + Q_UNUSED(path); } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop -#pragma GCC diagnostic ignored "-Wunused-parameter" push void PointItem::addToPath(QPainterPath& path) { + Q_UNUSED(path); } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop PosItem PointItem::computeExtents() { diff --git a/pointitem.h b/GC-3.6.1-T1/src/pointitem.h similarity index 100% rename from pointitem.h rename to GC-3.6.1-T1/src/pointitem.h diff --git a/positem.cpp b/GC-3.6.1-T1/src/positem.cpp similarity index 100% rename from positem.cpp rename to GC-3.6.1-T1/src/positem.cpp diff --git a/positem.h b/GC-3.6.1-T1/src/positem.h similarity index 100% rename from positem.h rename to GC-3.6.1-T1/src/positem.h diff --git a/GC-3.6.1-T1/src/qrc_GrblController.cpp b/GC-3.6.1-T1/src/qrc_GrblController.cpp new file mode 100644 index 0000000..d1c153c --- /dev/null +++ b/GC-3.6.1-T1/src/qrc_GrblController.cpp @@ -0,0 +1,572 @@ +/**************************************************************************** +** Resource object code +** +** Created: Sun 1. Jun 21:06:43 2014 +** by: The Resource Compiler for Qt version 4.7.3 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/down.PNG + 0x0,0x0,0x1,0x78, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54, + 0x45,0x0,0x0,0x0,0x66,0x66,0x66,0x20,0x20,0x20,0xc0,0xc0,0xc0,0x99,0x99,0x99, + 0x40,0x40,0x40,0xe0,0xe0,0xe0,0x10,0x10,0x10,0x80,0x80,0x80,0xb0,0xb0,0xb0,0x50, + 0x50,0x50,0x33,0x33,0x33,0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff, + 0xff,0xf,0x55,0x2f,0xf,0x0,0x0,0x0,0x10,0x74,0x52,0x4e,0x53,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0xe0,0x23,0x5d, + 0x19,0x0,0x0,0x0,0x9e,0x49,0x44,0x41,0x54,0x38,0x4f,0xd5,0x92,0x49,0x16,0xc4, + 0x20,0x8,0x5,0xc9,0xa4,0x19,0x1f,0xf7,0xbf,0x6d,0x1b,0xc,0xfa,0x55,0x7c,0xd9, + 0xa6,0x5d,0x42,0x49,0x21,0x48,0xfc,0x72,0xe8,0x5f,0x80,0x9d,0x3a,0x67,0xf,0x2f, + 0x90,0x57,0x78,0x1b,0xf0,0x77,0x4e,0x80,0xd9,0x6,0xe6,0x4,0xf0,0x62,0x11,0x8b, + 0x8c,0x28,0xe,0xca,0x19,0x12,0xef,0x0,0xb0,0x24,0x22,0xd0,0xa,0xdc,0x4a,0xa2, + 0x20,0x3,0xae,0xee,0x22,0xa,0x32,0xc0,0x6b,0x49,0xac,0xba,0xc4,0xbc,0xcd,0x3, + 0x89,0x23,0x2d,0x39,0x3,0x27,0x2,0xa7,0x1,0xa0,0x24,0x9,0xa0,0x87,0x70,0x65, + 0xd4,0x1a,0x63,0xba,0x5f,0x2,0x93,0x2,0x53,0x7,0xe0,0x2b,0x12,0x17,0xe4,0x9f, + 0x51,0x6b,0x44,0x24,0x28,0x28,0x15,0xcc,0x22,0x41,0x41,0xd,0xf0,0x40,0x34,0xa0, + 0xa0,0x1,0xd8,0xcb,0x2f,0xe9,0x35,0x19,0xe2,0xdb,0xf6,0x2,0x54,0xe9,0x56,0xf1, + 0x49,0xe0,0x7,0xe1,0x8f,0x2c,0xc1,0x52,0x87,0x91,0xd,0x0,0x0,0x0,0x0,0x49, + 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/up.PNG + 0x0,0x0,0x1,0x7c, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54, + 0x45,0x0,0x0,0x0,0x66,0x66,0x66,0x20,0x20,0x20,0xbf,0xbf,0xbf,0x99,0x99,0x99, + 0x40,0x40,0x40,0xdf,0xdf,0xdf,0x10,0x10,0x10,0x80,0x80,0x80,0xaf,0xaf,0xaf,0x50, + 0x50,0x50,0x33,0x33,0x33,0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff, + 0xff,0x43,0x17,0xab,0xb7,0x0,0x0,0x0,0x10,0x74,0x52,0x4e,0x53,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0xe0,0x23,0x5d, + 0x19,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x38,0x4f,0xd5,0xd3,0xc9,0xe,0x83, + 0x30,0xc,0x45,0xd1,0xc7,0xe4,0x30,0xaa,0xff,0xff,0xb7,0xad,0xed,0xc,0xb6,0x83, + 0xe8,0x9a,0xac,0x10,0x39,0xe4,0x6,0x50,0xf0,0xf9,0x33,0xf0,0x46,0xb0,0x6d,0x61, + 0xd7,0xe1,0x2d,0x28,0x25,0xf2,0x22,0x80,0x1,0x18,0x9e,0xc0,0x84,0xdf,0x98,0x9c, + 0x70,0x2b,0xd0,0xc8,0x60,0x74,0x11,0x7,0x2e,0x9e,0x7,0x2e,0xbb,0x84,0x5,0x12, + 0x88,0x11,0xb,0x24,0x20,0x11,0xb3,0x84,0x1,0x6b,0x99,0x7,0xd6,0x26,0x1a,0x38, + 0xdb,0x3c,0x70,0x56,0xd1,0xc0,0x61,0xc1,0xd1,0x3,0x13,0x60,0x59,0x23,0x65,0x5, + 0xb2,0xcf,0xf3,0x75,0xf9,0x18,0x5,0x2c,0x11,0x2c,0x39,0x92,0xc1,0x1c,0xe7,0x81, + 0x59,0x85,0x2,0x4a,0x3d,0xc8,0xbf,0x55,0x41,0x17,0x60,0xaf,0x11,0x1,0x37,0x1, + 0x16,0x12,0x61,0x70,0x17,0x60,0x20,0x11,0x6,0x7b,0xbf,0x1,0xbd,0xb3,0xd7,0x4d, + 0x3e,0x9c,0x9e,0x57,0x9c,0xac,0x2f,0x4d,0x47,0x2c,0x8b,0xf7,0xb1,0xd7,0xd3,0x0, + 0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/right.PNG + 0x0,0x0,0x1,0x9e, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x60,0x50,0x4c,0x54, + 0x45,0x0,0x0,0x0,0x66,0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f, + 0x40,0x40,0x40,0xdf,0xdf,0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50, + 0x50,0x50,0x33,0x33,0x33,0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80, + 0x80,0x99,0x99,0x99,0x70,0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x21,0x2b,0xd9,0x38,0x0,0x0,0x0,0x20,0x74,0x52,0x4e,0x53,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4e,0xd6,0x1c, + 0x31,0x0,0x0,0x0,0x84,0x49,0x44,0x41,0x54,0x38,0x4f,0xad,0x93,0xc9,0xe,0x80, + 0x20,0xc,0x44,0x7,0x37,0x14,0x8d,0x6,0xff,0xff,0x63,0x3d,0x28,0xb1,0x74,0x9, + 0x81,0xc0,0xf9,0xf1,0x28,0xed,0x14,0x77,0xe1,0xa0,0x17,0x10,0x16,0xcb,0xf4,0x3d, + 0x1,0x7f,0x1a,0x44,0x2,0x80,0x59,0x97,0xfc,0x0,0xfc,0xa4,0x49,0x8,0xa0,0x4b, + 0x32,0x0,0x58,0x85,0x84,0x1,0xd8,0xf,0x86,0x70,0x40,0x48,0x24,0x80,0x71,0xa0, + 0x12,0x5,0x0,0x22,0xf9,0xb1,0xa,0x50,0x89,0xe,0x0,0x2e,0x49,0x2c,0x0,0x7e, + 0x7b,0x2b,0x69,0x6,0x5c,0xfa,0x49,0x5b,0x91,0x91,0x34,0xa2,0xa1,0x51,0x57,0x3e, + 0x8c,0xda,0x61,0xb1,0xeb,0xbc,0xf,0x5a,0xea,0x2a,0x22,0x57,0x8,0x6d,0x29,0xf6, + 0xc1,0xdc,0xc0,0x6e,0xbb,0x69,0xef,0xf8,0x3,0x8,0x8e,0x35,0x85,0x8,0x3c,0xe2, + 0xc9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/zapmaker-logo-130.png + 0x0,0x0,0xb,0x59, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x82,0x0,0x0,0x0,0x21,0x8,0x6,0x0,0x0,0x0,0x15,0x8b,0x73,0xbd, + 0x0,0x0,0x0,0x4,0x73,0x42,0x49,0x54,0x8,0x8,0x8,0x8,0x7c,0x8,0x64,0x88, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0x8,0xd2,0x0,0x0,0x8,0xd2, + 0x1,0x3b,0x61,0x13,0xc2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x53,0x6f,0x66, + 0x74,0x77,0x61,0x72,0x65,0x0,0x77,0x77,0x77,0x2e,0x69,0x6e,0x6b,0x73,0x63,0x61, + 0x70,0x65,0x2e,0x6f,0x72,0x67,0x9b,0xee,0x3c,0x1a,0x0,0x0,0xa,0xd6,0x49,0x44, + 0x41,0x54,0x78,0x9c,0xed,0x9c,0x7f,0x8c,0x55,0xc5,0x15,0xc7,0x3f,0xf7,0xbe,0xb7, + 0xb,0x28,0xa,0x28,0xb6,0xfe,0xe8,0x80,0x45,0x6f,0x2b,0xf5,0x47,0x63,0x6c,0xf1, + 0x57,0x13,0x69,0xd5,0xa8,0x55,0xa1,0xa2,0x2e,0xfe,0x2,0x8d,0xb4,0x12,0xc4,0x5f, + 0x4d,0x6a,0x63,0x8b,0x51,0xd7,0x58,0xab,0xad,0x3f,0x4a,0x15,0x1b,0x4c,0xc4,0x4a, + 0x15,0xe3,0x4a,0x68,0xd5,0xa6,0xd5,0xa6,0x8d,0xc6,0x56,0xd4,0x54,0xab,0xb6,0x58, + 0xad,0xd3,0x58,0xe1,0x88,0x58,0x40,0x44,0x5c,0x7e,0xec,0xbe,0xfb,0xde,0xf4,0x8f, + 0x99,0xbb,0x3b,0x3b,0x6f,0xde,0xb2,0x4b,0x90,0x45,0xca,0x37,0xb9,0x79,0x77,0xe6, + 0xcc,0x99,0x39,0x33,0xf7,0xcc,0x99,0x33,0x67,0x66,0x37,0x31,0xc6,0xd0,0x8,0x33, + 0x5b,0x5a,0xbe,0x96,0xd6,0x6a,0xb,0x80,0xcf,0x1,0x6,0xa8,0xc5,0x7e,0xd,0xd4, + 0x92,0x20,0x3f,0x31,0xc6,0x98,0x24,0xa9,0x91,0x24,0x6,0x63,0x6a,0x8d,0x78,0xfd, + 0x3a,0x8a,0x76,0x13,0x48,0xba,0x5f,0xfb,0xf4,0x6b,0xc,0xdc,0x76,0xf7,0xc2,0x85, + 0xbf,0x68,0xd8,0x99,0x9d,0xe8,0x15,0x49,0x4c,0x11,0x5a,0x5b,0x5b,0xd3,0xd5,0x4b, + 0x96,0xcc,0xc2,0x98,0xeb,0x81,0xd2,0xb6,0x17,0xab,0x5f,0x58,0x9,0x4c,0xbd,0x6b, + 0xe1,0xc2,0xa7,0x6,0x5a,0x90,0x4f,0x33,0xca,0x61,0xc6,0xe5,0x13,0x27,0xee,0x4b, + 0x53,0xd3,0x43,0xc0,0xf8,0x6d,0x2f,0x4e,0xbf,0xf1,0xc7,0x5a,0x9a,0x4e,0x99,0xd3, + 0xd6,0xf6,0xfe,0x40,0xb,0xf2,0x69,0x47,0xf,0x8b,0x70,0xc5,0x99,0x67,0x9e,0xa, + 0xfc,0xd2,0x24,0xc9,0xc8,0x81,0x13,0xa9,0x4f,0xc8,0x8d,0x31,0xd7,0xcd,0x59,0xb4, + 0xe8,0x16,0xd3,0xdb,0xda,0xb6,0x13,0x7d,0x46,0x62,0x8c,0xa1,0xb5,0xa5,0xa5,0xf9, + 0x3,0x63,0x6e,0x35,0xc6,0x5c,0x35,0xd0,0x2,0xf5,0x1,0x4b,0x4d,0x9a,0x9e,0x7b, + 0x77,0x5b,0xdb,0xf3,0x3,0x2d,0xc8,0x8e,0x84,0x32,0xc0,0xfb,0x79,0x3e,0xbc,0xa9, + 0x5c,0x7e,0xb8,0x56,0xab,0x2d,0x48,0x93,0xc4,0xa4,0x69,0x6a,0x4c,0xad,0x56,0xab, + 0xa6,0xa9,0x29,0xe5,0xb9,0xc9,0xd3,0xd4,0x94,0xd2,0xd4,0xa4,0x79,0x6e,0x4c,0xb9, + 0x5c,0xab,0xe6,0xb9,0x49,0x5d,0x5e,0xee,0xf2,0x4a,0x95,0x8a,0xc9,0x4b,0x25,0x53, + 0x4a,0x53,0x53,0xae,0x54,0x4c,0x25,0x4d,0x8d,0xa9,0x56,0x6b,0xa5,0x52,0xc9,0x54, + 0x4a,0x25,0x53,0xee,0xe8,0x30,0xe5,0x72,0xd9,0x74,0x96,0x4a,0x6,0xa0,0xb9,0x5a, + 0x4d,0x0,0xf2,0x3c,0xb7,0xbf,0x83,0x6,0x25,0x0,0x4d,0x2e,0xbf,0xea,0x7e,0x9b, + 0x9a,0x9b,0x2d,0xdd,0xa5,0x2b,0x95,0xca,0xaa,0xb9,0x8f,0x3f,0xbe,0x61,0x5b,0xf, + 0xd4,0x8e,0x8e,0xa8,0xb3,0xb8,0x13,0xff,0x7f,0x28,0x3,0x64,0x4a,0x8d,0x2,0x76, + 0xd9,0x2,0xfe,0x8d,0x5a,0x64,0xe9,0xd6,0x15,0x69,0xc7,0x43,0xa6,0xd4,0x8,0xe0, + 0xb3,0x41,0xf6,0x1a,0x2d,0xb2,0x72,0x20,0xe4,0x89,0xa1,0xd8,0x35,0xdc,0xf,0x7c, + 0x63,0xb,0xf8,0x17,0x3,0xc7,0x6e,0x3d,0x71,0x76,0x58,0x4c,0x1,0x66,0x7,0x79, + 0xb7,0x2,0xd7,0xc,0x80,0x2c,0x51,0xa4,0xee,0xb7,0x79,0xb,0xf9,0xd7,0x6f,0x2d, + 0x41,0x76,0x70,0xa4,0x91,0xbc,0xb5,0xdb,0x5c,0x8a,0x5e,0x50,0x8,0xb8,0xeb,0x16, + 0xf2,0xef,0x54,0x84,0xbe,0x21,0xa6,0x8,0x1f,0x6d,0x73,0x29,0x7a,0x41,0xb1,0x34, + 0xfc,0x1a,0x78,0x1a,0xd8,0x4,0x74,0x0,0x9d,0x5e,0x99,0xfd,0x81,0xe9,0xd,0xf8, + 0x97,0xf5,0x56,0x79,0xa6,0xd4,0x20,0x60,0x4,0x30,0x4,0x58,0xa1,0x45,0x36,0xf5, + 0x45,0xa8,0x4c,0xa9,0x66,0x60,0x37,0xac,0x82,0xa6,0x8e,0xb7,0xa3,0x2f,0xbc,0xd, + 0xea,0x2b,0x3,0xfb,0x61,0x43,0xda,0x2b,0xb4,0x48,0x25,0xa0,0xa7,0xc0,0xde,0xc0, + 0x26,0x2d,0xb2,0xa6,0x1f,0xf5,0xe,0xc1,0xf6,0xaf,0xc9,0xd5,0xdb,0xd9,0xa0,0xe8, + 0x56,0xb7,0x8,0x99,0x52,0x83,0x81,0x51,0xc0,0x87,0x5a,0x64,0xd5,0x16,0xd6,0x31, + 0x1c,0xd8,0x1d,0x58,0xde,0xeb,0xae,0x21,0x53,0x6a,0x18,0xd6,0xf,0xf8,0x52,0x84, + 0xfc,0x24,0xf0,0x2d,0xff,0x3,0x65,0x4a,0x9d,0xf,0x1c,0x7,0x1c,0xa,0x1c,0x8c, + 0xfd,0x98,0x3e,0x56,0x2,0x8f,0x1,0xb3,0x7c,0xe1,0x33,0xa5,0xbe,0x1,0x5c,0x8, + 0x1c,0x0,0x8c,0x1,0xf6,0x9,0xf8,0xc,0xb0,0xa,0x78,0x1b,0xab,0xb4,0xf7,0x68, + 0x91,0xf6,0x40,0xd6,0x3b,0x81,0x13,0x81,0x2a,0xf6,0xc,0xa2,0xc,0x8c,0x3,0x7e, + 0xec,0xea,0x2e,0x64,0x69,0xc7,0xfa,0x44,0xdf,0x73,0x83,0x70,0x33,0x70,0x1e,0xdd, + 0x56,0x71,0x35,0x70,0xf,0x70,0x53,0x44,0x61,0x66,0xb8,0x3a,0xf,0x5,0xc6,0xd2, + 0xd3,0xc1,0x36,0xc0,0xfb,0xc0,0x43,0xc0,0x8d,0x5a,0xe4,0x63,0x8f,0xef,0x1a,0x27, + 0x87,0x8f,0x6f,0x6a,0x91,0xdf,0x3b,0xfa,0x21,0xc0,0x23,0xd8,0xf3,0x96,0x2a,0x56, + 0x71,0x12,0x60,0xaa,0x16,0x79,0xc5,0xab,0x67,0x4f,0xe0,0x87,0xc0,0xd9,0xd8,0xf3, + 0x9f,0xe2,0xac,0x65,0x3d,0xf0,0x32,0x70,0x83,0x16,0x79,0x3a,0x90,0xf9,0x36,0xe0, + 0x64,0x6f,0x5c,0x4a,0xc0,0x44,0xe0,0x16,0xe0,0xc,0xd7,0xd6,0xe9,0xd,0x15,0xc1, + 0xcd,0xca,0xdf,0x1,0xc7,0x47,0xc8,0x2f,0x0,0xc7,0x6b,0x91,0xd,0x1,0xcf,0x72, + 0x60,0xdf,0x68,0x85,0x3d,0xb1,0x16,0xf8,0xbc,0x16,0x59,0xeb,0xf8,0x6e,0x0,0xae, + 0xef,0x3,0x5f,0x81,0x37,0x81,0xf1,0x5a,0xe4,0xbf,0x5e,0xdb,0x8b,0xb0,0x1d,0x2b, + 0x90,0x3,0xcf,0x0,0x27,0x34,0xa8,0xe3,0x1,0xe0,0x30,0xe0,0xf0,0x6,0xf4,0x7, + 0xb5,0xc8,0x14,0xaf,0xfe,0x32,0xb0,0x91,0x48,0x58,0x3e,0x82,0x65,0xc0,0x1,0x5a, + 0x24,0x77,0xbc,0x37,0x50,0xdf,0xbf,0x63,0xb5,0xc8,0xe2,0x4c,0xa9,0x12,0x76,0xb2, + 0x8d,0xb,0xe8,0x37,0x6b,0x91,0x59,0x5e,0xfb,0x93,0xb0,0xa,0xbc,0xfb,0x66,0xda, + 0x7e,0x48,0x8b,0x5c,0xe0,0xf1,0x3d,0xc,0x9c,0x13,0x94,0x79,0x3,0xab,0xc8,0x5, + 0xce,0x8a,0x99,0xac,0xc2,0x54,0xfe,0x8a,0xb8,0x12,0xfc,0xb,0x38,0x2d,0xa2,0x4, + 0xbb,0xd1,0x3d,0x93,0x3f,0x2,0xfe,0xa,0xb4,0x1,0x4f,0x60,0x7,0xd0,0xc7,0x70, + 0x60,0x82,0x97,0xee,0xaf,0xb3,0x7a,0x10,0xf0,0xd3,0x20,0x6f,0x50,0x90,0x2e,0xd3, + 0x58,0x9,0xc0,0x5a,0x89,0x46,0x4a,0x0,0x30,0x21,0x53,0xaa,0xc9,0x4b,0x8f,0xa1, + 0x5b,0x9,0x3e,0xc0,0x4e,0x86,0x87,0xb1,0x96,0xb1,0x12,0xf0,0x8e,0xa2,0xe7,0x59, + 0xcd,0x90,0x48,0xfd,0xc5,0xd2,0x70,0x15,0xf5,0x4a,0xf0,0xc,0x70,0x5d,0x91,0xc8, + 0x94,0x52,0xc0,0x3c,0x7a,0x2a,0x41,0xe,0xfc,0xd,0x8,0x97,0xb2,0xf3,0x33,0xa5, + 0xa6,0x46,0xda,0xf3,0x31,0x36,0x48,0xf,0x89,0x2a,0x2,0x70,0x37,0xd0,0x12,0xc9, + 0x7f,0xf,0x38,0x49,0x8b,0x7c,0x10,0xa1,0xed,0x7,0xdc,0x85,0xdd,0x86,0x8e,0xd4, + 0x22,0xe3,0xb4,0xc8,0x64,0x2d,0x32,0x1,0xb8,0x33,0x52,0xfe,0x38,0xef,0xbd,0x29, + 0x42,0xff,0xb,0xd6,0x6c,0x5f,0xd,0xfc,0x26,0x42,0x9f,0x92,0x29,0xe5,0x6f,0x5d, + 0x87,0x46,0xca,0x0,0x2c,0xa5,0x7e,0xb0,0x7c,0xbc,0x8d,0xfd,0xb0,0x21,0x76,0x7, + 0xe,0xf4,0xd2,0x7b,0x1,0x3f,0x1,0x8e,0x1,0xf6,0xd2,0x22,0x47,0x6b,0x91,0xf3, + 0xb4,0xc8,0x29,0xc0,0x82,0x8,0xbf,0xdf,0xbf,0xc1,0x11,0xfa,0x47,0x99,0x52,0x7, + 0x1,0x37,0x5,0xf9,0x2b,0x81,0x73,0xb5,0x48,0xd5,0xcb,0x9b,0x7,0xc,0xf3,0xd2, + 0xed,0xc0,0x38,0x2d,0x72,0x4,0x30,0x1a,0xf8,0x7b,0x50,0x47,0x6b,0xa4,0xbd,0x46, + 0x30,0xc0,0xd0,0x3a,0x33,0x97,0x29,0xd5,0xa,0xcc,0x88,0x9,0xe,0x9c,0xdc,0x28, + 0x80,0xa4,0x45,0xde,0x4,0xae,0xc,0xea,0x1a,0x85,0x5d,0xb7,0x2f,0x88,0xb0,0xf8, + 0x8e,0x63,0x4c,0x11,0xae,0xd1,0x22,0xcf,0xb9,0xf7,0xdb,0x32,0xa5,0x1e,0x0,0x42, + 0x4d,0x9f,0x8,0x14,0x65,0x62,0x3b,0x9f,0x27,0xb4,0xc8,0x84,0x4c,0xa9,0x7d,0x81, + 0x77,0x22,0xed,0x3c,0xa,0x4c,0xc6,0xae,0xb7,0x4b,0xe9,0x5e,0x73,0xb,0x74,0xf9, + 0x3f,0x4e,0x96,0xe7,0x7c,0x62,0xa6,0xd4,0x81,0xc0,0x29,0xc0,0x69,0x91,0xb6,0xfd, + 0xfe,0xc5,0x64,0xdb,0x84,0xf5,0x77,0x7c,0x25,0x31,0x58,0xbf,0xa0,0xeb,0x34,0x35, + 0x53,0x6a,0x2c,0xf5,0x96,0x6d,0x7e,0xe1,0x3b,0x68,0x91,0xf6,0x4c,0xa9,0xc7,0xb0, + 0xcb,0x5c,0x81,0xfd,0x33,0xa5,0x86,0xbb,0xa5,0x37,0x76,0x8d,0xa0,0x13,0xf8,0x1, + 0x30,0x1f,0xf8,0x18,0x68,0xee,0xa1,0x8,0x99,0x52,0x97,0xe1,0x99,0x24,0xf,0x1d, + 0xc0,0x4,0x2d,0xf2,0x8f,0x8,0xcd,0xe7,0x1f,0x4,0x9c,0x89,0xfd,0xf8,0xe3,0xb1, + 0x3b,0x8e,0x46,0xf0,0xb7,0x4f,0xb1,0xa5,0x61,0x75,0x90,0x7e,0x90,0x7a,0x45,0x38, + 0xd8,0x7b,0x8f,0x59,0x84,0xbb,0x0,0xb4,0xc8,0x7b,0x99,0x52,0x2b,0xb0,0x26,0xdb, + 0xc7,0x1d,0x5a,0xc4,0x0,0x92,0x29,0xf5,0x2e,0xa0,0x2,0x7a,0x8f,0xed,0x71,0xa6, + 0xd4,0x50,0xac,0xa5,0x3c,0x1e,0xf8,0x3a,0xf5,0x4e,0xad,0xf,0xbf,0x7f,0xa1,0xd3, + 0xc,0x70,0x29,0xf0,0xd5,0x20,0x6f,0xb6,0x16,0x9,0xef,0x55,0xc4,0x2,0x7d,0xe7, + 0x64,0x4a,0x9d,0xea,0xa5,0x63,0x7e,0xc3,0x18,0xec,0xd2,0x11,0x8b,0x18,0xdf,0xae, + 0x45,0xee,0xf0,0xd2,0x1d,0x5d,0x8a,0x90,0x29,0x75,0xe,0xf5,0xd1,0x2f,0xb0,0x9e, + 0xec,0x79,0x5a,0xe4,0xd9,0x8,0xad,0xb,0x8e,0xff,0x67,0xd4,0x87,0x52,0x1b,0xc1, + 0x1f,0xa8,0x70,0x7d,0x87,0xfa,0x75,0x77,0x71,0xac,0x59,0xef,0x3d,0xa6,0x8,0x2f, + 0x7a,0xef,0xa1,0x57,0x5c,0x3,0x5e,0xeb,0x85,0xe,0xb0,0xae,0xab,0x21,0xa5,0x66, + 0x62,0xcd,0xf8,0xf0,0x48,0xb9,0x18,0xfc,0xfe,0xc5,0x3e,0xd4,0xab,0x91,0xbc,0x50, + 0x51,0xa1,0x5e,0x39,0x1,0xf6,0x70,0x4f,0x6f,0x28,0x1c,0xe9,0x98,0x22,0x3c,0x18, + 0x66,0xa4,0x0,0x99,0x52,0x27,0x62,0xbd,0xe8,0x98,0xcf,0x70,0x99,0x16,0x59,0xd4, + 0x5b,0x8b,0x99,0x52,0x13,0xb0,0xeb,0x64,0xa8,0x4,0x55,0xe0,0x59,0xac,0x53,0x15, + 0xc2,0xdf,0xfe,0xc5,0x3e,0xe2,0x17,0x82,0xf4,0x17,0x23,0x65,0xfc,0xb,0x29,0xe1, + 0xac,0xab,0x68,0x91,0x75,0x5e,0x3a,0x74,0xd8,0xd6,0x69,0x11,0xdf,0x89,0xd,0x7, + 0x2c,0x2f,0xe8,0x99,0x52,0x97,0x60,0xfd,0xa6,0x50,0x9,0x3a,0x81,0xa7,0x80,0xc7, + 0x23,0xb2,0xf9,0xfd,0xb,0x15,0xa1,0x53,0x8b,0x3c,0x1,0xfc,0x39,0xc8,0x9f,0x94, + 0x29,0x15,0x3a,0xe8,0xb1,0xf8,0xc9,0x74,0xac,0xcf,0x30,0xcc,0xd5,0xbd,0x1b,0x76, + 0xc,0x77,0x75,0xfd,0x18,0xa2,0x45,0x96,0xbb,0xb2,0xe1,0xb2,0x54,0x1,0x74,0x58, + 0x61,0x9a,0x29,0x75,0x14,0xb0,0x88,0xb8,0x79,0xbe,0x51,0x8b,0xf4,0xe5,0x1e,0xe0, + 0xcd,0xd4,0xaf,0xaf,0x3f,0x2,0xf6,0xd6,0x22,0xc7,0x1,0xb1,0xbb,0x3,0xbe,0xd9, + 0x8d,0x99,0xce,0xc9,0x41,0xfa,0x92,0x48,0x19,0xd,0x5d,0xbb,0x9c,0xb0,0x8e,0x30, + 0x60,0x13,0x2a,0x42,0xfb,0x66,0xe8,0xeb,0x5c,0xdd,0x9,0xb6,0x7f,0x3e,0x72,0x6c, + 0x1c,0xe2,0x33,0x5a,0xe4,0x64,0xe0,0x9f,0x11,0xd9,0xfc,0xfe,0x85,0x8a,0x50,0x7c, + 0xdc,0xef,0x47,0xf8,0x66,0xbb,0xad,0x6a,0x81,0x7f,0x47,0xca,0x7c,0x59,0x8b,0xac, + 0x73,0xcf,0xc7,0x5a,0xa4,0x5d,0x8b,0xac,0xd7,0x22,0x1b,0xb4,0xc8,0xc6,0x20,0x70, + 0x37,0x22,0xe0,0x5d,0x15,0xc6,0x47,0xc0,0x6e,0x87,0x1e,0x20,0x3e,0x23,0x2b,0xc0, + 0x91,0x99,0x52,0x4f,0xba,0x74,0x82,0x35,0xe1,0xc5,0xb3,0x2b,0xf0,0x15,0xec,0x80, + 0x86,0xb3,0xf7,0x75,0x2d,0x72,0x6d,0x2f,0xc2,0xc0,0xe6,0x15,0xe1,0xa2,0x4c,0xa9, + 0x1c,0x3b,0xe3,0x4e,0x20,0x1e,0xdd,0x2c,0x64,0x1b,0x4a,0xbd,0x22,0xfa,0x66,0x3d, + 0xa1,0x7e,0x66,0xac,0xf7,0xe8,0x29,0xf5,0x16,0xa1,0x50,0x94,0xbd,0x80,0x3d,0x3, + 0xda,0xd3,0x5a,0xe4,0x76,0x2f,0xbd,0xb9,0xfe,0x45,0x15,0x41,0x8b,0xbc,0x90,0x29, + 0xb5,0x10,0x38,0xcb,0xa3,0x1d,0x8c,0xf5,0x1f,0x7e,0xee,0xd2,0xcf,0x62,0x15,0xcf, + 0x57,0x8e,0x19,0x99,0x52,0x1d,0xd8,0xe0,0xdc,0x62,0xac,0x25,0x1f,0x8d,0xdd,0xa9, + 0x8c,0x7,0x2e,0x2c,0x62,0x18,0x11,0xd9,0xa2,0x11,0xda,0x32,0x3d,0xb7,0x25,0x3e, + 0x9a,0x80,0x93,0x1a,0xd0,0xa,0x6c,0xd4,0x22,0x26,0x53,0xea,0x65,0xe0,0x28,0xbf, + 0x33,0x99,0x52,0xf7,0x2,0x6f,0x61,0x23,0x5e,0x5b,0xa2,0x8,0x0,0xdf,0x76,0x4f, + 0xc,0xaf,0x1,0xb,0xdd,0x7b,0xac,0xf,0xbe,0xd9,0x1f,0x4e,0xfd,0xb2,0xe7,0xcf, + 0x9a,0x61,0xd4,0x2b,0xd2,0x6,0x0,0x2d,0xb2,0x32,0x53,0x6a,0x19,0x3d,0xd7,0xef, + 0xf1,0x99,0x52,0xb3,0x81,0x15,0xc0,0x1f,0xd8,0x7c,0xff,0xc2,0x25,0xc5,0xff,0x18, + 0xb3,0xb0,0x81,0x30,0xdf,0xbb,0x6f,0xcd,0x94,0x5a,0xa0,0x45,0x56,0x6b,0x91,0xa5, + 0x6e,0xc7,0x34,0xcd,0xa3,0x27,0xc0,0x77,0xdd,0xd3,0x49,0x4f,0x6b,0xae,0x3d,0x25, + 0x88,0xb5,0x1d,0xd,0xf3,0xc7,0x66,0x42,0x5f,0xb1,0xc9,0x6b,0xf0,0xfe,0x8,0xfd, + 0x3b,0xd8,0xa0,0xcf,0x2a,0xfa,0xaf,0x8,0x1d,0x34,0x10,0xd8,0x61,0x2d,0x70,0xa9, + 0xf3,0xf8,0x21,0xee,0x8c,0xf9,0xfc,0xe1,0x8c,0xe,0xe9,0x31,0x7,0xd0,0xf,0x98, + 0xcd,0xb,0x68,0x4d,0xc0,0x15,0xd8,0xe5,0x6f,0x19,0xbd,0xf4,0xcf,0x9d,0x9,0x34, + 0x5a,0x1a,0xd0,0x22,0x6f,0x61,0xad,0xb2,0x8f,0xe1,0xf4,0x5c,0x8e,0xae,0xa6,0xde, + 0x9f,0x28,0x10,0x2e,0xe9,0x4b,0x8a,0x17,0x17,0xe4,0xb,0x43,0x4,0x39,0x11,0xa4, + 0x74,0x9b,0xcc,0x9a,0x2b,0xd4,0x11,0x79,0x2a,0x8e,0x56,0xa5,0xfb,0xef,0x11,0xba, + 0xd6,0x58,0x2d,0x72,0x2f,0x76,0xe6,0x86,0x57,0xc8,0x96,0x6a,0x91,0x25,0xae,0x63, + 0x55,0xac,0xf6,0x56,0x5c,0x1d,0xbd,0x29,0xc2,0x72,0xe0,0x8,0x6c,0x54,0xb2,0x1a, + 0xd0,0x5e,0x1,0x8e,0xd4,0x22,0xfe,0x2e,0x62,0x98,0xab,0xb3,0xe2,0xe4,0xcd,0x3, + 0x59,0xf6,0x8c,0xd0,0x43,0x45,0x8,0xe9,0x5d,0xf2,0x69,0x91,0x56,0xec,0xcc,0xd, + 0xf,0x95,0x5e,0xd4,0x22,0xab,0x1d,0x7f,0x31,0x76,0x15,0xec,0xf8,0x14,0xfc,0xfb, + 0x6c,0xa6,0x6d,0xb0,0xbb,0x91,0x62,0x8c,0x3b,0xdd,0x73,0x51,0xa6,0xd4,0xe1,0xae, + 0xfd,0xf,0xb1,0x5b,0xf2,0x6b,0xb1,0xe1,0xe1,0x46,0xe8,0xa4,0xa7,0x3f,0x36,0x22, + 0xd2,0x76,0x34,0x88,0xb8,0x55,0xaf,0xaa,0xb9,0xb5,0x76,0x34,0x76,0x5b,0xd7,0x81, + 0x55,0x84,0x77,0xfa,0xc0,0xb7,0x89,0x9e,0x5b,0xc8,0xd7,0xb5,0xc8,0x21,0x8e,0x36, + 0x2,0x1b,0x2c,0x29,0x3,0xaf,0x36,0x88,0x6a,0x6e,0x13,0xb8,0x73,0x81,0x31,0xee, + 0xd9,0x0,0xbc,0xed,0x79,0xe7,0xdb,0x52,0x8e,0xd1,0x58,0xdf,0x65,0xf,0xec,0xb8, + 0xb4,0x63,0x97,0xa9,0xff,0x4,0xcb,0x42,0x9f,0x31,0xe0,0x77,0x16,0x33,0xa5,0x76, + 0xa1,0xfe,0x5e,0xc3,0x4b,0x5a,0x24,0xc,0xb6,0xec,0xc4,0x27,0x88,0xbe,0x9c,0xa4, + 0x7d,0xd2,0x88,0xfd,0xd,0x45,0x9f,0xee,0x2d,0x0,0x24,0x49,0x92,0x5c,0x7e,0xc6, + 0x19,0x87,0xd5,0xd2,0x74,0x70,0x9a,0xa6,0x6,0xa0,0x5a,0xad,0x9a,0x34,0x49,0xc, + 0x40,0x9a,0xa6,0xa6,0x5a,0xad,0xda,0xf7,0x24,0x31,0x55,0x57,0xa6,0x94,0xe7,0x6, + 0xa0,0xb8,0xa1,0xd,0x90,0xe6,0x79,0x17,0x3d,0x4d,0x53,0x53,0x75,0x65,0x8a,0x7a, + 0x8b,0x5b,0xdb,0x5d,0xef,0x45,0xbe,0xbb,0xc1,0x5d,0xe4,0x3,0x14,0x37,0xb9,0x1, + 0xca,0xa5,0x92,0xa9,0x74,0x76,0x5a,0xba,0x2b,0x57,0xdc,0xec,0x6,0xf0,0x6f,0x77, + 0x87,0x28,0x6e,0x7b,0x43,0xf7,0x8d,0xef,0xae,0xb4,0xbb,0xf9,0x5d,0xa0,0xc9,0x2b, + 0xeb,0xc6,0xa1,0x2b,0x5d,0xdc,0x6,0xef,0xe2,0xf5,0x68,0x49,0x9e,0x57,0xb6,0x7, + 0x8b,0x70,0x4,0xf0,0x52,0x90,0xfd,0x27,0x2d,0xd2,0xdb,0xc9,0x21,0x33,0x5a,0x5a, + 0xf6,0x2b,0xd7,0x6a,0x17,0x1,0x17,0x63,0x4d,0xf5,0x4e,0xf4,0x1f,0x6f,0x90,0x24, + 0xf3,0xf2,0x6a,0x75,0xfe,0xf6,0x6a,0x11,0xa2,0x7b,0xdd,0xe9,0xd3,0xa7,0x37,0xd, + 0x5a,0xb3,0xe6,0x74,0x63,0xcc,0xb4,0xb2,0xdd,0xda,0x6e,0xef,0x7f,0x97,0xb9,0x3d, + 0xa2,0xdd,0x40,0x5b,0x29,0x49,0xee,0x9b,0xfd,0xe8,0xa3,0x5d,0xe,0xf7,0xf6,0xa0, + 0x8,0x83,0xb1,0x27,0x7f,0x3e,0xde,0xf5,0x13,0x33,0x27,0x4d,0x1a,0x9b,0x94,0x4a, + 0xd3,0x9a,0x8d,0x99,0x6a,0xac,0x93,0xb4,0x13,0xfd,0x85,0x31,0xcf,0x3,0xf7,0xd5, + 0x4a,0xa5,0x47,0xe6,0xb4,0xb5,0x85,0x51,0xd5,0x81,0x77,0x16,0x1b,0x61,0x66,0x4b, + 0xcb,0xd0,0xb4,0x5a,0x9d,0xc,0x4c,0x23,0x49,0x8e,0x1e,0x68,0x79,0x3e,0xa5,0x58, + 0x9,0xcc,0xaf,0xd5,0x6a,0xf3,0xe6,0x2c,0x5a,0xd4,0xdb,0xb6,0x73,0xfb,0x53,0x84, + 0x2b,0xcf,0x3e,0xfb,0x98,0x9a,0x31,0x17,0x63,0xef,0xe5,0xd,0xc5,0xee,0xc9,0x8b, + 0x87,0x20,0x1d,0xcb,0xc3,0x80,0x49,0x7a,0x29,0x53,0x74,0xda,0x58,0x87,0xd2,0xe0, + 0x1c,0x4b,0x6c,0xbe,0x71,0xff,0xd3,0x21,0x5a,0x37,0xf6,0x7f,0x31,0xf8,0xf5,0x37, + 0x2c,0x13,0xf6,0x2d,0xa9,0x8f,0x5e,0x26,0xd,0xde,0xfb,0x95,0x36,0x1,0x2d,0x49, + 0x92,0xd7,0x4d,0xad,0x76,0x5f,0x65,0xe4,0xc8,0xdf,0xce,0x9d,0x3b,0xb7,0xee,0x5c, + 0x21,0x86,0xff,0x1,0xa9,0xc5,0x4d,0x76,0xcf,0x54,0x50,0x57,0x0,0x0,0x0,0x0, + 0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/logotiny.PNG + 0x0,0x0,0xa,0x61, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x96,0x0,0x0,0x0,0x37,0x8,0x3,0x0,0x0,0x0,0xd9,0x9f,0x43,0x9b, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x80,0x50,0x4c,0x54, + 0x45,0x10,0x14,0x83,0x7b,0x7d,0xbb,0xd1,0xd2,0xe7,0x41,0x43,0x9c,0xb0,0xb2,0xd6, + 0x5c,0x60,0xab,0x99,0x99,0xcc,0xef,0xef,0xf7,0x33,0x33,0x99,0xc6,0xc7,0xe2,0x4d, + 0x51,0xa3,0x6b,0x6e,0xb3,0x38,0x3b,0x97,0x2b,0x2f,0x92,0x89,0x8b,0xc1,0xe1,0xe2, + 0xf0,0xa8,0xaa,0xd2,0xf6,0xf6,0xfa,0xbd,0xbe,0xdd,0x28,0x2c,0x90,0x72,0x73,0xb5, + 0xda,0xdb,0xec,0x54,0x58,0xa6,0xff,0xff,0xff,0x22,0x27,0x8c,0x47,0x4a,0x9f,0x83, + 0x85,0xbe,0x3a,0x3f,0x98,0xa0,0xa2,0xce,0x62,0x64,0xac,0x8e,0x91,0xc4,0xc0,0xc2, + 0xdf,0xb7,0xb8,0xda,0xe7,0xe7,0xf3,0x57,0x5a,0xa7,0x26,0x2a,0x8e,0x75,0x78,0xb7, + 0x43,0x47,0x9d,0x66,0x6a,0xaf,0xf8,0xf8,0xfc,0x87,0x89,0xc0,0x6e,0x71,0xb4,0xd7, + 0xd8,0xeb,0x1c,0x20,0x89,0x4a,0x4d,0xa1,0x52,0x54,0xa5,0x33,0x33,0x99,0xce,0xce, + 0xe5,0x92,0x94,0xc6,0x5a,0x5d,0xaa,0x7e,0x81,0xbc,0xad,0xae,0xd5,0xb5,0xb5,0xd8, + 0x8b,0x8d,0xc3,0xb8,0xba,0xdb,0xc4,0xc5,0xe0,0xa4,0xa5,0xd0,0x7b,0x7b,0xb5,0xd4, + 0xd5,0xe8,0x68,0x6b,0xb0,0x3a,0x3d,0x99,0x3d,0x41,0x9b,0xe5,0xe6,0xf1,0xea,0xeb, + 0xf4,0xde,0xde,0xee,0x17,0x1b,0x86,0x20,0x24,0x8b,0xc9,0xca,0xe3,0xef,0xf7,0xf7, + 0xa5,0xad,0xce,0x13,0x17,0x85,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x98,0x7,0x3c,0xe1,0x0,0x0,0x0,0x80,0x74,0x52,0x4e,0x53,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x16,0x12,0xe4, + 0x7b,0x0,0x0,0x7,0xc7,0x49,0x44,0x41,0x54,0x68,0x43,0xc5,0x99,0xeb,0x92,0xa2, + 0xb0,0x12,0x80,0xbd,0x1,0x51,0x12,0xef,0x3a,0x82,0x88,0x8a,0x28,0xe2,0xc1,0x12, + 0x15,0x5d,0x4a,0x45,0xdc,0xb5,0xea,0xf0,0xfe,0x6f,0x74,0x3a,0x1,0x5,0x67,0xbd, + 0xe0,0xd4,0xcc,0xd9,0xfe,0x21,0x10,0x43,0xfa,0xa3,0xd3,0xe9,0x74,0x92,0x4c,0xf0, + 0x65,0x31,0x84,0xd6,0x79,0xe0,0xaa,0x2b,0x93,0x9b,0x4b,0xdd,0x2e,0x19,0x81,0x10, + 0x8c,0xa5,0x39,0x67,0xae,0x54,0xd7,0x29,0xb6,0x7c,0xe3,0xcb,0x4d,0x7,0x99,0xb7, + 0x5f,0x35,0x86,0xbb,0xfe,0xda,0xce,0xee,0x35,0xc9,0xc3,0x17,0x41,0x18,0x1f,0xba, + 0x20,0x7,0x8c,0xd1,0x55,0xba,0x92,0xb6,0xcf,0xda,0xd5,0xfa,0x6e,0x58,0x7b,0x5b, + 0xc9,0x3b,0x58,0xfe,0x62,0xbd,0xd9,0x5b,0xa1,0x66,0x2c,0x2d,0x4d,0xd9,0x76,0xb, + 0xf5,0xf3,0xae,0x55,0x19,0xfa,0x82,0x20,0xd4,0x40,0xe0,0xe2,0xf,0x2b,0xad,0xdd, + 0xb9,0xef,0xb8,0xb6,0xdc,0xe4,0xac,0x88,0x52,0x9a,0x94,0xd7,0x8b,0xe1,0x47,0x7a, + 0xba,0x74,0x58,0xc6,0x69,0xa0,0xf6,0x3c,0xaa,0xc3,0x5b,0x66,0x79,0x67,0x71,0x12, + 0xd2,0x6a,0x10,0x2a,0x8b,0x1,0x9f,0x5d,0x7a,0xf4,0x53,0xe,0x5c,0xd9,0x69,0xa5, + 0xeb,0xd9,0xd7,0x58,0x42,0xd1,0xee,0x31,0xa0,0x89,0x3a,0xd8,0xa5,0xc6,0xf9,0x8c, + 0x2d,0xcc,0xb6,0xb6,0x38,0xa6,0x70,0x9c,0xda,0xf7,0x5f,0x7e,0xd4,0x73,0xac,0x5a, + 0x51,0x6d,0x53,0x22,0x53,0x39,0xbf,0x6e,0xea,0xa5,0xae,0x20,0x10,0x16,0xae,0x4e, + 0xd9,0x4a,0xd3,0xfe,0xf3,0xf,0x7c,0x82,0x55,0xa9,0xf6,0xa0,0x5,0x4b,0xde,0x1e, + 0x53,0x28,0x7c,0xa3,0xca,0xb0,0x3e,0x2d,0x51,0xab,0x29,0xa7,0xc7,0x2f,0x3d,0xc2, + 0x3a,0xf1,0x73,0x70,0x6,0xdd,0x19,0xbe,0xa1,0xef,0x8d,0xaa,0x7e,0x7d,0x95,0x7, + 0xa3,0xd9,0xb3,0x7,0xef,0xdc,0xc5,0xf2,0xab,0x6d,0x42,0x24,0x3b,0xf7,0x86,0x9e, + 0x2f,0x54,0x9d,0xf1,0x60,0xb4,0x92,0x72,0xf7,0xc3,0xef,0x60,0x2d,0x74,0x84,0xc6, + 0xf,0xbf,0xe3,0xb,0xfa,0x1f,0xbf,0x72,0xe2,0x2d,0x84,0xc4,0xe2,0xdf,0x15,0xfe, + 0xc2,0x72,0xe6,0x4,0xe9,0xe7,0x6f,0x55,0xfe,0xb4,0xb1,0xdc,0xa,0x13,0x6b,0xfd, + 0x39,0x6c,0xdc,0x62,0x19,0xeb,0x31,0xc9,0x2b,0xdf,0x32,0xe8,0xd2,0x7f,0x98,0x50, + 0x95,0x50,0xd7,0xbd,0x5,0xbb,0xc1,0x1a,0x48,0x64,0x5e,0x4f,0xdf,0xde,0xf7,0xd5, + 0xac,0xb7,0x91,0xb7,0x4e,0x36,0x97,0xc0,0xda,0x71,0x44,0x72,0x8e,0xc2,0xb1,0x52, + 0x79,0xa6,0xcf,0xaf,0x80,0x7c,0x39,0xaa,0x3e,0x6c,0xb9,0x5e,0x22,0xed,0x45,0xfc, + 0x6f,0x8c,0x65,0x23,0xa4,0x4,0x41,0x9e,0x10,0x82,0x9f,0x5,0xaa,0x15,0x8d,0xd4, + 0xfc,0xf7,0x19,0xea,0xda,0x52,0x15,0xa1,0xe9,0xb5,0x27,0x2f,0x58,0x95,0x36,0x31, + 0x61,0xa8,0xa,0xdd,0x46,0xa3,0x81,0x9e,0x61,0x65,0x1b,0x0,0xfe,0x13,0x58,0x81, + 0x90,0x25,0xd6,0x25,0x8e,0x45,0x58,0x7d,0x84,0xa,0x94,0xbb,0xe6,0xbd,0xc2,0x5a, + 0x1,0xd5,0xcf,0x60,0x5,0x41,0x1d,0x21,0x27,0xb4,0x5e,0x88,0xb5,0x46,0x52,0x8b, + 0xdd,0xfc,0x5b,0xac,0xe0,0xd8,0x26,0xe0,0x48,0x17,0xac,0x35,0x59,0x46,0x4e,0xfc, + 0x8f,0xb1,0x2,0x43,0xc,0x7b,0x82,0x5a,0xab,0x4f,0x96,0x97,0xfc,0xf1,0x5f,0x63, + 0x5,0x81,0x48,0xa8,0x37,0x1,0xd6,0x10,0x4b,0xd7,0xac,0xf6,0xc7,0xb0,0x8c,0xb4, + 0x89,0xb3,0xd1,0x46,0xe0,0x4f,0x80,0xb5,0x27,0xf1,0x3c,0xfe,0x1a,0x4b,0xbe,0x71, + 0x79,0xa3,0x76,0x1b,0x9d,0x43,0x7,0xbd,0x83,0xa0,0x63,0xfb,0x5e,0x50,0xa1,0x99, + 0xf6,0xa7,0xf2,0x23,0xd2,0x28,0xd6,0x2,0xa9,0xf1,0x1f,0x2f,0xb0,0x6a,0xb3,0xf5, + 0x3c,0xc,0x10,0x7e,0x9f,0xcf,0xf6,0x4a,0x63,0xcf,0xf3,0xa4,0xf9,0x64,0xa5,0x84, + 0x9,0x67,0xae,0x3a,0x15,0x35,0x2b,0xef,0x79,0xe3,0x12,0xd7,0x54,0xb,0xec,0x6b, + 0x87,0x75,0xa8,0x38,0x97,0x8,0x41,0x56,0x7b,0x2f,0xbb,0xc5,0xc8,0x89,0x5d,0x91, + 0x9b,0x5b,0x63,0xa8,0xea,0x79,0xf9,0x71,0x49,0x9b,0x64,0xc3,0x21,0x47,0xc5,0x25, + 0x75,0xc0,0x32,0x71,0x92,0x97,0x5,0x88,0xe8,0xd5,0xe4,0x67,0x8,0xad,0xbe,0xbb, + 0xe2,0x3c,0x44,0x6d,0x45,0xb1,0x64,0x2,0x15,0xc3,0x7,0x76,0x37,0x85,0xca,0x33, + 0xc,0xb7,0x71,0x59,0xa3,0x4b,0xdb,0xd1,0x3f,0x55,0x8c,0x42,0x5e,0xaf,0x43,0x15, + 0x45,0xcd,0xd1,0x2a,0x83,0x58,0x5b,0x9e,0xb,0x32,0x27,0xbc,0xa,0x2,0xde,0x6c, + 0x86,0x22,0xb2,0x8a,0xfb,0xe8,0x29,0xba,0xec,0x7b,0xed,0x31,0xc6,0xa1,0xfa,0x2b, + 0x56,0x63,0x3c,0x75,0xb7,0xe7,0xdc,0x2e,0x57,0x74,0x94,0x55,0xbe,0xc1,0xb0,0x8, + 0x31,0xf9,0xc2,0xaf,0xc5,0x6e,0x77,0xae,0x57,0x55,0xd3,0xca,0x33,0xac,0x91,0x44, + 0x2b,0x72,0xd,0xbd,0xe8,0xf0,0xd9,0x6e,0x23,0xc2,0x12,0x47,0x93,0x2d,0x5d,0x34, + 0x55,0x4e,0xb3,0x5c,0x71,0x5b,0xb5,0xb3,0x89,0xe4,0xce,0x46,0xc5,0x8c,0x8a,0xfa, + 0x41,0xc0,0x5d,0xf4,0x45,0x6a,0x3f,0x5d,0x80,0xe7,0x5a,0x81,0xdd,0x83,0xb5,0x1a, + 0xd9,0x84,0x31,0xf5,0x8,0xb,0x7f,0x24,0x2d,0xcc,0xdc,0x4e,0x1f,0x6d,0xe8,0xc5, + 0x6c,0x30,0xdf,0x9a,0x5c,0xb0,0x9a,0xa3,0xc7,0x33,0x45,0xe,0x99,0x99,0x25,0x86, + 0x94,0x7a,0xff,0x1c,0x2b,0x49,0x39,0x16,0xed,0xc2,0x42,0x0,0x2c,0x3d,0x41,0xd0, + 0xbc,0x58,0xab,0xba,0x1d,0x5c,0x65,0xfb,0x2b,0xc4,0x92,0xe9,0x45,0x6c,0x30,0xf, + 0x66,0x58,0xdb,0x82,0xe3,0xb4,0x47,0x7b,0xe7,0x22,0x85,0xc4,0x1c,0x4d,0x2b,0xf9, + 0x18,0x67,0x4a,0x8,0xa6,0xc2,0x37,0xb0,0x24,0xdd,0x5d,0x80,0x7f,0xdf,0xc7,0x1a, + 0xdd,0x98,0x39,0xf4,0xad,0x1b,0xac,0x1e,0x60,0x9,0x98,0x5a,0x3c,0x29,0x93,0xa4, + 0x8d,0x61,0x24,0x77,0x3b,0x99,0x25,0x2,0x6b,0x71,0xf7,0x3b,0xef,0x5a,0x9a,0xe8, + 0x45,0xda,0x87,0x58,0xb9,0x8b,0x75,0xb2,0xc6,0xb1,0x48,0x5e,0x3,0xdf,0xc7,0xaa, + 0x2d,0x2d,0xab,0x84,0x1b,0x87,0x92,0x15,0x89,0xc4,0xba,0x39,0x16,0x6a,0x2d,0x1b, + 0x41,0xe2,0xd7,0xaf,0x46,0xa2,0x80,0x67,0xc3,0x40,0xbb,0x3c,0xb2,0xab,0xcb,0xab, + 0x7a,0xf,0xd6,0xf8,0x9f,0x5c,0xfe,0xef,0x4e,0xa4,0xd,0x7f,0x18,0x91,0x7c,0x2c, + 0xc8,0x3,0xac,0xe0,0x3,0xc4,0xec,0xa8,0xf4,0x12,0xca,0x2d,0x15,0x84,0x2c,0x3d, + 0x53,0xc1,0x49,0xdf,0xd,0x58,0x80,0xb8,0x17,0x91,0x85,0x5d,0x61,0xca,0x1d,0x12, + 0x23,0xd1,0x64,0x1e,0xcd,0xc4,0x10,0x99,0x6f,0xf9,0x83,0x53,0x5c,0x16,0x14,0x1f, + 0x62,0xd1,0x57,0xcc,0x51,0x22,0x5a,0x42,0xbf,0x1d,0x13,0x3a,0x55,0x74,0xce,0x4, + 0x7a,0x32,0x4c,0xbd,0x8,0xa7,0xc2,0x42,0xb1,0xc2,0x70,0xba,0x6a,0x90,0xbc,0x26, + 0x66,0xcb,0x9b,0xcd,0xca,0x5c,0xe6,0x9,0x73,0xa0,0x1d,0x42,0xdd,0xb6,0x29,0xab, + 0x3c,0x6f,0xcb,0x66,0x1b,0x8f,0x92,0xd6,0xea,0x35,0x98,0xe7,0x53,0xdf,0x62,0x22, + 0x8e,0x3c,0xce,0xd4,0xe5,0x72,0x79,0xba,0xd2,0x45,0xae,0xd4,0xed,0xc6,0x6e,0x6f, + 0x78,0x3d,0x8,0xa7,0x39,0x16,0xa,0x23,0x49,0x3d,0xf9,0x28,0x79,0x44,0x3b,0x35, + 0x12,0x34,0x76,0xa1,0x81,0x4a,0x9,0xa2,0xde,0xb5,0x8c,0x20,0x8d,0x5a,0x40,0xec, + 0xb0,0xde,0xa8,0xae,0xd8,0x22,0x61,0x79,0x31,0x92,0x98,0xa8,0x49,0x5f,0xc1,0x71, + 0xdc,0xe2,0xc9,0x2f,0x3a,0x27,0x9a,0x24,0x2e,0x7a,0x8d,0xc5,0xd2,0x40,0x9a,0x14, + 0xf9,0x8b,0x81,0x62,0x97,0xe5,0xb2,0xad,0x38,0x74,0x68,0x32,0x11,0x66,0x75,0xd7, + 0x9e,0xae,0x56,0x53,0xdb,0xad,0xcf,0x4,0x56,0xb4,0xce,0x26,0xe2,0x77,0xa0,0x64, + 0x7f,0x45,0x35,0x73,0xf5,0xb5,0x62,0xab,0x65,0x59,0x2e,0xab,0xb6,0x52,0x28,0xc6, + 0xb,0xff,0x13,0xe2,0xd8,0x54,0x2d,0x78,0xde,0x75,0x9,0xf6,0x1a,0x2b,0x4b,0xb1, + 0x36,0xc7,0xca,0x11,0xf6,0xb4,0xd8,0x86,0x16,0xfd,0xf1,0x61,0x5d,0x2,0x72,0x2d, + 0x63,0x85,0x43,0x56,0xe8,0xb,0xc7,0xd6,0x9,0x82,0x79,0xab,0xd5,0x82,0x9f,0x23, + 0x6c,0x7f,0xc1,0xed,0xa9,0x72,0xc,0xdf,0xf4,0x7d,0xba,0x35,0x6,0x3f,0xd7,0xad, + 0xc3,0x9a,0x85,0x60,0x89,0x43,0xf3,0xad,0x33,0x69,0x87,0x5f,0x96,0x26,0x3b,0x35, + 0x59,0xe4,0xbd,0xee,0x3,0xbe,0xbe,0xc9,0x6b,0x1a,0x4c,0x5d,0x92,0xa6,0x69,0xdd, + 0xfc,0x72,0x39,0xc7,0x78,0xac,0x69,0x1e,0xca,0xc3,0xc6,0x21,0xbb,0xd5,0xf2,0xa8, + 0xb4,0x9c,0x7b,0x18,0xe6,0x1a,0x2a,0x46,0x8f,0x6c,0xe1,0xc2,0x92,0xe6,0x1,0x9a, + 0x47,0xf6,0x7a,0x6d,0x2d,0x91,0x61,0x7d,0xe,0x88,0x8f,0x9f,0xc7,0x8e,0x6d,0xf7, + 0x3d,0x6f,0x60,0xdb,0x36,0x5e,0xd9,0x3a,0xdf,0x94,0x6,0x36,0x5f,0x20,0xb2,0xd5, + 0xe9,0x74,0xe,0x5,0xde,0xb6,0xf3,0x62,0x41,0x55,0x26,0x9d,0x10,0xab,0xc6,0x91, + 0x2a,0xbd,0x86,0xb9,0xfc,0x96,0x78,0xa1,0x7f,0xa5,0xc5,0x7a,0x11,0x7e,0xe3,0xbf, + 0x3b,0x72,0x4e,0x96,0x65,0xac,0xe6,0xca,0xea,0xfc,0xb7,0x6a,0x65,0xb4,0xb2,0x5a, + 0x5c,0xc9,0x39,0x73,0xa3,0x75,0xc6,0xa5,0xec,0x4e,0x55,0xb9,0xdf,0x13,0x65,0xaa, + 0xd8,0x7f,0x18,0x56,0xcb,0xa,0xa9,0x2e,0x5b,0xba,0x67,0x4c,0xe8,0x58,0xa,0x6a, + 0x87,0x57,0x2b,0x1f,0xf1,0x76,0x82,0x79,0xc5,0xd7,0x40,0xcd,0xdf,0x7f,0xfe,0x8c, + 0x46,0x6a,0xb9,0xcc,0x1f,0x44,0x7e,0xc3,0x2f,0xf1,0xfe,0xf7,0x7f,0x9a,0x9d,0x9, + 0xdc,0xf6,0xfe,0x2b,0x6f,0x36,0x76,0x29,0x5f,0x96,0x55,0x91,0x59,0xab,0x80,0x68, + 0x6c,0x4f,0x60,0x5,0xc3,0x1e,0xe9,0xc1,0x68,0xa8,0xd1,0x80,0xf9,0x74,0xf9,0x3a, + 0x21,0xf1,0x5e,0x72,0xaa,0xbb,0xb0,0xfe,0xdf,0xb9,0x0,0x4,0x93,0xb8,0xb4,0x1, + 0x79,0xcc,0xd0,0x24,0xed,0xcb,0x80,0x8c,0x57,0xd5,0xa,0x42,0x76,0x2d,0xa8,0xc0, + 0x88,0x89,0x13,0xc5,0x10,0xfd,0x46,0x4e,0x8b,0x9f,0x90,0xdc,0xc9,0xa7,0xfa,0xaf, + 0x9a,0x12,0x7b,0x10,0x15,0x91,0x1c,0xc2,0x9e,0xfd,0x7,0x52,0x97,0x8,0x97,0xd8, + 0x1a,0xbc,0xd9,0xb1,0xe9,0xcf,0x49,0xbe,0x9a,0x76,0x89,0xf2,0x8d,0xec,0x46,0x41, + 0x22,0x52,0x32,0xea,0x7e,0x3e,0xc5,0x18,0xcc,0x9,0xb6,0x9f,0xee,0xd8,0x7c,0x23, + 0x4d,0xd4,0xd4,0x90,0xf7,0x90,0x74,0xb3,0x8d,0x74,0x1d,0x89,0xb1,0xb2,0x7e,0xf, + 0x72,0xf9,0xbe,0xf1,0xfd,0xda,0xef,0xb7,0xf8,0xf1,0xab,0x89,0x90,0x76,0x63,0xa9, + 0xe4,0x48,0x4c,0xbc,0x34,0x93,0xe1,0xec,0x44,0x5e,0x7c,0xfc,0x1f,0xc8,0x76,0x65, + 0x8f,0xa0,0xe4,0xea,0xe2,0xa2,0xf3,0xc6,0xb7,0x2e,0x85,0x35,0x7,0x76,0xe4,0x3d, + 0xb9,0xf8,0xa3,0x6e,0x66,0x9c,0xcb,0xb0,0x99,0xb6,0x5c,0xb,0xf7,0x3e,0xff,0x2e, + 0x16,0x54,0x1c,0x56,0x39,0x88,0x36,0xfb,0x6a,0x3c,0xb3,0x7f,0xab,0xf1,0x2a,0x6b, + 0x13,0x9a,0xd7,0x94,0x47,0x6e,0xfc,0x8,0xb,0x20,0x7c,0xa7,0x9,0x29,0xb4,0xa7, + 0xaf,0x9f,0xc6,0xb1,0xf7,0x69,0x4f,0x85,0x2c,0x98,0x9,0x89,0x85,0x27,0x47,0x11, + 0x4f,0xb0,0x40,0xa1,0x91,0xe3,0xe9,0x1,0xb,0xee,0xd9,0xf5,0xca,0x77,0x8c,0x82, + 0x63,0xdf,0x9e,0xd0,0x83,0x3f,0x8e,0x5f,0x3c,0x77,0x90,0xe7,0x58,0xd4,0x14,0xb5, + 0x9c,0x6b,0xc2,0x41,0x8,0xc2,0x4b,0xb9,0x7a,0x3e,0x7e,0x11,0xce,0x18,0x2e,0xd6, + 0xd3,0x25,0x3b,0x68,0x13,0x95,0x17,0x48,0xf,0x46,0xe2,0xbd,0x6e,0x19,0x16,0x21, + 0x23,0x61,0x67,0x96,0xd6,0x7e,0xea,0xf6,0x67,0x69,0xf,0x54,0x6b,0xfe,0xac,0x5f, + 0xdd,0x88,0xf4,0xe8,0x9,0x21,0x49,0xe4,0xfb,0x29,0x8f,0xb5,0x5e,0x5b,0x2b,0xa6, + 0xac,0xb5,0xea,0xbc,0xae,0x75,0xbb,0x4c,0x87,0x57,0xea,0x35,0xd9,0xf1,0x6b,0x71, + 0x31,0x6b,0x41,0x5e,0x1a,0x9,0x9c,0xbd,0xc2,0xa6,0x42,0xbd,0xe0,0xf2,0x53,0xbd, + 0x7,0xd9,0x1d,0xab,0x7b,0x68,0xeb,0xfc,0x36,0x4a,0xa2,0xd3,0xf9,0xe2,0x3b,0x58, + 0x51,0x8b,0xf4,0x40,0x55,0x81,0xa5,0x63,0x7b,0x7c,0x38,0x1c,0x1e,0x27,0x11,0x78, + 0x3c,0xef,0xe9,0x65,0xc5,0x39,0xa7,0x3f,0xaa,0x8d,0x91,0xbf,0x80,0x75,0x7d,0xd9, + 0xf0,0xe1,0x68,0xbf,0x6a,0x4f,0xb3,0x22,0xd7,0x2e,0x59,0x79,0x10,0xa9,0x34,0xe7, + 0x44,0x1d,0x8c,0xe8,0x14,0x53,0xf7,0xf3,0x5d,0xf3,0xfd,0xf,0x6f,0x76,0x3,0x25, + 0xd2,0xb7,0x42,0x29,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + + // U:/DONNEES/TRAVAIL_NT/CodeBlock/Gcc/Qt/ControleurGrbl/new-3.6.1-T1/src/img/left.PNG + 0x0,0x0,0x1,0xaa, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x60,0x50,0x4c,0x54, + 0x45,0x0,0x0,0x0,0x66,0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f, + 0x40,0x40,0x40,0xdf,0xdf,0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50, + 0x50,0x50,0x33,0x33,0x33,0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80, + 0x80,0x99,0x99,0x99,0x70,0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x21,0x2b,0xd9,0x38,0x0,0x0,0x0,0x20,0x74,0x52,0x4e,0x53,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4e,0xd6,0x1c, + 0x31,0x0,0x0,0x0,0x90,0x49,0x44,0x41,0x54,0x38,0x4f,0xb5,0x93,0xdb,0x12,0x80, + 0x20,0x8,0x44,0xed,0x46,0xd7,0xa9,0xc9,0xff,0xff,0xd8,0x50,0x8b,0xd1,0x44,0xf7, + 0xa1,0xa9,0x57,0xce,0x2e,0x18,0x8b,0xb1,0xe0,0x33,0xff,0x1,0xb4,0x4,0xef,0x52, + 0x8b,0x7d,0xbc,0x2b,0x3a,0x40,0x83,0x31,0x35,0xa0,0x1f,0xb9,0x5e,0x6,0xbc,0xbc, + 0x2,0x4c,0xa1,0x5c,0x72,0xd8,0xd6,0xa7,0xae,0xb7,0x10,0xb9,0xee,0xd0,0x76,0x22, + 0xd7,0x0,0x3a,0xe3,0x72,0x3e,0x43,0x2a,0xcf,0x1c,0xa8,0x49,0xe5,0x6f,0x60,0xf6, + 0xbf,0xa6,0xd2,0x2,0x2,0xd6,0x82,0x16,0xbc,0x57,0x30,0xa4,0x5b,0x3d,0x78,0x66, + 0x66,0xa2,0x6,0xe6,0x88,0x1e,0xa2,0x27,0xa,0x2d,0x8b,0x55,0x62,0x52,0xcc,0x24, + 0xa,0xc,0xb,0x41,0xe4,0x98,0x40,0xa1,0x65,0x4,0xc4,0xde,0xcd,0x7,0xe,0x47, + 0x4e,0xf6,0xfb,0xf1,0x5e,0x7f,0x7c,0x35,0x85,0x42,0x97,0xbd,0xb8,0x0,0x0,0x0, + 0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + +}; + +static const unsigned char qt_resource_name[] = { + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // down.PNG + 0x0,0x8, + 0x6,0xe1,0x38,0x47, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x2e,0x0,0x50,0x0,0x4e,0x0,0x47, + // up.PNG + 0x0,0x6, + 0x7,0xc3,0x35,0x27, + 0x0,0x75, + 0x0,0x70,0x0,0x2e,0x0,0x50,0x0,0x4e,0x0,0x47, + // right.PNG + 0x0,0x9, + 0xd,0xf7,0xc4,0xc7, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x50,0x0,0x4e,0x0,0x47, + // zapmaker-logo-130.png + 0x0,0x15, + 0x8,0xf3,0x6e,0x27, + 0x0,0x7a, + 0x0,0x61,0x0,0x70,0x0,0x6d,0x0,0x61,0x0,0x6b,0x0,0x65,0x0,0x72,0x0,0x2d,0x0,0x6c,0x0,0x6f,0x0,0x67,0x0,0x6f,0x0,0x2d,0x0,0x31,0x0,0x33,0x0,0x30, + 0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // logotiny.PNG + 0x0,0xc, + 0x2,0x33,0xf8,0x67, + 0x0,0x6c, + 0x0,0x6f,0x0,0x67,0x0,0x6f,0x0,0x74,0x0,0x69,0x0,0x6e,0x0,0x79,0x0,0x2e,0x0,0x50,0x0,0x4e,0x0,0x47, + // left.PNG + 0x0,0x8, + 0xb,0xd7,0x3b,0x67, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x50,0x0,0x4e,0x0,0x47, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/img + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x2, + // :/img/logotiny.PNG + 0x0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xf,0xfb, + // :/img/down.PNG + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/up.PNG + 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x7c, + // :/img/zapmaker-logo-130.png + 0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x4,0x9e, + // :/img/left.PNG + 0x0,0x0,0x0,0x9a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1a,0x60, + // :/img/right.PNG + 0x0,0x0,0x0,0x34,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0xfc, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources_GrblController)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_GrblController)) + +int QT_MANGLE_NAMESPACE(qCleanupResources_GrblController)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_GrblController)) + diff --git a/qrc_images.cpp b/GC-3.6.1-T1/src/qrc_images.cpp similarity index 100% rename from qrc_images.cpp rename to GC-3.6.1-T1/src/qrc_images.cpp diff --git a/renderarea.cpp b/GC-3.6.1-T1/src/renderarea.cpp similarity index 65% rename from renderarea.cpp rename to GC-3.6.1-T1/src/renderarea.cpp index 12d71bd..ca6be75 100644 --- a/renderarea.cpp +++ b/GC-3.6.1-T1/src/renderarea.cpp @@ -3,10 +3,12 @@ RenderArea::RenderArea(QWidget *parent) : QWidget(parent), penProposedPath(QPen(Qt::blue)), penAxes(QPen(QColor(193,97,0))), - penCoveredPath(QPen(QColor(60,196,70), 2)), penCurrPos(QPen(Qt::red, 6)), - penMeasure(QPen(QColor(151,111,26))) + penCoveredPath(QPen(QColor(60,196,70), 2)), + penCurrPosActive(QPen(Qt::red, 6)), penCurrPosInactive(QPen(QColor(60,196,70), 6)), + penMeasure(QPen(QColor(151,111,26))), isLiveCurrPos(false) { - penCurrPos.setCapStyle(Qt::RoundCap); + penCurrPosActive.setCapStyle(Qt::RoundCap); + penCurrPosInactive.setCapStyle(Qt::RoundCap); } void RenderArea::setItems(QList itemsRcvd) @@ -19,11 +21,18 @@ void RenderArea::setItems(QList itemsRcvd) update(); } -void RenderArea::setLivePoint(double x, double y, bool mm) +void RenderArea::setLivePoint(double x, double y, bool mm, bool isLiveCP) { + isLiveCurrPos = isLiveCP; livePoint.setCoords(x, y, mm); listToRender.setLivePoint(livePoint); update(); + +} + +void RenderArea::setVisualLivenessCurrPos(bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; } void RenderArea::setVisCurrLine(int currLine) @@ -57,7 +66,10 @@ void RenderArea::paintEvent(QPaintEvent * /* event */) //if (!livePoint.isNull()) FIX isNull { - painter.setPen(penCurrPos); + if (isLiveCurrPos) + painter.setPen(penCurrPosActive); + else + painter.setPen(penCurrPosInactive); listToRender.drawPoint(painter, livePoint); } } diff --git a/renderarea.h b/GC-3.6.1-T1/src/renderarea.h similarity index 69% rename from renderarea.h rename to GC-3.6.1-T1/src/renderarea.h index dba9e71..4023ecc 100644 --- a/renderarea.h +++ b/GC-3.6.1-T1/src/renderarea.h @@ -9,19 +9,19 @@ #include "renderitemlist.h" #include "arcitem.h" #include "lineitem.h" -#include "renderitemlist.h" class RenderArea : public QWidget { Q_OBJECT public: explicit RenderArea(QWidget *parent = 0); - + signals: - + public slots: void setItems(QList); - void setLivePoint(double x, double y, bool isMM); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisualLivenessCurrPos(bool isLiveCP); void setVisCurrLine(int currLine); protected: @@ -30,8 +30,9 @@ public slots: private: QList items; RenderItemList listToRender; - QPen penProposedPath, penAxes, penCoveredPath, penCurrPos, penMeasure; + QPen penProposedPath, penAxes, penCoveredPath, penCurrPosActive, penCurrPosInactive, penMeasure; PosItem livePoint; + bool isLiveCurrPos; }; #endif // RENDERAREA_H diff --git a/renderitemlist.cpp b/GC-3.6.1-T1/src/renderitemlist.cpp similarity index 95% rename from renderitemlist.cpp rename to GC-3.6.1-T1/src/renderitemlist.cpp index e6dbd73..ae94a7e 100644 --- a/renderitemlist.cpp +++ b/GC-3.6.1-T1/src/renderitemlist.cpp @@ -1,4 +1,5 @@ #include "renderitemlist.h" +#include RenderItemList::RenderItemList() : scale(1), offsetx(50), offsety(50), mm(true), currFileLine(0) @@ -152,24 +153,23 @@ void RenderItemList::drawMeasurements(QPainter& painter) int ht = painter.fontMetrics().height(); int wd = painter.fontMetrics().averageCharWidth(); - QString units = mm ? " mm" : " inches"; - - QString info(QString::number(extents.j).append(units).append(" (Width-X: ").append(QString::number(extents.width())) - .append(" Height-Y: ").append(QString::number(extents.height())).append(")")); + QString units = mm ? QObject::tr(" mm") : QObject::tr(" inches"); + QString info(QString::number(extents.j).append(units).append(QObject::tr(" (Width-X: ").append(QString::number(extents.width())) + .append(QObject::tr(" Height-Y: ")).append(QString::number(extents.height())).append(")")) ) ; int xMsgTop = x + wd; QRect br = painter.fontMetrics().boundingRect(info); br.setWidth(br.width() + wd); if (br.width() > (windowSize.width() - x)) xMsgTop = wd; -#ifdef Q_WS_MACX +#ifdef Q_OS_MACX writeText(painter, info, xMsgTop, (3 * ht / 4) + 4, wd); #else writeText(painter, info, xMsgTop, (3 * ht / 4) + 1, wd); #endif -#ifdef Q_WS_MACX +#ifdef Q_OS_MACX writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 2) - 1, wd); #else writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 4) - 1, wd); diff --git a/renderitemlist.h b/GC-3.6.1-T1/src/renderitemlist.h similarity index 100% rename from renderitemlist.h rename to GC-3.6.1-T1/src/renderitemlist.h diff --git a/rs232.cpp b/GC-3.6.1-T1/src/rs232.cpp similarity index 80% rename from rs232.cpp rename to GC-3.6.1-T1/src/rs232.cpp index 5525730..587dd9e 100644 --- a/rs232.cpp +++ b/GC-3.6.1-T1/src/rs232.cpp @@ -1,249 +1,284 @@ -/**************************************************************** - * rs232.cpp - * GrblHoming - zapmaker fork on github - * - * 15 Nov 2012 - * GPL License (see LICENSE file) - * Software is provided AS-IS - ****************************************************************/ - -#include "rs232.h" - -RS232::RS232() - : port(NULL), detectedEOL(0) -{ -} - -bool RS232::OpenComport(QString commPortStr, QString baudRate) -{ - if (port != NULL) - CloseComport(); - - bool ok; - BaudRateType baud = (BaudRateType)baudRate.toInt(&ok); - if (!ok) - { - baud = BAUD9600; - } - else - { - int possibleBaudRates[] = {BAUD110,BAUD300,BAUD600,BAUD1200,BAUD2400,BAUD4800,BAUD9600,BAUD19200,BAUD38400,BAUD57600,BAUD115200}; - int pbrCount = sizeof possibleBaudRates / sizeof possibleBaudRates[0]; - - bool found = false; - for (int i = 0; i < pbrCount; i++) - { - if (baud == possibleBaudRates[i]) - { - found = true; - break; - } - } - if (!found) - baud = BAUD9600; - } - - PortSettings settings = {baud, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10}; - - port = new QextSerialPort(commPortStr, settings, QextSerialPort::Polling); - - port->open(QIODevice::ReadWrite); - - return port->isOpen(); -} - - -int RS232::PollComport(char *buf, int size) -{ - if (port == NULL || !port->isOpen()) - return 0; - - int n = port->bytesAvailable(); - if (!n) - return 0; - - n = port->read(buf, size); - return(n); -} - -// This is different than QIoDevice.readline() - this method only returns data if it has a full line in the -// input buffer by peeking at the buffer. It never removes items unless it can remove a full line. -int RS232::PollComportLine(char *buf, int size) -{ - if (port == NULL || !port->isOpen()) - return 0; - - int n = port->bytesAvailable(); - if (!n) - return 0; - - n = port->peek(buf, size); - if (n <= 0) - return n; - - //printf("PEEK: %d out of %d\n", n, size); - if (detectedEOL == 0) - { - // algorithm assumes we received both eol chars if there are two in this peek - int pos = 0; - char firstEOL = 0; - char secondEOL = 0; - for (int i = 0; i < n; i++) - { - char b = buf[i]; - if (b == '\n' || b == '\r') - { - if (firstEOL == 0) - { - firstEOL = b; - pos = i; - } - else if ((pos + 1) == i) - { - secondEOL = b; - break; - } - else - break; - } - } - - if (firstEOL != 0) - { - if (secondEOL != 0) - { - detectedEOL = secondEOL; - detectedLineFeed = firstEOL; - detectedLineFeed += secondEOL; - } - else - { - detectedEOL = firstEOL; - detectedLineFeed = firstEOL; - } - } - } - - int toRead = 0; - if (detectedEOL) - { - for (int i = 0; i < n; i++) - { - char b = buf[i]; - if (b == detectedEOL) - { - toRead = i + 1; - break; - } - } - } - - // let's hope the serial subsystem's read buffer is big enough to find a linefeed - if (!toRead) - { - return 0; - } - - n = port->read(buf, toRead); - - return n; -} - -int RS232::SendBuf(const char *buf, int size) -{ - if (port == NULL || !port->isOpen()) - return 0; - - if (size <= 0) - { - err("Unexpected: Told to send %d bytes\n", size); - return 1; - } - - char b[300] = {0}; - memcpy(b, buf, size); -#ifdef DIAG - printf("Sending to port %s [%s]:", port->portName().toLocal8Bit().constData(), b); - for (int x= 0; x < size; x++) - { - printf("%02X ", buf[x]); - } - printf("\n"); - fflush(stdout); -#endif - - port->waitForBytesWritten(-1);// this usually doesn't do anything, but let's put it here in case - - int result = port->write(buf, size); - if (result == 0) - { - err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); - /* the following code doesn't seem to help. Generate an error instead - int limit = 0; - while (!result && limit < 100) - { - SLEEP(100); - result = port->write(buf, size); - limit++; - } - - if (!result) - { - err("Unable to write %d bytes to port!", size); - } - else if (result != size) - err("Unexpected: Retry send wrote %d bytes out of expected %d\n", result, size); - */ - } - else if (result == -1) - { - err("Error writing to port. Write data lost!"); - result = 0; - } - return result; -} - - -void RS232::CloseComport() -{ - if (port != NULL) - { - port->close(); - delete port; - port = NULL; - } -} - -void RS232::Reset() //still to test -{ - if (port != NULL) - port->reset(); -} - -void RS232::flush() -{ - int n=1; - char buf[255]; - - while (n > 0) - n = PollComport(buf,255); -} - -bool RS232::isPortOpen() -{ - if (port == NULL) - return false; - - return port->isOpen(); -} - -QString RS232::getDetectedLineFeed() -{ - return detectedLineFeed; -} - -int RS232::bytesAvailable() -{ - int n = port->bytesAvailable(); - return n; -} +/**************************************************************** + * rs232.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "rs232.h" +#include + +RS232::RS232() + : port(NULL), detectedEOL(0), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS) +{ +} + +bool RS232::OpenComport(QString commPortStr, QString baudRate) +{ + if (port != NULL) + CloseComport(); + + bool ok; + BaudRateType baud = (BaudRateType)baudRate.toInt(&ok); + if (!ok) + { + baud = BAUD9600; + } + else + { + int possibleBaudRates[] = {BAUD110,BAUD300,BAUD600,BAUD1200,BAUD2400,BAUD4800,BAUD9600,BAUD19200,BAUD38400,BAUD57600,BAUD115200}; + int pbrCount = sizeof possibleBaudRates / sizeof possibleBaudRates[0]; + + bool found = false; + for (int i = 0; i < pbrCount; i++) + { + if (baud == possibleBaudRates[i]) + { + found = true; + break; + } + } + if (!found) + baud = BAUD9600; + } + + PortSettings settings = {baud, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10}; + + port = new QextSerialPort(commPortStr, settings, QextSerialPort::Polling); + + port->open(QIODevice::ReadWrite); + + return port->isOpen(); +} + + +int RS232::PollComport(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->read(buf, size); + return(n); +} + +// This is different than QIoDevice.readline() - this method only returns data if it has a full line in the +// input buffer by peeking at the buffer. It never removes items unless it can remove a full line. +int RS232::PollComportLine(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->peek(buf, size); + if (n <= 0) + return n; + + //printf("PEEK: %d out of %d\n", n, size); + if (detectedEOL == 0) + { + // algorithm assumes we received both eol chars if there are two in this peek + int pos = 0; + char firstEOL = 0; + char secondEOL = 0; + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == '\n' || b == '\r') + { + if (firstEOL == 0) + { + firstEOL = b; + pos = i; + } + else if ((pos + 1) == i) + { + secondEOL = b; + break; + } + else + break; + } + } + + if (firstEOL != 0) + { + if (secondEOL != 0) + { + detectedEOL = secondEOL; + detectedLineFeed = firstEOL; + detectedLineFeed += secondEOL; + } + else + { + detectedEOL = firstEOL; + detectedLineFeed = firstEOL; + } + } + } + + int toRead = 0; + if (detectedEOL) + { + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == detectedEOL) + { + toRead = i + 1; + break; + } + } + } + + // let's hope the serial subsystem's read buffer is big enough to find a linefeed + if (!toRead) + { + return 0; + } + + n = port->read(buf, toRead); + + return n; +} + +int RS232::SendBuf(const char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + if (size <= 0) + { + err( qPrintable(QObject::tr("Unexpected: Told to send %d bytes\n")), size) ; + return 1; + } + + char b[300] = {0}; + memcpy(b, buf, size); +#ifdef DIAG + printf("Sending to port %s [%s]:", port->portName().toLocal8Bit().constData(), b); + for (int x= 0; x < size; x++) + { + printf("%02X ", buf[x]); + } + printf("\n"); + fflush(stdout); +#endif + + port->waitForBytesWritten(-1);// this usually doesn't do anything, but let's put it here in case + +#if 1 + // On very fast PCs running Windows we have to slow down the sending of bytes to grbl + // because grbl loses bytes due to its interrupt service routine (ISR) taking too many clock + // cycles away from serial handling. + int result = 0; + for (int i = 0; i < size; i++) + { + result = port->write(&buf[i], 1); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + break; + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + break; + } + + if (charSendDelayMs > 0) + { + SLEEP(charSendDelayMs); + } + } + +#else + // DO NOT RUN THIS CODE + int result = port->write(buf, size); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + /* the following code doesn't seem to help. Generate an error instead + int limit = 0; + while (!result && limit < 100) + { + SLEEP(100); + result = port->write(buf, size); + limit++; + } + + if (!result) + { + err("Unable to write %d bytes to port!", size); + } + else if (result != size) + err("Unexpected: Retry send wrote %d bytes out of expected %d\n", result, size); + */ + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + } +#endif + return result; +} + + +void RS232::CloseComport() +{ + if (port != NULL) + { + port->close(); + delete port; + port = NULL; + } +} + +void RS232::Reset() //still to test +{ + if (port != NULL) + port->reset(); +} + +void RS232::flush() +{ + int n=1; + char buf[255]; + + while (n > 0) + n = PollComport(buf,255); +} + +bool RS232::isPortOpen() +{ + if (port == NULL) + return false; + + return port->isOpen(); +} + +QString RS232::getDetectedLineFeed() +{ + return detectedLineFeed; +} + +int RS232::bytesAvailable() +{ + int n = port->bytesAvailable(); + return n; +} + +void RS232::setCharSendDelayMs(int csd) +{ + charSendDelayMs = csd; +} diff --git a/rs232.h b/GC-3.6.1-T1/src/rs232.h similarity index 87% rename from rs232.h rename to GC-3.6.1-T1/src/rs232.h index 2f7f50c..a70ec55 100644 --- a/rs232.h +++ b/GC-3.6.1-T1/src/rs232.h @@ -15,7 +15,7 @@ #include #include -#if defined(Q_OS_LINUX) || defined(Q_WS_MACX) || defined(Q_OS_ANDROID) +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) #include #include "../termiosext.h" #include @@ -40,7 +40,7 @@ #include "definitions.h" -#if defined(Q_OS_LINUX) || defined(Q_WS_MACX) || defined(Q_OS_ANDROID) +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) #define SLEEP(x) usleep(1000 * x); #else #define SLEEP(x) Sleep(x); @@ -62,11 +62,13 @@ class RS232 bool isPortOpen(); QString getDetectedLineFeed(); int bytesAvailable(); + void setCharSendDelayMs(int charSendDelayMs); private: QextSerialPort *port; char detectedEOL; QString detectedLineFeed; + int charSendDelayMs; }; diff --git a/termiosext.h b/GC-3.6.1-T1/src/termiosext.h similarity index 100% rename from termiosext.h rename to GC-3.6.1-T1/src/termiosext.h diff --git a/timer.cpp b/GC-3.6.1-T1/src/timer.cpp similarity index 84% rename from timer.cpp rename to GC-3.6.1-T1/src/timer.cpp index 2c15d20..2556b7d 100644 --- a/timer.cpp +++ b/GC-3.6.1-T1/src/timer.cpp @@ -6,11 +6,9 @@ * GPL License (see LICENSE file) * Software is provided AS-IS ****************************************************************/ - #include "timer.h" - -Timer::Timer() - : timing(false) +Timer::Timer(QObject *parent) : + QObject(parent), timing(false) { startTimer(500); } @@ -22,9 +20,10 @@ void Timer::resetTimer(bool timeIt) timer.start(); } -#pragma GCC diagnostic ignored "-Wunused-parameter" push void Timer::timerEvent(QTimerEvent *event) { + Q_UNUSED(event); + if (timing) { int secs = timer.elapsed() / 1000; @@ -34,4 +33,3 @@ void Timer::timerEvent(QTimerEvent *event) emit setRuntime(QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(mins, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'))); } } -#pragma GCC diagnostic ignored "-Wunused-parameter" pop diff --git a/timer.h b/GC-3.6.1-T1/src/timer.h similarity index 93% rename from timer.h rename to GC-3.6.1-T1/src/timer.h index 5c6e079..eed99ca 100644 --- a/timer.h +++ b/GC-3.6.1-T1/src/timer.h @@ -17,7 +17,7 @@ class Timer : public QObject Q_OBJECT public: - Timer(); + explicit Timer(QObject *parent = 0); signals: void setRuntime(QString timestr); diff --git a/GC-3.6.1-T1/src/translate.bat b/GC-3.6.1-T1/src/translate.bat new file mode 100644 index 0000000..a623222 --- /dev/null +++ b/GC-3.6.1-T1/src/translate.bat @@ -0,0 +1,19 @@ +rem translate.bat + +echo off + +set PATH=%PATH%;u:\DONNEES\SVN_COMPILE\qt\4.7.3\bin + +rem create "trlocale\*.ts" + +lupdate.exe GcodeSenderGUIthreads.pro + +rem create *.qm + +linguist trlocale\GrblController_fr.ts + +lrelease trlocale\GrblController_fr.ts -qm trlocale\GrblController_fr.qm + +xcopy /Y trlocale\GrblController_fr.qm release\trlocale\ + +cd .. diff --git a/GC-3.6.1-T1/src/trlocale/GrblController_fr.qm b/GC-3.6.1-T1/src/trlocale/GrblController_fr.qm new file mode 100644 index 0000000..9f4d585 Binary files /dev/null and b/GC-3.6.1-T1/src/trlocale/GrblController_fr.qm differ diff --git a/GC-3.6.1-T1/src/trlocale/GrblController_fr.ts b/GC-3.6.1-T1/src/trlocale/GrblController_fr.ts new file mode 100644 index 0000000..52e6623 --- /dev/null +++ b/GC-3.6.1-T1/src/trlocale/GrblController_fr.ts @@ -0,0 +1,1309 @@ + + + + + About + + + About... + A propos ... + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + Le programme est fourni en l'état SANS GARANTIE D'AUCUNE SORTE, MEME LES GARANTIES DE CONCEPTION, MARCHANDE ET D'ADAPTATION À UN USAGE PARTICULIER. + + + + Grbl Controller + Controleur Grbl + + + Grbl Controller 4 + Controleur Grbl 4 + + + + GCode + + + Can't open COM port + Impossible d'ouvrir le port série + + + + -Is hardware connected to USB? + - le périphérique est-il bien connecté sur un port USB ? + + + + -Is correct port chosen? + - le port choisi est-il correct ? + + + + -Does current user have sufficient permissions? + - l'utilisateur a-t-il les droits d'utilisation suffisants ? + + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + Emis : 0x%02X (CTRL-X) pour verifier la presence de Grbl + + + + + Sending to port failed + L'émission vers le port a échouée + + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + Port not available yet + Le port n'est plus disponible + + + + Buffer size too small + Le tampon est trop petit + + + + SENDING[%d]: 0x%02X (CTRL-X) + + EMIS[%d]: 0x%02X (CTRL-X)\n + + + + SENDING[%d]: %s + + EMIS[%d]: %s\n + + + + WAITFOROK FAILED + + Echec lors de l'attente de Ok + + + + Wait for ok failed + L'attente d'un bon déroulement a échouée + + + + + Error reading data from COM port + + Erreur de lecture des données sur le port série + + + + Unexpected: list is empty (o)! + Liste attendue vide (o) + + + + + GOT[%d]:%s for %s + + Obtenu [%d]:%s pour %s\n + + + + Error? + Erreur non répertoriée + + + + Unexpected: list is empty (e)! + Liste attendue vide (e) + + + + + + GOT:%s + + Obtenu : %s\n + + + + Wait interrupted by user + Attente d'interuption par l'utilisateur + + + + Expecting Grbl version string. Unable to parse response. + Attente de la version Grbl, impossible d'analyser la réponse + + + + No data from COM port after connect. Expecting Grbl version string. + Aucune données depuis le port série après la connexion, en attente de la version Grbl + + + + Wait interrupted by user (startup) + Attente d'interuption par l'utilisateur (démarrage) + + + XYUV-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XYUV : [%1]=>[%2] + + + ([a-zA-Z]+),MPos: + ([a-zA-Z]+),PosM : + + + ([a-zA-Z]+), MPos: + ([a-zA-Z]+) ,PosM : + + + MPos: + PosM : + + + WPos: + PosT : + + + Decoded: State:%s MPos: %f,%f,%f WPos: %f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f WPos: %f,%f,%f + + + + Decoded: State:%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + Error decoding position data! + + Erreur de décodage des données de position\n + + + GOT[%d]: '%s' for '%s' (aggressive) + + Emis :[%d]: '%s' pour '%s' (offensif) + + + GOT: '%s' (aggressive) + + EMIS : '%s' (offensif) + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + L'axe supplémentaire existe matériellement. Veuillez corriger les options en cochant 4 ème axe. + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + L'axe supplémentaire n'existe pas matériellement. Veuillez corriger les options en décochant 4 ème axe. + + + + Decoded: State:%s + Decodage : Etat :%s + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + GOT-TE:%s + + Obtenu evenement temporel :%s\n + + + + Sending file '%1' + Emission du fichier '%1' + + + + Gave up waiting for OK + + Fin d'attente Ok\n + + + + Code sent successfully with %1 error(s): + Code émis correctement avec %1 erreur(s) + + + + Code sent successfully with no errors. + Code émis correctement sans erreur + + + + Filtered %1 commands: + Commande filtrée %1 + + + + Process interrupted. + Processus interrompu + + + + Removed unsupported command '%1' part of '%2' + Suppression de la commande '%1' portion de '%2 ( non supportée) + + + + Removed unsupported G command '%1' + Suppression de la commande G '%1' non supportée + + + + Removed unsupported M command '%1' + Suppression de la commande M '%1' non supportée + + + + Removed unsupported command '%1' + Suppression de la commande '%1' non supportée + + + + Unable to remove enough decimal places for command (will be truncated): %s + Impossible de supprimer assez de decimales pour la commande (sera tronquee) %s + + + + Error, insufficent reduction '%1' + Erreur : réduction insuffisante '%1' + + + + Precision reduced '%1' + Précision réduite '%1' + + + + Z-Rate Limit: [%1]=>[%2] + Limite de vitesse Z [%1]=>[%2] + + + + Z-Rate Limit: [%1]=>[%2,%3] + Limite de vitesse Z : [%1]=>[%2,%3] + + + + XY-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XY : [%1]=>[%2] + + + + Bad command: %1 + Commande erronee : %1 + + + + Options specify use mm but Grbl parser set for inches. Fixing. + Vous utiliser des 'mm' alors que l'analyse indique des 'pouces'. Corriger dans la configuration + + + + Options specify use inches but Grbl parser set for mm. Fixing. + Vous utiliser les 'pouces' alors que l'analyse indique des 'mm'. Corriger dans la configuration + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + Vous utiliser les mm alors que Grbl donne des pouces. Corriger dans la configuration + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + Vous utiliser les 'pouce's alors que Grbl donne des 'mm'. Corriger dans la configuration + + + + + (mm) + (mm) + + + + + (in) + (pouce) + + + + GrblDialog + + + Grbl Settings + Configuration GRBL + + + + Apply + Appliquer + + + + Close + Fermer + + + + Value + Valeur + + + + Item + Elément + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + Activation de 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Use of non activated appender '%1' + Utilisation de 'Appender' '%1' non activé + + + + Use of closed appender '%1' + Utilisation de 'Appender' '%1' fermé + + + + Use of appender '%1' that requires layout and has no layout set + Utiliser 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + Utiliation de 'Appender' '%1' sans un modèle valide initialisé + + + + The pattern '%1' does not specify a frequency for appender '%2' + Le modème '%1' ne spécifie aucune fréquence pour 4Appender' '%2' + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + La conversion de type '%1' de la propriété '%2' de l'objet de classe '%3' est impossible. + + + + Unable to set property value on object + Impossible d'inialiser la valeur de la propriété de l'objet. + + + + Invalid null object pointer + Pointeur d'objet 'null' invalide + + + + Invalid empty property name + Nom de propriété invalide (vide) + + + + Property '%1' does not exist in class '%2' + La propriété '%1' n'existe pas dans la classe '%2' + + + + Property '%1' is not writable in class '%2' + La propriété '%1' ne peut être modifiée dans la classe '%2' + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + L'activation de 'Appender' '%1' nécessite un fichier associé + + + + Use of appender '%1' without open file + Utilisation de 'Appender' '%1' sans fichier ouvert + + + + Unable to write to file '%1' for appender '%2' + Impossible d'écrire dans le fichier '%1' pour 'Appender' '%2' + + + + Unable to open file '%1' for appender '%2' + Impossible d'ouvrir le fichier '%1' pour 'Appender' '%2' + + + + Unable to remove file '%1' for appender '%2' + Impossible de supprimer le fichier '%1' pour 'Appender' '%2' + + + + Unable to rename file '%1' to '%2' for appender '%3' + Impossible de renommer le fichier '%1' en '%2' pour 'Appender' '%3' + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + Parenthèse fermante manquante pour la parenthèse ouvrante '%1'. Valeur de substitution '%2' invalide + + + + Invalid option string '%1' for a boolean + Option chaîne '%1' invalide pour un booléen + + + + Invalid option string '%1' for a file size + Option chaîne '%1' invalide pour la taille d'un fichier + + + + Invalid option string '%1' for an integer + Option chaîne '%1' invalide pour un entier + + + + Invalid option string '%1' for a level + Option chaîne '%1' invalide pour un niveau + + + + Invalid option string '%1' for a target + Option chaîne '%1' invalide pour une cible + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + On trouve un caractère'%1', alors qu'un chiffre est attendu. + + + + Option '%1' cannot be converted into an integer + L'option '%1' ne peut-être convertie vers un entier + + + + Option %1 isn't a positive integer + L'option '%1' n'est pas un entier positif + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + Impossible d'ouvrir le fichier de propriétés '%1' + + + + Unable to read property file '%1' + Impossible de lire le fichier de propriétés '%1' + + + + Missing appender definition for appender named '%1' + La définition de 'appender' est manquente pour 'Appender' nommé '%1' + + + + Unable to create appender of class '%1' named '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Unable to create layout of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + Unable to create appender of class '%1' namd '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Missing layout definition for appender '%1' + La définition de la structure est manquante pour 'Appender' '%1' + + + Unable to create layoput of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + Activation de 'Appender' '%1' lequel nécessite un éditeur non configuré ! + + + + Use of appender '%1' without a writer set + Utiliser 'Appender' '%1' sans éditeur configuré + + + + MainWindow + + + Grbl Controller + Contrôleur Grbl + + + + X + X + + + + Y + Y + + + + Z + Z + + + + Send File + Envoi d'un fichier + + + + Begin + Démarrer + + + + Stop + Arrêter + + + + Choose file + Choisir un fichier + + + + Runtime: + Exécution + + + Manual GCode + Commande directe en GCode + + + + Command + Commande + + + + + Open + Ouvrir + + + + C + C + + + GRBL +settings + Configuratiion +GRBL + + + + Port name + Nom du port + + + + Reset Control + Commande RAZ + + + + Soft Reset Grbl + RAZ logiciel de Grbl + + + + Unlock Grbl + Débloquer Grbl + + + + Machine Coordinates + Coordonnées machine + + + + Work Coordinates + Coordonnées de travail + + + + Last State: + Dernier état + + + + Zero Position + Vers position zéro + + + + Go Home + Aller position repos + + + + Axis Control + Commandes d'axes + + + + + Z Jog + pilote Z + + + + Step Size + Valeur du pas + + + + Absolute coordinates after adjust + Coordonnées absolues après ajustement + + + + Spindle On + Départ broche + + + + + 0 + + + + + + C Jog + pilote C + + + + Visualizer + Visualisateur + + + + Baud Rate + Vitesse du port + + + + %v + + + + + File progress + Avancement + + + + Queued Commands + Ordres en attente + + + + Advanced + Avancé + + + + GRBL Settings + Configuratiion +GRBL + + + + Refresh Pos + Actualiser position + + + Firmware : + Micrologiciel : + + + none + aucun + + + + &Help + &Aide + + + + &Tools + &Outils + + + + &File + &Fichiers + + + + &About + &A propos + + + + &Options + &Options + + + + E&xit + &Quitter + + + + Close / Reset + Fermer / Raz + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + Vous semblez avoir la dernière version du contrôleur Grbl. Soyez conscient que depuis la version 3.4 le comportement par défaut de l'envoi de commandes à Grbl a été modifié pour les envoyer aussi vite que possible (mode de précharge agressif). + +Vos paramètres ont été modifiés pour permettre ce mode. Pourquoi? Parce qu'il permet une utilisation la plus optimale de Grbl et réduit considérablement le temps de terminer un travail typique. Qu'est-ce que cela signifie pour vous ? Maintenant les commandes d'arc vont être plus continues et plus rapides qu'auparavant, ce qui peut amener votre broche à travailler un peu plus vite, s'il vous plaît donc faire quelques tests en premier. Sinon, passez à la boîte de dialogue Options et désactiver manuellement la précharge agressive + + + Wish to "zero position" before beginning? + Voulez-vous allez en postion zéro avant de démarrer ? + + + + User clicked Port Open/Close + L'utilisateur a clique Ouverture/Fermeture du port + + + + Resetting port to restart controller + L'initialisation du port initialise le contrôleur + + + + Do you want to zero the displayed position before proceeding? + Voulez-vous afficher la postion zéro avant de démarrer ? + + + %s has started + Lancement de %s + + + %s has stopped + Fin de %s + + + + Open File + Charger un fichier + + + + NC (*.nc);;All Files (*.*) + NC (*.nc);;Tous fichiers (*.*) + + + + A Jog + pilote A + + + + B Jog + pilote B + + + + U Jog + pilote U + + + + V Jog + pilote V + + + + W Jog + pilote W + + + + Spindle On. + Marche de la broche + + + + Spindle Off. + Arrêt de la broche + + + Usr chg: pos=%d new=%d + + Changement de position : %d -> =%d + + + Usr chg: pos=%.1f new=%.1f + + Changement de position : %.1f -> =%.1f + + + Usr chg no slider: %d + + Utilisation du coulisseau : %d + + + Usr chg no slider: %.1f + + Utilisation du coulisseau : %.1f + + + Pressed and stopped + + Actionne et stoppe + + + Pressed not stopped + + Actionne sans stop + + + Released + + Relache + + + + Options + + + Options + Options + + + + Axis + Axes + + + + Invert Axis + Inverser les axes + + + + Z Axis + Axe Z + + + + Y Axis + Axe Y + + + + X Axis + Axe X + + + C Axis + Axe C + + + + Seconds to Wait for Response + Secondes d'attente lors d'une réponse + + + + Z-Jog Rate (inches or mm/min) + Vitesse manuelle Z (pouces ou mmm/min) + + + Main + Général + + + + Use millimeters when sending manual commands (v0.8c+ only) + Emission des commandes manuelles en millimètre (v0.8c+ seulement) + + + + Filtering + Filtre + + + + Z Rate Limiting + Limitation de vitesse + + + + Limit Z Rate + Vitesse max Z + + + + Z-Rate Limit (inches or mm/min) + Vitesse limite Z (pouces ou mmm/min) + + + + XY Rate (inches or mm/min) + Vitesse XY (pouces ou mmm/min) + + + + Use aggressive preload strategy for Grbl + Utiliser une stratégie offensive de pré-chargement pour Grbl + + + + General + Général + + + + Wait for each jog/manual command to complete (future feature) + Attendre à chaque commande manuelle pour terminer (option future) + + + + Write debugging log to home folder (requires restart) + Mise au point sauvée dans le répertoire d'accueil (+ redémarrage) + + + + Fourth Axis + 4 ème axe + + + + Selecting the Fourth axis + Choix du quatrième axe + + + + A + A + + + + B + B + + + + C + C + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + Valider le mode 4 axes + + + + Display + Affichage + + + + Enable position request and report + Demander la position puis l'afficher + + + + Position Request + Demande de position + + + + Always Request (most reliable/slightly slower jogging) + permanente (plus fiable, mais les commandes manuelles sont ralenties) + + + + Always Request but without Idle Check (fast jog/manual operations) + permanente mais sans controler l'inactivité (commandes manuelles rapides) + + + + Not during manual control (no position update during jog/manual) + sauf les commandes manuelles où l'actualisation de la position est inactive. + + + Always Request + Demande permanente + + + Not during manual control + Exclure des commandes manuelles + + + + Request frequency (seconds) + Période des demandes (secondes) + + + + Command Filtering + Filtrage des commandes + + + + Filter file commands before sending + Filtrage des commandes du fichier GCode avant l'émission + + + + Selectively reduce precision for excessively long lines + Réduire sélectivement la précision, lors de longues lignes de code + + + + Character send delay ms + Délai d'émission des caractères en mS + + + + Grbl Line Buffer Size + Taille du tampon d'entrée de Grbl + + + + QObject + + + Unexpected: Told to send %d bytes + + Inattendu : impossible d'envoyer%d octets + + + Unable to write bytes to port probably due to outgoing queue full. Write data lost! + Impossible d'ecrire sur le port, probablement la file d'attente de sortie est pleine.Perte de donnees en ecriture ! + + + Error writing to port. Write data lost! + Erreu d'ecriture sur le port. Les donnees a ecrire sont perdues + + + + mm + mm + + + + inches + pouces + + + + (Width-X: + (Larg-X: + + + + Height-Y: + Haut-Y: + + + Unexpected type %c + Type attendu %c + + + + Initialising Log4Qt %1 + Initialisation de LOg4Qt %1 + + + + QextSerialPort + + + No Error has occurred + Aucune erreur + + + + Invalid file descriptor (port was not opened correctly) + Descripteur de périphérique invalide (port mal ouvert) + + + + Unable to allocate memory tables (POSIX) + Impossible d'allouer les tables en mémoire (POSIX) + + + + Caught a non-blocked signal (POSIX) + Capture d'un signal non-bloqué (POSIX) + + + + Operation timed out (POSIX) + Dépassement temporel (POSIX) + + + + The file opened by the port is not a valid device + Le fichier ouvert pour le port n'est pas un périphérique valide + + + + The port detected a break condition + Le port a détecté une condition d'arrêt + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + Le port a détecté une erreur de trame (probablement due à une vitesse erronée) + + + + There was an I/O error while communicating with the port + Erreur d'entrée/sortie lors d'une communication sur le port + + + + Character buffer overrun + Dépassementt du tampon de caractères + + + + Receive buffer overflow + Débordement du tampon de réception + + + + The port detected a parity error in the received data + Le port a détecté une erreur de parité lors de la réception de données + + + + Transmit buffer overflow + Débordement du tampon d'émission + + + + General read operation failure + Echec d'une opération de lecture + + + + General write operation failure + Echec d'une opération d'écriture + + + + The %1 file doesn't exists + Le fichier %1 n'existe pas + + + + Permission denied + Non autorisé + + + + Device is already locked + Périphérique déjà bloqué + + + + Unknown error: %1 + Erreur non répertoriée : %1 + + + diff --git a/GC-3.6.1-T1/src/trlocale/GrblController_xx.qm b/GC-3.6.1-T1/src/trlocale/GrblController_xx.qm new file mode 100644 index 0000000..be651ee --- /dev/null +++ b/GC-3.6.1-T1/src/trlocale/GrblController_xx.qm @@ -0,0 +1 @@ +<¸dÊÍ!¿`¡½Ý \ No newline at end of file diff --git a/GC-3.6.1-T1/src/trlocale/GrblController_xx.ts b/GC-3.6.1-T1/src/trlocale/GrblController_xx.ts new file mode 100644 index 0000000..f26012e --- /dev/null +++ b/GC-3.6.1-T1/src/trlocale/GrblController_xx.ts @@ -0,0 +1,1152 @@ + + + + + About + + + About... + + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + + + Grbl Controller + + + + + GCode + + + Can't open COM port + + + + + -Is hardware connected to USB? + + + + + -Is correct port chosen? + + + + + -Does current user have sufficient permissions? + + + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + + + + + + Sending to port failed + + + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + + + + + Port not available yet + + + + + Buffer size too small + + + + + SENDING[%d]: 0x%02X (CTRL-X) + + + + + + SENDING[%d]: %s + + + + + + WAITFOROK FAILED + + + + + + Wait for ok failed + + + + + + Error reading data from COM port + + + + + + Unexpected: list is empty (o)! + + + + + Error? + + + + + Unexpected: list is empty (e)! + + + + + + GOT[%d]:%s for %s + + + + + + + + GOT:%s + + + + + + Wait interrupted by user + + + + + Expecting Grbl version string. Unable to parse response. + + + + + No data from COM port after connect. Expecting Grbl version string. + + + + + Wait interrupted by user (startup) + + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + + + + + Decoded: State:%s + + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + + GOT-TE:%s + + + + + + Sending file '%1' + + + + + Gave up waiting for OK + + + + + + Code sent successfully with %1 error(s): + + + + + Code sent successfully with no errors. + + + + + Filtered %1 commands: + + + + + Process interrupted. + + + + + Removed unsupported command '%1' part of '%2' + + + + + Removed unsupported G command '%1' + + + + + Removed unsupported M command '%1' + + + + + Removed unsupported command '%1' + + + + + Unable to remove enough decimal places for command (will be truncated): %s + + + + + Error, insufficent reduction '%1' + + + + + Precision reduced '%1' + + + + + Z-Rate Limit: [%1]=>[%2] + + + + + Z-Rate Limit: [%1]=>[%2,%3] + + + + + XY-Rate Limit FIX: [%1]=>[%2] + + + + + Bad command: %1 + + + + + Options specify use mm but Grbl parser set for inches. Fixing. + + + + + Options specify use inches but Grbl parser set for mm. Fixing. + + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + + + + + + (mm) + + + + + + (in) + + + + + GrblDialog + + + Grbl Settings + + + + + Apply + + + + + Close + + + + + Value + + + + + Item + + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + + + + + Use of non activated appender '%1' + + + + + Use of closed appender '%1' + + + + + Use of appender '%1' that requires layout and has no layout set + + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + + + + + The pattern '%1' does not specify a frequency for appender '%2' + + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + + + + + Unable to set property value on object + + + + + Invalid null object pointer + + + + + Invalid empty property name + + + + + Property '%1' does not exist in class '%2' + + + + + Property '%1' is not writable in class '%2' + + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + + + + + Use of appender '%1' without open file + + + + + Unable to write to file '%1' for appender '%2' + + + + + Unable to open file '%1' for appender '%2' + + + + + Unable to remove file '%1' for appender '%2' + + + + + Unable to rename file '%1' to '%2' for appender '%3' + + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + + + + + Invalid option string '%1' for a boolean + + + + + Invalid option string '%1' for a file size + + + + + Invalid option string '%1' for an integer + + + + + Invalid option string '%1' for a level + + + + + Invalid option string '%1' for a target + + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + + + + + Option '%1' cannot be converted into an integer + + + + + Option %1 isn't a positive integer + + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + + + + + Unable to read property file '%1' + + + + + Missing appender definition for appender named '%1' + + + + + Unable to create appender of class '%1' named '%2' + + + + + Unable to create layout of class '%1' requested by appender '%2' + + + + + Missing layout definition for appender '%1' + + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + + + + + Use of appender '%1' without a writer set + + + + + MainWindow + + + Grbl Controller + + + + + X + + + + + Y + + + + + Z + + + + + C + + + + + Send File + + + + + Begin + + + + + Stop + + + + + Choose file + + + + + Runtime: + + + + + + Open + + + + + Port name + + + + + Reset Control + + + + + Soft Reset Grbl + + + + + Unlock Grbl + + + + + Machine Coordinates + + + + + Work Coordinates + + + + + Last State: + + + + + Zero Position + + + + + Go Home + + + + + Axis Control + + + + + + Z Jog + + + + + Step Size + + + + + Absolute coordinates after adjust + + + + + Spindle On + + + + + + 0 + + + + + + C Jog + + + + + Visualizer + + + + + Baud Rate + + + + + %v + + + + + File progress + + + + + Queued Commands + + + + + Command + + + + + Advanced + + + + + GRBL Settings + + + + + Refresh Pos + + + + + &Help + + + + + &Tools + + + + + &File + + + + + &About + + + + + &Options + + + + + E&xit + + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + + + + + User clicked Port Open/Close + + + + + Do you want to zero the displayed position before proceeding? + + + + + Close / Reset + + + + + Resetting port to restart controller + + + + + Open File + + + + + NC (*.nc);;All Files (*.*) + + + + + A Jog + + + + + B Jog + + + + + U Jog + + + + + V Jog + + + + + W Jog + + + + + Spindle On. + + + + + Spindle Off. + + + + + Options + + + Options + + + + + Axis + + + + + Invert Axis + + + + + Z Axis + + + + + Y Axis + + + + + X Axis + + + + + Seconds to Wait for Response + + + + + Z-Jog Rate (inches or mm/min) + + + + + General + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + Wait for each jog/manual command to complete (future feature) + + + + + Filtering + + + + + Z Rate Limiting + + + + + Limit Z Rate + + + + + Z-Rate Limit (inches or mm/min) + + + + + XY Rate (inches or mm/min) + + + + + Use aggressive preload strategy for Grbl + + + + + Write debugging log to home folder (requires restart) + + + + + Fourth Axis + + + + + Selecting the Fourth axis + + + + + A + + + + + B + + + + + C + + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + + + + + Display + + + + + Enable position request and report + + + + + Position Request + + + + + Always Request (most reliable/slightly slower jogging) + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + Not during manual control (no position update during jog/manual) + + + + + Request frequency (seconds) + + + + + Command Filtering + + + + + Filter file commands before sending + + + + + Selectively reduce precision for excessively long lines + + + + + Character send delay ms + + + + + Grbl Line Buffer Size + + + + + QObject + + + mm + + + + + inches + + + + + (Width-X: + + + + + Height-Y: + + + + + Unexpected: Told to send %d bytes + + + + + + Initialising Log4Qt %1 + + + + + QextSerialPort + + + No Error has occurred + + + + + Invalid file descriptor (port was not opened correctly) + + + + + Unable to allocate memory tables (POSIX) + + + + + Caught a non-blocked signal (POSIX) + + + + + Operation timed out (POSIX) + + + + + The file opened by the port is not a valid device + + + + + The port detected a break condition + + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + + + + + There was an I/O error while communicating with the port + + + + + Character buffer overrun + + + + + Receive buffer overflow + + + + + The port detected a parity error in the received data + + + + + Transmit buffer overflow + + + + + General read operation failure + + + + + General write operation failure + + + + + The %1 file doesn't exists + + + + + Permission denied + + + + + Device is already locked + + + + + Unknown error: %1 + + + + diff --git a/version.h b/GC-3.6.1-T1/src/version.h similarity index 79% rename from version.h rename to GC-3.6.1-T1/src/version.h index c4a53b4..48c3d3d 100644 --- a/version.h +++ b/GC-3.6.1-T1/src/version.h @@ -1,14 +1,12 @@ -/**************************************************************** - * version.h - * GrblHoming - zapmaker fork on github - * - * 14 July 2013 - * GPL License (see LICENSE file) - * Software is provided AS-IS - ****************************************************************/ -#ifndef VERSION_H -#define VERSION_H - -#define GRBL_CONTROLLER_NAME_AND_VERSION "Grbl Controller 3.4.3" - -#endif // VERSION_H +/**************************************************************** + * version.h + * GrblHoming - zapmaker fork on github + * + * 14 July 2013 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#ifndef VERSION_H +#define VERSION_H +#define GRBL_CONTROLLER_NAME_AND_VERSION "Grbl Controller 3.6.1-T1" +#endif // VERSION_H diff --git a/wininfoafter.txt b/GC-3.6.1-T1/src/wininfoafter.txt similarity index 100% rename from wininfoafter.txt rename to GC-3.6.1-T1/src/wininfoafter.txt diff --git a/wininfobefore.txt b/GC-3.6.1-T1/src/wininfobefore.txt similarity index 100% rename from wininfobefore.txt rename to GC-3.6.1-T1/src/wininfobefore.txt diff --git a/winlicense.txt b/GC-3.6.1-T1/src/winlicense.txt similarity index 100% rename from winlicense.txt rename to GC-3.6.1-T1/src/winlicense.txt diff --git a/GC-3.6.1-T1/translate.bat b/GC-3.6.1-T1/translate.bat new file mode 100644 index 0000000..1e48183 --- /dev/null +++ b/GC-3.6.1-T1/translate.bat @@ -0,0 +1,6 @@ +rem translate.bat +rem by LETARTARE + +cd src + +translate.bat diff --git a/GC-3.6.1-T2/README b/GC-3.6.1-T2/README new file mode 100644 index 0000000..1d7b5c6 --- /dev/null +++ b/GC-3.6.1-T2/README @@ -0,0 +1,44 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Details on how to do this can be found here: +http://zapmaker.org/ + +-------------------------------------------------------------------------------- + +V3.6.1-T2 (LETARTARE proposals June 03, 2014) + +* 3.6.1-T1 + + +1- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +2- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +3- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +4- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + +-------------------------------------------------------------------------------- + +V3.6.1-T1 (LETARTARE proposals June 01, 2014) + +- 3.6.1 + +1- Improved to the same card 3 and 4 axis detection +2- Displays the line numbers of the file if no number exists +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, future 0.8c1 (0.8c to 4 axes) + +-------------------------------------------------------------------------------- + + + diff --git a/GC-3.6.1-T2/buildWin.txt b/GC-3.6.1-T2/buildWin.txt new file mode 100644 index 0000000..3737a80 --- /dev/null +++ b/GC-3.6.1-T2/buildWin.txt @@ -0,0 +1,25 @@ +builWin.txt by LETARTARE + + +To build the executable under Windows, you must have +1- a 'Qt' version installed and compiled, the tests were performed with 'Qt-4.7.3'. +2- 'mingw32' installed to use 'mingw32-make.exe', the tests were performed with 'MinGw32-TDM-4.7.1' + +You have to adapt the file 'makeWin.bat' for the paths are correct. + +Example Qt4 : + set PATH_Qt=u:\DONNEES\SVN_COMPILE\qt\4.7.3 + set PATH_MINGW32=o:\DevCpp\MinGw32-TDM + +Example Qt5 : + set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ + set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +Open a DOS console and +1 - makeWin.bat +2 - execute.bat + +if you want the French translation +3 - translate.bat +4 - execute.bat diff --git a/GC-3.6.1-T2/clean.bat b/GC-3.6.1-T2/clean.bat new file mode 100644 index 0000000..6a4585c --- /dev/null +++ b/GC-3.6.1-T2/clean.bat @@ -0,0 +1,26 @@ +rem clean.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +clean.bat + + diff --git a/GC-3.6.1-T2/execute.bat b/GC-3.6.1-T2/execute.bat new file mode 100644 index 0000000..dbd9cf0 --- /dev/null +++ b/GC-3.6.1-T2/execute.bat @@ -0,0 +1,8 @@ +rem execute.bat +rem by LETARTARE + +cd src\release + +GrblController.exe + +cd ..\.. \ No newline at end of file diff --git a/GC-3.6.1-T2/makeWin.bat b/GC-3.6.1-T2/makeWin.bat new file mode 100644 index 0000000..c96e888 --- /dev/null +++ b/GC-3.6.1-T2/makeWin.bat @@ -0,0 +1,12 @@ +rem makeWin.bat +rem by LETARTARE + +rem Change with your paths +set PATH_QT = "u:\DONNEES\SVN_COMPILE\qt\4.7.3" +set PATH_MINGW32 = "o:\DevCpp\MinGw32-TDM" + +cd src + +makeWin.bat + + diff --git a/GC-3.6.1-T2/mw.bat b/GC-3.6.1-T2/mw.bat new file mode 100644 index 0000000..bd60e58 --- /dev/null +++ b/GC-3.6.1-T2/mw.bat @@ -0,0 +1,24 @@ +rem makeWin.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +makeWin.bat + + diff --git a/GC-3.6.1-T2/src/.gitignore b/GC-3.6.1-T2/src/.gitignore new file mode 100644 index 0000000..f128f9d --- /dev/null +++ b/GC-3.6.1-T2/src/.gitignore @@ -0,0 +1,19 @@ +GcodeSenderGUIthreads.pro.user +Makefile +Makefile.Debug +Makefile.Release +debug/ +release/ +favs.txt +object_script.GcodeSenderGUI.Debug +object_script.GcodeSenderGUI.Release +settings +ui_*.h +Output/ +android/ +GrblController +*.o +moc_*.cpp +qrc_*.cpp +*.stash +GrblController-local.iss diff --git a/GC-3.6.1-T2/src/GcodeSenderGUIthreads.pro b/GC-3.6.1-T2/src/GcodeSenderGUIthreads.pro new file mode 100644 index 0000000..400cffe --- /dev/null +++ b/GC-3.6.1-T2/src/GcodeSenderGUIthreads.pro @@ -0,0 +1,110 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-02-13 T17:48:40 +# +# (fourth axis modifications and translation added by LETARTARE 2013-08-03) +#------------------------------------------------- + +QT += core gui + +# LETARTARE June 12, 2014 +contains(QT_VERSION, "^5.*") { + QT *= widgets +} + +TARGET = GrblController +TEMPLATE = app + +include(QextSerialPort/qextserialport.pri) +include(log4qt/log4qt.pri) + + +SOURCES += main.cpp\ + mainwindow.cpp \ + rs232.cpp \ + options.cpp \ + grbldialog.cpp \ + about.cpp \ + gcode.cpp \ + timer.cpp \ + atomicintbool.cpp \ + coord3d.cpp \ + renderarea.cpp \ + positem.cpp \ + renderitemlist.cpp \ + lineitem.cpp \ + itemtobase.cpp \ + arcitem.cpp \ + pointitem.cpp \ + controlparams.cpp + +HEADERS += mainwindow.h \ + rs232.h \ + options.h \ + grbldialog.h \ + definitions.h \ + about.h \ + images.rcc \ + gcode.h \ + timer.h \ + atomicintbool.h \ + coord3d.h \ + log4qtdef.h \ + renderarea.h \ + positem.h \ + renderitemlist.h \ + lineitem.h \ + itemtobase.h \ + arcitem.h \ + pointitem.h \ + termiosext.h \ + controlparams.h \ + version.h + +FORMS += mainwindow.ui \ + options.ui \ + grbldialog.ui \ + about.ui + +RESOURCES += GrblController.qrc + +RC_FILE = grbl.rc + +OTHER_FILES += \ + android/AndroidManifest.xml \ + android/res/drawable/icon.png \ + android/res/drawable/logo.png \ + android/res/drawable-hdpi/icon.png \ + android/res/drawable-ldpi/icon.png \ + android/res/drawable-mdpi/icon.png \ + android/res/layout/splash.xml \ + android/res/values/libs.xml \ + android/res/values/strings.xml \ + android/res/values-de/strings.xml \ + android/res/values-el/strings.xml \ + android/res/values-es/strings.xml \ + android/res/values-et/strings.xml \ + android/res/values-fa/strings.xml \ + android/res/values-fr/strings.xml \ + android/res/values-id/strings.xml \ + android/res/values-it/strings.xml \ + android/res/values-ja/strings.xml \ + android/res/values-ms/strings.xml \ + android/res/values-nb/strings.xml \ + android/res/values-nl/strings.xml \ + android/res/values-pl/strings.xml \ + android/res/values-pt-rBR/strings.xml \ + android/res/values-ro/strings.xml \ + android/res/values-rs/strings.xml \ + android/res/values-ru/strings.xml \ + android/res/values-zh-rCN/strings.xml \ + android/res/values-zh-rTW/strings.xml \ + android/src/org/kde/necessitas/ministro/IMinistro.aidl \ + android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \ + android/src/org/kde/necessitas/origo/QtActivity.java \ + android/src/org/kde/necessitas/origo/QtApplication.java \ + android/version.xml + +# Translations + TRANSLATIONS += trlocale/GrblController_xx.ts + TRANSLATIONS += trlocale/GrblController_fr.ts diff --git a/GC-3.6.1-T2/src/GrblController.iss b/GC-3.6.1-T2/src/GrblController.iss new file mode 100644 index 0000000..49dc801 --- /dev/null +++ b/GC-3.6.1-T2/src/GrblController.iss @@ -0,0 +1,58 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "Grbl Controller" +#define MyAppVersion "3.6.1" +#define MyAppPublisher "Zapmaker" +#define MyAppURL "http://zapmaker.org" +#define MyAppExeName "GrblController.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{2DC56D0D-0673-4954-9BDE-3D664965BA97} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=C:\dev\github\GrblHoming\winlicense.txt +InfoBeforeFile=C:\dev\github\GrblHoming\wininfobefore.txt +InfoAfterFile=C:\dev\github\GrblHoming\wininfoafter.txt +OutputBaseFilename=GrblController361Setup +Compression=lzma +SolidCompression=yes + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked +Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 + +[Files] +Source: "C:\dev\github\GrblHoming\release\GrblController.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\dev\github\GrblHoming\trlocale\*.qm"; DestDir: "{app}\trlocale"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\mingwm10.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\mingw\bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/GC-3.6.1-T2/src/GrblController.qrc b/GC-3.6.1-T2/src/GrblController.qrc new file mode 100644 index 0000000..f3b4e5e --- /dev/null +++ b/GC-3.6.1-T2/src/GrblController.qrc @@ -0,0 +1,10 @@ + + + img/down.PNG + img/left.PNG + img/logotiny.PNG + img/right.PNG + img/up.PNG + img/zapmaker-logo-130.png + + diff --git a/GC-3.6.1-T2/src/LICENSE b/GC-3.6.1-T2/src/LICENSE new file mode 100644 index 0000000..9e419e0 --- /dev/null +++ b/GC-3.6.1-T2/src/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/GC-3.6.1-T2/src/Makefile b/GC-3.6.1-T2/src/Makefile new file mode 100644 index 0000000..6a5bf7e --- /dev/null +++ b/GC-3.6.1-T2/src/Makefile @@ -0,0 +1,153 @@ +############################################################################# +# Makefile for building: GrblController +# Generated by qmake (2.01a) (Qt 4.7.3) on: dim. 1. juin 22:36:27 2014 +# Project: GcodeSenderGUIthreads.pro +# Template: app +# Command: u:/DONNEES/SVN_COMPILE/qt/4.7.3/bin/qmake.exe -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro +############################################################################# + +first: release +install: release-install +uninstall: release-uninstall +MAKEFILE = Makefile +QMAKE = u:/DONNEES/SVN_COMPILE/qt/4.7.3/bin/qmake.exe +DEL_FILE = rm +CHK_DIR_EXISTS= test -d +MKDIR = mkdir +COPY = cp +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm +SYMLINK = +DEL_DIR = rmdir +MOVE = mv +CHK_DIR_EXISTS= test -d +MKDIR = mkdir +SUBTARGETS = \ + release \ + debug + +release: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_default: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_first: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release first +release-all: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release all +release-clean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release clean +release-distclean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release distclean +release-install: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release install +release-uninstall: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release uninstall +debug: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_default: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_first: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug first +debug-all: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug all +debug-clean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug clean +debug-distclean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug distclean +debug-install: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug install +debug-uninstall: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug uninstall + +Makefile: GcodeSenderGUIthreads.pro u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++/qmake.conf u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/qconfig.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/modules/qt_webkit_version.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_functions.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_config.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/exclusive_builds.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_pre.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_pre.prf \ + QextSerialPort/qextserialport.pri \ + log4qt/log4qt.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/release.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/debug_and_release.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_post.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_post.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/rtti.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/exceptions.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/stl.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/msvc_mp.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/shared.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/warn_on.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/thread.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/moc.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/windows.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/resources.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/uic.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/yacc.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/lex.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/include_source_dir.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/lib/qtmain.prl + $(QMAKE) -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/qconfig.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/modules/qt_webkit_version.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_functions.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_config.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/exclusive_builds.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_pre.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_pre.prf: +QextSerialPort/qextserialport.pri: +log4qt/log4qt.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/release.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/debug_and_release.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_post.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_post.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/rtti.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/exceptions.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/stl.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/msvc_mp.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/shared.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/warn_on.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/thread.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/moc.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/windows.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/resources.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/uic.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/yacc.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/lex.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/include_source_dir.prf: +u:\DONNEES\SVN_COMPILE\qt\4.7.3\lib\qtmain.prl: +qmake: qmake_all FORCE + @$(QMAKE) -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro + +qmake_all: FORCE + +make_default: release-make_default debug-make_default FORCE +make_first: release-make_first debug-make_first FORCE +all: release-all debug-all FORCE +clean: release-clean debug-clean FORCE +distclean: release-distclean debug-distclean FORCE + -$(DEL_FILE) Makefile + +check: first + +release-mocclean: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocclean +debug-mocclean: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocclean +mocclean: release-mocclean debug-mocclean + +release-mocables: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocables +debug-mocables: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocables +mocables: release-mocables debug-mocables +FORCE: + +$(MAKEFILE).Release: Makefile +$(MAKEFILE).Debug: Makefile diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.cpp new file mode 100644 index 0000000..ec1491a --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" + +#include +#include +#include + +QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator) + :q_ptr(enumrator) +{ + platformSpecificInit(); +} + +QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate() +{ + platformSpecificDestruct(); +} + +/*! + \class QextPortInfo + + \brief The QextPortInfo class containing port information. + + Structure containing port information. + + \code + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID + \endcode + */ + +/*! \class QextSerialEnumerator + + \brief The QextSerialEnumerator class provides list of ports available in the system. + + \section1 Usage + To poll the system for a list of connected devices, simply use getPorts(). Each + QextPortInfo structure will populated with information about the corresponding device. + + \bold Example + \code + QList ports = QextSerialEnumerator::getPorts(); + foreach (QextPortInfo port, ports) { + // inspect port... + } + \endcode + + To enable event-driven notification of device connection events, first call + setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() + signals. Event-driven behavior is currently available only on Windows and OS X. + + \bold Example + \code + QextSerialEnumerator *enumerator = new QextSerialEnumerator(); + connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), + myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); + connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), + myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); + \endcode + + \section1 Credits + Windows implementation is based on Zach Gorman's work from + \l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp). + + OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html + + \bold author Michal Policht, Liam Staskawicz +*/ + +/*! + \fn void QextSerialEnumerator::deviceDiscovered(const QextPortInfo &info) + A new device has been connected to the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that has been discovered. +*/ + +/*! + \fn void QextSerialEnumerator::deviceRemoved(const QextPortInfo &info); + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that was disconnected. +*/ + +/*! + Constructs a QextSerialEnumerator object with the given \a parent. +*/ +QextSerialEnumerator::QextSerialEnumerator(QObject *parent) + :QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this)) +{ + if (!QMetaType::isRegistered(QMetaType::type("QextPortInfo"))) + qRegisterMetaType("QextPortInfo"); +} + +/*! + Destructs the QextSerialEnumerator object. +*/ +QextSerialEnumerator::~QextSerialEnumerator() +{ + delete d_ptr; +} + +/*! + Get list of ports. + + return list of ports currently available in the system. +*/ +QList QextSerialEnumerator::getPorts() +{ + return QextSerialEnumeratorPrivate::getPorts_sys(); +} + +/*! + Enable event-driven notifications of board discovery/removal. +*/ +void QextSerialEnumerator::setUpNotifications() +{ + Q_D(QextSerialEnumerator); + if (!d->setUpNotifications_sys(true)) + QESP_WARNING("Setup Notification Failed..."); +} + +#include "moc_qextserialenumerator.cpp" diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.h b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.h new file mode 100644 index 0000000..99f515d --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALENUMERATOR_H_ +#define _QEXTSERIALENUMERATOR_H_ + +#include +#include +#include "qextserialport_global.h" + +struct QextPortInfo { + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID +}; + +class QextSerialEnumeratorPrivate; +class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialEnumerator) +public: + QextSerialEnumerator(QObject *parent=0); + ~QextSerialEnumerator(); + + static QList getPorts(); + void setUpNotifications(); + +Q_SIGNALS: + void deviceDiscovered(const QextPortInfo &info); + void deviceRemoved(const QextPortInfo &info); + +private: + Q_DISABLE_COPY(QextSerialEnumerator) +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent()) +#endif + QextSerialEnumeratorPrivate *d_ptr; +}; + +#endif /*_QEXTSERIALENUMERATOR_H_*/ diff --git a/QextSerialPort/qextserialenumerator_unix.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_linux.cpp similarity index 52% rename from QextSerialPort/qextserialenumerator_unix.cpp rename to GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_linux.cpp index 3a48aa4..a57dfe6 100644 --- a/QextSerialPort/qextserialenumerator_unix.cpp +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_linux.cpp @@ -1,100 +1,210 @@ -/**************************************************************************** -** Copyright (c) 2000-2003 Wayne Roth -** Copyright (c) 2004-2007 Stefan Sander -** Copyright (c) 2007 Michal Policht -** Copyright (c) 2008 Brandon Fosdick -** Copyright (c) 2009-2010 Liam Staskawicz -** Copyright (c) 2011 Debao Zhang -** All right reserved. -** Web: http://code.google.com/p/qextserialport/ -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -** -****************************************************************************/ - -#include "qextserialenumerator.h" -#include "qextserialenumerator_p.h" -#include -#include -#include - -void QextSerialEnumeratorPrivate::platformSpecificInit() -{ -} - -void QextSerialEnumeratorPrivate::platformSpecificDestruct() -{ -} - -QList QextSerialEnumeratorPrivate::getPorts_sys() -{ - QList infoList; -#ifdef Q_OS_LINUX - QStringList portNamePrefixes, portNameList; - portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first - - QDir dir(QLatin1String("/dev")); - portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); - - // remove the values which are not serial ports for e.g. /dev/ttysa - for (int i = 0; i < portNameList.size(); i++) { - bool ok; - QString current = portNameList.at(i); - // remove the ttyS part, and check, if the other part is a number - current.remove(0,4).toInt(&ok, 10); - if (!ok) { - portNameList.removeAt(i); - i--; - } - } - - // get the non standard serial ports names - // (USB-serial, bluetooth-serial, 18F PICs, and so on) - // if you know an other name prefix for serial ports please let us know - portNamePrefixes.clear(); - portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); - portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); - - foreach (QString str , portNameList) { - QextPortInfo inf; - inf.physName = QLatin1String("/dev/")+str; - inf.portName = str; - - if (str.contains(QLatin1String("ttyS"))) { - inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); - } - else if (str.contains(QLatin1String("ttyUSB"))) { - inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); - } - else if (str.contains(QLatin1String("rfcomm"))) { - inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); - } - inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? - infoList.append(inf); - } -#endif - return infoList; -} - -bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) -{ - Q_UNUSED(setup) - return false; -} +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifndef QESP_NO_UDEV + monitor = NULL; + notifierFd = -1; + notifier = NULL; + + udev = udev_new(); + if (!udev) + qCritical() << "Unable to initialize udev notifications"; +#endif +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifndef QESP_NO_UDEV + if (notifier) { + notifier->setEnabled(false); + delete notifier; + } + + if (monitor) + udev_monitor_unref(monitor); + + if (udev) + udev_unref(udev); +#endif +} + +#ifndef QESP_NO_UDEV +static QextPortInfo portInfoFromDevice(struct udev_device *dev) +{ + QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID")); + QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID")); + + QextPortInfo pi; + pi.vendorID = vendor.toInt(0, 16); + pi.productID = product.toInt(0, 16); + pi.portName = QString::fromLatin1(udev_device_get_devnode(dev)); + pi.physName = pi.portName; + + return pi; +} +#endif + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; +#ifndef QESP_NO_UDEV + struct udev *ud = udev_new(); + if (!ud) { + qCritical() << "Unable to enumerate ports because udev is not initialized."; + return infoList; + } + + struct udev_enumerate *enumerate = udev_enumerate_new(ud); + udev_enumerate_add_match_subsystem(enumerate, "tty"); + udev_enumerate_scan_devices(enumerate); + struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); + struct udev_list_entry *entry; + udev_list_entry_foreach(entry, list) { + const char *path; + struct udev_device *dev; + + // Have to grab the actual udev device here... + path = udev_list_entry_get_name(entry); + dev = udev_device_new_from_syspath(ud, path); + + infoList.append(portInfoFromDevice(dev)); + + // Done with this device + udev_device_unref(dev); + } + // Done with the list and this udev + udev_enumerate_unref(enumerate); + udev_unref(ud); +#else + QStringList portNamePrefixes, portNameList; + portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first + + QDir dir(QLatin1String("/dev")); + portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + // remove the values which are not serial ports for e.g. /dev/ttysa + for (int i = 0; i < portNameList.size(); i++) { + bool ok; + QString current = portNameList.at(i); + // remove the ttyS part, and check, if the other part is a number + current.remove(0,4).toInt(&ok, 10); + if (!ok) { + portNameList.removeAt(i); + i--; + } + } + + // get the non standard serial ports names + // (USB-serial, bluetooth-serial, 18F PICs, and so on) + // if you know an other name prefix for serial ports please let us know + portNamePrefixes.clear(); + portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); + portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + foreach (QString str , portNameList) { + QextPortInfo inf; + inf.physName = QLatin1String("/dev/")+str; + inf.portName = str; + + if (str.contains(QLatin1String("ttyS"))) { + inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); + } + else if (str.contains(QLatin1String("ttyUSB"))) { + inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); + } + else if (str.contains(QLatin1String("rfcomm"))) { + inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); + } + inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? + infoList.append(inf); + } +#endif + + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup); +#ifndef QESP_NO_UDEV + Q_Q(QextSerialEnumerator); + if (!udev) { + qCritical() << "Unable to initialize notifications because udev is not initialized."; + return false; + } + + // Emit signals immediately for devices already connected (Windows version seems to behave + // this way) + foreach (QextPortInfo i, getPorts_sys()) + Q_EMIT q->deviceDiscovered(i); + + // Look for tty devices from udev. + monitor = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL); + udev_monitor_enable_receiving(monitor); + notifierFd = udev_monitor_get_fd(monitor); + notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read); + q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent())); + notifier->setEnabled(true); + + return true; +#else + return false; +#endif +} + +#ifndef QESP_NO_UDEV +void QextSerialEnumeratorPrivate::_q_deviceEvent() +{ + Q_Q(QextSerialEnumerator); + struct udev_device *dev = udev_monitor_receive_device(monitor); + if (dev) { + QextPortInfo pi = portInfoFromDevice(dev); + + QLatin1String action(udev_device_get_action(dev)); + udev_device_unref(dev); + + if (action == QLatin1String("add")) + Q_EMIT q->deviceDiscovered(pi); + else if (action == QLatin1String("remove")) + Q_EMIT q->deviceRemoved(pi); + } +} +#endif diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_osx.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_osx.cpp new file mode 100644 index 0000000..2dd0357 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_osx.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ + IONotificationPortDestroy(notificationPortRef); +} + +// static +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + io_iterator_t serialPortIterator = 0; + kern_return_t kernResult = KERN_FAILURE; + CFMutableDictionaryRef matchingDictionary; + + // first try to get any serialbsd devices, then try any USBCDC devices + if (!(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue))) { + QESP_WARNING("IOServiceMatching returned a NULL dictionary."); + return infoList; + } + CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + // then create the iterator with all the matching devices + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + serialPortIterator = 0; + + if (!(matchingDictionary = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("IOServiceNameMatching returned a NULL dictionary."); + return infoList; + } + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + + return infoList; +} + +void QextSerialEnumeratorPrivate::iterateServicesOSX(io_object_t service, QList &infoList) +{ + // Iterate through all modems found. + io_object_t usbService; + while ((usbService = IOIteratorNext(service))) { + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + getServiceDetailsOSX(usbService, &info); + infoList.append(info); + } +} + +bool QextSerialEnumeratorPrivate::getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo) +{ + bool retval = true; + CFTypeRef bsdPathAsCFString = NULL; + CFTypeRef productNameAsCFString = NULL; + CFTypeRef vendorIdAsCFNumber = NULL; + CFTypeRef productIdAsCFNumber = NULL; + // check the name of the modem's callout device + bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, 0); + + // wander up the hierarchy until we find the level that can give us the + // vendor/product IDs and the product name, if available + io_registry_entry_t parent; + kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); + while (kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber) { + if (!productNameAsCFString) + productNameAsCFString = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR("Product Name"), + kCFAllocatorDefault, 0); + vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBVendorID), + kCFAllocatorDefault, 0); + productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBProductID), + kCFAllocatorDefault, 0); + io_registry_entry_t oldparent = parent; + kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent); + IOObjectRelease(oldparent); + } + + io_string_t ioPathName; + IORegistryEntryGetPath(service, kIOServicePlane, ioPathName); + portInfo->physName = ioPathName; + + if (bsdPathAsCFString) { + char path[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)bsdPathAsCFString, path, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->portName = path; + CFRelease(bsdPathAsCFString); + } + + if (productNameAsCFString) { + char productName[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)productNameAsCFString, productName, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->friendName = productName; + CFRelease(productNameAsCFString); + } + + if (vendorIdAsCFNumber) { + SInt32 vID; + if (CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID)) + portInfo->vendorID = vID; + CFRelease(vendorIdAsCFNumber); + } + + if (productIdAsCFNumber) { + SInt32 pID; + if (CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID)) + portInfo->productID = pID; + CFRelease(productIdAsCFNumber); + } + IOObjectRelease(service); + return retval; +} + +// IOKit callbacks registered via setupNotifications() +void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceDiscoveredOSX(serialService); +} + +void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceTerminatedOSX(serialService); +} + +/* + A device has been discovered via IOKit. + Create a QextPortInfo if possible, and emit the signal indicating that we've found it. +*/ +void QextSerialEnumeratorPrivate::onDeviceDiscoveredOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceDiscovered(info); +} + +/* + Notification via IOKit that a device has been removed. + Create a QextPortInfo if possible, and emit the signal indicating that it's gone. +*/ +void QextSerialEnumeratorPrivate::onDeviceTerminatedOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceRemoved(info); +} + +/* + Create matching dictionaries for the devices we want to get notifications for, + and add them to the current run loop. Invoke the callbacks that will be responding + to these notifications once to arm them, and discover any devices that + are currently connected at the time notifications are setup. +*/ +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool /*setup*/) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFRunLoopSourceRef notificationRunLoopSource; + CFMutableDictionaryRef classesToMatch; + CFMutableDictionaryRef cdcClassesToMatch; + io_iterator_t portIterator; + + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) { + qDebug() << "IOMasterPort returned:" << kernResult; + return false; + } + + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch == NULL) + qDebug("IOServiceMatching returned a NULL dictionary."); + else + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + if (!(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("couldn't create cdc matching dict"); + return false; + } + + // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. + classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); + cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); + + notificationPortRef = IONotificationPortCreate(masterPort); + if (notificationPortRef == NULL) { + qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); + return false; + } + + notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); + if (notificationRunLoopSource == NULL) { + qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); + return false; + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + return true; +} + diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_p.h b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_p.h new file mode 100644 index 0000000..c69e925 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef _QEXTSERIALENUMERATOR_P_H_ +#define _QEXTSERIALENUMERATOR_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialenumerator.h" + +#ifdef Q_OS_WIN +// needed for mingw to pull in appropriate dbt business... +// probably a better way to do this +// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html +# ifdef __MINGW32__ +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef _WIN32_WINDOWS +# define _WIN32_WINDOWS 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +# endif +# include +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC +# include +#endif /*Q_OS_MAC*/ + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) +# include +extern "C" { +# include +} +#endif + +class QextSerialRegistrationWidget; +class QextSerialEnumeratorPrivate +{ + Q_DECLARE_PUBLIC(QextSerialEnumerator) +public: + QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator); + ~QextSerialEnumeratorPrivate(); + void platformSpecificInit(); + void platformSpecificDestruct(); + + static QList getPorts_sys(); + bool setUpNotifications_sys(bool setup); + +#ifdef Q_OS_WIN + LRESULT onDeviceChanged(WPARAM wParam, LPARAM lParam); + bool matchAndDispatchChangedDevice(const QString &deviceID, const GUID &guid, WPARAM wParam); +# ifdef QT_GUI_LIB + QextSerialRegistrationWidget *notificationWidget; +# endif +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC + /*! + * Search for serial ports using IOKit. + * \param infoList list with result. + */ + static void iterateServicesOSX(io_object_t service, QList &infoList); + static bool getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo); + void onDeviceDiscoveredOSX(io_object_t service); + void onDeviceTerminatedOSX(io_object_t service); + friend void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + friend void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + + IONotificationPortRef notificationPortRef; +#endif // Q_OS_MAC + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + QSocketNotifier *notifier; + int notifierFd; + struct udev *udev; + struct udev_monitor *monitor; + + void _q_deviceEvent(); +#endif + +private: + QextSerialEnumerator *q_ptr; +}; + +#endif //_QEXTSERIALENUMERATOR_P_H_ diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_unix.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_unix.cpp new file mode 100644 index 0000000..80a4ad4 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_unix.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +} + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet."); + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup) + QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet"); + return false; +} diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_win.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_win.cpp new file mode 100644 index 0000000..55b71aa --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialenumerator_win.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "qextserialport.h" + +#ifdef QT_GUI_LIB +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +class QextSerialRegistrationWidget : public QWidget +#else +#include +class QextSerialRegistrationWidget : public QWindow +#endif +{ +public: + QextSerialRegistrationWidget(QextSerialEnumeratorPrivate *qese) { + this->qese = qese; + } + ~QextSerialRegistrationWidget() {} + +protected: + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + bool winEvent(MSG *message, long *result) { +#else + bool nativeEvent(const QByteArray & /*eventType*/, void *msg, long *result) { + MSG *message = static_cast(msg); +#endif + if (message->message == WM_DEVICECHANGE) { + qese->onDeviceChanged(message->wParam, message->lParam); + *result = 1; + return true; + } + return false; + } +private: + QextSerialEnumeratorPrivate *qese; +}; + +#endif // QT_GUI_LIB + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifdef QT_GUI_LIB + notificationWidget = 0; +#endif // QT_GUI_LIB +} + +/*! + default +*/ +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifdef QT_GUI_LIB + if (notificationWidget) + delete notificationWidget; +#endif +} + +// see http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426(v=vs.85).aspx +// for list of GUID classes +const GUID deviceClassGuids[] = +{ + // Ports (COM & LPT ports), Class = Ports + {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Modem, Class = Modem + {0x4D36E96D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Bluetooth Devices, Class = Bluetooth + {0xE0CBF06C, 0xCD8B, 0x4647, {0xBB, 0x8A, 0x26, 0x3B, 0x43, 0xF0, 0xF9, 0x74}}, + // Added by Arne Kristian Jansen, for use with com0com virtual ports (See Issue 54) + {0xDF799E12, 0x3C56, 0x421B, {0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78}} +}; + +/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ +#ifdef UNICODE + #define QStringToTCHAR(x) (wchar_t *) x.utf16() + #define PQStringToTCHAR(x) (wchar_t *) x->utf16() + #define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) + #define TCHARToQStringN(x,y) QString::fromUtf16((ushort *)(x),(y)) +#else + #define QStringToTCHAR(x) x.local8Bit().constData() + #define PQStringToTCHAR(x) x->local8Bit().constData() + #define TCHARToQString(x) QString::fromLocal8Bit((char *)(x)) + #define TCHARToQStringN(x,y) QString::fromLocal8Bit((char *)(x),(y)) +#endif /*UNICODE*/ + +/*! + \internal + Get value of specified property from the registry. + \a key handle to an open key. + \a property property name. + + return property value. +*/ +static QString getRegKeyValue(HKEY key, LPCTSTR property) +{ + DWORD size = 0; + DWORD type; + ::RegQueryValueEx(key, property, NULL, NULL, NULL, &size); + BYTE *buff = new BYTE[size]; + QString result; + if (::RegQueryValueEx(key, property, NULL, &type, buff, &size) == ERROR_SUCCESS) + result = TCHARToQString(buff); + ::RegCloseKey(key); + delete [] buff; + return result; +} + +/*! + \internal + Get specific property from registry. + \a devInfo pointer to the device information set that contains the interface + and its underlying device. Returned by SetupDiGetClassDevs() function. + \a devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. + this is returned by SetupDiGetDeviceInterfaceDetail() function. + \a property registry property. One of defined SPDRP_* constants. + + return property string. + */ +static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) +{ + DWORD buffSize = 0; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); + BYTE *buff = new BYTE[buffSize]; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); + QString result = TCHARToQString(buff); + delete [] buff; + return result; +} + +/*! + \internal +*/ +static bool getDeviceDetailsWin(QextPortInfo *portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData + , WPARAM wParam = DBT_DEVICEARRIVAL) +{ + portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME); + if (wParam == DBT_DEVICEARRIVAL) + portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); + portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME); + QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID); + HKEY devKey = ::SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + portInfo->portName = getRegKeyValue(devKey, TEXT("PortName")); + QRegExp idRx(QLatin1String("VID_(\\w+)&PID_(\\w+)")); + if (hardwareIDs.toUpper().contains(idRx)) { + bool dummy; + portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16); + portInfo->productID = idRx.cap(2).toInt(&dummy, 16); + //qDebug() << "got vid:" << vid << "pid:" << pid; + } + return true; +} + +/*! + \internal +*/ +static void enumerateDevicesWin(const GUID &guid, QList *infoList) +{ + HDEVINFO devInfo; + if ((devInfo = ::SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE) { + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for(int i = 0; ::SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + QextPortInfo info; + info.productID = info.vendorID = 0; + getDeviceDetailsWin(&info, devInfo, &devInfoData); + if (!info.portName.startsWith(QLatin1String("LPT"), Qt::CaseInsensitive)) + infoList->append(info); + } + ::SetupDiDestroyDeviceInfoList(devInfo); + } +} + + +static bool lessThan(const QextPortInfo &s1, const QextPortInfo &s2) +{ + if (s1.portName.startsWith(QLatin1String("COM")) + && s2.portName.startsWith(QLatin1String("COM"))) { + return s1.portName.mid(3).toInt() QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList ports; + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; iwinId(), &dbh, flags) == NULL) { + QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError(); + return false; + } + // setting up notifications doesn't tell us about devices already connected + // so get those manually + foreach (QextPortInfo port, getPorts_sys()) + Q_EMIT q->deviceDiscovered(port); + return true; +#endif // QT_GUI_LIB +} + +LRESULT QextSerialEnumeratorPrivate::onDeviceChanged(WPARAM wParam, LPARAM lParam) +{ + if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + // delimiters are different across APIs...change to backslash. ugh. + QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace(QLatin1String("#"), QLatin1String("\\")); + + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; ideviceDiscovered(info); + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + Q_EMIT q->deviceRemoved(info); + break; + } + } + SetupDiDestroyDeviceInfoList(devInfo); + } + return rv; +} diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.cpp new file mode 100644 index 0000000..119bef8 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.cpp @@ -0,0 +1,1011 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include + +/*! + \class PortSettings + + \brief The PortSettings class contain port settings + + Structure to contain port settings. + + \code + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; + \endcode +*/ + +QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q) + :lock(QReadWriteLock::Recursive), q_ptr(q) +{ + lastErr = E_NO_ERROR; + settings.BaudRate = BAUD9600; + settings.Parity = PAR_NONE; + settings.FlowControl = FLOW_OFF; + settings.DataBits = DATA_8; + settings.StopBits = STOP_1; + settings.Timeout_Millisec = 10; + settingsDirtyFlags = DFE_ALL; + + platformSpecificInit(); +} + +QextSerialPortPrivate::~QextSerialPortPrivate() +{ + platformSpecificDestruct(); +} + +void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update) +{ + switch (baudRate) { +#ifdef Q_OS_WIN + //Windows Special + case BAUD14400: + case BAUD56000: + case BAUD128000: + case BAUD256000: + QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<isOpen()) + updatePortSettings(); + break; +#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC)) + default: + QESP_WARNING()<<"QextSerialPort does not support baudRate:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update) +{ + switch(dataBits) { + + case DATA_5: + if (settings.StopBits == STOP_2) { + QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); + } + else { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_6: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_7: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_8: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support Data bits:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update) +{ + switch (stopBits) { + + /*one stop bit*/ + case STOP_1: + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + break; + +#ifdef Q_OS_WIN + /*1.5 stop bits*/ + case STOP_1_5: + QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); + if (settings.DataBits != DATA_5) { + QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; +#endif + + /*two stop bits*/ + case STOP_2: + if (settings.DataBits == DATA_5) { + QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support stop bits: "<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update) +{ + settings.FlowControl = flow; + settingsDirtyFlags |= DFE_Flow; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setTimeout(long millisec, bool update) +{ + settings.Timeout_Millisec = millisec; + settingsDirtyFlags |= DFE_TimeOut; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update) +{ + setBaudRate(settings.BaudRate, false); + setDataBits(settings.DataBits, false); + setStopBits(settings.StopBits, false); + setParity(settings.Parity, false); + setFlowControl(settings.FlowControl, false); + setTimeout(settings.Timeout_Millisec, false); + settingsDirtyFlags = DFE_ALL; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + + +void QextSerialPortPrivate::_q_canRead() +{ + qint64 maxSize = bytesAvailable_sys(); + if (maxSize > 0) { + char *writePtr = readBuffer.reserve(size_t(maxSize)); + qint64 bytesRead = readData_sys(writePtr, maxSize); + if (bytesRead < maxSize) + readBuffer.chop(maxSize - bytesRead); + Q_Q(QextSerialPort); + Q_EMIT q->readyRead(); + } +} + +/*! \class QextSerialPort + + \brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems. + + \section1 Usage + QextSerialPort offers both a polling and event driven API. Event driven + is typically easier to use, since you never have to worry about checking + for new data. + + \bold Example + \code + QextSerialPort *port = new QextSerialPort("COM1"); + connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable())); + port->open(); + + void MyClass::onDataAvailable() + { + QByteArray data = port->readAll(); + processNewData(usbdata); + } + \endcode + + \section1 Compatibility + The user will be notified of errors and possible portability conflicts at run-time + by default. + + For example, if a application has used BAUD1800, when it is runing under unix, you + will get following message. + + \code + QextSerialPort Portability Warning: Windows does not support baudRate:1800 + \endcode + + This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings) + or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project. + + + \bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang +*/ + +/*! + \enum QextSerialPort::QueryMode + + This enum type specifies query mode used in a serial port: + + \value Polling + asynchronously read and write + \value EventDriven + synchronously read and write +*/ + +/*! + \fn void QextSerialPort::dsrChanged(bool status) + This signal is emitted whenever dsr line has changed its state. You may + use this signal to check if device is connected. + + \a status true when DSR signal is on, false otherwise. + */ + + +/*! + \fn QueryMode QextSerialPort::queryMode() const + Get query mode. + */ + +/*! + Default constructor. Note that the name of the device used by a QextSerialPort is dependent on + your OS. Possible naming conventions and their associated OS are: + + \code + + OS Constant Used By Naming Convention + ------------- ------------- ------------------------ + Q_OS_WIN Windows COM1, COM2 + Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2 + Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0 + Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb + Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02 + Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1 + Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01 + Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1 + /dev/ttyS0, /dev/ttyS1 + \endcode + + This constructor assigns the device name to the name of the first port on the specified system. + See the other constructors if you need to open a different port. Default \a mode is EventDriven. + As a subclass of QObject, \a parent can be specified. +*/ + +QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ +#ifdef Q_OS_WIN + setPortName(QLatin1String("COM1")); + +#elif defined(Q_OS_IRIX) + setPortName(QLatin1String("/dev/ttyf1")); + +#elif defined(Q_OS_HPUX) + setPortName(QLatin1String("/dev/tty1p0")); + +#elif defined(Q_OS_SOLARIS) + setPortName(QLatin1String("/dev/ttya")); + +#elif defined(Q_OS_OSF) //formally DIGITAL UNIX + setPortName(QLatin1String("/dev/tty01")); + +#elif defined(Q_OS_FREEBSD) + setPortName(QLatin1String("/dev/ttyd1")); + +#elif defined(Q_OS_OPENBSD) + setPortName(QLatin1String("/dev/tty00")); + +#else + setPortName(QLatin1String("/dev/ttyS0")); +#endif + setQueryMode(mode); +} + +/*! + Constructs a serial port attached to the port specified by name. + \a name is the name of the device, which is windowsystem-specific, + e.g."COM1" or "/dev/ttyS0". \a mode +*/ +QextSerialPort::QextSerialPort(const QString &name, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + setQueryMode(mode); + setPortName(name); +} + +/*! + Constructs a port with default name and specified \a settings. +*/ +QextSerialPort::QextSerialPort(const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Constructs a port with specified \a name , \a mode and \a settings. +*/ +QextSerialPort::QextSerialPort(const QString &name, const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setPortName(name); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Opens a serial port and sets its OpenMode to \a mode. + Note that this function does not specify which device to open. + Returns true if successful; otherwise returns false.This function has no effect + if the port associated with the class is already open. The port is also + configured to the current settings, as stored in the settings structure. +*/ +bool QextSerialPort::open(OpenMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != QIODevice::NotOpen && !isOpen()) + d->open_sys(mode); + + return isOpen(); +} + + +/*! \reimp + Closes a serial port. This function has no effect if the serial port associated with the class + is not currently open. +*/ +void QextSerialPort::close() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) { + // Be a good QIODevice and call QIODevice::close() before really close() + // so the aboutToClose() signal is emitted at the proper time + QIODevice::close(); // mark ourselves as closed + d->close_sys(); + d->readBuffer.clear(); + } +} + +/*! + Flushes all pending I/O to the serial port. This function has no effect if the serial port + associated with the class is not currently open. +*/ +void QextSerialPort::flush() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->flush_sys(); +} + +/*! \reimp + Returns the number of bytes waiting in the port's receive queue. This function will return 0 if + the port is not currently open, or -1 on error. +*/ +qint64 QextSerialPort::bytesAvailable() const +{ + QWriteLocker locker(&d_func()->lock); + if (isOpen()) { + qint64 bytes = d_func()->bytesAvailable_sys(); + if (bytes != -1) { + return bytes + d_func()->readBuffer.size() + + QIODevice::bytesAvailable(); + } else { + return -1; + } + } + return 0; +} + +/*! \reimp + +*/ +bool QextSerialPort::canReadLine() const +{ + QReadLocker locker(&d_func()->lock); + return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine(); +} + +/*! + * Set desired serial communication handling style. You may choose from polling + * or event driven approach. This function does nothing when port is open; to + * apply changes port must be reopened. + * + * In event driven approach read() and write() functions are acting + * asynchronously. They return immediately and the operation is performed in + * the background, so they doesn't freeze the calling thread. + * To determine when operation is finished, QextSerialPort runs separate thread + * and monitors serial port events. Whenever the event occurs, adequate signal + * is emitted. + * + * When polling is set, read() and write() are acting synchronously. Signals are + * not working in this mode and some functions may not be available. The advantage + * of polling is that it generates less overhead due to lack of signals emissions + * and it doesn't start separate thread to monitor events. + * + * Generally event driven approach is more capable and friendly, although some + * applications may need as low overhead as possible and then polling comes. + * + * \a mode query mode. + */ +void QextSerialPort::setQueryMode(QueryMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != d->queryMode) { + d->queryMode = mode; + } +} + +/*! + Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". +*/ +void QextSerialPort::setPortName(const QString &name) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + d->port = name; +} + +/*! + Returns the name set by setPortName(). +*/ +QString QextSerialPort::portName() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->port; +} + +QextSerialPort::QueryMode QextSerialPort::queryMode() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->queryMode; +} + +/*! + Reads all available data from the device, and returns it as a QByteArray. + This function has no way of reporting errors; returning an empty QByteArray() + can mean either that no data was currently available for reading, or that an error occurred. +*/ +QByteArray QextSerialPort::readAll() +{ + int avail = this->bytesAvailable(); + return (avail > 0) ? this->read(avail) : QByteArray(); +} + +/*! + Returns the baud rate of the serial port. For a list of possible return values see + the definition of the enum BaudRateType. +*/ +BaudRateType QextSerialPort::baudRate() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.BaudRate; +} + +/*! + Returns the number of data bits used by the port. For a list of possible values returned by + this function, see the definition of the enum DataBitsType. +*/ +DataBitsType QextSerialPort::dataBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.DataBits; +} + +/*! + Returns the type of parity used by the port. For a list of possible values returned by + this function, see the definition of the enum ParityType. +*/ +ParityType QextSerialPort::parity() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.Parity; +} + +/*! + Returns the number of stop bits used by the port. For a list of possible return values, see + the definition of the enum StopBitsType. +*/ +StopBitsType QextSerialPort::stopBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.StopBits; +} + +/*! + Returns the type of flow control used by the port. For a list of possible values returned + by this function, see the definition of the enum FlowType. +*/ +FlowType QextSerialPort::flowControl() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.FlowControl; +} + +/*! + \reimp + Returns true if device is sequential, otherwise returns false. Serial port is sequential device + so this function always returns true. Check QIODevice::isSequential() documentation for more + information. +*/ +bool QextSerialPort::isSequential() const +{ + return true; +} + +/*! + Return the error number, or 0 if no error occurred. +*/ +ulong QextSerialPort::lastError() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->lastErr; +} + +/*! + Returns the line status as stored by the port function. This function will retrieve the states + of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines + can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned + long with specific bits indicating which lines are high. The following constants should be used + to examine the states of individual lines: + + \code + Mask Line + ------ ---- + LS_CTS CTS + LS_DSR DSR + LS_DCD DCD + LS_RI RI + LS_RTS RTS (POSIX only) + LS_DTR DTR (POSIX only) + LS_ST Secondary TXD (POSIX only) + LS_SR Secondary RXD (POSIX only) + \endcode + + This function will return 0 if the port associated with the class is not currently open. +*/ +unsigned long QextSerialPort::lineStatus() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + return d->lineStatus_sys(); + return 0; +} + +/*! + Returns a human-readable description of the last device error that occurred. +*/ +QString QextSerialPort::errorString() +{ + Q_D(QextSerialPort); + QReadLocker locker(&d->lock); + switch(d->lastErr) { + case E_NO_ERROR: + return tr("No Error has occurred"); + case E_INVALID_FD: + return tr("Invalid file descriptor (port was not opened correctly)"); + case E_NO_MEMORY: + return tr("Unable to allocate memory tables (POSIX)"); + case E_CAUGHT_NON_BLOCKED_SIGNAL: + return tr("Caught a non-blocked signal (POSIX)"); + case E_PORT_TIMEOUT: + return tr("Operation timed out (POSIX)"); + case E_INVALID_DEVICE: + return tr("The file opened by the port is not a valid device"); + case E_BREAK_CONDITION: + return tr("The port detected a break condition"); + case E_FRAMING_ERROR: + return tr("The port detected a framing error (usually caused by incorrect baud rate settings)"); + case E_IO_ERROR: + return tr("There was an I/O error while communicating with the port"); + case E_BUFFER_OVERRUN: + return tr("Character buffer overrun"); + case E_RECEIVE_OVERFLOW: + return tr("Receive buffer overflow"); + case E_RECEIVE_PARITY_ERROR: + return tr("The port detected a parity error in the received data"); + case E_TRANSMIT_OVERFLOW: + return tr("Transmit buffer overflow"); + case E_READ_FAILED: + return tr("General read operation failure"); + case E_WRITE_FAILED: + return tr("General write operation failure"); + case E_FILE_NOT_FOUND: + return tr("The %1 file doesn't exists").arg(this->portName()); + case E_PERMISSION_DENIED: + return tr("Permission denied"); + case E_AGAIN: + return tr("Device is already locked"); + default: + return tr("Unknown error: %1").arg(d->lastErr); + } +} + +/*! + Destructs the QextSerialPort object. +*/ +QextSerialPort::~QextSerialPort() +{ + if (isOpen()) { + close(); + } + delete d_ptr; +} + +/*! + Sets the flow control used by the port to \a flow. Possible values of flow are: + \code + FLOW_OFF No flow control + FLOW_HARDWARE Hardware (RTS/CTS) flow control + FLOW_XONXOFF Software (XON/XOFF) flow control + \endcode +*/ +void QextSerialPort::setFlowControl(FlowType flow) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.FlowControl != flow) + d->setFlowControl(flow, true); +} + +/*! + Sets the parity associated with the serial port to \a parity. The possible values of parity are: + \code + PAR_SPACE Space Parity + PAR_MARK Mark Parity + PAR_NONE No Parity + PAR_EVEN Even Parity + PAR_ODD Odd Parity + \endcode +*/ +void QextSerialPort::setParity(ParityType parity) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Parity != parity) + d->setParity(parity, true); +} + +/*! + Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are: + \code + DATA_5 5 data bits + DATA_6 6 data bits + DATA_7 7 data bits + DATA_8 8 data bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 5 data bits cannot be used with 2 stop bits. + \o 1.5 stop bits can only be used with 5 data bits. + \o 8 data bits cannot be used with space parity on POSIX systems. + \endlist + */ +void QextSerialPort::setDataBits(DataBitsType dataBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.DataBits != dataBits) + d->setDataBits(dataBits, true); +} + +/*! + Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are: + \code + STOP_1 1 stop bit + STOP_1_5 1.5 stop bits + STOP_2 2 stop bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 2 stop bits cannot be used with 5 data bits. + \o 1.5 stop bits cannot be used with 6 or more data bits. + \o POSIX does not support 1.5 stop bits. + \endlist +*/ +void QextSerialPort::setStopBits(StopBitsType stopBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.StopBits != stopBits) + d->setStopBits(stopBits, true); +} + +/*! + Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on + all platforms. The following table shows translations of the various baud rate + constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * + are speeds that are usable on both Windows and POSIX. + \code + + RATE Windows Speed POSIX Speed + ----------- ------------- ----------- + BAUD50 X 50 + BAUD75 X 75 + *BAUD110 110 110 + BAUD134 X 134.5 + BAUD150 X 150 + BAUD200 X 200 + *BAUD300 300 300 + *BAUD600 600 600 + *BAUD1200 1200 1200 + BAUD1800 X 1800 + *BAUD2400 2400 2400 + *BAUD4800 4800 4800 + *BAUD9600 9600 9600 + BAUD14400 14400 X + *BAUD19200 19200 19200 + *BAUD38400 38400 38400 + BAUD56000 56000 X + *BAUD57600 57600 57600 + BAUD76800 X 76800 + *BAUD115200 115200 115200 + BAUD128000 128000 X + BAUD230400 X 230400 + BAUD256000 256000 X + BAUD460800 X 460800 + BAUD500000 X 500000 + BAUD576000 X 576000 + BAUD921600 X 921600 + BAUD1000000 X 1000000 + BAUD1152000 X 1152000 + BAUD1500000 X 1500000 + BAUD2000000 X 2000000 + BAUD2500000 X 2500000 + BAUD3000000 X 3000000 + BAUD3500000 X 3500000 + BAUD4000000 X 4000000 + \endcode +*/ + +void QextSerialPort::setBaudRate(BaudRateType baudRate) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.BaudRate != baudRate) + d->setBaudRate(baudRate, true); +} + +/*! + For Unix: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Note that this is a per-character timeout, i.e. the port will wait this long for each + individual character, not for the whole read operation. This timeout also applies to the + bytesWaiting() function. + + \bold note: + POSIX does not support millisecond-level control for I/O timeout values. Any + timeout set using this function will be set to the next lowest tenth of a second for + the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds + will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and + writing the port. However millisecond-level control is allowed by the select() system call, + so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for + the purpose of detecting available bytes in the read buffer. + + For Windows: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Setting 0 indicates that timeouts are not used for read nor write operations; + however read() and write() functions will still block. Set -1 to provide + non-blocking behaviour (read() and write() will return immediately). + + \bold note: this function does nothing in event driven mode. +*/ +void QextSerialPort::setTimeout(long millisec) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Timeout_Millisec != millisec) + d->setTimeout(millisec, true); +} + +/*! + Sets DTR line to the requested state (\a set default to high). This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setDtr(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setDtr_sys(set); +} + +/*! + Sets RTS line to the requested state \a set (high by default). + This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setRts(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setRts_sys(set); +} + +/*! \reimp + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::readData(char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + qint64 bytesFromBuffer = 0; + if (!d->readBuffer.isEmpty()) { + bytesFromBuffer = d->readBuffer.read(data, maxSize); + if (bytesFromBuffer == maxSize) + return bytesFromBuffer; + } + qint64 bytesFromDevice = d->readData_sys(data+bytesFromBuffer, maxSize-bytesFromBuffer); + if (bytesFromDevice < 0) { + return -1; + } + return bytesFromBuffer + bytesFromDevice; +} + +/*! \reimp + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::writeData(const char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + return d->writeData_sys(data, maxSize); +} + +#include "moc_qextserialport.cpp" diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport.h b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.h new file mode 100644 index 0000000..5334e94 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.h @@ -0,0 +1,240 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_H_ +#define _QEXTSERIALPORT_H_ + +#include +#include "qextserialport_global.h" +#ifdef Q_OS_UNIX +#include +#endif +/*line status constants*/ +// ### QESP2.0 move to enum +#define LS_CTS 0x01 +#define LS_DSR 0x02 +#define LS_DCD 0x04 +#define LS_RI 0x08 +#define LS_RTS 0x10 +#define LS_DTR 0x20 +#define LS_ST 0x40 +#define LS_SR 0x80 + +/*error constants*/ +// ### QESP2.0 move to enum +#define E_NO_ERROR 0 +#define E_INVALID_FD 1 +#define E_NO_MEMORY 2 +#define E_CAUGHT_NON_BLOCKED_SIGNAL 3 +#define E_PORT_TIMEOUT 4 +#define E_INVALID_DEVICE 5 +#define E_BREAK_CONDITION 6 +#define E_FRAMING_ERROR 7 +#define E_IO_ERROR 8 +#define E_BUFFER_OVERRUN 9 +#define E_RECEIVE_OVERFLOW 10 +#define E_RECEIVE_PARITY_ERROR 11 +#define E_TRANSMIT_OVERFLOW 12 +#define E_READ_FAILED 13 +#define E_WRITE_FAILED 14 +#define E_FILE_NOT_FOUND 15 +#define E_PERMISSION_DENIED 16 +#define E_AGAIN 17 + +enum BaudRateType +{ +#if defined(Q_OS_UNIX) || defined(qdoc) + BAUD50 = 50, //POSIX ONLY + BAUD75 = 75, //POSIX ONLY + BAUD134 = 134, //POSIX ONLY + BAUD150 = 150, //POSIX ONLY + BAUD200 = 200, //POSIX ONLY + BAUD1800 = 1800, //POSIX ONLY +# if defined(B76800) || defined(qdoc) + BAUD76800 = 76800, //POSIX ONLY +# endif +# if (defined(B230400) && defined(B4000000)) || defined(qdoc) + BAUD230400 = 230400, //POSIX ONLY + BAUD460800 = 460800, //POSIX ONLY + BAUD500000 = 500000, //POSIX ONLY + BAUD576000 = 576000, //POSIX ONLY + BAUD921600 = 921600, //POSIX ONLY + BAUD1000000 = 1000000, //POSIX ONLY + BAUD1152000 = 1152000, //POSIX ONLY + BAUD1500000 = 1500000, //POSIX ONLY + BAUD2000000 = 2000000, //POSIX ONLY + BAUD2500000 = 2500000, //POSIX ONLY + BAUD3000000 = 3000000, //POSIX ONLY + BAUD3500000 = 3500000, //POSIX ONLY + BAUD4000000 = 4000000, //POSIX ONLY +# endif +#endif //Q_OS_UNIX +#if defined(Q_OS_WIN) || defined(qdoc) + BAUD14400 = 14400, //WINDOWS ONLY + BAUD56000 = 56000, //WINDOWS ONLY + BAUD128000 = 128000, //WINDOWS ONLY + BAUD256000 = 256000, //WINDOWS ONLY +#endif //Q_OS_WIN + BAUD110 = 110, + BAUD300 = 300, + BAUD600 = 600, + BAUD1200 = 1200, + BAUD2400 = 2400, + BAUD4800 = 4800, + BAUD9600 = 9600, + BAUD19200 = 19200, + BAUD38400 = 38400, + BAUD57600 = 57600, + BAUD115200 = 115200 +}; + +enum DataBitsType +{ + DATA_5 = 5, + DATA_6 = 6, + DATA_7 = 7, + DATA_8 = 8 +}; + +enum ParityType +{ + PAR_NONE, + PAR_ODD, + PAR_EVEN, +#if defined(Q_OS_WIN) || defined(qdoc) + PAR_MARK, //WINDOWS ONLY +#endif + PAR_SPACE +}; + +enum StopBitsType +{ + STOP_1, +#if defined(Q_OS_WIN) || defined(qdoc) + STOP_1_5, //WINDOWS ONLY +#endif + STOP_2 +}; + +enum FlowType +{ + FLOW_OFF, + FLOW_HARDWARE, + FLOW_XONXOFF +}; + +/** + * structure to contain port settings + */ +struct PortSettings +{ + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; +}; + +class QextSerialPortPrivate; +class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialPort) + Q_ENUMS(QueryMode) + Q_PROPERTY(QString portName READ portName WRITE setPortName) + Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode) +public: + enum QueryMode { + Polling, + EventDriven + }; + + explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0); + QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent=0); + + ~QextSerialPort(); + + QString portName() const; + QueryMode queryMode() const; + BaudRateType baudRate() const; + DataBitsType dataBits() const; + ParityType parity() const; + StopBitsType stopBits() const; + FlowType flowControl() const; + + bool open(OpenMode mode); + bool isSequential() const; + void close(); + void flush(); + qint64 bytesAvailable() const; + bool canReadLine() const; + QByteArray readAll(); + + ulong lastError() const; + + ulong lineStatus(); + QString errorString(); + +public Q_SLOTS: + void setPortName(const QString &name); + void setQueryMode(QueryMode mode); + void setBaudRate(BaudRateType); + void setDataBits(DataBitsType); + void setParity(ParityType); + void setStopBits(StopBitsType); + void setFlowControl(FlowType); + void setTimeout(long); + + void setDtr(bool set=true); + void setRts(bool set=true); + +Q_SIGNALS: + void dsrChanged(bool status); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(QextSerialPort) + +#ifdef Q_OS_WIN + Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE)) +#endif + Q_PRIVATE_SLOT(d_func(), void _q_canRead()) + + QextSerialPortPrivate *const d_ptr; +}; + +#endif diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport.pri b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.pri new file mode 100644 index 0000000..461d56f --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +PUBLIC_HEADERS += $$PWD/qextserialport.h \ + $$PWD/qextserialenumerator.h \ + $$PWD/qextserialport_global.h + +HEADERS += $$PUBLIC_HEADERS \ + $$PWD/qextserialport_p.h \ + $$PWD/qextserialenumerator_p.h \ + +SOURCES += $$PWD/qextserialport.cpp \ + $$PWD/qextserialenumerator.cpp +unix { + SOURCES += $$PWD/qextserialport_unix.cpp + linux* { + SOURCES += $$PWD/qextserialenumerator_linux.cpp + } else:macx { + SOURCES += $$PWD/qextserialenumerator_osx.cpp + } else { + SOURCES += $$PWD/qextserialenumerator_unix.cpp + } +} +win32:SOURCES += $$PWD/qextserialport_win.cpp \ + $$PWD/qextserialenumerator_win.cpp + +linux*{ + !qesp_linux_udev:DEFINES += QESP_NO_UDEV + qesp_linux_udev: LIBS += -ludev +} + +macx:LIBS += -framework IOKit -framework CoreFoundation +win32:LIBS += -lsetupapi -ladvapi32 -luser32 + +# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work +linux*:DEFINES += __linux__ diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport_global.h b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_global.h new file mode 100644 index 0000000..824d455 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_global.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTSERIALPORT_GLOBAL_H +#define QEXTSERIALPORT_GLOBAL_H + +#include + +#ifdef QEXTSERIALPORT_BUILD_SHARED +# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT +#elif defined(QEXTSERIALPORT_USING_SHARED) +# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT +#else +# define QEXTSERIALPORT_EXPORT +#endif + +// ### for compatible with old version. should be removed in QESP 2.0 +#ifdef _TTY_NOWARN_ +# define QESP_NO_WARN +#endif +#ifdef _TTY_NOWARN_PORT_ +# define QESP_NO_PORTABILITY_WARN +#endif + +/*if all warning messages are turned off, flag portability warnings to be turned off as well*/ +#ifdef QESP_NO_WARN +# define QESP_NO_PORTABILITY_WARN +#endif + +/*macros for warning and debug messages*/ +#ifdef QESP_NO_PORTABILITY_WARN +# define QESP_PORTABILITY_WARNING while (false)qWarning +#else +# define QESP_PORTABILITY_WARNING qWarning +#endif /*QESP_NOWARN_PORT*/ + +#ifdef QESP_NO_WARN +# define QESP_WARNING while (false)qWarning +#else +# define QESP_WARNING qWarning +#endif /*QESP_NOWARN*/ + +#endif // QEXTSERIALPORT_GLOBAL_H + diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport_p.h b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_p.h new file mode 100644 index 0000000..d278a17 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_p.h @@ -0,0 +1,251 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_P_H_ +#define _QEXTSERIALPORT_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialport.h" +#include +#ifdef Q_OS_UNIX +# include +#elif (defined Q_OS_WIN) +# include +#endif +#include + +// This is QextSerialPort's read buffer, needed by posix system. +// ref: QRingBuffer & QIODevicePrivateLinearBuffer +class QextReadBuffer +{ +public: + inline QextReadBuffer(size_t growth=4096) + : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { + } + + ~QextReadBuffer() { + delete [] buf; + } + + inline void clear() { + first = buf; + len = 0; + } + + inline int size() const { + return len; + } + + inline bool isEmpty() const { + return len == 0; + } + + inline int read(char *target, int size) { + int r = qMin(size, len); + if (r == 1) { + *target = *first; + --len; + ++first; + } else { + memcpy(target, first, r); + len -= r; + first += r; + } + return r; + } + + inline char *reserve(size_t size) { + if ((first - buf) + len + size > capacity) { + size_t newCapacity = qMax(capacity, basicBlockSize); + while (newCapacity < len + size) + newCapacity *= 2; + if (newCapacity > capacity) { + // allocate more space + char *newBuf = new char[newCapacity]; + memmove(newBuf, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf, first, len); + } + first = buf; + } + char *writePtr = first + len; + len += (int)size; + return writePtr; + } + + inline void chop(int size) { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + + inline void squeeze() { + if (first != buf) { + memmove(buf, first, len); + first = buf; + } + size_t newCapacity = basicBlockSize; + while (newCapacity < size_t(len)) + newCapacity *= 2; + if (newCapacity < capacity) { + char *tmp = static_cast(realloc(buf, newCapacity)); + if (tmp) { + buf = tmp; + capacity = newCapacity; + } + } + } + + inline QByteArray readAll() { + char *f = first; + int l = len; + clear(); + return QByteArray(f, l); + } + + inline int readLine(char *target, int size) { + int r = qMin(size, len); + char *eol = static_cast(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return int(r); + } + + inline bool canReadLine() const { + return memchr(first, '\n', len); + } + +private: + int len; + char *first; + char *buf; + size_t capacity; + size_t basicBlockSize; +}; + +class QWinEventNotifier; +class QReadWriteLock; +class QSocketNotifier; + +class QextSerialPortPrivate +{ + Q_DECLARE_PUBLIC(QextSerialPort) +public: + QextSerialPortPrivate(QextSerialPort *q); + ~QextSerialPortPrivate(); + enum DirtyFlagEnum + { + DFE_BaudRate = 0x0001, + DFE_Parity = 0x0002, + DFE_StopBits = 0x0004, + DFE_DataBits = 0x0008, + DFE_Flow = 0x0010, + DFE_TimeOut = 0x0100, + DFE_ALL = 0x0fff, + DFE_Settings_Mask = 0x00ff //without TimeOut + }; + mutable QReadWriteLock lock; + QString port; + PortSettings settings; + QextReadBuffer readBuffer; + int settingsDirtyFlags; + ulong lastErr; + QextSerialPort::QueryMode queryMode; + + // platform specific members +#ifdef Q_OS_UNIX + int fd; + QSocketNotifier *readNotifier; + struct termios currentTermios; + struct termios oldTermios; +#elif (defined Q_OS_WIN) + HANDLE handle; + OVERLAPPED overlap; + COMMCONFIG commConfig; + COMMTIMEOUTS commTimeouts; + QWinEventNotifier *winEventNotifier; + DWORD eventMask; + QList pendingWrites; + QReadWriteLock *bytesToWriteLock; +#endif + + /*fill PortSettings*/ + void setBaudRate(BaudRateType baudRate, bool update=true); + void setDataBits(DataBitsType dataBits, bool update=true); + void setParity(ParityType parity, bool update=true); + void setStopBits(StopBitsType stopbits, bool update=true); + void setFlowControl(FlowType flow, bool update=true); + void setTimeout(long millisec, bool update=true); + void setPortSettings(const PortSettings &settings, bool update=true); + + void platformSpecificDestruct(); + void platformSpecificInit(); + void translateError(ulong error); + void updatePortSettings(); + + qint64 readData_sys(char *data, qint64 maxSize); + qint64 writeData_sys(const char *data, qint64 maxSize); + void setDtr_sys(bool set=true); + void setRts_sys(bool set=true); + bool open_sys(QIODevice::OpenMode mode); + bool close_sys(); + bool flush_sys(); + ulong lineStatus_sys(); + qint64 bytesAvailable_sys() const; + +#ifdef Q_OS_WIN + void _q_onWinEvent(HANDLE h); +#endif + void _q_canRead(); + + QextSerialPort *q_ptr; +}; + +#endif //_QEXTSERIALPORT_P_H_ diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport_unix.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_unix.cpp new file mode 100644 index 0000000..4c02a20 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_unix.cpp @@ -0,0 +1,460 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void QextSerialPortPrivate::platformSpecificInit() +{ + fd = 0; + readNotifier = 0; +} + +/*! + Standard destructor. +*/ +void QextSerialPortPrivate::platformSpecificDestruct() +{ +} + +static QString fullPortName(const QString &name) +{ + if (name.startsWith(QLatin1Char('/'))) + return name; + return QLatin1String("/dev/")+name; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + //note: linux 2.6.21 seems to ignore O_NDELAY flag + if ((fd = ::open(fullPortName(port).toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { + + /*In the Private class, We can not call QIODevice::open()*/ + q->setOpenMode(mode); // Flag the port as opened + ::tcgetattr(fd, &oldTermios); // Save the old termios + currentTermios = oldTermios; // Make a working copy + ::cfmakeraw(¤tTermios); // Enable raw access + + /*set up other port settings*/ + currentTermios.c_cflag |= CREAD|CLOCAL; + currentTermios.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + currentTermios.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + currentTermios.c_oflag &= (~OPOST); + currentTermios.c_cc[VMIN] = 0; +#ifdef _POSIX_VDISABLE // Is a disable character available on this system? + // Some systems allow for per-device disable-characters, so get the + // proper value for the configured device + const long vdisable = ::fpathconf(fd, _PC_VDISABLE); + currentTermios.c_cc[VINTR] = vdisable; + currentTermios.c_cc[VQUIT] = vdisable; + currentTermios.c_cc[VSTART] = vdisable; + currentTermios.c_cc[VSTOP] = vdisable; + currentTermios.c_cc[VSUSP] = vdisable; +#endif //_POSIX_VDISABLE + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + if (queryMode == QextSerialPort::EventDriven) { + readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); + q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead())); + } + return true; + } else { + translateError(errno); + return false; + } +} + +bool QextSerialPortPrivate::close_sys() +{ + // Force a flush and then restore the original termios + flush_sys(); + // Using both TCSAFLUSH and TCSANOW here discards any pending input + ::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios + ::close(fd); + if (readNotifier) { + delete readNotifier; + readNotifier = 0; + } + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + ::tcdrain(fd); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + int bytesQueued; + if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) { + return (qint64)-1; + } + return bytesQueued; +} + +/*! + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + switch (error) { + case EBADF: + case ENOTTY: + lastErr = E_INVALID_FD; + break; + case EINTR: + lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL; + break; + case ENOMEM: + lastErr = E_NO_MEMORY; + break; + case EACCES: + lastErr = E_PERMISSION_DENIED; + break; + case EAGAIN: + lastErr = E_AGAIN; + break; + } +} + +void QextSerialPortPrivate::setDtr_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_DTR; + else + status &= ~TIOCM_DTR; + ::ioctl(fd, TIOCMSET, &status); +} + +void QextSerialPortPrivate::setRts_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_RTS; + else + status &= ~TIOCM_RTS; + ::ioctl(fd, TIOCMSET, &status); +} + +unsigned long QextSerialPortPrivate::lineStatus_sys() +{ + unsigned long Status=0, Temp=0; + ::ioctl(fd, TIOCMGET, &Temp); + if (Temp & TIOCM_CTS) Status |= LS_CTS; + if (Temp & TIOCM_DSR) Status |= LS_DSR; + if (Temp & TIOCM_RI) Status |= LS_RI; + if (Temp & TIOCM_CD) Status |= LS_DCD; + if (Temp & TIOCM_DTR) Status |= LS_DTR; + if (Temp & TIOCM_RTS) Status |= LS_RTS; + if (Temp & TIOCM_ST) Status |= LS_ST; + if (Temp & TIOCM_SR) Status |= LS_SR; + return Status; +} + +/*! + Reads a block of data from the serial port. This function will read at most maxSize bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + int retVal = ::read(fd, data, maxSize); + if (retVal == -1) + lastErr = E_READ_FAILED; + + return retVal; +} + +/*! + Writes a block of data to the serial port. This function will write maxSize bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + int retVal = ::write(fd, data, maxSize); + if (retVal == -1) + lastErr = E_WRITE_FAILED; + + return (qint64)retVal; +} + +static void setBaudRate2Termios(termios *config, int baudRate) +{ +#ifdef CBAUD + config->c_cflag &= (~CBAUD); + config->c_cflag |= baudRate; +#else + ::cfsetispeed(config, baudRate); + ::cfsetospeed(config, baudRate); +#endif +} + +/* + All the platform settings was performed in this function. +*/ +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_func()->isOpen() || !settingsDirtyFlags) + return; + + if (settingsDirtyFlags & DFE_BaudRate) { + switch (settings.BaudRate) { + case BAUD50: + setBaudRate2Termios(¤tTermios, B50); + break; + case BAUD75: + setBaudRate2Termios(¤tTermios, B75); + break; + case BAUD110: + setBaudRate2Termios(¤tTermios, B110); + break; + case BAUD134: + setBaudRate2Termios(¤tTermios, B134); + break; + case BAUD150: + setBaudRate2Termios(¤tTermios, B150); + break; + case BAUD200: + setBaudRate2Termios(¤tTermios, B200); + break; + case BAUD300: + setBaudRate2Termios(¤tTermios, B300); + break; + case BAUD600: + setBaudRate2Termios(¤tTermios, B600); + break; + case BAUD1200: + setBaudRate2Termios(¤tTermios, B1200); + break; + case BAUD1800: + setBaudRate2Termios(¤tTermios, B1800); + break; + case BAUD2400: + setBaudRate2Termios(¤tTermios, B2400); + break; + case BAUD4800: + setBaudRate2Termios(¤tTermios, B4800); + break; + case BAUD9600: + setBaudRate2Termios(¤tTermios, B9600); + break; + case BAUD19200: + setBaudRate2Termios(¤tTermios, B19200); + break; + case BAUD38400: + setBaudRate2Termios(¤tTermios, B38400); + break; + case BAUD57600: + setBaudRate2Termios(¤tTermios, B57600); + break; +#ifdef B76800 + case BAUD76800: + setBaudRate2Termios(¤tTermios, B76800); + break; +#endif + case BAUD115200: + setBaudRate2Termios(¤tTermios, B115200); + break; +#if defined(B230400) && defined(B4000000) + case BAUD230400: + setBaudRate2Termios(¤tTermios, B230400); + break; + case BAUD460800: + setBaudRate2Termios(¤tTermios, B460800); + break; + case BAUD500000: + setBaudRate2Termios(¤tTermios, B500000); + break; + case BAUD576000: + setBaudRate2Termios(¤tTermios, B576000); + break; + case BAUD921600: + setBaudRate2Termios(¤tTermios, B921600); + break; + case BAUD1000000: + setBaudRate2Termios(¤tTermios, B1000000); + break; + case BAUD1152000: + setBaudRate2Termios(¤tTermios, B1152000); + break; + case BAUD1500000: + setBaudRate2Termios(¤tTermios, B1500000); + break; + case BAUD2000000: + setBaudRate2Termios(¤tTermios, B2000000); + break; + case BAUD2500000: + setBaudRate2Termios(¤tTermios, B2500000); + break; + case BAUD3000000: + setBaudRate2Termios(¤tTermios, B3000000); + break; + case BAUD3500000: + setBaudRate2Termios(¤tTermios, B3500000); + break; + case BAUD4000000: + setBaudRate2Termios(¤tTermios, B4000000); + break; +#endif +#ifdef Q_OS_MAC + default: + setBaudRate2Termios(¤tTermios, settings.BaudRate); + break; +#endif + } + } + if (settingsDirtyFlags & DFE_Parity) { + switch (settings.Parity) { + case PAR_SPACE: + /*space parity not directly supported - add an extra data bit to simulate it*/ + settingsDirtyFlags |= DFE_DataBits; + break; + case PAR_NONE: + currentTermios.c_cflag &= (~PARENB); + break; + case PAR_EVEN: + currentTermios.c_cflag &= (~PARODD); + currentTermios.c_cflag |= PARENB; + break; + case PAR_ODD: + currentTermios.c_cflag |= (PARENB|PARODD); + break; + } + } + /*must after Parity settings*/ + if (settingsDirtyFlags & DFE_DataBits) { + if (settings.Parity != PAR_SPACE) { + currentTermios.c_cflag &= (~CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS5; + break; + case DATA_6: + currentTermios.c_cflag |= CS6; + break; + case DATA_7: + currentTermios.c_cflag |= CS7; + break; + case DATA_8: + currentTermios.c_cflag |= CS8; + break; + } + } else { + /*space parity not directly supported - add an extra data bit to simulate it*/ + currentTermios.c_cflag &= ~(PARENB|CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS6; + break; + case DATA_6: + currentTermios.c_cflag |= CS7; + break; + case DATA_7: + currentTermios.c_cflag |= CS8; + break; + case DATA_8: + /*this will never happen, put here to Suppress an warning*/ + break; + } + } + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + currentTermios.c_cflag &= (~CSTOPB); + break; + case STOP_2: + currentTermios.c_cflag |= CSTOPB; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + case FLOW_OFF: + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + case FLOW_XONXOFF: + /*software (XON/XOFF) flow control*/ + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag |= (IXON|IXOFF|IXANY); + break; + case FLOW_HARDWARE: + currentTermios.c_cflag |= CRTSCTS; + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + } + } + + /*if any thing in currentTermios changed, flush*/ + if (settingsDirtyFlags & DFE_Settings_Mask) + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + + if (settingsDirtyFlags & DFE_TimeOut) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + ::fcntl(fd, F_SETFL, O_NDELAY); + } + else { + //O_SYNC should enable blocking ::write() + //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2) + ::fcntl(fd, F_SETFL, O_SYNC); + } + ::tcgetattr(fd, ¤tTermios); + currentTermios.c_cc[VTIME] = millisec/100; + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + } + + settingsDirtyFlags = 0; +} diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextserialport_win.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_win.cpp new file mode 100644 index 0000000..6b13b52 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextserialport_win.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +# include +#else +# include +#endif +void QextSerialPortPrivate::platformSpecificInit() +{ + handle = INVALID_HANDLE_VALUE; + ZeroMemory(&overlap, sizeof(OVERLAPPED)); + overlap.hEvent = CreateEvent(NULL, true, false, NULL); + winEventNotifier = 0; + bytesToWriteLock = new QReadWriteLock; +} + +void QextSerialPortPrivate::platformSpecificDestruct() { + CloseHandle(overlap.hEvent); + delete bytesToWriteLock; +} + + +/*! + \internal + COM ports greater than 9 need \\.\ prepended + + This is only need when open the port. +*/ +static QString fullPortNameWin(const QString &name) +{ + QRegExp rx(QLatin1String("^COM(\\d+)")); + QString fullName(name); + if (fullName.contains(rx)) + fullName.prepend(QLatin1String("\\\\.\\")); + return fullName; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + DWORD confSize = sizeof(COMMCONFIG); + commConfig.dwSize = confSize; + DWORD dwFlagsAndAttributes = 0; + if (queryMode == QextSerialPort::EventDriven) + dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; + + /*open the port*/ + handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); + if (handle != INVALID_HANDLE_VALUE) { + q->setOpenMode(mode); + /*configure port settings*/ + GetCommConfig(handle, &commConfig, &confSize); + GetCommState(handle, &(commConfig.dcb)); + + /*set up parameters*/ + commConfig.dcb.fBinary = TRUE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + commConfig.dcb.fAbortOnError = FALSE; + commConfig.dcb.fNull = FALSE; + /* Dtr default to true. See Issue 122*/ + commConfig.dcb.fDtrControl = TRUE; + /*flush all settings*/ + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + //init event driven approach + if (queryMode == QextSerialPort::EventDriven) { + if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { + QESP_WARNING()<<"failed to set Comm Mask. Error code:"<("HANDLE"); + q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection); + WaitCommEvent(handle, &eventMask, &overlap); + } + return true; + } + return false; +} + +bool QextSerialPortPrivate::close_sys() +{ + flush_sys(); + CancelIo(handle); + if (CloseHandle(handle)) + handle = INVALID_HANDLE_VALUE; + if (winEventNotifier) { + winEventNotifier->setEnabled(false); + winEventNotifier->deleteLater(); + winEventNotifier = 0; + } + + foreach (OVERLAPPED *o, pendingWrites) { + CloseHandle(o->hEvent); + delete o; + } + pendingWrites.clear(); + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + FlushFileBuffers(handle); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + DWORD Errors; + COMSTAT Status; + if (ClearCommError(handle, &Errors, &Status)) { + return Status.cbInQue; + } + return (qint64)-1; +} + +/* + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + if (error & CE_BREAK) { + lastErr = E_BREAK_CONDITION; + } + else if (error & CE_FRAME) { + lastErr = E_FRAMING_ERROR; + } + else if (error & CE_IOE) { + lastErr = E_IO_ERROR; + } + else if (error & CE_MODE) { + lastErr = E_INVALID_FD; + } + else if (error & CE_OVERRUN) { + lastErr = E_BUFFER_OVERRUN; + } + else if (error & CE_RXPARITY) { + lastErr = E_RECEIVE_PARITY_ERROR; + } + else if (error & CE_RXOVER) { + lastErr = E_RECEIVE_OVERFLOW; + } + else if (error & CE_TXFULL) { + lastErr = E_TRANSMIT_OVERFLOW; + } +} + +/* + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + DWORD bytesRead = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED overlapRead; + ZeroMemory(&overlapRead, sizeof(OVERLAPPED)); + if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) { + if (GetLastError() == ERROR_IO_PENDING) + GetOverlappedResult(handle, &overlapRead, &bytesRead, true); + else + failed = true; + } + } else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) { + failed = true; + } + if (!failed) + return (qint64)bytesRead; + + lastErr = E_READ_FAILED; + return -1; +} + +/* + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + DWORD bytesWritten = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED *newOverlapWrite = new OVERLAPPED; + ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED)); + newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL); + if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) { + CloseHandle(newOverlapWrite->hEvent); + delete newOverlapWrite; + } + else if (GetLastError() == ERROR_IO_PENDING) { + // writing asynchronously...not an error + QWriteLocker writelocker(bytesToWriteLock); + pendingWrites.append(newOverlapWrite); + } + else { + QESP_WARNING()<<"QextSerialPort write error:"<hEvent)) + QESP_WARNING("QextSerialPort: couldn't cancel IO"); + if (!CloseHandle(newOverlapWrite->hEvent)) + QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle"); + delete newOverlapWrite; + } + } else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) { + failed = true; + } + + if (!failed) + return (qint64)bytesWritten; + + lastErr = E_WRITE_FAILED; + return -1; +} + +void QextSerialPortPrivate::setDtr_sys(bool set) { + EscapeCommFunction(handle, set ? SETDTR : CLRDTR); +} + +void QextSerialPortPrivate::setRts_sys(bool set) { + EscapeCommFunction(handle, set ? SETRTS : CLRRTS); +} + +ulong QextSerialPortPrivate::lineStatus_sys(void) { + unsigned long Status = 0, Temp = 0; + GetCommModemStatus(handle, &Temp); + if (Temp & MS_CTS_ON) Status |= LS_CTS; + if (Temp & MS_DSR_ON) Status |= LS_DSR; + if (Temp & MS_RING_ON) Status |= LS_RI; + if (Temp & MS_RLSD_ON) Status |= LS_DCD; + return Status; +} + +/* + Triggered when there's activity on our HANDLE. +*/ +void QextSerialPortPrivate::_q_onWinEvent(HANDLE h) +{ + Q_Q(QextSerialPort); + if (h == overlap.hEvent) { + if (eventMask & EV_RXCHAR) { + if (q->sender() != q && bytesAvailable_sys() > 0) + _q_canRead(); + } + if (eventMask & EV_TXEMPTY) { + /* + A write completed. Run through the list of OVERLAPPED writes, and if + they completed successfully, take them off the list and delete them. + Otherwise, leave them on there so they can finish. + */ + qint64 totalBytesWritten = 0; + QList overlapsToDelete; + foreach (OVERLAPPED *o, pendingWrites) { + DWORD numBytes = 0; + if (GetOverlappedResult(handle, o, &numBytes, false)) { + overlapsToDelete.append(o); + totalBytesWritten += numBytes; + } else if (GetLastError() != ERROR_IO_INCOMPLETE) { + overlapsToDelete.append(o); + QESP_WARNING()<<"CommEvent overlapped write error:" << GetLastError(); + } + } + + if (q->sender() != q && totalBytesWritten > 0) { + QWriteLocker writelocker(bytesToWriteLock); + Q_EMIT q->bytesWritten(totalBytesWritten); + } + + foreach (OVERLAPPED *o, overlapsToDelete) { + OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o)); + CloseHandle(toDelete->hEvent); + delete toDelete; + } + } + if (eventMask & EV_DSR) { + if (lineStatus_sys() & LS_DSR) + Q_EMIT q->dsrChanged(true); + else + Q_EMIT q->dsrChanged(false); + } + } + WaitCommEvent(handle, &eventMask, &overlap); +} + +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_ptr->isOpen() || !settingsDirtyFlags) + return; + + //fill struct : COMMCONFIG + if (settingsDirtyFlags & DFE_BaudRate) { + commConfig.dcb.BaudRate = settings.BaudRate; + } + if (settingsDirtyFlags & DFE_Parity) { + commConfig.dcb.Parity = (BYTE)settings.Parity; + commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE; + } + if (settingsDirtyFlags & DFE_DataBits) { + commConfig.dcb.ByteSize = (BYTE)settings.DataBits; + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + commConfig.dcb.StopBits = ONESTOPBIT; + break; + case STOP_1_5: + commConfig.dcb.StopBits = ONE5STOPBITS; + break; + case STOP_2: + commConfig.dcb.StopBits = TWOSTOPBITS; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + /*no flow control*/ + case FLOW_OFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + /*software (XON/XOFF) flow control*/ + case FLOW_XONXOFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = TRUE; + commConfig.dcb.fOutX = TRUE; + break; + /*hardware flow control*/ + case FLOW_HARDWARE: + commConfig.dcb.fOutxCtsFlow = TRUE; + commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + } + } + + //fill struct : COMMTIMEOUTS + if (settingsDirtyFlags & DFE_TimeOut) { + if (queryMode != QextSerialPort::EventDriven) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutConstant = 0; + } else { + commTimeouts.ReadIntervalTimeout = millisec; + commTimeouts.ReadTotalTimeoutConstant = millisec; + } + commTimeouts.ReadTotalTimeoutMultiplier = 0; + // zapmaker fix for dropped sent packets on fast Windows computers + //commTimeouts.WriteTotalTimeoutMultiplier = millisec; + commTimeouts.WriteTotalTimeoutMultiplier = 500; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + else { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutMultiplier = 0; + commTimeouts.ReadTotalTimeoutConstant = 0; + commTimeouts.WriteTotalTimeoutMultiplier = 0; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + } + + + if (settingsDirtyFlags & DFE_Settings_Mask) + SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG)); + if ((settingsDirtyFlags & DFE_TimeOut)) + SetCommTimeouts(handle, &commTimeouts); + settingsDirtyFlags = 0; +} diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.cpp b/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.cpp new file mode 100644 index 0000000..f029421 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextwineventnotifier_p.h" +#include +#include +#include +#include +#include +#include +#include + +class QextWinEventNotifierPrivate +{ + Q_DECLARE_PUBLIC(QextWinEventNotifier) +public: + QextWinEventNotifierPrivate(HANDLE hEvent, QextWinEventNotifier * q) + :handleToEvent(hEvent), enabled(false), q_ptr(q) + {} + + HANDLE handleToEvent; + bool enabled; +private: + QextWinEventNotifier * q_ptr; +}; + +/* + \internal + + \class QextWinEventNotifierThread + + This class works more or less like an EventDispatcher. + + The api function WaitForMultipleObjects() is used in the new thread + to wait for the registered handle. +*/ +class QextWinEventNotifierThread:public QThread +{ +public: + explicit QextWinEventNotifierThread(QObject * parent=0); + ~QextWinEventNotifierThread(); + void stop(); + bool registerEventNotifier(QextWinEventNotifier * notifier); + void unregisterEventNotifier(QextWinEventNotifier * notifier); +protected: + void run(); +private: + HANDLE hStopEvent; //stop thread when this event signaled. + HANDLE hUpdateEvent; //make sure eventlist updated. + QMutex mutex; + QList winEventNotifierList; +}; + +Q_GLOBAL_STATIC(QextWinEventNotifierThread, notifierThread) + +QextWinEventNotifierThread::QextWinEventNotifierThread(QObject * parent) + :QThread(parent) +{ + hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hUpdateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + start(); +} + +QextWinEventNotifierThread::~QextWinEventNotifierThread() +{ + if (isRunning()) + stop(); + CloseHandle(hStopEvent); + CloseHandle(hUpdateEvent); +} + +void QextWinEventNotifierThread::stop() +{ + { + QMutexLocker locker(&mutex); + SetEvent(hStopEvent); + } + wait(); /// Is this an good idea? +} + +bool QextWinEventNotifierThread::registerEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return false; + } + if (winEventNotifierList.contains(notifier)) + return true; + if (winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 3) { + QESP_WARNING("QextWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 3); + return false; + } + winEventNotifierList.append(notifier); + SetEvent(hUpdateEvent); + return true; +} + +void QextWinEventNotifierThread::unregisterEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return; + } + + int idx = winEventNotifierList.indexOf(notifier); + if (idx != -1) { + winEventNotifierList.takeAt(idx); + SetEvent(hUpdateEvent); + } +} + +void QextWinEventNotifierThread::run() +{ + forever{ + HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; + DWORD nCount = 0; + { + QMutexLocker locker(&mutex); + nCount = winEventNotifierList.count(); + for (int i=0; i<(int)nCount; ++i) + pHandles[i] = winEventNotifierList.at(i)->handle(); + pHandles[nCount] = hUpdateEvent; + pHandles[nCount+1] = hStopEvent; + } + DWORD ret = WaitForMultipleObjects(nCount+2, pHandles, FALSE, INFINITE); + if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + nCount) { + QEvent *evt = new QEvent(QEvent::User); + QMutexLocker locker(&mutex); + ResetEvent(pHandles[ret-WAIT_OBJECT_0]); + QObject * notifier = winEventNotifierList[ret - WAIT_OBJECT_0]; + QCoreApplication::postEvent(notifier, evt); + } + else if (ret == WAIT_OBJECT_0 + nCount) { + //ResetEvent(hUpdateEvent); + } + else if (ret == WAIT_OBJECT_0 + nCount + 1) { + //qDebug()<<"quit..."; + return; + } + } +} + +/*! + \internal + \class QextWinEventNotifier + \brief The QextWinEventNotifier class provides support for the Windows Wait functions. + + The QextWinEventNotifier class makes it possible to use the wait + functions on windows in a asynchronous manner. With this class + you can register a HANDLE to an event and get notification when + that event becomes signalled. + + \bold Note: If it is a manual reset event ,it will be reset before + the notification. This is different from QWinEventNotifier. + + \bold Note: All the registered handles will be waited under a new thread. + This is different from QWinEventNotifier whose event handle will be waited + in its affinal thread. +*/ + +QextWinEventNotifier::QextWinEventNotifier(QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(0, this)) +{} + +QextWinEventNotifier::QextWinEventNotifier(HANDLE hEvent, QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(hEvent, this)) +{ + setEnabled(true); +} + +QextWinEventNotifier::~QextWinEventNotifier() +{ + setEnabled(false); +} + +void QextWinEventNotifier::setHandle(HANDLE hEvent) +{ + setEnabled(false); + Q_D(QextWinEventNotifier); + d->handleToEvent = hEvent; +} + +HANDLE QextWinEventNotifier::handle() const +{ + return d_func()->handleToEvent; +} + +bool QextWinEventNotifier::isEnabled() const +{ + return d_func()->enabled; +} + +void QextWinEventNotifier::setEnabled(bool enable) +{ + Q_D(QextWinEventNotifier); + + if (d->enabled == enable) + return; + d->enabled = enable; + + if (d->enabled) + notifierThread()->registerEventNotifier(this); + else + notifierThread()->unregisterEventNotifier(this); +} + +bool QextWinEventNotifier::event(QEvent * e) +{ + Q_D(QextWinEventNotifier); + QObject::event(e); + if (e->type() == QEvent::User) { + emit activated(d->handleToEvent); + return true; + } + return false; +} + diff --git a/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.h b/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.h new file mode 100644 index 0000000..38f1457 --- /dev/null +++ b/GC-3.6.1-T2/src/QextSerialPort/qextwineventnotifier_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTWINEVENTNOTIFIER_P_H_ +#define QEXTWINEVENTNOTIFIER_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qextserialport_global.h" + +class QextWinEventNotifierPrivate; +class QEXTSERIALPORT_EXPORT QextWinEventNotifier : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextWinEventNotifier) + +public: + explicit QextWinEventNotifier(QObject *parent = 0); + explicit QextWinEventNotifier(HANDLE hEvent, QObject *parent = 0); + ~QextWinEventNotifier(); + + void setHandle(HANDLE hEvent); + HANDLE handle() const; + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); + +Q_SIGNALS: + void activated(HANDLE hEvent); + +protected: + bool event(QEvent * e); + +private: + Q_DISABLE_COPY(QextWinEventNotifier) + QextWinEventNotifierPrivate * d_ptr; +}; + +#endif // QEXTWINEVENTNOTIFIER_P_H_ diff --git a/GC-3.6.1-T2/src/README b/GC-3.6.1-T2/src/README new file mode 100644 index 0000000..57820c6 --- /dev/null +++ b/GC-3.6.1-T2/src/README @@ -0,0 +1,493 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Version 3.0 is a near-complete rewrite of the C++ code fixing all known bugs. +The other major enhancement is native Mac OSX support (including older 32 bit Intel 10.5). + +The code was tested with real milling projects using the Shapeoko and works +pretty well. For a list of possible future enhancements, see file TODO. + +Prebuilt binaries/installers can be found on github's download section for this +project (GrblHoming). Alternately, if you download the (a) Qt SDK from Nokia or +(b) the Qt source from Qt Project along with the standalone Qt Creator, you can +build from source. + +Details on how to do this can be found here: +http://zapmaker.org/ + +V3.6.1->T2 (LETARTARE proposals) + +* 3.6.1-T1 + + +- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + + +V3.6.1->T1 (LETARTARE proposals) + +- Improved to the same card 3 and 4 axis detection +- Displays the line numbers of the file if no number exists +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, + 2- Four axes 0845, future 0.8c1 (0.8c1 to 4 axes) + +V3.6.1 +Executable release rollup + +IMPORTANT: Manual/Jog control defaults to new mode which doesn't update the position. +This was done to ensure that jog motions are as fast as possible. However, if you want +to have the original 3.5.1 and earlier behavior, go to Tools | Options | Display +and change radio button to "Always Request but without Idle Check". Sending files +still updates position, it is only manual/jog that does not. + +V3.6 +Enhancements +- Options dialog is now tabbed to better fit widgets +- Ability to handle 4th axis as either A, B, or C (requires correct grbl version for axis), + please see https://github.com/zapmaker/GrblHoming/issues/56 and + https://github.com/LETARTARE/Grbl_with_Arduino/tree/master/Grbl845Mega2560 + which is the A,B,C,U,V,W axes grbl variant. +- LETARTARE: Added UVW axes +- #45: Added ability to completely or partially turn off querying position from grbl to + help improve responsiveness. The new default is to disable waiting for idle before a + jog or manual command, which speeds up those operations. Additional, you can + completely turn it off position reporting during jog or manual control which will + result in light-greyed LCD numbers. A button to query the position has been + added, which will provided up-to-date position at the time the button is pushed. + Look in Options | Display tab for new button options. You can also set the rate + at which the query takes place from 0.5-10 seconds, if it is enabled. Setting a time + that is too long may result in the system waiting too long to retrieve the final position + before control is handed back. Also, the current position dot on the Visualizer turns + from red to green when the position is not accurately known to match the color of the path. +Bug fix +- Fixed fourth axis adjust buttons and coordinate display greyed out when they shouldn't + be (under specific operating circumstances). + +V3.5.1 +Enhancements +- Made subtle modifications to the command preload when sending a file so that the + command queue on grbl is as full as possible. Previously we were depleting the + queue and then filling it again. This has possible negative performance implications, + although testing shows them to be negligible, probably because we immediately send + a command after the last ok is received. +- The status list view now supports only a maximum of 200 items when active. This was + done for the slower processors like the raspberry pi to prevent excessive CPU usage + when many commands lines exist in a file. When the user grabs the scrollbar, all + items are restored back into the view. +- A new progress bar has been added showing the current items in the grbl queue during + a file send. If the number of items for some reason drops to 0 the label text will + flash red. For this 0 count to occur is a very rare event. +- Added the ability to set the delay between sending of characters to grbl. The theory + is that grbl can drop characters if the sending computer is very fast. There is still + some debate on whether this is happening, so I provided the ability to set this value + in the options from 0 to 20 ms. Note: The default of 0 ms delay is back, like in 3.4.6 + and unlike in 3.5 which has a hardcoded 10 ms delay. +Bug fix +- Modified the status window redraw to always ensure items show on the bottom when the + redraw timer expires. + +V3.5 +Bug fix +- For very fast computers, they send characters with virtually no delay between which + requires grbl to process the serial port as fast as it can. The problem is that + grbl has an interrupt service routine that can slow down the processing it does + of incoming characters on its serial port. This causes lost characters in its input + buffer, which results in hung gcode file processing or errors. To fix, I have added + a slight delay (10ms) after sending every character. This has been confirmed to + solve the lost character problem on grbl. + +V3.4.6 +Bug fix +- Scrolling of content now completes each time. Previously there were conditions where + auto-scrolling would fail and you would have to manually scroll to see some lines +- Fixes to support 4-axis Mega2560 (tested with actual Mega2560 running 0.81 c-axis). + Includes fix to command filter to support A/B/C axis commands +- Fixed minor issue where connecting with wrong baud rate can cause long delay before + you can again control the Open/Close button +- Incorporated more translations from LETARTARE + +V3.4.5 +Bug fix +- When modifying the ui files for auto widget rescaling, broke a number of programmatically + greyed out widgets, mainly, you couldn't reopen the port after closing it. Now those are fixed. + +Enhancement +- Incorporated LETARTARE's localization file for French so that it is possible to see + locale-specific text in the installed version of Grbl Controller (see trlocale subdir) + +V3.4.4 +Bug fix +- Incorporated LETARTARE's 4-axis (C-axis) implementation - thanks! (Issues #29 and #34) + (added option to enable/disable 4-axis mode) - potential issue that needs investigating: + Can this be enabled on the fly or if it requires restart of Grbl Controller? +- Incorporated LETARTARE's translation support (French) +- Incorporated LETARTARE's fix for command history (#26) +- Incorporated Kosme's fix to issue #17 (#33). Z axis slider now moves in 0.1 inch increments + when in inches mode. +- Incorporated Kosme's fix to issue #27. If work units are inches, now displays inches, + not mm. +Enhancements +- Ability to resize entire screen and widgets. Scales down to close to 600x400 pixels + for tiny displays; also remembers last size and position of screen. (#37) +- Incorporated Kosme's fix to issue #10 (#33). Popup appears to remind you to zero position + if starting a new job. + +V3.4.3 +Bug fix +- Unsupported G43/G44 commands include following Z command which causes problems when + left standalone. The entire line must be removed. +- Now treat M2 and M30 as unsupported as they cause grbl lockup when using aggressive + preloading. +- Moved program version define into its own header file so fewer files need recompiling + with a version change. + +V3.4.2 +Bug fix +- If a gcode command line is an arc with X,Y,Z and z-rate limiting enabled, fixed to + properly split the z rate to not use the G2 command and use G1 instead as grbl + was generating an error with the G2. + +V3.4.1 +Code sync +- Fixes to code now allows code to compile under Qt5 without error and also resolves + some localization issues. Continues to properly compile under Qt4 also. No normally + noticable functional differences. + +V3.4 +Enhancements +- Z-axis slider now allows rapid control of Z-axis positioning. This feature is still + being evaluated for proper behavior due to some user-interface issues. + If you run into trouble, please report a bug. +- All axis control buttons have been permanently enabled regardless of whether or not an + axis command is in progress - this allows more rapid updating. Note - there is no error + checking for the case of entering too many commands for the Grbl buffer. This is unlikely + but possible. +- Now supports setting of baud rates from 9600 to 115200 +- Aggressive preload enabled is now the default. If the user upgraded from an older + Grbl Controller and had it disabled, a popup will warn them that it is being enabled. + They still have the option to disable, if desired +- Logging is turned on by default (only for new installs) +- All detected errors are collected and displayed after a file is run in the status view +- If filtering unsupported commands, all commands filtered out are listed after the file + is run. +- Logging now gives the line number of each command sent from the file and the corresponding + ok or error also contains the line number. +- An option has been provided to reduce the precision of lines that exceed Grbl's line buffer, + which by default is 50 characters. The code removes the arguments with the greatest precision + first and ending with at least one decimal place of precision. Errors are generated if it + cannot remove sufficient precision for the available buffer space. The buffer size on Grbl + is configurable in the options, as older Grbls have 50 characters and newer have 70. + +Bug Fixes +- If Grbl stops responding (waiting for an ok), Soft Reset Grbl now functions correctly + (so you can soft reset without having to restart Grbl Controller). This affects aggressive + preload mode only. +- Commands to start/stop coolant coupled with dwell commands and aggressive preload cause + Grbl's modal logic to stop sending OK responses (on purpose). This was solved by waiting + for the OK of the coolant off before sending additional commands. It is not clear whether + this fixes all possible such modal problems, so use carefully and report any anomalies. + +V3.3.9 +Enhancement +- We now are able to remember and restore ports that are not visible to QextSerialEnumerator + so that user doesn't have to retype the ghost port every time they start Grbl Controller. + +V3.3.8 +Enhancement/Fix +- Modified code that detects presence of Grbl upon serial port opening, the original + assumption was that we would get the version string upon serial port open, but some + Arduino-compatible boards like the AlaMode did not behave this way. Fixed the code + so that if there is no response upon serial port open, we send a soft reset (Ctrl-X) + and wait for the version string. Tested to work with AlaMode and with traditional + Ardiuno Uno. + +V3.3.7 +Enhancement +- Made COM port field editable + +V3.3.6 +Bug Fixes +- Fixed decimal on the LCD display to always show three decimal points so that + it is easier to read the display (it doesn't jump around anymore). Tested to + hold up to 9999.999 and -9999.999, which should handle 20 x 20 meter Shapeokos. + +V3.3.5 +Bug Fixes +- Changed how we detect Grbl upon opening on COM port. + ** NOTE ** This change will probably break older V0.51 capability + Previously we sent out a linefeed to trigger a response, however, this caused problems + on some arduino variants and would not result in correct sync with the controller. + Fixed by no longer sending the linefeed and instead just watch the port for Grbl response. +- Changed the default "short" wait timeout to 2 seconds from 1 second in case of slow responses. + +V3.3.4 +Enhancements +- Added option checkbox to choose to filter gcode or send it as-is to the controller. The + filtering removes gcode that is not supported in v0.8 of Grbl, which reduces the error + reports from Grbl. Some files generate unexpected codes like G91.1 which can actually + affect the motion in unexpected ways- filtering helps prevent this from happening. + + IMPORTANT: The default is to not filter, which is different than previous versions! This + may result in unexpected command processing. If using advanced gcodes, perform an air run + first. + +Bug Fixes +- Mach3 files have no whitespace in the gcode. Fixed code to handle such files. Affects + the Visualizer only. +- The filtering logic was fixed to properly filter gcode when sending a file - previous + versions would filter out gcode that Grbl supported. +- Changed validator for double (i.e. float) values so that code compiles under older Qt + versions. +- Changed Visualizer display to say Width-X and Height-Y instead of Width and Depth to make + it less confusing. + +V3.3.3 +Bug Fix +- Modal G arc (where G2 or G3 is specified once followed by X/Y/I/J) was failing for certain + arc combinations in the visualizer due to resetting the cw to false with each line. Fixed + to not reset the cw variable and retain from previous lines. + +V3.3.2 +Bug Fix +- G-command can now be set once and multiple X/Y commands then issued on lines following + (Allows "ShapeOko_Calibration_Pattern_01b.ngc to be rendered) + +V3.3.1 +Bug Fixes +- Hardened the visualizer's file parser so that it supports spaces between positional + arguments and values +- No longer skips last line in file if that line contains a valid command +- No longer crashes if line contains one or more stray whilespace characters +- Also accepts semi-colon as a comment line (in addition to existing open paren and percent) + +V3.3 +Enhancemetns +- Added "Visualizer" feature. It is now possible to see top-down view of the + file to be milled. + * Shows actual file units (inches or millimeters) independent of coordinate display + * Auto-scaling + * Supports limited subset of commands (G0/G1/G2/G3) + * Visualizer on tab panel shared with Axis control + * Actual last spindle cutter position is shown; auto-scales to include both cutter + and file + * When file is being run, overlay of all commands sent to Grbl is shown in green + * Displays dimensions of design, along with design's width and depth in file's units + +V3.2 +Enhancements +- Support for "Aggressive Preload" of commands when sending file to Grbl + * File's lines are sent to Grbl as fast as Grbl can take it, allowing + Grbl to optimize acceleration. Some files have been observed to take + 1/3 the time to complete! + * Modeled after Grbl's own python script (computes/predicts how much + space is available in Grbl's input buffer) + * Due to the additional processing, CPU usage is greater than normal mode + and it has been optimized to run fine on a Raspberry Pi + * Normal (non-preload) mode is the default + * Response processing code now waits until a line has been received rather + than collect a long stream to behave like the python script + * LCD updates have been set to be roughly once every second independent + of rate of line sends/preloads +- Z-rate limit feature now includes default xy rate setting + * Z rate limiting only occurs during file sends. If z is included with x&y + then they are split into two commands automatically and the xy rate setting + is used for the xy portion + * Since feed rate is modal, code will fix any subsequent xy items that are + missing feed rate specifiers (cambam correctly adds them, but others may not) +- Replaced basic logging with Log4Qt logging capabilities. + * Support for error, warning, info, debug message types. All messages are timestamped. + * More diagnostic messages added, mainly around sending and receiving from com ports + * Only error and warning are displayed in release build, all are displayed in debug. + * If the user enables file logging, all messages are stored regardless of build type + * File is output to user's home folder + * If you enable or disable logging to file, you must restart Grbl Controller + * You can split out diagnostic from status messages by grepping for (DIAG) or (STATUS) +- Changed menus so that the first menu is File > Exit. Menus now use accelerators + +Bug Fixes +- Fixed problems with z-rate limit feature, previous version was not implemented correctly. +- Fixed subtle issues with sending bytes to COM port + * On really fast Windows PCs, the default timeout values would occasionally result in + a line not being sent. This was fixed by changing the write timeout from 10 to + 500 ms by hardcoding it into the QextSerialPort library. This was only observed in + aggressive preload mode, never in normal mode. + +Known issues +- New reponse line detect mode requires more processing because mainly of the faster + stream of status messages. To get around this, certain features have been disabled + in the status view so that CPU usage is manageable on the Raspberry Pi, specifically + the horizontal scroll bar is not available. Turn on file logging if you wish to see + the entire line. +- When using aggressive preload, any error messages returned by Grbl are not synced + to sent messages (they come back randomly). This can be confusing. +- If running preload, it can take longer for steppers to stop after a Stop command + due to the number of items in Grbl's queue. The only way to stop sooner is to + press Close / Reset button +- Under exteme CPU loads (unlikely to occur with recent optimizations), the "runtime" + display does not display accurate times, oddly, it displays the same time that would + occur if not under load + +Tested on cardboard using file provided by user: +- Windows 7 64bit, 0.8c, aggressive mode (~4 minute run) +- Windows 7 64bit, 0.8c, normal mode (~10 minute run) +- Windows 7 64bit, 0.8a, aggressive mode(~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode (~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode and z-limit (~6 minute run) + +V3.1.2 (unofficial release, optimizations for Raspberry Pi) +Enhancements +- Optimized multiline write to status window to use faster list-based approach +- Removed unnecessary main window repaint after every line added to status window +- Fixed options window text positioning so that it appears proper on the pi + +V3.1.1 (unofficial release, adjustments for Raspberry Pi) +Enhancements +- Changed measurement units in LCD from "inches" to "in" (cosmetic) +- Shortened text and adjusted main window layout for the text size on the pi + +V3.1 +Enhancements +- Supports Grbl 0.8c. Still supports 0.8a. 0.51 is supported but without LCDs. +- Grbl settings dialog is now a table of dynamic length depending on # of params. +- LCD position data is now obtained from Grbl and is *not* computed +- Added LCD displays for both machine and work coordinates +- Cycling of Grbl via COM port toggling has been completely removed, except + that Close button has now been renamed Close / Reset. +- Position data on Grbl is persisted as long as possible to allow for repositioning, etc. +- Zero work coordinates has been added (G92) +- Go-to-home feature added (lifts tool 5 mm and traverses to x=0, y=0) +- Option to put manual command (back) into absolute mode after jog button command +- Grbl Soft reset (Ctrl-X) button added +- Z-axis rate limiting capability added. Only affects file, not jog or manual commands. +- User is required to specify which measurement mode they are using, mm or inches: + * Default is millimeters + * Grbl is configured to operate in either mm or inches + * If a file is sent in inches and user is in mm, it will auto-restore to mm + after the file has been sent (and vice-versa, mm->inches) +- 0.8c enhancements: + * Displays current Grbl state (i.e. Run, Idle, etc.) + * LCDs display whether values are in inches or millimeters + * Unlock Grbl button added ($X) + * Determines and sets parser state for current mm/inch command mode ($G) + * Determines and sets coordinate units via $13 +- Removed annoying "No movement expected for command" message +- Flags that cross threads have been changed to use QAtomicInt +- Version is now shown in title bar +- A basic log file feature has been added +- Runs on the Raspberry Pi! + +Known Issues +- The registry key product name has been changed from GCodeSender to GrblController + *** WARNING: Old settings are not migrated **** +- Switching between millimeters and inches works, but has not been fully tested +- Go to home has not been fully tested with inches mode +- Manually issuing $13 or G20/G21 can confuse the program + +V3.0 +Enhancements +- Nearly a full code rewrite to ensure ease-of-use and robustness +- Percentage complete progress bar for files; also shows time elapsed sending file. +- Reset button now cycles COM port which causes Arduino to stop steppers and + reinitialize position to 0,0,0 (No more manual Auduino resets!) +- Settings configurations are now stored using QSettings class for platform independence. +- Only available COM ports are now shown. Uses third-party QextSerialPort library. +- App remembers last COM port used, last folder, last file extension used after restart +- Ability to configure wait-for-response time +- Status list window now shows both sent and received data +- Error responses are ignored during file send (nearly 100% of the time they are not important) +- Z-jog speed using buttons is configurable +- Radio buttons to select mode have been removed in favor of enabling/disabling widgets based + on current context. This simplifies usage. +- Popups have been removed in favor of writing errors to status list window + +Bug fixes +- Overall code hardening +- Properly implementing Qt signals and slots across the board + +Build verification +- Windows 7 64 bit using MinGW +- Inno Setup for Windows, installs successfully on Windows 7 +- Mac OSX Mountain Lion, target 64 bit and 32 bit executables +- Qt Mac installer successfully installs and runs on Mountain Lion and 10.5 32 bit Intel +- Linux: Builds successfully on Debian 6, Ubuntu 12.10 + +V2.1x1 + +NOTE: Changes were only focused on Arduino GRBL capabilities with the Shapeoko, so +things like Tool Change were not tested. + +Enhancements +- Improved handling of response code - this is the most significant change as it +ensures reliable send/response handling when sending a file to the Grbl processor. +- Manual command now allows hitting return and command is sent. No need to press Go. +- Default job step size changed from 0.01 to 1 mm +- Compiles and runs under Linux now (tested with Debian and latest Qt) +- Works with old 168 Arduino processor (except that old code is buggy and not recommended) +- Disabled "go to home at end of job". The arduino code doesn't handle it correctly +and mills straight back into and through your work. Checkbox in settings has no effect. + +Bug fixes +- Fixed crash when options file is not present the first time run +- Fixed crash when trying to get GRBL settings from device +- Settings work with 168 (8 settings) and 328 processors (10 settings) +- Fixed Stop to call proper routine stopsig - now Stop button works correctly + +------------------------------------------------------------- +Fork by Zapmaker at this rev +------------------------------------------------------------- +v2.1a + +Bug fixes + +- Corrected an issue that caused the program to crash if the g-code had blank lines. + +V2.1 + +New Features + +- Gcode that is valid but is not recognized by GRBL gets filtered and it is not sent. + +Bug fixes + +- Corrected an issue that prevented manually sent Gcode for being displayed correctly. +- Corrected an issue with the images not displaying. + +V2.0 Major release + +- Improved the port handling reducing opening and closing frecuency. +- Added the ability to type and send commands directly. +- Support for tool change instructions. If enabled it pauses execution, raises the spindle, goes to a fixed location for toolchange, waits for tool change, and continues excecution. +- Added About window. + +V1.0c Minor + +Bug fixes + +- Corrected a problem when adjusting axis that caused all axis to move at the same time. Caused by grbl starting in incremental programming. + +V1.0b Minor + +Bug fixes + +- Corrected a bug in the adjusting script. + +V1.0a Minor + +Bug fixes + +- Fixed a bug reading some file formats that avoided the dials from updating. + diff --git a/GC-3.6.1-T2/src/TODO b/GC-3.6.1-T2/src/TODO new file mode 100644 index 0000000..c73577e --- /dev/null +++ b/GC-3.6.1-T2/src/TODO @@ -0,0 +1,68 @@ +This file contains enhancements the developer and user community would like to see: + + +Planned for 3.4.x +- Bug fixes +Planned for 3.5: +- (What is the problem here? Run is shown, then Idle when stopped) Detect machine state at end of run and display it properly (i.e. "transitioning" when it is still moving) +- Every second or so, if not scrolled to bottom, scroll to bottom of status +- Allow reload of same file from same location +- After a run, suppress $$ output with a single line +- Report system settings at beginning of log file. Include OS. +- Can't see drill holes under axis, move axes under toolpaths? +- Create test plan (i.e. verify all text appears correctly on all platforms) +- Display detected version of Grbl +- Speed limit for X and Y like the Z speed limit + +Planned for 3.6: +- Implement support for Grbl 0.8c "homing" feature (using limit switches) +- UI support for homing limit switches +- Restore "Tool change" feature, including popup dialog +- Option to engage stepper lock (include fade out rate setting - start time of fade, end time of fade, requires hw mod) +- Display current feedrate in mm/sec or in/sec +- Add additional rs232 error logging value (-1 is not very useful) +- Analyze file ahead of time and determine if it will go beyond extents +- Update manual since 3.3 + +Planned for 3.7 +- Switch to compiling using Qt 5 +- Auto-scale widgets to full screen size +- Localization ready code +- Don't fail on timeout waiting for command - let user continue if they want +- Pick up from where left off (if GC dies due to PC falling asleep, etc.) +- Look at all hardware connection options of Grbl on the shield and make + sure that we have some way to control those, i.e. spindle control. +- Clear log button +- Print current GRBL settings +- Add option to always use last working port, even if it isn't currently connected + +Primary: +- Save/Load current GRBL settings from disk +- Suppress some bookkeeping output from the status window +- Add local Help linked from main screen and options dialog +- When parsing for visualizer, if bad value arg, warn user +- If nothing appears in visualizer, attempt to diagnose and explain to user +- If get error from grbl, provide command that generated error on same line +- Allow user to choose how to handle unspecified units in file for visualizer +- Fix Zero position next to begin? +- Show drill holes as larger dots? +- Build in calibration pattern +- Build in "flatten table feature" +- File viewer +- Estimate bounds based on both toolpaths and tool diameter, not just toolpaths + +Secondary: +- Make GC generic to support controllers other than Grbl +- Recent files list under 'Files' +- Restore "Favorites" feature +- Provide diagnostic response view +- Provide counter showing time waiting for a response if time > 5s +- Estimated time to completion (this can acutally be computed from feedrates) + +Notes pulled from https://github.com/grbl/grbl/issues/202 + +Move Z to upper clear position. (<- another parameter?) +Stop the spindle. +X and Y to the change tool coordinates. +A way to adjust new Z (manual for me) and perhaps new speed for the spindle (manual for me). +When ready (~) start cycle? to continue with the new tool with the same X and Y initial coordinates than the last tool. \ No newline at end of file diff --git a/GC-3.6.1-T2/src/about.cpp b/GC-3.6.1-T2/src/about.cpp new file mode 100644 index 0000000..f3b8df1 --- /dev/null +++ b/GC-3.6.1-T2/src/about.cpp @@ -0,0 +1,26 @@ +/**************************************************************** + * about.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "about.h" +#include "version.h" +#include "ui_about.h" + +About::About(QWidget *parent) : + QDialog(parent), + ui(new Ui::About) +{ + ui->setupUi(this); + + ui->labelProductAndVersion->setText(GRBL_CONTROLLER_NAME_AND_VERSION); +} + +About::~About() +{ + delete ui; +} diff --git a/GC-3.6.1-T2/src/about.h b/GC-3.6.1-T2/src/about.h new file mode 100644 index 0000000..e8f7291 --- /dev/null +++ b/GC-3.6.1-T2/src/about.h @@ -0,0 +1,32 @@ +/**************************************************************** + * about.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef ABOUT_H +#define ABOUT_H + +#include +#include "definitions.h" + +namespace Ui { +class About; +} + +class About : public QDialog +{ + Q_OBJECT + +public: + explicit About(QWidget *parent = 0); + ~About(); + +private: + Ui::About *ui; +}; + +#endif // ABOUT_H diff --git a/GC-3.6.1-T2/src/about.ui b/GC-3.6.1-T2/src/about.ui new file mode 100644 index 0000000..eef05b7 --- /dev/null +++ b/GC-3.6.1-T2/src/about.ui @@ -0,0 +1,154 @@ + + + About + + + + 0 + 0 + 414 + 214 + + + + About... + + + + + 40 + 170 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + 10 + 30 + 151 + 61 + + + + + + + Qt::PlainText + + + :/img/logotiny.PNG + + + + + + 180 + 70 + 201 + 91 + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + true + + + + + + 180 + 10 + 211 + 51 + + + + + 12 + 75 + true + + + + Grbl Controller + + + + + + 330 + 10 + 71 + 16 + + + + + + + + + + 20 + 120 + 130 + 33 + + + + + + + :/img/zapmaker-logo-130.png + + + + + + + + + buttonBox + accepted() + About + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + About + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GC-3.6.1-T2/src/arcitem.cpp b/GC-3.6.1-T2/src/arcitem.cpp new file mode 100644 index 0000000..4f58670 --- /dev/null +++ b/GC-3.6.1-T2/src/arcitem.cpp @@ -0,0 +1,120 @@ +#include "arcitem.h" + +ArcItem::ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw1, int index1) + : ItemToBase(index1), sx(sx1), sy(sy1), ex(ex1), ey(ey1), centx(centx1), centy(centy1), cw(cw1), radius(0), angleStart(0), angleDelta(0) +{ +} + +PosItem ArcItem::computeExtents() +{ + PosItem extents(sx, sy, ex, ey); + + radius = qSqrt(((sx - centx) * (sx - centx)) + ((sy - centy) * (sy - centy))); + + if (cw) + { + double angle1 = qAtan2(ey - centy, ex - centx); + double angle2 = qAtan2(sy - centy, sx - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + else + { + double angle1 = qAtan2(sy - centy, sx - centx); + double angle2 = qAtan2(ey - centy, ex - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + + // sample points along the curve + double angleEnd = angleStart + angleDelta; + for (double angle = angleStart; + (angleDelta < 0 ? angle > angleEnd : angle < angleEnd); + angle += (angleDelta < 0 ? -0.4 : 0.4)) + { + double x = qCos(angle) * radius + centx; + double y = qSin(angle) * radius + centy; + + PosItem curr(x, y, x, y); + + // expand rectange if it exceeds our last rectangle + extents.expand(curr); + } + + return extents; +} + +void ArcItem::addToPath(QPainterPath& path) +{ + // need to convert our coordinates into arcTo arguments (rectangle boxes and angles, etc.) + // Also, we are at this point in screen coordinates, not machine coordinates, i.e. Y positive is down! + + // first, we know for a fact that we are dealing with a circular arc, not an ellipse + // (code could be put here to verify that is true) + // Thus our radius is also our bounding box determined from the center of the arc/circle + + if (cw) + { + path.moveTo(screenX(sx), screenY(sy)); + } + else + { + path.moveTo(screenX(ex), screenY(ey)); + } + + double x = centx - radius; + double y = centy + radius; + double wd = radius * 2; + double ht = wd; + + double fx = screenX(x); + double fy = screenY(y); + double w = wd * scale; + double h = ht * scale; + + double angleStartDeg = toDegrees(angleStart); + double angleDeltaDeg = toDegrees(angleDelta); + + path.arcTo(fx, fy, w, h, angleStartDeg, angleDeltaDeg); + + path.moveTo(screenX(ex), screenY(ey)); +} + +void ArcItem::moveToFirst(QPainterPath& path) +{ + // not applicable! generate error! + Q_UNUSED(path); +} + +double ArcItem::getXScr() +{ + return screenX(ex); +} + +double ArcItem::getYScr() +{ + return screenY(ey); +} + +double ArcItem::getXRaw() +{ + return ex; +} + +double ArcItem::getYRaw() +{ + return ey; +} + +double ArcItem::toDegrees(double rad) +{ + return 360 * rad / TWO_PI; +} diff --git a/GC-3.6.1-T2/src/arcitem.h b/GC-3.6.1-T2/src/arcitem.h new file mode 100644 index 0000000..c992472 --- /dev/null +++ b/GC-3.6.1-T2/src/arcitem.h @@ -0,0 +1,39 @@ +#ifndef ARCITEM_H +#define ARCITEM_H +#include +#include "itemtobase.h" + +#define TWO_PI (2 * 3.1415926) + +class ArcItem : public ItemToBase +{ +public: + ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw, int index); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + + double toDegrees(double rad); + +private: + double sx; + double sy; + double ex; + double ey; + double centx; + double centy; + bool cw; + + double radius; + double angleStart; + double angleDelta; + +}; + +#endif // ARCITEM_H diff --git a/GC-3.6.1-T2/src/atomicintbool.cpp b/GC-3.6.1-T2/src/atomicintbool.cpp new file mode 100644 index 0000000..630dc3c --- /dev/null +++ b/GC-3.6.1-T2/src/atomicintbool.cpp @@ -0,0 +1,22 @@ +#include "atomicintbool.h" + +AtomicIntBool::AtomicIntBool(int newValue /* = 0 */) + : value(newValue) +{ +} + +void AtomicIntBool::set(int newValue) +{ + value.fetchAndStoreRelaxed(newValue); +} + +int AtomicIntBool::get() +{ + return value.fetchAndAddRelaxed(0); +} +/* +int AtomicIntBool::getAndClear() +{ + return value.fetchAndStoreRelease(0); +} +*/ diff --git a/GC-3.6.1-T2/src/atomicintbool.h b/GC-3.6.1-T2/src/atomicintbool.h new file mode 100644 index 0000000..93f08e0 --- /dev/null +++ b/GC-3.6.1-T2/src/atomicintbool.h @@ -0,0 +1,22 @@ +#ifndef ATOMICINTBOOL_H +#define ATOMICINTBOOL_H + +#include + +// we wrap QAtomicInt because it is possible to accidentally +// access the non-atomic operations of the class (look at the +// header for QAtomicInt to see what I mean, and thus setting +// a value directly against one of these variables will access +// the non-atomic method) +class AtomicIntBool +{ +public: + AtomicIntBool(int newValue = 0); + void set(int newValue); + int get(); + +private: + QAtomicInt value; +}; + +#endif // ATOMICINTBOOL_H diff --git a/GC-3.6.1-T2/src/clean.bat b/GC-3.6.1-T2/src/clean.bat new file mode 100644 index 0000000..8a41d93 --- /dev/null +++ b/GC-3.6.1-T2/src/clean.bat @@ -0,0 +1,12 @@ +rem clean.bat +rem by LETARTARE + +mingw32-make clean + +del release\GrblController.exe + +del debug\GrblController.exe + +cd .. + + diff --git a/GC-3.6.1-T2/src/controlparams.cpp b/GC-3.6.1-T2/src/controlparams.cpp new file mode 100644 index 0000000..7e7ed6a --- /dev/null +++ b/GC-3.6.1-T2/src/controlparams.cpp @@ -0,0 +1,14 @@ +#include "controlparams.h" + +ControlParams::ControlParams() + : waitTime(LONG_WAIT_SEC), zJogRate(DEFAULT_Z_JOG_RATE), + useMm(true), zRateLimit(false), zRateLimitAmount(DEFAULT_Z_LIMIT_RATE), + xyRateAmount(DEFAULT_XY_RATE), + useAggressivePreload(false), filterFileCommands(false), + reducePrecision(false), grblLineBufferLen(DEFAULT_GRBL_LINE_BUFFER_LEN), + useFourAxis(false), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS), + fourthAxisType(FOURTH_AXIS_A), usePositionRequest(true), + positionRequestType(PREQ_ALWAYS_NO_IDLE_CHK), postionRequestTimeMilliSec(DEFAULT_POS_REQ_FREQ_MSEC), + waitForJogToComplete(true) +{ +} diff --git a/GC-3.6.1-T2/src/controlparams.h b/GC-3.6.1-T2/src/controlparams.h new file mode 100644 index 0000000..0328f2d --- /dev/null +++ b/GC-3.6.1-T2/src/controlparams.h @@ -0,0 +1,34 @@ +#ifndef CONTROLPARAMS_H +#define CONTROLPARAMS_H + +#include "definitions.h" + +#define SHORT_WAIT_SEC 2 +#define LONG_WAIT_SEC 100 + +class ControlParams +{ +public: + ControlParams(); + +public: + int waitTime; + double zJogRate; + bool useMm; + bool zRateLimit; + double zRateLimitAmount; + double xyRateAmount; + bool useAggressivePreload; + bool filterFileCommands; + bool reducePrecision; + int grblLineBufferLen; + bool useFourAxis; + int charSendDelayMs; + char fourthAxisType; + bool usePositionRequest; + QString positionRequestType; + int postionRequestTimeMilliSec; + bool waitForJogToComplete; +}; + +#endif // CONTROLPARAMS_H diff --git a/GC-3.6.1-T2/src/coord3d.cpp b/GC-3.6.1-T2/src/coord3d.cpp new file mode 100644 index 0000000..b89d175 --- /dev/null +++ b/GC-3.6.1-T2/src/coord3d.cpp @@ -0,0 +1,11 @@ +#include "coord3d.h" + +Coord3D::Coord3D() + : x(0.0), y(0.0), z(0.0), fourth(0.0), stoppedZ(true), sliderZIndex(0) +{ +} + +bool Coord3D::operator==(const Coord3D& rhs) +{ + return (x == rhs.x && y == rhs.y && z == rhs.z && fourth == rhs.fourth) ; +} diff --git a/GC-3.6.1-T2/src/coord3d.h b/GC-3.6.1-T2/src/coord3d.h new file mode 100644 index 0000000..aac648e --- /dev/null +++ b/GC-3.6.1-T2/src/coord3d.h @@ -0,0 +1,23 @@ +#ifndef COORD3D_H +#define COORD3D_H + +#include + +class Coord3D +{ +public: + Coord3D(); + bool operator==(const Coord3D& rhs); + +public: + float x; + float y; + float z; + float fourth; + bool stoppedZ; + int sliderZIndex; +}; + +Q_DECLARE_METATYPE ( Coord3D ) + +#endif // COORD3D_H diff --git a/GC-3.6.1-T2/src/definitions.h b/GC-3.6.1-T2/src/definitions.h new file mode 100644 index 0000000..1491d8e --- /dev/null +++ b/GC-3.6.1-T2/src/definitions.h @@ -0,0 +1,68 @@ +/**************************************************************** + * definitions.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#include +#include +#include +#include "atomicintbool.h" + +#define DEFAULT_WAIT_TIME_SEC 100 + +#define DEFAULT_Z_JOG_RATE 260.0 +#define DEFAULT_Z_LIMIT_RATE 100.0 +#define DEFAULT_XY_RATE 2000.0 + +#define DEFAULT_GRBL_LINE_BUFFER_LEN 50 +#define DEFAULT_CHAR_SEND_DELAY_MS 0 + +#define MM_IN_AN_INCH 25.4 +#define PRE_HOME_Z_ADJ_MM 5.0 + +#define REQUEST_CURRENT_POS "?" +#define SETTINGS_COMMAND_V08a "$" +#define SETTINGS_COMMAND_V08c "$$" +#define REQUEST_PARSER_STATE_V08c "$G" +#define SET_UNLOCK_STATE_V08c "$X" + +#define REGEXP_SETTINGS_LINE "(\\d+)\\s*=\\s*([\\w\\.]+)\\s*\\(([^\\)]*)\\)" + +#define OPEN_BUTTON_TEXT "Open" +#define CLOSE_BUTTON_TEXT "Close / Reset" + +#define LOG_MSG_TYPE_DIAG "DIAG" +#define LOG_MSG_TYPE_STATUS "STATUS" + +/// LETARTARE : one axis choice U or V or W or A or B or C +#define FOURTH_AXIS_U 'U' +#define FOURTH_AXIS_V 'V' +#define FOURTH_AXIS_W 'W' +/// <-- +#define FOURTH_AXIS_A 'A' +#define FOURTH_AXIS_B 'B' +#define FOURTH_AXIS_C 'C' + +#define PREQ_ALWAYS "always" +#define PREQ_ALWAYS_NO_IDLE_CHK "alwaysWithoutIdleChk" +#define PREQ_NOT_WHEN_MANUAL "notWhenManual" + +#define DEFAULT_POS_REQ_FREQ_SEC 1.0 +#define DEFAULT_POS_REQ_FREQ_MSEC 1000 + +extern AtomicIntBool g_enableDebugLog; + +void status(const char *str, ...); +void diag(const char *str, ...); +void err(const char *str, ...); +void warn(const char *str, ...); +void info(const char *str, ...); + +#endif // DEFINITIONS_H diff --git a/GC-3.6.1-T2/src/fixqt4headers.pl b/GC-3.6.1-T2/src/fixqt4headers.pl new file mode 100644 index 0000000..bb719f7 --- /dev/null +++ b/GC-3.6.1-T2/src/fixqt4headers.pl @@ -0,0 +1,170 @@ +#!/usr/bin/env perl +############################################################################# +## +## Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +## Contact: http://www.qt-project.org/legal +## +## This file is part of the porting tools of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and Digia. For licensing terms and +## conditions see http://qt.digia.com/licensing. For further information +## use the contact form at http://qt.digia.com/contact-us. +## +## 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, Digia gives you certain additional +## rights. These rights are described in the Digia Qt LGPL Exception +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3.0 as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL included in the +## packaging of this file. Please review the following information to +## ensure the GNU General Public License version 3.0 requirements will be +## met: http://www.gnu.org/copyleft/gpl.html. +## +## +## $QT_END_LICENSE$ +## +############################################################################# + + +use Cwd; +use File::Find; +use File::Spec; +use IO::File; +use Getopt::Long; +use strict; +use warnings; + +my $dry_run = 0; +my $help = 0; +my $stripModule = 0; +my $fixedFileCount = 0; +my $fileCount = 0; +my $verbose = 0; +my $qtdir = $ENV{'QTDIR'}; + +my $USAGE=< : Point to Qt 5's qtbase directory +EOF + +if (!GetOptions('dry-run' => \$dry_run, 'help' => \$help, + 'strip-modules' => \$stripModule, 'verbose' => \$verbose, 'qtdir:s' => \$qtdir) + || $help) { + print $USAGE; + exit (1); +} + +my %headerSubst = (); +my $cwd = getcwd(); + +sub fixHeaders +{ + my $fileName = $File::Find::name; + my $relFileName = File::Spec->abs2rel($fileName, $cwd); + + # only check sources, also ignore symbolic links and directories + return unless -f $fileName && $fileName =~ /(\.h|\.cpp|\/C|\.cc|\.CC)$/; + + my $inFile = new IO::File('<' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + $fileCount++; + my @affectedClasses; + my @outLines; + + while (my $line = <$inFile>) { + if ($line =~ /^#(\s*)include(\s*)<.*?\/(.*?)>(.*)/) { + my $newHeader = $headerSubst{$3}; + if ($newHeader) { + $line = '#' . $1 . 'include' . $2 . '<' . $newHeader . '>' . $4 . "\n"; + push(@affectedClasses, $3); + } + } elsif ($line =~ /^#(\s*)include(\s*)(.*)/) { + $line = '#' . $1 . 'include' . $2 . '' . $3 . "\n"; + push(@affectedClasses, 'QtGui'); + } + push(@outLines, $line); + } + $inFile->close(); + + if (scalar(@affectedClasses)) { + $fixedFileCount++; + print $relFileName, ': ', join(', ', @affectedClasses), "\n" if ($verbose || $dry_run); + if (!$dry_run) { + my $outFile = new IO::File('>' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + map { print $outFile $_; } @outLines; + $outFile->close(); + } + } else { + print $relFileName, ": no modification.\n" if ($verbose || $dry_run); + } +} + +sub findQtHeaders +{ + my ($dirName,$baseDir) = @_; + + local (*DIR); + + opendir(DIR, $baseDir . '/include/' . $dirName) || die ('Unable to open ' .$baseDir . '/include/' . $dirName . ': ' . $!); + my @headers = readdir(DIR); + closedir(DIR); + + foreach my $header (@headers) { + next if (-d ($baseDir . '/include/' . $dirName . '/' . $header) || $header =~ /\.pri$/); + $headerSubst{$header} = $stripModule ? $header : ($dirName . '/' . $header); + } +} + +# -------- MAIN + +die "This script requires the QTDIR environment variable pointing to Qt 5\n" unless $qtdir; + +findQtHeaders('QtCore', $qtdir); +findQtHeaders('QtConcurrent', $qtdir); +findQtHeaders('QtWidgets', $qtdir); +findQtHeaders('QtPrintSupport', $qtdir); + +if (-d $qtdir . '/include/QtMultiMedia') { + findQtHeaders('QtMultiMedia', $qtdir); + findQtHeaders('QtMultiMediaWidgets', $qtdir); +} elsif (-d $qtdir . '/../qtmultimedia' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtMultiMedia', $qtdir . '/../qtmultimedia'); + findQtHeaders('QtMultiMediaWidgets', $qtdir . '/../qtmultimedia'); +} + +# Support porting from "Qt 4.99" QtDeclarative to QtQuick (QQuickItem et al) +if (-d $qtdir . '/include/QtQuick') { + findQtHeaders('QtQuick', $qtdir); +} elsif (-d $qtdir . '/../qtdeclarative' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtQuick', $qtdir . '/../qtdeclarative'); +} + +# special case +$headerSubst{'QtGui'} = 'QtWidgets/QtWidgets'; + +find({ wanted => \&fixHeaders, no_chdir => 1}, $cwd); + +print 'Done. ', ($dry_run ? 'Checked' : 'Modified'), ' ', $fixedFileCount, ' of ', $fileCount, " file(s).\n"; diff --git a/GC-3.6.1-T2/src/gcode.cpp b/GC-3.6.1-T2/src/gcode.cpp new file mode 100644 index 0000000..529cecb --- /dev/null +++ b/GC-3.6.1-T2/src/gcode.cpp @@ -0,0 +1,2027 @@ +/**************************************************************** + * gcode.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "gcode.h" + +#include + +GCode::GCode() + : errorCount(0), doubleDollarFormat(false), + incorrectMeasurementUnits(false), incorrectLcdDisplayUnits(false), + maxZ(0), motionOccurred(false), + sliderZCount(0), + positionValid(false), + numaxis(DEFAULT_AXIS_COUNT) +{ + // use base class's timer - use it to capture random text from the controller + startTimer(1000); + // for position polling + pollPosTimer.start(); +} + +void GCode::openPort(QString commPortStr, QString baudRate) +{ + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + clearToHome(); + + currComPort = commPortStr; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if (port.OpenComport(commPortStr, baudRate)) + { + emit portIsOpen(true); + } + else + { + emit portIsClosed(false); + QString msg = tr("Can't open COM port ") + commPortStr; + sendMsg(msg); + addList(msg); + warn("%s", qPrintable(msg)); + + addList(tr("-Is hardware connected to USB?") ); + addList(tr("-Is correct port chosen?") ); + addList(tr("-Does current user have sufficient permissions?") ); +#if defined(Q_OS_LINUX) + addList("-Is current user in sudoers group?"); +#endif + //QMessageBox(QMessageBox::Critical,"Error","Could not open port.",QMessageBox::Ok).exec(); + } +} + +void GCode::closePort(bool reopen) +{ + port.CloseComport(); + emit portIsClosed(reopen); +} + +bool GCode::isPortOpen() +{ + return port.isPortOpen(); +} + +// Abort means stop file send after the end of this line +void GCode::setAbort() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + abortState.set(true); +} + +// Reset means immediately stop waiting for a response +void GCode::setReset() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + resetState.set(true); +} + +// Shutdown means app is shutting down - we give thread about .3 sec to exit what it is doing +void GCode::setShutdown() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + shutdownState.set(true); +} + +// Slot for interrupting current operation or doing a clean reset of grbl without changing position values +void GCode::sendGrblReset() +{ + clearToHome(); + + QString x(CTRL_X); + sendGcodeLocal(x, true, SHORT_WAIT_SEC); +} + +void GCode::sendGrblUnlock() +{ + sendGcodeLocal(SET_UNLOCK_STATE_V08c); +} + +// Slot for gcode-based 'zero out the current position values without motion' +void GCode::grblSetHome() +{ + clearToHome(); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G92 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G92 x0 y0 z0"); +} + +void GCode::goToHome() +{ + if (!motionOccurred) + return; + + double maxZOver = maxZ; + + if (doubleDollarFormat) + { + maxZOver += (controlParams.useMm ? PRE_HOME_Z_ADJ_MM : (PRE_HOME_Z_ADJ_MM / MM_IN_AN_INCH)); + } + else + { + // all reporting is in mm + maxZOver += PRE_HOME_Z_ADJ_MM; + } + + QString zpos = QString::number(maxZOver); + + gotoXYZFourth(QString("G0 z").append(zpos)); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G1 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G1 x0 y0 z0"); + + maxZ -= maxZOver; + + motionOccurred = false; +} + +// Slot called from other threads (i.e. main window, grbl dialog, etc.) +void GCode::sendGcode(QString line) +{ + bool checkMeasurementUnits = false; + + // empty line means we have just opened the com port + if (line.length() == 0) + { + resetState.set(false); + + QString result; + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, false)) + { + if (shutdownState.get() || resetState.get()) + return; + // it is possible that we are already connected and missed the + // signon banner. Force a reset (is this ok?) to get the banner + +/// LETARTARE for 0.845 !! +/* + emit addListOut("(CTRL-X)"); + + char buf[2] = {0}; + + buf[0] = CTRL_X; + + diag(qPrintable(tr("SENDING: 0x%02X (CTRL-X) to check presence of Grbl\n")), buf[0]) ; + if (!port.SendBuf(buf, 1)) + { + QString msg = tr("Sending to port failed"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return; + } +*/ +/// <-- + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, true)) + return; + } + + checkMeasurementUnits = true; + } + else + { + pollPosWaitForIdle(false); + // normal send of actual commands + sendGcodeLocal(line, false); + } + + pollPosWaitForIdle(checkMeasurementUnits); +} + +// keep polling our position and state until we are done running +void GCode::pollPosWaitForIdle(bool checkMeasurementUnits) +{ + if (controlParams.usePositionRequest + && (controlParams.positionRequestType == PREQ_ALWAYS_NO_IDLE_CHK + || controlParams.positionRequestType == PREQ_ALWAYS + || checkMeasurementUnits)) + { + bool immediateQuit = false; + for (int i = 0; i < 10000; i++) + { + GCode::PosReqStatus ret = positionUpdate(); + if (ret == POS_REQ_RESULT_ERROR || ret == POS_REQ_RESULT_UNAVAILABLE) + { + immediateQuit = true; + break; + } + else if (ret == POS_REQ_RESULT_TIMER_SKIP) + { + SLEEP(250); + continue; + } + + if (doubleDollarFormat) + { + if (lastState.compare("Run") != 0) + break; + } + else + { + if (machineCoordLastIdlePos == machineCoord + && workCoordLastIdlePos == workCoord) + { + break; + } + + machineCoordLastIdlePos = machineCoord; + workCoordLastIdlePos = workCoord; + } + + if (shutdownState.get()) + return; + } + + if (immediateQuit) + return; +/// LETARTARE T3 + /* + if (checkMeasurementUnits) + { + if (doubleDollarFormat) + checkAndSetCorrectMeasurementUnits(); + else + setOldFormatMeasurementUnitControl(); + } + */ + } + else + { + setLivenessState(false); + } +} + +// Slot called from other thread that returns whatever text comes back from the controller +void GCode::sendGcodeAndGetResult(int id, QString line) +{ + QString result; + + emit sendMsg(""); + resetState.set(false); + if (!sendGcodeInternal(line, result, false, SHORT_WAIT_SEC, false)) + result.clear(); + + emit gcodeResult(id, result); +} + +// To be called only from this class, not from other threads. Use above two methods for that. +// Wraps sendGcodeInternal() to allow proper handling of failure cases, etc. +bool GCode::sendGcodeLocal(QString line, bool recordResponseOnFail /* = false */, int waitSec /* = -1 */, bool aggressive /* = false */, int currLine /* = 0 */) +{ + QString result; + sendMsg(""); + resetState.set(false); + + bool ret = sendGcodeInternal(line, result, recordResponseOnFail, waitSec, aggressive, currLine); + if (shutdownState.get()) + return false; + + if (!ret && (!recordResponseOnFail || resetState.get())) + { + if (!resetState.get()) + emit stopSending(); + + if (!ret && resetState.get()) + { + resetState.set(false); + port.Reset(); + } + } + else + { + if (checkGrbl(result)) + { + emit enableGrblDialogButton(); + } + } + resetState.set(false); + return ret; +} + +bool GCode::checkGrbl(const QString& result) +{ + if (result.contains("Grbl")) + { +/// LETARTARE T2 + (\\w*) for 0.8cx + QRegExp rx("Grbl (\\d+)\\.(\\d+)(\\w*)(\\w*)"); + if (rx.indexIn(result) != -1 && rx.captureCount() > 0) + { + doubleDollarFormat = false; + + QStringList list = rx.capturedTexts(); + if (list.size() >= 3) + { + int majorVer = list.at(1).toInt(); + int minorVer = list.at(2).toInt(); + char letter = ' '; + char postVer = ' '; /// T2 + if (list.size() >= 4 && list.at(3).size() > 0) + { + letter = list.at(3).toLatin1().at(0); + /// T2 for 0.8cx + if (list.at(3).toLatin1().size() > 1) + postVer = list.at(3).toLatin1().at(1); + } + + if (majorVer > 0 || (minorVer > 8 && minorVer < 51) || letter > 'a') + { + doubleDollarFormat = true; + } +/// LETARTARE T2 + diag(qPrintable(tr("Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d)\n")), + majorVer, minorVer, letter, postVer, doubleDollarFormat); + QString resu = list.at(0); + emit setVersionGrbl(resu); +/// <-- + } + + if (!doubleDollarFormat) + setUnitsTypeDisplay(true); + } + return true; + } + return false; +} + +// Wrapped method. Should only be called from above method. +bool GCode::sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine /* = 0 */) +{ + if (!port.isPortOpen()) + { + QString msg = tr("Port not available yet") ; + err("%s", msg.toLocal8Bit().constData()); + emit addList(msg); + emit sendMsg(msg); + return false; + } + + bool ctrlX = line.size() > 0 ? (line.at(0).toLatin1() == CTRL_X) : false; + + bool sentReqForLocation = false; + bool sentReqForSettings = false; + bool sentReqForParserState = false; + + if (checkForGetPosStr(line)) + { + sentReqForLocation = true; + setLivenessState(true); + } + else if (!line.compare(REQUEST_PARSER_STATE_V08c)) + { + sentReqForParserState = true; + } + else if (!line.compare(SETTINGS_COMMAND_V08a)) + { + if (doubleDollarFormat) + line = SETTINGS_COMMAND_V08c; + + sentReqForSettings = true; + } + else + motionOccurred = true; + + // adds to UI list, but prepends a > indicating a sent command + if (ctrlX) + { + emit addListOut("(CTRL-X)"); + } + else if (!sentReqForLocation)// if requesting location, don't add that "noise" to the output view + { +/// T1, T2 + fix bug + QString nLine(line); + if (currLine) { + nLine = QString().setNum(currLine); + emit setLinesFile(nLine); + if (line.at(0).toLatin1() != 'N') + nLine = "L" + nLine + " " + line; + else + nLine = line ; + } + emit addListOut(nLine); + /// <-- + } + + if (line.size() == 0 || (!line.endsWith('\r') && !ctrlX)) + line.append('\r'); + + char buf[BUF_SIZE + 1] = {0}; + if (line.length() >= BUF_SIZE) + { + QString msg = tr("Buffer size too small"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + for (int i = 0; i < line.length(); i++) + buf[i] = line.at(i).toLatin1(); + + if (ctrlX) + diag(qPrintable(tr("SENDING[%d]: 0x%02X (CTRL-X)\n")), currLine, buf[0]); + else + diag(qPrintable(tr("SENDING[%d]: %s\n")), currLine, buf); + + int waitSecActual = waitSec == -1 ? controlParams.waitTime : waitSec; + + if (aggressive) + { + if (ctrlX) + sendCount.append(CmdResponse("(CTRL-X)", line.length(), currLine)); + else + sendCount.append(CmdResponse(buf, line.length(), currLine)); + + //diag("DG Buffer Add %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + + waitForOk(result, waitSecActual, false, false, aggressive, false); + + if (shutdownState.get()) + return false; + } + + if (!port.SendBuf(buf, line.length())) + { + QString msg = tr("Sending to port failed") ; + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + else + { + sentI++; + if (!waitForOk(result, waitSecActual, sentReqForLocation, sentReqForParserState, aggressive, false)) + { + diag(qPrintable(tr("WAITFOROK FAILED\n"))); + if (shutdownState.get()) + return false; + + if (!recordResponseOnFail && !(resetState.get() || abortState.get())) + { + QString msg = tr("Wait for ok failed"); + emit addList(msg); + emit sendMsg(msg); + } + + return false; + } + else + { + if (sentReqForSettings) + { + QStringList list = result.split("$"); + for (int i = 0; i < list.size(); i++) + { + QString item = list.at(i); + const QRegExp rx(REGEXP_SETTINGS_LINE); + + if (rx.indexIn(item, 0) != -1 && rx.captureCount() == 3) + { + QStringList capList = rx.capturedTexts(); + if (!capList.at(1).compare("13")) + { + if (!capList.at(2).compare("0")) + { + if (!controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + else + { + if (controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + break; + } + } + } + + settingsItemCount.set(list.size()); + } + } + } + return true; +} + +bool GCode::waitForOk(QString& result, int waitSec, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize) +{ + int okcount = 0; + + if (aggressive) + { + //if (!port.bytesAvailable()) //more conservative code + if (!finalize || !port.bytesAvailable()) + { + int total = 0; + bool haveWait = false; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + if (cmdResp.waitForMe) + { + haveWait = true; + } + } + + //printf("Total out (a): %d (%d) (%d)\n", total, sendCount.size(), haveWait); + + if (!haveWait) + { + if (total < (GRBL_RX_BUFFER_SIZE - 1)) + { + return true; + } + } + } + } + + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!result.contains(RESPONSE_OK) && !result.contains(RESPONSE_ERROR) && !resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + if (aggressive && sendCount.size() == 0) + return false; + + count++; + SLEEP(100); + } + else if (n < 0) + { + QString Mes(tr("Error reading data from COM port\n")) ; + err(qPrintable(Mes)); + + if (aggressive && sendCount.size() == 0) + return false; + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + QString received(tmp); + + if (aggressive) + { + if (received.contains(RESPONSE_OK)) + { + if (sendCount.isEmpty()) { + err(qPrintable(tr("Unexpected: list is empty (o)!"))); + } + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + diag(qPrintable(tr("GOT[%d]:%s for %s\n")), cmdResp.line, tmpTrim.toLocal8Bit().constData(), cmdResp.cmd.toLocal8Bit().constData()); + + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + rcvdI++; + okcount++; + } + else if (received.contains(RESPONSE_ERROR)) + { + QString orig(tr("Error?")); + if (sendCount.isEmpty()) + err(qPrintable(tr("Unexpected: list is empty (e)!"))); + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + orig = cmdResp.cmd; + diag(qPrintable(tr("GOT[%d]:%s for %s\n")), cmdResp.line, tmpTrim.toLocal8Bit().constData(), orig.toLocal8Bit().constData()); + + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + errorCount++; + QString result; + QTextStream(&result) << received << " [for " << orig << "]"; + emit addList(result); + grblCmdErrors.append(result); + rcvdI++; + } + else + { + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + parseCoordinates(received, aggressive); + } + + int total = 0; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + } + + //printf("Total out (b): %d (%d)\n", total, sendCount.size()); + //printf("SENT:%d RCVD:%d\n", sentI, rcvdI); + + if (total >= (GRBL_RX_BUFFER_SIZE - 1)) + { + //diag("DG Loop again\n"); + result.clear(); + continue; + } + else if (port.bytesAvailable()) + { + // comment out this block for more conservative approach + if (!finalize && okcount > 0) + { + //diag("DG Leave early\n"); + return true; + } + + result.clear(); + continue; + } + else + { + return true; + } + } + else + { + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + } + + if (!received.contains(RESPONSE_OK) && !received.contains(RESPONSE_ERROR)) + { + if (sentReqForParserState) + { + const QRegExp rx("\\[([\\s\\w\\.\\d]+)\\]"); + + if (rx.indexIn(received, 0) != -1 && rx.captureCount() == 1) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 2) + { + QStringList items = list.at(1).split(" "); + if (items.contains("G20"))// inches + { + if (controlParams.useMm) + incorrectMeasurementUnits = true; + else + incorrectMeasurementUnits = false; + } + else if (items.contains("G21"))// millimeters + { + if (controlParams.useMm) + incorrectMeasurementUnits = false; + else + incorrectMeasurementUnits = true; + } + else + { + // not in list! + incorrectMeasurementUnits = true; + } + } + } + } + else + { + parseCoordinates(received, aggressive); + } + } + count = 0; + } + + SLEEP(100); + + if (count > waitCount) + { + // waited too long for a response, fail + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (!aggressive) + SLEEP(100); + + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !sentReqForLocation && !list.at(i).startsWith("MPos:[")) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +bool GCode::waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound) +{ + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + count++; + SLEEP(100); + } + else if (n < 0) + { + err(qPrintable(tr("Error reading data from COM port\n")) ); + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + + if (tmpTrim.length() > 0) + { + if (!checkGrbl(tmpTrim)) + { + if (failOnNoFound) + { + QString msg(tr("Expecting Grbl version string. Unable to parse response.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + status = false; + } + else + { + emit enableGrblDialogButton(); + } + break; + } + } + + SLEEP(100); + + if (count > waitCount) + { + if (failOnNoFound) + { + // waited too long for a response, fail + + QString msg(tr("No data from COM port after connect. Expecting Grbl version string.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user (startup)")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +/// LETARTARE T1 +/* +/// May 13, 2014 + 1- frame1 : < 8c (3 axes), 0.845 (4 axes) -> $$==0 + received == "MPos:[....],WPos:[....]" + 2- frame2 : 0.8c1 or 0.8c2 (4 axes) -> $$==1 + received == "" + 3- frame2 : 0.8c (3 axes) -> $$==1 + received == "" + 4- frame3 : 0.9d (3 axes), 0.9d1 (4 axes) -> $$==1 + received == "" +*/ + +void GCode::parseCoordinates(const QString& received, bool aggressive) +{ + if (aggressive) + { + int ms = parseCoordTimer.elapsed(); + if (ms < 500) + return; + + parseCoordTimer.restart(); + } + + bool good = false ; + int captureCount ; + QString state; + QString prepend; + QString append; + QString preamble = "([a-zA-Z]+),MPos:"; + if (!doubleDollarFormat) + { + prepend = "\\["; + append = "\\]"; + preamble = "MPos:" ; + } + QString coordRegExp; + QRegExp rxStateMPos; + QRegExp rxWPos; +/// 1 axis + QString format1("(-*\\d+\\.\\d+)") ; + QString sep(","); + /// 3 axes + QString format3 = format1 + sep + format1 + sep + format1 ; + /// 4 axes + QString format4 = format3 + sep + format1 ; + QString format ; + int naxis ; + for (naxis = MAX_AXIS_COUNT; naxis >= DEFAULT_AXIS_COUNT; naxis--) { + if (!doubleDollarFormat) + captureCount = naxis ; + else + captureCount = naxis + 1 ; + + if (naxis == MAX_AXIS_COUNT ) + format = format4; + else + format = format3; + + coordRegExp = prepend + format + append ; + rxStateMPos = QRegExp(preamble + coordRegExp); + rxWPos = QRegExp(QString("WPos:") + coordRegExp); + good = rxStateMPos.indexIn(received, 0) != -1 + && rxStateMPos.captureCount() == captureCount + && rxWPos.indexIn(received, 0) != -1 + && rxWPos.captureCount() == naxis + ; + + // find naxis ... + if (good) + break; + } + if (good) { /// naxis contains number axis + if (numaxis <= DEFAULT_AXIS_COUNT) + { + if (naxis > DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + else + { + if (naxis <= DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + + numaxis = naxis; + QStringList list = rxStateMPos.capturedTexts(); + int index = 1; + + if (doubleDollarFormat) + state = list.at(index++); + + machineCoord.x = list.at(index++).toFloat(); + machineCoord.y = list.at(index++).toFloat(); + machineCoord.z = list.at(index++).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + machineCoord.fourth = list.at(index++).toFloat(); + list = rxWPos.capturedTexts(); + workCoord.x = list.at(1).toFloat(); + workCoord.y = list.at(2).toFloat(); + workCoord.z = list.at(3).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + workCoord.fourth = list.at(4).toFloat(); + if (state != "Run") + workCoord.stoppedZ = true; + else + workCoord.stoppedZ = false; + + workCoord.sliderZIndex = sliderZCount; + + if (doubleDollarFormat) + diag(qPrintable(tr("Decoded: State:%s")), qPrintable(state) ); + if (numaxis == DEFAULT_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f WPos: %f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, + workCoord.x, workCoord.y, workCoord.z + ); + else if (numaxis == MAX_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, machineCoord.fourth, + workCoord.x, workCoord.y, workCoord.z, workCoord.fourth + ); + + if (workCoord.z > maxZ) + maxZ = workCoord.z; + + emit updateCoordinates(machineCoord, workCoord); + emit setLivePoint(workCoord.x, workCoord.y, controlParams.useMm, positionValid); + emit setLastState(state); + + lastState = state; + return; + } + // TODO fix to print + //if (!good /*&& received.indexOf("MPos:") != -1*/) + // err(qPrintable(tr("Error decoding position data! [%s]\n")), qPrintable(received)); + + lastState = ""; +} + +void GCode::sendStatusList(QStringList& listToSend) +{ + if (listToSend.size() > 1) + { + emit addListFull(listToSend); + } + else if (listToSend.size() == 1) + { + emit addList(listToSend.at(0)); + } +} + +// called once a second to capture any random strings that come from the controller +void GCode::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (port.isPortOpen()) + { + char tmp[BUF_SIZE + 1] = {0}; + QString result; + + for (int i = 0; i < 10 && !shutdownState.get() && !resetState.get(); i++) + { + int n = port.PollComport(tmp, BUF_SIZE); + if (n == 0) + break; + + tmp[n] = 0; + result.append(tmp); + diag(qPrintable(tr("GOT-TE:%s\n")), tmp); + } + + if (shutdownState.get()) + { + return; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && (list.at(i) != "ok" || (list.at(i) == "ok" && abortState.get()))) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + } +} + +void GCode::sendFile(QString path) +{ + addList(QString(tr("Sending file '%1'")).arg(path)); + + // send something to be sure the controller is ready + //sendGcodeLocal("", true, SHORT_WAIT_SEC); + + setProgress(0); + emit setQueuedCommands(0, false); + grblCmdErrors.clear(); + grblFilteredCmds.clear(); + errorCount = 0; + abortState.set(false); + QFile file(path); + if (file.open(QFile::ReadOnly)) + { +/// LETARTARE T1 + int totalLineCount = 0; + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLineCount++; + code.readLine(); + } + if (totalLineCount == 0) + totalLineCount = 1; + + code.seek(0); + + // set here once so that it doesn't change in the middle of a file send + bool aggressive = controlParams.useAggressivePreload; + if (aggressive) + { + sendCount.clear(); + //if (sendCount.size() == 0) + //{ + // diag("DG Buffer 0 at start\n")); + //} + + emit setQueuedCommands(sendCount.size(), true); + } + + sentI = 0; + rcvdI = 0; + emit resetTimer(true); + + parseCoordTimer.restart(); + + int currLine = 0; + bool xyRateSet = false; +/// LETARTARE T1 + QString strline ; + do + { + strline = code.readLine(); + + emit setVisCurrLine(currLine + 1); + + if (controlParams.filterFileCommands) + { + trimToEnd(strline, '('); + trimToEnd(strline, ';'); + trimToEnd(strline, '%'); + } + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + if (controlParams.filterFileCommands) + { + strline = strline.toUpper(); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline = removeUnsupportedCommands(strline); + } + + if (strline.size() != 0) + { + if (controlParams.reducePrecision) + { + strline = reducePrecision(strline); + } + + QString rateLimitMsg; + QStringList outputList; + if (controlParams.zRateLimit) + { + outputList = doZRateLimit(strline, rateLimitMsg, xyRateSet); + } + else + { + outputList.append(strline); + } + + bool ret = false; + if (outputList.size() == 1) + { + ret = sendGcodeLocal(outputList.at(0), false, -1, aggressive, currLine + 1); + } + else + { + foreach (QString outputLine, outputList) + { + ret = sendGcodeLocal(outputLine, false, -1, aggressive, currLine + 1); + + if (!ret) + break; + } + } + + if (rateLimitMsg.size() > 0) + addList(rateLimitMsg); + + if (!ret) + { + abortState.set(true); + break; + } + } + } + + float percentComplete = (currLine * 100.0) / totalLineCount; + setProgress((int)percentComplete); + + positionUpdate(); + currLine++; + } while ((code.atEnd() == false) && (!abortState.get())); + file.close(); + + if (aggressive) + { + int limitCount = 5000; + while (sendCount.size() > 0 && limitCount) + { + QString result; + waitForOk(result, controlParams.waitTime, false, false, aggressive, true); + SLEEP(100); + + if (shutdownState.get()) + return; + + if (abortState.get()) + break; + + limitCount--; + } + + if (!limitCount) + { + err(qPrintable(tr("Gave up waiting for OK\n"))); + } + } + + positionUpdate(); + + emit resetTimer(false); + + if (shutdownState.get()) + { + return; + } + + QString msg; + if (!abortState.get()) + { + setProgress(100); + if (errorCount > 0) + { + msg = QString(tr("Code sent successfully with %1 error(s):")).arg(QString::number(errorCount)); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblCmdErrors) + { + emit sendMsg(errItem); + } + emit addListFull(grblCmdErrors); + } + else + { + msg = tr("Code sent successfully with no errors."); + emit sendMsg(msg); + emit addList(msg); + } + + if (grblFilteredCmds.size() > 0) + { + msg = QString(tr("Filtered %1 commands:")).arg(QString::number(grblFilteredCmds.size())); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblFilteredCmds) + { + emit sendMsg(errItem); + } + emit addListFull(grblFilteredCmds); + } + } + else + { + msg = tr("Process interrupted."); + emit sendMsg(msg); + emit addList(msg); + } + } + + pollPosWaitForIdle(true); + + if (!resetState.get()) + { + emit stopSending(); + } + + emit setQueuedCommands(0, false); +} + +void GCode::trimToEnd(QString& strline, QChar ch) +{ + int pos = strline.indexOf(ch); + if (pos != -1) + strline = strline.left(pos); +} + +QString GCode::removeUnsupportedCommands(QString line) +{ + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString tmp; + QString s; + QString following; + bool toEndOfLine = false; + foreach (s, components) + { + if (toEndOfLine) + { + QString msg(QString(tr("Removed unsupported command '%1' part of '%2'")).arg(s).arg(following)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + continue; + } + + if (s.at(0) == 'G') + { + float value = s.mid(1,-1).toFloat(); + if (isGCommandValid(value, toEndOfLine)) + tmp.append(s).append(" "); + else + { + if (toEndOfLine) + following = s; + QString msg(QString(tr("Removed unsupported G command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'M') + { + float value = s.mid(1,-1).toFloat(); + if (isMCommandValid(value)) + tmp.append(s).append(" "); + else + { + QString msg(QString(tr("Removed unsupported M command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'N') + { + // skip line numbers + } + else if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'Z' + || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C' +/// LETARTARE + || s.at(0) == 'U' || s.at(0) == 'V' || s.at(0) == 'W' +/// <-- + || s.at(0) == 'I' || s.at(0) == 'J' || s.at(0) == 'K' + || s.at(0) == 'F' || s.at(0) == 'L' || s.at(0) == 'S') + { + tmp.append(s).append(" "); + } + else + { + QString msg(QString(tr("Removed unsupported command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + + return tmp.trimmed(); +} + +QString GCode::reducePrecision(QString line) +{ + // first remove all spaces to determine what are line length is + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString result; + foreach(QString token, components) + { + result.append(token); + } + + if (result.length() == 0) + return line;// nothing to do + + if (!result.at(0).isLetter()) + return line;// leave as-is if not a command + + // find first comment and eliminate + int pos = result.indexOf('('); + if (pos >= 0) + result = result.left(pos); + + int charsToRemove = result.length() - (controlParams.grblLineBufferLen - 1);// subtract 1 to account for linefeed sent with command later + + if (charsToRemove > 0) + { + // ok need to do something with precision + // split apart based on letter + pos = 0; + components.clear(); + int i; + for (i = 1; i < result.length(); i++) + { + if (result.at(i).isLetter()) + { + components.append(result.mid(pos, i - pos)); + pos = i; + } + } + + if (pos == 0) + { + // we get here if only one command + components.append(result); + } + else + { + // add last item + components.append(result.mid(pos, i)); + } + + QList items; + foreach (QString tmp, components) + { + items.append(DecimalFilter(tmp)); + } + + int totalDecCount = 0; + int eligibleArgumentCount = 0; + int largestDecCount = 0; + for (int j = 0; j < items.size(); j++) + { + DecimalFilter& item = items[j]; + pos = item.token.indexOf('.'); + if ((item.token.at(1).isDigit() || item.token.at(1) == '-' || item.token.at(1) == '.') && pos >= 0) + { + // candidate to modify + // count number of decimal places + int decPlaceCount = 0; + for (i = pos + 1; i < item.token.length(); i++, decPlaceCount++) + { + if (!item.token.at(i).isDigit()) + break; + } + + // skip commands that have a single decimal place + if (decPlaceCount > 1) + { + item.decimals = decPlaceCount; + totalDecCount += decPlaceCount - 1;// leave at least the last decimal place + eligibleArgumentCount++; + if (decPlaceCount > largestDecCount) + largestDecCount = decPlaceCount; + } + } + } + + bool failRemoveSufficientDecimals = false; + if (totalDecCount < charsToRemove) + { + // remove as many as possible, then grbl will truncate + charsToRemove = totalDecCount; + failRemoveSufficientDecimals = true; + } + + if (eligibleArgumentCount > 0) + { + for (int k = largestDecCount; k > 1 && charsToRemove > 0; k--) + { + for (int j = 0; j < items.size() && charsToRemove > 0; j++) + { + DecimalFilter& item = items[j]; + if (item.decimals == k) + { + item.token.chop(1); + item.decimals--; + charsToRemove--; + } + } + } + + //chk.clear(); + //chk.append("CORRECTED:"); + result.clear(); + foreach (DecimalFilter item, items) + { + result.append(item.token); + + //chk.append("["); + //chk.append(item.token); + //chk.append("]"); + } + //diag(chk.toLocal8Bit().constData()); + + err(qPrintable(tr("Unable to remove enough decimal places for command (will be truncated): %s")), line.toLocal8Bit().constData()); + + QString msg; + if (failRemoveSufficientDecimals) + msg = QString(tr("Error, insufficent reduction '%1'")).arg(result); + else + msg = QString(tr("Precision reduced '%1'")).arg(result); + + emit addList(msg); + emit sendMsg(msg); + } + } + + return result; +} + +bool GCode::isGCommandValid(float value, bool& toEndOfLine) +{ + toEndOfLine = false; + // supported values obtained from https://github.com/grbl/grbl/wiki + const static float supported[] = + { + 0, 1, 2, 3, 4, + 10, 17, 18, 19, 20, 21, 28, 28.1, 30, 30.1, + 53, 54, 55, 56, 57, 58, 59, + 80, 90, 91, 92, 92.1, 93, 94 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + + if (value == 43 || value == 44) + { + toEndOfLine = true; + } + return false; +} + +bool GCode::isMCommandValid(float value) +{ + // supported values obtained from https://github.com/grbl/grbl/wiki + + // NOTE: M2 and M30 are supported but they cause occasional grbl lockups + // and thus have been removed from the supported list. No harm is caused + // by their removal. + const static float supported[] = + { + 0, 3, 4, 5, 8, 9 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + return false; +} + +QStringList GCode::doZRateLimit(QString inputLine, QString& msg, bool& xyRateSet) +{ + // i.e. + //G00 Z1 => G01 Z1 F100 + //G01 Z1 F260 => G01 Z1 F100 + //G01 Z1 F30 => G01 Z1 F30 + //G01 X1 Y1 Z1 F200 -> G01 X1 Y1 & G01 Z1 F100 + QStringList list; + QString line = inputLine.toUpper(); + + if (line.count("Z") > 0) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + bool foundFeed = false; + bool didLimit = false; + + // We need to build one or two command strings depending on input. + QString x, y, g, f; + + // First get all component parts + bool inLimit = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + g = s; + } + else if (s.at(0) == 'F') + { + f = s; + + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + inLimit = true; + } + else if (s.at(0) == 'X') + { + x = s; + } + else if (s.at(0) == 'Y') + { + y = s; + } + } + + // Determine whether we want to have one or two command lins + // 1 string: Have !G0 and F but not in limit + // 1 string: Have Z only + // 2 strings: All other conditions + QString line1; + QString line2; + if ((g != "G0" && f.size() > 0 && !inLimit) + || (x.size() == 0 && y.size() == 0)) + { + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value == 0) + line1.append("G1"); + else + line1.append(s); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s); + + foundFeed = true; + } + else + { + line1.append(s); + } + line1.append(" "); + } + } + else + { + // two lines + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 1) + line1.append("G1").append(" "); + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + + foundFeed = true; + } + else if (s.at(0) == 'Z') + { + line1.append(s).append(" "); + } + else + { + line2.append(s).append(" "); + } + } + } + + if (!foundFeed) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + + line1 = line1.trimmed(); + line2 = line2.trimmed(); + + if (didLimit) + { + if (line2.size() == 0) + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2]")).arg(inputLine).arg(line1); + xyRateSet = true; + } + else + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2,%3]")).arg(inputLine).arg(line1).arg(line2); + line2.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + } + } + + list.append(line1); + if (line2.size() > 0) + list.append(line2); + return list; + } + else if (xyRateSet) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + + bool addRateG = false; + bool addRateXY = false; + bool gotF = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 0) + { + addRateG = true; + } + } + else if (s.at(0) == 'F') + { + gotF = true; + } + else + if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C') + { + addRateXY = true; + } + } + + if (addRateG && addRateXY) + { + if (!gotF) + { + QString line = inputLine; + line.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + msg = QString(tr("XY-Rate Limit FIX: [%1]=>[%2]")).arg(inputLine).arg(line); + list.append(line); + } + else + { + list.append(inputLine); + } + + xyRateSet = false; + + return list; + } + } + + list.append(inputLine); + return list; + +} + +void GCode::gotoXYZFourth(QString line) +{ + bool queryPos = checkForGetPosStr(line); + if (!queryPos && controlParams.usePositionRequest + && controlParams.positionRequestType == PREQ_ALWAYS) + pollPosWaitForIdle(false); + + if (sendGcodeLocal(line)) + { + line = line.toUpper(); + + bool moveDetected = false; + + QStringList list = line.split(QRegExp("[\\s]+")); + for (int i = 0; i < list.size(); i++) + { + QString item = getMoveAmountFromString("X", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Y", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Z", list.at(i)); + moveDetected = item.length() > 0 ; + if (numaxis == MAX_AXIS_COUNT) { + item = getMoveAmountFromString(QString(controlParams.fourthAxisType), list.at(i)); + moveDetected = item.length() > 0; + } + } + + if (!moveDetected) + { + //emit addList("No movement expected for command."); + } + + if (!queryPos) + pollPosWaitForIdle(false); + } + else + { + QString msg(QString(tr("Bad command: %1")).arg(line)); + warn("%s", qPrintable(msg)); + emit addList(msg); + } + + emit setCommandText(""); +} + + +QString GCode::getMoveAmountFromString(QString prefix, QString item) +{ + int index = item.indexOf(prefix); + if (index != -1) + return item.mid(index + 1); + + return ""; +} + +void GCode::axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sZC) +{ + if (inv) + { + coord = (-coord); + } + + QString cmd = QString("G01 ").append(axis) + .append(QString::number(coord)); + + if (axis == 'Z') + { + cmd.append(" F").append(QString::number(controlParams.zJogRate)); + } + + SendJog(cmd, absoluteAfterAxisAdj); + + if (axis == 'Z') + sliderZCount = sZC; + + emit adjustedAxis(); +} + +bool GCode::SendJog(QString cmd, bool absoluteAfterAxisAdj) +{ + pollPosWaitForIdle(false); + + // G91 = distance relative to previous + bool ret = sendGcodeLocal("G91\r"); + + bool result = ret && sendGcodeLocal(cmd.append("\r")); + + if (result) + { + pollPosWaitForIdle(false); + } + + if (absoluteAfterAxisAdj) + sendGcodeLocal("G90\r"); + + return result; +} + +// settings change calls here +void GCode::setResponseWait(ControlParams controlParamsIn) +{ + bool oldMm = controlParams.useMm; + + controlParams = controlParamsIn; + + controlParams.useMm = oldMm; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if ((oldMm != controlParamsIn.useMm) && isPortOpen() && doubleDollarFormat) + { + if (controlParamsIn.useMm) + { + setConfigureMmMode(true); + } + else + { + setConfigureInchesMode(true); + } + } + + controlParams.useMm = controlParamsIn.useMm; + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + setUnitsTypeDisplay(controlParams.useMm); +} + +int GCode::getSettingsItemCount() +{ + return settingsItemCount.get(); +} + +// 0.8c and above only! +void GCode::checkAndSetCorrectMeasurementUnits() +{ + sendGcodeLocal(REQUEST_PARSER_STATE_V08c, false); + + if (incorrectMeasurementUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl parser set for inches. Fixing.")); + setConfigureMmMode(true); + } + else + { + emit addList(tr("Options specify use inches but Grbl parser set for mm. Fixing.") ); + setConfigureInchesMode(true); + } + incorrectMeasurementUnits = false;// hope this is ok to do here + positionUpdate(true); + } + else + { + sendGcodeLocal(SETTINGS_COMMAND_V08c); + + if (incorrectLcdDisplayUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl reporting set for inches. Fixing.")); + setConfigureMmMode(false); + } + else + { + emit addList(tr("Options specify use inches but Grbl reporting set for mm. Fixing.")); + setConfigureInchesMode(false); + } + } + incorrectLcdDisplayUnits = false; + } +} + +void GCode::setOldFormatMeasurementUnitControl() +{ + if (controlParams.useMm) + sendGcodeLocal("G21"); + else + sendGcodeLocal("G20"); +} + +void GCode::setConfigureMmMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=0"); + if (setGrblUnits) + sendGcodeLocal("G21"); + positionUpdate(true); +} + +void GCode::setConfigureInchesMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=1"); + if (setGrblUnits) + sendGcodeLocal("G20"); + positionUpdate(true); +} + +void GCode::setUnitsTypeDisplay(bool millimeters) +{ + if (millimeters) + { + emit setUnitsWork(tr("(mm)")); + emit setUnitsMachine(tr("(mm)")); + } + else + { + emit setUnitsWork(tr("(in)")); + emit setUnitsMachine(tr("(in)")); + } +} + +void GCode::clearToHome() +{ + maxZ = 0; + motionOccurred = false; +} + +int GCode:: getNumaxis() +{ + return numaxis; +} + +GCode::PosReqStatus GCode::positionUpdate(bool forceIfEnabled /* = false */) +{ + if (controlParams.usePositionRequest) + { + if (forceIfEnabled) + { + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + int ms = pollPosTimer.elapsed(); + if (ms >= controlParams.postionRequestTimeMilliSec) + { + pollPosTimer.restart(); + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + return POS_REQ_RESULT_TIMER_SKIP; + } + } + } + return POS_REQ_RESULT_UNAVAILABLE; +} + +bool GCode::checkForGetPosStr(QString& line) +{ + return (!line.compare(REQUEST_CURRENT_POS) + || (line.startsWith(REQUEST_CURRENT_POS) && line.endsWith('\r') && line.length() == 2)); +} + +void GCode::setLivenessState(bool valid) +{ + positionValid = valid; + emit setVisualLivenessCurrPos(valid); + emit setLcdState(valid); +} diff --git a/GC-3.6.1-T2/src/gcode.h b/GC-3.6.1-T2/src/gcode.h new file mode 100644 index 0000000..0cf7353 --- /dev/null +++ b/GC-3.6.1-T2/src/gcode.h @@ -0,0 +1,189 @@ +/**************************************************************** + * gcode.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GCODE_H +#define GCODE_H + +#include "log4qtdef.h" + +#include +#include +#include +#include +#include "definitions.h" +#include "rs232.h" +#include "coord3d.h" +#include "controlparams.h" + +#define BUF_SIZE 300 + +#define RESPONSE_OK "ok" +#define RESPONSE_ERROR "error" + +// as defined in the grbl project on github... +#define GRBL_RX_BUFFER_SIZE 128 + +#define CTRL_X '\x18' + +#define DEFAULT_AXIS_COUNT 3 +#define MAX_AXIS_COUNT 4 + +class CmdResponse +{ +public: + CmdResponse(const char *buf, int c, int l) : cmd(buf), count(c), line(l) + { + waitForMe = false; + if (buf[0] == 'M') + { + int value = cmd.mid(1,-1).toInt(); + if (value == 9) + waitForMe = true; + } + } +public: + QString cmd; + int count; + int line; + bool waitForMe; +}; + +class DecimalFilter +{ +public: + DecimalFilter(QString t) : token(t), decimals(0) {} +public: + QString token; + int decimals; +}; + +class GCode : public QObject +{ + Q_OBJECT + +public: + GCode(); + void setAbort(); + void setReset(); + void setShutdown(); + int getSettingsItemCount(); + int getNumaxis(); + + static void trimToEnd(QString& strline, QChar); + +signals: + void addList(QString line); + void addListFull(QStringList list); + void addListOut(QString line); + void sendMsg(QString msg); + void stopSending(); + void portIsClosed(bool reopen); + void portIsOpen(bool sendCode); + void setCommandText(QString value); + void adjustedAxis(); + void gcodeResult(int id, QString result); + void setProgress(int); + void setQueuedCommands(int, bool); + void resetTimer(bool timeIt); + void enableGrblDialogButton(); + void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); + void setLastState(QString state); + void setUnitsWork(QString value); + void setUnitsMachine(QString value); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisCurrLine(int currLine); + void setLcdState(bool valid); + void setVisualLivenessCurrPos(bool isLiveCP); +/// LETARTARE T2 + void setVersionGrbl(QString versionGrbl ); + void setLinesFile(QString); + +public slots: + void openPort(QString commPortStr, QString baudRate); + void closePort(bool reopen); + void sendGcode(QString line); + void sendGcodeAndGetResult(int id, QString line); + void sendFile(QString path); + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void grblSetHome(); + void sendGrblReset(); + void sendGrblUnlock(); + void goToHome(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + enum PosReqStatus + { + POS_REQ_RESULT_OK, + POS_REQ_RESULT_ERROR, + POS_REQ_RESULT_TIMER_SKIP, + POS_REQ_RESULT_UNAVAILABLE + }; +private: + bool sendGcodeLocal(QString line, bool recordResponseOnFail = false, int waitSec = -1, bool aggressive = false, int currLine = 0); + bool waitForOk(QString& result, int waitCount, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize); + bool waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound); + bool sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine = 0); + QString removeUnsupportedCommands(QString line); + QString reducePrecision(QString line); + bool isGCommandValid(float value, bool& toEndOfLine); + bool isMCommandValid(float value); + bool isPortOpen(); + QString getMoveAmountFromString(QString prefix, QString item); + bool SendJog(QString strline, bool absoluteAfterAxisAdj); + void parseCoordinates(const QString& received, bool aggressive); + void pollPosWaitForIdle(bool checkMeasurementUnits); + void checkAndSetCorrectMeasurementUnits(); + void setOldFormatMeasurementUnitControl(); + void setUnitsTypeDisplay(bool millimeters); + void setConfigureMmMode(bool setGrblUnits); + void setConfigureInchesMode(bool setGrblUnits); + QStringList doZRateLimit(QString strline, QString& msg, bool& xyRateSet); + void sendStatusList(QStringList& listToSend); + void clearToHome(); + bool checkGrbl(const QString& result); + PosReqStatus positionUpdate(bool forceIfEnabled = false); + bool checkForGetPosStr(QString& line); + void setLivenessState(bool valid); + +private: + RS232 port; + AtomicIntBool abortState; + AtomicIntBool resetState; + AtomicIntBool shutdownState; + ControlParams controlParams; + int errorCount; + QString currComPort; + bool doubleDollarFormat; + AtomicIntBool settingsItemCount; + QString lastState; + bool incorrectMeasurementUnits; + bool incorrectLcdDisplayUnits; + Coord3D machineCoord, workCoord; + Coord3D machineCoordLastIdlePos, workCoordLastIdlePos; + double maxZ; + QList sendCount; + QTime parseCoordTimer; + bool motionOccurred; + int sliderZCount; + QStringList grblCmdErrors; + QStringList grblFilteredCmds; + QTime pollPosTimer; + bool positionValid; + + int sentI; + int rcvdI; + int numaxis; +}; + +#endif // GCODE_H diff --git a/GC-3.6.1-T2/src/grbl.ico b/GC-3.6.1-T2/src/grbl.ico new file mode 100644 index 0000000..d34802a Binary files /dev/null and b/GC-3.6.1-T2/src/grbl.ico differ diff --git a/GC-3.6.1-T2/src/grbl.rc b/GC-3.6.1-T2/src/grbl.rc new file mode 100644 index 0000000..14ed995 --- /dev/null +++ b/GC-3.6.1-T2/src/grbl.rc @@ -0,0 +1 @@ +IDI_ICON_GRBL ICON DISCARDABLE "grbl.ico" \ No newline at end of file diff --git a/GC-3.6.1-T2/src/grbldialog.cpp b/GC-3.6.1-T2/src/grbldialog.cpp new file mode 100644 index 0000000..da7a5c8 --- /dev/null +++ b/GC-3.6.1-T2/src/grbldialog.cpp @@ -0,0 +1,154 @@ +/**************************************************************** + * grbldialog.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "grbldialog.h" +#include "ui_grbldialog.h" + +GrblDialog::GrblDialog(QWidget *parent, GCode *gc) : + QDialog(parent), + gcode(gc), + ui(new Ui::GrblDialog), + tableRowCount(0) +{ + ui->setupUi(this); + connect(ui->btnCancel,SIGNAL(clicked()),this,SLOT(Cancel())); + connect(ui->btnOk,SIGNAL(clicked()),this,SLOT(Ok())); + connect(this, SIGNAL(sendGcodeAndGetResult(int, QString)), gcode, SLOT(sendGcodeAndGetResult(int, QString))); + connect(gcode, SIGNAL(gcodeResult(int, QString)), this, SLOT(gcodeResult(int, QString))); + + ui->btnCancel->setEnabled(false); + ui->btnOk->setEnabled(false); + + QStringList labels; + labels << tr("Value") << tr("Item"); + ui->table->setHorizontalHeaderLabels(labels); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + ui->table->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); +#else + ui->table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); +#endif + ui->table->verticalHeader()->hide(); + ui->table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + ui->table->setShowGrid(true); +} + +GrblDialog::~GrblDialog() +{ + delete ui; +} + +void GrblDialog::getSettings() +{ + emit sendGcodeAndGetResult(GDLG_CMD_ID_GET, SETTINGS_COMMAND_V08a); +} + +void GrblDialog::gcodeResult(int id, QString result) +{ + switch (id) + { + case GDLG_CMD_ID_GET: + { + originalValues.clear(); + changeFlags.clear(); + + if (result.size() > 0) + { + QRegExp rx(QString("\\$") + REGEXP_SETTINGS_LINE); + int pos = 0; + QStringList fieldValues; + QStringList descriptions; + while ((pos = rx.indexIn(result, pos)) != -1) + { + int matched = rx.matchedLength(); + //QString extracted = received.mid(pos, matched); + pos += matched; + + if (rx.captureCount() > 0) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 4) + { + fieldValues.append(list.at(2)); + descriptions.append(list.at(3)); + } + } + } + + tableRowCount = fieldValues.size(); + ui->table->setRowCount(0); + ui->table->setColumnCount(2); + + int i; + for (i = 0; i < tableRowCount; i++) + { + ui->table->insertRow(i); + ui->table->setItem(i, 0, new QTableWidgetItem(fieldValues.at(i))); + + QTableWidgetItem *descWidget = new QTableWidgetItem(descriptions.at(i)); + descWidget->setFlags(Qt::NoItemFlags); + + ui->table->setItem(i, 1, descWidget); + + ui->table->item(i, 0)->setFont(QFont("Tahoma",10,87,false)); + ui->table->item(i, 1)->setFont(QFont("Tahoma",10,-1,false)); + + originalValues.append(fieldValues.at(i)); + changeFlags.append(false); + } + + ui->table->resizeColumnsToContents(); + int colWidthValues = ui->table->columnWidth(0); + ui->table->setColumnWidth(0, colWidthValues + 10); + + connect(ui->table,SIGNAL(cellChanged(int,int)),this,SLOT(changeValues(int,int))); + } + else + { + ui->table->setRowCount(0); + ui->table->setColumnCount(2); + } + ui->btnCancel->setEnabled(true); + ui->btnOk->setEnabled(true); + break; + } + case GDLG_CMD_ID_SET: + break; + } +} + +void GrblDialog::Cancel() +{ + this->close(); +} + +void GrblDialog::changeValues(int row, int col) +{ + Q_UNUSED(col); + + if ((ui->table->item(row,0)->text() != originalValues.at(row)) + && ui->table->item(row,0)->text().length() > 0) + { + changeFlags.replace(row, true); + } +} + +void GrblDialog::Ok() +{ + for(int i = 0; i < tableRowCount; i++) + { + if (changeFlags.at(i) == true) + { + QString strline = "$"; + strline.append(QString::number(i)).append("=").append(ui->table->item(i,0)->text()).append('\r'); + emit sendGcodeAndGetResult(GDLG_CMD_ID_SET, strline); + } + } + this->close(); +} + diff --git a/GC-3.6.1-T2/src/grbldialog.h b/GC-3.6.1-T2/src/grbldialog.h new file mode 100644 index 0000000..5a194cf --- /dev/null +++ b/GC-3.6.1-T2/src/grbldialog.h @@ -0,0 +1,63 @@ +/**************************************************************** + * grbldialog.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GRBLDIALOG_H +#define GRBLDIALOG_H + +#include +#include +#include +#include +#include +#include "definitions.h" +#include "mainwindow.h" +#include "gcode.h" + +namespace Ui { +class GrblDialog; +} + +#define GDLG_CMD_ID_GET 1 +#define GDLG_CMD_ID_SET 2 + + +class GrblDialog : public QDialog +{ + Q_OBJECT + +public: + explicit GrblDialog(QWidget *parent, GCode *gcode); + ~GrblDialog(); + + //variables + GCode *gcode; + + //methods + void getSettings(); + +signals: + void sendGcodeAndGetResult(int id, QString cmd); + +public slots: + //buttons + void Ok(); + void Cancel(); + //Column Widget + void changeValues(int row, int col); + void gcodeResult(int id, QString result); + +private: + Ui::GrblDialog *ui; + QStringList originalValues; + QList changeFlags; + int tableRowCount; + +}; + +#endif // GRBLDIALOG_H diff --git a/GC-3.6.1-T2/src/grbldialog.ui b/GC-3.6.1-T2/src/grbldialog.ui new file mode 100644 index 0000000..a85b809 --- /dev/null +++ b/GC-3.6.1-T2/src/grbldialog.ui @@ -0,0 +1,96 @@ + + + GrblDialog + + + + 0 + 0 + 440 + 438 + + + + + 0 + 0 + + + + Grbl Settings + + + + + 50 + 390 + 75 + 31 + + + + Apply + + + + + + 280 + 390 + 75 + 31 + + + + Close + + + + + + 10 + 20 + 411 + 351 + + + + + 10 + 0 + + + + Qt::ImhNone + + + 30 + + + true + + + 2 + + + true + + + 40 + + + 40 + + + true + + + 30 + + + + + + + + diff --git a/GC-3.6.1-T2/src/images.rcc b/GC-3.6.1-T2/src/images.rcc new file mode 100644 index 0000000..e5149ba --- /dev/null +++ b/GC-3.6.1-T2/src/images.rcc @@ -0,0 +1,157 @@ +/**************************************************************************** +** Resource object code +** +** Created: Fri 10. Feb 22:39:40 2012 +** by: The Resource Compiler for Qt version 4.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/down.gif + 0x0,0x0,0x0,0xbe, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xc0,0xc0,0xc0,0x99,0x99,0x99,0x40,0x40,0x40,0xe0,0xe0, + 0xe0,0x10,0x10,0x10,0x80,0x80,0x80,0xb0,0xb0,0xb0,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6b, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x95,0x2,0x9c, + 0x68,0xaa,0xae,0xa8,0x72,0x1d,0x6c,0xcc,0x1e,0x18,0x21,0xdf,0x28,0x91,0x15,0xb8, + 0x5c,0x68,0x6,0x58,0x4f,0x75,0x30,0x6c,0x6c,0xc3,0x94,0x8e,0xc3,0x4b,0x2,0x7e, + 0x1d,0x83,0x13,0x60,0xf4,0x20,0x92,0x88,0xd0,0xa2,0xb7,0x10,0x31,0x7a,0x8c,0xd1, + 0x55,0x96,0x25,0x9,0x62,0x2,0x92,0x64,0x10,0x1b,0xa8,0x25,0x8d,0x55,0xe3,0x3d, + 0x39,0xa3,0xd2,0xf4,0x75,0xca,0x9d,0x97,0x4,0x4e,0x1,0x7d,0x14,0x7,0x34,0x82, + 0x13,0x9,0x9,0x86,0x8a,0x8b,0x8c,0x8d,0x8e,0x8c,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/right.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xbb,0x2a,0x86,0x2b,0x4b,0xc0, + 0xe1,0xcc,0x2d,0xa0,0x17,0x31,0x9e,0xea,0xba,0x3,0xc1,0x87,0x2,0x2,0x79,0xc4, + 0x92,0xd1,0x88,0x48,0x8e,0x96,0xc6,0x5,0xc3,0x9,0x5d,0x36,0x89,0xd5,0xe5,0x40, + 0xe0,0xcb,0x42,0x23,0x3d,0x97,0x17,0xba,0x95,0x8d,0xab,0x81,0xb0,0xea,0x5c,0x3d, + 0x24,0x58,0x6c,0xa8,0x1b,0x1e,0x7,0x6,0xc4,0xf5,0x32,0x9e,0x1d,0xc1,0xb1,0xf5, + 0x33,0x67,0xf,0x49,0x5e,0x52,0x54,0x55,0x83,0x4e,0x34,0x4b,0x48,0x8a,0x8b,0x41, + 0x43,0x8e,0x22,0x47,0x6a,0x8e,0x35,0x37,0x92,0x24,0xa,0x99,0x9c,0x9d,0x9e,0x32, + 0x21,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/up.gif + 0x0,0x0,0x0,0xbd, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xbf,0xbf,0xbf,0x99,0x99,0x99,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x80,0x80,0x80,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6a, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x61,0x92,0x90, + 0x99,0x71,0x1c,0x6,0x7a,0x5,0x0,0x10,0xb8,0xd5,0x10,0xc7,0x3,0x2d,0x19,0xc2, + 0xd,0x8,0x2d,0x5a,0xc3,0x17,0x6b,0xd0,0x6c,0x44,0x9c,0xab,0x97,0xfc,0xa1,0x10, + 0xcd,0x1b,0x62,0xc4,0x88,0xfa,0x18,0xa2,0x85,0xf5,0xb6,0x8,0x41,0xb7,0xd2,0x8f, + 0x1,0x4c,0xc,0x72,0xa,0x64,0x5f,0xa1,0x43,0x48,0x13,0x9,0x1b,0x95,0xdb,0xc7, + 0xd2,0xa0,0xe7,0xea,0x4c,0x1b,0xff,0xbe,0xc8,0xf9,0x74,0x66,0x13,0xa,0x80,0x49, + 0xa,0x3a,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x16,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/left.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xeb,0xbe,0x86,0xf2,0xba,0xce, + 0x1,0xcc,0xab,0x51,0x0,0x3c,0x9e,0x12,0x36,0xde,0xcd,0x57,0xd2,0x9,0x85,0x44, + 0x12,0xe2,0x78,0x4c,0x4a,0x18,0xb,0x66,0x93,0xb8,0x94,0x4e,0x67,0x82,0x81,0x95, + 0x39,0x33,0x44,0xb6,0xd2,0x57,0x16,0x1c,0x66,0x19,0x2,0x64,0x2b,0x2b,0x11,0x4c, + 0x73,0x57,0x6c,0x77,0x99,0x85,0x96,0x23,0x5d,0x63,0x3b,0xee,0x2b,0xf7,0xe5,0xc9, + 0x49,0xf,0x69,0x4e,0x50,0x60,0x4e,0x22,0x82,0x6a,0x87,0x12,0x46,0x6f,0x8b,0x12, + 0x40,0x57,0x8f,0x8d,0x43,0x8f,0x23,0x35,0x95,0x96,0x23,0x32,0x9a,0x9d,0x9e,0x49, + 0x21,0x0,0x3b, + +}; + +static const unsigned char qt_resource_name[] = { + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // down.gif + 0x0,0x8, + 0x6,0xe1,0x40,0x96, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // right.gif + 0x0,0x9, + 0xd,0xf7,0xbc,0x16, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // up.gif + 0x0,0x6, + 0x7,0xc3,0x4d,0xf6, + 0x0,0x75, + 0x0,0x70,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // left.gif + 0x0,0x8, + 0xb,0xd7,0x43,0xb6, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/img + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2, + // :/img/down.gif + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/up.gif + 0x0,0x0,0x0,0x3a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xba, + // :/img/left.gif + 0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0x7b, + // :/img/right.gif + 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc2, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources)) + +int QT_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources)) + diff --git a/GC-3.6.1-T2/src/img/Thumbs.db b/GC-3.6.1-T2/src/img/Thumbs.db new file mode 100644 index 0000000..7d8e59e Binary files /dev/null and b/GC-3.6.1-T2/src/img/Thumbs.db differ diff --git a/GC-3.6.1-T2/src/img/down.PNG b/GC-3.6.1-T2/src/img/down.PNG new file mode 100644 index 0000000..f157397 Binary files /dev/null and b/GC-3.6.1-T2/src/img/down.PNG differ diff --git a/GC-3.6.1-T2/src/img/down.gif b/GC-3.6.1-T2/src/img/down.gif new file mode 100644 index 0000000..d55ee1d Binary files /dev/null and b/GC-3.6.1-T2/src/img/down.gif differ diff --git a/GC-3.6.1-T2/src/img/left.PNG b/GC-3.6.1-T2/src/img/left.PNG new file mode 100644 index 0000000..7562000 Binary files /dev/null and b/GC-3.6.1-T2/src/img/left.PNG differ diff --git a/GC-3.6.1-T2/src/img/left.gif b/GC-3.6.1-T2/src/img/left.gif new file mode 100644 index 0000000..9b40ffc Binary files /dev/null and b/GC-3.6.1-T2/src/img/left.gif differ diff --git a/GC-3.6.1-T2/src/img/logotiny.PNG b/GC-3.6.1-T2/src/img/logotiny.PNG new file mode 100644 index 0000000..4cade12 Binary files /dev/null and b/GC-3.6.1-T2/src/img/logotiny.PNG differ diff --git a/GC-3.6.1-T2/src/img/logotiny.gif b/GC-3.6.1-T2/src/img/logotiny.gif new file mode 100644 index 0000000..baf6126 Binary files /dev/null and b/GC-3.6.1-T2/src/img/logotiny.gif differ diff --git a/GC-3.6.1-T2/src/img/right.PNG b/GC-3.6.1-T2/src/img/right.PNG new file mode 100644 index 0000000..858b59f Binary files /dev/null and b/GC-3.6.1-T2/src/img/right.PNG differ diff --git a/GC-3.6.1-T2/src/img/right.gif b/GC-3.6.1-T2/src/img/right.gif new file mode 100644 index 0000000..59dfad3 Binary files /dev/null and b/GC-3.6.1-T2/src/img/right.gif differ diff --git a/GC-3.6.1-T2/src/img/up.PNG b/GC-3.6.1-T2/src/img/up.PNG new file mode 100644 index 0000000..e9b3dbb Binary files /dev/null and b/GC-3.6.1-T2/src/img/up.PNG differ diff --git a/GC-3.6.1-T2/src/img/up.gif b/GC-3.6.1-T2/src/img/up.gif new file mode 100644 index 0000000..b6bf918 Binary files /dev/null and b/GC-3.6.1-T2/src/img/up.gif differ diff --git a/GC-3.6.1-T2/src/img/zapmaker-logo-130.png b/GC-3.6.1-T2/src/img/zapmaker-logo-130.png new file mode 100644 index 0000000..5963823 Binary files /dev/null and b/GC-3.6.1-T2/src/img/zapmaker-logo-130.png differ diff --git a/GC-3.6.1-T2/src/itemtobase.cpp b/GC-3.6.1-T2/src/itemtobase.cpp new file mode 100644 index 0000000..5a9c087 --- /dev/null +++ b/GC-3.6.1-T2/src/itemtobase.cpp @@ -0,0 +1,28 @@ +#include "itemtobase.h" + +ItemToBase::ItemToBase(int index1) + : scale(1), height(100), offsetx(50), offsety(50), index(index1) +{ +} + +ItemToBase::~ItemToBase() +{ +} + +void ItemToBase::setParams(double scale1, double height1, double offsetx1, double offsety1) +{ + scale = scale1; + height = height1; + offsetx = offsetx1; + offsety = offsety1; +} + +double ItemToBase::screenX(double fx) +{ + return (fx * scale) + offsetx; +} + +double ItemToBase::screenY(double fy) +{ + return height - ((fy * scale) + offsety); +} diff --git a/GC-3.6.1-T2/src/itemtobase.h b/GC-3.6.1-T2/src/itemtobase.h new file mode 100644 index 0000000..2ad8f25 --- /dev/null +++ b/GC-3.6.1-T2/src/itemtobase.h @@ -0,0 +1,37 @@ +#ifndef ITEMTOBASE_H +#define ITEMTOBASE_H +#include +#include "stdio.h" +#include "positem.h" + +class ItemToBase +{ +public: + ItemToBase(int index); + virtual ~ItemToBase() ; + + virtual void moveToFirst(QPainterPath& path) = 0; + virtual void addToPath(QPainterPath& path) = 0; + virtual PosItem computeExtents() = 0; + + virtual double getXScr() = 0; + virtual double getYScr() = 0; + virtual double getXRaw() = 0; + virtual double getYRaw() = 0; + + void setParams(double scale, double height, double offsetx, double offsety); + + double screenX(double x); + double screenY(double y); + + int getIndex() { return index; } + +protected: + double scale; + double height; + double offsetx; + double offsety; + int index; +}; + +#endif // ITEMTOBASE_H diff --git a/GC-3.6.1-T2/src/lineitem.cpp b/GC-3.6.1-T2/src/lineitem.cpp new file mode 100644 index 0000000..8bfba6f --- /dev/null +++ b/GC-3.6.1-T2/src/lineitem.cpp @@ -0,0 +1,61 @@ +#include "lineitem.h" + +LineItem::LineItem(double x1, double y1, int index1) + : ItemToBase(index1), x(x1), y(y1) +{ +} + +LineItem::LineItem(double x1, double y1, bool stretchX1, double length1) +: ItemToBase(0), x(x1), y(y1), stretchX(stretchX1), length(length1) +{ +} + +PosItem LineItem::computeExtents() +{ + PosItem curr(x, y, x, y); + return curr; +} + +void LineItem::addToPath(QPainterPath& path) +{ + path.lineTo(screenX(x), screenY(y)); +} + +void LineItem::moveToFirst(QPainterPath& path) +{ + path.moveTo(screenX(x), screenY(y)); +} + +double LineItem::getXScr() +{ + return screenX(x); +} + +double LineItem::getYScr() +{ + return screenY(y); +} + +double LineItem::getXRaw() +{ + return x; +} + +double LineItem::getYRaw() +{ + return y; +} + +void LineItem::drawTo(QPainterPath& path) +{ + if (stretchX) + { + path.moveTo(screenX(x), screenY(y) + length); + path.lineTo(screenX(x), screenY(y) - length); + } + else + { + path.moveTo(screenX(x) + length, screenY(y)); + path.lineTo(screenX(x) - length, screenY(y)); + } +} diff --git a/GC-3.6.1-T2/src/lineitem.h b/GC-3.6.1-T2/src/lineitem.h new file mode 100644 index 0000000..6969e0e --- /dev/null +++ b/GC-3.6.1-T2/src/lineitem.h @@ -0,0 +1,29 @@ +#ifndef LINEITEM_H +#define LINEITEM_H +#include "itemtobase.h" + +class LineItem : public ItemToBase +{ +public: + LineItem(double x1, double y1, int index); + LineItem(double x1, double y1, bool stretchX, double length); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + void drawTo(QPainterPath& path); + + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; + bool stretchX; + double length; +}; + +#endif // LINEITEM_H diff --git a/GC-3.6.1-T2/src/log4qt/appender.h b/GC-3.6.1-T2/src/log4qt/appender.h new file mode 100644 index 0000000..81f6aa4 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/appender.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ********************************************************************************/ + +#ifndef LOG4QT_APPENDER_H +#define LOG4QT_APPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" + +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class LoggingEvent; + + /*! + * \brief The class Appender is the base class for all Appenders. + * + * To allow the whole hirarchy to be an ascendant of QObject Appender is + * not an interface. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Appender : public LogObject + { + Q_OBJECT + + /*! + * The property holds the Layout used by the Appender. + * + * \sa layout(), setLayout() + */ + Q_PROPERTY(Layout* layout READ layout WRITE setLayout) + + /*! + * The property holds the name of the Appender. + * + * \sa name(), setName() + */ + Q_PROPERTY(QString name READ name WRITE setName) + + /*! + * The property holds if the Appender requires a Layout or not. + * + * \sa requiresLayout(), setRequiresLayout() + */ + Q_PROPERTY(bool requiresLayout READ requiresLayout) + + public: + Appender(QObject *pParent = 0); + virtual ~Appender(); + private: + Appender(const Appender &rOther); // Not implemented + Appender &operator=(const Appender &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const = 0; + virtual QString name() const = 0; + virtual Layout *layout() const = 0; + virtual bool requiresLayout() const = 0; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout) = 0; + virtual void setName(const QString &rName) = 0; + + virtual void addFilter(Filter *pFilter) = 0; + virtual void clearFilters() = 0; + virtual void close() = 0; + virtual void doAppend(const LoggingEvent &rEvent) = 0; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender::Appender(QObject *pParent) : + LogObject(pParent) + {} + + inline Appender::~Appender() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Appender, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_APPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/appenderskeleton.cpp b/GC-3.6.1-T2/src/log4qt/appenderskeleton.cpp new file mode 100644 index 0000000..d9f784b --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/appenderskeleton.cpp @@ -0,0 +1,261 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/appenderskeleton.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" +#include "log4qt/spi/filter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + ***************************************************************************/ + + + /*! + * \brief The class RecursionGuardLocker controls a boolean flag. + * + * It is a helper class to control a boolean flag. The class sets the flag + * on creation and resets it on destruction. + */ + class RecursionGuardLocker + { + public: + RecursionGuardLocker(bool *pGuard); + ~RecursionGuardLocker(); + private: + RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented + RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented + private: + bool *mpGuard; + }; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: RecursionGuardLocker + ***************************************************************************/ + + + inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard) + { + Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null"); + + mpGuard = pGuard; + *mpGuard = true; + } + + + inline RecursionGuardLocker::~RecursionGuardLocker() + { + *mpGuard = false; + }; + + + + /************************************************************************** + * Class implementation: AppenderSkeleton + **************************************************************************/ + + + AppenderSkeleton::AppenderSkeleton(QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(true), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + AppenderSkeleton::AppenderSkeleton(const bool isActive, + QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(isActive), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + void AppenderSkeleton::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"), + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return; + } + mIsActive = true; + } + + + void AppenderSkeleton::addFilter(Filter *pFilter) + { + if(!pFilter) + { + logger()->warn("Adding null Filter to Appender '%1'", name()); + return; + } + + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = pFilter; + if (mpHeadFilter) + mpHeadFilter->setNext(pFilter); + else + mpHeadFilter = pFilter; + } + + + void AppenderSkeleton::clearFilters() + { + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = 0; + mpHeadFilter = 0; + } + + + void AppenderSkeleton::close() + { + QMutexLocker locker(&mObjectGuard); + + mIsClosed = true; + mIsActive = false; + } + + + void AppenderSkeleton::doAppend(const LoggingEvent &rEvent) + { + // The mutex serialises concurrent access from multiple threads. + // - e.g. two threads using the same logger + // - e.g. two threads using different logger with the same appender + // + // A call from the same thread will pass the mutex (QMutex::Recursive) + // and get to the recursion guard. The recursion guard blocks recursive + // invocation and prevents a possible endless loop. + // - e.g. an appender logs an error with a logger that uses it + + QMutexLocker locker(&mObjectGuard); + + if (mAppendRecursionGuard) + return; + + RecursionGuardLocker recursion_locker(&mAppendRecursionGuard); + + if (!checkEntryConditions()) + return; + if (!isAsSevereAsThreshold(rEvent.level())) + return; + + Filter *p_filter = mpHeadFilter; + while(p_filter) + { + Filter::Decision decision = p_filter->decide(rEvent); + if (decision == Filter::ACCEPT) + break; + else if (decision == Filter::DENY) + return; + else + p_filter = p_filter->next(); + } + + append(rEvent); + } + + + bool AppenderSkeleton::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!isActive()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"), + APPENDER_NOT_ACTIVATED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (isClosed()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"), + APPENDER_CLOSED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"), + APPENDER_USE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/appenderskeleton.h b/GC-3.6.1-T2/src/log4qt/appenderskeleton.h new file mode 100644 index 0000000..6f252b3 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/appenderskeleton.h @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_APPENDERSKELETON_H +#define LOG4QT_APPENDERSKELETON_H + + +/****************************************************************************** + * Dependencies +******************************************************************************/ + +#include "log4qt/appender.h" + +#include +#include "log4qt/helpers/logobjectptr.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class Logger; + class LoggingEvent; + + /*! + * \brief The class AppenderSkeleton implements general Appender functionality. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class AppenderSkeleton : public Appender + { + Q_OBJECT + + /*! + * The property holds if the Appender has been activated. + * + * \sa isActive() + */ + Q_PROPERTY(bool isActive READ isActive) + + /*! + * The property holds if the Appender has been closed. + * + * \sa isClosed() + */ + Q_PROPERTY(bool isClosed READ isClosed) + + /*! + * The property holds the threshold level used by the Appender. + * + * \sa threshold(), setThreshold() + */ + Q_PROPERTY(Level threshold READ threshold WRITE setThreshold) + + public: + AppenderSkeleton(QObject *pParent = 0); + protected: + AppenderSkeleton(const bool isActive, + QObject *pParent = 0); + public: + // virtual ~AppenderSkeleton(); Use compiler default + private: + AppenderSkeleton(const AppenderSkeleton &rOther); // Not implemented + AppenderSkeleton &operator=(const AppenderSkeleton &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const; + virtual Layout *layout() const; + bool isActive() const; + bool isClosed() const; + virtual QString name() const; + Level threshold() const; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout); + virtual void setName(const QString &rName); + void setThreshold(Level level); + + virtual void activateOptions(); + virtual void addFilter(Filter *pFilter); + virtual void clearFilters(); + virtual void close(); + + /*! + * Performs checks and delegates the actuall appending to the subclass + * specific append() function. + * + * \sa append(), checkEntryConditions(), isAsSevereAsThreshold(), Filter + */ + virtual void doAppend(const LoggingEvent &rEvent); + + // JAVA: void finalize(); + Filter* firstFilter() const; + bool isAsSevereAsThreshold(Level level) const; + + protected: + virtual void append(const LoggingEvent &rEvent) = 0; + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. + * + * The checked conditions are: + * - That the appender has been activated (APPENDER_NOT_ACTIVATED_ERROR) + * - That the appender was not closed (APPENDER_CLOSED_ERROR) + * - That the appender has a layout set, if it requires one + * (logging_error(APPENDER_USE_MISSING_LAYOUT_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by doAppend(). The doAppend() function calls the subclass + * specific checkEntryConditions() function. The function checks the + * class specific conditions and calls checkEntryConditions() of + * it's parent class. The last function called is + * AppenderSkeleton::checkEntryConditions(). + * + * \sa doAppend() + */ + virtual bool checkEntryConditions() const; + + protected: + mutable QMutex mObjectGuard; + private: + bool mAppendRecursionGuard; + volatile bool mIsActive; + volatile bool mIsClosed; + LogObjectPtr mpLayout; + Level mThreshold; + LogObjectPtr mpHeadFilter; + LogObjectPtr mpTailFilter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter *AppenderSkeleton::filter() const + { QMutexLocker locker(&mObjectGuard); + return mpHeadFilter; } + + inline Layout *AppenderSkeleton::layout() const + { QMutexLocker locker(&mObjectGuard); + return mpLayout; } + + inline QString AppenderSkeleton::name() const + { QMutexLocker locker(&mObjectGuard); + return objectName(); } + + inline Level AppenderSkeleton::threshold() const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void AppenderSkeleton::setLayout(Layout *pLayout) + { QMutexLocker locker(&mObjectGuard); + mpLayout = pLayout; } + + inline void AppenderSkeleton::setName(const QString &rName) + { QMutexLocker locker(&mObjectGuard); + setObjectName(rName); } + + inline void AppenderSkeleton::setThreshold(Level level) + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool AppenderSkeleton::isActive() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsActive; } + + inline bool AppenderSkeleton::isClosed() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsClosed; } + + inline Filter *AppenderSkeleton::firstFilter() const + { QMutexLocker locker(&mObjectGuard); + return filter(); } + + inline bool AppenderSkeleton::isAsSevereAsThreshold(Level level) const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return (mThreshold <= level); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::AppenderSkeleton, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_APPENDERSKELETON_H diff --git a/GC-3.6.1-T2/src/log4qt/basicconfigurator.cpp b/GC-3.6.1-T2/src/log4qt/basicconfigurator.cpp new file mode 100644 index 0000000..280b88d --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/basicconfigurator.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/basicconfigurator.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/logmanager.h" +#include "log4qt/patternlayout.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: BasicConfigurator + **************************************************************************/ + + + bool BasicConfigurator::configure() + { + LogObjectPtr list = new ListAppender; + list->setName(QLatin1String("BasicConfigurator")); + list->setConfiguratorList(true); + list->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(list); + + PatternLayout *p_layout = new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout->setName(QLatin1String("BasicConfigurator TTCC")); + p_layout->activateOptions(); + ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("BasicConfigurator stdout")); + p_appender->activateOptions(); + LogManager::rootLogger()->addAppender(p_appender); + + LogManager::logLogger()->removeAppender(list); + ConfiguratorHelper::setConfigureError(list->list()); + return (list->list().count() == 0); + } + + + void BasicConfigurator::configure(Appender *pAppender) + { + LogManager::rootLogger()->addAppender(pAppender); + } + + + void BasicConfigurator::resetConfiguration() + { + LogManager::resetConfiguration(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/basicconfigurator.h b/GC-3.6.1-T2/src/log4qt/basicconfigurator.h new file mode 100644 index 0000000..c301501 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/basicconfigurator.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_BASICCONFIGURATOR_H +#define LOG4QT_BASICCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Appender; + + /*! + * \brief The class BasicConfigurator provides a simple package + * configuration. + * + * \note All the functions declared in this class are thread-safe. + */ + class BasicConfigurator + { + private: + BasicConfigurator(); // Not implemented + // BasicConfigurator(const BasicConfigurator &rOther); // Use compiler default + // virtual ~BasicConfigurator(); // Use compiler default + // BasicConfigurator &operator=(const BasicConfigurator &rOther); // Use compiler default + + public: + static bool configure(); + static void configure(Appender *pAppender); + static void resetConfiguration(); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namspace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::BasicConfigurator, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_BASICCONFIGURATOR_H diff --git a/GC-3.6.1-T2/src/log4qt/consoleappender.cpp b/GC-3.6.1-T2/src/log4qt/consoleappender.cpp new file mode 100644 index 0000000..1b4fe03 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/consoleappender.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/consoleappender.h" + +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConsoleAppender + **************************************************************************/ + + + ConsoleAppender::ConsoleAppender(QObject *pParent) : + WriterAppender(pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + setTarget(rTarget); + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(target), + mpTextStream(0) + { + } + + + ConsoleAppender::~ConsoleAppender() + { + close(); + } + + + QString ConsoleAppender::target() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + if (mTarget == STDOUT_TARGET) + return QLatin1String("STDOUT_TARGET"); + else + return QLatin1String("STDERR_TARGET"); + } + + + void ConsoleAppender::setTarget(const QString &rTarget) + { + bool ok; + Target target = (Target)OptionConverter::toTarget(rTarget, &ok); + if (ok) + setTarget(target); + } + + + void ConsoleAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + closeStream(); + + if (mTarget == STDOUT_TARGET) + mpTextStream = new QTextStream(stdout); + else + mpTextStream = new QTextStream(stderr); + setWriter(mpTextStream); + + WriterAppender::activateOptions(); + } + + + void ConsoleAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeStream(); + } + + + void ConsoleAppender::closeStream() + { + // Q_ASSERT_X(, "ConsoleAppender::closeStream()", "Lock must be held by caller") + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ConsoleAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString target; + if (mTarget == STDOUT_TARGET) + target = QLatin1String("STDOUT"); + else + target = QLatin1String("STDERR"); + + rDebug.nospace() << "ConsoleAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "target:" << target << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/consoleappender.h b/GC-3.6.1-T2/src/log4qt/consoleappender.h new file mode 100644 index 0000000..466015d --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/consoleappender.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CONSOLEAPPENDER_H +#define LOG4QT_CONSOLEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class ConsoleAppender appends to stdout or stderr. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ConsoleAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds the target used by the appender. + * + * The default is STDOUT_TARGET for the standard output. + * + * \sa Target, target(), setTarget() + */ + Q_PROPERTY(QString target READ target WRITE setTarget) + + public: + /*! + * The enum defines the possible output targets + * + * \sa target(), setTarget() + */ + enum Target { + /*! The output target is standard out. */ + STDOUT_TARGET, + /*! The output target is standard error. */ + STDERR_TARGET + }; + Q_ENUMS(Target) + + ConsoleAppender(QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent = 0); + + /*! + * Creates a ConsoleAppender with the layout \a pLayout, the target + * value specified by the \a target constant and the parent + * \a pParent. + */ + ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent = 0); + + virtual ~ConsoleAppender(); + private: + ConsoleAppender(const ConsoleAppender &rOther); // Not implemented + ConsoleAppender &operator=(const ConsoleAppender &rOther); // Not implemented + + public: + // JAVA: bool follow() const; + QString target() const; + // JAVA: void setFollow(bool follow); + void setTarget(const QString &rTarget); + + /*! + * Sets the target to the value specified by the \a target constant. + */ + void setTarget(Target target); + + virtual void activateOptions(); + virtual void close(); + + protected: + void closeStream(); + + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ConsoleAppender(name:"CA" filter:0x0 isactive:true isclosed:false + * layout:"PL" target:"STDERR" referenceCount:1 + * threshold:"WARN_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + #endif // QT_NO_DEBUG_STREAM + + private: + volatile Target mTarget; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline void ConsoleAppender::setTarget(Target target) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mTarget = target; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConsoleAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CONSOLEAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.cpp b/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.cpp new file mode 100644 index 0000000..0590f16 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.cpp @@ -0,0 +1,352 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/dailyrollingfileappender.h" + +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DailyRollingFileAppender + **************************************************************************/ + + + DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mDatePattern() + { + setDatePattern(DAILY_ROLLOVER); + } + + + DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mDatePattern() + { + setDatePattern(rDatePattern); + } + + + DailyRollingFileAppender::~DailyRollingFileAppender() + { + close(); + } + + + void DailyRollingFileAppender::setDatePattern(DatePattern datePattern) + { + switch (datePattern) + { + case MINUTELY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm")); + break; + case HOURLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh")); + break; + case HALFDAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-a")); + break; + case DAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd")); + break; + case WEEKLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-ww")); + break; + case MONTHLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM")); + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant"); + setDatePattern(DAILY_ROLLOVER); + }; + } + + + void DailyRollingFileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + computeFrequency(); + if (!mActiveDatePattern.isEmpty()) + { + computeRollOverTime(); + FileAppender::activateOptions(); + } + } + + + void DailyRollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller") + + if (QDateTime::currentDateTime() > mRollOverTime) + rollOver(); + FileAppender::append(rEvent); + } + + + bool DailyRollingFileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (mActiveDatePattern.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"), + APPENDER_USE_INVALID_PATTERN_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return FileAppender::checkEntryConditions(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "DailyRollingFileAppender(" + << "name:" << name() << " " + << "activedatepattern:" << mActiveDatePattern << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "datepattern:" << datePattern() << " " + << "encoding:" << codec_name << " " + << "frequency:" << frequencyToString() << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "rollovertime:" << mRollOverTime + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void DailyRollingFileAppender::computeFrequency() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller") + + const DateTime start_time(QDate(1999, 1, 1), QTime(0, 0)); + const QString start_string = start_time.toString(mDatePattern); + mActiveDatePattern.clear(); + + if (start_string != static_cast(start_time.addSecs(60)).toString(mDatePattern)) + mFrequency = MINUTELY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60)).toString(mDatePattern)) + mFrequency = HOURLY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60 * 12)).toString(mDatePattern)) + mFrequency = HALFDAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(1)).toString(mDatePattern)) + mFrequency = DAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(7)).toString(mDatePattern)) + mFrequency = WEEKLY_ROLLOVER; + else if (start_string != static_cast(start_time.addMonths(1)).toString(mDatePattern)) + mFrequency = MONTHLY_ROLLOVER; + else + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"), + APPENDER_INVALID_PATTERN_ERROR); + e << mDatePattern << name(); + logger()->error(e); + return; + } + + mActiveDatePattern = mDatePattern; + logger()->trace("Frequency set to %2 using date pattern %1", + mActiveDatePattern, + frequencyToString()); + } + + + void DailyRollingFileAppender::computeRollOverTime() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern"); + + QDateTime now = QDateTime::currentDateTime(); + QDate now_date = now.date(); + QTime now_time = now.time(); + QDateTime start; + + switch (mFrequency) + { + case MINUTELY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + now_time.minute(), + 0, 0)); + mRollOverTime = start.addSecs(60); + } + break; + case HOURLY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + 0, 0, 0)); + mRollOverTime = start.addSecs(60*60); + } + break; + case HALFDAILY_ROLLOVER: + { + int hour = now_time.hour(); + if (hour >= 12) + hour = 12; + else + hour = 0; + start = QDateTime(now_date, + QTime(hour, 0, 0, 0)); + mRollOverTime = start.addSecs(60*60*12); + } + break; + case DAILY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(0, 0, 0, 0)); + mRollOverTime = start.addDays(1); + } + break; + case WEEKLY_ROLLOVER: + { + // QT numbers the week days 1..7. The week starts on Monday. + // Change it to being numbered 0..6, starting with Sunday. + int day = now_date.dayOfWeek(); + if (day == Qt::Sunday) + day = 0; + start = QDateTime(now_date, + QTime(0, 0, 0, 0)).addDays(-1 * day); + mRollOverTime = start.addDays(7); + } + break; + case MONTHLY_ROLLOVER: + { + start = QDateTime(QDate(now_date.year(), + now_date.month(), + 1), + QTime(0, 0, 0, 0)); + mRollOverTime = start.addMonths(1); + } + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant"); + mRollOverTime = QDateTime::fromTime_t(0); + } + + mRollOverSuffix = static_cast(start).toString(mActiveDatePattern); + Q_ASSERT_X(static_cast(now).toString(mActiveDatePattern) == mRollOverSuffix, + "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval"); + Q_ASSERT_X(mRollOverSuffix != static_cast(mRollOverTime).toString(mActiveDatePattern), + "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover"); + + logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3", + now, + start, + mRollOverTime); + } + + + QString DailyRollingFileAppender::frequencyToString() const + { + QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern")); + return QLatin1String(meta_enum.valueToKey(mFrequency)); + } + + + void DailyRollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern"); + + QString roll_over_suffix = mRollOverSuffix; + computeRollOverTime(); + if (roll_over_suffix == mRollOverSuffix) + return; + + closeFile(); + + QString target_file_name = file() + roll_over_suffix; + QFile f(target_file_name); + if (f.exists() && !removeFile(f)) + return; + f.setFileName(file()); + if (!renameFile(f, target_file_name)) + return; + openFile(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.h b/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.h new file mode 100644 index 0000000..e3fe638 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/dailyrollingfileappender.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DAILYROLLINGFILEAPPENDER_H +#define LOG4QT_DAILYROLLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DailyRollingFileAppender extends FileAppender so that the + * underlying file is rolled over at a specified frequency. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class DailyRollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the date pattern used by the appender. + * + * The default is DAILY_ROLLOVER for rollover at midnight each day. + * + * \sa datePattern(), setDatePattern() + */ + Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern) + + public: + /*! + * The enum DatePattern defines constants for date patterns. + * + * \sa setDatePattern(DatePattern) + */ + enum DatePattern + { + /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */ + MINUTELY_ROLLOVER = 0, + /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */ + HOURLY_ROLLOVER, + /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */ + HALFDAILY_ROLLOVER, + /*! The daily date pattern string is "'.'yyyy-MM-dd". */ + DAILY_ROLLOVER, + /*! The weekly date pattern string is "'.'yyyy-ww". */ + WEEKLY_ROLLOVER, + /*! The monthly date pattern string is "'.'yyyy-MM". */ + MONTHLY_ROLLOVER + }; + Q_ENUMS(DatePattern) + + DailyRollingFileAppender(QObject *pParent = 0); + DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent = 0); + virtual ~DailyRollingFileAppender(); + private: + DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented + DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented + + public: + QString datePattern() const; + + /*! + * Sets the datePattern to the value specified by the \a datePattern + * constant. + */ + void setDatePattern(DatePattern datePattern); + + void setDatePattern(const QString &rDatePattern); + + virtual void activateOptions(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * FileAppender::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm" + * appendfile:false bufferedio:true + * datepattern:"'.'yyyy-MM-dd-hh-mm" + * encoding:"" frequency:"MINUTELY_ROLLOVER" + * file:"/log.txt" filter:0x0 immediateflush:true + * isactive:true isclosed:false layout:"TTCC" + * referencecount:1 + * rollovertime:QDateTime("Mon Oct 22 05:23:00 2007") + * threshold: "NULL" writer: 0x0 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void computeFrequency(); + void computeRollOverTime(); + QString frequencyToString() const; + void rollOver(); + + private: + QString mDatePattern; + DatePattern mFrequency; + QString mActiveDatePattern; + QDateTime mRollOverTime; + QString mRollOverSuffix; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString DailyRollingFileAppender::datePattern() const + { QMutexLocker locker(&mObjectGuard); + return mDatePattern; } + + inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern) + { QMutexLocker locker(&mObjectGuard); + mDatePattern = rDatePattern; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DailyRollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DAILYROLLINGFILEAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/fileappender.cpp b/GC-3.6.1-T2/src/log4qt/fileappender.cpp new file mode 100644 index 0000000..265634f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/fileappender.cpp @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/fileappender.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: FileAppender + **************************************************************************/ + + + FileAppender::FileAppender(QObject *pParent) : + WriterAppender(pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(buffered), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::~FileAppender() + { + close(); + } + + + void FileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (mFileName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"), + APPENDER_ACTIVATE_MISSING_FILE_ERROR); + e << name(); + logger()->error(e); + return; + } + closeFile(); + openFile(); + WriterAppender::activateOptions(); + } + + + void FileAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeFile(); + } + + + bool FileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!mpFile || !mpTextStream) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"), + APPENDER_NO_OPEN_FILE_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return WriterAppender::checkEntryConditions(); + } + + + void FileAppender::closeFile() + { + // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller") + + if (mpFile) + logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name()); + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + delete mpFile; + mpFile = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug FileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "FileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool FileAppender::handleIoErrors() const + { + // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller") + + if (mpFile->error() == QFile::NoError) + return false; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"), + APPENDER_WRITING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return true; + } + + + void FileAppender::openFile() + { + Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file"); + + QFileInfo file_info(mFileName); + QDir parent_dir = file_info.dir(); + if (!parent_dir.exists()) + { + logger()->trace("Creating missing parent directory for file %1", mFileName); + QString name = parent_dir.dirName(); + parent_dir.cdUp(); + parent_dir.mkdir(name); + } + + + mpFile = new QFile(mFileName); + QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text; + if (mAppendFile) + mode |= QIODevice::Append; + else + mode |= QIODevice::Truncate; + if (!mBufferedIo) + mode |= QIODevice::Unbuffered; + if (!mpFile->open(mode)) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + APPENDER_OPENING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return; + } + mpTextStream = new QTextStream(mpFile); + setWriter(mpTextStream); + logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name()); + } + + + bool FileAppender::removeFile(QFile &rFile) const + { + if (rFile.remove()) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"), + APPENDER_REMOVE_FILE_ERROR); + e << rFile.fileName() << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + bool FileAppender::renameFile(QFile &rFile, + const QString &rFileName) const + { + logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName); + if (rFile.rename(rFileName)) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"), + APPENDER_RENAMING_FILE_ERROR); + e << rFile.fileName() << rFileName << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/fileappender.h b/GC-3.6.1-T2/src/log4qt/fileappender.h new file mode 100644 index 0000000..2479d4e --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/fileappender.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILEAPPENDER_H +#define LOG4QT_FILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class FileAppender appends log events to a file. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class FileAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds, if the output is appended to the file. + * + * The default is false for not appending. + * + * \sa appendFile(), setAppendFile() + */ + Q_PROPERTY(bool appendFile READ appendFile WRITE setAppendFile) + + /*! + * The property holds, if the output is buffered. + * + * The default is true for buffering. + * + * \sa bufferedIo(), setBufferedIo() + */ + Q_PROPERTY(bool bufferedIo READ bufferedIo WRITE setBufferedIo) + + /*! + * The property holds the name of the file. + * + * \sa file(), setFile() + */ + Q_PROPERTY(QString file READ file WRITE setFile) + + public: + FileAppender(QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent = 0); + virtual ~FileAppender(); + private: + FileAppender(const FileAppender &rOther); // Not implemented + FileAppender &operator=(const FileAppender &rOther); // Not implemented + + public: + bool appendFile() const; + QString file() const; + bool bufferedIo() const; + // JAVA: int bufferSize() const; + void setAppendFile(bool append); + void setBufferedIo(bool buffered); + // JAVA: void setBufferSize(int bufferSize); + void setFile(const QString &rFileName); + + virtual void activateOptions(); + virtual void close(); + + protected: + /*! + * Tests if all entry conditions for using append() in this class are met. + * + * If a conditions is not met, an error is logged and the function returns + * false. Otherwise the result of WriterAppender::checkEntryConditions() + * is returned. + * + * The checked conditions are: + * - That a file is set and open (APPENDER_NO_OPEN_FILE_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeFile(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %FileAppender(name:"FA" appendfile:false bufferedio:true encoding:"" + * file:"/log.txt" filter: 0x0 immediateflush:true isactive:false + * isclosed:false layout:"TTCC" referencecount:2 + * threshold:"NULL" writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Checks for file I/O errrors. If an error is found it is logged and the + * function returns true. Otherwise false is returned. + */ + virtual bool handleIoErrors() const; + + /*! + * Opens the file for the appender based on the specified file name and + * mode. A text stream is created and passed on to the super class + * WriterAppender. + * + * If the parent directory of the specified file does not exists, + * it is created. + */ + void openFile(); + + /*! + * Removes the file \a rFile. If the operation is successful, true is + * returned. Otherwise an APPENDER_REMOVE_FILE_ERROR error is logged + * and false is returned. + */ + bool removeFile(QFile &rFile) const; + + /*! + * Renames the file \a rFile to \a rFileName. If the operation is + * successful, true is returned. Otherwise an + * APPENDER_RENAMING_FILE_ERROR error is logged and false is returned. + */ + bool renameFile(QFile &rFile, + const QString &rFileName) const; + + // JAVA: void setQWForFiles(Writer writer); + + private: + volatile bool mAppendFile; + volatile bool mBufferedIo; + QString mFileName; + QFile *mpFile; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool FileAppender::appendFile() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAppendFile; } + + inline QString FileAppender::file() const + { QMutexLocker locker(&mObjectGuard); + return mFileName; } + + inline bool FileAppender::bufferedIo() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mBufferedIo; } + + inline void FileAppender::setAppendFile(bool append) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mAppendFile = append; } + + inline void FileAppender::setBufferedIo(bool buffered) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mBufferedIo = buffered; } + + inline void FileAppender::setFile(const QString &rFileName) + { QMutexLocker locker(&mObjectGuard); + mFileName = rFileName; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::FileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_FILEAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/classlogger.cpp b/GC-3.6.1-T2/src/log4qt/helpers/classlogger.cpp new file mode 100644 index 0000000..50b6c7f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/classlogger.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/classlogger.h" + +#include +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ClassLogger + **************************************************************************/ + + + ClassLogger::ClassLogger() : + mpLogger(0) + { + } + + + Logger *ClassLogger::logger(const QObject *pObject) + { + Q_ASSERT_X(pObject, "ClassLogger::logger()", "pObject must not be null"); +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + if (!mpLogger) + q_atomic_test_and_set_ptr(&mpLogger, + 0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(mpLogger); +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + if (!static_cast(mpLogger)) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger)); +#else + if (!static_cast(mpLogger.loadAcquire())) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger.loadAcquire())); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/classlogger.h b/GC-3.6.1-T2/src/log4qt/helpers/classlogger.h new file mode 100644 index 0000000..065a852 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/classlogger.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CLASSLOGGER_H +#define LOG4QT_CLASSLOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The class Log4Qt::ClassLogger is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Logger; + + /*! + * \brief The class ClassLogger provides logging for a QObject derived + * class. + * + * The class ClassLogger provides a logger for a specified QObject derived + * object. It is used by \ref LOG4QT_DECLARE_QCLASS_LOGGER to implement the + * member functions provided by the macro. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa LOG4QT_DECLARE_QCLASS_LOGGER + */ + class ClassLogger + { + public: + /*! + * Creates a ClassLogger object. + */ + ClassLogger(); + // ~ClassLogger(); // Use compiler default + // ClassLogger(const ClassLogger &rOther); // Use compiler default + // ClassLogger &operator=(const ClassLogger &rOther); // Use compiler default + + /*! + * Returns a pointer to a Logger named after the class of the object + * \a pObject. + * + * On the first invocation the Logger is requested by a call to + * LogManager::logger(const char *pName). The pointer is stored to be + * returned on subsequent invocations. + * + * \sa LogManager::logger(const char *pName) + */ + Logger *logger(const QObject *pObject); + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile Logger *mpLogger; +#else + mutable QAtomicPointer mpLogger; +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::ClassLogger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CLASSLOGGER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.cpp b/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.cpp new file mode 100644 index 0000000..3b34f40 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/configuratorhelper.h" + +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConfiguratorHelper + **************************************************************************/ + + + ConfiguratorHelper::ConfiguratorHelper() : + mObjectGuard(), + mConfigurationFile(), + mpConfigureFunc(0), + mpConfigurationFileWatch(0), + mConfigureError() + { + } + + + ConfiguratorHelper::~ConfiguratorHelper() + { + delete mpConfigurationFileWatch; + } + + + LOG4QT_IMPLEMENT_INSTANCE(ConfiguratorHelper) + + + void ConfiguratorHelper::doConfigurationFileChanged(const QString &rFileName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mpConfigureFunc) + return; + mpConfigureFunc(rFileName); + // Shall we hold the lock while emitting the signal? + emit configurationFileChanged(rFileName, mConfigureError.count() > 0); + } + + + + void ConfiguratorHelper::doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { + QMutexLocker locker(&mObjectGuard); + + mConfigurationFile.clear(); + mpConfigureFunc = 0; + delete mpConfigurationFileWatch; + if (rFileName.isEmpty()) + return; + + mConfigurationFile = rFileName; + mpConfigureFunc = pConfigureFunc; + mpConfigurationFileWatch = new QFileSystemWatcher(); + mpConfigurationFileWatch->addPath(rFileName); + connect(mpConfigurationFileWatch, + SIGNAL(fileChanged(const QString &)), + SLOT(configurationFileChanged(const QString &))); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper) + { + debug.nospace() << "ConfiguratorHelper(" + << "configurationfile:" << ConfiguratorHelper::configurationFile() + << "configurefunc:" << rConfiguratorHelper.mpConfigureFunc + << "filesystemwatcher:" << rConfiguratorHelper.mpConfigurationFileWatch + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.h b/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.h new file mode 100644 index 0000000..765f86a --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/configuratorhelper.h @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_CONFIGURATORHELPER_H +#define LOG4QT_HELPERS_CONFIGURATORHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFileSystemWatcher; + + +namespace Log4Qt +{ + + /*! + * \brief The class ConfiguratorHelper provides a confiuration file watch + * and last error for configurator classes. + * + * A configuration file can be set using setConfigurationFile(). The file + * is watched for changes. If a change occurs the configuration is reloaded + * and the ConfigurationFileChanged() signal is emitted. Error information + * for the last call to a configure function or the last configuration file + * change can be accessed using configureError(). + * + * \note All the functions declared in this class are thread-safe. + */ + class ConfiguratorHelper : public QObject + { + Q_OBJECT + + public: + /*! + * Prototype for a configure callback function. The function is called + * when then configuration file is changed and takes the + * configuration file as a parameter. + * + * \sa setConfigurationFile(), + * PropertyConfigurator::configure(const QString &) + */ + typedef bool (*ConfigureFunc)(const QString &rFileName); + + private: + ConfiguratorHelper(); + ConfiguratorHelper(const ConfiguratorHelper &rOther); // Not implemented + virtual ~ConfiguratorHelper(); + ConfiguratorHelper &operator=(const ConfiguratorHelper &rOther); // Not implemented + + public: + + /*! + * Returns the error information for the last configuration operation + * that took place. The configuration operation could be the result of + * a call to one of the configure methods or through a change + * to the configuration file. + * + * \sa setConfigureError(), PropertyConfigurator::configure(), + * setConfigurationFile() + */ + static QList configureError(); + + /*! + * Returns the current configuration file. + * + * \sa setConfigurationFile() + */ + static QString configurationFile(); + + /*! + * Returns the ConfiguratorHelper instance. + */ + static ConfiguratorHelper *instance(); + + /*! + * Sets the configuration error information for the last configuration + * operation. + * + * \sa configureError() + */ + static void setConfigureError(const QList &rConfigureError); + + /*! + * Sets the configuration file to \a rFileName. The file is watched for + * changes. On a file change the function \a pConfigureFunc will be called + * and the signal configurationFileChange() will be emitted. + * + * Setting the configuration file to an empty string stops the file watch. + * + * \sa configurationFile(), PropertyConfigurator::configureAndWatch(), + * configureError() + */ + static void setConfigurationFile(const QString &rFileName = QString(), + ConfigureFunc pConfigureFunc = 0); + + signals: + /*! + * The signal is emitted after a change to the file \a rFileName + * was processed. If an error occured during the configuration, the + * flag \a error will be true and error information is available + * over configureError(). + */ + void configurationFileChanged(const QString &rFileName, + bool error); + + private slots: + void doConfigurationFileChanged(const QString &rFileName); + + private: + void doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc); + + private: + mutable QMutex mObjectGuard; + QString mConfigurationFile; + ConfigureFunc mpConfigureFunc; + QFileSystemWatcher *mpConfigurationFileWatch; + QList mConfigureError; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates ConfiguratorHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %ConfiguratorHelper(configurationfile: "" configurefunc: false + * filesystemwatcher: QObject(0x0) ) + * + * \sa QDebug, ConfiguratorHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QList ConfiguratorHelper::configureError() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigureError; } + + inline QString ConfiguratorHelper::configurationFile() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigurationFile; } + + inline void ConfiguratorHelper::setConfigureError(const QList &rConfigureError) + { QMutexLocker locker(&instance()->mObjectGuard); + instance()->mConfigureError = rConfigureError; } + + inline void ConfiguratorHelper::setConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { instance()->doSetConfigurationFile(rFileName, pConfigureFunc); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConfiguratorHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_CONFIGURATORHELPER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/datetime.cpp b/GC-3.6.1-T2/src/log4qt/helpers/datetime.cpp new file mode 100644 index 0000000..6da69a2 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/datetime.cpp @@ -0,0 +1,326 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/datetime.h" + +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DateTime + **************************************************************************/ + + + QString DateTime::toString(const QString &rFormat) const + { + QString format(rFormat); + + if (format.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + if (format == QLatin1String("NONE")) + return QString(); + + if (format == QLatin1String("RELATIVE")) + return QString::number(toMilliSeconds() - InitialisationHelper::startTime()); + + if (format == QLatin1String("ISO8601")) + format = QLatin1String("yyyy-MM-dd hh:mm:ss.zzz"); + if (format == QLatin1String("ABSOLUTE")) + format = QLatin1String("HH:mm:ss.zzz"); + if (format == QLatin1String("DATE")) + format = QLatin1String("dd MMM YYYY HH:mm:ss.zzzz"); + + return formatDateTime(format); + } + + + QString DateTime::formatDateTime(const QString &rFormat) const + { + if (rFormat.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + + const QLatin1Char null('0'); + const QLatin1Char quote('\''); + const QString tokens = QLatin1String("\'dMyhHmszAPapw"); + const bool am_pm = hasAMPM(rFormat); + + QString result; + QString token; + QChar expected = null; + + QChar c; + int i; + for (i = 0; i < rFormat.length(); i++) + { + c = rFormat.at(i); + + // Handle literal text + if (expected == quote) + { + if (c == quote) + { + Q_ASSERT_X(i > 0, "DateTime::toString()", "Found quote with status quote at i = 0"); + if (i > 0 && rFormat.at(i - 1) == quote) + // Second of two quotes + result += quote; + expected = null; + } + else + // Next literal character + result += c; + } + else if (c == expected) + { + // Extend token + token += c; + } + else + { + // Close last token + result += formatToken(token, am_pm); + token.clear(); + expected = null; + + // Test for valid character + if (tokens.indexOf(c) >= 0) + { + if (c == QLatin1Char('a')) + expected = QLatin1Char('p'); + else if (c == QLatin1Char('A')) + expected = QLatin1Char('P'); + else if (c.toLower() == QLatin1Char('p')) + expected = null; + else + expected = c; + if (c != quote) + token += c; + } else + result += c; + } + } + + result += formatToken(token, am_pm); + return result; + } + + + QString DateTime::formatToken(const QString &rToken, bool am_pm) const + { + if (rToken.isEmpty()) + return QString(); + + const QChar c = rToken.at(0); + QString result; + int used = 0; + + // Qt data format strings + if (rToken.startsWith(QLatin1String("dddd"))) + { + result = QDate::longDayName(date().dayOfWeek()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("ddd"))) + { + result = QDate::shortDayName(date().dayOfWeek()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("dd"))) + { + result = QString::number(date().day()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('d')) + { + result = QString::number(date().day()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("MMMM"))) + { + result = QDate::longMonthName(date().month()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("MMM"))) + { + result = QDate::shortMonthName(date().month()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("MM"))) + { + result = QString::number(date().month()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('M')) + { + result = QString::number(date().month()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("yyyy"))) + { + result = QString::number(date().year()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("yy"))) + { + result = QString::number(date().year() % 100).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + + // Qt time format strings + else if (rToken.startsWith(QLatin1String("hh")) || rToken.startsWith(QLatin1String("HH"))) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('h') || c == QLatin1Char('H')) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour); + used = 2; + } + else if (rToken.startsWith(QLatin1String("mm"))) + { + result = QString::number(time().minute()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == (QLatin1Char('m'))) + { + result = QString::number(time().minute()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("ss"))) + { + result = QString::number(time().second()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('s')) + { + result = QString::number(time().second()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("zzz"))) + { + result = QString::number(time().msec()).rightJustified(3, QLatin1Char('0'), true); + used = 3; + } + else if (c == QLatin1Char('z')) + { + result = QString::number(time().msec()); + used = 1; + } + else if (c.toLower() == QLatin1Char('a')) + { + bool is_lower = c == QLatin1Char('a'); + if (time().hour() < 12) + result = QLatin1String("AM"); + else + result = QLatin1String("PM"); + if (is_lower) + result = result.toLower(); + if (rToken.size() > 1 && + ((is_lower && rToken.at(1) == QLatin1Char('p')) || + (!is_lower && rToken.at(1) == QLatin1Char('P'))) + ) + used = 2; + else + used = 1; + } + + // Extension for week number + else if (rToken.startsWith(QLatin1String("ww"))) + { + result = QString::number(date().weekNumber()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('w')) + { + result = QString::number(date().weekNumber()); + used = 1; + } + + if (used) + return result + formatToken(rToken.mid(used), am_pm); + else + return result; + } + + + bool DateTime::hasAMPM(const QString &rToken) + { + bool in_literal = false; + QChar c; + int i; + for (i = 0; i < rToken.length(); i++) + { + c = rToken.at(i); + if (c == QLatin1Char('\'')) + in_literal = !in_literal; + else if (!in_literal && c.toLower() == QLatin1Char('a')) + return true; + } + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/datetime.h b/GC-3.6.1-T2/src/log4qt/helpers/datetime.h new file mode 100644 index 0000000..2c83a47 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/datetime.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_DATETIME_H +#define LOG4QT_HELPERS_DATETIME_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class DateTime provides extended functionality for QDateTime. + * + * The class DateTime implements additional formatting options for + * toString() and provides conversion functions from and to milliseconds. + */ + class DateTime : public QDateTime + { + public: + /*! + * Constructs a null date time. + * + * \sa QDateTime::QDateTime() + */ + DateTime(); + + // DateTime(const DateTime &rOther); // Use compiler default + + /*! + * Constructs a copy of another QDateTime. + * + * \sa QDateTime::QDateTime(const QDateTime &rOther) + */ + DateTime(const QDateTime &rOther); + + /*! + * Constructs a datetime with the given \a rDate and \a rTime, using + * the time specification defined by \a timeSpec. + * + * \sa QDateTime::QDateTime(const QDate &rDate, const QTime &rTime, + * Qt::TimeSpec timeSpec = Qt::LocalTime) + */ + DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec = Qt::LocalTime); + + // virtual ~DateTime(); // Use compiler default + + /*! + * Assigns \a rOther to this DateTime and returns a reference to it. + */ + DateTime &operator=(const DateTime &rOther); + + /*! + * Returns the datetime as the number of milliseconds that have passed + * since 1970-01-01T00:00:00,000, Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::toTime_t() + */ + qint64 toMilliSeconds() const; + + /*! + * Returns the datetime as a string. The \a rFormat parameter + * determines the format of the result string. + * + * In addition to the expressions of QDateTime::toString(const QString + * &rFormat) the following expression can be used. + * + * + * + * + * + * + * + * + * + * + * + * + *
Expression Output
w the week of the year as number without a leading zero (1 to 53)
ww the week of the year as number with a leading zero (01 to 53)
+ * + * Alternatively the \a rFormat parameter can specify one of the + * following strings. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
String Format
ABSOLUTE uses the format HH:mm:ss.zzz
DATE uses the format dd MMM YYYY HH:mm:ss.zzzz
ISO8601 uses the format yyyy-MM-dd hh:mm:ss.zzz
NONE uses an empty string as format
RELATIVE returns the milliseconds since start of the program
+ * + * \sa QDateTime::toString(const QString &rFormat) + */ + QString toString(const QString &rFormat) const; + + /*! + * Returns the current datetime, as reported by the system clock, in + * the local time zone. + * + * \sa QDateTime::currentDateTime() + */ + static DateTime currentDateTime(); + + /*! + * Returns a datetime whose date and time are the number of + * milliseconds that have passed since 1970-01-01T00:00:00, + * Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::fromTime_t(uint seconds) + */ + static DateTime fromMilliSeconds(qint64 milliSeconds); + + private: + QString formatDateTime(const QString &rFormat) const; + QString formatToken(const QString &rToken, bool am_pm) const; + static bool hasAMPM(const QString &rFormat); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DateTime::DateTime() : QDateTime() + {} + + inline DateTime::DateTime(const QDateTime &rOther) : QDateTime(rOther) + {} + + inline DateTime::DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec) : + QDateTime(rDate, rTime, timeSpec) + {} + + inline DateTime &DateTime::operator=(const DateTime &rOther) + { QDateTime::operator=(rOther); return *this; } + + inline qint64 DateTime::toMilliSeconds() const + { return (qint64)1000 * toTime_t() + time().msec(); } + + inline DateTime DateTime::currentDateTime() + { return DateTime(QDateTime::currentDateTime()); } + + inline DateTime DateTime::fromMilliSeconds(qint64 milliSeconds) + { return DateTime(QDateTime::fromTime_t(milliSeconds / 1000).addMSecs(milliSeconds % 1000)); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::DateTime, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_HELPERS_DATETIME_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/factory.cpp b/GC-3.6.1-T2/src/log4qt/helpers/factory.cpp new file mode 100644 index 0000000..557226f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/factory.cpp @@ -0,0 +1,457 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/factory.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/dailyrollingfileappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/patternlayout.h" +#include "log4qt/rollingfileappender.h" +#include "log4qt/simplelayout.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/debugappender.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelmatchfilter.h" +#include "log4qt/varia/levelrangefilter.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/varia/nullappender.h" +#include "log4qt/varia/stringmatchfilter.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory) + + + // Appenders + + Appender *console_file_appender() + { return new ConsoleAppender; } + + Appender *create_daily_rolling_file_appender() + { return new DailyRollingFileAppender; } + + Appender *create_debug_appender() + { return new DebugAppender; } + + Appender *create_file_appender() + { return new FileAppender; } + + Appender *create_list_appender() + { return new ListAppender; } + + Appender *create_null_appender() + { return new NullAppender; } + + Appender *create_rolling_file_appender() + { return new RollingFileAppender; } + + + // Filters + + Filter *create_deny_all_filter() + { return new DenyAllFilter; } + + Filter *create_level_match_filter() + { return new LevelMatchFilter; } + + Filter *create_level_range_filter() + { return new LevelRangeFilter; } + + Filter *create_string_match_filter() + { return new StringMatchFilter; } + + + // Layouts + + Layout *create_pattern_layout() + { return new PatternLayout; } + + Layout *create_simple_layout() + { return new SimpleLayout; } + + Layout *create_ttcc_layout() + { return new TTCCLayout; } + + + + /************************************************************************** + * Class implementation: Factory + **************************************************************************/ + + + Factory::Factory() : + mObjectGuard(), + mAppenderRegistry(), + mFilterRegistry(), + mLayoutRegistry() + { + registerDefaultAppenders(); + registerDefaultFilters(); + registerDefaultLayouts(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(Factory) + + + Appender *Factory::doCreateAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName); + return 0; + } + return mAppenderRegistry.value(rAppenderClassName)(); + } + + + Filter *Factory::doCreateFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName); + return 0; + } + return mFilterRegistry.value(rFilterClassName)(); + } + + + Layout *Factory::doCreateLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName); + return 0; + } + return mLayoutRegistry.value(rLayoutClassName)(); + } + + + void Factory::doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rAppenderClassName.isEmpty()) + { + logger()->warn("Registering Appender factory function with empty class name"); + return; + } + mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc); + } + + + void Factory::doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rFilterClassName.isEmpty()) + { + logger()->warn("Registering Filter factory function with empty class name"); + return; + } + mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc); + } + + + void Factory::doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rLayoutClassName.isEmpty()) + { + logger()->warn("Registering Layout factory function with empty class name"); + return; + } + mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc); + } + + + void Factory::doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { + // - Validate property + // - Get correct property name from meta object + // - Find specific property setter + // - If no specfifc propery setter can be found, + // find general property setter + // - Call property setter + + QMetaProperty meta_property; + if (!validateObjectProperty(meta_property, rProperty, pObject)) + return; + + QString property = QLatin1String(meta_property.name()); + QString type = QLatin1String(meta_property.typeName()); + logger()->debug("Setting property '%1' on object of class '%2' to value '%3'", + property, + QLatin1String(pObject->metaObject()->className()), + rValue); + + QVariant value; + bool ok = true; + if (type == QLatin1String("bool")) + value = OptionConverter::toBoolean(rValue, &ok); + else if (type == QLatin1String("int")) + value = OptionConverter::toInt(rValue, &ok); + else if (type == QLatin1String("Log4Qt::Level")) + value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok)); + else if (type == QLatin1String("QString")) + value = rValue; + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"), + CONFIGURATOR_UNKNOWN_TYPE_ERROR, + "Log4Qt::Factory"); + e << type + << property + << QString::fromLatin1(pObject->metaObject()->className()); + logger()->error(e); + return; + } + if (!ok) + return; + + // Everything is checked and the type is the one of the property. + // Write should never return false + if (!meta_property.write(pObject, value)) + logger()->warn("Unxpected error result from QMetaProperty.write()"); + } + + + void Factory::doUnregisterAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName); + return; + } + mAppenderRegistry.remove(rAppenderClassName); + } + + + void Factory::doUnregisterFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName); + return; + } + mFilterRegistry.remove(rFilterClassName); + } + + + void Factory::doUnregisterLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName); + return; + } + mLayoutRegistry.remove(rLayoutClassName); + } + + + void Factory::registerDefaultAppenders() + { + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender); + } + + + void Factory::registerDefaultFilters() + { + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter); + } + + + void Factory::registerDefaultLayouts() + { + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout); + } + + + bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject) + { + // Validate: + // - No null object pointer + // - No empty property name + // - Property exists on the object (QT or Java name) + // - Property is readable + // - Property is writable + + const char *p_context = "Log4Qt::Factory"; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"), + CONFIGURATOR_PROPERTY_ERROR, + p_context); + + if (!pObject) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + if (rProperty.isEmpty()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + const QMetaObject *p_meta_object = pObject->metaObject(); + QString property = rProperty; + int i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + // Try name with lower case first character. Java properties names + // start upper case + property[0] = property[0].toLower(); + i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + } + rMetaProperty = p_meta_object->property(i); + if (!rMetaProperty.isWritable()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Factory &rFactory) + { + debug.nospace() << "Factory(" + << "appenderfactories:" << rFactory.registeredAppenders() + << "filterfactories:" << rFactory.registeredFilters() + << "layoutfactories:" << rFactory.registeredLayouts() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GC-3.6.1-T2/src/log4qt/helpers/factory.h b/GC-3.6.1-T2/src/log4qt/helpers/factory.h new file mode 100644 index 0000000..5b9b926 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/factory.h @@ -0,0 +1,444 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_FACTORY_H +#define LOG4QT_HELPERS_FACTORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Appender; + class Filter; + class Layout; + + /*! + * \brief The class Factory provides factories for Appender, Filter and + * Layout objects. + * + * The functions createAppender(), createFilter() and createLayout() + * allow to create objects by specifying their class names. By default + * all classes of the package are recognised with their Log4j and Log4Qt + * classanmes. For example an object of the class FileAppender can be + * craeted using "org.apache.log4j.FileAppender" or "Log4Qt::FileAppender". + * Additional classes can be registered using registerAppender(), + * registerFilter() and registerLayout(). + * + * An QObject property can be set from a string value with + * setObjectProperty(). The function handles the required error checking + * and type conversion. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa PropertyConfigurator + */ + class Factory + { + public: + /*! + * Prototype for an Appender factory function. The function creates + * an Appender object on the heap and returns a pointer to it. + * + * \sa registerAppender(), createAppender() + */ + typedef Appender *(*AppenderFactoryFunc)(); + + /*! + * Prototype for a Filter factory function. The function creates + * a Filter object on the heap and returns a pointer to it. + * + * \sa registerFilter(), createFilter() + */ + typedef Filter *(*FilterFactoryFunc)(); + + /*! + * Prototype for a Layout factory function. The function creates + * a Layout object on the heap and returns a pointer to it. + * + * \sa registerLayout(), createLayout() + */ + typedef Layout *(*LayoutFactoryFunc)(); + + private: + Factory(); + Factory(const Factory &rOther); // Not implemented + // virtual ~Factory(); // Use compiler default + Factory &operator=(const Factory &rOther); // Not implemented + + public: + /*! + * Creates an object for the class \a rAppenderClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerAppender(), unregisterAppender(), registeredAppenders() + */ + static Appender *createAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Appender *createAppender(const char *pAppenderClassName); + + /*! + * Creates an object for the class \a rFilterClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerFilter(), unregisterFilter(), registeredFilters() + */ + static Filter *createFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Filter *createFilter(const char *pFilterClassName); + + /*! + * Creates an object for the class \a rLayoutClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerLayout(), unregisterLayout(), registeredLayouts() + */ + static Layout *createLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Layout *createLayout(const char *pLayoutClassName); + + /*! + * Returns the Factory instance. + */ + static Factory *instance(); + + /*! + * Registers the Appender factory function \a pAppenderFactoryFunc + * for the class \a rAppenderClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pAppenderFactoryFunc. + * + * \sa unregisterAppender(), registeredAppenders(), createAppender() + */ + static void registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * Registers the Filter factory function \a pFilterFactoryFunc + * for the class \a rFilterClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pFilterFactoryFunc. + * + * \sa unregisterFilter(), registeredFilters(), createFilter() + */ + static void registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * Registers the Layout factory function \a pLayoutFactoryFunc + * for the class \a rLayoutClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pLayoutFactoryFunc. + * + * \sa unregisterLayout(), registeredLayout(), createLayout() + */ + static void registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * Returns a list of the class names for registered Appender factory + * functions. + * + * \sa registerAppender(), unregisterAppender() + */ + static QStringList registeredAppenders(); + + /*! + * Returns a list of the class names for registered Filter factory + * functions. + * + * \sa registerFilter(), unregisterFilter() + */ + static QStringList registeredFilters(); + + /*! + * Returns a list of the class names for registered Layout factory + * functions. + * + * \sa registerLayout(), unregisterLayout() + */ + static QStringList registeredLayouts(); + + /*! + * Sets the property \a rProperty of the object \a pObject to the + * value \a rValue. The function will test that the property + * \a rProperty is writeable and of a type the function can convert to. + * The types bool, int, Level and QString are supported. + * + * \sa OptionConverter + */ + static void setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue); + + /*! + * Unregisters the Appender factory function for the class + * \a rAppenderClassName. + * + * \sa registerAppender(), registeredAppenders() + */ + static void unregisterAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterAppender(const char *pAppenderClassName); + + /*! + * Unregisters the Filter factory function for the class + * \a rFilterClassName. + * + * \sa registerFilter(), registeredFilters() + */ + static void unregisterFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterFilter(const char *pFilterClassName); + + /*! + * Unregisters the Layout factory function for the class + * \a rLayoutClassName. + * + * \sa registerLayout(), registeredLayouts() + */ + static void unregisterLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterLayout(const char *pLayoutClassName); + + private: + Appender *doCreateAppender(const QString &rAppenderClassName); + Filter *doCreateFilter(const QString &rFilterClassName); + Layout *doCreateLayout(const QString &rLayoutClassName); + void doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + void doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + void doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + void doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + void doUnregisterAppender(const QString &rAppenderClassName); + void doUnregisterFilter(const QString &rFilterClassName); + void doUnregisterLayout(const QString &rLayoutClassName); + void registerDefaultAppenders(); + void registerDefaultFilters(); + void registerDefaultLayouts(); + bool validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject); + + private: + mutable QMutex mObjectGuard; + QHash mAppenderRegistry; + QHash mFilterRegistry; + QHash mLayoutRegistry; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Factory + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Factory(appenderfactories:("Log4Qt::DebugAppender", "Log4Qt::NullAppender", + * "Log4Qt::ConsoleAppender", "org.apache.log4j.varia.DebugAppender", + * "org.apache.log4j.FileAppender", "org.apache.log4j.RollingFileAppender", + * "org.apache.log4j.DailyRollingFileAppender", + * "org.apache.log4j.varia.ListAppender", + * "org.apache.log4j.varia.NullAppender", + * "Log4Qt::FileAppender", "org.apache.log4j.ConsoleAppender", + * "Log4Qt::DailyRollingFileAppender", "Log4Qt::ListAppender", + * "Log4Qt::RollingFileAppender") filterfactories: + * ("Log4Qt::DenyAllFilter", "Log4Qt::StringMatchFilter", + * "Log4Qt::LevelRangeFilter", "org.apache.log4j.varia.DenyAllFilter", + * "org.apache.log4j.varia.LevelRangeFilter", + * "org.apache.log4j.varia.StringMatchFilter", "Log4Qt::LevelMatchFilter", + * "org.apache.log4j.varia.LevelMatchFilter") layoutfactories: + * ("org.apache.log4j.SimpleLayout", "Log4Qt::PatternLayout", + * "Log4Qt::SimpleLayout", "org.apache.log4j.TTCCLayout", + * "Log4Qt::TTCCLayout", "org.apache.log4j.PatternLayout") ) + * + * \sa QDebug, Factory::logManager() + */ + QDebug operator<<(QDebug debug, + const Factory &rFactory); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender *Factory::createAppender(const QString &rAppenderClassName) + { return instance()->doCreateAppender(rAppenderClassName); } + + inline Appender *Factory::createAppender(const char *pAppenderClassName) + { return instance()->doCreateAppender(QLatin1String(pAppenderClassName)); } + + inline Filter *Factory::createFilter(const QString &rFilterClassName) + { return instance()->doCreateFilter(rFilterClassName); } + + inline Filter *Factory::createFilter(const char *pFilterClassName) + { return instance()->doCreateFilter(QLatin1String(pFilterClassName)); } + + inline Layout *Factory::createLayout(const QString &rLayoutClassName) + { return instance()->doCreateLayout(rLayoutClassName); } + + inline Layout *Factory::createLayout(const char *pLayoutClassName) + { return instance()->doCreateLayout(QLatin1String(pLayoutClassName)); } + + inline void Factory::registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(rAppenderClassName, pAppenderFactoryFunc); } + + inline void Factory::registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(QLatin1String(pAppenderClassName), pAppenderFactoryFunc); } + + inline void Factory::registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(rFilterClassName, pFilterFactoryFunc); } + + inline void Factory::registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(QLatin1String(pFilterClassName), pFilterFactoryFunc); } + + inline void Factory::registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(rLayoutClassName, pLayoutFactoryFunc); } + + inline void Factory::registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(QLatin1String(pLayoutClassName), pLayoutFactoryFunc); } + + inline QStringList Factory::registeredAppenders() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mAppenderRegistry.keys(); } + + inline QStringList Factory::registeredFilters() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mFilterRegistry.keys(); } + + inline QStringList Factory::registeredLayouts() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mLayoutRegistry.keys(); } + + inline void Factory::setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, rProperty, rValue); } + + inline void Factory::setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, QLatin1String(pProperty), rValue); } + + inline void Factory::unregisterAppender(const QString &rAppenderClassName) + { instance()->doUnregisterAppender(rAppenderClassName); } + + inline void Factory::unregisterAppender(const char *pAppenderClassName) + { instance()->doUnregisterAppender(QLatin1String(pAppenderClassName)); } + + inline void Factory::unregisterFilter(const QString &rFilterClassName) + { instance()->doUnregisterFilter(rFilterClassName); } + + inline void Factory::unregisterFilter(const char *pFilterClassName) + { instance()->doUnregisterFilter(QLatin1String(pFilterClassName)); } + + inline void Factory::unregisterLayout(const QString &rLayoutClassName) + { instance()->doUnregisterLayout(rLayoutClassName); } + + inline void Factory::unregisterLayout(const char *pLayoutClassName) + { instance()->doUnregisterLayout(QLatin1String(pLayoutClassName)); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Factory, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_FACTORY_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.cpp b/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.cpp new file mode 100644 index 0000000..783929e --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/initialisationhelper.h" + +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: InitialisationHelper + **************************************************************************/ + + + InitialisationHelper::InitialisationHelper() : + mStartTime(DateTime::currentDateTime().toMilliSeconds()), + mEnvironmentSettings() + { + doRegisterTypes(); + doInitialiseEnvironmentSettings(); + } + + + InitialisationHelper::~InitialisationHelper() + { + Q_ASSERT_X(false, "InitialisationHelper::~InitialisationHelper()", "Unexpected destruction of singleton object"); + } + + + LOG4QT_IMPLEMENT_INSTANCE(InitialisationHelper) + + + void InitialisationHelper::doInitialiseEnvironmentSettings() + { + // Is Process::systemEnvironment() safe to be used before a QCoreApplication + // object has been created? + + QStringList setting_keys; + setting_keys << QLatin1String("Debug"); + setting_keys << QLatin1String("DefaultInitOverride"); + setting_keys << QLatin1String("Configuration"); + setting_keys << QLatin1String("ConfiguratorClass"); + + QHash env_keys; + QString entry; + Q_FOREACH(entry, setting_keys) + env_keys.insert(QString::fromLatin1("log4qt_").append(entry).toUpper(), entry); + + QStringList sys_env = QProcess::systemEnvironment(); + Q_FOREACH(entry, sys_env) + { + int i = entry.indexOf(QLatin1Char('=')); + if (i == -1) + continue; + QString key = entry.left(i); + QString value = entry.mid(i + 1).trimmed(); + if (env_keys.contains(key)) + mEnvironmentSettings.insert(env_keys.value(key), value); + } + } + + + void InitialisationHelper::doRegisterTypes() + { + qRegisterMetaType("Log4Qt::LogError"); + qRegisterMetaType("Log4Qt::Level"); + qRegisterMetaType("Log4Qt::LoggingEvent"); + + #ifndef QT_NO_DATASTREAM + qRegisterMetaTypeStreamOperators("Log4Qt::LogError"); + qRegisterMetaTypeStreamOperators("Log4Qt::Level"); + qRegisterMetaTypeStreamOperators("Log4Qt::LoggingEvent"); + #endif + } + + + QString InitialisationHelper::doSetting(const QString &rKey, + const QString &rDefault) const + { + if (mEnvironmentSettings.contains(rKey)) + return mEnvironmentSettings.value(rKey); + + if (QCoreApplication::instance()) + { + QSettings s; + s.beginGroup(QLatin1String("Log4Qt")); + return s.value(rKey, rDefault).toString().trimmed(); + } + else + return rDefault; + } + + + bool InitialisationHelper::staticInitialisation() + { + instance(); + return true; + } + + + bool InitialisationHelper::msStaticInitialisation = staticInitialisation(); + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper) + { + Q_UNUSED(rInitialisationHelper); + debug.nospace() << "InitialisationHelper(" + << "starttime:" << InitialisationHelper::startTime() + << "(" << DateTime::fromMilliSeconds(InitialisationHelper::startTime()) << ")" + << "environmentsettings:" << InitialisationHelper::environmentSettings() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.h b/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.h new file mode 100644 index 0000000..95b370d --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/initialisationhelper.h @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H +#define LOG4QT_HELPERS_INITIALISATIONHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QMutex; + +namespace Log4Qt +{ + /*! + * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that + * returns a pointer to a singleton object of the type \a TYPE. + * + * The macro uses a static variable to store a pointer to the singleton + * object. On the first invocation an object of the type \a TYPE is created + * on the heap and the pointer is set. Any further invocations will return + * the stored pointer. If multiple threads are accessing the function + * without the pointer being set, each thread will create an object of the + * type \a TYPE. The threads that find the pointer already been set will + * delete their object. The singleton object will not be deleted during static + * de-initialisation. + * + * The following example uses a global global mutex object to synchronise + * access to a static member variable. + * + * \code + * #file: myclass.h + * + * class MyClass + * { + * public: + * MyClass(); + * ~MyClass(); + * private: + * static qint64 msObjectCount; + * } + * \endcode + * \code + * #file: myclass.cpp + * + * #include myclass.h + * + * LOG4QT_GLOBAL_STATIC(QMutex, class_guard) + * + * MyClass::MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount++; + * } + * + * MyClass::~MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount--; + * } + * + * qint64 MyClass::msObjectCount = 0; + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static volatile TYPE *sp_global_static_##FUNCTION = 0; \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return const_cast(sp_global_static_##FUNCTION); \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION; \ + } +#else + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a + * singleton class \a TYPE. + * + * The function works like the one created by + * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC". + * + * The following example illustrates how to use the macro to create a + * singleton class: + * + * \code + * #file: mysingleton.h + * + * class MySingleton + * { + * private: + * MySingleton(); + * ~MySingleton(); + * public: + * MySingleton *instance(); + * } + * \endcode + * \code + * #file: mysingleton.cpp + * + * #include mysingleton.h + * + * MySingleton::MySingleton() + * {} + * + * MySingleton::~MySingleton() + * {} + * + * LOG4QT_IMPLEMENT_INSTANCE(MySingleton) + * + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static TYPE *sp_singleton_##TYPE = 0; \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#else + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE.loadAcquire(); \ + } +#endif + + /*! + * \brief The class InitialisationHelper performs static initialisation + * tasks. + * + * The InitialisationHelper is either created on the first call or through + * static initialisation. It will capture the programs startup time, + * which can be retrieved using startTime(). The system environment + * is analysed for package related definitions. The result is available + * over environmentSettings(). The packages custom types are registered with + * the Qt type system. + * + * Settings for the package can be retrieved using setting(). Two macros + * are available to help with the creation of singletons / global static + * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and + * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"). + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Init "Initialization procedure", + */ + class InitialisationHelper + { + private: + InitialisationHelper(); + InitialisationHelper(const InitialisationHelper &rOther); // Not implemented + virtual ~InitialisationHelper(); + InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented + + public: + + /*! + * Returns a hash with the settings retrieved from the system + * environment on startup. + * + * The following table shows the environment variables taken into + * account and the setting key used for them. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Environment variable Setting key
LOG4QT_DEBUG Debug
LOG4QT_DEFAULTINITOVERRIDE DefaultInitOverride
LOG4QT_CONFIGURATION Configuration
LOG4QT_CONFIGURATORCLASS ConfiguratorClass
+ * + * \sa \ref Env "Environment Variables", + * setting() + */ + static QHash environmentSettings(); + + /*! + * Returns the InitialisationHelper instance. + */ + static InitialisationHelper *instance(); + + /*! + * Returns the value for the setting \a rKey or \a rDefault, if it is + * not defined. + * + * A setting can be either defined by an environment variable or by a + * key in the application setting. The function will first test the + * settings made by environment variables for the key \a rKey using + * environmentSettings(). If the key is not present and a + * QCoreApplication exists, the application settings are tested for + * the key \a rKey in the group \c %Log4Qt. + * + * The following setting exists: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Setting key Description
Debug The variable controls the Level value for the logger + * LogManager::logLogger(). If the value is a valid Level string, + * the level for the logger is set to the level. If the value is not + * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used. + * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used.
DefaultInitOverride The variable controls the \ref Init "initialization procedure" + * performed by the \ref LogManager "LogManager" on startup. + * If it is set to any other value then \c false the \ref Init + * "initialization procedure" is skipped.
Configuration Specifies the configuration file used for initialising the package.
ConfiguratorClass Specifies the configurator class used for initialising the package.
+ * + * \sa environmentSettings(), \ref Env "Environment Variables", + * \ref Init "Initialization procedure", + * LogManager::configureLogLogger(), LogManager::startup() + */ + static QString setting(const QString &rKey, + const QString &rDefault = QString()); + + /*! + * Returns the start time of the program as the number of milliseconds + * that have passed since 1970-01-01T00:00:00,000, Coordinated + * Universal Time (Qt::UTC). + * + * \sa DateTime::fromMilliSeconds(), + * DateTime::toMilliSeconds() + */ + static qint64 startTime(); + + private: + void doInitialiseEnvironmentSettings(); + void doRegisterTypes(); + QString doSetting(const QString &rKey, + const QString &rDefault) const; + static bool shutdown(); + static bool staticInitialisation(); + + private: + // QMutex mObjectGuard; + const qint64 mStartTime; + QHash mEnvironmentSettings; + static bool msStaticInitialisation; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates InitialisationHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %InitialisationHelper(InitialisationHelper(starttime:1193883677438( + * QDateTime("Wed Oct 31 21:21:17 2007") ) + * environmentsettings: QHash(("configuration", "\myapp.log4j") + * ("Debug", "DEBUG")) ) ) + * + * \sa QDebug, InitialisationHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QHash InitialisationHelper::environmentSettings() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mEnvironmentSettings; } + + inline QString InitialisationHelper::setting(const QString &rKey, + const QString &rDefault) + { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const + return instance()->doSetting(rKey, rDefault); } + + inline qint64 InitialisationHelper::startTime() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mStartTime; } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logerror.cpp b/GC-3.6.1-T2/src/log4qt/helpers/logerror.cpp new file mode 100644 index 0000000..f78d2ab --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logerror.cpp @@ -0,0 +1,354 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + *****************************************************************************/ + + +#include "log4qt/helpers/logerror.h" + +#include +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + typedef QThreadStorage ThreadError; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(ThreadError, thread_error) + + + + /************************************************************************** + * Class implementation: LogError + **************************************************************************/ + + + LogError::LogError() : + mCode(0), + mContext(), + mMessage(), + mSymbol(), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const QString &rMessage, + int code, + const QString &rSymbol, + const QString &rContext) : + mCode(code), + mContext(rContext), + mMessage(cleanMessage(rMessage)), + mSymbol(rSymbol), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const char *pMessage, + int code, + const char *pSymbol, + const char *pContext, + Encoding encoding) : + mCode(code), + mContext(QString::fromLatin1(pContext)), + mMessage(), + mSymbol(QString::fromLatin1(pSymbol)), + mArgs(), + mCausingErrors() + { + switch(encoding) + { + case LATIN1: + mMessage = QString::fromLatin1(pMessage); + break; + case CODECFORTR: +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + mMessage = QTextCodec::codecForTr()->toUnicode(pMessage); +#else + mMessage = QString::fromUtf8(pMessage); +#endif + break; + case UNICODEUTF8: + mMessage = QString::fromUtf8(pMessage); + break; + default: + Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant"); + mMessage = QString::fromLatin1(pMessage); + } + mMessage = cleanMessage(mMessage); + + if (mSymbol == QString::number(mCode)) + mSymbol.clear(); + } + + + QString LogError::translatedMessage() const + { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0, QCoreApplication::UnicodeUTF8); +#else + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0); +#endif + } + + + LogError LogError::lastError() + { + if (!thread_error()->hasLocalData()) + return LogError(); + else + return *thread_error()->localData(); + } + + + void LogError::setLastError(const LogError &rLogError) + { + if (!thread_error()->hasLocalData()) + thread_error()->setLocalData(new LogError); + + *thread_error()->localData() = rLogError; + } + + + QString LogError::toString() const + { + QString result = messageWithArgs(); + + QString context_symbol = mContext; + if (!context_symbol.isEmpty() && !mSymbol.isEmpty()) + context_symbol.append(QLatin1String("::")); + context_symbol.append(mSymbol); + + if (!context_symbol.isEmpty() || mCode) + { + result.append(QLatin1String(" (")); + if (!context_symbol.isEmpty()) + result.append(context_symbol); + if (!context_symbol.isEmpty() && mCode) + result.append(QLatin1String(", ")); + if (mCode) + result.append(QString::number(mCode)); + result.append(QLatin1String(")")); + } + + if (!mCausingErrors.isEmpty()) + { + QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString(); + int i = 1; + while (i < mCausingErrors.count()) + { + causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString()); + i++; + } + result.append(causing_errors_str); + } + + return result; + } + + + QString LogError::insertArgs(const QString &rMessage) const + { + QString result; + + /* + + // Don't use a loop to be able to handle arguments that conatin strings + // like %1. + // Using this method only 9 arguments can be handled as the %1 + // in %11 gets also replaced with the first argument. + + switch (mArgs.count()) + { + case 0: + break; + case 1: + result = rMessage.arg(mArgs.at(0)); + break; + case 2: + result = rMessage.arg(mArgs.at(0), mArgs.at(1)); + break; + case 3: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2)); + break; + case 4: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3)); + break; + case 5: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4)); + break; + case 6: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5)); + break; + case 7: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6)); + break; + case 8: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7)); + break; + default: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8)); + break; + } + + if (mArgs.count() > 9) + { + int i = 9; + while(i < mArgs.count()) + { + result = result.arg(mArgs.at(i)); + i++; + } + } + */ + + result = rMessage; + QVariant arg; + Q_FOREACH(arg, mArgs) + result = result.arg(arg.toString()); + return result; + } + + + QString LogError::cleanMessage(const QString &rMessage) + { + if (rMessage.isEmpty()) + return rMessage; + + QString result = rMessage; + if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.')) + result = rMessage.left(rMessage.size() - 1); + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLogError.mCode + << rLogError.mContext + << rLogError.mMessage + << rLogError.mSymbol + << rLogError.mArgs + << rLogError.mCausingErrors; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString level; + QString logger; + stream >> rLogError.mCode + >> rLogError.mContext + >> rLogError.mMessage + >> rLogError.mSymbol + >> rLogError.mArgs + >> rLogError.mCausingErrors; + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogError &rLogError) + { + // Escape % sign + QString message = rLogError.message(); + message.replace(QLatin1String("%"), QLatin1String("%%")); + + debug.nospace() << "LogError(" + << "code:" << rLogError.code() << " " + << "context:" << rLogError.context() << " " + << "message:" << message << " " + << "symbol:" << rLogError.symbol() << " " + << "args:" << rLogError.args() + << "translatedMessage:" << rLogError.translatedMessage() + << ")"; + return debug.maybeSpace(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logerror.h b/GC-3.6.1-T2/src/log4qt/helpers/logerror.h new file mode 100644 index 0000000..06d1a67 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logerror.h @@ -0,0 +1,550 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGERROR_H +#define LOG4QT_LOGERROR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + /*! + * Creates an LogError object with the error message \a message, the error + * code \a code and the context \a context. The symbol of the error is + * set to \a code as string value. + * + * The following example logs an error, if a character is not a digit. + * + * \code + * if (!c.isDigit()) + * { + * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + * LAYOUT_EXPECTED_DIGIT_ERROR, + * "Log4Qt::PatternFormatter"); + * e << QString(c); + * logger()->error(e); + * } + * \endcode + */ + #define LOG4QT_ERROR(message, code, context) \ + LogError(message, code, #code, context) + + /*! + * Creates an LogError object with the error message \a message and the + * error code \a code. The symbol of the error is set to \a code as string + * value. The context is set to the class name of the current object. The + * current objects class must be derived from QObject. + * + * The following example handles an error while opening a file. + * + * \code + * if (!mpFile->open(mode)) + * { + * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + * APPENDER_OPENING_FILE_ERROR); + * e << mFileName << name(); + * e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + * logger()->error(e); + * return; + * } + * \endcode + */ + #define LOG4QT_QCLASS_ERROR(message, code) \ + LogError(message, code, #code, this->metaObject()->className()) + + /*! + * \brief The class LogError represents an error. + * + * The class error allows storing error information in a structured way. + * The error message is stored separately from the information that may be + * substituted into the message string. This way it is possible to access + * all information after the error has been raised. It also allows to + * translate the error at a later point in time or to get a translated and + * a not translated error text (e.g. translated for the UI and not + * translated for a log). + * + * The message is accessed using message() and setMessage(). Arguments for + * the message can be added using addArg() or operator<<(). The arguments + * can be retrieved using args(). The message with substituted arguments + * is returned by messageWithArgs(). + * + * An error code can be set as integer value code() and/or a symbolic value + * symbol(). + * + * To allow the translation of the message the error stores the translation + * context (context(), setContext()). The translated message can be accessed + * using translatedMessage() or using translatedMessageWithArgs(), if it + * should contain the arguments. + * + * An error can have one or more related errors that caused it. An error is + * related using addCausingError(). All causing errors can be retrieved using + * causingErrors(). + * + * A per thread error can be maintained using lastError() and setLastError(). + * + * There are two macros avaiable to simplify the error creation. The macro + * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived + * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * is used with classes derived from QObject. + */ + class LogError + { + public: + + /*! + * The enum Encoding defines the 8-bit encoding of a character string + * arguments to \ref LogError::LogError(const char *, int, const char *, + * const char *, Encoding) "LogError::LogError()". + * + * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()" + */ + enum Encoding + { + /*! LATIN-1 */ + LATIN1, + /*! + * The encoding specified by QTextCodec::codecForTr() + * (Latin-1 if none has been set). + */ + CODECFORTR, + /*! UTF-8 */ + UNICODEUTF8 + }; + Q_ENUMS(Encoding) + + /*! + * Creates an empty error. The error code is set to 0 and all other + * members are set to be empty. + * + * \sa isEmpty() + */ + LogError(); + + /*! + * Creates an error with the Message \a rMessage and the error code + * \a code. The symbol for the error code is set to \a rSymbol and the + * context to \a rContext. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requested. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const QString &rMessage, + int code = 0, + const QString &rSymbol = QString(), + const QString &rContext = QString()); + + /*! + * Creates an error with the Message \a pMessage and the error code + * \a code. The symbol for the error code is set to \a pSymbol and the + * context to \a pContext. + * + * \a encoding specifies the encoding of \a pMessage. \a pSymbol and + * \a pContext are expected to be Latin-1. + * + * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" + * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * the function tests, if \a pSymbol is the string representation of + * \a code. If it is, the symbol is set to be empty. Otherwise symbol + * is set to \a pSymbol. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const char *pMessage, + int code = 0, + const char *pSymbol = 0, + const char *pContext = 0, + Encoding encoding = LATIN1); + + // LogError(const LogError &rOther); // Use compiler default + // virtual ~LogError(); // Use compiler default + // LogError &operator=(const LogError &rOther); // Use compiler default + + /*! + * Returns the error code. + * + * \sa setCode() + */ + int code() const; + + /*! + * Returns the context for the error. + * + * \sa setContext() + */ + QString context() const; + + /*! + * Returns the error message. + * + * \sa setMessage() + */ + QString message() const; + + /*! + * Returns the symbol for the error code. + * + * \sa setSymbol() + */ + QString symbol() const; + + /*! + * Returns the translated error message. + * + * The translated message is created by calling + * QCoreApplication::translate() using context().toLatin1() as + * context and message.toUtf8() as message. + * + * \sa translatedMessageWithArgs() + */ + QString translatedMessage() const; + + /*! + * Sets the error code to \a code. + * + * \sa code() + */ + void setCode(int code); + + /*! + * Sets the context to \a rClassName. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requestd. + * + * \sa context(), translatedMessage(), translatedMessageWithArgs() + */ + void setContext(const QString &rClassName); + + /*! + * Sets the error message to \a rMessage + * + * \sa message() + */ + void setMessage(const QString &rMessage); + + /*! + * Sets the symbol for the error code to \a rSymbol. + * + * \sa symbol() + */ + void setSymbol(const QString &rSymbol); + + /*! + * Returns the last error set for the current thread using + * setLastError(). + * + * \note: This function is thread-safe. + * + * \sa setLastError() + */ + static LogError lastError(); + + /*! + * Sets the last error for the current thread to \a rLogError. + * + * \note: This function is thread-safe. + * + * \sa lastError() + */ + static void setLastError(const LogError &rLogError); + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa operator<<(), args(), clearArgs() + */ + LogError &addArg(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(const QString &rArg); + + /*! + * Appends \a rLogError to the list of causing errors and returns a + * reference to this error. + * + * \sa causingErrors(), clearCausingErrors() + */ + LogError &addCausingError(const LogError &rLogError); + + /*! + * Returns the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList args() const; + + /*! + * Returns the list of causing errors that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList causingErrors() const; + + /*! + * Clears the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), args() + */ + void clearArgs(); + + /*! + * Clears the list of causing errors that have been added to this error. + * + * \sa addCausingError(), causingErrors() + */ + void clearCausingErrors(); + + /*! + * Returns true, if the error code is 0 and the message is empty. + * Otherwise it returns false. + * + * \sa code(), message() + */ + bool isEmpty() const; + + /*! + * Returns the message with arguments. The arguments are incoorporated + * into the messag using QString::arg(). + * + * \sa QString::arg(), translatedMessageWithArgs() + */ + QString messageWithArgs() const; + + /*! + * Returns the translated message with arguments. The arguments are + * incoorporated into the messag using QString::arg(). + * + * \sa QString::arg(), messageWithArgs(), translatedMessage() + */ + QString translatedMessageWithArgs() const; + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa addArg() + */ + LogError &operator<<(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(const QString &rArg); + + /*! + * Returns a string representation of the error. + * + * The string has the following format: + * + * + * message (context::symbol, code): causing_error, causing_error + * + * + * If members are empty they are omitted: + * - Omit context, if empty + * - Omit symbol, if empty + * - Omit double colon with context and symbol, if both are empty + * - Omit code, if 0 + * - Omit bracket with context/symbol and code, if all are empty + * - Omit colon with causing errors, if no causing errors exist + */ + QString toString() const; + + private: + QString insertArgs(const QString &rMessage) const; + QString cleanMessage(const QString &rMessage); + + private: + int mCode; + QString mContext; + QString mMessage; + QString mSymbol; + QList mArgs; + QList mCausingErrors; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + friend QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LogError + * + * Writes the given error \a rLogError to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + + /*! + * \relates LogError + * + * Reads an error from the given stream \a rStream into the given + * error \a rLogError, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogError + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LogError(code:7 context:"Log4Qt::FileAppender" + * message:"Unable to open file '%1' for appender '%2'" + * symbol:"APPENDER_OPENING_FILE_ERROR" + * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") ) + * translatedMessage: "Unable to open file '%1' for appender '%2'" ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogError &rLogError); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int LogError::code() const + { return mCode; } + + inline QString LogError::context() const + { return mContext; } + + inline QString LogError::message() const + { return mMessage; } + + inline QString LogError::symbol() const + { return mSymbol; } + + inline void LogError::setCode(int code) + { mCode = code; } + + inline void LogError::setContext(const QString &rContext) + { mContext = rContext; } + + inline void LogError::setMessage(const QString &rMessage) + { mMessage = cleanMessage(rMessage); } + + inline void LogError::setSymbol(const QString &rSymbol) + { mSymbol = rSymbol; } + + inline LogError &LogError::addArg(const QVariant &rArg) + { mArgs << rArg; return *this; } + + inline LogError &LogError::addArg(int arg) + { mArgs << QVariant(arg); return *this; } + + inline LogError &LogError::addArg(const QString &rArg) + { mArgs << QVariant(rArg); return *this; } + + inline LogError &LogError::addCausingError(const LogError &rLogError) + { mCausingErrors << rLogError; return *this; } + + inline QList LogError::args() const + { return mArgs; } + + inline void LogError::clearArgs() + { mArgs.clear(); } + + inline void LogError::clearCausingErrors() + { mCausingErrors.clear(); } + + inline QList LogError::causingErrors() const + { return mCausingErrors; } + + inline bool LogError::isEmpty() const + { return mCode || !mMessage.isEmpty(); } + + inline QString LogError::messageWithArgs() const + { return insertArgs(message()); } + + inline QString LogError::translatedMessageWithArgs() const + { return insertArgs(translatedMessage()); } + + inline LogError &LogError::operator<<(const QVariant &rArg) + { return addArg(rArg); } + + inline LogError &LogError::operator<<(int arg) + { return addArg(arg); } + + inline LogError &LogError::operator<<(const QString &rArg) + { return addArg(rArg); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LogError) +Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_ERROR_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logobject.cpp b/GC-3.6.1-T2/src/log4qt/helpers/logobject.cpp new file mode 100644 index 0000000..44f1121 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logobject.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobject.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObject + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogObject &rLogObject) + { + return rLogObject.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logobject.h b/GC-3.6.1-T2/src/log4qt/helpers/logobject.h new file mode 100644 index 0000000..97b02c5 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logobject.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_increment and q_atomic_decrement + * with QAtomicInt. + * Feb 2009, Martin Heinrich + * - Fixed a problem where the pParent parameter of the constructor + * was not passed on to the QObject constructor + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECT_H +#define LOG4QT_LOGOBJECT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include "log4qt/helpers/classlogger.h" +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# warning "QAtomicInt reference counting is not native. The class Log4Qt::LogObject is not thread-safe." +# endif +#endif + + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LogObject is the common base class for many classes + * in the package. + * + * The class inherits QObject to allow its subclass to be accessed using + * the Qt property system. + * + * LogObject objects provide a reference counter. A reference to the + * object is established by calling retain() and freed by calling + * release(). The object will delete itself when the reference counter + * is decremented to 0. + * + * A class specific logger can be accessed over logger(). + * + * The class also implements generic streaming to QDebug. Streaming an + * object to QDebug will invoke debug() to create class specific output. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Ownership "Object ownership", + * LOG4QT_DECLARE_QCLASS_LOGGER + */ + class LogObject : public QObject + { + Q_OBJECT + + public: + /*! + * Creates a LogObject which is a child of \a pObject. + */ + LogObject(QObject *pObject = 0); + + /*! + * Destroys the LogObject. + */ + virtual ~LogObject(); + + private: + LogObject(const LogObject &rOther); // Not implemented + LogObject &operator=(const LogObject &rOther); // Not implemented + + public: + /*! + * Returns the value of the reference counter. + */ + int referenceCount() const; + + /*! + * Decrements the reference count of the object. If the reference count + * count reaches zero and the object does not have a parent the object + * is deleted. + */ + void release(); + + /*! + * Increments the reference count of the object. + */ + void retain(); + + protected: + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to + * generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif // QT_NO_DEBUG_STREAM + + /*! + * Returns a pointer to a Logger named after of the object. + * + * \sa Logger::logger(const char *pName) + */ + Logger* logger() const; + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile int mReferenceCount; +#else + mutable QAtomicInt mReferenceCount; +#endif + mutable ClassLogger mLog4QtClassLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogObject + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle sub-classing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LogObject::LogObject(QObject *pParent) : + QObject(pParent), + mReferenceCount() + {} + + inline LogObject::~LogObject() + {} + + inline int LogObject::referenceCount() const +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + { return mReferenceCount; } +#else + { return mReferenceCount.loadAcquire(); } +#endif + + inline void LogObject::release() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { if ((q_atomic_decrement(&mReferenceCount) == 0) && !parent()) + delete(this); } +#else + { if (!mReferenceCount.deref()) + delete(this); } +#endif + + inline void LogObject::retain() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { q_atomic_increment(&mReferenceCount); } +#else + { mReferenceCount.ref(); } +#endif + + inline Logger *LogObject::logger() const + { return mLog4QtClassLogger.logger(this); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogObject, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGOBJECT_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.cpp b/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.cpp new file mode 100644 index 0000000..8084a79 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.cpp @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobjectptr.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObjectPtr + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.h b/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.h new file mode 100644 index 0000000..6a8b613 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/logobjectptr.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECTPTR_H +#define LOG4QT_LOGOBJECTPTR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +namespace Log4Qt +{ + /*! + * \brief The class LogObjectPtr implements automatic reference counting + * for LogObject objects. + */ + template + class LogObjectPtr + { + public: + /*! + * Constructs a 0 LogObject pointer. + */ + LogObjectPtr(); + + /*! + * Constructs a LogObject pointer that points to the same object then + * \a rOther. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(const LogObjectPtr &rOther); + + /*! + * Constructs a LogObject pointer that points to the object + * \a LogObject. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(T *pLogObject); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * same object that \a rOther points to. The reference counter of the + * object the LogObjectPtr pointed to before the assignment is + * decremented by one. The reference counter of the object \a rOther + * is pointing to is incremented by one. + */ + LogObjectPtr &operator=(const LogObjectPtr &rOther); + + /*! + * Destructs the object. The reference counter of the object the + * LogObjectPtr points to is decremented by one. + */ + ~LogObjectPtr(); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * object \a pLogObject. The reference counter of the object the + * LogObjectPtr pointed to before the assignment is decremented by + * one. The reference counter of the object \a pLogObject is pointing + * to is incremented by one. + */ + LogObjectPtr &operator=(T *pLogObject); + + /*! + * Arrow operator. Returns the LogObject the object points to. + */ + T *operator->() const; + + /*! + * Dereference operator. Returns a pointer to the LogObject the + * object points to. + */ + T &operator*() const; + + /*! + * Cast operator. Cast the object to the LogObject the object points + * to. + */ + operator T*() const; + + private: + void retain() const; + void release() const; + + private: + T *mpLogObject; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + template + inline LogObjectPtr::LogObjectPtr() : + mpLogObject(0) + {} + + template + inline LogObjectPtr::LogObjectPtr(const LogObjectPtr &rOther) : + mpLogObject(rOther.mpLogObject) + { retain(); } + + template + inline LogObjectPtr::LogObjectPtr(T *pLogObject) : + mpLogObject(pLogObject) + { retain(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(const LogObjectPtr &rOther) + { rOther.retain(); + release(); + mpLogObject = rOther.mpLogObject; + return *this; } + + template + inline LogObjectPtr::~LogObjectPtr() + { release(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(T *pLogObject) + { if (pLogObject) + reinterpret_cast(pLogObject)->retain(); + release(); + mpLogObject = pLogObject; + return *this; } + + template + inline T *LogObjectPtr::operator->() const + { return mpLogObject; } + + template + inline T &LogObjectPtr::operator*() const + { return *mpLogObject; } + + template + inline LogObjectPtr::operator T*() const + { return mpLogObject; } + + template + inline void LogObjectPtr::retain() const + { if (mpLogObject) + reinterpret_cast(mpLogObject)->retain(); } + + template + inline void LogObjectPtr::release() const + { + if (mpLogObject) + reinterpret_cast(mpLogObject)->release(); + } + +} // namespace Log4Qt + + +//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); // Declare within T + + +#endif // LOG4QT_LOGOBJECTPTR_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.cpp b/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.cpp new file mode 100644 index 0000000..c8dc969 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.cpp @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a problem were OptionConverter::toBoolean would not + * return the default value, if the conversion fails. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/optionconverter.h" + +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/logger.h" +#include "log4qt/consoleappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::OptionConverter) + + + + /************************************************************************** + * Class implementation: OptionConverter + **************************************************************************/ + + + QString OptionConverter::findAndSubst(const Properties &rProperties, + const QString &rKey) + { + QString value = rProperties.property(rKey); + if (value.isNull()) + return value; + + const QString begin_subst = QLatin1String("${"); + const QString end_subst = QLatin1String("}"); + const int begin_length = begin_subst.length(); + const int end_length = end_subst.length(); + + // Don't return a null string, the null string indicates that the + // property key does not exist. + QString result = QLatin1String(""); + + int i = 0; + int begin; + int end; + while (i < value.length()) + { + begin = value.indexOf(begin_subst, i); + if (begin == -1) + { + result += value.mid(i); + i = value.length(); + } + else + { + result += value.mid(i, begin - i); + end = value.indexOf(end_subst, i + begin_length); + if (end == -1) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2."), + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + "Log4Qt::OptionConverter"); + e << begin << value; + logger()->error(e); + return result; + } + else + { + result += findAndSubst(rProperties, value.mid(begin + begin_length, end - begin - end_length - 1)); + i = end + end_length; + } + } + } + return result; + } + + + QString OptionConverter::classNameJavaToCpp(const QString &rClassName) + { + const QLatin1String java_class_delimiter("."); + const QLatin1String cpp_class_delimiter("::"); + + QString result = rClassName; + return result.replace(java_class_delimiter, cpp_class_delimiter); + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool *p_ok) + { + const QLatin1String str_true("true"); + const QLatin1String str_enabled("enabled"); + const QLatin1String str_one("1"); + const QLatin1String str_false("false"); + const QLatin1String str_disabled("disabled"); + const QLatin1String str_zero("0"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == str_true || s == str_enabled || s == str_one) + return true; + if (s == str_false || s == str_disabled || s == str_zero) + return false; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a boolean"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return false; + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool default_value) + { + bool ok; + bool result = toBoolean(rOption, &ok); + if (ok) + return result; + else + return default_value; + } + + qint64 OptionConverter::toFileSize(const QString &rOption, + bool *p_ok) + { + // - Search for unit + // - Convert characters befor unit to int + // - Error, if + // - the conversion failed + // - the value < 0 + // - there is text after the unit characters + + if (p_ok) + *p_ok = false; + QString s = rOption.trimmed().toLower(); + qint64 f = 1; + int i; + i = s.indexOf(QLatin1String("kb")); + if (i >= 0) + f = 1024; + else + { + i = s.indexOf(QLatin1String("mb")); + if (i >= 0) + f = 1024 * 1024; + else + { + i = s.indexOf(QLatin1String("gb")); + if (i >= 0) + f = 1024 * 1024 * 1024; + } + } + if (i < 0) + i = s.length(); + bool ok; + qint64 value = s.left(i).toLongLong(&ok); + if (!ok || value < 0 || s.length() > i + 2) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a file size"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + if (p_ok) + *p_ok = true; + return value * f; + } + + + int OptionConverter::toInt(const QString &rOption, + bool *p_ok) + { + int value = rOption.trimmed().toInt(p_ok); + if (*p_ok) + return value; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for an integer"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + + + Level OptionConverter::toLevel(const QString &rOption, + bool *p_ok) + { + bool ok; + Level level = Level::fromString(rOption.toUpper().trimmed(), &ok); + if (p_ok) + *p_ok = ok; + if (ok) + return level; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a level"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return level; + } + + + Level OptionConverter::toLevel(const QString &rOption, + const Level &rDefaultValue) + { + bool ok; + Level result = toLevel(rOption, &ok); + if (ok) + return result; + else + return rDefaultValue; + } + + + int OptionConverter::toTarget(const QString &rOption, + bool *p_ok) + { + const QLatin1String java_stdout("system.out"); + const QLatin1String cpp_stdout("stdout_target"); + const QLatin1String java_stderr("system.err"); + const QLatin1String cpp_stderr("stderr_target"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == java_stdout || s == cpp_stdout) + return ConsoleAppender::STDOUT_TARGET; + if (s == java_stderr || s == cpp_stderr) + return ConsoleAppender::STDERR_TARGET; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a target"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return ConsoleAppender::STDOUT_TARGET; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.h b/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.h new file mode 100644 index 0000000..dda49d2 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/optionconverter.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_OPTIONCONVERTER_H +#define LOG4QT_OPTIONCONVERTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + +namespace Log4Qt +{ + class Properties; + + /*! + * \brief The class OptionConverter provides functions to convert strings + * to property values. + */ + class OptionConverter + { + private: + OptionConverter(); + OptionConverter(const OptionConverter &rOther); // Not implemented + // virtual ~OptionConverter(); // Use compiler default + OptionConverter &operator=(const OptionConverter &rOther); // Not implemented + + public: + static QString findAndSubst(const Properties &rProperties, + const QString &rKey); + + /*! + * Returns the JAVA class name \a rClassName as C++ class name by + * replacing all . characters with ::. + */ + static QString classNameJavaToCpp(const QString &rClassName); + + /*! + * Converts the option \a rOption to a boolean value. Valid strings + * for true are "true", "enabled" and "1". Valid strings + * for false are "false", "disabled" and "0". If the conversion is + * successful, the target is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and false is returned. + */ + static bool toBoolean(const QString &rOption, + bool *p_ok = 0); + + static bool toBoolean(const QString &rOption, + bool default_value); + + /*! + * Converts the option string \a rOption to a file size. The string can + * be a positive integer followed by an optional unit suffix "KB", "MB" + * or "GB". If a unit suffix is specified the the integer is + * interpreted as kilobytes, megabytes or gigabytes. If the conversion + * is successful, the size is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and 0 is returned. + */ + static qint64 toFileSize(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a integer value using + * QString::toInt(). If the conversion is successful, the integer is + * returned and \a p_ok is set to true. Otherwise an error is written + * to the log, \a p_ok is set to false and 0 is returned. + */ + static int toInt(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a level value using + * Level::fromString(). If the conversion is successful, the level + * is returned and \a p_ok is set to true. Otherwise an error is + * written to the log, \a p_ok is set to false and a level with + * the value Level::NULL_INT is returned. + * + * \sa Level::fromString() + */ + static Level toLevel(const QString &rOption, + bool *p_ok = 0); + + static Level toLevel(const QString &rOption, + const Level &rDefaultValue); + + /*! + * Converts the option \a rOption to a ConsoleAppender::Target value. + * Valid strings for \a rOption are "System.out", "STDOUT_TARGET", + * "System.err" and "STDERR_TARGET". If the conversion is successful, + * the target is returned and \a p_ok is set to true. Otherwise an + * error is written to the log, \a p_ok is set to false and + * ConsoleAppender::STDOUT_TARGET is returned. + */ + static int toTarget(const QString &rOption, + bool *p_ok = 0); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::OptionConverter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_OPTIONCONVERTER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.cpp b/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.cpp new file mode 100644 index 0000000..1fd54f0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.cpp @@ -0,0 +1,893 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in LiteralPatternConverter::convert. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/patternformatter.h" + +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + /*! + * \brief The class FormattingInfo stores the formatting modifier for a + * pattern converter. + * + * \sa PatternConverter + */ + class FormattingInfo + { + public: + FormattingInfo() + { clear(); } + // FormattingInfo(const FormattingInfo &rOther); // Use compiler default + // virtual ~FormattingInfo(); // Use compiler default + // FormattingInfo &operator=(const FormattingInfo &rOther); // Use compiler default + + void clear(); + static QString intToString(int i); + + public: + int mMinLength; + int mMaxLength; + bool mLeftAligned; + }; + + + /*! + * \brief The class PatternConverter is the abstract base class for all + * pattern converters. + * + * PatternConverter handles the minimum and maximum modifier for a + * conversion character. The actual conversion is by calling the + * convert() member function of the derived class. + * + * \sa PatternLayout::format() + */ + class PatternConverter + { + public: + PatternConverter(const FormattingInfo &rFormattingInfo = FormattingInfo()) : + mFormattingInfo(rFormattingInfo) + {}; + virtual ~PatternConverter() + {}; + private: + PatternConverter(const PatternConverter &rOther); // Not implemented + PatternConverter &operator=(const PatternConverter &rOther); // Not implemented + + public: + void format(QString &rFormat, const LoggingEvent &rLoggingEvent) const; + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const = 0; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + protected: + FormattingInfo mFormattingInfo; + }; + + + /*! + * \brief The class BasicPatternConverter converts several members of a + * LoggingEvent to a string. + * + * BasicPatternConverter is used by PatternLayout to convert members that + * do not reuquire additional formatting to a string as part of formatting + * the LoggingEvent. It handles the following conversion characters: + * 'm', 'p', 't', 'x' + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class BasicPatternConverter : public PatternConverter + { + public: + enum Type { + MESSAGE_CONVERTER, + NDC_CONVERTER, + LEVEL_CONVERTER, + THREAD_CONVERTER, + }; + + public: + BasicPatternConverter(const FormattingInfo &rFormattingInfo, + Type type) : + PatternConverter(rFormattingInfo), + mType(type) + {}; + // virtual ~BasicPatternConverter(); // Use compiler default + private: + BasicPatternConverter(const BasicPatternConverter &rOther); // Not implemented + BasicPatternConverter &operator=(const BasicPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + Type mType; + }; + + + /*! + * \brief The class DatePatternConverter converts the time stamp of a + * LoggingEvent to a string. + * + * DatePatternConverter is used by PatternLayout to convert the time stamp + * of a LoggingEvent to a string as part of formatting the LoggingEvent. + * It handles the 'd' and 'r' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class DatePatternConverter : public PatternConverter + { + public: + DatePatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rFormat) : + PatternConverter(rFormattingInfo), + mFormat(rFormat) + {}; + // virtual ~DatePatternConverter(); // Use compiler default + private: + DatePatternConverter(const DatePatternConverter &rOther); // Not implemented + DatePatternConverter &operator=(const DatePatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mFormat; + }; + + + /*! + * \brief The class LiteralPatternConverter provides string literals. + * + * LiteralPatternConverter is used by PatternLayout to embed string + * literals as part of formatting the LoggingEvent. It handles string + * literals and the 'n' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LiteralPatternConverter : public PatternConverter + { + public: + LiteralPatternConverter(const QString &rLiteral) : + PatternConverter(), + mLiteral(rLiteral) + {}; + // virtual ~LiteralPatternConverter(); // Use compiler default + private: + LiteralPatternConverter(const LiteralPatternConverter &rOther); // Not implemented + LiteralPatternConverter &operator=(const LiteralPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mLiteral; + }; + + + /*! + * \brief The class LoggerPatternConverter converts the Logger name of a + * LoggingEvent to a string. + * + * LoggerPatternConverter is used by PatternLayout to convert the Logger + * name of a LoggingEvent to a string as part of formatting the + * LoggingEvent. It handles the 'c' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LoggerPatternConverter : public PatternConverter + { + public: + LoggerPatternConverter(const FormattingInfo &rFormattingInfo, + int precision) : + PatternConverter(rFormattingInfo), + mPrecision(precision) + {}; + // virtual ~LoggerPatternConverter(); // Use compiler default + private: + LoggerPatternConverter(const LoggerPatternConverter &rOther); // Not implemented + LoggerPatternConverter &operator=(const LoggerPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + int mPrecision; + }; + + + + /*! + * \brief The class MDCPatternConverter converts the MDC data of a + * LoggingEvent to a string. + * + * MDCPatternConverter is used by PatternLayout to convert the MDC data of + * a LoggingEvent to a string as part of formatting the LoggingEvent. It + * handles the 'X' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class MDCPatternConverter : public PatternConverter + { + public: + MDCPatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rKey) : + PatternConverter(rFormattingInfo), + mKey(rKey) + {}; + // virtual ~MDCPatternConverter(); // Use compiler default + private: + MDCPatternConverter(const MDCPatternConverter &rOther); // Not implemented + MDCPatternConverter &operator=(const MDCPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mKey; + }; + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const FormattingInfo &rFormattingInfo); + #endif + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PatternFormatter) + + + + /************************************************************************** + * Class implementation: PatternFormatter + **************************************************************************/ + + + PatternFormatter::PatternFormatter(const QString &rPattern) : + mIgnoreCharacters(QLatin1String("CFlLM")), + mConversionCharacters(QLatin1String("cdmprtxX")), + mOptionCharacters(QLatin1String("cd")), + mPattern(rPattern), + mPatternConverters() + { + parse(); + } + + + PatternFormatter::~PatternFormatter() + { + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + delete p_converter; + } + + + QString PatternFormatter::format(const LoggingEvent &rLoggingEvent) const + { + QString result; + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + p_converter->format(result, rLoggingEvent); + return result; + } + + + bool PatternFormatter::addDigit(const QChar &rDigit, + int &rValue) + { + if (!rDigit.isDigit()) + return false; + + int digit_value = rDigit.digitValue(); + if (rValue > (INT_MAX - digit_value) / 10) + rValue = INT_MAX; + else + rValue = rValue * 10 + digit_value; + return true; + } + + + void PatternFormatter::createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption) + { + Q_ASSERT_X(mConversionCharacters.indexOf(rChar) >= 0, "PatternFormatter::createConverter", "Unknown conversion character" ); + + LogError e("Creating Converter for character '%1' min %2, max %3, left %4 and option '%5'"); + e << QString(rChar) + << FormattingInfo::intToString(rFormattingInfo.mMinLength) + << FormattingInfo::intToString(rFormattingInfo.mMaxLength) + << rFormattingInfo.mLeftAligned + << rOption; + logger()->trace(e); + + switch (rChar.toLatin1()) + { + case 'c': + mPatternConverters << new LoggerPatternConverter(rFormattingInfo, + parseIntegerOption(rOption)); + break; + case 'd': + { + QString option = rOption; + if (rOption.isEmpty()) + option = QLatin1String("ISO8601"); + mPatternConverters << new DatePatternConverter(rFormattingInfo, + option); + break; + } + case 'm': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::MESSAGE_CONVERTER); + break; + case 'p': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::LEVEL_CONVERTER); + break; + case 'r': + mPatternConverters << new DatePatternConverter(rFormattingInfo, + QLatin1String("RELATIVE")); + break; + case 't': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::THREAD_CONVERTER); + break; + case 'x': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::NDC_CONVERTER); + break; + case 'X': + mPatternConverters << new MDCPatternConverter(rFormattingInfo, + rOption); + break; + default: + Q_ASSERT_X(false, "PatternFormatter::createConverter", "Unknown pattern character"); + } + } + + + void PatternFormatter::createLiteralConverter(const QString &rLiteral) + { + logger()->trace("Creating literal LiteralConverter with Literal '%1'", + rLiteral); + mPatternConverters << new LiteralPatternConverter(rLiteral); + } + + + void PatternFormatter::parse() + { + enum State { + LITERAL_STATE, + ESCAPE_STATE, + MIN_STATE, + DOT_STATE, + MAX_STATE, + CHARACTER_STATE, + POSSIBLEOPTION_STATE, + OPTION_STATE + }; + + int i = 0; + QChar c; + char ch; + State state = LITERAL_STATE; + FormattingInfo formatting_info; + QString literal; + int converter_start = 0; + int option_start = 0; + while (i < mPattern.length()) + { + // i points to the current character + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character + // continue is used to change state without consuming the character + + c = mPattern.at(i); + ch = c.toLatin1(); + switch (state) + { + case LITERAL_STATE: + if (ch == '%') + { + formatting_info.clear(); + converter_start = i; + state = ESCAPE_STATE; + } else + literal += c; + break; + case ESCAPE_STATE: + if (ch == '%') + { + literal += c; + state = LITERAL_STATE; + } + else if (ch == 'n') + { + literal += Layout::endOfLine(); + state = LITERAL_STATE; + } + else + { + if (!literal.isEmpty()) + { + createLiteralConverter(literal); + literal.clear(); + } + if (ch == '-') + formatting_info.mLeftAligned = true; + else if (c.isDigit()) + { + formatting_info.mMinLength = c.digitValue(); + state = MIN_STATE; + } + else if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case MIN_STATE: + if (!addDigit(c, formatting_info.mMinLength)) + { + if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case DOT_STATE: + if (c.isDigit()) + { + formatting_info.mMaxLength = c.digitValue(); + state = MAX_STATE; + } + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + LAYOUT_EXPECTED_DIGIT_ERROR, + "Log4Qt::PatternFormatter"); + e << QString(c); + logger()->error(e); + } + break; + case MAX_STATE: + if (!addDigit(c, formatting_info.mMaxLength)) + { + state = CHARACTER_STATE; + continue; + } + break; + case CHARACTER_STATE: + if (mIgnoreCharacters.indexOf(c) >= 0) + state = LITERAL_STATE; + else if (mOptionCharacters.indexOf(c) >= 0) + state = POSSIBLEOPTION_STATE; + else if (mConversionCharacters.indexOf(c) >= 0) + { + createConverter(c, formatting_info); + state = LITERAL_STATE; + } + else + { + logger()->warn("Invalid conversion character '%1' at %2 in pattern '%3'", + c, i, mPattern); + createLiteralConverter(mPattern.mid(converter_start, i - converter_start + 1)); + state = LITERAL_STATE; + } + break; + case POSSIBLEOPTION_STATE: + if (ch == '{') + { + option_start = i; + state = OPTION_STATE; + } + else + { + createConverter(mPattern.at(i - 1), + formatting_info); + state = LITERAL_STATE; + continue; + } + break; + case OPTION_STATE: + if (ch == '}') + { + createConverter(mPattern.at(option_start - 1), + formatting_info, + mPattern.mid(option_start + 1, i - option_start - 1)); + state = LITERAL_STATE; + } + break; + default: + Q_ASSERT_X(false, "PatternFormatter::parse()", "Unknown parsing state constant"); + state = LITERAL_STATE; + } + i++; + } + + if (state != LITERAL_STATE) + { + logger()->warn("Unexptected end of pattern '%1'", mPattern); + if (state == ESCAPE_STATE) + literal += c; + else + literal += mPattern.mid(converter_start); + } + + if (!literal.isEmpty()) + createLiteralConverter(literal); + } + + + int PatternFormatter::parseIntegerOption(const QString &rOption) + { + if (rOption.isEmpty()) + return 0; + + bool ok; + int result = rOption.toInt(&ok); + if (!ok) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option '%1' cannot be converted into an integer"), + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + "Log4Qt::PatterFormatter"); + e << rOption; + logger()->error(e); + } + if (result < 0) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option %1 isn't a positive integer"), + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + "Log4Qt::PatterFormatter"); + e << result; + logger()->error(e); + result = 0; + } + return result; + } + + + /************************************************************************** + * Class implementation: FormattingInfo + **************************************************************************/ + + + void FormattingInfo::clear() + { + mMinLength = 0; + mMaxLength = INT_MAX; + mLeftAligned = false; + }; + + + QString FormattingInfo::intToString(int i) + { + if (i == INT_MAX) + return QLatin1String("INT_MAX"); + else + return QString::number(i); + } + + + + /************************************************************************** + * Class implementation: PatternConverter + **************************************************************************/ + + + void PatternConverter::format(QString &rFormat, const LoggingEvent &rLoggingEvent) const + { + const QLatin1Char space(' '); + QString s = convert(rLoggingEvent); + + if (s.length() > mFormattingInfo.mMaxLength) + rFormat += s.left(mFormattingInfo.mMaxLength); + else if (mFormattingInfo.mLeftAligned) + rFormat += s.leftJustified(mFormattingInfo.mMinLength, space, false); + else + rFormat += s.rightJustified(mFormattingInfo.mMinLength, space, false); + } + + + + /************************************************************************** + * Class implementation: BasicPatternConverter + **************************************************************************/ + + + QString BasicPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + switch (mType) + { + case MESSAGE_CONVERTER: + return rLoggingEvent.message(); + break; + case NDC_CONVERTER: + return rLoggingEvent.ndc(); + break; + case LEVEL_CONVERTER: + return rLoggingEvent.level().toString(); + break; + case THREAD_CONVERTER: + return rLoggingEvent.threadName(); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::convert()", "Unkown type constant"); + return QString(); + } + } + + + QDebug BasicPatternConverter::debug(QDebug &rDebug) const + { + QString type; + switch (mType) + { + case MESSAGE_CONVERTER: + type = QLatin1String("MESSAGE_CONVERTER"); + break; + case NDC_CONVERTER: + type = QLatin1String("NDC_CONVERTER"); + break; + case LEVEL_CONVERTER: + type = QLatin1String("LEVEL_CONVERTER"); + break; + case THREAD_CONVERTER: + type = QLatin1String("THREAD_CONVERTER"); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::debug()", "Unkown type constant"); + } + rDebug.nospace() << "BasicPatternConverter(" + << mFormattingInfo + << "type:" << type + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: DatePatternConverter + **************************************************************************/ + + + QString DatePatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()).toString(mFormat); + } + + + QDebug DatePatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DatePatternConverter(" + << mFormattingInfo + << "format:" << mFormat + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LiteralPatternConverter + **************************************************************************/ + + + QString LiteralPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + Q_UNUSED(rLoggingEvent); + return mLiteral; + }; + + + QDebug LiteralPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LiteralPatternConverter(" + << mFormattingInfo + << "literal:" << mLiteral + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LoggerPatternConverter + **************************************************************************/ + + + QString LoggerPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + if (!rLoggingEvent.logger()) + return QString(); + QString name = rLoggingEvent.logger()->name(); + if (mPrecision <= 0 || (name.isEmpty())) + return name; + + const QString separator(QLatin1String("::")); + + int i = mPrecision; + int begin = name.length(); + while ((i > 0) && (begin >= 0)) + { + begin = name.lastIndexOf(separator, begin - name.length() - 1); + i--; + } + if (begin < 0) + begin = 0; + else + begin += 2; + return name.mid(begin); + } + + + QDebug LoggerPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LoggerPatternConverter(" + << mFormattingInfo + << "precision:" << mPrecision + << ")"; + return rDebug.space(); + } + + + + /****************************************************************************** + * Class implementation: MDCPatternConverter + ******************************************************************************/ + + + QString MDCPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return rLoggingEvent.mdc().value(mKey); + }; + + + QDebug MDCPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "MDCPatternConverter(" + << mFormattingInfo + << "key:" << mKey + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternFormatter &rPatternFormatter) + { + debug.nospace() << "PatternFormatter(" + << "pattern:" << rPatternFormatter.mPattern << " " + << "converters:("; + int i; + for (i = 0; i < rPatternFormatter.mPatternConverters.size(); i++) + { + if (i > 0) + debug.nospace() << ", "; + debug.nospace() << *rPatternFormatter.mPatternConverters.at(i); + } + debug.nospace() << ") )"; + return debug.space(); + } + #endif + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const FormattingInfo &rFormattingInfo) + { + debug.nospace() << "FormattingInfo(" + << "min:" << FormattingInfo::intToString(rFormattingInfo.mMinLength) << " " + << "max:" << FormattingInfo::intToString(rFormattingInfo.mMaxLength) << " " + << "left:" << rFormattingInfo.mLeftAligned + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternConverter &rPatternConverter) + { + return rPatternConverter.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.h b/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.h new file mode 100644 index 0000000..8965e81 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/patternformatter.h @@ -0,0 +1,195 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNFORMATTER_H +#define LOG4QT_PATTERNFORMATTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class FormattingInfo; + class PatternConverter; + class LoggingEvent; + + /*! + * \brief The class PatternFormatter formats a logging event based on a + * pattern string. + * + * The class PatternFormatter formats a LoggingEvent base on a pattern + * string. It is used by the patternLayout and TTCCLayout class to + * implement the formatting. + * + * On object construction the provided patterns tring is parsed. Based on + * the information found a chain of PatternConverter is created. Each + * PatternConverter handles a certain member of a LoggingEvent. + * + * \sa PatternLayout::format() + * \sa TTCCLayout::format() + */ + class PatternFormatter + { + public: + /*! + * Creates a PatternFormatter using a the specified \a rPattern. + */ + PatternFormatter(const QString &rPattern); + + /*! + * Destroys the PatternFormatter and all PatternConverter. + */ + virtual ~PatternFormatter(); + + private: + PatternFormatter(const PatternFormatter &rOther); // Not implemented + PatternFormatter &operator=(const PatternFormatter &rOther); // Not implemented + + public: + /*! + * Formats the given \a rLoggingEvent using the chain of + * PatternConverter created during construction from the specified + * pattern. + */ + QString format(const LoggingEvent &rLoggingEvent) const; + + private: + /*! + * If the character \a rDigit is a digit the digit is added to the + * integer \a rValue and the function returns true. Otherwise the + * function returns false. + * + * The function adds the digit by multiplying the existing value + * with ten and adding the numerical value of the digit. If the + * maximum integer value would be exceeded by the operation + * \a rValue is set to INT_MAX. + */ + bool addDigit(const QChar &rDigit, + int &rValue); + + /*! + * Creates a PatternConverter based on the specified conversion + * character \a rChar, the formatting information + * \a rFormattingInfo and the option \a rOption. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption = QString()); + + /*! + * Creates a LiteralPatternConverter with the string literal + * \a rLiteral. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createLiteralConverter(const QString &rLiteral); + + /*! + * Parses the pattern string specified on construction and creates + * PatternConverter according to it. + */ + void parse(); + + /*! + * Parses an integer option from an option string. If the string is + * not a valid integer or the integer value is less then zero, zero + * is returned. Returns the end of line seperator for the operating + * system. + */ + int parseIntegerOption(const QString &rOption); + + private: + const QString mIgnoreCharacters; + const QString mConversionCharacters; + const QString mOptionCharacters; + QString mPattern; + QList mPatternConverters; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug, const PatternFormatter &rPatternFormatter); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PatternFormatter + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %PatternFormatter(pattern:"%r [%t] %p %c %x - %m%n" + * converters:( + * DatePatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) format: "RELATIVE" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " [" ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "THREAD_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "] " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "LEVEL_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * LoggerPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) precision: 0 ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "NDC_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " - " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "MESSAGE_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "" ) ) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PatternFormatter &rPatternFormatter); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::PatternFormatter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PATTERNFORMATTER_H diff --git a/GC-3.6.1-T2/src/log4qt/helpers/properties.cpp b/GC-3.6.1-T2/src/log4qt/helpers/properties.cpp new file mode 100644 index 0000000..ec74978 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/properties.cpp @@ -0,0 +1,364 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/properties.h" + +#include +#include +#include +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties) + + + + /************************************************************************** + * Class implementation: Properties + **************************************************************************/ + + + void Properties::load(QIODevice *pDevice) + { + const QLatin1Char append_char(msEscapeChar); + + if (!pDevice) + { + logger()->warn("No device specified for load."); + return; + } + + QTextStream stream(pDevice); + QString line; + int line_number = 0; + QString property; + int property_start_line = 1; + + do { + line = trimLeft(stream.readLine()); + line_number++; + + if (!line.isEmpty() && line.at(line.length() - 1) == append_char) + property += line.left(line.length() - 1); + else + { + property += line; + parseProperty(property, property_start_line); + property.clear(); + property_start_line = line_number + 1; + } + } + while (!line.isNull()); + } + + + void Properties::load(const QSettings &rSettings) + { + QStringList keys = rSettings.childKeys(); + QString key; + Q_FOREACH(key, keys) + insert(key, rSettings.value(key).toString()); + } + + + QString Properties::property(const QString &rKey) const + { + // Null string indicates the property does not contain the key. + + if (contains(rKey)) + { + QString value = this->value(rKey); + if (value.isNull()) + return QString(QLatin1String("")); + else + return value; + } + + if (mpDefaultProperties) + return mpDefaultProperties->property(rKey); + else + return QString(); + } + + + QString Properties::property(const QString &rKey, + const QString &rDefaultValue) const + { + QString value = property(rKey); + if (value.isNull()) + return rDefaultValue; + else + return value; + } + + + QStringList Properties::propertyNames() const + { + QStringList default_keys; + if (mpDefaultProperties) + default_keys = mpDefaultProperties->propertyNames(); + + QStringList keys = this->keys(); + QString key; + Q_FOREACH(key, default_keys) + if (!keys.contains(key)) + keys << key; + + return keys; + } + + + void Properties::parseProperty(const QString &rProperty, + int line) + { + Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces"); + + enum State + { + KEY_STATE, + KEYSPACE_STATE, + SPACEVALUE_STATE, + VALUE_STATE, + KEYESCAPE_STATE, + VALUEESCAPE_STATE, + UNICODEESCAPE_STATE + }; + const QString value_escape_codes =QLatin1String(msValueEscapeCodes); + const QString value_escape_chars = QLatin1String(msValueEscapeChars); + Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map"); + const QString key_escape_codes = QLatin1String(msKeyEscapeCodes); + const QString key_escape_chars = QLatin1String(msKeyEscapeChars); + Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map"); + + if (rProperty.isEmpty()) + return; + + int i = 0; + QChar c; + char ch; + State state = KEY_STATE; + QString key; + QString value; + QString *p_string = &key; + uint ucs = 0; + int ucs_digits = 0; + while (i < rProperty.length()) + { + // i points to the current character. + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character. + // continue is used to change state without consuming the character + + c = rProperty.at(i); + ch = c.toLatin1(); + + switch (state) + { + case KEY_STATE: + if (ch == '!' || ch == '#' ) + return; + else if (c.isSpace()) + { + p_string = &value; + state = KEYSPACE_STATE; + } + else if (ch == '=' || ch == ':') + { + p_string = &value; + state = SPACEVALUE_STATE; + } + else if (ch == msEscapeChar) + state = KEYESCAPE_STATE; + else + *p_string += c; + break; + case KEYSPACE_STATE: + if (ch == '=' || ch == ':') + state = SPACEVALUE_STATE; + else if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case SPACEVALUE_STATE: + if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case VALUE_STATE: + if (ch == msEscapeChar) + state = VALUEESCAPE_STATE; + else + *p_string += c; + break; + case KEYESCAPE_STATE: + { + int convert = key_escape_codes.indexOf(c); + if (convert >= 0) + *p_string += key_escape_chars.at(convert); + else + { + logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2", + QString(c), + line); + *p_string += c; + } + state = KEY_STATE; + break; + } + case VALUEESCAPE_STATE: + { + int convert = value_escape_codes.indexOf(c); + if (convert >= 0) + { + *p_string += value_escape_chars.at(convert); + state = VALUE_STATE; + } + else if (ch == 'u') + { + ucs = 0; + ucs_digits = 0; + state = UNICODEESCAPE_STATE; + } + else + { + logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line); + *p_string += c; + state = VALUE_STATE; + } + break; + } + case UNICODEESCAPE_STATE: + { + int hex = hexDigitValue(c); + if (hex >= 0) + { + ucs = ucs * 16 + hex; + ucs_digits++; + if (ucs_digits == 4 || i == rProperty.length() - 1) + { + *p_string += QChar(ucs); + state = VALUE_STATE; + } + } + else + { + if (ucs_digits > 0) + *p_string += QChar(ucs); + state = VALUE_STATE; + continue; + } + break; + } + default: + Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant"); + return; + } + i++; + } + + if (key.isEmpty() && !value.isEmpty()) + logger()->warn("Found value with no key in property starting at line %1", line); + + logger()->trace("Loaded property '%1' : '%2'", key, value); + insert(key, value); + } + + + int Properties::hexDigitValue(const QChar &rDigit) + { + bool ok; + int result = QString(rDigit).toInt(&ok, 16); + if (!ok) + return -1; + else + return result; + } + + + QString Properties::trimLeft(const QString &rLine) + { + int i = 0; + while (i < rLine.length() && rLine.at(i).isSpace()) + i++; + return rLine.right(rLine.length() - i); + } + + + const char Properties::msEscapeChar ='\\'; + const char *Properties::msValueEscapeCodes = "tnr\\\"\' "; + const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' "; + const char *Properties::msKeyEscapeCodes = " :="; + const char *Properties::msKeyEscapeChars = " :="; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Properties &rProperties) + { + debug.nospace() << "Properties(" + << "default:" << rProperties.defaultProperties() << " " + << "properties:" << *reinterpret_cast *>(&rProperties) + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/helpers/properties.h b/GC-3.6.1-T2/src/log4qt/helpers/properties.h new file mode 100644 index 0000000..a9601f4 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/helpers/properties.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.h + * created: September + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTIES_H +#define LOG4QT_PROPERTIES_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QIODevice; +class QSettings; + + +namespace Log4Qt +{ + /*! + * \brief The class Properties implements a JAVA property hash. + */ + class Properties : public QHash + { + public: + Properties(Properties *pDefaultProperties = 0); + // virtual ~Properties(); // Use compiler default + // Properties(const Properties &rOther); // Use compiler default + // Properties &operator=(const Properties &rOther); // Not implemented + + public: + Properties *defaultProperties() const; + QString property(const QString &rKey) const; + QString property(const QString &rKey, + const QString &rDefaultValue) const; + void setDefaultProperties(Properties *pDefault); + void setProperty(const QString &rKey, + const QString &rValue); + + // JAVA: void list(QTextStream &rTextStream); + void load(QIODevice *pDevice); + + /*! + * Reads all child keys from the QSettings object \a rSettings and + * inserts them into this object. The value is created using + * QVariant::toString(). Types that do not support toString() are + * resulting in an empty string. + * + * \code + * QSettings settings; + * settings.setValue("Package", "Full"); + * settings.setValue("Background", Qt::white); + * settings.setValue("Support", true); + * settings.setValue("Help/Language", "en_UK"); + * + * Properties properties + * properties.load(&settings) + * + * // properties (("Package", "Full"), ("Background", ""), ("Support", "true")) + * \endcode + */ + void load(const QSettings &rSettings); + + QStringList propertyNames() const; + // JAVA: void save(QIODevice *pDevice) const; + + private: + void parseProperty(const QString &rProperty, + int line); + static int hexDigitValue(const QChar &rDigit); + static QString trimLeft(const QString &rString); + + private: + Properties *mpDefaultProperties; + static const char msEscapeChar; + static const char *msValueEscapeCodes; + static const char *msValueEscapeChars; + static const char *msKeyEscapeCodes; + static const char *msKeyEscapeChars; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Properties + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Properties(default:0x0 properties:QHash(("log4j.appender.testAppender.layout", "org.apache.log4j.PatternLayout ") + * ("log4j.appender.testAppender.layout.ConversionPattern", "[%t] %-5p %l: %m%n") + * ("log4j.appender.testAppender.Append", "false ") + * ("log4j.appender.testAppender.File", "output/temp ") + * ("log4j.rootCategory", "TRACE, testAppender") + * ("log4j.appender.testAppender", "org.apache.log4j.FileAppender")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Properties &rProperties); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Properties::Properties(Properties *pDefaultProperties) : + mpDefaultProperties(pDefaultProperties) + {} + + inline Properties *Properties::defaultProperties() const + { return mpDefaultProperties; } + + inline void Properties::setDefaultProperties(Properties *pDefaultProperties) + { mpDefaultProperties = pDefaultProperties; } + + inline void Properties::setProperty(const QString &rKey, + const QString &rValue) + { insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::Properties, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PROPERTIES_H diff --git a/GC-3.6.1-T2/src/log4qt/hierarchy.cpp b/GC-3.6.1-T2/src/log4qt/hierarchy.cpp new file mode 100644 index 0000000..ef93d55 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/hierarchy.cpp @@ -0,0 +1,213 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/hierarchy.h" + +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LoggerRepository) + + + + /************************************************************************** + * Class implementation: Hierarchy + **************************************************************************/ + + + Hierarchy::Hierarchy() : +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mLoggers(), + mThreshold(Level::NULL_INT), + mpRootLogger(logger(QString())) + { + Q_UNUSED(mHandleQtMessages); + // Store root logger to allow rootLogger() to be const + } + + + Hierarchy::~Hierarchy() + { + static_logger()->warn("Unexpected destruction of Hierarchy"); + + // QWriteLocker locker(&mObjectGuard); + // + // resetConfiguration(); + // clear(); + // delete mpRootLogger; + } + + + bool Hierarchy::exists(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.contains(rName); + } + + + Logger *Hierarchy::logger(const QString &rName) + { + QWriteLocker locker(&mObjectGuard); + + return createLogger(rName); + } + + + QList Hierarchy::loggers() const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.values(); + } + + + void Hierarchy::setThreshold(const QString &rThreshold) + { + setThreshold(Level::fromString(rThreshold)); + } + + + void Hierarchy::resetConfiguration() + { + QWriteLocker locker(&mObjectGuard); + + // Reset all loggers. + // Leave log, qt and root logger to the last to allow debugging of shutdown. + + Logger *p_logging_logger = logger(QLatin1String("Log4Qt")); + Logger *p_qt_logger = logger(QLatin1String("Qt")); + Logger *p_root_logger = rootLogger(); + + Logger *p_logger; + Q_FOREACH(p_logger, mLoggers) + { + if ((p_logger == p_logging_logger) || (p_logger == p_qt_logger) || (p_logger == p_root_logger)) + continue; + resetLogger(p_logger, Level::NULL_INT); + } + resetLogger(p_qt_logger, Level::NULL_INT); + resetLogger(p_logging_logger, Level::NULL_INT); + resetLogger(p_root_logger, Level::DEBUG_INT); + } + + + void Hierarchy::shutdown() + { + static_logger()->debug("Shutting down Hierarchy"); + resetConfiguration(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Hierarchy::debug(QDebug &rDebug) const + { + rDebug.nospace() << "Hierarchy(" + << "loggers:" << loggers().count() << " " + << "threshold:" << threshold().toString() << " " + << "root-level:" << rootLogger()->level().toString() << " " + << "root-appenders:" << rootLogger()->appenders().count() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + Logger *Hierarchy::createLogger(const QString &rName) + { + // Q_ASSERT_X(, "Hierarchy::createLogger", "Lock must be held by caller") + + const QString name_separator = QLatin1String("::"); + + Logger *p_logger = mLoggers.value(rName, 0); + if (p_logger != 0) + return p_logger; + + if (rName.isEmpty()) + { + p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), 0); + mLoggers.insert(QString(), p_logger); + return p_logger; + } + QString parent_name; + int index = rName.lastIndexOf(name_separator); + if (index >=0) + parent_name = rName.left(index); + p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name)); + mLoggers.insert(rName, p_logger); + return p_logger; + } + + + void Hierarchy::resetLogger(Logger *pLogger, Level level) const + { + // Q_ASSERT_X(, "Hierarchy::resetLogger", "Lock must be held by caller") + + pLogger->removeAllAppenders(); + pLogger->setAdditivity(true); + pLogger->setLevel(level); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/hierarchy.h b/GC-3.6.1-T2/src/log4qt/hierarchy.h new file mode 100644 index 0000000..18a90eb --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/hierarchy.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HIERARCHY_H +#define LOG4QT_HIERARCHY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/loggerrepository.h" + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Hierarchy implements a logger repository. + * + * \note All the functions declared in this class are thread-safe. + */ + class Hierarchy : public LoggerRepository + { + public: + Hierarchy(); + // Hierarchy(const Hierarchy &rOther); // Use compiler default + virtual ~Hierarchy(); + // Hierarchy &operator=(const Hierarchy &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const; + virtual Logger *logger(const QString &rName); + virtual QList loggers() const; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual Logger *rootLogger() const; + virtual Level threshold() const; + virtual void setThreshold(Level level); + virtual void setThreshold(const QString &rThreshold); + + // JAVA: void clear(); + virtual bool isDisabled(Level level); + virtual void resetConfiguration(); + virtual void shutdown(); + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + // JAVA: void addRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + // JAVA: QHash getRendererMap() const; + // JAVA: setRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Hierarchy(loggers:6 threshold:"ALL" root-level:"DEBUG" root-appenders:0) + * + * \sa QDebug, operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rdebug) const; +#endif + + private: + Logger *createLogger(const QString &rName); + void resetLogger(Logger *pLogger, Level level) const; + + private: + mutable QReadWriteLock mObjectGuard; + QHash mLoggers; + volatile bool mHandleQtMessages; + Level mThreshold; + Logger *mpRootLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Logger *Hierarchy::rootLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpRootLogger; } + + inline Level Hierarchy::threshold() const + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void Hierarchy::setThreshold(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool Hierarchy::isDisabled(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return level < mThreshold; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Hierarchy, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_HIERARCHY_H diff --git a/GC-3.6.1-T2/src/log4qt/layout.cpp b/GC-3.6.1-T2/src/log4qt/layout.cpp new file mode 100644 index 0000000..160f80d --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/layout.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/layout.h" + +#include +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" + + + +namespace Log4Qt +{ + + + /*************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Layout + **************************************************************************/ + + + QString Layout::contentType() const + { + return QString::fromLatin1("text/plain"); + } + + + void Layout::activateOptions() + { + } + + + QString Layout::endOfLine() + { + // There seams to be no function in Qt for this + +#ifdef Q_OS_WIN32 + return QLatin1String("\r\n"); +#endif // Q_OS_WIN32 +//#ifdef Q_OS_MAC +// return QLatin1String("\r"); +//#endif // Q_OS_MAC + return QLatin1String("\n"); + } + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/layout.h b/GC-3.6.1-T2/src/log4qt/layout.h new file mode 100644 index 0000000..42f3b3e --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/layout.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LAYOUT_H +#define LOG4QT_LAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Layout is the base class for all layouts. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class Layout : public LogObject + { + Q_OBJECT + + /*! + * The property holds the content type of the layout. + * + * \sa contentType() + */ + Q_PROPERTY(QString footercontentType READ contentType) + /*! + * The property holds the footer used by the layout. + * + * \sa footer(), setFooter() + */ + Q_PROPERTY(QString footer READ footer WRITE setFooter) + /*! + * The property holds the header used by the layout. + * + * \sa header(), setHeader() + */ + Q_PROPERTY(QString header READ header WRITE setHeader) + + public: + Layout(QObject *pParent = 0); + virtual ~Layout(); + private: + Layout(const Layout &rOther); // Not implemented + Layout &operator=(const Layout &rOther); // Not implemented + + public: + virtual QString contentType() const; + QString footer() const; + QString header() const; + // JAVA: virtual bool ignoresThrowable() const; + QString name() const; + void setFooter(const QString &rFooter); + void setHeader(const QString &rHeader); + void setName(const QString &rName); + // JAVA: void setIgnoresThrowable(bool) const; + + virtual void activateOptions(); + virtual QString format(const LoggingEvent &rEvent) = 0; + + /*! + * Returns the end of line seperator for the operating system. + * + * Windows: \\r\\n + * Mac: \\r + * UNIX: \\n + */ + static QString endOfLine(); + + // Member variables + private: + QString mFooter; + QString mHeader; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Layout::Layout(QObject *pParent) : + LogObject(pParent) + {} + + inline Layout::~Layout() + {} + + inline QString Layout::footer() const + { return mFooter; } + + inline QString Layout::header() const + { return mHeader; } + + inline QString Layout::name() const + { return objectName(); } + + inline void Layout::setFooter(const QString &rFooter) + { mFooter = rFooter; } + + inline void Layout::setHeader(const QString &rHeader) + { mHeader = rHeader; } + + inline void Layout::setName(const QString &rName) + { setObjectName(rName); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Layout, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LAYOUT_H diff --git a/GC-3.6.1-T2/src/log4qt/level.cpp b/GC-3.6.1-T2/src/log4qt/level.cpp new file mode 100644 index 0000000..a55038f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/level.cpp @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/level.h" + +#include +#include +#include +#include "log4qt/logger.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Level) + + + + /************************************************************************** + * Class implementation: Level + **************************************************************************/ + + + int Level::syslogEquivalent() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + switch (mValue) + { + case NULL_INT: + case ALL_INT: + case TRACE_INT: + case DEBUG_INT: + return 7; + case INFO_INT: + return 6; + case WARN_INT: + return 4; + case ERROR_INT: + return 3; + case FATAL_INT: + case OFF_INT: + return 0; + default: + Q_ASSERT_X(false, "Level::syslogEquivalent()", "Unknown level value"); + return 7; + } + } + + + QString Level::toString() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + const char *p_context = "Level"; + + switch (mValue) + { + case NULL_INT: + return QCoreApplication::translate(p_context, "NULL"); + case ALL_INT: + return QCoreApplication::translate(p_context, "ALL"); + case TRACE_INT: + return QCoreApplication::translate(p_context, "TRACE"); + case DEBUG_INT: + return QCoreApplication::translate(p_context, "DEBUG"); + case INFO_INT: + return QCoreApplication::translate(p_context, "INFO"); + case WARN_INT: + return QCoreApplication::translate(p_context, "WARN"); + case ERROR_INT: + return QCoreApplication::translate(p_context, "ERROR"); + case FATAL_INT: + return QCoreApplication::translate(p_context, "FATAL"); + case OFF_INT: + return QCoreApplication::translate(p_context, "OFF"); + default: + Q_ASSERT_X(false, "Level::toString()", "Unknown level value"); + return QCoreApplication::translate(p_context, "NULL"); + } + } + + + Level Level::fromString(const QString &rLevel, bool *pOk) + { + const char *p_context = "Level"; + if (pOk) + *pOk = true; + + if (rLevel == QLatin1String("OFF") || + rLevel == QCoreApplication::translate(p_context, "OFF")) + return OFF_INT; + if (rLevel == QLatin1String("FATAL") || + rLevel == QCoreApplication::translate(p_context, "FATAL")) + return FATAL_INT; + if (rLevel == QLatin1String("ERROR") || + rLevel == QCoreApplication::translate(p_context, "ERROR")) + return ERROR_INT; + if (rLevel == QLatin1String("WARN") || + rLevel == QCoreApplication::translate(p_context, "WARN")) + return WARN_INT; + if (rLevel == QLatin1String("INFO") || + rLevel == QCoreApplication::translate(p_context, "INFO")) + return INFO_INT; + if (rLevel == QLatin1String("DEBUG") || + rLevel == QCoreApplication::translate(p_context, "DEBUG")) + return DEBUG_INT; + if (rLevel == QLatin1String("TRACE") || + rLevel == QCoreApplication::translate(p_context, "TRACE")) + return TRACE_INT; + if (rLevel == QLatin1String("ALL") || + rLevel == QCoreApplication::translate(p_context, "ALL")) + return ALL_INT; + if (rLevel == QLatin1String("NULL") || + rLevel == QCoreApplication::translate(p_context, "NULL")) + return NULL_INT; + + logger()->warn("Use of invalid level string '%1'. Using 'Level::NULL_INT' instead.", rLevel); + if (pOk) + *pOk = false; + return NULL_INT; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel) + { + quint8 l = rLevel.mValue; + rStream << l; + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel) + { + quint8 l; + rStream >> l; + rLevel.mValue = (Level::Value)l; + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Level &rLevel) + { + debug.nospace() << "Level(" + << rLevel.toString() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/level.h b/GC-3.6.1-T2/src/log4qt/level.h new file mode 100644 index 0000000..93914c2 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/level.h @@ -0,0 +1,193 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVEL_H +#define LOG4QT_LEVEL_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Level defines the level of a logging event. + * + * \note All the functions declared in this class are thread-safe. + */ + class Level + { + public: + // Comparisson operators rely on the order: + // NULL_INT < ALL_INT < TRACE_INT < ... + // Serialisation uses unsigned 8 bit int + + /*! + * The enumeration Value contains all possible Level values. + */ + enum Value + { + /*! NULL_INT is used for no level has been specified */ + NULL_INT = 0, + ALL_INT = 32, + TRACE_INT = 64, + DEBUG_INT = 96, + INFO_INT = 128, + WARN_INT = 150, + ERROR_INT = 182, + FATAL_INT = 214, + OFF_INT = 255 + }; + + public: + Level(Value value = NULL_INT); + // Level(const Level &rOther); // Use compiler default + // virtual ~Level(); // Use compiler default + // Level &operator=(const Level &rOther); // Use compiler default + + int syslogEquivalent() const; + int toInt() const; + + bool operator==(const Level &rOther) const; + bool operator!=(const Level &rOther) const; + bool operator<(const Level &rOther) const; + bool operator<=(const Level &rOther) const; + bool operator>(const Level &rOther) const; + bool operator>=(const Level &rOther) const; + QString toString() const; + + static Level fromString(const QString &rName, bool *pOk = 0); + + private: + // QMutex mObjectGuard; + volatile Value mValue; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + friend QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates Level + * + * Writes the given error \a rLevel to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + + /*! + * \relates Level + * + * Reads an error from the given stream \a rStream into the given + * error \a rLevel, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Level + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Level("ERROR") + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Level &rLevel); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + + inline Level::Level(Value value) : + mValue(value) + {} + + inline int Level::toInt() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue; } + + inline bool Level::operator==(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue == rOther.mValue; } + + inline bool Level::operator!=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue != rOther.mValue; } + + inline bool Level::operator<(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue < rOther.mValue; } + + inline bool Level::operator<=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue <= rOther.mValue; } + + inline bool Level::operator>(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue > rOther.mValue; } + + inline bool Level::operator>=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue >= rOther.mValue; } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::Level) +Q_DECLARE_TYPEINFO(Log4Qt::Level, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LEVEL_H diff --git a/GC-3.6.1-T2/src/log4qt/log4qt.cpp b/GC-3.6.1-T2/src/log4qt/log4qt.cpp new file mode 100644 index 0000000..9378f46 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/log4qt.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + *Dependencies + ******************************************************************************/ + + +#include "log4qt/log4qt.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + *Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/log4qt.h b/GC-3.6.1-T2/src/log4qt/log4qt.h new file mode 100644 index 0000000..73c3cfe --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/log4qt.h @@ -0,0 +1,614 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Added a compile time version check for the Qt version + * Jan 2009, Martin Heinrich: + * - Updated documentation and version information for version 0.2 + * Feb 2009, Martin Heinrich: + * - Updated version information for version 0.3 + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_H +#define LOG4QT_H + + +/*! + * \mainpage + * + * %Log4Qt is a C++ port of the Apache Software Foundation Log4j package + * using the Trolltech Qt Framework. + * + * The documentation describes classes and methods that have been added or + * changed compared to Log4j. + * + * The following sections are describing the implementation in more detail: + * - \ref Changes "Differences to Log4j" + * - \ref Ownership "Object ownership" + * - \ref LogLog "Logging within the package" + * - \ref Init "Initialization procedure" + * - \ref Env "Environment Variables" + * - \ref Undocumented "Undocumented functions" + * - \ref Assumptions "Assumptions" + * + * \author Martin Heinrich + * \version 0.3 (January 2009) + * + */ + +/*! + * \page Changes Differences to Log4j + * + * The following fundamental differences exist between %Log4Qt and Log4j: + * + * - As a JAVA package Log4j does not have to manage object ownership and + * lifetime in the same way then it is required in C++. For details on + * how object ownership is handled see \ref Ownership "Object ownership". + * - The package uses itself for its internal logging similar to Log4j 1.3. + * For details see \ref LogLog "Logging within the package". + * - The configuration using system properties was replaced with a combination + * of environment variables and application settings. For details see + * \ref Env "Environment Variables". + * - Custom levels are not supported. + * - Multiple Logger Repositories are not supported + * + * The following classes have been changed: + * + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - The procedure of checking, if logging is possible, originally used by + * \ref Log4Qt::WriterAppender "WriterAppender" was generalised and is used + * in \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" and derived classes + * (\ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()"). + * - The \ref Log4Qt::AppenderSkeleton::doAppend() "doAppend()" member function will + * check the entry conditions by calling the sub-class specific + * \ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()". + * If successful the sub-class specific + * \ref Log4Qt::AppenderSkeleton::append() "append()" function is called. + * + * - Configurator + * - Configure functions return a boolean indicating, if the configuration + * was successful. + * - Configure errors are accessible over + * \ref Log4Qt::ConfiguratorHelper::configureError() + * "ConfiguratorHelper::configureError()". + * - Watching for configuration file changes is a function performed + * centrally by the \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper". + * The class provides signals to notify on configuration change and errors. + * - The class \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" was + * extended to be able to read configuration data from a QSettings object. + * + * - \ref Log4Qt::Level "Level" + * - A new value \ref Log4Qt::Level::NULL_INT "Level::NULL_INT" was + * introduced to indicate there is no level set. + * + * - \ref Log4Qt::Logger "Logger" + * - The method \ref Log4Qt::Logger::isEnabledFor() "isEnabledFor()" + * does also take the repository threshold into account. + * - Several overloaded convenience member function are available to log + * messages with arguments of different types. + * - Two macros, \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * and \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER", + * allows retrieving and caching of a pointer to a logger object. + * + * - \ref Log4Qt::LogManager "LogManager" + * - A QtMessage handler can be installed via + * \ref Log4Qt::LogManager::setHandleQtMessages() "setHandleQtMessages()", + * to redirect all messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() to a logger. The logger is named Qt and can be + * accessed using \ref Log4Qt::LogManager::qtLogger() "qtLogger()". + * - The initialisation procedure is available over a public method + * (\ref Log4Qt::LogManager::startup() "startup()"). + * - The LogManager provides access to the logger used internally by the + * package (\ref Log4Qt::LogManager::logLogger() "logLogger()") and to + * its default initialisation procedure + * (\ref Log4Qt::LogManager::configureLogLogger() "configureLogLogger()"). + * + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - The class will call \ref Log4Qt::WriterAppender::handleIoErrors() + * "handleIoErrors()" after all I/O operations. Sub-classes should + * re-implement the function to handle errors. + * + * The following classes have been added: + * + * - An additional appender class, \ref Log4Qt::DebugAppender "DebugAppender", + * was added. The class appends logging events to the platform specific debug + * output. + * - Various helper class have been introduced: + * - \ref Log4Qt::ClassLogger "ClassLogger": The class ClassLogger provides + * logging for a QObject derived class. + * - \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper": The class + * ConfiguratorHelper provides a configuration file watch and last error + * for configurator classes. + * - \ref Log4Qt::DateTime "DateTime": The class DateTime provides extended + * functionality for QDateTime. + * - \ref Log4Qt::LogError "LogError": The class LogError represents an error. + * - \ref Log4Qt::Factory "Factory": The class Factory provides factories + * for Appender, Filter and Layout objects. + * - \ref Log4Qt::InitialisationHelper "InitialisationHelper": The class + * InitialisationHelper performs static initialisation tasks. + * - \ref Log4Qt::LogObject "LogObject": The class LogObject is the common + * base class for many classes in the package. + * - \ref Log4Qt::LogObjectPtr "LogObjectPtr": The class LogObjectPtr + * implements automatic reference counting for LogObject objects. + * - \ref Log4Qt::PatternFormatter "PatternFormatter": The class + * PatternFormatter formats a logging event based on a pattern string. + * - \ref Log4Qt::Properties "Properties": The class Properties implements a + * JAVA property hash. + */ + +/*! + * \page Ownership Object ownership + * + * In difference to the JAVA Log4j package %Log4Qt must manage ownership and + * lifetime of the objects used. This is non trivial as objects are created + * and used in different ways. + * + * In general an object can be created explicitly for example an application + * may create Loggers, Appenders and Layouts during creation of a QApplication + * object. But they can also be automatically created by the package on + * startup using a \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" + * configuration file. Objects may also be created the one way and then used + * the other. Object may be used by multiple other objects. A Layout for example + * may be used by multiple Appenders. Objects are also created from multiple + * threads. The creation may happen during static initialisation and the + * deletion during static de-initialization. + * + * The parent child model used by QObject cannot be used to handle this. It + * cannot automatically delete an object that is used by multiple others as + * for example an Appender used by multiple Loggers. In addition to this + * QObjects and their children must reside in the same thread. This would + * either mean to impose restriction on how objects can be created or to move + * objects to a specific thread. + * + * To allow an automatic deletion of not required objects the package + * implements reference counting for Appenders, Layouts and Filters. The + * reference counting is implemented in \ref Log4Qt::LogObject "LogObject", + * which is used as a common base class. The reference count can be explicitly + * changed using the methods \ref Log4Qt::LogObject::retain() "retain()" and + * \ref Log4Qt::LogObject::release() "release()". Alternatively an auto pointer + * is available \ref Log4Qt::LogObjectPtr "LogObjectPtr", which is used + * throughout the package. + * + * The reference counting mechanism will test, if an object has a QObject + * parent object set. If a parent is set, the object will not be deleted, if + * the reference count reaches 0. This allows to mix the reference counted + * paradigm with the QObject parent child one. + * + * The following example configures a logger and uses reference counting to + * manage the ownership of objects. + * + * \code + * // Create layout + * TTCCLayout *p_layout = new TTCCLayout(); + * + * // Create appender + * ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // p_appender and p_layout are deleted here + * \endcode + * + * The following example configures a logger and uses QObject ownership of + * objects. + * + * \code + * QObject *p_parent = new MyObject; + * + * // Create objects + * ConsoleAppender *p_appender = new ConsoleAppender(p_parent); + * TTCCLayout *p_layout = new TTCCLayout(p_appender); + * + * // Configure appender + * p_appender->setTarget(ConsoleAppender::STDOUT_TARGET); + * p_appender->setLayout(p_layout); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); + * + * delete p_parent; // p_appender and p_layout are deleted here + * \endcode + * + * The following example shows how to use objects created on the stack. + * + * \code + * { + * // Create layout + * TTCCLayout layout; + * layout.retain(); + * + * // Create appender + * ConsoleAppender appender(&layout, ConsoleAppender::STDOUT_TARGET); + * appender.retain(); + * appender.activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(&appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // Without retain() program crashes here + * + * } // p_appender and p_layout are deleted here + * \endcode + */ + +/*! + * \page LogLog Logging within the package + * + * The package uses itself for logging similar to Log4j 1.3. This brings much + * more flexibility over logging to stdout, stderr like in Log4j 1.2 using + * logLog. It also enables the program to capture and handle errors raised by + * the package. + * + * Using this approach introduces the issue of recursion. The following example + * explains a situation where this happens. Let's say all logger are configured + * to be additive and only the root logger has an appender set. The appender + * is a \ref Log4Qt::FileAppender "FileAppender". During the logging of an + * event an I/O error occurs. The \ref Log4Qt::FileAppender "FileAppender" logs + * an event by itself using the logger %Log4Qt::FileAppender. The event is + * passed to the root logger, which calls then the \ref Log4Qt::FileAppender + * "FileAppender". This causes another I/O error, which is logged by + * the \ref Log4Qt::FileAppender "FileAppender". + * + * To avoid an endless loop the appender will drop the event on a recursive + * invocation. This check is done by \ref Log4Qt::AppenderSkeleton + * "AppenderSkeleton" in \ref Log4Qt::AppenderSkeleton::doAppend() + * "doAppend()". + * + * The problem only occurs, if a logger, appender, layout or filter log an + * event while an event is appended. Neither the logger class nor any of the + * layout or filter classes log events during appending of an event. Most of + * the appender classes may log errors during appending. Only the + * \ref Log4Qt::ListAppender "ListAppender" and + * \ref Log4Qt::ListAppender "ConsoleAppender" are not logging events. + * + * The default configuration uses two \ref Log4Qt::ListAppender + * "ConsoleAppender", one for stderr and one for stdout. No event will be + * dropped, because no recursive invocations can occur. + */ + +/*! + * \page Init Initialization procedure + * + * The package is initialised in two stages. The first stage takes place during + * static initialization. The second stage takes place when the + * \ref Log4Qt::LogManager "LogManager" singleton is created. + * + * During static initialisation the \ref Log4Qt::InitialisationHelper + * "InitialisationHelper" singleton is created . On construction it captures + * the program startup time, reads the required values from the system + * environment and registers the package types with the Qt type system. + * + * The \ref Log4Qt::LogManager "LogManager" singleton is created on first use. + * The creation is usually triggered by the request for a \ref Log4Qt::Logger + * "Logger" object. The call to \ref Log4Qt::Logger::logger() + * "Logger::logger()" is passed through to \ref Log4Qt::LogManager::logger() + * "LogManager::logger()". On creation the \ref Log4Qt::LogManager "LogManager" + * creates a \ref Log4Qt::Hierarchy "Hierarchy" object as logger repository. + * + * After the singleton is created the logging of the package is configured to + * its default by a call to \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()". The logger + * \ref Log4Qt::LogManager::logLogger() "logLogger()" is configured to be not + * additive. Messages with the level \ref Log4Qt::Level::ERROR_INT + * "Level::ERROR_INT" and \ref Log4Qt::Level::FATAL_INT "Level::FATAL_INT" are + * written to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is read from + * the system environment or application settings using + * \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" with the key \c Debug. If a level value + * is found, but it is not a valid Level string, + * \ref Log4Qt::Level::DEBUG_INT "Level::DEBUG_INT" is used. If no level string + * is found \ref Log4Qt::Level::ERROR_INT "Level::ERROR_INT" is used. + * + * Once the logging is configured the package is initialised by a call to + * \ref Log4Qt::LogManager::startup() "LogManager::startup()". The function + * will test for the setting \c DefaultInitOverride in the system environment + * and application settings using \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()". If the value is present and set to + * anything else then \c false, the initialisation is aborted.
+ * The system environment and application settings are tested for the setting + * \c Configuration. If it is found and it is a valid path to a file, the + * package is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting \c Configuration is + * not available and a QCoreApplication object is present, the application + * settings are tested for a group \c Log4Qt/Properties. If the group exists, + * the package is configured with the setting using the + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration file nor + * configuration settings could be found, the current working directory is + * searched for the file \c "log4qt.properties". If it is found, the package + * is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * The following example shows how to use application settings to initialise the + * package. + * + * \code + * # file: myapplication.h + * + * #include qapplication.h + * + * class MyApplication : public QApplication + * { + * Q_OBJECT + * + * public: + * MyApplication(); + * ~MyApplication(); + * void setupLog4Qt(); + * } + * \endcode + * \code + * # file: myapplication.cpp + * + * #include myapplication.h + * + * MyApplication::MyApplication( + * { + * // Set Application data to allow Log4Qt initialisation to read the + * // correct values + * setApplicationName("MyApplication"); + * setOrganisationName("MyOrganisation"); + * setOrganizationDomain("www.myorganisation.com"); + * + * // Log first message, which initialises Log4Qt + * Log4Qt::Logger::logger("MyApplication")->info("Hello World"); + * } + * + * MyApplication::~MyApplication() + * { + * } + * + * void MyApplication::setupLog4Qt() + * { + * QSettings s; + * + * // Set logging level for Log4Qt to TRACE + * s.beginGroup("Log4Qt"); + * s.setValue("Debug", "TRACE"); + * + * // Configure logging to log to the file C:/myapp.log using the level TRACE + * s.beginGroup("Properties"); + * s.setValue("log4j.appender.A1", "org.apache.log4j.FileAppender"); + * s.setValue("log4j.appender.A1.file", "C:/myapp.log"); + * s.setValue("log4j.appender.A1.layout", "org.apache.log4j.TTCCLayout"); + * s.setValue("log4j.appender.A1.layout.DateFormat", "ISO8601"); + * s.setValue("log4j.rootLogger", "TRACE, A1"); + * + * // Settings will become active on next application startup + * } + * \endcode + */ + +/*! + * \page Env Environment Variables + * + * The package uses environment variables to control the initialization + * procedure. The environment variables replace the system property entries + * used by Log4j. + * + * For compability reasons the Log4j entry is recognised. Alternatively a + * environment variable style Log4Qt form can be used. The following entries + * are used: + * + * - LOG4QT_DEBUG
+ * The variable controls the \ref Log4Qt::Level "Level" value for the + * logger \ref Log4Qt::LogManager::logLogger() "LogManager::logLogger()". + * If the value is a valid \ref Log4Qt::Level "Level" string, the level for + * the is set to the level. If the value is not a valid + * \ref Log4Qt::Level "Level" string, \ref Log4Qt::Level::DEBUG_INT + * "DEBUG_INT" is used. Otherwise \ref Log4Qt::Level::ERROR_INT "ERROR_INT" + * is used. + * - \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()" + * + * - LOG4QT_DEFAULTINITOVERRIDE
+ * The variable controls the \ref Init "initialization procedure" performed + * by the \ref Log4Qt::LogManager "LogManager" on startup. If it is set to + * any other value then \c false the \ref Init "initialization procedure" + * is skipped. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATION
+ * The variable specifies the configuration file used for initialising the + * package. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATORCLASS
+ * The variable specifies the configurator class used for initialising the + * package. + * + * Environment variables are read during static initialisation on creation of + * the \ref Log4Qt::InitialisationHelper "InitialisationHelper". They can be + * accessed by calling \ref Log4Qt::InitialisationHelper::environmentSettings() + * "InitialisationHelper::environmentSettings()". + * + * All settings can also be made in the application settings under the group + * \c %Log4Qt. For example the environment variable \c LOG4QT_DEBUG is + * equivalent to the setting \c Log4Qt/Debug. If an environment variable is + * set it takes precedence over the application setting. Settings are only + * used, if an QApplication object is available, when the + * \ref Log4Qt::LogManager "LogManager" is + * initialised (see \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" for details). + */ + +/*! + * \page Undocumented Undocumented functions + * + * In general it was tried to avoid the usage of undocumented features of Qt. + * Nice to have features like for example Q_DECLARE_PRIVATE are not used. Only + * features that would have been resulted in re-coding the same functionality + * are used. + * + * - QT_WA: The macro is used to call Windows A/W functions + * - \ref Log4Qt::DebugAppender "DebugAppender" + * - QBasicAtomicPointer: The class is used instead of QAtomicPointer, because + * it allows the initialisation as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * - Q_BASIC_ATOMIC_INITIALIZER: The macro is used to initialise QAtomicPointer + * objects as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + */ + +/*! + * \page Assumptions Assumptions + * + * The following assumptions are used throughout the package: + * + * - Reading / writing of bool or int is thread-safe, if declared volatile + * - \ref Log4Qt::ListAppender "ListAppender" + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - \ref Log4Qt::ConsoleAppender "ConsoleAppender" + * - \ref Log4Qt::FileAppender "FileAppender" + * - \ref Log4Qt::Hierarchy "Hierarchy" + * - \ref Log4Qt::Level "Level" + * - \ref Log4Qt::Logger "Logger" + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - \ref Log4Qt::Layout::format() "Layout::format()" is implemented reentrant + * in all sub-classes. + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - Being able to use singleton objects during static de-initialization without + * order issues is more valuable then their destruction. + * - \ref Log4Qt::LogManager "LogManager" + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + */ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#if QT_VERSION < QT_VERSION_CHECK(4, 3, 0) +# error "Log4Qt requires Qt version 4.3.0 or higher" +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +/*! + * \brief The namespace %Log4Qt encloses all parts of the package. + */ +namespace Log4Qt +{ + /*! + * This macro expands a numeric value of the form 0xMMmmPP (MM = major, + * mm = minor, PP = patch) that specifies Log4Qt's version number. + * This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION 0x000200 + + /*! + * The macro expands to a string that specifies the Log4Qt's version + * number. This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION_STR "0.3.0" + + enum ErrorCode + { + OK = 0, + // AppenderSkeleton, FileAppender, WriterAppender + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR, + APPENDER_ACTIVATE_MISSING_WRITER_ERROR, + APPENDER_ACTIVATE_MISSING_FILE_ERROR, + APPENDER_CLOSED_ERROR, + APPENDER_INVALID_PATTERN_ERROR, + APPENDER_NO_OPEN_FILE_ERROR, + APPENDER_NOT_ACTIVATED_ERROR, + APPENDER_OPENING_FILE_ERROR, + APPENDER_RENAMING_FILE_ERROR, + APPENDER_REMOVE_FILE_ERROR, + APPENDER_USE_INVALID_PATTERN_ERROR, + APPENDER_USE_MISSING_LAYOUT_ERROR, + APPENDER_USE_MISSING_WRITER_ERROR, + APPENDER_WRITING_FILE_ERROR, + // Level + LEVEL_INVALID_LEVEL_STRING, + // Layouts, PatternFormatter + LAYOUT_EXPECTED_DIGIT_ERROR, + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + // Logger + LOGGER_INVALID_LEVEL_FOR_ROOT, + // PropertyConfigurator, OptionHandler + CONFIGURATOR_OPENING_FILE_ERROR, + CONFIGURATOR_READING_FILE_ERROR, + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + CONFIGURATOR_INVALID_OPTION_ERROR, + CONFIGURATOR_MISSING_APPENDER_ERROR, + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + CONFIGURATOR_MISSING_LAYOUT_ERROR, + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + CONFIGURATOR_PROPERTY_ERROR, + CONFIGURATOR_UNKNOWN_TYPE_ERROR + }; + + + /****************************************************************************** + * Operators, Helpers + ******************************************************************************/ + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + +} // namespace Log4Qt + + +#endif // LOG4QT_H diff --git a/GC-3.6.1-T2/src/log4qt/log4qt.pri b/GC-3.6.1-T2/src/log4qt/log4qt.pri new file mode 100644 index 0000000..f9730b9 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/log4qt.pri @@ -0,0 +1,111 @@ +# ******************************************************************************* +# +# package: Log4Qt +# file: log4qt.pri +# created: September 2007 +# author: Martin Heinrich +# +# +# Copyright 2007 Martin Heinrich +# +# 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. +# +# ******************************************************************************* + +INCLUDEPATH += $$PWD/.. +DEPENDPATH += $$PWD/.. +HEADERS += \ + $$PWD/appender.h \ + $$PWD/appenderskeleton.h \ + $$PWD/basicconfigurator.h \ + $$PWD/consoleappender.h \ + $$PWD/dailyrollingfileappender.h \ + $$PWD/fileappender.h \ + $$PWD/helpers/classlogger.h \ + $$PWD/helpers/configuratorhelper.h \ + $$PWD/helpers/datetime.h \ + $$PWD/helpers/factory.h \ + $$PWD/helpers/initialisationhelper.h \ + $$PWD/helpers/logerror.h \ + $$PWD/helpers/logobject.h \ + $$PWD/helpers/logobjectptr.h \ + $$PWD/helpers/optionconverter.h \ + $$PWD/helpers/patternformatter.h \ + $$PWD/helpers/properties.h \ + $$PWD/hierarchy.h \ + $$PWD/layout.h \ + $$PWD/level.h \ + $$PWD/log4qt.h \ + $$PWD/logger.h \ + $$PWD/loggerrepository.h \ + $$PWD/loggingevent.h \ + $$PWD/logmanager.h \ + $$PWD/mdc.h \ + $$PWD/ndc.h \ + $$PWD/patternlayout.h \ + $$PWD/propertyconfigurator.h \ + $$PWD/rollingfileappender.h \ + $$PWD/simplelayout.h \ + $$PWD/spi/filter.h \ + $$PWD/ttcclayout.h \ + $$PWD/writerappender.h \ + $$PWD/varia/debugappender.h \ + $$PWD/varia/denyallfilter.h \ + $$PWD/varia/nullappender.h \ + $$PWD/varia/levelmatchfilter.h \ + $$PWD/varia/levelrangefilter.h \ + $$PWD/varia/listappender.h \ + $$PWD/varia/stringmatchfilter.h + +SOURCES += \ + $$PWD/appenderskeleton.cpp \ + $$PWD/basicconfigurator.cpp \ + $$PWD/consoleappender.cpp \ + $$PWD/dailyrollingfileappender.cpp \ + $$PWD/fileappender.cpp \ + $$PWD/helpers/classlogger.cpp \ + $$PWD/helpers/configuratorhelper.cpp \ + $$PWD/helpers/datetime.cpp \ + $$PWD/helpers/factory.cpp \ + $$PWD/helpers/initialisationhelper.cpp \ + $$PWD/helpers/logerror.cpp \ + $$PWD/helpers/logobject.cpp \ + $$PWD/helpers/logobjectptr.cpp \ + $$PWD/helpers/optionconverter.cpp \ + $$PWD/helpers/patternformatter.cpp \ + $$PWD/helpers/properties.cpp \ + $$PWD/hierarchy.cpp \ + $$PWD/layout.cpp \ + $$PWD/level.cpp \ + $$PWD/log4qt.cpp \ + $$PWD/logger.cpp \ + $$PWD/loggerrepository.cpp \ + $$PWD/loggingevent.cpp \ + $$PWD/logmanager.cpp \ + $$PWD/mdc.cpp \ + $$PWD/ndc.cpp \ + $$PWD/patternlayout.cpp \ + $$PWD/propertyconfigurator.cpp \ + $$PWD/rollingfileappender.cpp \ + $$PWD/simplelayout.cpp \ + $$PWD/spi/filter.cpp \ + $$PWD/ttcclayout.cpp \ + $$PWD/writerappender.cpp \ + $$PWD/varia/debugappender.cpp \ + $$PWD/varia/denyallfilter.cpp \ + $$PWD/varia/nullappender.cpp \ + $$PWD/varia/levelmatchfilter.cpp \ + $$PWD/varia/levelrangefilter.cpp \ + $$PWD/varia/listappender.cpp \ + $$PWD/varia/stringmatchfilter.cpp + \ No newline at end of file diff --git a/GC-3.6.1-T2/src/log4qt/logger.cpp b/GC-3.6.1-T2/src/log4qt/logger.cpp new file mode 100644 index 0000000..d5dc936 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/logger.cpp @@ -0,0 +1,349 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logger.h" + +#include +#include "log4qt/appenderskeleton.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/loggingevent.h" +#include "log4qt/log4qt.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Logger + **************************************************************************/ + + + Logger::Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent) : + QObject(0), +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mName(rName), + mpLoggerRepository(pLoggerRepository), + mAdditivity(true), + mAppenders(), + mLevel(level), + mpParent(pParent) + { + Q_ASSERT_X(pLoggerRepository, "Logger::Logger()", "Construction of Logger with null LoggerRepository"); + + setObjectName(mName); + } + + + Logger::~Logger() + { + logger()->warn("Unexpected destruction of Logger"); + + // QWriteLocker locker(&mObjectGuard); + // + // QMutableListIterator< LogObjectPtr > i(mAppenders); + // while (i.hasNext()) + // { + // i.next(); + // i.remove(); + // } + } + + + QList Logger::appenders() const + { + QReadLocker locker(&mObjectGuard); + + QList result; + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + result << p_appender; + return result; + } + + + void Logger::setLevel(Level level) + { + // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe + + if ((parentLogger() == 0) && (level == Level::NULL_INT)) + { + logger()->warn("Invalid root logger level NULL_INT. Using DEBUG_INT instead"); + level = Level::DEBUG_INT; + } + mLevel = level; + } + + + void Logger::addAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Handle warnings, before write lock is aquired + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + { + QReadLocker locker(&mObjectGuard); + + if(!p_appender) + { + logger()->warn("Adding null Appender to Logger '%1'", name()); + return; + } + if(mAppenders.contains(p_appender)) + { + logger()->warn("Adding of duplicate appender '%2' to logger '%1'", name(), p_appender->name()); + return; + } + } + { + QWriteLocker locker(&mObjectGuard); + + if(mAppenders.contains(p_appender)) + return; + mAppenders.append(p_appender); + } + } + + + Appender *Logger::appender(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + if (p_appender->name() == rName) + return p_appender; + return 0; + } + + + + void Logger::callAppenders(const LoggingEvent &rEvent) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + p_appender->doAppend(rEvent); + if (additivity() && (parentLogger() != 0)) + parentLogger()->callAppenders(rEvent); + } + + + bool Logger::isAttached(Appender *pAppender) const + { + QReadLocker locker(&mObjectGuard); + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + return mAppenders.contains(p_appender); + } + + + void Logger::removeAllAppenders() + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to all appenders so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + logger()->trace("Removing all appenders from logger '%1'", name()); + + QList< LogObjectPtr > appenders; + { + QWriteLocker locker(&mObjectGuard); + QMutableListIterator< LogObjectPtr > i(mAppenders); + while (i.hasNext()) + { + Appender *p_appender = i.next(); + ListAppender *p_listappender = qobject_cast(p_appender); + if (p_listappender && p_listappender->configuratorList()) + continue; + else + { + appenders << p_appender; + i.remove(); + } + } + } + appenders.clear(); + } + + + void Logger::removeAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to the appender so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + LogObjectPtr p_appender = pAppender; + + if(!p_appender) + { + logger()->warn("Request to remove null Appender from Logger '%1'", name()); + return; + } + int n; + { + QWriteLocker locker(&mObjectGuard); + + n = mAppenders.removeAll(p_appender); + } + if (n == 0) + { + logger()->warn("Request to remove Appender '%2', which is not part of Logger '%1' appenders", name(), p_appender->name()); + return; + } + } + + + void Logger::removeAppender(const QString &rName) + { + Appender *p_appender = appender(rName); + if (p_appender) + removeAppender(p_appender); + } + + + Level Logger::effectiveLevel() const + { + Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT, "Logger::effectiveLevel()", "Root logger level must not be NULL_INT"); + + QReadLocker locker(&mObjectGuard); + + const Logger *p_logger = this; + while (p_logger->level() == Level::NULL_INT) + p_logger = p_logger->parentLogger(); + return p_logger->level(); + } + + + bool Logger::isEnabledFor(Level level) const + { + if (mpLoggerRepository->isDisabled(level)) + return false; + return (effectiveLevel() <= level); + } + + + Logger *Logger::logger(const QString &rName) + { + return LogManager::logger(rName); + } + + + Logger *Logger::logger(const char *pName) + { + return LogManager::logger(QLatin1String(pName)); + } + + + Logger *Logger::rootLogger() + { + return LogManager::rootLogger(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Logger::debug(QDebug &rDebug) const + { + QReadLocker locker(&mObjectGuard); + + QString parent_logger; + if (mpParent) + parent_logger = mpParent->name(); + + rDebug.nospace() << "Logger(" + << "name:" << name() << " " + << "appenders:" << mAppenders.count() << " " + << "additivity:" << mAdditivity << " " + << mLevel + << "parentLogger:" << parent_logger + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void Logger::forcedLog(Level level, const QString &rMessage) const + { + QReadLocker locker(&mObjectGuard); + + LoggingEvent event(this, level, rMessage); + callAppenders(event); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Logger &rLogger) + { + return rLogger.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/logger.h b/GC-3.6.1-T2/src/log4qt/logger.h new file mode 100644 index 0000000..1b58adc --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/logger.h @@ -0,0 +1,1665 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGER_H +#define LOG4QT_LOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/classlogger.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/level.h" + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macro Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * LOG4QT_DECLARE_STATIC_LOGGER declares a static function \a FUNCTION that + * returns a pointer to a \ref Log4Qt::Logger "Logger" named after \a CLASS. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by calling \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger( #CLASS )". The pointer is stored to be returned on + * subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class not derived from QObject. + * + * \code + * #file: counter.h + * + * #include logger.h + * + * class Counter + * { + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * LOG4QT_DECLARE_STATIC_LOGGER(logger, Counter) + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) : + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static Log4Qt::Logger *p_logger = 0; \ + if (!p_logger) \ + { \ + q_atomic_test_and_set_ptr( \ + &p_logger, \ + 0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#else + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger.loadAcquire()) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_DECLARE_QCLASS_LOGGER declares member functions to retrieve + * \ref Log4Qt::Logger "Logger" for the class it is used in. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by a call to \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger(const char *pName)". The pointer is stored to be + * returned on subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class derived from QObject. + * + * \code + * #file: counter.h + * + * #include qobject.h + * #include logger.h + * + * class Counter : public QObject + * { + * Q_OBJECT + * LOG4QT_DECLARE_QCLASS_LOGGER + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)", + * \ref Log4Qt::ClassLogger "ClassLogger" + */ + #define LOG4QT_DECLARE_QCLASS_LOGGER \ + private: \ + mutable Log4Qt::ClassLogger mLog4QtClassLogger; \ + public: \ + inline Log4Qt::Logger *logger() const \ + { return mLog4QtClassLogger.logger(this); } \ + private: + + class Appender; + class LoggingEvent; + class LoggerRepository; + + /*! + * \brief The class Logger provides logging services. + * + * A pointer to a logger can be retrieved by calling Logger::logger() or + * LogManager::logger() with the class name as argument. Because a logger + * is never destroyed it is possible to store the pointer to the logger. + * This way the lookup of the pointer in the repository is only required + * on the first logging operation. The macros \ref + * Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" and + * \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER" + * provide a thread-safe implementation to store the logger pointer. + * + * \note All the functions declared in this class are thread-safe. + */ + class Logger : public QObject + { + Q_OBJECT + + /*! + * The property holds, if the logger is additive. + * + * The default is true for being additive. + * + * \sa additive(), setAdditive() + */ + Q_PROPERTY(bool additivity READ additivity WRITE setAdditivity) + + /*! + * The property holds the level used by the logger. + * + * The default is Level::NULL_INT. + * \sa level(), setLevel() + */ + Q_PROPERTY(Level level READ level WRITE setLevel) + + /*! + * The property holds the LoggerRepository of the logger. + * + * \sa loggerRepository() + */ + Q_PROPERTY(LoggerRepository* loggerRepository READ loggerRepository) + + /*! + * The property holds the name of the logger. + * + * \sa name() + */ + Q_PROPERTY(QString name READ name) + + /*! + * The property holds the parent logger of the logger. + * + * \sa parentLogger() + */ + Q_PROPERTY(Logger* parentLogger READ parentLogger) + + LOG4QT_DECLARE_QCLASS_LOGGER + + protected: + Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent = 0); + virtual ~Logger(); + private: + Logger(const Logger &rOther); // Not implemented + Logger &operator=(const Logger &rOther); // Not implemented + + public: + bool additivity() const; + QList appenders() const; + Level level() const; + LoggerRepository *loggerRepository() const; + QString name() const; + Logger *parentLogger() const; + // JAVA: ResourceBundle *resourceBundle() const; + // JAVA: void setResourceBundle(ResourceBundle *pResourceBundle); + void setAdditivity(bool additivity); + virtual void setLevel(Level level); + + void addAppender(Appender *pAppender); + Appender *appender(const QString &rName) const; + void callAppenders(const LoggingEvent &rEvent) const; + bool isAttached(Appender *pAppender) const; + + /*! + * Removes all appenders that have been previously added from this + * Logger. + * + * To allow configurators to collect events during the configuration + * process ListAppenders with the configuratorList property set, will + * not be removed. + * + * \sa LisAppender::setConfiguratorList() + */ + void removeAllAppenders(); + + void removeAppender(Appender *pAppender); + void removeAppender(const QString &rName); + // JAVA: QString resourceBundleString(const QString &rKey) const; + + Level effectiveLevel() const; + bool isDebugEnabled() const; + + /*! + * Checks if this logger is enabled for a given Level \a level. If the + * logger is enabled the function returns true. Otherwise it returns + * false. + * + * A logger is enabled for a level, if the level is greater or equal + * then the repository threshold and greater and equal then the loggers + * effective level. + * + * \sa LoggerRepository::isDisabled(), effectiveLevel() + */ + bool isEnabledFor(Level level) const; + + bool isErrorEnabled() const; + bool isFatalEnabled() const; + bool isInfoEnabled() const; + bool isTraceEnabled() const; + bool isWarnEnabled() const; + + void debug(const QString &rMessage) const; + void debug(const LogError &rLogError) const; + void debug(const char *pMessage) const; + void debug(const char *pMessage, + const QString &rArg1) const; + void debug(const char *pMessage, + int arg1) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2) const; + void debug(const char *pMessage, + int arg1, + int arg2) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void error(const QString &rMessage) const; + void error(const LogError &rLogError) const; + void error(const char *pMessage) const; + void error(const char *pMessage, + const QString &rArg1) const; + void error(const char *pMessage, + int arg1) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void error(const char *pMessage, + const QString &rArg1, int arg2) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2) const; + void error(const char *pMessage, + int arg1, + int arg2) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void fatal(const QString &rMessage) const; + void fatal(const LogError &rLogError) const; + void fatal(const char *pMessage) const; + void fatal(const char *pMessage, + const QString &rArg1) const; + void fatal(const char *pMessage, + int arg1) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + int arg1, + int arg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void info(const QString &rMessage) const; + void info(const LogError &rLogError) const; + void info(const char *pMessage) const; + void info(const char *pMessage, + const QString &rArg1) const; + void info(const char *pMessage, + int arg1) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2) const; + void info(const char *pMessage, + int arg1, + int arg2) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void log(Level level, + const QString &rMessage) const; + void log(Level level, + const LogError &rLogError) const; + void log(Level level, + const char *pMessage) const; + void log(Level level, + const char *pMessage, + const QString &rArg1) const; + void log(Level level, + const char *pMessage, + int arg1) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // JAVA: void l7dlog(Level level, + // const QString &rKey); + // JAVA: void l7dlog(Level level, + // const QString &rKey, + // const QList rParameters); + + void trace(const QString &rMessage) const; + void trace(const LogError &rLogError) const; + void trace(const char *pMessage) const; + void trace(const char *pMessage, + const QString &rArg1) const; + void trace(const char *pMessage, + int arg1) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2) const; + void trace(const char *pMessage, + int arg1, + int arg2) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void warn(const QString &rMessage) const; + void warn(const LogError &rLogError) const; + void warn(const char *pMessage) const; + void warn(const char *pMessage, + const QString &rArg1) const; + void warn(const char *pMessage, + int arg1) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2) const; + void warn(const char *pMessage, + int arg1, + int arg2) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // LogManager operations + static Logger *logger(const QString &rName); + static Logger *logger(const char *pName); + static Logger *rootLogger(); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Logger(name:"Log4Qt" appenders:0 additivity:true Level("NULL") + * parentLogger: "root" ) + * + * \sa QDebug, operator<<(QDebug debug, const Appender &rAppender) + */ + virtual QDebug debug(QDebug &rDebug) const; + friend QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + void forcedLog(Level level, + const QString &rMessage) const; + + protected: + mutable QReadWriteLock mObjectGuard; + private: + const QString mName; + LoggerRepository* mpLoggerRepository; + volatile bool mAdditivity; + QList< LogObjectPtr > mAppenders; + Level mLevel; + Logger *mpParent; + + // Needs to be friend to create Logger objects + friend class Hierarchy; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Logger + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * To handle subclassing the function uses the virtual member function debug(). + * This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool Logger::additivity() const + { // QReadLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAdditivity; } + + inline Level Logger::level() const + { // QReadLocker locker(&mObjectGuard); // Level is thread-safe + return mLevel; } + + inline LoggerRepository *Logger::loggerRepository() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpLoggerRepository; } + + inline QString Logger::name() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mName; } + + inline Logger *Logger::parentLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpParent; } + + inline void Logger::setAdditivity(bool additivity) + { // QWriteLocker locker(&mObjectGuard); // Read/Write of int is safe + mAdditivity = additivity; } + + // Level operations + + inline bool Logger::isDebugEnabled() const + { return isEnabledFor(Level::DEBUG_INT); } + + inline bool Logger::isErrorEnabled() const + { return isEnabledFor(Level::ERROR_INT); } + + inline bool Logger::isFatalEnabled() const + { return isEnabledFor(Level::FATAL_INT); } + + inline bool Logger::isInfoEnabled() const + { return isEnabledFor(Level::INFO_INT); } + + inline bool Logger::isTraceEnabled() const + { return isEnabledFor(Level::TRACE_INT); } + + inline bool Logger::isWarnEnabled() const + { return isEnabledFor(Level::WARN_INT); } + + // Log operations: debug + + inline void Logger::debug(const LogError &rLogError) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rLogError.toString()); } + + inline void Logger::debug(const QString &rMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rMessage); } + + inline void Logger::debug(const char *pMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::debug(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: error + + inline void Logger::error(const QString &rMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rMessage); } + + inline void Logger::error(const LogError &rLogError) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rLogError.toString()); } + + inline void Logger::error(const char *pMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::error(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: fatal + + inline void Logger::fatal(const QString &rMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rMessage); } + + inline void Logger::fatal(const LogError &rLogError) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rLogError.toString()); } + + inline void Logger::fatal(const char *pMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::fatal(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: info + + inline void Logger::info(const QString &rMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rMessage); } + + inline void Logger::info(const LogError &rLogError) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rLogError.toString()); } + + inline void Logger::info(const char *pMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::info(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: log + + inline void Logger::log(Level level, + const QString &rMessage) const + { if (isEnabledFor(level)) + forcedLog(level, rMessage); } + + inline void Logger::log(Level level, + const LogError &rLogError) const + { if (isEnabledFor(level)) + forcedLog(level, rLogError.toString()); } + + inline void Logger::log(Level level, + const char *pMessage) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: trace + + inline void Logger::trace(const QString &rMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rMessage); } + + inline void Logger::trace(const LogError &rLogError) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rLogError.toString()); } + + inline void Logger::trace(const char *pMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::trace(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: warn + + inline void Logger::warn(const QString &rMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rMessage); } + + inline void Logger::warn(const LogError &rLogError) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rLogError.toString()); } + + inline void Logger::warn(const char *pMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::warn(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::Logger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGER_H diff --git a/GC-3.6.1-T2/src/log4qt/loggerrepository.cpp b/GC-3.6.1-T2/src/log4qt/loggerrepository.cpp new file mode 100644 index 0000000..b541bb2 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/loggerrepository.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggerrepository.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggerRepository + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository) + { + return rLoggerRepository.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/loggerrepository.h b/GC-3.6.1-T2/src/log4qt/loggerrepository.h new file mode 100644 index 0000000..13c0488 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/loggerrepository.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGERREPOSITORY_H +#define LOG4QT_LOGGERREPOSITORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggerRepository is abstract base class for a logger + * repository. + */ + class LoggerRepository + { + public: + // LoggerRepository(); // Use compiler default + // LoggerRepository(const LoggerRepository &rOther); // Use compiler default + // virtual ~LoggerRepository(); // Use compiler default + // LoggerRepository &operator=(const LoggerRepository &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const = 0; + virtual Logger *logger(const QString &rName) = 0; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual QList loggers() const = 0; + virtual Logger *rootLogger() const = 0; + virtual Level threshold() const = 0; + virtual void setThreshold(Level level) = 0; + virtual void setThreshold(const QString &rThreshold) = 0; + + virtual bool isDisabled(Level level) = 0; + virtual void resetConfiguration() = 0; + virtual void shutdown() = 0; + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + *\relates LoggerRepository + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + * to generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggerRepository + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle subclassing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LoggerRepository, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGERREPOSITORY_H diff --git a/GC-3.6.1-T2/src/log4qt/loggingevent.cpp b/GC-3.6.1-T2/src/log4qt/loggingevent.cpp new file mode 100644 index 0000000..161f01c --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/loggingevent.cpp @@ -0,0 +1,272 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggingevent.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggingevent.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" +#include "log4qt/mdc.h" +#include "log4qt/ndc.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(QMutex, sequence_guard) + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggingEvent + **************************************************************************/ + + + LoggingEvent::LoggingEvent() : + mLevel(Level::NULL_INT), + mpLogger(0), + mMessage(), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(timeStamp) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(rNdc), + mProperties(rProperties), + mSequenceNumber(nextSequenceNumber()), + mThreadName(rThreadName), + mTimeStamp(timeStamp) + { + } + + + QString LoggingEvent::loggerName() const + { + if (mpLogger) + return mpLogger->name(); + else + return QString(); + } + + + QString LoggingEvent::toString() const + { + return level().toString() + QLatin1Char(':') + message(); + } + + + qint64 LoggingEvent::sequenceCount() + { + QMutexLocker locker(sequence_guard()); + + return msSequenceCount; + } + + + qint64 LoggingEvent::startTime() + { + return InitialisationHelper::startTime(); + } + + + void LoggingEvent::setThreadNameToCurrent() + { + if (QThread::currentThread()) + mThreadName = QThread::currentThread()->objectName(); + } + + + qint64 LoggingEvent::nextSequenceNumber() + { + QMutexLocker locker(sequence_guard()); + + return ++msSequenceCount; + } + + + qint64 LoggingEvent::msSequenceCount = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, const LoggingEvent &rLoggingEvent) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLoggingEvent.mLevel + << rLoggingEvent.loggerName() + << rLoggingEvent.mMessage + << rLoggingEvent.mNdc + << rLoggingEvent.mProperties + << rLoggingEvent.mSequenceNumber + << rLoggingEvent.mThreadName + << rLoggingEvent.mTimeStamp; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, LoggingEvent &rLoggingEvent) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString logger; + stream >> rLoggingEvent.mLevel + >> logger + >> rLoggingEvent.mMessage + >> rLoggingEvent.mNdc + >> rLoggingEvent.mProperties + >> rLoggingEvent.mSequenceNumber + >> rLoggingEvent.mThreadName + >> rLoggingEvent.mTimeStamp; + if (logger.isEmpty()) + rLoggingEvent.mpLogger = 0; + else + rLoggingEvent.mpLogger = Logger::logger(logger); + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent) + { + QString logger; + if (rLoggingEvent.logger() != 0) + logger = rLoggingEvent.logger()->name(); + + debug.nospace() << "LoggingEvent(" + << "level:" << rLoggingEvent.level().toString() << " " + << "logger:" << logger << " " + << "message:" << rLoggingEvent.message() << " " + << "sequencenumber:" << rLoggingEvent.sequenceNumber() << " " + << "threadname:" << rLoggingEvent.threadName() << " " + << "timestamp:" << rLoggingEvent.timeStamp() + << "(" << DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()) << ")" + << "sequenceCount:" << rLoggingEvent.sequenceCount() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/loggingevent.h b/GC-3.6.1-T2/src/log4qt/loggingevent.h new file mode 100644 index 0000000..87e2ed6 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/loggingevent.h @@ -0,0 +1,221 @@ +/****************************************************************************** +* +* package: Log4Qt +* file: loggingevent.h +* created: September 2007 +* author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * +******************************************************************************/ + +#ifndef LOG4QT_LOG4QTEVENT_H +#define LOG4QT_LOG4QTEVENT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggingEvent is the internal representation of a + * logging event. + * + * The class uses milliseconds since 1970-01-01T00:00:00, Coordinated + * Universal Time for time values. For converstion from and to QDateTime + * use DateTime. + */ + class LoggingEvent + { + public: + LoggingEvent(); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp); + // LoggingEvent(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + // virtual ~LoggingEvent(); // Use compiler default + // LoggingEvent &operator=(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + + // JAVA: QString fqnOfLoggerClass() const; + Level level() const; + // LocationInformation locationInformation() const; + const Logger *logger() const; + QString message() const; + QHash mdc() const; + QString ndc() const; + QHash properties() const; + qint64 sequenceNumber() const; + QString threadName() const; + // JAVA: ThrowableInformation throwableInformation() const; + qint64 timeStamp() const; + + // JAVA: bool locationInformationExists() const; + QString loggerName() const; + QString property(const QString &rKey) const; + QStringList propertyKeys() const; + void setProperty(const QString &rKey, const QString &rValue); + // JAVA: QString throwableStrRep() const; + QString toString() const; + static qint64 sequenceCount(); + static qint64 startTime(); + + private: + void setThreadNameToCurrent(); + static qint64 nextSequenceNumber(); + + private: + Level mLevel; + const Logger *mpLogger; + QString mMessage; + QString mNdc; + QHash mProperties; + qint64 mSequenceNumber; + QString mThreadName; + qint64 mTimeStamp; + static qint64 msSequenceCount; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + friend QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LoggingEvent + * + * Writes the given error \a rLoggingEvent to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + + /*! + * \relates LoggingEvent + * + * Reads an error from the given stream \a rStream into the given + * error \a rLoggingEvent, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggingEvent + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LoggingEvent(level:"WARN" logger:"Log4Qt::Properties" + * message:"Unknown escape sequence '\j' in property starting at line 1" + * sequencenumber:14 threadname:"main" + * timestamp:1194337148937(QDateTime("Tue Nov 6 03:19:08 2007") ) + * sequenceCount: 14 ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Level LoggingEvent::level() const + { return mLevel; } + + inline const Logger *LoggingEvent::logger() const + { return mpLogger; } + + inline QString LoggingEvent::message() const + { return mMessage; } + + inline QHash LoggingEvent::mdc() const + { return mProperties; } + + inline QString LoggingEvent::ndc() const + { return mNdc; } + + inline QHash LoggingEvent::properties() const + { return mProperties; } + + inline qint64 LoggingEvent::sequenceNumber() const + { return mSequenceNumber; } + + inline QString LoggingEvent::threadName() const + { return mThreadName; } + + inline qint64 LoggingEvent::timeStamp() const + { return mTimeStamp; } + + inline QString LoggingEvent::property(const QString &rKey) const + { return mProperties.value(rKey); } + + inline QStringList LoggingEvent::propertyKeys() const + { return QStringList(mProperties.keys()); } + + inline void LoggingEvent::setProperty(const QString &rKey, const QString &rValue) + { mProperties.insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LoggingEvent) +Q_DECLARE_TYPEINFO(Log4Qt::LoggingEvent, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LOG4QTEVENT_H diff --git a/GC-3.6.1-T2/src/log4qt/logmanager.cpp b/GC-3.6.1-T2/src/log4qt/logmanager.cpp new file mode 100644 index 0000000..2c5e9ba --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/logmanager.cpp @@ -0,0 +1,504 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logmanager.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/hierarchy.h" +#include "log4qt/propertyconfigurator.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelrangefilter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) + LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) + + + + /************************************************************************** + * Class implementation: LogManager + **************************************************************************/ + + + LogManager::LogManager() : + mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() + mpLoggerRepository(new Hierarchy()), + mHandleQtMessages(false), + mOldQtMsgHandler(0) + { + } + + + LogManager::~LogManager() + { + static_logger()->warn("Unexpected destruction of LogManager"); + + // doSetConfigureHandleQtMessages(false); + // delete mpLoggerRepository; + } + + + Logger *LogManager::rootLogger() + { + return instance()->mpLoggerRepository->rootLogger(); + } + + + QList LogManager::loggers() + { + return instance()->mpLoggerRepository->loggers(); + } + + + Level LogManager::threshold() + { + return instance()->mpLoggerRepository->threshold(); + } + + + void LogManager::setThreshold(Level level) + { + instance()->mpLoggerRepository->setThreshold(level); + } + + + bool LogManager::exists(const char *pName) + { + return instance()->mpLoggerRepository->exists(QLatin1String(pName)); + } + + + LogManager *LogManager::instance() + { + // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive + // to construct, an exit handler must be set and doStartup must be + // called. + + if (!mspInstance) + { + QMutexLocker locker(singleton_guard()); + if (!mspInstance) + { + mspInstance = new LogManager; + // qAddPostRoutine(shutdown); + atexit(shutdown); + mspInstance->doConfigureLogLogger(); + mspInstance->welcome(); + mspInstance->doStartup(); + } + } + return mspInstance; + } + + + Logger *LogManager::logger(const QString &rName) + { + return instance()->mpLoggerRepository->logger(rName); + } + + + void LogManager::resetConfiguration() + { + setHandleQtMessages(false); + instance()->mpLoggerRepository->resetConfiguration(); + configureLogLogger(); + } + + + const char* LogManager::version() + { + return LOG4QT_VERSION_STR; + } + + + void LogManager::shutdown() + { + instance()->mpLoggerRepository->shutdown(); + } + + + void LogManager::doSetHandleQtMessages(bool handleQtMessages) + { + QMutexLocker locker(&mObjectGuard); + + if (instance()->mHandleQtMessages == handleQtMessages) + return; + + instance()->mHandleQtMessages = handleQtMessages; + if (instance()->mHandleQtMessages) + { + static_logger()->trace("Activate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); +#else + instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); +#endif + } + else + { + static_logger()->trace("Deactivate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + qInstallMsgHandler(instance()->mOldQtMsgHandler); +#else + qInstallMessageHandler(instance()->mOldQtMsgHandler); +#endif + } + } + + + void LogManager::doConfigureLogLogger() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Level + QString value = InitialisationHelper::setting(QLatin1String("Debug"), + QLatin1String("ERROR")); + logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); + + // Common layout + TTCCLayout *p_layout = new TTCCLayout(); + p_layout->setName(QLatin1String("LogLog TTCC")); + p_layout->setContextPrinting(false); + p_layout->activateOptions(); + + // Common deny all filter + Filter *p_denyall = new DenyAllFilter(); + p_denyall->activateOptions(); + + // ConsoleAppender on stdout for all events <= INFO + ConsoleAppender *p_appender; + LevelRangeFilter *p_filter; + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::NULL_INT); + p_filter->setLevelMax(Level::INFO_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stdout")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + + // ConsoleAppender on stderr for all events >= WARN + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::WARN_INT); + p_filter->setLevelMax(Level::OFF_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stderr")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + } + + + void LogManager::doStartup() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Override + QString default_value = QLatin1String("false"); + QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), + default_value); + if (value != default_value) + { + static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); + return; + } + + // Configuration using setting Configuration + value = InitialisationHelper::setting(QLatin1String("Configuration")); + if (QFile::exists(value)) + { + static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); + PropertyConfigurator::configure(value); + return; + } + + // Configuration using setting + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + QSettings s; + s.beginGroup(log4qt_group); + if (s.childGroups().contains(properties_group)) + { + const QString group(QLatin1String("Log4Qt/Properties")); + static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); + s.beginGroup(properties_group); + PropertyConfigurator::configure(s); + return; + } + } + + // Configuration using default file + const QString default_file(QLatin1String("log4qt.properties")); + if (QFile::exists(default_file)) + { + static_logger()->debug("Default initialisation configures from default file '%1'", default_file); + PropertyConfigurator::configure(default_file); + return; + } + + static_logger()->debug("Default initialisation leaves package unconfigured"); + } + + + void LogManager::welcome() + { + static_logger()->info(qPrintable(QObject::tr("Initialising Log4Qt %1")), + QLatin1String(LOG4QT_VERSION_STR)); + + // Debug: Info + if (static_logger()->isDebugEnabled()) + { + // Create a nice timestamp with UTC offset + DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); + QString offset; + { + QDateTime utc = start_time.toUTC(); + QDateTime local = start_time.toLocalTime(); + QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); + int min = utc.secsTo(local_as_utc) / 60; + if (min < 0) + offset += QLatin1Char('-'); + else + offset += QLatin1Char('+'); + min = abs(min); + offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); + offset += QLatin1Char(':'); + offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); + } + static_logger()->debug("Program startup time is %1 (UTC%2)", + start_time.toString(QLatin1String("ISO8601")), + offset); + static_logger()->debug("Internal logging uses the level %1", + logLogger()->level().toString()); + } + + // Trace: Dump settings + if (static_logger()->isTraceEnabled()) + { + static_logger()->trace("Settings from the system environment:"); + QString entry; + Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) + static_logger()->trace(" %1: '%2'", + entry, + InitialisationHelper::environmentSettings().value(entry)); + + static_logger()->trace("Settings from the application settings:"); + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + static_logger()->trace(" %1:", log4qt_group); + QSettings s; + s.beginGroup(log4qt_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + static_logger()->trace(" %1/%2:", log4qt_group, properties_group); + s.beginGroup(properties_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + } else + static_logger()->trace(" QCoreApplication::instance() is not available"); + } + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) + { + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, pMessage); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#else + void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) + { + Q_UNUSED(context); + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, message); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, message.toUtf8().constData()); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#endif + + + + LogManager *LogManager::mspInstance = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const LogManager &rLogManager) + { + Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 + QList loggers = rLogManager.loggers(); + debug.nospace() << "LogManager(" + << "loggerrepository:" << *rLogManager.loggerRepository() + << "log-level:" << rLogManager.logLogger()->level().toString() + << "log-appenders:" << rLogManager.logLogger()->appenders().count() + << "qt-level:" << rLogManager.qtLogger()->level().toString() + << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() + << "handleqtmessages:" << rLogManager.handleQtMessages() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/logmanager.h b/GC-3.6.1-T2/src/log4qt/logmanager.h new file mode 100644 index 0000000..27111a0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/logmanager.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGMANAGER_H +#define LOG4QT_LOGMANAGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include +#include "log4qt/level.h" +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggerRepository; + + /*! + * \brief The class LogManager manages Logger in the default + * LoggerRepository. + * + * The LogManager manages logger in a single Hierarchy instance. It + * provides access to special logger over the logLogger(), qtLogger() + * and rootLogger() member functions. + * + * The LogManager is handling the initialisation on startup. The + * initialisation procedure will first attempt to configure the package + * based on environment variables. If the attempt fails it will check for + * the existence of configuration files in several location. For detailed + * description of the initialisation procedure see \ref Init + * "Initialization procedure". + * + * Messages created by qDebug(), qWarning(), qCritical() and qFatal() can + * be can be handled by the LogManager. By default the message handling + * is disabled. It can be enabled by calling setHandleQtMessages(). Once + * enabled all messages are logged using the logger qtLogger(). + * + * The Log4Qt runtime version is accessible over version(). The macros + * \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION" and + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" provide the + * compile time version. + * + * \note All the functions declared in this class are thread-safe. + */ + class LogManager + { + private: + LogManager(); + LogManager(const LogManager &rOther); // Not implemented + virtual ~LogManager(); + LogManager &operator=(const LogManager &rOther); // Not implemented + + public: + /*! + * Returns if the handling of messages created by calls to qDebug(), + * qWarning(), qCritical() and qFatal() is activated. + * + * \sa setHandleQtMessages() + */ + static bool handleQtMessages(); + + static LoggerRepository *loggerRepository(); + + /*! + * Returns the logger used for logging internal messages. See + * \ref LogLog "Logging within the package" for more details. + * + * Calling this function is equivalent to calling logger("Log4Qt"). + */ + static Logger *logLogger(); + + /*! + * Returns a pointer to the logger used for logging messages created by + * calls to qDebug(), qWarning(), qCritical() and qFatal(). + * + * Calling this function is equivalent to calling logger("Qt"). + * + * \sa setHandleQtMessages() + */ + static Logger *qtLogger(); + + static Logger *rootLogger(); + static QList loggers(); + static Level threshold(); + static void setThreshold(Level level); + + /*! + * Activates or deactivates the handling of messages created by calls + * to qDebug(), qWarning(), qCritical() and qFatal() is activated. + * + * If activated, a Qt message handler is installed. Messages are logged + * using the logger returned by qtLogger(). For fatal messages the same + * exit procedure is implemented as for qFatal(). + * + * The following mappping is used from QtMsgType to Level: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    QtMsgType     %Level
QtDebugMsg Level::DEBUG_INT
QtWarningMsg Level::WARN_INT
QtCriticalMsg Level::ERROR_INT
QtFatalMsg Level::FATAL_INT
QtSystemMsg Level::TRACE_INT
+ * + * The default value is false for not handling Qt messages. + * + * \sa handleQtMessages(), qInstallMsgHandler(), qFatal() + */ + static void setHandleQtMessages(bool handleQtMessages); + + /*! + * Configures the logging for the package to its default behaviour. + * + * The logger logLogger() is configured to be not additive. Messages + * with the level Level::ERROR_INT and Level::FATAL_INT are written + * to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is + * read from the system environment or application settings using + * InitialisationHelper::setting() with the key \c Debug. If a level + * value is found, but it is not a valid Level string, + * Level::DEBUG_INT is used. If no level string is found + * Level::ERROR_INT is used. + * + * The function does not remove any appender from the logger + * logLogger(). + * + * \sa \ref LogLog "Logging within the package", + * \ref Env "Environment Variables", + * resetConfiguration(), InitialisationHelper::setting() + */ + static void configureLogLogger(); + + static bool exists(const char *pName); + // JAVA: void fireAddAppenderEvent(Logger *pLogger, Appender *pAppender); + + /*! + * Returns the LogManager instance. + */ + static LogManager *instance(); + + static Logger *logger(const QString &rName); + + /*! + * Reset all values contained in logger repository to their default. + * + * All appenders are removed from all loggers. The loggers are handled + * in no particular order. The last loggers to be reset are qtLogger(), + * logLogger() and rootLogger() in that order. + * + * The handling of messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() is deactivated. + * + * The internal logging is initialised to its default bahaviour + * using configureLogLogger(). + * + * \sa LoggerRepository::resetConfiguration(), setHandleQtMessages(), + * configureLogLogger() + */ + static void resetConfiguration(); + + static void shutdown(); + + /*! + * Executes the default initialisation procedure of the package. + * + * The function will test for the setting \c DefaultInitOverride in + * the system environment and application settings using + * \ref InitialisationHelper::setting(). If the value is present and + * set to anything else then \c false, the initialisation is aborted. + *
+ * The system environment and application settings are tested for the + * setting \c Configuration. If it is found and it is a valid path to + * a file, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting + * \c Configuration is not available and a QCoreApplication object is + * present, the application settings are tested for a group + * \c Log4Qt/Properties. If the group exists, the package is configured + * with the setting using the + * \ref PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration + * file nor configuration settings could be found, the current working + * directory is searched for the file \c "log4qt.properties". If it is + * found, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * \sa \ref Init "Initialization procedure", + * \ref Env "Environment Variables", + * InitialisationHelper::setting() + */ + static void startup(); + + /*! + * Returns the version number of Log4Qt at run-time. This may be a + * different version than the version the application was compiled + * against. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" + + */ + static const char* version(); + + private: + void doSetHandleQtMessages(bool handleQtMessages); + void doConfigureLogLogger(); + void doStartup(); + void welcome(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + static void qtMessageHandler(QtMsgType type, + const char *pMessage); +#else + static void qtMessageHandler(QtMsgType type, + const QMessageLogContext &context, + const QString &message); +#endif + + + private: + mutable QMutex mObjectGuard; + LoggerRepository *mpLoggerRepository; + Logger *mpNullLogger; + bool mHandleQtMessages; +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QtMsgHandler mOldQtMsgHandler; +#else + QtMessageHandler mOldQtMsgHandler; +#endif + static LogManager *mspInstance; + }; + + + /*************************************************************************** + * Operators, Helper + ***************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogManager + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %LogManager(loggerrepository:Hierarchy(loggers:6 root-level:"DEBUG" + * root-appenders:0 log-level: "NULL" log-appenders:0 + * qt-level: "NULL" qt-appenders:0 handleqtmessages: false ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogManager &rLogManager); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LoggerRepository *LogManager::loggerRepository() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mpLoggerRepository; } + + inline bool LogManager::handleQtMessages() + { // QMutexLocker locker(&instance()->mObjectGuard); // Read/Write of bool is safe + return instance()->mHandleQtMessages; } + + inline Logger *LogManager::logLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Log4Qt")); } + + inline Logger *LogManager::qtLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Qt")); } + + inline void LogManager::setHandleQtMessages(bool handleQtMessages) + { instance()->doSetHandleQtMessages(handleQtMessages); } + + inline void LogManager::configureLogLogger() + { instance()->doConfigureLogLogger(); } + + inline void LogManager::startup() + { instance()->doStartup(); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogManager, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGMANAGER_H diff --git a/GC-3.6.1-T2/src/log4qt/mdc.cpp b/GC-3.6.1-T2/src/log4qt/mdc.cpp new file mode 100644 index 0000000..5ba2ba8 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/mdc.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/mdc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: MDC + **************************************************************************/ + + + QString MDC::get(const QString &rKey) + { + if (!instance()->mHash.hasLocalData()) + return QString(); + + return instance()->mHash.localData()->value(rKey); + } + + + QHash MDC::context() + { + if (!instance()->mHash.hasLocalData()) + return QHash(); + + return *instance()->mHash.localData(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(MDC) + + + QHash *MDC::localData() + { + if (!instance()->mHash.hasLocalData()) + instance()->mHash.setLocalData(new QHash); + return instance()->mHash.localData(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const MDC &rMDC) + { + Q_UNUSED(rMDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "MDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "context:" << rMDC.context() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/mdc.h b/GC-3.6.1-T2/src/log4qt/mdc.h new file mode 100644 index 0000000..5e8fce9 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/mdc.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_MDC_H +#define LOG4QT_MDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + +/*! + * \brief The class MDC implements a mapped diagnostic context. + * + * \note All the functions declared in this class are thread-safe. + */ + class MDC + { + private: + MDC(); + MDC(const MDC &rOther); // Not implemented + // virtual ~MDC(); // Use compiler default + MDC &operator=(const MDC &rOther); // Not implemented + + public: + static QString get(const QString &rKey); + static QHash context(); + + /*! + * Returns the MDC instance. + */ + static MDC *instance(); + + static void put(const QString &rKey, const QString &rValue); + static void remove(const QString &rKey); + + private: + static QHash *localData(); + + private: + QThreadStorage< QHash * > mHash; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates MDC + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %MDC(thread:"main" context:QHash(("login", "Peter")("database", "UAT")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const MDC &rMDC); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline MDC::MDC() : + mHash() + {} + + inline void MDC::put(const QString &rKey, const QString &rValue) + { localData()->insert(rKey, rValue); } + + inline void MDC::remove(const QString &rKey) + { localData()->remove(rKey); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::MDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_MDC_H diff --git a/GC-3.6.1-T2/src/log4qt/ndc.cpp b/GC-3.6.1-T2/src/log4qt/ndc.cpp new file mode 100644 index 0000000..17ebd47 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/ndc.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ndc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt:NDC) + + + + /************************************************************************** + * Class implementation: NDC + **************************************************************************/ + + + void NDC::clear() + { + if (!instance()->mStack.hasLocalData()) + return; + + instance()->mStack.localData()->clear(); + } + + + int NDC::depth() + { + if (!instance()->mStack.hasLocalData()) + return 0; + + return instance()->mStack.localData()->count(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(NDC) + + + QString NDC::pop() + { + if (!instance()->mStack.hasLocalData() || instance()->mStack.localData()->isEmpty()) + { + logger()->warn("Requesting pop from empty NDC stack"); + return QString(); + } + + return instance()->mStack.localData()->pop(); + } + + + void NDC::push(const QString &rMessage) + { + if (!instance()->mStack.hasLocalData()) + instance()->mStack.setLocalData(new QStack); + + instance()->mStack.localData()->push(rMessage); + } + + + void NDC::setMaxDepth(int maxDepth) + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->size() <= maxDepth) + return; + + instance()->mStack.localData()->resize(maxDepth); + } + + + QString NDC::peek() + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->isEmpty()) + return QString(); + + return instance()->mStack.localData()->top(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const NDC &rNDC) + { + Q_UNUSED(rNDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "NDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "peek:" << rNDC.peek() << " " + << "depth:" << rNDC.depth() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/ndc.h b/GC-3.6.1-T2/src/log4qt/ndc.h new file mode 100644 index 0000000..e2c4210 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/ndc.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NDC_H +#define LOG4QT_NDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class NDC implements a nested diagnostic context. + * + * The method remove() is not required. QThreadStorage cleans up on thread + * exit. + * + * \note All the functions declared in this class are thread-safe. + */ + class NDC + { + private: + NDC(); + NDC(const NDC &rOther); // Not implemented + // virtual ~NDC(); // Use compiler default + NDC &operator=(const NDC &rOther); // Not implemented + + public: + static void clear(); + // JAVA: static QStack cloneStack(); + // JAVA: static QString get(); + static int depth(); + // JAVA: inherit(Stack stack) + + /*! + * Returns the NDC instance. + */ + static NDC *instance(); + + static QString pop(); + static void push(const QString &rMessage); + // JAVA: static void remove(); // Not required + static void setMaxDepth(int maxDepth); + static QString peek(); + + private: + QThreadStorage< QStack * > mStack; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates NDC + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NDC(thread:"main" peek:"i = 3" depth:4) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const NDC &rNDC); + #endif // QT_NO_DEBUG_STREAM + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + inline NDC::NDC() : + mStack() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NDC_H diff --git a/GC-3.6.1-T2/src/log4qt/patternlayout.cpp b/GC-3.6.1-T2/src/log4qt/patternlayout.cpp new file mode 100644 index 0000000..a93099f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/patternlayout.cpp @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/patternlayout.h" + +#include +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: PatternLayout + **************************************************************************/ + + + PatternLayout::PatternLayout(QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(DEFAULT_CONVERSION_PATTERN); + } + + + PatternLayout::PatternLayout(const QString &rPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(rPattern); + } + + + PatternLayout::PatternLayout(ConversionPattern conversionPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(conversionPattern); + } + + + PatternLayout::~PatternLayout() + { + delete mpPatternFormatter; + } + + + void PatternLayout::setConversionPattern(ConversionPattern conversionPattern) + { + switch (conversionPattern) + { + case DEFAULT_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%m%n")); + break; + case TTCC_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%r [%t] %p %c %x - %m%n")); + break; + default: + Q_ASSERT_X(false, "PatternLayout::setConversionFormat", "Unkown ConversionFormat"); + setConversionPattern(QString()); + } + } + + + QString PatternLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "PatternLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void PatternLayout::updatePatternFormatter() + { + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(mPattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug PatternLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "PatternLayout(" + << "name:" << name() << " " + << "pattern:" << conversionPattern() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/patternlayout.h b/GC-3.6.1-T2/src/log4qt/patternlayout.h new file mode 100644 index 0000000..2152f4b --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/patternlayout.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNLAYOUT_H +#define LOG4QT_PATTERNLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class PatternFormatter; + + /*! + * \brief The class PatternLayout outputs a logging event based on a + * pattern string. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class PatternLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds the conversion pattern used by the appender. + * + * The default is "%m%n". + * + * \sa conversionPattern(), setConversionPattern() + */ + Q_PROPERTY(QString conversionPattern READ conversionPattern WRITE setConversionPattern) + + public: + /*! + * The enum ConversionPattern defines constants for pattern strings. + * + * \sa setConversionPattern(ConversionPattern); + */ + enum ConversionPattern + { + /*! The default conversion pattern string is "%m,%n". */ + DEFAULT_CONVERSION_PATTERN, + /*! + * The ttcc conversion pattern string is + * "%r [%t] %p %c %x - %m%n". + */ + TTCC_CONVERSION_PATTERN, + }; + Q_ENUMS(ConversionPattern) + + PatternLayout(QObject *pParent = 0); + PatternLayout(const QString &rPattern, + QObject *pParent = 0); + + /*! + * Creates a PatternLayout with the conversion pattern value specified + * by the \a conversionPattern constant. + */ + PatternLayout(ConversionPattern conversionPattern, + QObject *pParent = 0); + + virtual ~PatternLayout(); + private: + PatternLayout(const PatternLayout &rOther); // Not implemented + PatternLayout &operator=(const PatternLayout &rOther); // Not implemented + + public: + QString conversionPattern() const; + void setConversionPattern(const QString &rPattern); + + /*! + * Sets the conversion pattern to the value specified by the + * \a conversionPattern constant. + */ + void setConversionPattern(ConversionPattern conversionPattern); + + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %PatternLayout(name:"PL" pattern:"%r [%t] %p %c %x - %m%n" + * "referencecount:3") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + QString mPattern; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString PatternLayout::conversionPattern() const + { return PatternLayout::mPattern; } + + inline void PatternLayout::setConversionPattern(const QString &rPattern) + { mPattern = rPattern; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::PatternLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PATTERNLAYOUT_H diff --git a/GC-3.6.1-T2/src/log4qt/propertyconfigurator.cpp b/GC-3.6.1-T2/src/log4qt/propertyconfigurator.cpp new file mode 100644 index 0000000..76f3ee0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/propertyconfigurator.cpp @@ -0,0 +1,588 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/propertyconfigurator.h" + +#include +#include +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/factory.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/appender.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/logmanager.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator) + + + + /************************************************************************** + * Class implementation: PropertyConfigurator + **************************************************************************/ + + + bool PropertyConfigurator::doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromProperties(rProperties, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromFile(rConfigFileName, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromSettings(rSettings, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::configure(const Properties &rProperties) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rProperties); + } + + + bool PropertyConfigurator::configure(const QString &rConfigFilename) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rConfigFilename); + } + + + bool PropertyConfigurator::configure(const QSettings &rSettings) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rSettings); + } + + + bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName) + { + // Stop an existing watch to avoid a possible concurrent configuration + ConfiguratorHelper::setConfigurationFile(); + if (rConfigFileName.isEmpty()) + return true; + + PropertyConfigurator configurator; + bool result = configurator.doConfigure(rConfigFileName); + ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure); + return result; + } + + + void PropertyConfigurator::configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + QFile file(rConfigFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"), + CONFIGURATOR_OPENING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + Properties properties; + properties.load(&file); + if (file.error()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"), + CONFIGURATOR_READING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + if (!pLoggerRepository) + pLoggerRepository = LogManager::loggerRepository(); + + configureGlobalSettings(rProperties, pLoggerRepository); + configureRootLogger(rProperties, pLoggerRepository); + configureNonRootElements(rProperties, pLoggerRepository); + mAppenderRegistry.clear(); + } + + + void PropertyConfigurator::configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + Properties properties; + properties.load(rSettings); + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null."); + + const QLatin1String key_reset("log4j.reset"); + const QLatin1String key_debug("log4j.Debug"); + const QLatin1String key_config_debug("log4j.configDebug"); + const QLatin1String key_threshold("log4j.threshold"); + const QLatin1String key_handle_qt_messages("log4j.handleQtMessages"); + + // Test each global setting and set it + // - Reset: log4j.reset + // - Debug: log4j.Debug, log4j.configDebug + // - Threshold: log4j.threshold + // - Handle Qt Messages: log4j.handleQtMessages + + // Reset + QString value = rProperties.property(key_reset); + if (!value.isEmpty() && OptionConverter::toBoolean(value, false)) + { + // Use LogManager and not pLoggerRepository to reset internal + // logging. + LogManager::resetConfiguration(); + logger()->debug("Reset configuration"); + } + + // Debug + value = rProperties.property(key_debug); + if (value.isNull()) + { + value = rProperties.property(key_config_debug); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug); + } + if (!value.isNull()) + { + // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting + bool ok; + Level level = Level::fromString(value, &ok); + if (!ok) + level = Level::DEBUG_INT; + LogManager::logLogger()->setLevel(level); + logger()->debug("Set level for Log4Qt logging to %1", + LogManager::logLogger()->level().toString()); + } + + // Threshold + value = rProperties.property(key_threshold); + if (!value.isNull()) + { + pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT)); + logger()->debug("Set threshold for LoggerRepository to %1", + pLoggerRepository->threshold().toString()); + } + + // Handle Qt messages + value = rProperties.property(key_handle_qt_messages); + if (!value.isNull()) + { + LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false)); + logger()->debug("Set handling of Qt messages LoggerRepository to %1", + QVariant(LogManager::handleQtMessages()).toString()); + } + } + + + void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null."); + + const QString logger_prefix = QLatin1String("log4j.logger."); + const QString category_prefix = QLatin1String("log4j.category."); + + // Iterate through all entries: + // - Test for the logger/category prefix + // - Convert JAVA class names to C++ ones + // - Parse logger data (Level, Appender) + // - Parse logger additivity + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + QString java_name; + if (key.startsWith(logger_prefix)) + java_name = key.mid(logger_prefix.length()); + else if (key.startsWith(category_prefix)) + java_name = key.mid(category_prefix.length()); + QString cpp_name = OptionConverter::classNameJavaToCpp(java_name); + if (!java_name.isEmpty()) + { + Logger *p_logger = pLoggerRepository->logger(cpp_name); + QString value = OptionConverter::findAndSubst(rProperties, key); + parseLogger(rProperties, p_logger, key, value); + parseAdditivityForLogger(rProperties, p_logger, java_name); + } + } + } + + + void PropertyConfigurator::configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null."); + + const QLatin1String key_root_logger("log4j.rootLogger"); + const QLatin1String key_root_category("log4j.rootCategory"); + + // - Test for the logger/category prefix + // - Parse logger data for root logger + + QString key = key_root_logger; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + key = key_root_category; + value = OptionConverter::findAndSubst(rProperties, key); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger); + } + + if (value.isNull()) + logger()->debug("Could not find root logger information. Is this correct?"); + else + parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value); + } + + + void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const + { + Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null."); + + const QLatin1String additivity_prefix("log4j.additivity."); + + // - Lookup additivity key for logger + // - Set additivity, if specified + + QString key = additivity_prefix + rLog4jName; + QString value = OptionConverter::findAndSubst(rProperties, key); + logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value); + if (!value.isEmpty()) + { + bool additivity = OptionConverter::toBoolean(value, true); + logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString()); + pLogger->setAdditivity(additivity); + } + } + + + LogObjectPtr PropertyConfigurator::parseAppender(const Properties &rProperties, + const QString &rName) + { + // - Test if appender has been parsed before + // - Find appender key + // - Create appender object + // - Set layout, if required by appender + // - Set properties + // - Activate options + // - Add appender to registry + + const QLatin1String appender_prefix("log4j.appender."); + + logger()->debug("Parsing appender named '%1'", rName); + + if (mAppenderRegistry.contains(rName)) + { + logger()->debug("Appender '%1' was already parsed.", rName); + return mAppenderRegistry.value(rName); + } + + QString key = appender_prefix + rName; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"), + CONFIGURATOR_MISSING_APPENDER_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rName; + logger()->error(e); + return 0; + } + LogObjectPtr p_appender = Factory::createAppender(value); + if (!p_appender) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"), + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rName; + logger()->error(e); + return 0; + } + p_appender->setName(rName); + + if (p_appender->requiresLayout()) + { + LogObjectPtr p_layout = parseLayout(rProperties, key); + if (p_layout) + p_appender->setLayout(p_layout); + else + return 0; + } + + QStringList exclusions; + exclusions << QLatin1String("layout"); + setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender); + AppenderSkeleton *p_appenderskeleton = qobject_cast(p_appender); + if (p_appenderskeleton) + p_appenderskeleton->activateOptions(); + + mAppenderRegistry.insert(rName, p_appender); + return p_appender; + } + + + LogObjectPtr PropertyConfigurator::parseLayout(const Properties &rProperties, + const QString &rAppenderKey) + { + Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty."); + + // - Find layout key + // - Create layput object + // - Set properties + // - Activate options + + const QLatin1String layout_suffix(".layout"); + + logger()->debug("Parsing layout for appender named '%1'", rAppenderKey); + + QString key = rAppenderKey + layout_suffix; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"), + CONFIGURATOR_MISSING_LAYOUT_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rAppenderKey; + logger()->error(e); + return 0; + } + LogObjectPtr p_layout = Factory::createLayout(value); + if (!p_layout) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layout of class '%1' requested by appender '%2'"), + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rAppenderKey; + logger()->error(e); + return 0; + } + + QStringList exclusions; + setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout); + p_layout->activateOptions(); + + return p_layout; + } + + + void PropertyConfigurator::parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue) + { + Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null."); + Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty."); + + const QLatin1String keyword_inherited("INHERITED"); + + // - Split value on comma + // - If level value, is specified + // - Test for NULL and INHERITED + // - Ensure root logger is not set to NULL + // - Set level + // - For each entry + // - Create Appender + + logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue); + QStringList appenders = rValue.split(QLatin1Char(',')); + QStringListIterator i (appenders); + + // First entry is the level. There will be always one entry, even if the rValue is + // empty or does not contain a comma. + QString value = i.next().trimmed(); + if (!value.isEmpty()) + { + Level level; + if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0) + level = Level::NULL_INT; + else + level = OptionConverter::toLevel(value, Level::DEBUG_INT); + if (level == Level::NULL_INT && pLogger->name() == QString()) + logger()->warn("The root logger level cannot be set to NULL."); + else + { + pLogger->setLevel(level); + logger()->debug("Set level for logger '%1' to '%2'", + pLogger->name(), pLogger->level().toString()); + } + } + + pLogger->removeAllAppenders(); + while(i.hasNext()) + { + value = i.next().trimmed(); + if(value.isEmpty()) + continue; + LogObjectPtr p_appender = parseAppender(rProperties, value); + if (p_appender) + pLogger->addAppender(p_appender); + } + } + + + void PropertyConfigurator::setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject) + { + Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty."); + Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null."); + + // Iterate through all entries: + // - Test for prefix to determine, if setting is for object + // - Skip empty property name + // - Skip property names in exclusion list + // - Set property on object + + logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'", + QLatin1String(pObject->metaObject()->className()), + rPrefix); + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + if (!key.startsWith(rPrefix)) + continue; + QString property = key.mid(rPrefix.length()); + if (property.isEmpty()) + continue; + QStringList split_property = property.split(QLatin1Char('.')); + if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive)) + continue; + QString value = OptionConverter::findAndSubst(rProperties, key); + Factory::setObjectProperty(pObject, property, value); + } + } + + + void PropertyConfigurator::startCaptureErrors() + { + Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty."); + + mpConfigureErrors = new ListAppender; + mpConfigureErrors->setName(QLatin1String("PropertyConfigurator")); + mpConfigureErrors->setConfiguratorList(true); + mpConfigureErrors->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(mpConfigureErrors); + } + + + bool PropertyConfigurator::stopCaptureErrors() + { + Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty."); + + LogManager::logLogger()->removeAppender(mpConfigureErrors); + ConfiguratorHelper::setConfigureError(mpConfigureErrors->list()); + bool result = (mpConfigureErrors->list().count() == 0); + mpConfigureErrors = 0; + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator) + { + Q_UNUSED(rPropertyConfigurator); + debug.nospace() << "PropertyConfigurator(" + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Logging diff --git a/GC-3.6.1-T2/src/log4qt/propertyconfigurator.h b/GC-3.6.1-T2/src/log4qt/propertyconfigurator.h new file mode 100644 index 0000000..ddf45e5 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/propertyconfigurator.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTYCONFIGURATOR_H +#define LOG4QT_PROPERTYCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QSettings; + +namespace Log4Qt +{ + + class Appender; + class Layout; + class ListAppender; + class Logger; + class Properties; + class LoggerRepository; + + /*! + * \brief The class PropertyConfigurator allows the configuration of the + * package from a JAVA properties file. + * + * \note All the functions declared in this class are thread-safe. + */ + class PropertyConfigurator + { + public: + PropertyConfigurator(); + // virtual ~PropertyConfigurator(); // Use compiler default + private: + PropertyConfigurator(const PropertyConfigurator &rOther); // Not implemented + PropertyConfigurator &operator=(const PropertyConfigurator &rOther); // Not implemented + + public: + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository = 0); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository = 0); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + bool doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository = 0); + + // JAVA: void doConfigure(const QUrl &rUrl, LoggerRepository *pLoggerRepository); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const Properties &rProperties); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const QString &rConfigFilename); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref doConfigure(const QSettings &, LoggerRepository *) "doConfigure()", + * \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + static bool configure(const QSettings &rSettings); + + // JAVA: static void configure(const QUrl &rUrl); + + /*! + * \sa ConfiguratorHelper::configureError(), + * ConfiguratorHelper::configurationFile() + */ + static bool configureAndWatch(const QString &rConfigFilename); + + private: + void configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository); + void configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository); + void configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const; + void configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const; + LogObjectPtr parseAppender(const Properties &rProperties, + const QString &rName); + LogObjectPtr parseLayout(const Properties &rProperties, + const QString &rAppenderName); + void parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue); + void setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject); + void startCaptureErrors(); + bool stopCaptureErrors(); + + private: + LogObjectPtr mpConfigureErrors; + QHash< QString, LogObjectPtr > mAppenderRegistry; + }; + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PropertyConfigurator + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * + * %PropertyConfigurator() + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline PropertyConfigurator::PropertyConfigurator() + {} + + +} // namspace Logging + + +// Q_DECLARE_TYPEINFO(Log4Qt::PropertyConfigurator, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PROPERTYCONFIGURATOR_H diff --git a/GC-3.6.1-T2/src/log4qt/rollingfileappender.cpp b/GC-3.6.1-T2/src/log4qt/rollingfileappender.cpp new file mode 100644 index 0000000..f9fac5f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/rollingfileappender.cpp @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/rollingfileappender.h" + +#include +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************ + Declarations + *************************************************************************/ + + + + /************************************************************************ + C helper functions + *************************************************************************/ + + + + /************************************************************************ + Class implementation: RollingFileAppender + *************************************************************************/ + + + RollingFileAppender::RollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + FileAppender(pLayout, rFileName, append, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::~RollingFileAppender() + { + close(); + } + + + void RollingFileAppender::setMaxFileSize(const QString &rMaxFileSize) + { + bool ok; + qint64 max_file_size = OptionConverter::toFileSize(rMaxFileSize, &ok); + if (ok) + setMaximumFileSize(max_file_size); + } + + QString RollingFileAppender::maxFileSize() + { + return QString("%1").arg(maximumFileSize()); + } + + + void RollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller") + + FileAppender::append(rEvent); + if (writer()->device()->size() > this->mMaximumFileSize) + rollOver(); + } + + + void RollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "RollingFileAppender::rollOver()", "Lock must be held by caller") + + logger()->debug("Rolling over with maxBackupIndex = %1", mMaxBackupIndex); + + closeFile(); + + QFile f; + f.setFileName(file() + QLatin1Char('.') + QString::number(mMaxBackupIndex)); + if (f.exists() && !removeFile(f)) + return; + + QString target_file_name; + int i; + for (i = mMaxBackupIndex - 1; i >=1; i--) + { + f.setFileName(file() + QLatin1Char('.') + QString::number(i)); + if (f.exists()) + { + target_file_name = file() + QLatin1Char('.') + QString::number(i + 1); + if (!renameFile(f, target_file_name)) + return; + } + } + + f.setFileName(file()); + target_file_name = file() + QLatin1String(".1"); + if (!renameFile(f, target_file_name)) + return; + + openFile(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug RollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "RollingFileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "maxbackupindex:" << maxBackupIndex() << " " + << "maximumfilesize:" << maximumFileSize() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/rollingfileappender.h b/GC-3.6.1-T2/src/log4qt/rollingfileappender.h new file mode 100644 index 0000000..47848a4 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/rollingfileappender.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_ROLINGFILEAPPENDER_H +#define LOG4QT_ROLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class RollingFileAppender extends FileAppender to backup + * the log files when they reach a certain size. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class RollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the maximum backup count used by the appender. + * + * The default is 1. + * + * \sa maxBackupIndex(), setMaxBackupIndex() + */ + Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex) + + /*! + * The property holds the maximum file size used by the appender. + * + * The default is 10 MB (10 * 1024 * 1024). + * + * \sa maximumFileSize(), setMaximumFileSize() + */ + Q_PROPERTY(qint64 maximumFileSize READ maximumFileSize WRITE setMaximumFileSize) + + /*! + * The property sets the maximum file size from a string value. + * + * \sa setMaxFileSize(), maximumFileSize() + */ + Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize) + + public: + RollingFileAppender(QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + virtual ~RollingFileAppender(); + private: + RollingFileAppender(const RollingFileAppender &rOther); // Not implemented + RollingFileAppender &operator=(const RollingFileAppender &rOther); // Not implemented + + public: + int maxBackupIndex() const; + qint64 maximumFileSize() const; + void setMaxBackupIndex(int maxBackupIndex); + void setMaximumFileSize(qint64 maximumFileSize); + QString maxFileSize(); + void setMaxFileSize(const QString &rMaxFileSize); + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %RollingFileAppender(name:"RFA" appendfile:false bufferedio:true + * encoding:"" file:"/log.txt" filter: 0x0 + * immediateflush:true isactive:true + * isclosed:false layout:"TTCC" maxbackupindex:2 + * maximumfilesize:40 referencecount:1 + * threshold:"NULL" writer:0x4175af8) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void rollOver(); + + private: + int mMaxBackupIndex; + qint64 mMaximumFileSize; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int RollingFileAppender::maxBackupIndex() const + { QMutexLocker locker(&mObjectGuard); + return mMaxBackupIndex; } + + inline qint64 RollingFileAppender::maximumFileSize() const + { QMutexLocker locker(&mObjectGuard); + return mMaximumFileSize; } + + inline void RollingFileAppender::setMaxBackupIndex(int maxBackupIndex) + { QMutexLocker locker(&mObjectGuard); + mMaxBackupIndex = maxBackupIndex; } + + inline void RollingFileAppender::setMaximumFileSize(qint64 maximumFileSize) + { QMutexLocker locker(&mObjectGuard); + mMaximumFileSize = maximumFileSize; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::RollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_ROLINGFILEAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/simplelayout.cpp b/GC-3.6.1-T2/src/log4qt/simplelayout.cpp new file mode 100644 index 0000000..a7d5234 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/simplelayout.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/simplelayout.h" + +#include +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: SimpleLayout + **************************************************************************/ + + + QString SimpleLayout::format(const LoggingEvent &rEvent) + { + return rEvent.level().toString() + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug SimpleLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "SimpleLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/simplelayout.h b/GC-3.6.1-T2/src/log4qt/simplelayout.h new file mode 100644 index 0000000..5ebe558 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/simplelayout.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_SIMPLELAYOUT_H +#define LOG4QT_SIMPLELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class SimpleLayout outputs the level and message of a logging + * event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class SimpleLayout : public Layout + { + Q_OBJECT + + public: + SimpleLayout(QObject *pParent = 0); + // virtual ~SimpleLayout(); // Use compiler default + private: + SimpleLayout(const SimpleLayout &rOther); // Not implemented + SimpleLayout &operator=(const SimpleLayout &rOther); // Not implemented + + public: + virtual QString format(const LoggingEvent &rEvent); + + protected: + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %SimpleLayout(name:"SL" referencecount:1) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline SimpleLayout::SimpleLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::SimpleLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_SIMPLELAYOUT_H diff --git a/GC-3.6.1-T2/src/log4qt/spi/filter.cpp b/GC-3.6.1-T2/src/log4qt/spi/filter.cpp new file mode 100644 index 0000000..8f2d10e --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/spi/filter.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/spi/filter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + void Filter::setNext(Filter *pFilter) + { + mpNext = pFilter; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/spi/filter.h b/GC-3.6.1-T2/src/log4qt/spi/filter.h new file mode 100644 index 0000000..0fd48f0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/spi/filter.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILTER_H +#define LOG4QT_FILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Filter is the base class for all filters. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Filter : public LogObject + { + Q_OBJECT + + /*! + * The property holds the next filter of this filter. + * + * The default is 0 for no next filter. + * + * \sa next(), setNext() + */ + Q_PROPERTY(Filter* next READ next WRITE setNext) + + public: + enum Decision + { + ACCEPT, + DENY, + NEUTRAL + }; + Q_ENUMS(Decision); + + public: + Filter(QObject *pObject = 0); + // Filter(const Filter &rOther); // Use compiler default + virtual ~Filter(); + // Filter &operator=(const Filter &rOther); // Use compiler default + + Filter* next() const; + void setNext(Filter *pFilter); + + virtual void activateOptions(); + virtual Decision decide(const LoggingEvent &rEvent) const = 0; + + private: + LogObjectPtr mpNext; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter::Filter(QObject *pObject) : + LogObject(pObject), + mpNext(0) + {} + + inline Filter::~Filter() + {} + + inline Filter* Filter::next() const + { return mpNext; } + + inline void Filter::activateOptions() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Filter, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_FILTER_H diff --git a/GC-3.6.1-T2/src/log4qt/ttcclayout.cpp b/GC-3.6.1-T2/src/log4qt/ttcclayout.cpp new file mode 100644 index 0000000..91baebc --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/ttcclayout.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ttcclayout.h" + +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: TTCCLayout + **************************************************************************/ + + + TTCCLayout::TTCCLayout(QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(RELATIVE); + } + + + TTCCLayout::TTCCLayout(const QString &rDateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(rDateFormat), + mThreadPrinting(true), + mpPatternFormatter(0) + { + } + + + TTCCLayout::TTCCLayout(DateFormat dateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(dateFormat); + } + + + TTCCLayout::~TTCCLayout() + { + delete mpPatternFormatter; + } + + + void TTCCLayout::setDateFormat(DateFormat dateFormat) + { + switch (dateFormat) + { + case NONE: + setDateFormat(QLatin1String("NONE")); + break; + case ISO8601: + setDateFormat(QLatin1String("ISO8601")); + break; + case ABSOLUTE: + setDateFormat(QLatin1String("ABSOLUTE")); + break; + case DATE: + setDateFormat(QLatin1String("DATE")); + break; + case RELATIVE: + setDateFormat(QLatin1String("RELATIVE")); + break; + default: + Q_ASSERT_X(false, "TTCCLayout::setDateFormat", "Unkown DateFormat"); + setDateFormat(QString()); + } + } + + + QString TTCCLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "TTCCLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void TTCCLayout::updatePatternFormatter() + { + QString pattern; + + pattern += QLatin1String("%d{") + mDateFormat + QLatin1String("}"); + if (mThreadPrinting) + pattern += QLatin1String(" [%t]"); + pattern += QLatin1String(" %-5p"); + if (mCategoryPrefixing) + pattern += QLatin1String(" %c"); + if (mContextPrinting) + pattern += QLatin1String(" %x"); + pattern += QLatin1String(" - %m%n"); + + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(pattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug TTCCLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "TTCCLayout(" + << "name:" << name() << " " + << "categoryprefixing:" << categoryPrefixing() << " " + << "contextprinting:" << contextPrinting() << " " + << "dateformat:" << dateFormat() << " " + << "referencecount:" << referenceCount() << " " + << "threadprinting:" << threadPrinting() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/ttcclayout.h b/GC-3.6.1-T2/src/log4qt/ttcclayout.h new file mode 100644 index 0000000..8987315 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/ttcclayout.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_TTCCLAYOUT_H +#define LOG4QT_TTCCLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + class PatternFormatter; + + /*! + * \brief The class TTCCLayout outputs the time, thread, logger and nested + * diagnostic context information of a logging event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class TTCCLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds if the logger name is part of the formatted output. + * + * The default value is true for including the logger name. + * + * \sa categoryPrefixing(), setCategoryPrefixing() + */ + Q_PROPERTY(bool categoryPrefixing READ categoryPrefixing WRITE setCategoryPrefixing) + + /*! + * The property holds if the nested context information is part of the + * formatted output. + * + * The default value it true for including the nested context information. + * + * \sa contextPrinting(), setContextPrinting() + */ + Q_PROPERTY(bool contextPrinting READ contextPrinting WRITE setContextPrinting) + + /*! + * The property holds the date format used by the layout. + * + * The default date format is "RELATIVE". + * + * \sa dateFormat(), setDateFormat() + */ + Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat) + + /*! + * The property holds if the thread name is part of the formatted output. + * + * The default value it true for including the thread name. + * + * \sa threadPrinting(), setThreadPrinting() + */ + Q_PROPERTY(bool threadPrinting READ threadPrinting WRITE setThreadPrinting) + + public: + /*! + * The enum DateFormat defines constants for date formats. + * + * \sa setDateFormat(DateFormat), DateTime::toString() + */ + enum DateFormat + { + /*! The none date format string is "NONE". */ + NONE, + /*! + * The iso8601 date format string is "ISO8601". The date will be + * formatted as yyyy-MM-dd hh:mm:ss.zzz. + */ + ISO8601, + /*! + * The absolute date format string is "ABSOLUTE". The date will be + * formatted as HH:mm:ss.zzz. + */ + ABSOLUTE, + /*! + * The date date format string is "DATE". The date will be formatted + * as MMM YYYY HH:mm:ss.zzzz. + */ + DATE, + /*! + * The relative date format string is "RELATIVE". The date will be + * formatted as milliseconds since start of the program. + */ + RELATIVE + }; + Q_ENUMS(DateFormat) + + TTCCLayout(QObject *pParent = 0); + TTCCLayout(const QString &rDateFormat, + QObject *pParent = 0); + + /*! + * Creates a TTCCLayout with the date formar value specified by + * the \a dateFormat constant and the parent \a pParent. + */ + TTCCLayout(DateFormat dateFormat, + QObject *pParent = 0); + + virtual ~TTCCLayout(); + private: + TTCCLayout(const TTCCLayout &rOther); // Not implemented + TTCCLayout &operator=(const TTCCLayout &rOther); // Not implemented + + public: + bool categoryPrefixing() const; + bool contextPrinting() const; + QString dateFormat() const; + // JAVA: bool ignoresThrowable() const; + bool threadPrinting() const; + void setCategoryPrefixing(bool categoryPrefixing); + void setContextPrinting(bool contextPrinting); + void setDateFormat(const QString &rDateFormat); + + /*! + * Sets the date format to the value specified by the \a dateFormat + * constant. + */ + void setDateFormat(DateFormat dateFormat); + + // JAVA: setIgnoresThrowable(bool ignoresThrowable); + void setThreadPrinting(bool threadPrinting); + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %TTCCLayout(name:"TTCC" categoryprefixing:true + * contextprinting:true dateformat:"ISO8601" + * referencecount:1 threadprinting:true) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + bool mCategoryPrefixing; + bool mContextPrinting; + QString mDateFormat; + bool mThreadPrinting; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool TTCCLayout::categoryPrefixing() const + { return mCategoryPrefixing; } + + inline bool TTCCLayout::contextPrinting() const + { return mContextPrinting; } + + inline QString TTCCLayout::dateFormat() const + { return mDateFormat; } + + inline bool TTCCLayout::threadPrinting() const + { return mThreadPrinting; } + + inline void TTCCLayout::setCategoryPrefixing(bool categoryPrefixing) + { mCategoryPrefixing = categoryPrefixing; + updatePatternFormatter(); } + + inline void TTCCLayout::setContextPrinting(bool contextPrinting) + { mContextPrinting = contextPrinting; + updatePatternFormatter(); } + + inline void TTCCLayout::setDateFormat(const QString &rDateFormat) + { mDateFormat = rDateFormat; + updatePatternFormatter(); } + + inline void TTCCLayout::setThreadPrinting(bool threadPrinting) + { mThreadPrinting = threadPrinting; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::TTCCLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_TTCCLAYOUT_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/debugappender.cpp b/GC-3.6.1-T2/src/log4qt/varia/debugappender.cpp new file mode 100644 index 0000000..fbaa351 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/debugappender.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/debugappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + +#if defined(Q_WS_WIN) +#include +#endif + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DebugAppender + **************************************************************************/ + + + DebugAppender::DebugAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(pParent) + { + setLayout(pLayout); + } + + + bool DebugAppender::requiresLayout() const + { + return true; + } + + + void DebugAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DebugAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "DebugAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); +#if defined(Q_WS_WIN) + QT_WA({ + OutputDebugStringW(reinterpret_cast(message.utf16())); + }, { + OutputDebugStringA(message.toLocal8Bit().data()); + }); +#else + fprintf(stderr, "%s", message.toLocal8Bit().data()); + fflush(stderr); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DebugAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "DebugAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namspace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/debugappender.h b/GC-3.6.1-T2/src/log4qt/varia/debugappender.h new file mode 100644 index 0000000..fc2b7f0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/debugappender.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DEBUGAPPENDER_H +#define LOG4QT_DEBUGAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DebugAppender appends logging events to the platform + * specific debug output. + * + * A DebugAppender appends to the Debugger on Windows and to stderr on all + * other systems. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DebugAppender : public AppenderSkeleton + { + Q_OBJECT + + public: + /*! + * Creates a DebugAppender. + */ + DebugAppender(QObject *pParent = 0); + + /*! + * Creates a DebugAppender with the specified layout \a pLayout + */ + DebugAppender(Layout *pLayout, + QObject *pParent = 0); + + // virtual ~DebugAppender(); // Use compiler default + private: + DebugAppender(const DebugAppender &rOther); // Not implemented + DebugAppender &operator=(const DebugAppender &rOther); // Not implemented + + public: + /*! + * The DebugAppended requires a layout. The function returns true. + * + * \sa setLayout() + */ + virtual bool requiresLayout() const; + + protected: + /*! + * Appends the specified logging event \a rEvent to the debug output. + * The output is formatted using the appender's layout. + * + * The method is called by the AppenderSkeleton::doAppend() after it + * the entry conditions have been tested and it has been found that the + * logging event needs to be appended. + * + * \sa setLayout(), AppenderSkeleton::doAppend(), checkEntryConditions() + */ + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DebugAppender(name:"DA" filter:0x3bee6b8 isactive:true isclosed:false + * layout:"SL" referencecount:1 threshold:"NULL") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DebugAppender::DebugAppender(QObject *pParent) : + AppenderSkeleton(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DebugAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DEBUGAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.cpp b/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.cpp new file mode 100644 index 0000000..31d8f64 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/denyallfilter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DenyAllFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DenyAllFilter(" + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.h b/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.h new file mode 100644 index 0000000..e67ffaa --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/denyallfilter.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a compile error on VS 2008 by using Q_UNUSED(&rEvent) + * instead of Q_UNUSED(rEvent) + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DENYALLFILTER_H +#define LOG4QT_DENYALLFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DenyAllFilter drops all logging events + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DenyAllFilter : public Filter + { + Q_OBJECT + + public: + DenyAllFilter(QObject *pParent = 0); + // DenyAllFilter(const DenyAllFilter &rOther); // Use compiler default + // virtual ~DenyAllFilter(); // Use compiler default + // DenyAllFilter &operator=(const DenyAllFilter &rOther); // Use compiler default + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DenyAllFilter(next:QObject(0x0) referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************* + * Operators, Helper + *************************************************************************/ + + + /************************************************************************* + * Inline + *************************************************************************/ + + inline DenyAllFilter::DenyAllFilter(QObject *pParent) : + Filter(pParent) + {} + + inline Filter::Decision DenyAllFilter::decide(const LoggingEvent &rEvent) const + { Q_UNUSED(&rEvent); return Filter::DENY; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DenyAllFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_DENYALLFILTER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.cpp b/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.cpp new file mode 100644 index 0000000..32a3d84 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + LevelMatchFilter::LevelMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelToMatch(Level::NULL_INT) + {} + + + Filter::Decision LevelMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (mLevelToMatch == Level::NULL_INT || + rEvent.level() != mLevelToMatch) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug LevelMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LevelMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "leveltomatch:" << mLevelToMatch.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.h b/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.h new file mode 100644 index 0000000..b2fb44c --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/levelmatchfilter.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELMATCHFILTER_H +#define LOG4QT_LEVELMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with a specified + * level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), setAcceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the level to match for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelToMatch(), setLevelToMatch() + */ + Q_PROPERTY(Level levelToMatch READ levelToMatch WRITE setLevelToMatch) + + public: + LevelMatchFilter(QObject *pParent = 0); + // LevelMatchFilter(const LevelMatchFilter &rOther); // Use compiler default + // virtual ~LevelMatchFilter(); // Use compiler default + // LevelMatchFilter &operator=(const LevelMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelToMatch() const; + void setAcceptOnMatch(bool accept); + void setLevelToMatch(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelMatchFilter(acceptonmatch:true leveltomatch:"WARN" + * next:Log4Qt::DenyAllFilter(0x3bce3a8) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + Level mLevelToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelMatchFilter::levelToMatch() const + { return mLevelToMatch; } + + inline void LevelMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelMatchFilter::setLevelToMatch(Level level) + { mLevelToMatch = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELMATCHFILTER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.cpp b/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.cpp new file mode 100644 index 0000000..b219cd9 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelrangefilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + + +/****************************************************************************** + * C helper functions + ******************************************************************************/ + + + +/****************************************************************************** + * Class implementation: Filter + ******************************************************************************/ + + +LevelRangeFilter::LevelRangeFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelMin(Level::NULL_INT), + mLevelMax(Level::OFF_INT) +{} + + +Filter::Decision LevelRangeFilter::decide(const LoggingEvent &rEvent) const +{ + if (rEvent.level() < mLevelMin) + return Filter::DENY; + + if (rEvent.level() > mLevelMax) + return Filter::DENY; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::NEUTRAL; +} + + +#ifndef QT_NO_DEBUG_STREAM +QDebug LevelRangeFilter::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "LevelRangeFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "levelmin:" << mLevelMin.toString() << " " + << "levelmax:" << mLevelMax.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.h b/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.h new file mode 100644 index 0000000..013e533 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/levelrangefilter.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELRANGEFILTER_H +#define LOG4QT_LEVELRANGEFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with levels in a + * specified range. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelRangeFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the maximum level of the range for this filter. + * + * The default is Level::OFF_INT. + * + * \sa levelMax(), setLevelMax() + */ + Q_PROPERTY(Level levelMax READ levelMax WRITE setLevelMax) + + /*! + * The property holds the minimum level of the range for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelMin(), setLevelMin() + */ + Q_PROPERTY(Level levelMin READ levelMin WRITE setLevelMin) + + public: + LevelRangeFilter(QObject *pParent = 0); + // LevelRangeFilter(const LevelRangeFilter &rOther); // Use compiler default + // virtual ~LevelRangeFilter(); // Use compiler default + // LevelRangeFilter &operator=(const LevelRangeFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelMax() const; + Level levelMin() const; + void setAcceptOnMatch(bool accept); + void setLevelMax(Level level); + void setLevelMin(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelRangeFilter(acceptonmatch:true levelmin:"ERROR" levelmax:"FATAL" + * next:Log4Qt::LevelMatchFilter(0x3bcd960) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + + private: + bool mAcceptOnMatch; + Level mLevelMin; + Level mLevelMax; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelRangeFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelRangeFilter::levelMax() const + { return mLevelMax; } + + inline Level LevelRangeFilter::levelMin() const + { return mLevelMin; } + + inline void LevelRangeFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelRangeFilter::setLevelMax(Level level) + { mLevelMax = level; } + + inline void LevelRangeFilter::setLevelMin(Level level) + { mLevelMin = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelRangeFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELRANGEFILTER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/listappender.cpp b/GC-3.6.1-T2/src/log4qt/varia/listappender.cpp new file mode 100644 index 0000000..db20284 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/listappender.cpp @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/listappender.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ListAppender + **************************************************************************/ + + + ListAppender::ListAppender(QObject *pParent) : + AppenderSkeleton(pParent), + mConfiguratorList(false), + mList(), + mMaxCount(0) + { + } + + + ListAppender::~ListAppender() + { + } + + + QList ListAppender::list() const + { + QMutexLocker locker(&mObjectGuard); + + return mList; + } + + + void ListAppender::setMaxCount(int n) + { + QMutexLocker locker(&mObjectGuard); + + if (n < 0) + { + logger()->warn("Attempt to set maximum count for appender '%1' to %2. Using zero instead", name(), n); + n = 0; + } + mMaxCount = n; + ensureMaxCount(); + } + + + QList ListAppender::clearList() + { + QMutexLocker locker(&mObjectGuard); + + QList result = mList; + mList.clear(); + return result; + } + + + // bool ListAppender::requiresLayout() const; + + + void ListAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "ListAppender::append()", "Lock must be held by caller") + + if ((mMaxCount <= 0) || (mList.size() < mMaxCount)) + mList << rEvent; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ListAppender::debug(QDebug &rDebug) const + { + rDebug.nospace() << "ListAppender(" + << "name:" << name() << " " + << "count:" << list().count() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "maxcount:" << maxCount() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void ListAppender::ensureMaxCount() + { + // Q_ASSERT_X(, "ListAppender::ensureMaxCount()", "Lock must be held by caller") + + if (mMaxCount <= 0) + return; + + while (mList.size() > mMaxCount) + mList.removeFirst(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/listappender.h b/GC-3.6.1-T2/src/log4qt/varia/listappender.h new file mode 100644 index 0000000..0b35c51 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/listappender.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LISTAPPENDER_H +#define LOG4QT_LISTAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class ListAppender appends logging events to a list for later + * processing. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ListAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds, if the Appender is used by a configurator. + * + * The default value is false for not being a configurator list. + * + * \sa configuratorList(), setConfiguratorList() + */ + Q_PROPERTY(bool configuratorList READ configuratorList WRITE setConfiguratorList) + + /*! + * The property holds the maximum count used by the appender. + * + * The default maximum count is -1 for unlimited. + * + * \sa maxCount(), setMaxCount() + */ + Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) + + public: + ListAppender(QObject *pParent = 0); + virtual ~ListAppender(); + private: + ListAppender(const ListAppender &rOther); // Not implemented + ListAppender &operator=(const ListAppender &rOther); // Not implemented + + public: + /*! + * Returns true, if the appender is used by a configurator. Otherweise it returns + * false. + * + * \sa setConfiguratorList() + */ + bool configuratorList() const; + + QList list() const; + int maxCount() const; + + /*! + * Sets that the appender is used by a configurator. If set to true, the appender + * will not be removed from a Logger when Logger::removeAllAppenders()is called. + * This way the appender can collect events raised during the configuration process. + * + * \sa configuratorList(), BasicConfigurator, PropertyConfigurator, + * ConfiguratorHelper::configureError() + */ + void setConfiguratorList(bool isConfiguratorList); + + void setMaxCount(int n); + + QList clearList(); + virtual bool requiresLayout() const; + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ListAppender(name:"LA" count:1 filter:0x41fa488 isactive:true + * isclosed:false maxcount:170 referencecount:1 + * threshold:"TRACE_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Ensures that the count of events is less or equal then the maxium + * count. If the list contains too many items, items are deleted from + * the begin of the list. + */ + void ensureMaxCount(); + + private: + volatile bool mConfiguratorList; + QList mList; + volatile int mMaxCount; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool ListAppender::configuratorList() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mConfiguratorList; } + + inline int ListAppender::maxCount() const + { return mMaxCount; } + + inline void ListAppender::setConfiguratorList(bool isConfiguratorList) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mConfiguratorList = isConfiguratorList; } + + inline bool ListAppender::requiresLayout() const + { return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ListAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LISTAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/nullappender.cpp b/GC-3.6.1-T2/src/log4qt/varia/nullappender.cpp new file mode 100644 index 0000000..a12ebf2 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/nullappender.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/nullappender.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: NullAppender + **************************************************************************/ + + + NullAppender::NullAppender(QObject *pParent) : + AppenderSkeleton(false, pParent) + { + } + + + NullAppender::~NullAppender() + { + close(); + } + + + void NullAppender::append(const LoggingEvent &rEvent) + { + Q_UNUSED(rEvent); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug NullAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "NullAppender(" + << "name:" << name() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "threshold:" << threshold().toString() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/nullappender.h b/GC-3.6.1-T2/src/log4qt/varia/nullappender.h new file mode 100644 index 0000000..becafb9 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/nullappender.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NULLAPPENDER_H +#define LOG4QT_NULLAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + +/*! + * \brief The class NullAppender ignores all requests to append. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ +class NullAppender : public AppenderSkeleton +{ + Q_OBJECT + +public: + NullAppender(QObject *pParent = 0); + virtual ~NullAppender(); +private: + NullAppender(const NullAppender &rOther); // Not implemented + NullAppender &operator=(const NullAppender &rOther); // Not implemented + +public: + virtual bool requiresLayout() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NullAppender() + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM +}; + + +/****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + +/****************************************************************************** + * Inline + ******************************************************************************/ + +inline bool NullAppender::requiresLayout() const +{ return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NullAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NULLAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.cpp b/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.cpp new file mode 100644 index 0000000..e660b21 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/stringmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + StringMatchFilter::StringMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mStringToMatch() + {} + + + Filter::Decision StringMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (rEvent.message().isEmpty() || + mStringToMatch.isEmpty() || + rEvent.message().indexOf(mStringToMatch) < 0) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug StringMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "StringMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "referencecount:" << referenceCount() << " " + << "stringtomatch:" << mStringToMatch << " " + << "next:" << next() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.h b/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.h new file mode 100644 index 0000000..921460f --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/varia/stringmatchfilter.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_STRINGMATCHFILTER_H +#define LOG4QT_STRINGMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class StringMatchFilter allows logging events with a + * specified level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class StringMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the string to match for this filter. + * + * \sa stringToMatch(), setStringToMatch() + */ + Q_PROPERTY(QString stringToMatch READ stringToMatch WRITE setStringToMatch) + + public: + StringMatchFilter(QObject *pParent = 0); + // StringMatchFilter(const StringMatchFilter &rOther); // Use compiler default + // virtual ~StringMatchFilter(); // Use compiler default + // StringMatchFilter &operator=(const StringMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + QString stringToMatch() const; + void setAcceptOnMatch(bool accept); + void setStringToMatch(const QString &rString); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %StringMatchFilter(acceptonmatch:true referencecount:1 + * stringtomatch:"LDAP_STRONG_AUTH_REQUIRED" + * next:Log4Qt::LevelMatchFilter(0x3bdd960) ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + QString mStringToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool StringMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline QString StringMatchFilter::stringToMatch() const + { return mStringToMatch; } + + inline void StringMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void StringMatchFilter::setStringToMatch(const QString &rString) + { mStringToMatch = rString; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::StringMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_STRINGMATCHFILTER_H diff --git a/GC-3.6.1-T2/src/log4qt/writerappender.cpp b/GC-3.6.1-T2/src/log4qt/writerappender.cpp new file mode 100644 index 0000000..25a633e --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/writerappender.cpp @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/writerappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: WriterAppender + **************************************************************************/ + + + WriterAppender::WriterAppender(QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(pTextStream), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::~WriterAppender() + { + close(); + } + + + void WriterAppender::setEncoding(QTextCodec *pEncoding) + { + QMutexLocker locker(&mObjectGuard); + + if (mpEncoding == pEncoding) + return; + + mpEncoding = pEncoding; + if (mpWriter) + { + if (mpEncoding) + mpWriter->setCodec(mpEncoding); + else + mpWriter->setCodec(QTextCodec::codecForLocale()); + } + } + + + void WriterAppender::setWriter(QTextStream *pTextStream) + { + QMutexLocker locker(&mObjectGuard); + + closeWriter(); + + mpWriter = pTextStream; + if (mpEncoding && mpWriter) + mpWriter->setCodec(mpEncoding); + writeHeader(); + } + + + void WriterAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires writer and has no writer set"), + APPENDER_ACTIVATE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return; + } + + AppenderSkeleton::activateOptions(); + } + + + void WriterAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + AppenderSkeleton::close(); + closeWriter(); + } + + + bool WriterAppender::requiresLayout() const + { + return true; + } + + + void WriterAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "WriterAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "WriterAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); + + *mpWriter << message; + if (handleIoErrors()) + return; + + if (immediateFlush()) + { + mpWriter->flush(); + if (handleIoErrors()) + return; + } + } + + + bool WriterAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a writer set"), + APPENDER_USE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + + void WriterAppender::closeWriter() + { + // Q_ASSERT_X(, "WriterAppender::closeWriter()", "Lock must be held by caller") + + if (!mpWriter) + return; + + writeFooter(); + mpWriter = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug WriterAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "WriterAppender(" + << "name:" << name() << " " + << "encoding:" << codec_name << " " + << "filter:" << firstFilter() + << "immediateFlush:" << immediateFlush() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool WriterAppender::handleIoErrors() const + { + return false; + } + + + void WriterAppender::writeFooter() const + { + // Q_ASSERT_X(, "WriterAppender::writeFooter()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString footer = layout()->footer(); + if (footer.isEmpty()) + return; + + *mpWriter << footer << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + void WriterAppender::writeHeader() const + { + // Q_ASSERT_X(, "WriterAppender::writeHeader()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString header = layout()->header(); + if (header.isEmpty()) + return; + + *mpWriter << header << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T2/src/log4qt/writerappender.h b/GC-3.6.1-T2/src/log4qt/writerappender.h new file mode 100644 index 0000000..5c8da09 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qt/writerappender.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_WRITERAPPENDER_H +#define LOG4QT_WRITERAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QTextCodec; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class WriterAppender appends log events to a QTextStream. + * + * \note All the functions declared in this class are thread-safe. + *   + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class WriterAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds the codec the appender uses. + * + * The default is null to use the codec the writer has set. + * + * \sa encoding(), setEncoding() + */ + Q_PROPERTY(QTextCodec* encoding READ encoding WRITE setEncoding) + + /*! + * The property holds the writer the appender uses. + * + * \sa writer(), setWriter() + */ + Q_PROPERTY(QTextStream* writer READ writer WRITE setWriter) + + /*! + * The property holds, if the writer flushes after all write operations. + * + * The default is true for flushing. + * + * \sa immediateFlush(), setImmediateFlush() + */ + Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush) + + public: + WriterAppender(QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent = 0); + virtual ~WriterAppender(); + private: + WriterAppender(const WriterAppender &rOther); // Not implemented + WriterAppender &operator=(const WriterAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + QTextCodec *encoding() const; + bool immediateFlush() const; + QTextStream *writer() const; + + /*! + * Sets the codec used by the writer to \a pTextCoded. + * + * If a codec is set with setEncoding, it will overwrite the codec set + * in the text stream. A subsequent call with \a pTextCoded equals null + * will resets the codec to the default QTextCodec::codecForLocale(). + * + * \sa encoding(), QTextSream::setCodec(), QTextCodec::codecForLocale() + */ + void setEncoding(QTextCodec *pTextCodec); + void setImmediateFlush(bool immediateFlush); + void setWriter(QTextStream *pTextStream); + + virtual void activateOptions(); + virtual void close(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeWriter(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %WriterAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + virtual bool handleIoErrors() const; + void writeFooter() const; + void writeHeader() const; + + private: + QTextCodec *mpEncoding; + QTextStream *mpWriter; + volatile bool mImmediateFlush; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QTextCodec *WriterAppender::encoding() const + { QMutexLocker locker(&mObjectGuard); + return mpEncoding; } + + inline bool WriterAppender::immediateFlush() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mImmediateFlush; } + + inline QTextStream *WriterAppender::writer() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mpWriter; } + + inline void WriterAppender::setImmediateFlush(bool immediateFlush) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mImmediateFlush = immediateFlush; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::WriterAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_WRITERAPPENDER_H diff --git a/GC-3.6.1-T2/src/log4qtdef.h b/GC-3.6.1-T2/src/log4qtdef.h new file mode 100644 index 0000000..ce801e0 --- /dev/null +++ b/GC-3.6.1-T2/src/log4qtdef.h @@ -0,0 +1,11 @@ +#ifndef LOG4QTDEF_H +#define LOG4QTDEF_H + +#include "log4qt/consoleappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/logger.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/patternlayout.h" +#include "log4qt/logmanager.h" + +#endif // LOG4QTDEF_H diff --git a/GC-3.6.1-T2/src/main.cpp b/GC-3.6.1-T2/src/main.cpp new file mode 100644 index 0000000..0be6143 --- /dev/null +++ b/GC-3.6.1-T2/src/main.cpp @@ -0,0 +1,204 @@ +/**************************************************************** + * main.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "mainwindow.h" +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +#include +#endif + +enum GC_LOG_TYPES +{ + LOG_DEBUG_TYPE = 1, + LOG_ERROR_TYPE, + LOG_WARN_TYPE, + LOG_INFO_TYPE, + LOG_STATUS_TYPE, +}; + +void logit(GC_LOG_TYPES type, const char *str, va_list args); + +FILE *pDebugLogFile = NULL; +AtomicIntBool g_enableDebugLog; +Log4Qt::PatternLayout *p_layout; +Log4Qt::FileAppender *p_fappender; + +int main(int argc, char *argv[]) +{ + // setup logging + Log4Qt::LogManager::rootLogger(); + //Log4Qt::TTCCLayout *p_layout = new Log4Qt::TTCCLayout(Log4Qt::TTCCLayout::ISO8601); + //Log4Qt::PatternLayout *p_layout = new Log4Qt::PatternLayout(Log4Qt::PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout = new Log4Qt::PatternLayout("%d %p (%c) - %m%n"); + p_layout->setName(QLatin1String("GC Basic Layout")); + p_layout->activateOptions(); + + // Create a console appender + Log4Qt::ConsoleAppender *p_appender = new Log4Qt::ConsoleAppender(p_layout, Log4Qt::ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("GC Basic Console Appender")); +#ifdef QT_DEBUG + p_appender->setThreshold(Log4Qt::Level::TRACE_INT); +#else + p_appender->setThreshold(Log4Qt::Level::WARN_INT); +#endif + p_appender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_appender); + + // Create a file appender + p_fappender = new Log4Qt::FileAppender(); + p_fappender->setLayout(p_layout); + p_fappender->setThreshold(Log4Qt::Level::TRACE_INT); + p_fappender->setFile(QDir::homePath() + "/GrblController.log"); + p_fappender->setName(QLatin1String("GC Basic File Appender")); + // don't open until ready (later during startup) + //p_fappender->activateOptions(); + //Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + + QApplication a(argc, argv); + + QString locale = QLocale::system().name().section('_', 0, 0); + QString dir = QDir::currentPath() + "/trlocale"; + QString file = QString("GrblController_") + locale; + QTranslator translator; + bool r = translator.load(file, dir); + if (!r) + { + dir = QDir::currentPath() + "/../GrblHoming/trlocale"; + translator.load(file, dir); + } + a.installTranslator(&translator); + + QString xlatpath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + file = QString("qt_") + locale ; + QTranslator qtTranslator; + r = qtTranslator.load(file , xlatpath); + if (!r) + { + xlatpath = QDir::currentPath() + "/trlocale"; + qtTranslator.load(file, xlatpath); + } + a.installTranslator(&qtTranslator); + + MainWindow w; + w.show(); + + int result = a.exec(); + + if (pDebugLogFile != NULL) + { + fclose(pDebugLogFile); + pDebugLogFile = NULL; + } + return result; +} + + +//------------------------------ +void status(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_STATUS_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void err(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_ERROR_TYPE, str, args); + va_end(args); +} + +void warn(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_WARN_TYPE, str, args); + va_end(args); +} + +void info(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_INFO_TYPE, str, args); + va_end(args); +} + +void diag(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_DEBUG_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void logit(GC_LOG_TYPES type, const char *str, va_list args) +{ +#define PRNTBUFSIZE 500 + char buf[PRNTBUFSIZE]; + buf[PRNTBUFSIZE-1] = '\0'; + + vsnprintf(buf, sizeof(buf) - 1, str, args); + + int len = strlen(buf); + if (len > 0) + { + if (len == 1 && (buf[0] == '\r' || buf[0] == '\n')) + { + buf[0] = '\0'; + } + else if (len > 1) + { + if (buf[len - 2] == '\r' || buf[len - 2] == '\n') + buf[len - 2] = '\0'; + else if (buf[len - 1] == '\r' || buf[len - 1] == '\n') + buf[len - 1] = '\0'; + } + } + else if (len == 0) + return; + + switch (type) + { + case LOG_STATUS_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_STATUS)->info(buf); + break; + case LOG_DEBUG_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->debug(buf); + break; + case LOG_ERROR_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->error(buf); + break; + case LOG_WARN_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->warn(buf); + break; + case LOG_INFO_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->info(buf); + break; + } +} diff --git a/GC-3.6.1-T2/src/mainwindow.cpp b/GC-3.6.1-T2/src/mainwindow.cpp new file mode 100644 index 0000000..bcd8fb3 --- /dev/null +++ b/GC-3.6.1-T2/src/mainwindow.cpp @@ -0,0 +1,1640 @@ +/**************************************************************** + * mainwindow.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "mainwindow.h" +#include "version.h" +#include "ui_mainwindow.h" + +extern Log4Qt::FileAppender *p_fappender; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + // open_button_text(tr(OPEN_BUTTON_TEXT)), + // close_button_text(tr(CLOSE_BUTTON_TEXT)), + open_button_text(tr("Open")), + close_button_text(tr("Close / Reset")), + absoluteAfterAxisAdj(false), + checkLogWrite(false), + sliderPressed(false), + sliderTo(0.0), + sliderZCount(0), + scrollRequireMove(true), scrollPressed(false), + queuedCommandsStarved(false), lastQueueCount(0), queuedCommandState(QCS_OK), + lastLcdStateValid(true) +{ + // Setup our application information to be used by QSettings + QCoreApplication::setOrganizationName(COMPANY_NAME); + QCoreApplication::setOrganizationDomain(DOMAIN_NAME); + QCoreApplication::setApplicationName(APPLICATION_NAME); + + // required if passing the object by reference into signals/slots + qRegisterMetaType("Coord3D"); + qRegisterMetaType("PosItem"); + qRegisterMetaType("ControlParams"); + + + ui->setupUi(this); + + readSettings(); + + info("%s has started", GRBL_CONTROLLER_NAME_AND_VERSION); + + // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/ + // The thread points out that the documentation for QThread is wrong :) and + // you should NOT subclass from QThread and override run(), rather, + // attach your QOBJECT to a thread and use events (signals/slots) to communicate. + gcode.moveToThread(&gcodeThread); + runtimeTimer.moveToThread(&runtimeTimerThread); + + ui->lcdWorkNumberX->setDigitCount(8); + ui->lcdMachNumberX->setDigitCount(8); + ui->lcdWorkNumberY->setDigitCount(8); + ui->lcdMachNumberY->setDigitCount(8); + ui->lcdWorkNumberZ->setDigitCount(8); + ui->lcdMachNumberZ->setDigitCount(8); + ui->lcdWorkNumberFourth->setDigitCount(8); + ui->lcdMachNumberFourth->setDigitCount(8); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + + //buttons + connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort())); + connect(ui->btnGRBL,SIGNAL(clicked()),this,SLOT(setGRBL())); + connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX())); + connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY())); + connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ())); + connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX())); + connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY())); + connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ())); + connect(ui->DecFourthBtn,SIGNAL(clicked()),this,SLOT(decFourth())); + connect(ui->IncFourthBtn,SIGNAL(clicked()),this,SLOT(incFourth())); + connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome())); + connect(ui->comboCommand->lineEdit(),SIGNAL(editingFinished()),this,SLOT(gotoXYZFourth())); + connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin())); + connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile())); + connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop())); + connect(ui->SpindleOn,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle())); + connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute())); + connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions())); + connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close())); + connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout())); + connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset())); + connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock())); + connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe())); + connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int))); + connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed())); + connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased())); + connect(ui->pushButtonRefreshPos,SIGNAL(clicked()),this,SLOT(refreshPosition())); + connect(ui->comboStep,SIGNAL(currentIndexChanged(QString)),this,SLOT(comboStepChanged(QString))); + + connect(this, SIGNAL(sendFile(QString)), &gcode, SLOT(sendFile(QString))); + connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString))); + connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool))); + connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString))); + connect(this, SIGNAL(gotoXYZFourth(QString)), &gcode, SLOT(gotoXYZFourth(QString))); + connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int))); + connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams))); + connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit())); + connect(this, SIGNAL(shutdown()), &runtimeTimerThread, SLOT(quit())); + connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); + connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome())); + connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset())); + connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock())); + connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome())); + connect(this, SIGNAL(setItems(QList)), ui->wgtVisualizer, SLOT(setItems(QList))); + + connect(&gcode, SIGNAL(sendMsg(QString)),this,SLOT(receiveMsg(QString))); + connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool))); + connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool))); + connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString))); + connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList))); + connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString))); + connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending())); + connect(&gcode, SIGNAL(setCommandText(QString)), ui->comboCommand->lineEdit(), SLOT(setText(QString))); + connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(&gcode, SIGNAL(setQueuedCommands(int, bool)), this, SLOT(setQueuedCommands(int, bool))); + connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis())); + connect(&gcode, SIGNAL(resetTimer(bool)), &runtimeTimer, SLOT(resetTimer(bool))); + connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton())); + connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D))); + connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsWork(QString)), ui->outputUnitsWork, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsMachine(QString)), ui->outputUnitsMachine, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setLivePoint(double, double, bool, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool, bool))); + connect(&gcode, SIGNAL(setVisualLivenessCurrPos(bool)), ui->wgtVisualizer, SLOT(setVisualLivenessCurrPos(bool))); + connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int))); + connect(&gcode, SIGNAL(setLcdState(bool)), this, SLOT(setLcdState(bool))); + + connect(&runtimeTimer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); +/// LETARTARE T2 + connect(&gcode, SIGNAL(setVersionGrbl(QString)), ui->GrblVersion, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setLinesFile(QString)), this, SLOT(setLinesFile(QString))); + + // This code generates too many messages and chokes operation on raspberry pi. Do not use. + //connect(ui->statusList->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), ui->statusList, SLOT(scrollToBottom())); + + // instead, use this one second timer-based approach + scrollTimer = new QTimer(this); + connect(scrollTimer, SIGNAL(timeout()), this, SLOT(doScroll())); + scrollTimer->start(1000); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderPressed()), this, SLOT(statusSliderPressed())); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(statusSliderReleased())); + + runtimeTimerThread.start(); + gcodeThread.start(); + + // Don't use - it will not show horizontal scrollbar for small app size + //ui->statusList->setUniformItemSizes(true); + + // Does not work correctly for horizontal scrollbar: + //MyItemDelegate *scrollDelegate = new MyItemDelegate(ui->statusList); + //scrollDelegate->setWidth(600); + //ui->statusList->setItemDelegate(scrollDelegate); + + scrollStatusTimer.start(); + queuedCommandsEmptyTimer.start(); + queuedCommandsRefreshTimer.start(); + + // Cool utility class off Google code that enumerates COM ports in platform-independent manner + QList ports = QextSerialEnumerator::getPorts(); + + int portIndex = -1; + for (int i = 0; i < ports.size(); i++) + { + ui->cmbPort->addItem(ports.at(i).portName.toLocal8Bit().constData()); + + if (ports.at(i).portName == lastOpenPort) + portIndex = i; + + //diag("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData()); + //diag("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData()); + //diag("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData()); + //diag("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData()); + //diag("===================================\n\n"); + } + + if (portIndex >= 0) + { + // found matching port + ui->cmbPort->setCurrentIndex(portIndex); + } + else if (lastOpenPort.size() > 0) + { + // did not find matching port + // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator + ui->cmbPort->addItem(lastOpenPort.toLocal8Bit().constData()); + if (ports.size() > 0) + ui->cmbPort->setCurrentIndex(ports.size()); + else + ui->cmbPort->setCurrentIndex(0); + } + + int baudRates[] = { 9600, 19200, 38400, 57600, 115200 }; + int baudRateCount = sizeof baudRates / sizeof baudRates[0]; + int baudRateIndex = 0; + for (int i = 0; i < baudRateCount; i++) + { + QString baudRate = QString::number(baudRates[i]); + ui->comboBoxBaudRate->addItem(baudRate); + if (baudRate == lastBaudRate) + { + baudRateIndex = i; + } + } + + ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex); + + ui->tabAxisVisualizer->setEnabled(false); + if (!controlParams.useFourAxis) + { + ui->lcdWorkNumberFourth->setEnabled(false);; + ui->lcdMachNumberFourth->setEnabled(false);; + ui->IncFourthBtn->setEnabled(false); + ui->DecFourthBtn->setEnabled(false); + ui->lblFourthJog->setEnabled(false); + } + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + styleSheet = ui->btnOpenPort->styleSheet(); + ui->statusList->setEnabled(true); + ui->openFile->setEnabled(true); + + this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION); + this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + + QSettings settings; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + + if (!controlParams.useAggressivePreload && !promptedAggrPreload) + { + QMessageBox msgBox; + msgBox.setText(tr("You appear to have upgraded to the latest version of Grbl Controller. " + "Please be aware that as of version 3.4 the default behavior of sending commands " + "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n" + "Your settings have been changed to enable this mode. Why? Because it provides the most " + "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n" + "What does this mean to you? " + "Arc commands will now run smoother and faster than before, which may " + "cause your spindle to work slightly harder, so please run some tests first. " + "Alternately, go to the Options dialog and manually disable Aggressive Preload") ); + msgBox.exec(); + + controlParams.useAggressivePreload = true; + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload); + } + + promptedAggrPreload = true; + + emit setResponseWait(controlParams); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +// called when user has clicked the close application button +void MainWindow::closeEvent(QCloseEvent *event) +{ + gcode.setShutdown(); + gcode.setAbort(); + gcode.setReset(); + + writeSettings(); + + info("%s has stopped", GRBL_CONTROLLER_NAME_AND_VERSION); + + SLEEP(300); + + emit shutdown(); + + event->accept(); +} + +void MainWindow::begin() +{ + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + + //receiveList("Starting File Send."); + resetProgress(); + int ret = QMessageBox::No; + if((ui->lcdWorkNumberX->value()!=0)||(ui->lcdWorkNumberY->value()!=0)||(ui->lcdWorkNumberZ->value()!=0) + || (ui->lcdWorkNumberFourth->value()!=0)) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you want to zero the displayed position before proceeding?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Yes); + ret = msgBox.exec(); + if(ret ==QMessageBox::Yes) + setHome(); + } + if(ret!=QMessageBox::Cancel) + { + ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(true); + ui->progressFileSend->setEnabled(true); + ui->progressQueuedCommands->setEnabled(true); + ui->labelFileSendProgress->setEnabled(true); + ui->labelQueuedCommands->setEnabled(true); + ui->outputRuntime->setEnabled(true); + ui->labelRuntime->setEnabled(true); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + emit sendFile(ui->filePath->text()); + } +} + +void MainWindow::stop() +{ + gcode.setAbort(); + + // Reenable a bunch of UI + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::grblReset() +{ + gcode.setAbort(); + gcode.setReset(); + emit sendGrblReset(); +} + +void MainWindow::grblUnlock() +{ + emit sendGrblUnlock(); +} + +void MainWindow::goHomeSafe() +{ + emit goToHome(); +} + +// slot called from GCode class to update our state +void MainWindow::stopSending() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnOpenPort->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + ui->openFile->setEnabled(true); +} + +// User has asked to open the port +void MainWindow::openPort() +{ + QString Mes = tr("User clicked Port Open/Close"); + info(qPrintable(Mes) ); + + openPortCtl(false); +} + +// User has asked to set current position as 'home' = 0,0,0 +void MainWindow::setHome() +{ + resetProgress(); + sendSetHome(); +} + +void MainWindow::resetProgress() +{ + setProgress(0); + setQueuedCommands(0, false); + setRuntime(""); +} + +// If the port isn't open, we ask to open it +// If the port is open, we close it, but if 'reopen' is +// true, we call back to this thread to reopen it which +// is done mainly to toggle the COM port state to reset +// the controller. +void MainWindow::openPortCtl(bool reopen) +{ + if (ui->btnOpenPort->text() == open_button_text) + { + // Port is closed if the button says 'Open' + QString portStr = ui->cmbPort->currentText(); + QString baudRate = ui->comboBoxBaudRate->currentText(); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->btnOpenPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + emit openPort(portStr, baudRate); + } + else + { + if (!reopen) + resetProgress(); + + // presume button says 'Close' currently, meaning port is open + + // Tell gcode port thread to stop what it is doing immediately (within 0.1 sec) + gcode.setAbort(); + gcode.setReset(); + + // Disable a bunch of UI +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->openFile->setEnabled(false); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + //ui->cmbPort->setEnabled(false); + //ui->comboBoxBaudRate->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->btnGRBL->setEnabled(false); +/// LETARTARE T2 + ui->GrblVersion->setText(tr("none")); + + // Send event to close the port + emit closePort(reopen); + } +} + +// slot telling us that port was closed successfully +// if 'reopen' is true, reopen our port to toggle +// so we reset the controller +void MainWindow::portIsClosed(bool reopen) +{ + SLEEP(100); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->cmbPort->setEnabled(true); + ui->comboBoxBaudRate->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(open_button_text); + ui->btnOpenPort->setStyleSheet(styleSheet); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + + if (reopen) + { + receiveList(tr("Resetting port to restart controller")); + openPortCtl(false); + } +} + +// slot that tells us the gcode thread successfully opened the port +void MainWindow::portIsOpen(bool sendCode) +{ + // Comm port successfully opened + if (sendCode) + sendGcode(""); +} + +void MainWindow::adjustedAxis() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + + if (ui->filePath->text().length() > 0) + ui->Begin->setEnabled(true); + + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + + ui->btnOpenPort->setEnabled(true); + ui->openFile->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::disableAllButtons() +{ + //ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); +} + +void MainWindow::enableGrblDialogButton() +{ + ui->openFile->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(close_button_text); + ui->btnOpenPort->setStyleSheet("* { background-color: rgb(255,125,100) }"); + ui->cmbPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + + if (ui->filePath->text().length() > 0) + { +/// LETARTARE T2 + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + ui->btnGRBL->setEnabled(true); +} + +void MainWindow::incX() +{ + disableAllButtons(); + emit axisAdj('X', jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incY() +{ + disableAllButtons(); + emit axisAdj('Y', jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incZ() +{ + disableAllButtons(); + emit axisAdj('Z', jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decX() +{ + disableAllButtons(); + emit axisAdj('X', -jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decY() +{ + disableAllButtons(); + emit axisAdj('Y', -jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decZ() +{ + disableAllButtons(); + emit axisAdj('Z', -jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, -jogStep, invFourth, absoluteAfterAxisAdj, 0); + } +void MainWindow::incFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, jogStep, invFourth, absoluteAfterAxisAdj, 0); +} + +void MainWindow::getOptions() +{ + Options opt(this); + opt.exec(); +} + +void MainWindow::gotoXYZFourth() +{ + if (ui->comboCommand->lineEdit()->text().length() == 0) + return; + + QString line = ui->comboCommand->lineEdit()->text().append("\r"); + + emit gotoXYZFourth(line); +} + +void MainWindow::openFile() +{ + QFileDialog dialog(this, tr("Open File"), + directory, + tr("NC (*.nc);;All Files (*.*)")); + + dialog.setFileMode(QFileDialog::ExistingFile); + + if (nameFilter.size() > 0) + dialog.selectNameFilter(nameFilter); + + if (fileOpenDialogState.size() > 0) + dialog.restoreState(fileOpenDialogState); + + QString fileName; + QStringList fileNames; + if (dialog.exec()) + { + fileOpenDialogState = dialog.saveState(); + + fileNames = dialog.selectedFiles(); + if (fileNames.length() > 0) + fileName = fileNames.at(0); + + nameFilter = dialog.selectedNameFilter(); + + resetProgress(); + } + + int slash = fileName.lastIndexOf('/'); + if (slash == -1) + { + slash = fileName.lastIndexOf('\\'); + } + + directory = ""; + if (slash != -1) + { + directory = fileName.left(slash); + } + + ui->filePath->setText(fileName); + if(ui->filePath->text().length() > 0 && ui->btnOpenPort->text() == close_button_text) + { +/// LETARTARE T2 + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + if (ui->filePath->text().length() > 0) + { + // read in the file to process it + preProcessFile(ui->filePath->text()); + + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + } +} + +void MainWindow::preProcessFile(QString filepath) +{ + QFile file(filepath); + if (file.open(QFile::ReadOnly)) + { + posList.clear(); +/// T2 float -> int -> global + totalLinesFile = 0; + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLinesFile++; + code.readLine(); + } + if (totalLinesFile == 0) + totalLinesFile = 1; +/// LETARTARE T2 + ui->outputLines->setText(QString().setNum(totalLinesFile)); + + code.seek(0); + + double x = 0; + double y = 0; + double i = 0; + double j = 0; + bool arc = false; + bool cw = false; + bool mm = true; + int index = 0; + int g = 0; + + bool zeroInsert = false; + do + { + QString strline = code.readLine(); + + index++; + + GCode::trimToEnd(strline, '('); + GCode::trimToEnd(strline, ';'); + GCode::trimToEnd(strline, '%'); + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + strline = strline.toUpper(); + strline.replace("M6", "M06"); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline.replace(QRegExp("\\s+"), " "); + //if (strline.contains("G", Qt::CaseInsensitive)) + { + if (processGCode(strline, x, y, i, j, arc, cw, mm, g)) + { + if (!zeroInsert) + { + // insert 0,0 position + posList.append(PosItem(0, 0, 0, 0, false, false, mm, 0)); + zeroInsert = true; + } + posList.append(PosItem(x, y, i, j, arc, cw, mm, index)); + + //printf("Got G command:%s (%f,%f)\n", strline.toLocal8Bit().constData(), x, y); + } + } + } + } while (code.atEnd() == false); + + file.close(); + + emit setItems(posList); + } + else + printf("Can't open file\n"); +} + +bool MainWindow::processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g) +{ + QString line = inputLine.toUpper(); + + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + arc = false; + bool valid = false; + int nextIsValue = NO_ITEM; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value >= 0 && value <= 3) + { + g = value; + if (value == 2) + cw = true; + else if (value == 3) + cw = false; + } + else if (value == 20) + mm = false; + else if (value == 21) + mm = true; + } + else if (g >= 0 && g <= 3 && s.at(0) == 'X') + { + x = decodeLineItem(s, X_ITEM, valid, nextIsValue); + } + else if (g >= 0 && g <= 3 && s.at(0) == 'Y') + { + y = decodeLineItem(s, Y_ITEM, valid, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'I') + { + i = decodeLineItem(s, I_ITEM, arc, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'J') + { + j = decodeLineItem(s, J_ITEM, arc, nextIsValue); + } + else if (nextIsValue != NO_ITEM) + { + switch (nextIsValue) + { + case X_ITEM: + x = decodeDouble(s, valid); + break; + case Y_ITEM: + y = decodeDouble(s, valid); + break; + case I_ITEM: + i = decodeDouble(s, arc); + break; + case J_ITEM: + j = decodeDouble(s, arc); + break; + }; + nextIsValue = NO_ITEM; + } + } + + return valid; +} + +double MainWindow::decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue) +{ + if (item.size() == 1) + { + nextIsValue = next; + return 0; + } + else + { + nextIsValue = NO_ITEM; + return decodeDouble(item.mid(1,-1), valid); + } +} + +double MainWindow::decodeDouble(QString value, bool& valid) +{ + /* + QDoubleValidator v; + int pos = 0; + QValidator::State s = v.validate(value, pos); + if (s == QValidator::Invalid) + return 0; + */ + if (value.indexOf(QRegExp("^[+-]?[0-9]*\\.?[0-9]*$")) == -1) + return 0; + valid = true; + return value.toDouble(); +} + +void MainWindow::readSettings() +{ + // use platform-independent settings storage, i.e. registry under Windows + QSettings settings; + + fileOpenDialogState = settings.value(SETTINGS_FILE_OPEN_DIALOG_STATE).value(); + directory = settings.value(SETTINGS_DIRECTORY).value(); + nameFilter = settings.value(SETTINGS_NAME_FILTER).value(); + lastOpenPort = settings.value(SETTINGS_PORT).value(); + lastBaudRate = settings.value(SETTINGS_BAUD, QString::number(BAUD9600)).value(); + + promptedAggrPreload = settings.value(SETTINGS_PROMPTED_AGGR_PRELOAD, false).value(); + + QString absAfterAdj = settings.value(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, "false").value(); + absoluteAfterAxisAdj = (absAfterAdj == "true"); + ui->chkRestoreAbsolute->setChecked(absoluteAfterAxisAdj); + + jogStepStr = settings.value(SETTINGS_JOG_STEP, "1").value(); + jogStep = jogStepStr.toFloat(); + + int indexDesired = 0; + QString steps[] = { "0.01", "0.1", "1", "10", "100" }; + for (unsigned int i = 0; i < (sizeof (steps) / sizeof (steps[0])); i++) { + ui->comboStep->addItem(steps[i]); + if (jogStepStr == steps[i]) { + indexDesired = i; + } + } + ui->comboStep->setCurrentIndex(indexDesired); + + settings.beginGroup( "mainwindow" ); + + restoreGeometry(settings.value( "geometry", saveGeometry() ).toByteArray()); + restoreState(settings.value( "savestate", saveState() ).toByteArray()); + move(settings.value( "pos", pos() ).toPoint()); + resize(settings.value( "size", size() ).toSize()); + if ( settings.value( "maximized", isMaximized() ).toBool() ) + showMaximized(); + + settings.endGroup(); + + updateSettingsFromOptionDlg(settings); +} + +// Slot called from settings dialog after user made a change. Reload settings from registry. +void MainWindow::setSettings() +{ + QSettings settings; + + updateSettingsFromOptionDlg(settings); + + // update gcode thread with latest values + emit setResponseWait(controlParams); +} + +void MainWindow::updateSettingsFromOptionDlg(QSettings& settings) +{ + QString sinvX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString sinvY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString sinvZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + //QString smm = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS,"false").value(); + QString sinvFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + QString sdbgLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + g_enableDebugLog.set(sdbgLog == "true"); + + // only enable/not enable file logging at startup. There are some kind of + // multithreaded issues turning on or off file logging at runtime causing + // crashes. + if (!checkLogWrite) + { + checkLogWrite = true; + + if (g_enableDebugLog.get()) + { + p_fappender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + } + } + + invX = sinvX == "true"; + invY = sinvY == "true"; + invZ = sinvZ == "true"; + invFourth = sinvFourth == "true"; + + controlParams.waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + controlParams.zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + controlParams.useMm = useMmManualCmds == "true"; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + controlParams.waitForJogToComplete = waitForJogToComplete == "true"; + + QString useFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + controlParams.useFourAxis = useFourAxis == "true"; + if (controlParams.useFourAxis) + { + char type = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + controlParams.fourthAxisType = type; + } + + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + else + { + ui->DecFourthBtn->show(); + ui->IncFourthBtn->show(); + ui->lblFourthJog->show(); + ui->lcdWorkNumberFourth->show(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lcdMachNumberFourth->show(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->show(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->setText(QString(controlParams.fourthAxisType)); + + QString axisJog(tr("Z Jog"));// not correct, but a default placeholder we have a translation for already + char axis = controlParams.fourthAxisType; + if (axis == FOURTH_AXIS_A) + axisJog = tr("A Jog"); + else if (axis == FOURTH_AXIS_B) + axisJog = tr("B Jog"); + else if (axis == FOURTH_AXIS_C) + axisJog = tr("C Jog"); + else if (axis == FOURTH_AXIS_U) + axisJog = tr("U Jog"); + else if (axis == FOURTH_AXIS_V) + axisJog = tr("V Jog"); + else if (axis == FOURTH_AXIS_W) + axisJog = tr("W Jog"); + + ui->lblFourthJog->setText(axisJog); + } + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + controlParams.zRateLimit = zRateLimit == "true"; + + QString ffCommands = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + controlParams.filterFileCommands = ffCommands == "true"; + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + controlParams.reducePrecision = rPrecision == "true"; + controlParams.grblLineBufferLen = settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value(); + controlParams.charSendDelayMs = settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value(); + + controlParams.zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + controlParams.xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + controlParams.usePositionRequest = enPosReq == "true"; + controlParams.positionRequestType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_ALWAYS_NO_IDLE_CHK).value(); + double posReqFreq = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + controlParams.postionRequestTimeMilliSec = static_cast(posReqFreq) * 1000; + + setLcdState(controlParams.usePositionRequest); +} + +// save last state of settings +void MainWindow::writeSettings() +{ + QSettings settings; + + settings.setValue(SETTINGS_FILE_OPEN_DIALOG_STATE, fileOpenDialogState); + settings.setValue(SETTINGS_NAME_FILTER, nameFilter); + settings.setValue(SETTINGS_DIRECTORY, directory); + settings.setValue(SETTINGS_PORT, ui->cmbPort->currentText()); + settings.setValue(SETTINGS_BAUD, ui->comboBoxBaudRate->currentText()); + + settings.setValue(SETTINGS_PROMPTED_AGGR_PRELOAD, promptedAggrPreload); + settings.setValue(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, ui->chkRestoreAbsolute->isChecked()); + settings.setValue(SETTINGS_JOG_STEP, ui->comboStep->currentText()); + + // From http://stackoverflow.com/questions/74690/how-do-i-store-the-window-size-between-sessions-in-qt + settings.beginGroup("mainwindow"); + + settings.setValue( "geometry", saveGeometry() ); + settings.setValue( "savestate", saveState() ); + settings.setValue( "maximized", isMaximized() ); + if ( !isMaximized() ) { + settings.setValue( "pos", pos() ); + settings.setValue( "size", size() ); + } + + settings.endGroup(); +} + +void MainWindow::receiveList(QString msg) +{ + addToStatusList(true, msg); +} + +void MainWindow::receiveListFull(QStringList list) +{ + addToStatusList(list); +} + +void MainWindow::receiveListOut(QString msg) +{ + addToStatusList(false, msg); +} + +void MainWindow::addToStatusList(bool in, QString msg) +{ + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + return; + + QString nMsg(msg); + if (!in) + nMsg = "> " + msg; + + fullStatus.append(msg); + ui->statusList->addItem(nMsg); + + status("%s", nMsg.toLocal8Bit().constData()); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::addToStatusList(QStringList& list) +{ + QStringList cleanList; + foreach (QString msg, list) + { + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + continue; + + cleanList.append(msg); + + fullStatus.append(msg); + + status("%s", msg.toLocal8Bit().constData()); + } + + if (cleanList.size() == 0) + return; + + ui->statusList->addItems(cleanList); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::doScroll() +{ + if (!scrollPressed && scrollRequireMove)// && scrollStatusTimer.elapsed() > 1000) + { + ui->statusList->scrollToBottom(); + QApplication::processEvents(); + scrollStatusTimer.restart(); + scrollRequireMove = false; + } +} + +void MainWindow::statusSliderPressed() +{ + scrollPressed = true; + + if (scrollStatusTimer.elapsed() > 3000) + { + ui->statusList->clear(); + ui->statusList->addItems(fullStatus); + } +} + +void MainWindow::statusSliderReleased() +{ + scrollPressed = false; +} + +/* testing optimizing scrollbar, doesn't work +int MainWindow::computeListViewMinimumWidth(QAbstractItemView* view) +{ + int minWidth = 0; + QAbstractItemModel* model = view->model(); + + QStyleOptionViewItem option; + + int rowCount = model->rowCount(); + for (int row = 0; row < rowCount; ++row) + { + QModelIndex index = model->index(row, 0); + QSize size = view->itemDelegate()->sizeHint(option, index); + scrollDelegate = new MyItemDelegate(view); + view->setItemDelegate(scrollDelegate); + + minWidth = qMax(size.width(), minWidth); + } + + if (rowCount > 0) + { + if (scrollDelegate == NULL) + { + scrollDelegate = new MyItemDelegate(view); + QModelIndex index = model->index(0, 0); + view->setItemDelegate(scrollDelegate); + } + + scrollDelegate->setWidth(minWidth); + info("Width is %d\n", minWidth); + } + return minWidth; +} +*/ + +void MainWindow::receiveMsg(QString msg) +{ + ui->centralWidget->setStatusTip(msg); +} + +void MainWindow::setGRBL() +{ + GrblDialog dlg(this, &gcode); + dlg.setParent(this); + dlg.getSettings(); + dlg.exec(); +} + +void MainWindow::showAbout() +{ + About about(this); + about.exec(); +} + +void MainWindow::toggleSpindle() +{ + if (ui->SpindleOn->QAbstractButton::isChecked()) + { + sendGcode("M03\r"); + receiveList(tr("Spindle On.")); + } + else + { + sendGcode("M05\r"); + receiveList(tr("Spindle Off.")); + } +} + +void MainWindow::toggleRestoreAbsolute() +{ + absoluteAfterAxisAdj = ui->chkRestoreAbsolute->QAbstractButton::isChecked(); +} + +void MainWindow::updateCoordinates(Coord3D machineCoord, Coord3D workCoord) +{ + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + machineCoordinates = machineCoord; + workCoordinates = workCoord; +/* + if (workCoordinates.stoppedZ == false) + { + int newPos = workCoordinates.z + sliderTo; + + QString to; + to.sprintf("%d", newPos); + + ui->resultingZJogSliderPosition->setText(to); + } +*/ + refreshLcd(); +} + +void MainWindow::refreshLcd() +{ + lcdDisplay('X', true, workCoordinates.x); + lcdDisplay('Y', true, workCoordinates.y); + lcdDisplay('Z', true, workCoordinates.z); + lcdDisplay('X', false, machineCoordinates.x); + lcdDisplay('Y', false, machineCoordinates.y); + lcdDisplay('Z', false, machineCoordinates.z); + if (controlParams.useFourAxis) { + lcdDisplay(controlParams.fourthAxisType, true, workCoordinates.fourth); + lcdDisplay(controlParams.fourthAxisType, false, machineCoordinates.fourth); + } + else { + lcdDisplay(controlParams.fourthAxisType, true, 0); + lcdDisplay(controlParams.fourthAxisType, false, 0); + } +} + +void MainWindow::lcdDisplay(char axis, bool workCoord, float floatVal) +{ + QString value = QString::number(floatVal, 'f', 3); + switch (axis) + { + case 'X': + if (workCoord) + ui->lcdWorkNumberX->display(value); + else + ui->lcdMachNumberX->display(value); + break; + case 'Y': + if (workCoord) + ui->lcdWorkNumberY->display(value); + else + ui->lcdMachNumberY->display(value); + break; + case 'Z': + if (workCoord) + ui->lcdWorkNumberZ->display(value); + else + ui->lcdMachNumberZ->display(value); + break; + default: + if (axis == FOURTH_AXIS_A || axis == FOURTH_AXIS_B || axis == FOURTH_AXIS_C +/// LETARTARE + || axis == FOURTH_AXIS_U || axis == FOURTH_AXIS_V || axis == FOURTH_AXIS_W +/// <- + ) + { + if (workCoord) + ui->lcdWorkNumberFourth->display(value); + else + ui->lcdMachNumberFourth->display(value); + } + else + { + err("Unexpected type %c", axis); + } + break; + } +} + +void MainWindow::zJogSliderDisplay(int pos) +{ + QString str; + + pos -= CENTER_POS; + + if (pos > 0) + if(controlParams.useMm) + str.sprintf("+%d", pos); + else + str.sprintf("+%.1f",(double)pos/10); + else if (pos < 0) + if(controlParams.useMm) + str.sprintf("%d", pos); + else + str.sprintf("%.1f", (double)pos/10); + else + str = "0"; + + ui->currentZJogSliderDelta->setText(str); + + double newPos; + QString to; + if(controlParams.useMm) + newPos = pos + sliderTo; + else + newPos = (double)pos/10+sliderTo; + + if(controlParams.useMm) + to.sprintf("%.1f", newPos); + else + to.sprintf("%.1f", newPos); + + if (sliderPressed) + { + ui->resultingZJogSliderPosition->setText(to); + if(controlParams.useMm) + info("Usr chg: pos=%d new=%d\n", pos, newPos); + else + info("Usr chg: pos=%.1f new=%.1f\n", (double)pos/10, newPos); + } + else + { + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + if(controlParams.useMm) + info("Usr chg no slider: %d\n", pos); + else + info("Usr chg no slider: %.1f\n", (double) pos/10); + } +} + +void MainWindow::zJogSliderPressed() +{ + sliderPressed = true; + if (workCoordinates.stoppedZ && workCoordinates.sliderZIndex == sliderZCount) + { + info("Pressed and stopped\n"); + sliderTo = workCoordinates.z; + } + else + { + info("Pressed not stopped\n"); + } +} + +void MainWindow::zJogSliderReleased() +{ + info("Released\n"); + if (sliderPressed) + { + sliderPressed = false; + int value = ui->verticalSliderZJog->value(); + + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + + value -= CENTER_POS; + + if (value != 0) + { + if(controlParams.useMm) + sliderTo += value; + else + sliderTo += (double)value/10; + float setTo = value; + if(controlParams.useMm) + emit axisAdj('Z', setTo, invZ, absoluteAfterAxisAdj, sliderZCount++); + else + emit axisAdj('Z', setTo/10, invZ, absoluteAfterAxisAdj, sliderZCount++); + } + } + + + //ui->resultingZJogSliderPosition->setText("0"); +} + +void MainWindow::setQueuedCommands(int commandCount, bool running) +{ + if (running) + { + switch (queuedCommandState) + { + case QCS_OK: + if (lastQueueCount == 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 2000) + { + if (!queuedCommandsStarved) + { + //diag("DG >>>>Switch to red\n"); + + queuedCommandsStarved = true; + + ui->labelQueuedCommands->setStyleSheet("QLabel { background-color : rgb(255,0,0); color : white; }"); + + queuedCommandState = QCS_WAITING_FOR_ITEMS; + } + } + } + break; + case QCS_WAITING_FOR_ITEMS: + if (commandCount > 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 3000) + { + if (queuedCommandsStarved) + { + //diag("DG >>>>Switch to green\n"); + + queuedCommandsStarved = false; + + ui->labelQueuedCommands->setStyleSheet(""); + } + + queuedCommandsEmptyTimer.restart(); + + queuedCommandState = QCS_OK; + } + } + break; + } + + if (queuedCommandsRefreshTimer.elapsed() > 1000) + { + ui->progressQueuedCommands->setValue(commandCount); + queuedCommandsRefreshTimer.restart(); + } + } + else + { + queuedCommandsEmptyTimer.restart(); + queuedCommandState = QCS_OK; + ui->progressQueuedCommands->setValue(commandCount); + } + + lastQueueCount = commandCount; +} + +void MainWindow::setLcdState(bool valid) +{ + if (lastLcdStateValid != valid) + { + QString ss = ""; + if (!valid) + { + ss = "QLCDNumber { background-color: #F8F8F8; color: #F0F0F0; }"; + } + ui->lcdWorkNumberX->setStyleSheet(ss); + ui->lcdMachNumberX->setStyleSheet(ss); + ui->lcdWorkNumberY->setStyleSheet(ss); + ui->lcdMachNumberY->setStyleSheet(ss); + ui->lcdWorkNumberZ->setStyleSheet(ss); + ui->lcdMachNumberZ->setStyleSheet(ss); + ui->lcdWorkNumberFourth->setStyleSheet(ss); + ui->lcdMachNumberFourth->setStyleSheet(ss); + + lastLcdStateValid = valid; + } +} + +void MainWindow::refreshPosition() +{ + gotoXYZFourth(REQUEST_CURRENT_POS); +} + +void MainWindow::comboStepChanged(const QString& text) +{ + jogStepStr = text; + jogStep = jogStepStr.toFloat(); +} + +/// LETARTARE T2 +void MainWindow::setLinesFile(QString linesFile) +{ + linesFile += "/" + QString().setNum(totalLinesFile); + ui->outputLines->setText(linesFile); +} +/// <-- diff --git a/GC-3.6.1-T2/src/mainwindow.h b/GC-3.6.1-T2/src/mainwindow.h new file mode 100644 index 0000000..5c8764f --- /dev/null +++ b/GC-3.6.1-T2/src/mainwindow.h @@ -0,0 +1,259 @@ +/**************************************************************** + * mainwindow.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "about.h" +#include "definitions.h" +#include "grbldialog.h" +#include "options.h" +//#include "filesender.h" +#include "timer.h" +#include "positem.h" +#include "gcode.h" +#include "renderarea.h" + +#define COMPANY_NAME "zapmaker" +#define APPLICATION_NAME "GrblController" +#define DOMAIN_NAME "org.zapmaker" + +#define TAB_AXIS_INDEX 0 +#define TAB_VISUALIZER_INDEX 1 +#define TAB_ADVANCED_INDEX 2 + +#define CENTER_POS 40 + +#define MAX_STATUS_LINES_WHEN_ACTIVE 200 + +/* testing optimizing scrollbar, doesn't work right +class MyItemDelegate : public QItemDelegate +{ +private: + int width; + QAbstractItemView *parentWidget; + +public: + + MyItemDelegate(QAbstractItemView *p) : parentWidget(p) {} + + void setWidth(int w) + { + width = w; + } + + void drawDisplay(QPainter *painter,const + QStyleOptionViewItem &option,const QRect &rect,const QString &text) const{ + + QRect tempRect(rect); + tempRect.setWidth(parentWidget->width()); + QItemDelegate::drawDisplay(painter,option,tempRect,text); + + } + + QSize sizeHint(const QStyleOptionViewItem & option, const + QModelIndex & index ) const { + + QListView *list = qobject_cast(parentWidget); + QSize newSize(QItemDelegate::sizeHint(option,index)); + if( list ) newSize.setWidth( width ); + return newSize; + } +}; +*/ + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void closeEvent(QCloseEvent *event); + + //variables + int delete_nr; + +signals: + //threads + void openPort(QString port, QString baudRate); + void closePort(bool reopen); + void shutdown(); + void sendGcode(QString line, bool recordResponseOnFail = false, int waitCount = SHORT_WAIT_SEC); + void sendFile(QString path); + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void setProgress(int percent); + void setRuntime(QString runtime); + void sendSetHome(); + void sendGrblReset(); + void sendGrblUnlock(); + void goToHome(); + void setItems(QList); + +private slots: + //buttons + void openPort(); + void setGRBL(); + //Adjust + void decX(); + void decY(); + void decZ(); + void decFourth(); + void incFourth(); + void incX(); + void incY(); + void incZ(); + void setHome(); + //manual + void gotoXYZFourth(); + //send Gcode + void begin(); + void openFile(); + void stop(); + void stopSending(); + // + void portIsOpen(bool sendCode); + void portIsClosed(bool reopen); + void adjustedAxis(); + + //check boxes + void toggleSpindle(); + void toggleRestoreAbsolute(); + + //communications + //options + void setSettings(); + //thread + void receiveList(QString msg); + void receiveListFull(QStringList list); + void receiveListOut(QString msg); + void receiveMsg(QString msg); + //menu bar + void getOptions(); + void showAbout(); + void enableGrblDialogButton(); + void grblReset(); + void grblUnlock(); + void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); + void goHomeSafe(); + void zJogSliderDisplay(int pos); + void zJogSliderPressed(); + void zJogSliderReleased(); + void doScroll(); + void statusSliderPressed(); + void statusSliderReleased(); + void setQueuedCommands(int commandCount, bool running); + void setLcdState(bool valid); + void refreshPosition(); + void comboStepChanged(const QString& text); +/// T2 + void setLinesFile(QString) ; + +private: + // enums + enum + { + NO_ITEM = 0, + X_ITEM, + Y_ITEM, + I_ITEM, + J_ITEM, + }; + enum + { + QCS_OK = 0, + QCS_WAITING_FOR_ITEMS + }; + //objects + Ui::MainWindow *ui; + //FileSender fileSender; + //QThread fileSenderThread; + GCode gcode; + QThread gcodeThread; + + Timer runtimeTimer; + QThread runtimeTimerThread; + + //variables + bool invX; + bool invY; + bool invZ; + bool invFourth; + /// for translation + QString open_button_text ; + QString close_button_text ; + bool mm; + QString styleSheet; + QString directory; + QString nameFilter; + QString lastOpenPort; + QString lastBaudRate; + QByteArray fileOpenDialogState; + Coord3D machineCoordinates; + Coord3D workCoordinates; + bool absoluteAfterAxisAdj; + bool checkLogWrite; + QTime scrollStatusTimer; + QTime queuedCommandsEmptyTimer; + QTime queuedCommandsRefreshTimer; + QList posList; + bool sliderPressed; + double sliderTo; + int sliderZCount; + bool promptedAggrPreload; + ControlParams controlParams; + QTimer *scrollTimer; + bool scrollRequireMove; + bool scrollPressed; + bool queuedCommandsStarved; + int lastQueueCount; + int queuedCommandState; + QStringList fullStatus; + bool lastLcdStateValid; + float jogStep; + QString jogStepStr; + + //methods + int SendJog(QString strline); + void readSettings(); + void writeSettings(); + void addToStatusList(bool in, QString msg); + void addToStatusList(QStringList& list); + void disableAllButtons(); + void openPortCtl(bool reopen); + void resetProgress(); + void refreshLcd(); + void lcdDisplay(char axis, bool workCoord, float value); + void updateSettingsFromOptionDlg(QSettings& settings); + int computeListViewMinimumWidth(QAbstractItemView* view); + void preProcessFile(QString filepath); + bool processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g); + double decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue); + double decodeDouble(QString value, bool& valid); +/// T2 + int totalLinesFile; +}; + + +#endif // MAINWINDOW_H diff --git a/GC-3.6.1-T2/src/mainwindow.ui b/GC-3.6.1-T2/src/mainwindow.ui new file mode 100644 index 0000000..35de951 --- /dev/null +++ b/GC-3.6.1-T2/src/mainwindow.ui @@ -0,0 +1,1877 @@ + + + MainWindow + + + Qt::NonModal + + + true + + + + 0 + 0 + 972 + 668 + + + + + 7 + 0 + + + + + 10000000 + 10000000 + + + + Grbl Controller + + + + + + + + 10 + + + 1 + + + 0 + + + + + 2 + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Port name + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + + + + + + + + + + 0 + 0 + + + + Open + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + + + + QFrame::NoFrame + + + Baud Rate + + + + + + + + + + + + + + Last State: + + + + + + + + 75 + true + + + + + + + + + + + + + + + + + + + false + + + Send File + + + + + + + + Stop + + + + + + + Qt::Horizontal + + + + 2 + 20 + + + + + + + + Choose file + + + + + + + Begin + + + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + 10 + + + 0 + + + %v + + + + + + + + 0 + 0 + + + + File progress + + + + + + + + 0 + 0 + + + + Queued Commands + + + + + + + + + + + false + + + Runtime: + + + + + + + false + + + + + + + + + + Lines + + + + + + + + 50 + false + + + + 0 + + + + + + + + + + + + + + Command + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + 12 + + + + + + + + + false + + + Qt::ScrollBarAsNeeded + + + 16 + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QListView::Static + + + false + + + QListView::Adjust + + + QListView::SinglePass + + + false + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + 2 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + X + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Work Coordinates + + + + + + + + + + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + Y + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 10 + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Box + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + Z + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + C + + + Qt::AlignCenter + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + 1 + + + 0 + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Machine Coordinates + + + + + + + + 100 + 16777215 + + + + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Axis Control + + + + + + QLayout::SetDefaultConstraint + + + + + QLayout::SetMaximumSize + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 18 + 17 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + + + + 10 + 75 + true + + + + C Jog + + + Qt::AlignCenter + + + + + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 30 + + + 30 + + + + + + 0 + 0 + + + + 80 + + + 40 + + + 40 + + + Qt::Vertical + + + false + + + false + + + QSlider::TicksBelow + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + 10 + 75 + true + + + + Z Jog + + + Qt::AlignCenter + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + + + + + + + + + + 0 + 0 + + + + Absolute coordinates after adjust + + + + + + + + 0 + 0 + + + + Spindle On + + + false + + + + + + + + + 0 + + + 4 + + + 0 + + + 5 + + + + + + 0 + 0 + + + + Step Size + + + + + + + + 0 + 0 + + + + + + + + + + + + + Visualizer + + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 244 + 237 + 187 + + + + + + + 244 + 237 + 187 + + + + + + + + true + + + + + + + + Advanced + + + + + 10 + 10 + 152 + 87 + + + + Reset Control + + + + + + + + + 0 + 0 + + + + Soft Reset Grbl + + + + + + + + 0 + 0 + + + + Unlock Grbl + + + + + + + + + + + 170 + 30 + 131 + 41 + + + + + 0 + 0 + + + + + 8 + + + + GRBL Settings + + + + + + + + + + + + 0 + 0 + + + + + 8 + + + + false + + + Zero Position + + + + + + + + 0 + 0 + + + + Go Home + + + + + + + Refresh Pos + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Firmware : + + + + + + + + 75 + true + + + + Qt::NoContextMenu + + + none + + + + + + + + + + + + + 0 + 0 + 972 + 23 + + + + + &Help + + + + + + &Tools + + + + + + &File + + + + + + + + + + + &About + + + + + &Options + + + + + E&xit + + + + + + + RenderArea + QWidget +
renderarea.h
+ 1 +
+
+ + + + +
diff --git a/GC-3.6.1-T2/src/makeWin.bat b/GC-3.6.1-T2/src/makeWin.bat new file mode 100644 index 0000000..0483953 --- /dev/null +++ b/GC-3.6.1-T2/src/makeWin.bat @@ -0,0 +1,18 @@ +rem May 30, 2014 +rem LETARTARE + +rem 3.6.1-Tx + +rem for release + +qmake -config release -spec win32-g++ GcodeSenderGUIthreads.pro +mingw32-make -fmakefile.release +rem release\GrblController.exe + +rem for debug + +rem qmake -config debug -spec win32-g++ GcodeSenderGUIthreads.pro +rem mingw32-make -fmakefile.debug +rem debug\GrblController.exe + +cd .. diff --git a/GC-3.6.1-T2/src/options.cpp b/GC-3.6.1-T2/src/options.cpp new file mode 100644 index 0000000..54a4cae --- /dev/null +++ b/GC-3.6.1-T2/src/options.cpp @@ -0,0 +1,286 @@ +/**************************************************************** + * options.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "options.h" +#include "ui_options.h" + +Options::Options(QWidget *parent) : + QDialog(parent), + ui(new Ui::Options) +{ + ui->setupUi(this); + + connect(ui->checkBoxUseMmManualCmds,SIGNAL(toggled(bool)),this,SLOT(toggleUseMm(bool))); + connect(ui->chkLimitZRate,SIGNAL(toggled(bool)),this,SLOT(toggleLimitZRate(bool))); + connect(ui->checkBoxFourAxis,SIGNAL(toggled(bool)),this,SLOT(toggleFourAxis(bool))); + connect(ui->checkBoxPositionReportEnabled,SIGNAL(toggled(bool)),this,SLOT(togglePosReporting(bool))); + + QSettings settings; + + QString invX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString invY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString invZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + + QString invFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + ui->chkInvFourth->setChecked(invFourth == "true"); + ui->chkInvX->setChecked(invX == "true"); + ui->chkInvY->setChecked(invY == "true"); + ui->chkInvZ->setChecked(invZ == "true"); + + // enable logging by default + QString enDebugLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + // default aggressive preload behavior to 'true'! + QString enAggressivePreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + QString enFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + char fourthAxisType = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + + if (enFourAxis == "false") + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + + ui->groupBoxFourthAxis->setEnabled(false); + } + else + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + + switch (fourthAxisType) + { + case FOURTH_AXIS_A: + default: + ui->radioButtonFourthAxisA->setChecked(true); + break; + case FOURTH_AXIS_B: + ui->radioButtonFourthAxisB->setChecked(true); + break; + case FOURTH_AXIS_C: + ui->radioButtonFourthAxisC->setChecked(true); + break; +/// LETARTARE + case FOURTH_AXIS_U: + ui->radioButtonFourthAxisU->setChecked(true); + break; + case FOURTH_AXIS_V: + ui->radioButtonFourthAxisV->setChecked(true); + break; + case FOURTH_AXIS_W: + ui->radioButtonFourthAxisW->setChecked(true); + break; +/// <-- + } + } + + ui->checkBoxEnableDebugLog->setChecked(enDebugLog == "true"); + ui->chkAggressivePreload->setChecked(enAggressivePreload == "true"); + //ui->checkBoxWaitForJogToComplete->setChecked(waitForJogToComplete == "true"); + ui->checkBoxWaitForJogToComplete->hide(); + ui->checkBoxUseMmManualCmds->setChecked(useMmManualCmds == "true"); + ui->checkBoxFourAxis->setChecked(enFourAxis == "true"); + + int waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + ui->spinResponseWaitSec->setValue(waitTime); + + double zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + ui->doubleSpinZJogRate->setValue(zJogRate); + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + ui->chkLimitZRate->setChecked(zRateLimit == "true"); + + double zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + ui->doubleSpinZRateLimit->setValue(zRateLimitAmount); + double xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + ui->doubleSpinXYRate->setValue(xyRateAmount); + + if (!ui->chkLimitZRate->isChecked()) + { + ui->doubleSpinZRateLimit->setEnabled(false); + ui->doubleSpinXYRate->setEnabled(false); + } + + QString ffCmd = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + ui->chkFilterFileCommands->setChecked(ffCmd == "true"); + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + ui->checkBoxReducePrecForLongLines->setChecked(rPrecision == "true"); + ui->spinBoxGrblLineBufferSize->setValue(settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value()); + ui->spinBoxCharSendDelay->setValue(settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value()); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + QString posReqType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_NOT_WHEN_MANUAL).value(); + double posRateFreqSec = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + + ui->checkBoxPositionReportEnabled->setChecked(enPosReq == "true"); + ui->doubleSpinBoxPosRequestFreqSec->setValue(posRateFreqSec); + if (posReqType == PREQ_NOT_WHEN_MANUAL) + { + ui->radioButton_ReqNotDuringManual->setChecked(true); + } + else if (posReqType == PREQ_ALWAYS) + { + ui->radioButton_ReqAlways->setChecked(true); + } + else + { + ui->radioButton_ReqAlwaysNoIdleCheck->setChecked(true); + } + + togglePosReporting(enPosReq == "true"); + +} + +Options::~Options() +{ + delete ui; +} + +void Options::accept() +{ + QSettings settings; + + settings.setValue(SETTINGS_INVERSE_X, ui->chkInvX->isChecked()); + settings.setValue(SETTINGS_INVERSE_Y, ui->chkInvY->isChecked()); + settings.setValue(SETTINGS_INVERSE_Z, ui->chkInvZ->isChecked()); + settings.setValue(SETTINGS_INVERSE_FOURTH, ui->chkInvFourth->isChecked()); + settings.setValue(SETTINGS_ENABLE_DEBUG_LOG, ui->checkBoxEnableDebugLog->isChecked()); + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, ui->chkAggressivePreload->isChecked()); + settings.setValue(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, ui->checkBoxWaitForJogToComplete->isChecked()); + settings.setValue(SETTINGS_USE_MM_FOR_MANUAL_CMDS, ui->checkBoxUseMmManualCmds->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_USE, ui->checkBoxFourAxis->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_TYPE, getFourthAxisType()); + + settings.setValue(SETTINGS_RESPONSE_WAIT_TIME, ui->spinResponseWaitSec->value()); + settings.setValue(SETTINGS_Z_JOG_RATE, ui->doubleSpinZJogRate->value()); + + settings.setValue(SETTINGS_Z_RATE_LIMIT, ui->chkLimitZRate->isChecked()); + settings.setValue(SETTINGS_Z_RATE_LIMIT_AMOUNT, ui->doubleSpinZRateLimit->value()); + settings.setValue(SETTINGS_XY_RATE_AMOUNT, ui->doubleSpinXYRate->value()); + + settings.setValue(SETTINGS_FILTER_FILE_COMMANDS, ui->chkFilterFileCommands->isChecked()); + settings.setValue(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, ui->checkBoxReducePrecForLongLines->isChecked()); + settings.setValue(SETTINGS_GRBL_LINE_BUFFER_LEN, ui->spinBoxGrblLineBufferSize->value()); + settings.setValue(SETTINGS_CHAR_SEND_DELAY_MS, ui->spinBoxCharSendDelay->value()); + + settings.setValue(SETTINGS_ENABLE_POS_REQ, ui->checkBoxPositionReportEnabled->isChecked()); + settings.setValue(SETTINGS_TYPE_POS_REQ, getPosReqType()); + settings.setValue(SETTINGS_POS_REQ_FREQ_SEC, ui->doubleSpinBoxPosRequestFreqSec->value()); + + connect(this, SIGNAL(setSettings()), parentWidget(), SLOT(setSettings())); + + emit setSettings(); + this->close(); +} + +void Options::toggleUseMm(bool useMm) +{ + double zJogRate = ui->doubleSpinZJogRate->value(); + double zRateLimit = ui->doubleSpinZRateLimit->value(); + double xyRate = ui->doubleSpinXYRate->value(); + + if (useMm) + { + ui->doubleSpinZJogRate->setValue(zJogRate * MM_IN_AN_INCH); + ui->doubleSpinZRateLimit->setValue(zRateLimit * MM_IN_AN_INCH); + ui->doubleSpinXYRate->setValue(xyRate * MM_IN_AN_INCH); + } + else + { + ui->doubleSpinZJogRate->setValue(zJogRate / MM_IN_AN_INCH); + ui->doubleSpinZRateLimit->setValue(zRateLimit / MM_IN_AN_INCH); + ui->doubleSpinXYRate->setValue(xyRate / MM_IN_AN_INCH); + } +} + +void Options::toggleLimitZRate(bool limitZ) +{ + ui->doubleSpinZRateLimit->setEnabled(limitZ); + ui->doubleSpinXYRate->setEnabled(limitZ); +} + +void Options::toggleFourAxis(bool four) +{ + if (four) + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + } + else + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->groupBoxFourthAxis->setEnabled(false); + } + +} + +void Options::togglePosReporting(bool usePosReporting) +{ + if (usePosReporting) + { + ui->groupBox_ReqPos->setEnabled(true); + } + else + { + ui->groupBox_ReqPos->setEnabled(false); + } +} + +char Options::getFourthAxisType() +{ + char type = FOURTH_AXIS_A; + + if (ui->radioButtonFourthAxisA->isChecked()) + { + type = FOURTH_AXIS_A; + } + else + if (ui->radioButtonFourthAxisB->isChecked()) + { + type = FOURTH_AXIS_B; + } + else + if (ui->radioButtonFourthAxisC->isChecked()) + { + type = FOURTH_AXIS_C; + } +/// LETATARE + if (ui->radioButtonFourthAxisU->isChecked()) + { + type = FOURTH_AXIS_U; + } + else + if (ui->radioButtonFourthAxisV->isChecked()) + { + type = FOURTH_AXIS_V; + } + else + if (ui->radioButtonFourthAxisW->isChecked()) + { + type = FOURTH_AXIS_W; + } +/// <-- + return type; +} + +QString Options::getPosReqType() +{ + if (ui->radioButton_ReqAlways->isChecked()) + { + return PREQ_ALWAYS; + } + else if (ui->radioButton_ReqNotDuringManual->isChecked()) + { + return PREQ_NOT_WHEN_MANUAL; + } + return PREQ_ALWAYS_NO_IDLE_CHK; +} diff --git a/GC-3.6.1-T2/src/options.h b/GC-3.6.1-T2/src/options.h new file mode 100644 index 0000000..c97ea62 --- /dev/null +++ b/GC-3.6.1-T2/src/options.h @@ -0,0 +1,89 @@ +/**************************************************************** + * options.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include +#include +#include +#include +#include + +#include "definitions.h" + +#define SETTINGS_INVERSE_FOURTH "inverse.c"// leave as 'c' for backwards compat +#define SETTINGS_INVERSE_X "inverse.x" +#define SETTINGS_INVERSE_Y "inverse.y" +#define SETTINGS_INVERSE_Z "inverse.z" +#define SETTINGS_RESPONSE_WAIT_TIME "responseWaitTime" +#define SETTINGS_Z_JOG_RATE "zJogRate" +#define SETTINGS_ENABLE_DEBUG_LOG "debugLog" +#define SETTINGS_USE_AGGRESSIVE_PRELOAD "aggressivePreload" +#define SETTINGS_WAIT_FOR_JOG_TO_COMPLETE "waitForJogToComplete" +#define SETTINGS_USE_MM_FOR_MANUAL_CMDS "useMMForManualCommands" +#define SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ "absCoordForManualAfterAxisAdj" +#define SETTINGS_Z_RATE_LIMIT "zRateLimit" +#define SETTINGS_Z_RATE_LIMIT_AMOUNT "zRateLimitAmount" +#define SETTINGS_XY_RATE_AMOUNT "xyRateAmount" +#define SETTINGS_FOUR_AXIS_USE "fourAxis" +#define SETTINGS_FOUR_AXIS_TYPE "fourAxisType" + +#define SETTINGS_FILE_OPEN_DIALOG_STATE "fileopendialogstate" +#define SETTINGS_NAME_FILTER "namefilter" +#define SETTINGS_DIRECTORY "directory" +#define SETTINGS_PORT "port" +#define SETTINGS_BAUD "baud" + +#define SETTINGS_PROMPTED_AGGR_PRELOAD "promptedAggrPreload" + +#define SETTINGS_FILTER_FILE_COMMANDS "filterFileCommands" +#define SETTINGS_REDUCE_PREC_FOR_LONG_LINES "reducePrecisionForLongLines" +#define SETTINGS_GRBL_LINE_BUFFER_LEN "grblLineBufferLen" +#define SETTINGS_CHAR_SEND_DELAY_MS "charSendDelayMs" +#define SETTINGS_JOG_STEP "jogStep" + +#define SETTINGS_ENABLE_POS_REQ "positionRequest" +#define SETTINGS_TYPE_POS_REQ "posRequestType" +#define SETTINGS_POS_REQ_FREQ_SEC "posReqFreqSec" + + +namespace Ui { +class Options; +} + +class Options : public QDialog +{ + Q_OBJECT + +public: + explicit Options(QWidget *parent = 0); + ~Options(); + void accept(); + +signals: + void setSettings(); + +private slots: + void toggleUseMm(bool useMm); + void toggleLimitZRate(bool limitZ); + void toggleFourAxis(bool four); + void togglePosReporting(bool usePosReporting); + +private: + char getFourthAxisType(); + QString getPosReqType(); +private: + Ui::Options *ui; + //variables + int settings; + +}; + +#endif // OPTIONS_H diff --git a/GC-3.6.1-T2/src/options.ui b/GC-3.6.1-T2/src/options.ui new file mode 100644 index 0000000..e4edec0 --- /dev/null +++ b/GC-3.6.1-T2/src/options.ui @@ -0,0 +1,711 @@ + + + Options + + + + 0 + 0 + 521 + 317 + + + + Options + + + + + 10 + 10 + 501 + 261 + + + + 0 + + + + General + + + + + 10 + 146 + 451 + 71 + + + + + + + Z-Jog Rate (inches or mm/min) + + + + + + + Seconds to Wait for Response + + + + + + + 1 + + + 1000 + + + 60 + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 260.000000000000000 + + + + + + + + + 10 + 10 + 451 + 121 + + + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + + + Use aggressive preload strategy for Grbl + + + + + + + false + + + Wait for each jog/manual command to complete (future feature) + + + + + + + Write debugging log to home folder (requires restart) + + + + + + + + + Filtering + + + + + 10 + 10 + 471 + 81 + + + + Z Rate Limiting + + + + + 20 + 20 + 451 + 53 + + + + + + + Limit Z Rate + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 100.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Z-Rate Limit (inches or mm/min) + + + + + + + XY Rate (inches or mm/min) + + + + + + + 2 + + + 0.100000000000000 + + + 999999.989999999990687 + + + 2000.000000000000000 + + + + + + + + + + 10 + 200 + 261 + 24 + + + + + + + Character send delay ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 100 + 461 + 61 + + + + Command Filtering + + + + + 30 + 20 + 431 + 17 + + + + Filter file commands before sending + + + + + + 30 + 40 + 431 + 17 + + + + Selectively reduce precision for excessively long lines + + + + + + + 10 + 170 + 261 + 24 + + + + + + + Grbl Line Buffer Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 270 + 200 + 50 + 22 + + + + 20 + + + 10 + + + + + + 270 + 170 + 50 + 22 + + + + 50 + + + + + + Axis + + + + + 10 + 111 + 451 + 60 + + + + Invert Axis + + + + + 20 + 20 + 431 + 31 + + + + + + + X Axis + + + + + + + Y Axis + + + + + + + Z Axis + + + + + + + Fourth Axis + + + + + + + + + + 10 + 41 + 451 + 51 + + + + Selecting the Fourth axis + + + + + 10 + 22 + 50 + 17 + + + + A + + + true + + + + + + 80 + 22 + 50 + 17 + + + + B + + + + + + 150 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + C + + + + + + 240 + 20 + 50 + 21 + + + + Qt::PreventContextMenu + + + U + + + + + + 310 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + V + + + + + + 380 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + W + + + + + + + 10 + 11 + 421 + 17 + + + + Enable 4-axis mode + + + + + + Display + + + + + 10 + 10 + 481 + 141 + + + + + + + Enable position request and report + + + + + + + Position Request + + + + + 10 + 20 + 461 + 93 + + + + + + + Always Request (most reliable/slightly slower jogging) + + + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + + + Not during manual control (no position update during jog/manual) + + + + + + + + + Request frequency (seconds) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0.500000000000000 + + + 10.000000000000000 + + + 0.500000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + + + + + 320 + 280 + 191 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + Options + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Options + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GC-3.6.1-T2/src/pointitem.cpp b/GC-3.6.1-T2/src/pointitem.cpp new file mode 100644 index 0000000..c0a3db9 --- /dev/null +++ b/GC-3.6.1-T2/src/pointitem.cpp @@ -0,0 +1,41 @@ +#include "pointitem.h" + +PointItem::PointItem(double x1, double y1) + : ItemToBase(0), x(x1), y(y1) +{ +} + +void PointItem::moveToFirst(QPainterPath& path) +{ + Q_UNUSED(path); +} + +void PointItem::addToPath(QPainterPath& path) +{ + Q_UNUSED(path); +} + +PosItem PointItem::computeExtents() +{ + return PosItem(); +} + +double PointItem::getXScr() +{ + return screenX(x); +} + +double PointItem::getYScr() +{ + return screenY(y); +} + +double PointItem::getXRaw() +{ + return x; +} + +double PointItem::getYRaw() +{ + return y; +} diff --git a/GC-3.6.1-T2/src/pointitem.h b/GC-3.6.1-T2/src/pointitem.h new file mode 100644 index 0000000..6adacf5 --- /dev/null +++ b/GC-3.6.1-T2/src/pointitem.h @@ -0,0 +1,23 @@ +#ifndef POINTITEM_H +#define POINTITEM_H +#include "itemtobase.h" + +class PointItem : public ItemToBase +{ +public: + PointItem(double x, double y); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; +}; + +#endif // POINTITEM_H diff --git a/GC-3.6.1-T2/src/positem.cpp b/GC-3.6.1-T2/src/positem.cpp new file mode 100644 index 0000000..053a35f --- /dev/null +++ b/GC-3.6.1-T2/src/positem.cpp @@ -0,0 +1,48 @@ +#include "positem.h" + +void PosItem::setCoords(double x1, double y1, double i1, double j1) +{ + x = x1; + y = y1; + i = i1; + j = j1; +} + +void PosItem::setCoords(double x1, double y1, bool mm1) +{ + x = x1; + y = y1; + i = x1; + j = y1; + mm = mm1; +} + +void PosItem::expand(const PosItem& item) +{ + if (item.x < x) + x = item.x; + if (item.y < y) + y = item.y; + if (item.i > i) + i = item.i; + if (item.j > j) + j = item.j; +} + +void PosItem::toMm() +{ + x *= MM_IN_AN_INCH; + y *= MM_IN_AN_INCH; + i *= MM_IN_AN_INCH; + j *= MM_IN_AN_INCH; + mm = true; +} + +void PosItem::toInches() +{ + x /= MM_IN_AN_INCH; + y /= MM_IN_AN_INCH; + i /= MM_IN_AN_INCH; + j /= MM_IN_AN_INCH; + mm = false; +} diff --git a/GC-3.6.1-T2/src/positem.h b/GC-3.6.1-T2/src/positem.h new file mode 100644 index 0000000..aaea573 --- /dev/null +++ b/GC-3.6.1-T2/src/positem.h @@ -0,0 +1,45 @@ +#ifndef POSITEM_H +#define POSITEM_H +#include +//#include "stdio.h" +#include "definitions.h" + +class PosItem +{ +public: + PosItem() + : x(0), y(0), i(0), j(0), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1) + : x(x1), y(y1), i(0), j(0), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1) + : x(x1), y(y1), i(i1), j(j1), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1, bool arc1, bool cw1, bool mm1, int index1) + : x(x1), y(y1), i(i1), j(j1), + arc(arc1), cw(cw1), mm(mm1), index(index1) {} + + void setCoords(double x1, double y1, double i1, double j1); + void setCoords(double x1, double y1, bool mm); + void expand(const PosItem& item); + double width() { return qAbs(i - x); } + double height() { return qAbs(j - y); } + bool isNull() { return x == 0 && y == 0 && i == 0 && j == 0 && arc == false && cw == false && index == 0; } + void toMm(); + void toInches(); + +public: + double x; + double y; + double i; + double j; + bool arc; + bool cw; + bool mm; + int index; +}; + +Q_DECLARE_METATYPE ( PosItem ) + +#endif // POSITEM_H diff --git a/GC-3.6.1-T2/src/renderarea.cpp b/GC-3.6.1-T2/src/renderarea.cpp new file mode 100644 index 0000000..ca6be75 --- /dev/null +++ b/GC-3.6.1-T2/src/renderarea.cpp @@ -0,0 +1,75 @@ +#include "renderarea.h" + +RenderArea::RenderArea(QWidget *parent) + : QWidget(parent), + penProposedPath(QPen(Qt::blue)), penAxes(QPen(QColor(193,97,0))), + penCoveredPath(QPen(QColor(60,196,70), 2)), + penCurrPosActive(QPen(Qt::red, 6)), penCurrPosInactive(QPen(QColor(60,196,70), 6)), + penMeasure(QPen(QColor(151,111,26))), isLiveCurrPos(false) +{ + penCurrPosActive.setCapStyle(Qt::RoundCap); + penCurrPosInactive.setCapStyle(Qt::RoundCap); +} + +void RenderArea::setItems(QList itemsRcvd) +{ + items = itemsRcvd; + + listToRender.setCurrFileLine(0); + listToRender.convertList(items); + listToRender.updateLivePoint(); + update(); +} + +void RenderArea::setLivePoint(double x, double y, bool mm, bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; + livePoint.setCoords(x, y, mm); + listToRender.setLivePoint(livePoint); + update(); + +} + +void RenderArea::setVisualLivenessCurrPos(bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; +} + +void RenderArea::setVisCurrLine(int currLine) +{ + if (listToRender.setCurrFileLine(currLine)) + update(); +} + +void RenderArea::paintEvent(QPaintEvent * /* event */) +{ + if (!items.size()) + return; + + QSize size = this->size(); + + listToRender.rescale(size); + + QPainter painter(this); + + painter.setPen(penProposedPath); + listToRender.writePath(painter, false); + + painter.setPen(penAxes); + listToRender.drawAxes(painter); + + painter.setPen(penMeasure); + listToRender.drawMeasurements(painter); + + painter.setPen(penCoveredPath); + listToRender.writePath(painter, true); + + //if (!livePoint.isNull()) FIX isNull + { + if (isLiveCurrPos) + painter.setPen(penCurrPosActive); + else + painter.setPen(penCurrPosInactive); + listToRender.drawPoint(painter, livePoint); + } +} diff --git a/GC-3.6.1-T2/src/renderarea.h b/GC-3.6.1-T2/src/renderarea.h new file mode 100644 index 0000000..4023ecc --- /dev/null +++ b/GC-3.6.1-T2/src/renderarea.h @@ -0,0 +1,38 @@ +#ifndef RENDERAREA_H +#define RENDERAREA_H + +#include +#include +#include + +#include "positem.h" +#include "renderitemlist.h" +#include "arcitem.h" +#include "lineitem.h" + +class RenderArea : public QWidget +{ + Q_OBJECT +public: + explicit RenderArea(QWidget *parent = 0); + +signals: + +public slots: + void setItems(QList); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisualLivenessCurrPos(bool isLiveCP); + void setVisCurrLine(int currLine); + +protected: + void paintEvent(QPaintEvent *event); + +private: + QList items; + RenderItemList listToRender; + QPen penProposedPath, penAxes, penCoveredPath, penCurrPosActive, penCurrPosInactive, penMeasure; + PosItem livePoint; + bool isLiveCurrPos; +}; + +#endif // RENDERAREA_H diff --git a/GC-3.6.1-T2/src/renderitemlist.cpp b/GC-3.6.1-T2/src/renderitemlist.cpp new file mode 100644 index 0000000..ae94a7e --- /dev/null +++ b/GC-3.6.1-T2/src/renderitemlist.cpp @@ -0,0 +1,241 @@ +#include "renderitemlist.h" +#include + +RenderItemList::RenderItemList() + : scale(1), offsetx(50), offsety(50), mm(true), currFileLine(0) +{ + font.setStyleHint(QFont::Courier); + font.setPointSize(10); +} + +RenderItemList::~RenderItemList() +{ + clearList(); +} + +void RenderItemList::clearList() +{ + while (!list.isEmpty()) + delete list.takeFirst(); +} + +void RenderItemList::convertList(const QList& items) +{ + clearList(); + + if (items.size() == 0) + return; + + double lastx = items.at(0).x, lasty = items.at(0).y; + mm = items.at(0).mm; + foreach (PosItem item, items) + { + if (item.arc) + { + double px = lastx + item.i; + double py = lasty + item.j; + double sx = lastx; + double sy = lasty; + double ex = item.x; + double ey = item.y; + + list.append(new ArcItem( + sx, sy, ex, ey, px, py, item.cw, item.index)); + } + else + { + double sx = item.x; + double sy = item.y; + + list.append(new LineItem(sx, sy, item.index)); + } + + lastx = item.x; + lasty = item.y; + } + + extents.setCoords(0,0,0,0); + foreach (ItemToBase *item, list) + { + PosItem e = item->computeExtents(); + + // can't use QRectF because it reverses the y axis in anticipation of screendraws, which we don't want + //extents = extents.united(e); + + extents.expand(e); + } +} + +void RenderItemList::rescale(const QSize& size) +{ + PosItem liveExtents(extents); + liveExtents.expand(livePoint); + + double scalex = SCREEN_SCALE_FILE * (size.width() / (liveExtents.width())); + double scaley = SCREEN_SCALE_FILE * (size.height() / (liveExtents.height())); + + scale = qMin(scalex, scaley); + + offsetx = size.width() / 2 - ((liveExtents.x + liveExtents.i) / 2) * scale; + offsety = size.height() / 2 - ((liveExtents.y + liveExtents.j) / 2) * scale; + + windowSize = size; +} + +void RenderItemList::writePath(QPainter& painter, bool updatedFromFile) +{ + QPainterPath path; + ItemToBase *item = list.at(0); + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->moveToFirst(path); + foreach (item, list) + { + if (updatedFromFile) + { + if (item->getIndex() > currFileLine) + break; + } + + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->addToPath(path); + } + + painter.drawPath(path); +} + +void RenderItemList::drawAxes(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + + path.moveTo(x, 0); + path.lineTo(x, windowSize.height() - 1); + path.moveTo(0, y); + path.lineTo(windowSize.width() - 1, y); + + painter.drawPath(path); +} + +void RenderItemList::drawMeasurements(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + double xr = item->getXRaw(); + double yr = item->getYRaw(); + + const int length = 6; + LineItem x1(extents.x, yr, true, length); + x1.setParams(scale, windowSize.height(), offsetx, offsety); + x1.drawTo(path); + + LineItem x2(extents.i, yr, true, length); + x2.setParams(scale, windowSize.height(), offsetx, offsety); + x2.drawTo(path); + + LineItem y1(xr, extents.y, false, length); + y1.setParams(scale, windowSize.height(), offsetx, offsety); + y1.drawTo(path); + + LineItem y2(xr, extents.j, false, length); + y2.setParams(scale, windowSize.height(), offsetx, offsety); + y2.drawTo(path); + + painter.drawPath(path); + + painter.setFont(font); + + int ht = painter.fontMetrics().height(); + int wd = painter.fontMetrics().averageCharWidth(); + + QString units = mm ? QObject::tr(" mm") : QObject::tr(" inches"); + + QString info(QString::number(extents.j).append(units).append(QObject::tr(" (Width-X: ").append(QString::number(extents.width())) + .append(QObject::tr(" Height-Y: ")).append(QString::number(extents.height())).append(")")) ) ; + int xMsgTop = x + wd; + QRect br = painter.fontMetrics().boundingRect(info); + br.setWidth(br.width() + wd); + if (br.width() > (windowSize.width() - x)) + xMsgTop = wd; + +#ifdef Q_OS_MACX + writeText(painter, info, xMsgTop, (3 * ht / 4) + 4, wd); +#else + writeText(painter, info, xMsgTop, (3 * ht / 4) + 1, wd); +#endif + +#ifdef Q_OS_MACX + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 2) - 1, wd); +#else + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 4) - 1, wd); +#endif + + writeText(painter, QString::number(extents.x), wd, y - (ht / 4), wd); + + QString right = QString::number(extents.i); + br = painter.fontMetrics().boundingRect(right); + writeText(painter, right, windowSize.width() - (br.width() + wd), y - (ht / 4), wd); +} + +void RenderItemList::writeText(QPainter& painter, QString text, double x, double y, int avgCharWd) +{ + // We need to clear a rectangle into which our text will be written so it is easier to read + QRect br = painter.fontMetrics().boundingRect(text); + br.setWidth(br.width() + avgCharWd); + br.translate(x, y); + // TODO: get the background color from the window instead, otherwise + // any changes to it need to be changed here + painter.fillRect(br, QColor(244,237,187)); + painter.drawText(x, y, text); +} + +void RenderItemList::drawPoint(QPainter& painter, const PosItem& point) +{ + double divisor = 1; + if ((mm && !point.mm) || (!mm && point.mm)) + divisor = MM_IN_AN_INCH; + + PointItem p(point.x / divisor, point.y / divisor); + + p.setParams(scale, windowSize.height(), offsetx, offsety); + + painter.drawPoint(p.getXScr(), p.getYScr()); + +} + +bool RenderItemList::setCurrFileLine(const int currLine) +{ + currFileLine = currLine; + foreach (ItemToBase *item, list) + { + if (item->getIndex() == currLine) + return true; + else if (item->getIndex() > currLine) + return false; + } + return false; +} + +void RenderItemList::setLivePoint(const PosItem& livePoint1) +{ + livePoint = livePoint1; + + updateLivePoint(); +} + +void RenderItemList::updateLivePoint() +{ + if (mm && !livePoint.mm) + { + livePoint.toMm(); + } + else if (!mm && livePoint.mm) + { + livePoint.toInches(); + } +} diff --git a/GC-3.6.1-T2/src/renderitemlist.h b/GC-3.6.1-T2/src/renderitemlist.h new file mode 100644 index 0000000..8b17b9b --- /dev/null +++ b/GC-3.6.1-T2/src/renderitemlist.h @@ -0,0 +1,42 @@ +#ifndef RENDERITEMLIST_H +#define RENDERITEMLIST_H +#include "arcitem.h" +#include "lineitem.h" +#include "pointitem.h" + +#define SCREEN_SCALE_FILE 0.85 + +class RenderItemList +{ +public: + RenderItemList(); + virtual ~RenderItemList(); + + void convertList(const QList& items); + void rescale(const QSize& size); + void writePath(QPainter& painter, bool updatedFromFile); + void drawAxes(QPainter& painter); + void drawMeasurements(QPainter& painter); + void drawPoint(QPainter& painter, const PosItem& point); + bool setCurrFileLine(const int currLine); + void setLivePoint(const PosItem& livePoint); + void updateLivePoint(); + +private: + void clearList(); + void writeText(QPainter& painter, QString text, double x, double y, int avgCharWd); + +private: + QList list; + double scale; + double offsetx; + double offsety; + PosItem extents; + QSize windowSize; + bool mm; + int currFileLine; + PosItem livePoint; + QFont font; +}; + +#endif // RENDERITEMLIST_H diff --git a/GC-3.6.1-T2/src/rs232.cpp b/GC-3.6.1-T2/src/rs232.cpp new file mode 100644 index 0000000..587dd9e --- /dev/null +++ b/GC-3.6.1-T2/src/rs232.cpp @@ -0,0 +1,284 @@ +/**************************************************************** + * rs232.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "rs232.h" +#include + +RS232::RS232() + : port(NULL), detectedEOL(0), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS) +{ +} + +bool RS232::OpenComport(QString commPortStr, QString baudRate) +{ + if (port != NULL) + CloseComport(); + + bool ok; + BaudRateType baud = (BaudRateType)baudRate.toInt(&ok); + if (!ok) + { + baud = BAUD9600; + } + else + { + int possibleBaudRates[] = {BAUD110,BAUD300,BAUD600,BAUD1200,BAUD2400,BAUD4800,BAUD9600,BAUD19200,BAUD38400,BAUD57600,BAUD115200}; + int pbrCount = sizeof possibleBaudRates / sizeof possibleBaudRates[0]; + + bool found = false; + for (int i = 0; i < pbrCount; i++) + { + if (baud == possibleBaudRates[i]) + { + found = true; + break; + } + } + if (!found) + baud = BAUD9600; + } + + PortSettings settings = {baud, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10}; + + port = new QextSerialPort(commPortStr, settings, QextSerialPort::Polling); + + port->open(QIODevice::ReadWrite); + + return port->isOpen(); +} + + +int RS232::PollComport(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->read(buf, size); + return(n); +} + +// This is different than QIoDevice.readline() - this method only returns data if it has a full line in the +// input buffer by peeking at the buffer. It never removes items unless it can remove a full line. +int RS232::PollComportLine(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->peek(buf, size); + if (n <= 0) + return n; + + //printf("PEEK: %d out of %d\n", n, size); + if (detectedEOL == 0) + { + // algorithm assumes we received both eol chars if there are two in this peek + int pos = 0; + char firstEOL = 0; + char secondEOL = 0; + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == '\n' || b == '\r') + { + if (firstEOL == 0) + { + firstEOL = b; + pos = i; + } + else if ((pos + 1) == i) + { + secondEOL = b; + break; + } + else + break; + } + } + + if (firstEOL != 0) + { + if (secondEOL != 0) + { + detectedEOL = secondEOL; + detectedLineFeed = firstEOL; + detectedLineFeed += secondEOL; + } + else + { + detectedEOL = firstEOL; + detectedLineFeed = firstEOL; + } + } + } + + int toRead = 0; + if (detectedEOL) + { + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == detectedEOL) + { + toRead = i + 1; + break; + } + } + } + + // let's hope the serial subsystem's read buffer is big enough to find a linefeed + if (!toRead) + { + return 0; + } + + n = port->read(buf, toRead); + + return n; +} + +int RS232::SendBuf(const char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + if (size <= 0) + { + err( qPrintable(QObject::tr("Unexpected: Told to send %d bytes\n")), size) ; + return 1; + } + + char b[300] = {0}; + memcpy(b, buf, size); +#ifdef DIAG + printf("Sending to port %s [%s]:", port->portName().toLocal8Bit().constData(), b); + for (int x= 0; x < size; x++) + { + printf("%02X ", buf[x]); + } + printf("\n"); + fflush(stdout); +#endif + + port->waitForBytesWritten(-1);// this usually doesn't do anything, but let's put it here in case + +#if 1 + // On very fast PCs running Windows we have to slow down the sending of bytes to grbl + // because grbl loses bytes due to its interrupt service routine (ISR) taking too many clock + // cycles away from serial handling. + int result = 0; + for (int i = 0; i < size; i++) + { + result = port->write(&buf[i], 1); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + break; + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + break; + } + + if (charSendDelayMs > 0) + { + SLEEP(charSendDelayMs); + } + } + +#else + // DO NOT RUN THIS CODE + int result = port->write(buf, size); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + /* the following code doesn't seem to help. Generate an error instead + int limit = 0; + while (!result && limit < 100) + { + SLEEP(100); + result = port->write(buf, size); + limit++; + } + + if (!result) + { + err("Unable to write %d bytes to port!", size); + } + else if (result != size) + err("Unexpected: Retry send wrote %d bytes out of expected %d\n", result, size); + */ + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + } +#endif + return result; +} + + +void RS232::CloseComport() +{ + if (port != NULL) + { + port->close(); + delete port; + port = NULL; + } +} + +void RS232::Reset() //still to test +{ + if (port != NULL) + port->reset(); +} + +void RS232::flush() +{ + int n=1; + char buf[255]; + + while (n > 0) + n = PollComport(buf,255); +} + +bool RS232::isPortOpen() +{ + if (port == NULL) + return false; + + return port->isOpen(); +} + +QString RS232::getDetectedLineFeed() +{ + return detectedLineFeed; +} + +int RS232::bytesAvailable() +{ + int n = port->bytesAvailable(); + return n; +} + +void RS232::setCharSendDelayMs(int csd) +{ + charSendDelayMs = csd; +} diff --git a/GC-3.6.1-T2/src/rs232.h b/GC-3.6.1-T2/src/rs232.h new file mode 100644 index 0000000..a70ec55 --- /dev/null +++ b/GC-3.6.1-T2/src/rs232.h @@ -0,0 +1,76 @@ +/**************************************************************** + * rs232.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef RS232_H +#define RS232_H + +#include +#include + +#include +#include +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#include +#include "../termiosext.h" +#include +#include +#include +#include +#include +#include +#else +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +// TODO - R - if I leave out Windows.h then Sleep is not found??? +#include +#include +#endif +#endif + +#include +#include + +#include "definitions.h" + + +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#define SLEEP(x) usleep(1000 * x); +#else +#define SLEEP(x) Sleep(x); +#endif + + +class RS232 +{ +public: + RS232(); + //methods + bool OpenComport(QString commPortStr, QString baudRate); + int PollComport(char *buf, int size); + int PollComportLine(char *buf, int size); + int SendBuf(const char *buf, int size); + void CloseComport(); + void Reset(); + void flush(); + bool isPortOpen(); + QString getDetectedLineFeed(); + int bytesAvailable(); + void setCharSendDelayMs(int charSendDelayMs); + +private: + QextSerialPort *port; + char detectedEOL; + QString detectedLineFeed; + int charSendDelayMs; + +}; + + +#endif // RS232_H diff --git a/GC-3.6.1-T2/src/termiosext.h b/GC-3.6.1-T2/src/termiosext.h new file mode 100644 index 0000000..93ac44f --- /dev/null +++ b/GC-3.6.1-T2/src/termiosext.h @@ -0,0 +1,11 @@ +#ifndef TERMIOSEXT_H +#define TERMIOSEXT_H + +#ifdef Q_OS_ANDROID +static __inline__ int tcdrain(int fd) +{ + return ioctl(fd, TCSBRK, (void *)(intptr_t)1); +} +#endif + +#endif // TERMIOSEXT_H diff --git a/GC-3.6.1-T2/src/timer.cpp b/GC-3.6.1-T2/src/timer.cpp new file mode 100644 index 0000000..2556b7d --- /dev/null +++ b/GC-3.6.1-T2/src/timer.cpp @@ -0,0 +1,35 @@ +/**************************************************************** + * timer.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "timer.h" +Timer::Timer(QObject *parent) : + QObject(parent), timing(false) +{ + startTimer(500); +} + +void Timer::resetTimer(bool timeIt) +{ + timing = timeIt; + if (timeIt) + timer.start(); +} + +void Timer::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (timing) + { + int secs = timer.elapsed() / 1000; + int mins = (secs / 60) % 60; + int hours = (secs / 3600); + secs = secs % 60; + emit setRuntime(QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(mins, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'))); + } +} diff --git a/GC-3.6.1-T2/src/timer.h b/GC-3.6.1-T2/src/timer.h new file mode 100644 index 0000000..eed99ca --- /dev/null +++ b/GC-3.6.1-T2/src/timer.h @@ -0,0 +1,36 @@ +/**************************************************************** + * timer.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include + +class Timer : public QObject +{ + Q_OBJECT + +public: + explicit Timer(QObject *parent = 0); + +signals: + void setRuntime(QString timestr); + +public slots: + void resetTimer(bool timeIt); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QTime timer; + bool timing; +}; + +#endif // TIMER_H diff --git a/GC-3.6.1-T2/src/translate.bat b/GC-3.6.1-T2/src/translate.bat new file mode 100644 index 0000000..3f52694 --- /dev/null +++ b/GC-3.6.1-T2/src/translate.bat @@ -0,0 +1,21 @@ +rem translate.bat + +echo off + +set PATH=%PATH%;u:\DONNEES\SVN_COMPILE\qt\4.7.3\bin + +rem create "trlocale\*.ts" + +lupdate.exe GcodeSenderGUIthreads.pro + +rem create *.qm + +linguist trlocale\GrblController_fr.ts + +lrelease trlocale\GrblController_fr.ts -qm trlocale\GrblController_fr.qm + +xcopy /Y trlocale\GrblController_fr.qm release\trlocale\ + +xcopy /Y trlocale\GrblController_fr.qm ..\cons\trlocale\ + +cd .. diff --git a/GC-3.6.1-T2/src/trlocale/GrblController_fr.qm b/GC-3.6.1-T2/src/trlocale/GrblController_fr.qm new file mode 100644 index 0000000..236187d Binary files /dev/null and b/GC-3.6.1-T2/src/trlocale/GrblController_fr.qm differ diff --git a/GC-3.6.1-T2/src/trlocale/GrblController_fr.ts b/GC-3.6.1-T2/src/trlocale/GrblController_fr.ts new file mode 100644 index 0000000..38de574 --- /dev/null +++ b/GC-3.6.1-T2/src/trlocale/GrblController_fr.ts @@ -0,0 +1,1316 @@ + + + + + About + + + About... + A propos ... + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + Le programme est fourni en l'état SANS GARANTIE D'AUCUNE SORTE, MEME LES GARANTIES DE CONCEPTION, MARCHANDE ET D'ADAPTATION À UN USAGE PARTICULIER. + + + + Grbl Controller + Controleur Grbl + + + Grbl Controller 4 + Controleur Grbl 4 + + + + GCode + + + Can't open COM port + Impossible d'ouvrir le port série + + + + -Is hardware connected to USB? + - le périphérique est-il bien connecté sur un port USB ? + + + + -Is correct port chosen? + - le port choisi est-il correct ? + + + + -Does current user have sufficient permissions? + - l'utilisateur a-t-il les droits d'utilisation suffisants ? + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + Emis : 0x%02X (CTRL-X) pour verifier la presence de Grbl + + + + Sending to port failed + L'émission vers le port a échouée + + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + Port not available yet + Le port n'est plus disponible + + + + Buffer size too small + Le tampon est trop petit + + + + SENDING[%d]: 0x%02X (CTRL-X) + + EMIS[%d]: 0x%02X (CTRL-X)\n + + + + SENDING[%d]: %s + + EMIS[%d]: %s\n + + + + WAITFOROK FAILED + + Echec lors de l'attente de Ok + + + + Wait for ok failed + L'attente d'un bon déroulement a échouée + + + + + Error reading data from COM port + + Erreur de lecture des données sur le port série + + + + Unexpected: list is empty (o)! + Liste attendue vide (o) + + + + + GOT[%d]:%s for %s + + Obtenu [%d]:%s pour %s\n + + + + Error? + Erreur non répertoriée + + + + Unexpected: list is empty (e)! + Liste attendue vide (e) + + + + + + GOT:%s + + Obtenu : %s\n + + + + Wait interrupted by user + Attente d'interuption par l'utilisateur + + + + Expecting Grbl version string. Unable to parse response. + Attente de la version Grbl, impossible d'analyser la réponse + + + + No data from COM port after connect. Expecting Grbl version string. + Aucune données depuis le port série après la connexion, en attente de la version Grbl + + + + Wait interrupted by user (startup) + Attente d'interuption par l'utilisateur (démarrage) + + + XYUV-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XYUV : [%1]=>[%2] + + + ([a-zA-Z]+),MPos: + ([a-zA-Z]+),PosM : + + + ([a-zA-Z]+), MPos: + ([a-zA-Z]+) ,PosM : + + + MPos: + PosM : + + + WPos: + PosT : + + + Decoded: State:%s MPos: %f,%f,%f WPos: %f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f WPos: %f,%f,%f + + + + Decoded: State:%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + Error decoding position data! + + Erreur de décodage des données de position\n + + + GOT[%d]: '%s' for '%s' (aggressive) + + Emis :[%d]: '%s' pour '%s' (offensif) + + + GOT: '%s' (aggressive) + + EMIS : '%s' (offensif) + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + L'axe supplémentaire existe matériellement. Veuillez corriger les options en cochant 4 ème axe. + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + L'axe supplémentaire n'existe pas matériellement. Veuillez corriger les options en décochant 4 ème axe. + + + + Decoded: State:%s + Decodage : Etat :%s + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + GOT-TE:%s + + Obtenu evenement temporel :%s\n + + + + Sending file '%1' + Emission du fichier '%1' + + + + Gave up waiting for OK + + Fin d'attente Ok\n + + + + Code sent successfully with %1 error(s): + Code émis correctement avec %1 erreur(s) + + + + Code sent successfully with no errors. + Code émis correctement sans erreur + + + + Filtered %1 commands: + Commande filtrée %1 + + + + Process interrupted. + Processus interrompu + + + + Removed unsupported command '%1' part of '%2' + Suppression de la commande '%1' portion de '%2 ( non supportée) + + + + Removed unsupported G command '%1' + Suppression de la commande G '%1' non supportée + + + + Removed unsupported M command '%1' + Suppression de la commande M '%1' non supportée + + + + Removed unsupported command '%1' + Suppression de la commande '%1' non supportée + + + + Unable to remove enough decimal places for command (will be truncated): %s + Impossible de supprimer assez de decimales pour la commande (sera tronquee) %s + + + + Error, insufficent reduction '%1' + Erreur : réduction insuffisante '%1' + + + + Precision reduced '%1' + Précision réduite '%1' + + + + Z-Rate Limit: [%1]=>[%2] + Limite de vitesse Z [%1]=>[%2] + + + + Z-Rate Limit: [%1]=>[%2,%3] + Limite de vitesse Z : [%1]=>[%2,%3] + + + + XY-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XY : [%1]=>[%2] + + + + Bad command: %1 + Commande erronee : %1 + + + + Options specify use mm but Grbl parser set for inches. Fixing. + Vous utiliser des 'mm' alors que l'analyse indique des 'pouces'. Corriger dans la configuration + + + + Options specify use inches but Grbl parser set for mm. Fixing. + Vous utiliser les 'pouces' alors que l'analyse indique des 'mm'. Corriger dans la configuration + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + Vous utiliser les mm alors que Grbl donne des pouces. Corriger dans la configuration + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + Vous utiliser les 'pouce's alors que Grbl donne des 'mm'. Corriger dans la configuration + + + + + (mm) + (mm) + + + + + (in) + (pouce) + + + + GrblDialog + + + Grbl Settings + Configuration GRBL + + + + Apply + Appliquer + + + + Close + Fermer + + + + Value + Valeur + + + + Item + Elément + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + Activation de 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Use of non activated appender '%1' + Utilisation de 'Appender' '%1' non activé + + + + Use of closed appender '%1' + Utilisation de 'Appender' '%1' fermé + + + + Use of appender '%1' that requires layout and has no layout set + Utiliser 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + Utiliation de 'Appender' '%1' sans un modèle valide initialisé + + + + The pattern '%1' does not specify a frequency for appender '%2' + Le modème '%1' ne spécifie aucune fréquence pour 4Appender' '%2' + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + La conversion de type '%1' de la propriété '%2' de l'objet de classe '%3' est impossible. + + + + Unable to set property value on object + Impossible d'inialiser la valeur de la propriété de l'objet. + + + + Invalid null object pointer + Pointeur d'objet 'null' invalide + + + + Invalid empty property name + Nom de propriété invalide (vide) + + + + Property '%1' does not exist in class '%2' + La propriété '%1' n'existe pas dans la classe '%2' + + + + Property '%1' is not writable in class '%2' + La propriété '%1' ne peut être modifiée dans la classe '%2' + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + L'activation de 'Appender' '%1' nécessite un fichier associé + + + + Use of appender '%1' without open file + Utilisation de 'Appender' '%1' sans fichier ouvert + + + + Unable to write to file '%1' for appender '%2' + Impossible d'écrire dans le fichier '%1' pour 'Appender' '%2' + + + + Unable to open file '%1' for appender '%2' + Impossible d'ouvrir le fichier '%1' pour 'Appender' '%2' + + + + Unable to remove file '%1' for appender '%2' + Impossible de supprimer le fichier '%1' pour 'Appender' '%2' + + + + Unable to rename file '%1' to '%2' for appender '%3' + Impossible de renommer le fichier '%1' en '%2' pour 'Appender' '%3' + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + Parenthèse fermante manquante pour la parenthèse ouvrante '%1'. Valeur de substitution '%2' invalide + + + + Invalid option string '%1' for a boolean + Option chaîne '%1' invalide pour un booléen + + + + Invalid option string '%1' for a file size + Option chaîne '%1' invalide pour la taille d'un fichier + + + + Invalid option string '%1' for an integer + Option chaîne '%1' invalide pour un entier + + + + Invalid option string '%1' for a level + Option chaîne '%1' invalide pour un niveau + + + + Invalid option string '%1' for a target + Option chaîne '%1' invalide pour une cible + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + On trouve un caractère'%1', alors qu'un chiffre est attendu. + + + + Option '%1' cannot be converted into an integer + L'option '%1' ne peut-être convertie vers un entier + + + + Option %1 isn't a positive integer + L'option '%1' n'est pas un entier positif + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + Impossible d'ouvrir le fichier de propriétés '%1' + + + + Unable to read property file '%1' + Impossible de lire le fichier de propriétés '%1' + + + + Missing appender definition for appender named '%1' + La définition de 'appender' est manquente pour 'Appender' nommé '%1' + + + + Unable to create appender of class '%1' named '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Unable to create layout of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + Unable to create appender of class '%1' namd '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Missing layout definition for appender '%1' + La définition de la structure est manquante pour 'Appender' '%1' + + + Unable to create layoput of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + Activation de 'Appender' '%1' lequel nécessite un éditeur non configuré ! + + + + Use of appender '%1' without a writer set + Utiliser 'Appender' '%1' sans éditeur configuré + + + + MainWindow + + + Grbl Controller + Contrôleur Grbl + + + + X + X + + + + Y + Y + + + + Z + Z + + + + Send File + Envoi d'un fichier + + + + Begin + Démarrer + + + + Stop + Arrêter + + + + Choose file + Choisir un fichier + + + + Runtime: + Exécution + + + Manual GCode + Commande directe en GCode + + + + Command + Commande + + + + + Open + Ouvrir + + + + C + C + + + GRBL +settings + Configuratiion +GRBL + + + + Port name + Nom du port + + + + Reset Control + Commande RAZ + + + + Soft Reset Grbl + RAZ logiciel de Grbl + + + + Unlock Grbl + Débloquer Grbl + + + + Machine Coordinates + Coordonnées machine + + + + Work Coordinates + Coordonnées de travail + + + + Last State: + Dernier état + + + + Zero Position + Vers position zéro + + + + Go Home + Aller position repos + + + + Axis Control + Commandes d'axes + + + + + Z Jog + pilote Z + + + + Step Size + Valeur du pas + + + + Absolute coordinates after adjust + Coordonnées absolues après ajustement + + + + Spindle On + Départ broche + + + + + + 0 + + + + + + C Jog + pilote C + + + + Visualizer + Visualisateur + + + + Baud Rate + Vitesse du port + + + + %v + + + + + File progress + Avancement + + + + Queued Commands + Ordres en attente + + + + Lines + Lignes + + + + Advanced + Avancé + + + + GRBL Settings + Configuratiion +GRBL + + + + Refresh Pos + Actualiser position + + + + Firmware : + Micrologiciel : + + + + + none + aucun + + + + &Help + &Aide + + + + &Tools + &Outils + + + + &File + &Fichiers + + + + &About + &A propos + + + + &Options + &Options + + + + E&xit + &Quitter + + + + Close / Reset + Fermer / Raz + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + Vous semblez avoir la dernière version du contrôleur Grbl. Soyez conscient que depuis la version 3.4 le comportement par défaut de l'envoi de commandes à Grbl a été modifié pour les envoyer aussi vite que possible (mode de précharge agressif). + +Vos paramètres ont été modifiés pour permettre ce mode. Pourquoi? Parce qu'il permet une utilisation la plus optimale de Grbl et réduit considérablement le temps de terminer un travail typique. Qu'est-ce que cela signifie pour vous ? Maintenant les commandes d'arc vont être plus continues et plus rapides qu'auparavant, ce qui peut amener votre broche à travailler un peu plus vite, s'il vous plaît donc faire quelques tests en premier. Sinon, passez à la boîte de dialogue Options et désactiver manuellement la précharge agressive + + + Wish to "zero position" before beginning? + Voulez-vous allez en postion zéro avant de démarrer ? + + + + User clicked Port Open/Close + L'utilisateur a clique Ouverture/Fermeture du port + + + + Resetting port to restart controller + L'initialisation du port initialise le contrôleur + + + + Do you want to zero the displayed position before proceeding? + Voulez-vous afficher la postion zéro avant de démarrer ? + + + %s has started + Lancement de %s + + + %s has stopped + Fin de %s + + + + Open File + Charger un fichier + + + + NC (*.nc);;All Files (*.*) + NC (*.nc);;Tous fichiers (*.*) + + + + A Jog + pilote A + + + + B Jog + pilote B + + + + U Jog + pilote U + + + + V Jog + pilote V + + + + W Jog + pilote W + + + + Spindle On. + Marche de la broche + + + + Spindle Off. + Arrêt de la broche + + + Usr chg: pos=%d new=%d + + Changement de position : %d -> =%d + + + Usr chg: pos=%.1f new=%.1f + + Changement de position : %.1f -> =%.1f + + + Usr chg no slider: %d + + Utilisation du coulisseau : %d + + + Usr chg no slider: %.1f + + Utilisation du coulisseau : %.1f + + + Pressed and stopped + + Actionne et stoppe + + + Pressed not stopped + + Actionne sans stop + + + Released + + Relache + + + + Options + + + Options + Options + + + + Axis + Axes + + + + Invert Axis + Inverser les axes + + + + Z Axis + Axe Z + + + + Y Axis + Axe Y + + + + X Axis + Axe X + + + C Axis + Axe C + + + + Seconds to Wait for Response + Secondes d'attente lors d'une réponse + + + + Z-Jog Rate (inches or mm/min) + Vitesse manuelle Z (pouces ou mmm/min) + + + Main + Général + + + + Use millimeters when sending manual commands (v0.8c+ only) + Emission des commandes manuelles en millimètre (v0.8c+ seulement) + + + + Filtering + Filtre + + + + Z Rate Limiting + Limitation de vitesse + + + + Limit Z Rate + Vitesse max Z + + + + Z-Rate Limit (inches or mm/min) + Vitesse limite Z (pouces ou mmm/min) + + + + XY Rate (inches or mm/min) + Vitesse XY (pouces ou mmm/min) + + + + Use aggressive preload strategy for Grbl + Utiliser une stratégie offensive de pré-chargement pour Grbl + + + + General + Général + + + + Wait for each jog/manual command to complete (future feature) + Attendre à chaque commande manuelle pour terminer (option future) + + + + Write debugging log to home folder (requires restart) + Mise au point sauvée dans le répertoire d'accueil (+ redémarrage) + + + + Fourth Axis + 4 ème axe + + + + Selecting the Fourth axis + Choix du quatrième axe + + + + A + A + + + + B + B + + + + C + C + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + Valider le mode 4 axes + + + + Display + Affichage + + + + Enable position request and report + Demander la position puis l'afficher + + + + Position Request + Demande de position + + + + Always Request (most reliable/slightly slower jogging) + permanente (plus fiable, mais les commandes manuelles sont ralenties) + + + + Always Request but without Idle Check (fast jog/manual operations) + permanente mais sans controler l'inactivité (commandes manuelles rapides) + + + + Not during manual control (no position update during jog/manual) + sauf les commandes manuelles où l'actualisation de la position est inactive. + + + Always Request + Demande permanente + + + Not during manual control + Exclure des commandes manuelles + + + + Request frequency (seconds) + Période des demandes (secondes) + + + + Command Filtering + Filtrage des commandes + + + + Filter file commands before sending + Filtrage des commandes du fichier GCode avant l'émission + + + + Selectively reduce precision for excessively long lines + Réduire sélectivement la précision, lors de longues lignes de code + + + + Character send delay ms + Délai d'émission des caractères en mS + + + + Grbl Line Buffer Size + Taille du tampon d'entrée de Grbl + + + + QObject + + + Unexpected: Told to send %d bytes + + Inattendu : impossible d'envoyer%d octets + + + Unable to write bytes to port probably due to outgoing queue full. Write data lost! + Impossible d'ecrire sur le port, probablement la file d'attente de sortie est pleine.Perte de donnees en ecriture ! + + + Error writing to port. Write data lost! + Erreu d'ecriture sur le port. Les donnees a ecrire sont perdues + + + + mm + mm + + + + inches + pouces + + + + (Width-X: + (Larg-X: + + + + Height-Y: + Haut-Y: + + + Unexpected type %c + Type attendu %c + + + + Initialising Log4Qt %1 + Initialisation de LOg4Qt %1 + + + + QextSerialPort + + + No Error has occurred + Aucune erreur + + + + Invalid file descriptor (port was not opened correctly) + Descripteur de périphérique invalide (port mal ouvert) + + + + Unable to allocate memory tables (POSIX) + Impossible d'allouer les tables en mémoire (POSIX) + + + + Caught a non-blocked signal (POSIX) + Capture d'un signal non-bloqué (POSIX) + + + + Operation timed out (POSIX) + Dépassement temporel (POSIX) + + + + The file opened by the port is not a valid device + Le fichier ouvert pour le port n'est pas un périphérique valide + + + + The port detected a break condition + Le port a détecté une condition d'arrêt + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + Le port a détecté une erreur de trame (probablement due à une vitesse erronée) + + + + There was an I/O error while communicating with the port + Erreur d'entrée/sortie lors d'une communication sur le port + + + + Character buffer overrun + Dépassementt du tampon de caractères + + + + Receive buffer overflow + Débordement du tampon de réception + + + + The port detected a parity error in the received data + Le port a détecté une erreur de parité lors de la réception de données + + + + Transmit buffer overflow + Débordement du tampon d'émission + + + + General read operation failure + Echec d'une opération de lecture + + + + General write operation failure + Echec d'une opération d'écriture + + + + The %1 file doesn't exists + Le fichier %1 n'existe pas + + + + Permission denied + Non autorisé + + + + Device is already locked + Périphérique déjà bloqué + + + + Unknown error: %1 + Erreur non répertoriée : %1 + + + diff --git a/GC-3.6.1-T2/src/trlocale/GrblController_xx.qm b/GC-3.6.1-T2/src/trlocale/GrblController_xx.qm new file mode 100644 index 0000000..be651ee --- /dev/null +++ b/GC-3.6.1-T2/src/trlocale/GrblController_xx.qm @@ -0,0 +1 @@ +<¸dÊÍ!¿`¡½Ý \ No newline at end of file diff --git a/GC-3.6.1-T2/src/trlocale/GrblController_xx.ts b/GC-3.6.1-T2/src/trlocale/GrblController_xx.ts new file mode 100644 index 0000000..2d849f4 --- /dev/null +++ b/GC-3.6.1-T2/src/trlocale/GrblController_xx.ts @@ -0,0 +1,1162 @@ + + + + + About + + + About... + + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + + + Grbl Controller + + + + + GCode + + + Can't open COM port + + + + + -Is hardware connected to USB? + + + + + -Is correct port chosen? + + + + + -Does current user have sufficient permissions? + + + + + Sending to port failed + + + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + + + + + Port not available yet + + + + + Buffer size too small + + + + + SENDING[%d]: 0x%02X (CTRL-X) + + + + + + SENDING[%d]: %s + + + + + + WAITFOROK FAILED + + + + + + Wait for ok failed + + + + + + Error reading data from COM port + + + + + + Unexpected: list is empty (o)! + + + + + Error? + + + + + Unexpected: list is empty (e)! + + + + + + GOT[%d]:%s for %s + + + + + + + + GOT:%s + + + + + + Wait interrupted by user + + + + + Expecting Grbl version string. Unable to parse response. + + + + + No data from COM port after connect. Expecting Grbl version string. + + + + + Wait interrupted by user (startup) + + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + + + + + Decoded: State:%s + + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + + GOT-TE:%s + + + + + + Sending file '%1' + + + + + Gave up waiting for OK + + + + + + Code sent successfully with %1 error(s): + + + + + Code sent successfully with no errors. + + + + + Filtered %1 commands: + + + + + Process interrupted. + + + + + Removed unsupported command '%1' part of '%2' + + + + + Removed unsupported G command '%1' + + + + + Removed unsupported M command '%1' + + + + + Removed unsupported command '%1' + + + + + Unable to remove enough decimal places for command (will be truncated): %s + + + + + Error, insufficent reduction '%1' + + + + + Precision reduced '%1' + + + + + Z-Rate Limit: [%1]=>[%2] + + + + + Z-Rate Limit: [%1]=>[%2,%3] + + + + + XY-Rate Limit FIX: [%1]=>[%2] + + + + + Bad command: %1 + + + + + Options specify use mm but Grbl parser set for inches. Fixing. + + + + + Options specify use inches but Grbl parser set for mm. Fixing. + + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + + + + + + (mm) + + + + + + (in) + + + + + GrblDialog + + + Grbl Settings + + + + + Apply + + + + + Close + + + + + Value + + + + + Item + + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + + + + + Use of non activated appender '%1' + + + + + Use of closed appender '%1' + + + + + Use of appender '%1' that requires layout and has no layout set + + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + + + + + The pattern '%1' does not specify a frequency for appender '%2' + + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + + + + + Unable to set property value on object + + + + + Invalid null object pointer + + + + + Invalid empty property name + + + + + Property '%1' does not exist in class '%2' + + + + + Property '%1' is not writable in class '%2' + + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + + + + + Use of appender '%1' without open file + + + + + Unable to write to file '%1' for appender '%2' + + + + + Unable to open file '%1' for appender '%2' + + + + + Unable to remove file '%1' for appender '%2' + + + + + Unable to rename file '%1' to '%2' for appender '%3' + + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + + + + + Invalid option string '%1' for a boolean + + + + + Invalid option string '%1' for a file size + + + + + Invalid option string '%1' for an integer + + + + + Invalid option string '%1' for a level + + + + + Invalid option string '%1' for a target + + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + + + + + Option '%1' cannot be converted into an integer + + + + + Option %1 isn't a positive integer + + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + + + + + Unable to read property file '%1' + + + + + Missing appender definition for appender named '%1' + + + + + Unable to create appender of class '%1' named '%2' + + + + + Unable to create layout of class '%1' requested by appender '%2' + + + + + Missing layout definition for appender '%1' + + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + + + + + Use of appender '%1' without a writer set + + + + + MainWindow + + + Grbl Controller + + + + + X + + + + + Y + + + + + Z + + + + + C + + + + + Send File + + + + + Begin + + + + + Stop + + + + + Choose file + + + + + Runtime: + + + + + + Open + + + + + Port name + + + + + Reset Control + + + + + Soft Reset Grbl + + + + + Unlock Grbl + + + + + Machine Coordinates + + + + + Work Coordinates + + + + + Last State: + + + + + Zero Position + + + + + Go Home + + + + + Axis Control + + + + + + Z Jog + + + + + Step Size + + + + + Absolute coordinates after adjust + + + + + Spindle On + + + + + + + 0 + + + + + + C Jog + + + + + Visualizer + + + + + Baud Rate + + + + + %v + + + + + File progress + + + + + Queued Commands + + + + + Lines + + + + + Command + + + + + Advanced + + + + + GRBL Settings + + + + + Refresh Pos + + + + + Firmware : + + + + + + none + + + + + &Help + + + + + &Tools + + + + + &File + + + + + &About + + + + + &Options + + + + + E&xit + + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + + + + + User clicked Port Open/Close + + + + + Do you want to zero the displayed position before proceeding? + + + + + Close / Reset + + + + + Resetting port to restart controller + + + + + Open File + + + + + NC (*.nc);;All Files (*.*) + + + + + A Jog + + + + + B Jog + + + + + U Jog + + + + + V Jog + + + + + W Jog + + + + + Spindle On. + + + + + Spindle Off. + + + + + Options + + + Options + + + + + Axis + + + + + Invert Axis + + + + + Z Axis + + + + + Y Axis + + + + + X Axis + + + + + Seconds to Wait for Response + + + + + Z-Jog Rate (inches or mm/min) + + + + + General + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + Wait for each jog/manual command to complete (future feature) + + + + + Filtering + + + + + Z Rate Limiting + + + + + Limit Z Rate + + + + + Z-Rate Limit (inches or mm/min) + + + + + XY Rate (inches or mm/min) + + + + + Use aggressive preload strategy for Grbl + + + + + Write debugging log to home folder (requires restart) + + + + + Fourth Axis + + + + + Selecting the Fourth axis + + + + + A + + + + + B + + + + + C + + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + + + + + Display + + + + + Enable position request and report + + + + + Position Request + + + + + Always Request (most reliable/slightly slower jogging) + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + Not during manual control (no position update during jog/manual) + + + + + Request frequency (seconds) + + + + + Command Filtering + + + + + Filter file commands before sending + + + + + Selectively reduce precision for excessively long lines + + + + + Character send delay ms + + + + + Grbl Line Buffer Size + + + + + QObject + + + mm + + + + + inches + + + + + (Width-X: + + + + + Height-Y: + + + + + Unexpected: Told to send %d bytes + + + + + + Initialising Log4Qt %1 + + + + + QextSerialPort + + + No Error has occurred + + + + + Invalid file descriptor (port was not opened correctly) + + + + + Unable to allocate memory tables (POSIX) + + + + + Caught a non-blocked signal (POSIX) + + + + + Operation timed out (POSIX) + + + + + The file opened by the port is not a valid device + + + + + The port detected a break condition + + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + + + + + There was an I/O error while communicating with the port + + + + + Character buffer overrun + + + + + Receive buffer overflow + + + + + The port detected a parity error in the received data + + + + + Transmit buffer overflow + + + + + General read operation failure + + + + + General write operation failure + + + + + The %1 file doesn't exists + + + + + Permission denied + + + + + Device is already locked + + + + + Unknown error: %1 + + + + diff --git a/GC-3.6.1-T2/src/version.h b/GC-3.6.1-T2/src/version.h new file mode 100644 index 0000000..4e9ce3e --- /dev/null +++ b/GC-3.6.1-T2/src/version.h @@ -0,0 +1,12 @@ +/**************************************************************** + * version.h + * GrblHoming - zapmaker fork on github + * + * 14 July 2013 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#ifndef VERSION_H +#define VERSION_H +#define GRBL_CONTROLLER_NAME_AND_VERSION "Grbl Controller 3.6.1-T2" +#endif // VERSION_H diff --git a/GC-3.6.1-T2/src/wininfoafter.txt b/GC-3.6.1-T2/src/wininfoafter.txt new file mode 100644 index 0000000..ab64a5b --- /dev/null +++ b/GC-3.6.1-T2/src/wininfoafter.txt @@ -0,0 +1 @@ +Thanks! Please visit www.zapmaker.org to give feedback. \ No newline at end of file diff --git a/GC-3.6.1-T2/src/wininfobefore.txt b/GC-3.6.1-T2/src/wininfobefore.txt new file mode 100644 index 0000000..a28c537 --- /dev/null +++ b/GC-3.6.1-T2/src/wininfobefore.txt @@ -0,0 +1,7 @@ +GrblController 3 - Control your Grbl Arduino and other basic CNC 3-axis systems. + +Installs a EXE file and support DLLs that communicate via COM port to Grbl Arduino using GCode. + +by Zapmaker + +Released under GPL 3.0 \ No newline at end of file diff --git a/GC-3.6.1-T2/src/winlicense.txt b/GC-3.6.1-T2/src/winlicense.txt new file mode 100644 index 0000000..720cb46 --- /dev/null +++ b/GC-3.6.1-T2/src/winlicense.txt @@ -0,0 +1,3 @@ +GrblController + +The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. \ No newline at end of file diff --git a/GC-3.6.1-T2/translate.bat b/GC-3.6.1-T2/translate.bat new file mode 100644 index 0000000..e19fc59 --- /dev/null +++ b/GC-3.6.1-T2/translate.bat @@ -0,0 +1,8 @@ +rem translate.bat +rem by LETARTARE + +cd src + +translate.bat + + diff --git a/GC-3.6.1-T3/README b/GC-3.6.1-T3/README new file mode 100644 index 0000000..b101add --- /dev/null +++ b/GC-3.6.1-T3/README @@ -0,0 +1,59 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Details on how to do this can be found here: +http://zapmaker.org/ + +-------------------------------------------------------------------------------- + +V3.6.1-T3 (LETARTARE proposals June 06, 2014) + +* 3.6.1-T2 + + +1- complete analysis of the Grbl version for 0.8cx versions +2- use 'Check' Grbl mode "$C" +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + +-------------------------------------------------------------------------------- + +V3.6.1-T2 (LETARTARE proposals June 03, 2014) + +* 3.6.1-T1 + + +1- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +2- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +3- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +4- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + +-------------------------------------------------------------------------------- + +V3.6.1-T1 (LETARTARE proposals June 01, 2014) + +- 3.6.1 + +1- Improved to the same card 3 and 4 axis detection +2- Displays the line numbers of the file if no number exists +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, future 0.8c1 (0.8c to 4 axes) + +-------------------------------------------------------------------------------- + + + diff --git a/GC-3.6.1-T3/buildWin.txt b/GC-3.6.1-T3/buildWin.txt new file mode 100644 index 0000000..3737a80 --- /dev/null +++ b/GC-3.6.1-T3/buildWin.txt @@ -0,0 +1,25 @@ +builWin.txt by LETARTARE + + +To build the executable under Windows, you must have +1- a 'Qt' version installed and compiled, the tests were performed with 'Qt-4.7.3'. +2- 'mingw32' installed to use 'mingw32-make.exe', the tests were performed with 'MinGw32-TDM-4.7.1' + +You have to adapt the file 'makeWin.bat' for the paths are correct. + +Example Qt4 : + set PATH_Qt=u:\DONNEES\SVN_COMPILE\qt\4.7.3 + set PATH_MINGW32=o:\DevCpp\MinGw32-TDM + +Example Qt5 : + set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ + set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +Open a DOS console and +1 - makeWin.bat +2 - execute.bat + +if you want the French translation +3 - translate.bat +4 - execute.bat diff --git a/GC-3.6.1-T3/clean.bat b/GC-3.6.1-T3/clean.bat new file mode 100644 index 0000000..6a4585c --- /dev/null +++ b/GC-3.6.1-T3/clean.bat @@ -0,0 +1,26 @@ +rem clean.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +clean.bat + + diff --git a/GC-3.6.1-T3/execute.bat b/GC-3.6.1-T3/execute.bat new file mode 100644 index 0000000..dbd9cf0 --- /dev/null +++ b/GC-3.6.1-T3/execute.bat @@ -0,0 +1,8 @@ +rem execute.bat +rem by LETARTARE + +cd src\release + +GrblController.exe + +cd ..\.. \ No newline at end of file diff --git a/GC-3.6.1-T3/mw.bat b/GC-3.6.1-T3/mw.bat new file mode 100644 index 0000000..bd60e58 --- /dev/null +++ b/GC-3.6.1-T3/mw.bat @@ -0,0 +1,24 @@ +rem makeWin.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +makeWin.bat + + diff --git a/GC-3.6.1-T3/src/.gitignore b/GC-3.6.1-T3/src/.gitignore new file mode 100644 index 0000000..f128f9d --- /dev/null +++ b/GC-3.6.1-T3/src/.gitignore @@ -0,0 +1,19 @@ +GcodeSenderGUIthreads.pro.user +Makefile +Makefile.Debug +Makefile.Release +debug/ +release/ +favs.txt +object_script.GcodeSenderGUI.Debug +object_script.GcodeSenderGUI.Release +settings +ui_*.h +Output/ +android/ +GrblController +*.o +moc_*.cpp +qrc_*.cpp +*.stash +GrblController-local.iss diff --git a/GC-3.6.1-T3/src/GcodeSenderGUIthreads.pro b/GC-3.6.1-T3/src/GcodeSenderGUIthreads.pro new file mode 100644 index 0000000..400cffe --- /dev/null +++ b/GC-3.6.1-T3/src/GcodeSenderGUIthreads.pro @@ -0,0 +1,110 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-02-13 T17:48:40 +# +# (fourth axis modifications and translation added by LETARTARE 2013-08-03) +#------------------------------------------------- + +QT += core gui + +# LETARTARE June 12, 2014 +contains(QT_VERSION, "^5.*") { + QT *= widgets +} + +TARGET = GrblController +TEMPLATE = app + +include(QextSerialPort/qextserialport.pri) +include(log4qt/log4qt.pri) + + +SOURCES += main.cpp\ + mainwindow.cpp \ + rs232.cpp \ + options.cpp \ + grbldialog.cpp \ + about.cpp \ + gcode.cpp \ + timer.cpp \ + atomicintbool.cpp \ + coord3d.cpp \ + renderarea.cpp \ + positem.cpp \ + renderitemlist.cpp \ + lineitem.cpp \ + itemtobase.cpp \ + arcitem.cpp \ + pointitem.cpp \ + controlparams.cpp + +HEADERS += mainwindow.h \ + rs232.h \ + options.h \ + grbldialog.h \ + definitions.h \ + about.h \ + images.rcc \ + gcode.h \ + timer.h \ + atomicintbool.h \ + coord3d.h \ + log4qtdef.h \ + renderarea.h \ + positem.h \ + renderitemlist.h \ + lineitem.h \ + itemtobase.h \ + arcitem.h \ + pointitem.h \ + termiosext.h \ + controlparams.h \ + version.h + +FORMS += mainwindow.ui \ + options.ui \ + grbldialog.ui \ + about.ui + +RESOURCES += GrblController.qrc + +RC_FILE = grbl.rc + +OTHER_FILES += \ + android/AndroidManifest.xml \ + android/res/drawable/icon.png \ + android/res/drawable/logo.png \ + android/res/drawable-hdpi/icon.png \ + android/res/drawable-ldpi/icon.png \ + android/res/drawable-mdpi/icon.png \ + android/res/layout/splash.xml \ + android/res/values/libs.xml \ + android/res/values/strings.xml \ + android/res/values-de/strings.xml \ + android/res/values-el/strings.xml \ + android/res/values-es/strings.xml \ + android/res/values-et/strings.xml \ + android/res/values-fa/strings.xml \ + android/res/values-fr/strings.xml \ + android/res/values-id/strings.xml \ + android/res/values-it/strings.xml \ + android/res/values-ja/strings.xml \ + android/res/values-ms/strings.xml \ + android/res/values-nb/strings.xml \ + android/res/values-nl/strings.xml \ + android/res/values-pl/strings.xml \ + android/res/values-pt-rBR/strings.xml \ + android/res/values-ro/strings.xml \ + android/res/values-rs/strings.xml \ + android/res/values-ru/strings.xml \ + android/res/values-zh-rCN/strings.xml \ + android/res/values-zh-rTW/strings.xml \ + android/src/org/kde/necessitas/ministro/IMinistro.aidl \ + android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \ + android/src/org/kde/necessitas/origo/QtActivity.java \ + android/src/org/kde/necessitas/origo/QtApplication.java \ + android/version.xml + +# Translations + TRANSLATIONS += trlocale/GrblController_xx.ts + TRANSLATIONS += trlocale/GrblController_fr.ts diff --git a/GC-3.6.1-T3/src/GrblController.iss b/GC-3.6.1-T3/src/GrblController.iss new file mode 100644 index 0000000..49dc801 --- /dev/null +++ b/GC-3.6.1-T3/src/GrblController.iss @@ -0,0 +1,58 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "Grbl Controller" +#define MyAppVersion "3.6.1" +#define MyAppPublisher "Zapmaker" +#define MyAppURL "http://zapmaker.org" +#define MyAppExeName "GrblController.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{2DC56D0D-0673-4954-9BDE-3D664965BA97} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=C:\dev\github\GrblHoming\winlicense.txt +InfoBeforeFile=C:\dev\github\GrblHoming\wininfobefore.txt +InfoAfterFile=C:\dev\github\GrblHoming\wininfoafter.txt +OutputBaseFilename=GrblController361Setup +Compression=lzma +SolidCompression=yes + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked +Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 + +[Files] +Source: "C:\dev\github\GrblHoming\release\GrblController.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\dev\github\GrblHoming\trlocale\*.qm"; DestDir: "{app}\trlocale"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\mingwm10.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\mingw\bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/GC-3.6.1-T3/src/GrblController.qrc b/GC-3.6.1-T3/src/GrblController.qrc new file mode 100644 index 0000000..f3b4e5e --- /dev/null +++ b/GC-3.6.1-T3/src/GrblController.qrc @@ -0,0 +1,10 @@ + + + img/down.PNG + img/left.PNG + img/logotiny.PNG + img/right.PNG + img/up.PNG + img/zapmaker-logo-130.png + + diff --git a/GC-3.6.1-T3/src/LICENSE b/GC-3.6.1-T3/src/LICENSE new file mode 100644 index 0000000..9e419e0 --- /dev/null +++ b/GC-3.6.1-T3/src/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/GC-3.6.1-T3/src/Makefile b/GC-3.6.1-T3/src/Makefile new file mode 100644 index 0000000..034c7c9 --- /dev/null +++ b/GC-3.6.1-T3/src/Makefile @@ -0,0 +1,153 @@ +############################################################################# +# Makefile for building: GrblController +# Generated by qmake (2.01a) (Qt 4.7.3) on: lun. 2. juin 07:55:41 2014 +# Project: GcodeSenderGUIthreads.pro +# Template: app +# Command: u:/DONNEES/SVN_COMPILE/qt/4.7.3/bin/qmake.exe -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro +############################################################################# + +first: release +install: release-install +uninstall: release-uninstall +MAKEFILE = Makefile +QMAKE = u:/DONNEES/SVN_COMPILE/qt/4.7.3/bin/qmake.exe +DEL_FILE = rm +CHK_DIR_EXISTS= test -d +MKDIR = mkdir +COPY = cp +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm +SYMLINK = +DEL_DIR = rmdir +MOVE = mv +CHK_DIR_EXISTS= test -d +MKDIR = mkdir +SUBTARGETS = \ + release \ + debug + +release: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_default: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_first: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release first +release-all: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release all +release-clean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release clean +release-distclean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release distclean +release-install: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release install +release-uninstall: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release uninstall +debug: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_default: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_first: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug first +debug-all: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug all +debug-clean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug clean +debug-distclean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug distclean +debug-install: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug install +debug-uninstall: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug uninstall + +Makefile: GcodeSenderGUIthreads.pro u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++/qmake.conf u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/qconfig.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/modules/qt_webkit_version.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_functions.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_config.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/exclusive_builds.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_pre.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_pre.prf \ + QextSerialPort/qextserialport.pri \ + log4qt/log4qt.pri \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/release.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/debug_and_release.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_post.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_post.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/rtti.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/exceptions.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/stl.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/msvc_mp.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/shared.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/warn_on.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/thread.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/moc.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/windows.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/resources.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/uic.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/yacc.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/lex.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/include_source_dir.prf \ + u:/DONNEES/SVN_COMPILE/qt/4.7.3/lib/qtmain.prl + $(QMAKE) -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/qconfig.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/modules/qt_webkit_version.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_functions.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt_config.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/exclusive_builds.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_pre.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_pre.prf: +QextSerialPort/qextserialport.pri: +log4qt/log4qt.pri: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/release.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/debug_and_release.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/default_post.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/default_post.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/rtti.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/exceptions.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/stl.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/msvc_mp.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/shared.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/warn_on.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/qt.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/thread.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/moc.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/win32/windows.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/resources.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/uic.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/yacc.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/lex.prf: +u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/features/include_source_dir.prf: +u:\DONNEES\SVN_COMPILE\qt\4.7.3\lib\qtmain.prl: +qmake: qmake_all FORCE + @$(QMAKE) -spec u:/DONNEES/SVN_COMPILE/qt/4.7.3/mkspecs/win32-g++ -config release -o Makefile GcodeSenderGUIthreads.pro + +qmake_all: FORCE + +make_default: release-make_default debug-make_default FORCE +make_first: release-make_first debug-make_first FORCE +all: release-all debug-all FORCE +clean: release-clean debug-clean FORCE +distclean: release-distclean debug-distclean FORCE + -$(DEL_FILE) Makefile + +check: first + +release-mocclean: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocclean +debug-mocclean: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocclean +mocclean: release-mocclean debug-mocclean + +release-mocables: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocables +debug-mocables: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocables +mocables: release-mocables debug-mocables +FORCE: + +$(MAKEFILE).Release: Makefile +$(MAKEFILE).Debug: Makefile diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.cpp new file mode 100644 index 0000000..ec1491a --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" + +#include +#include +#include + +QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator) + :q_ptr(enumrator) +{ + platformSpecificInit(); +} + +QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate() +{ + platformSpecificDestruct(); +} + +/*! + \class QextPortInfo + + \brief The QextPortInfo class containing port information. + + Structure containing port information. + + \code + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID + \endcode + */ + +/*! \class QextSerialEnumerator + + \brief The QextSerialEnumerator class provides list of ports available in the system. + + \section1 Usage + To poll the system for a list of connected devices, simply use getPorts(). Each + QextPortInfo structure will populated with information about the corresponding device. + + \bold Example + \code + QList ports = QextSerialEnumerator::getPorts(); + foreach (QextPortInfo port, ports) { + // inspect port... + } + \endcode + + To enable event-driven notification of device connection events, first call + setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() + signals. Event-driven behavior is currently available only on Windows and OS X. + + \bold Example + \code + QextSerialEnumerator *enumerator = new QextSerialEnumerator(); + connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), + myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); + connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), + myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); + \endcode + + \section1 Credits + Windows implementation is based on Zach Gorman's work from + \l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp). + + OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html + + \bold author Michal Policht, Liam Staskawicz +*/ + +/*! + \fn void QextSerialEnumerator::deviceDiscovered(const QextPortInfo &info) + A new device has been connected to the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that has been discovered. +*/ + +/*! + \fn void QextSerialEnumerator::deviceRemoved(const QextPortInfo &info); + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that was disconnected. +*/ + +/*! + Constructs a QextSerialEnumerator object with the given \a parent. +*/ +QextSerialEnumerator::QextSerialEnumerator(QObject *parent) + :QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this)) +{ + if (!QMetaType::isRegistered(QMetaType::type("QextPortInfo"))) + qRegisterMetaType("QextPortInfo"); +} + +/*! + Destructs the QextSerialEnumerator object. +*/ +QextSerialEnumerator::~QextSerialEnumerator() +{ + delete d_ptr; +} + +/*! + Get list of ports. + + return list of ports currently available in the system. +*/ +QList QextSerialEnumerator::getPorts() +{ + return QextSerialEnumeratorPrivate::getPorts_sys(); +} + +/*! + Enable event-driven notifications of board discovery/removal. +*/ +void QextSerialEnumerator::setUpNotifications() +{ + Q_D(QextSerialEnumerator); + if (!d->setUpNotifications_sys(true)) + QESP_WARNING("Setup Notification Failed..."); +} + +#include "moc_qextserialenumerator.cpp" diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.h b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.h new file mode 100644 index 0000000..99f515d --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALENUMERATOR_H_ +#define _QEXTSERIALENUMERATOR_H_ + +#include +#include +#include "qextserialport_global.h" + +struct QextPortInfo { + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID +}; + +class QextSerialEnumeratorPrivate; +class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialEnumerator) +public: + QextSerialEnumerator(QObject *parent=0); + ~QextSerialEnumerator(); + + static QList getPorts(); + void setUpNotifications(); + +Q_SIGNALS: + void deviceDiscovered(const QextPortInfo &info); + void deviceRemoved(const QextPortInfo &info); + +private: + Q_DISABLE_COPY(QextSerialEnumerator) +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent()) +#endif + QextSerialEnumeratorPrivate *d_ptr; +}; + +#endif /*_QEXTSERIALENUMERATOR_H_*/ diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_linux.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_linux.cpp new file mode 100644 index 0000000..a57dfe6 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_linux.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifndef QESP_NO_UDEV + monitor = NULL; + notifierFd = -1; + notifier = NULL; + + udev = udev_new(); + if (!udev) + qCritical() << "Unable to initialize udev notifications"; +#endif +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifndef QESP_NO_UDEV + if (notifier) { + notifier->setEnabled(false); + delete notifier; + } + + if (monitor) + udev_monitor_unref(monitor); + + if (udev) + udev_unref(udev); +#endif +} + +#ifndef QESP_NO_UDEV +static QextPortInfo portInfoFromDevice(struct udev_device *dev) +{ + QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID")); + QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID")); + + QextPortInfo pi; + pi.vendorID = vendor.toInt(0, 16); + pi.productID = product.toInt(0, 16); + pi.portName = QString::fromLatin1(udev_device_get_devnode(dev)); + pi.physName = pi.portName; + + return pi; +} +#endif + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; +#ifndef QESP_NO_UDEV + struct udev *ud = udev_new(); + if (!ud) { + qCritical() << "Unable to enumerate ports because udev is not initialized."; + return infoList; + } + + struct udev_enumerate *enumerate = udev_enumerate_new(ud); + udev_enumerate_add_match_subsystem(enumerate, "tty"); + udev_enumerate_scan_devices(enumerate); + struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); + struct udev_list_entry *entry; + udev_list_entry_foreach(entry, list) { + const char *path; + struct udev_device *dev; + + // Have to grab the actual udev device here... + path = udev_list_entry_get_name(entry); + dev = udev_device_new_from_syspath(ud, path); + + infoList.append(portInfoFromDevice(dev)); + + // Done with this device + udev_device_unref(dev); + } + // Done with the list and this udev + udev_enumerate_unref(enumerate); + udev_unref(ud); +#else + QStringList portNamePrefixes, portNameList; + portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first + + QDir dir(QLatin1String("/dev")); + portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + // remove the values which are not serial ports for e.g. /dev/ttysa + for (int i = 0; i < portNameList.size(); i++) { + bool ok; + QString current = portNameList.at(i); + // remove the ttyS part, and check, if the other part is a number + current.remove(0,4).toInt(&ok, 10); + if (!ok) { + portNameList.removeAt(i); + i--; + } + } + + // get the non standard serial ports names + // (USB-serial, bluetooth-serial, 18F PICs, and so on) + // if you know an other name prefix for serial ports please let us know + portNamePrefixes.clear(); + portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); + portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + foreach (QString str , portNameList) { + QextPortInfo inf; + inf.physName = QLatin1String("/dev/")+str; + inf.portName = str; + + if (str.contains(QLatin1String("ttyS"))) { + inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); + } + else if (str.contains(QLatin1String("ttyUSB"))) { + inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); + } + else if (str.contains(QLatin1String("rfcomm"))) { + inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); + } + inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? + infoList.append(inf); + } +#endif + + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup); +#ifndef QESP_NO_UDEV + Q_Q(QextSerialEnumerator); + if (!udev) { + qCritical() << "Unable to initialize notifications because udev is not initialized."; + return false; + } + + // Emit signals immediately for devices already connected (Windows version seems to behave + // this way) + foreach (QextPortInfo i, getPorts_sys()) + Q_EMIT q->deviceDiscovered(i); + + // Look for tty devices from udev. + monitor = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL); + udev_monitor_enable_receiving(monitor); + notifierFd = udev_monitor_get_fd(monitor); + notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read); + q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent())); + notifier->setEnabled(true); + + return true; +#else + return false; +#endif +} + +#ifndef QESP_NO_UDEV +void QextSerialEnumeratorPrivate::_q_deviceEvent() +{ + Q_Q(QextSerialEnumerator); + struct udev_device *dev = udev_monitor_receive_device(monitor); + if (dev) { + QextPortInfo pi = portInfoFromDevice(dev); + + QLatin1String action(udev_device_get_action(dev)); + udev_device_unref(dev); + + if (action == QLatin1String("add")) + Q_EMIT q->deviceDiscovered(pi); + else if (action == QLatin1String("remove")) + Q_EMIT q->deviceRemoved(pi); + } +} +#endif diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_osx.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_osx.cpp new file mode 100644 index 0000000..2dd0357 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_osx.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ + IONotificationPortDestroy(notificationPortRef); +} + +// static +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + io_iterator_t serialPortIterator = 0; + kern_return_t kernResult = KERN_FAILURE; + CFMutableDictionaryRef matchingDictionary; + + // first try to get any serialbsd devices, then try any USBCDC devices + if (!(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue))) { + QESP_WARNING("IOServiceMatching returned a NULL dictionary."); + return infoList; + } + CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + // then create the iterator with all the matching devices + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + serialPortIterator = 0; + + if (!(matchingDictionary = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("IOServiceNameMatching returned a NULL dictionary."); + return infoList; + } + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + + return infoList; +} + +void QextSerialEnumeratorPrivate::iterateServicesOSX(io_object_t service, QList &infoList) +{ + // Iterate through all modems found. + io_object_t usbService; + while ((usbService = IOIteratorNext(service))) { + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + getServiceDetailsOSX(usbService, &info); + infoList.append(info); + } +} + +bool QextSerialEnumeratorPrivate::getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo) +{ + bool retval = true; + CFTypeRef bsdPathAsCFString = NULL; + CFTypeRef productNameAsCFString = NULL; + CFTypeRef vendorIdAsCFNumber = NULL; + CFTypeRef productIdAsCFNumber = NULL; + // check the name of the modem's callout device + bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, 0); + + // wander up the hierarchy until we find the level that can give us the + // vendor/product IDs and the product name, if available + io_registry_entry_t parent; + kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); + while (kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber) { + if (!productNameAsCFString) + productNameAsCFString = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR("Product Name"), + kCFAllocatorDefault, 0); + vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBVendorID), + kCFAllocatorDefault, 0); + productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBProductID), + kCFAllocatorDefault, 0); + io_registry_entry_t oldparent = parent; + kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent); + IOObjectRelease(oldparent); + } + + io_string_t ioPathName; + IORegistryEntryGetPath(service, kIOServicePlane, ioPathName); + portInfo->physName = ioPathName; + + if (bsdPathAsCFString) { + char path[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)bsdPathAsCFString, path, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->portName = path; + CFRelease(bsdPathAsCFString); + } + + if (productNameAsCFString) { + char productName[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)productNameAsCFString, productName, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->friendName = productName; + CFRelease(productNameAsCFString); + } + + if (vendorIdAsCFNumber) { + SInt32 vID; + if (CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID)) + portInfo->vendorID = vID; + CFRelease(vendorIdAsCFNumber); + } + + if (productIdAsCFNumber) { + SInt32 pID; + if (CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID)) + portInfo->productID = pID; + CFRelease(productIdAsCFNumber); + } + IOObjectRelease(service); + return retval; +} + +// IOKit callbacks registered via setupNotifications() +void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceDiscoveredOSX(serialService); +} + +void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceTerminatedOSX(serialService); +} + +/* + A device has been discovered via IOKit. + Create a QextPortInfo if possible, and emit the signal indicating that we've found it. +*/ +void QextSerialEnumeratorPrivate::onDeviceDiscoveredOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceDiscovered(info); +} + +/* + Notification via IOKit that a device has been removed. + Create a QextPortInfo if possible, and emit the signal indicating that it's gone. +*/ +void QextSerialEnumeratorPrivate::onDeviceTerminatedOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceRemoved(info); +} + +/* + Create matching dictionaries for the devices we want to get notifications for, + and add them to the current run loop. Invoke the callbacks that will be responding + to these notifications once to arm them, and discover any devices that + are currently connected at the time notifications are setup. +*/ +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool /*setup*/) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFRunLoopSourceRef notificationRunLoopSource; + CFMutableDictionaryRef classesToMatch; + CFMutableDictionaryRef cdcClassesToMatch; + io_iterator_t portIterator; + + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) { + qDebug() << "IOMasterPort returned:" << kernResult; + return false; + } + + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch == NULL) + qDebug("IOServiceMatching returned a NULL dictionary."); + else + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + if (!(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("couldn't create cdc matching dict"); + return false; + } + + // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. + classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); + cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); + + notificationPortRef = IONotificationPortCreate(masterPort); + if (notificationPortRef == NULL) { + qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); + return false; + } + + notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); + if (notificationRunLoopSource == NULL) { + qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); + return false; + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + return true; +} + diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_p.h b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_p.h new file mode 100644 index 0000000..c69e925 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef _QEXTSERIALENUMERATOR_P_H_ +#define _QEXTSERIALENUMERATOR_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialenumerator.h" + +#ifdef Q_OS_WIN +// needed for mingw to pull in appropriate dbt business... +// probably a better way to do this +// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html +# ifdef __MINGW32__ +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef _WIN32_WINDOWS +# define _WIN32_WINDOWS 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +# endif +# include +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC +# include +#endif /*Q_OS_MAC*/ + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) +# include +extern "C" { +# include +} +#endif + +class QextSerialRegistrationWidget; +class QextSerialEnumeratorPrivate +{ + Q_DECLARE_PUBLIC(QextSerialEnumerator) +public: + QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator); + ~QextSerialEnumeratorPrivate(); + void platformSpecificInit(); + void platformSpecificDestruct(); + + static QList getPorts_sys(); + bool setUpNotifications_sys(bool setup); + +#ifdef Q_OS_WIN + LRESULT onDeviceChanged(WPARAM wParam, LPARAM lParam); + bool matchAndDispatchChangedDevice(const QString &deviceID, const GUID &guid, WPARAM wParam); +# ifdef QT_GUI_LIB + QextSerialRegistrationWidget *notificationWidget; +# endif +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC + /*! + * Search for serial ports using IOKit. + * \param infoList list with result. + */ + static void iterateServicesOSX(io_object_t service, QList &infoList); + static bool getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo); + void onDeviceDiscoveredOSX(io_object_t service); + void onDeviceTerminatedOSX(io_object_t service); + friend void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + friend void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + + IONotificationPortRef notificationPortRef; +#endif // Q_OS_MAC + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + QSocketNotifier *notifier; + int notifierFd; + struct udev *udev; + struct udev_monitor *monitor; + + void _q_deviceEvent(); +#endif + +private: + QextSerialEnumerator *q_ptr; +}; + +#endif //_QEXTSERIALENUMERATOR_P_H_ diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_unix.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_unix.cpp new file mode 100644 index 0000000..80a4ad4 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_unix.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +} + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet."); + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup) + QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet"); + return false; +} diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_win.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_win.cpp new file mode 100644 index 0000000..55b71aa --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialenumerator_win.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "qextserialport.h" + +#ifdef QT_GUI_LIB +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +class QextSerialRegistrationWidget : public QWidget +#else +#include +class QextSerialRegistrationWidget : public QWindow +#endif +{ +public: + QextSerialRegistrationWidget(QextSerialEnumeratorPrivate *qese) { + this->qese = qese; + } + ~QextSerialRegistrationWidget() {} + +protected: + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + bool winEvent(MSG *message, long *result) { +#else + bool nativeEvent(const QByteArray & /*eventType*/, void *msg, long *result) { + MSG *message = static_cast(msg); +#endif + if (message->message == WM_DEVICECHANGE) { + qese->onDeviceChanged(message->wParam, message->lParam); + *result = 1; + return true; + } + return false; + } +private: + QextSerialEnumeratorPrivate *qese; +}; + +#endif // QT_GUI_LIB + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifdef QT_GUI_LIB + notificationWidget = 0; +#endif // QT_GUI_LIB +} + +/*! + default +*/ +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifdef QT_GUI_LIB + if (notificationWidget) + delete notificationWidget; +#endif +} + +// see http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426(v=vs.85).aspx +// for list of GUID classes +const GUID deviceClassGuids[] = +{ + // Ports (COM & LPT ports), Class = Ports + {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Modem, Class = Modem + {0x4D36E96D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Bluetooth Devices, Class = Bluetooth + {0xE0CBF06C, 0xCD8B, 0x4647, {0xBB, 0x8A, 0x26, 0x3B, 0x43, 0xF0, 0xF9, 0x74}}, + // Added by Arne Kristian Jansen, for use with com0com virtual ports (See Issue 54) + {0xDF799E12, 0x3C56, 0x421B, {0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78}} +}; + +/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ +#ifdef UNICODE + #define QStringToTCHAR(x) (wchar_t *) x.utf16() + #define PQStringToTCHAR(x) (wchar_t *) x->utf16() + #define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) + #define TCHARToQStringN(x,y) QString::fromUtf16((ushort *)(x),(y)) +#else + #define QStringToTCHAR(x) x.local8Bit().constData() + #define PQStringToTCHAR(x) x->local8Bit().constData() + #define TCHARToQString(x) QString::fromLocal8Bit((char *)(x)) + #define TCHARToQStringN(x,y) QString::fromLocal8Bit((char *)(x),(y)) +#endif /*UNICODE*/ + +/*! + \internal + Get value of specified property from the registry. + \a key handle to an open key. + \a property property name. + + return property value. +*/ +static QString getRegKeyValue(HKEY key, LPCTSTR property) +{ + DWORD size = 0; + DWORD type; + ::RegQueryValueEx(key, property, NULL, NULL, NULL, &size); + BYTE *buff = new BYTE[size]; + QString result; + if (::RegQueryValueEx(key, property, NULL, &type, buff, &size) == ERROR_SUCCESS) + result = TCHARToQString(buff); + ::RegCloseKey(key); + delete [] buff; + return result; +} + +/*! + \internal + Get specific property from registry. + \a devInfo pointer to the device information set that contains the interface + and its underlying device. Returned by SetupDiGetClassDevs() function. + \a devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. + this is returned by SetupDiGetDeviceInterfaceDetail() function. + \a property registry property. One of defined SPDRP_* constants. + + return property string. + */ +static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) +{ + DWORD buffSize = 0; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); + BYTE *buff = new BYTE[buffSize]; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); + QString result = TCHARToQString(buff); + delete [] buff; + return result; +} + +/*! + \internal +*/ +static bool getDeviceDetailsWin(QextPortInfo *portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData + , WPARAM wParam = DBT_DEVICEARRIVAL) +{ + portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME); + if (wParam == DBT_DEVICEARRIVAL) + portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); + portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME); + QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID); + HKEY devKey = ::SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + portInfo->portName = getRegKeyValue(devKey, TEXT("PortName")); + QRegExp idRx(QLatin1String("VID_(\\w+)&PID_(\\w+)")); + if (hardwareIDs.toUpper().contains(idRx)) { + bool dummy; + portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16); + portInfo->productID = idRx.cap(2).toInt(&dummy, 16); + //qDebug() << "got vid:" << vid << "pid:" << pid; + } + return true; +} + +/*! + \internal +*/ +static void enumerateDevicesWin(const GUID &guid, QList *infoList) +{ + HDEVINFO devInfo; + if ((devInfo = ::SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE) { + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for(int i = 0; ::SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + QextPortInfo info; + info.productID = info.vendorID = 0; + getDeviceDetailsWin(&info, devInfo, &devInfoData); + if (!info.portName.startsWith(QLatin1String("LPT"), Qt::CaseInsensitive)) + infoList->append(info); + } + ::SetupDiDestroyDeviceInfoList(devInfo); + } +} + + +static bool lessThan(const QextPortInfo &s1, const QextPortInfo &s2) +{ + if (s1.portName.startsWith(QLatin1String("COM")) + && s2.portName.startsWith(QLatin1String("COM"))) { + return s1.portName.mid(3).toInt() QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList ports; + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; iwinId(), &dbh, flags) == NULL) { + QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError(); + return false; + } + // setting up notifications doesn't tell us about devices already connected + // so get those manually + foreach (QextPortInfo port, getPorts_sys()) + Q_EMIT q->deviceDiscovered(port); + return true; +#endif // QT_GUI_LIB +} + +LRESULT QextSerialEnumeratorPrivate::onDeviceChanged(WPARAM wParam, LPARAM lParam) +{ + if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + // delimiters are different across APIs...change to backslash. ugh. + QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace(QLatin1String("#"), QLatin1String("\\")); + + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; ideviceDiscovered(info); + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + Q_EMIT q->deviceRemoved(info); + break; + } + } + SetupDiDestroyDeviceInfoList(devInfo); + } + return rv; +} diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.cpp new file mode 100644 index 0000000..119bef8 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.cpp @@ -0,0 +1,1011 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include + +/*! + \class PortSettings + + \brief The PortSettings class contain port settings + + Structure to contain port settings. + + \code + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; + \endcode +*/ + +QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q) + :lock(QReadWriteLock::Recursive), q_ptr(q) +{ + lastErr = E_NO_ERROR; + settings.BaudRate = BAUD9600; + settings.Parity = PAR_NONE; + settings.FlowControl = FLOW_OFF; + settings.DataBits = DATA_8; + settings.StopBits = STOP_1; + settings.Timeout_Millisec = 10; + settingsDirtyFlags = DFE_ALL; + + platformSpecificInit(); +} + +QextSerialPortPrivate::~QextSerialPortPrivate() +{ + platformSpecificDestruct(); +} + +void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update) +{ + switch (baudRate) { +#ifdef Q_OS_WIN + //Windows Special + case BAUD14400: + case BAUD56000: + case BAUD128000: + case BAUD256000: + QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<isOpen()) + updatePortSettings(); + break; +#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC)) + default: + QESP_WARNING()<<"QextSerialPort does not support baudRate:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update) +{ + switch(dataBits) { + + case DATA_5: + if (settings.StopBits == STOP_2) { + QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); + } + else { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_6: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_7: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_8: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support Data bits:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update) +{ + switch (stopBits) { + + /*one stop bit*/ + case STOP_1: + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + break; + +#ifdef Q_OS_WIN + /*1.5 stop bits*/ + case STOP_1_5: + QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); + if (settings.DataBits != DATA_5) { + QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; +#endif + + /*two stop bits*/ + case STOP_2: + if (settings.DataBits == DATA_5) { + QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support stop bits: "<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update) +{ + settings.FlowControl = flow; + settingsDirtyFlags |= DFE_Flow; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setTimeout(long millisec, bool update) +{ + settings.Timeout_Millisec = millisec; + settingsDirtyFlags |= DFE_TimeOut; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update) +{ + setBaudRate(settings.BaudRate, false); + setDataBits(settings.DataBits, false); + setStopBits(settings.StopBits, false); + setParity(settings.Parity, false); + setFlowControl(settings.FlowControl, false); + setTimeout(settings.Timeout_Millisec, false); + settingsDirtyFlags = DFE_ALL; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + + +void QextSerialPortPrivate::_q_canRead() +{ + qint64 maxSize = bytesAvailable_sys(); + if (maxSize > 0) { + char *writePtr = readBuffer.reserve(size_t(maxSize)); + qint64 bytesRead = readData_sys(writePtr, maxSize); + if (bytesRead < maxSize) + readBuffer.chop(maxSize - bytesRead); + Q_Q(QextSerialPort); + Q_EMIT q->readyRead(); + } +} + +/*! \class QextSerialPort + + \brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems. + + \section1 Usage + QextSerialPort offers both a polling and event driven API. Event driven + is typically easier to use, since you never have to worry about checking + for new data. + + \bold Example + \code + QextSerialPort *port = new QextSerialPort("COM1"); + connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable())); + port->open(); + + void MyClass::onDataAvailable() + { + QByteArray data = port->readAll(); + processNewData(usbdata); + } + \endcode + + \section1 Compatibility + The user will be notified of errors and possible portability conflicts at run-time + by default. + + For example, if a application has used BAUD1800, when it is runing under unix, you + will get following message. + + \code + QextSerialPort Portability Warning: Windows does not support baudRate:1800 + \endcode + + This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings) + or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project. + + + \bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang +*/ + +/*! + \enum QextSerialPort::QueryMode + + This enum type specifies query mode used in a serial port: + + \value Polling + asynchronously read and write + \value EventDriven + synchronously read and write +*/ + +/*! + \fn void QextSerialPort::dsrChanged(bool status) + This signal is emitted whenever dsr line has changed its state. You may + use this signal to check if device is connected. + + \a status true when DSR signal is on, false otherwise. + */ + + +/*! + \fn QueryMode QextSerialPort::queryMode() const + Get query mode. + */ + +/*! + Default constructor. Note that the name of the device used by a QextSerialPort is dependent on + your OS. Possible naming conventions and their associated OS are: + + \code + + OS Constant Used By Naming Convention + ------------- ------------- ------------------------ + Q_OS_WIN Windows COM1, COM2 + Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2 + Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0 + Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb + Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02 + Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1 + Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01 + Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1 + /dev/ttyS0, /dev/ttyS1 + \endcode + + This constructor assigns the device name to the name of the first port on the specified system. + See the other constructors if you need to open a different port. Default \a mode is EventDriven. + As a subclass of QObject, \a parent can be specified. +*/ + +QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ +#ifdef Q_OS_WIN + setPortName(QLatin1String("COM1")); + +#elif defined(Q_OS_IRIX) + setPortName(QLatin1String("/dev/ttyf1")); + +#elif defined(Q_OS_HPUX) + setPortName(QLatin1String("/dev/tty1p0")); + +#elif defined(Q_OS_SOLARIS) + setPortName(QLatin1String("/dev/ttya")); + +#elif defined(Q_OS_OSF) //formally DIGITAL UNIX + setPortName(QLatin1String("/dev/tty01")); + +#elif defined(Q_OS_FREEBSD) + setPortName(QLatin1String("/dev/ttyd1")); + +#elif defined(Q_OS_OPENBSD) + setPortName(QLatin1String("/dev/tty00")); + +#else + setPortName(QLatin1String("/dev/ttyS0")); +#endif + setQueryMode(mode); +} + +/*! + Constructs a serial port attached to the port specified by name. + \a name is the name of the device, which is windowsystem-specific, + e.g."COM1" or "/dev/ttyS0". \a mode +*/ +QextSerialPort::QextSerialPort(const QString &name, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + setQueryMode(mode); + setPortName(name); +} + +/*! + Constructs a port with default name and specified \a settings. +*/ +QextSerialPort::QextSerialPort(const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Constructs a port with specified \a name , \a mode and \a settings. +*/ +QextSerialPort::QextSerialPort(const QString &name, const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setPortName(name); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Opens a serial port and sets its OpenMode to \a mode. + Note that this function does not specify which device to open. + Returns true if successful; otherwise returns false.This function has no effect + if the port associated with the class is already open. The port is also + configured to the current settings, as stored in the settings structure. +*/ +bool QextSerialPort::open(OpenMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != QIODevice::NotOpen && !isOpen()) + d->open_sys(mode); + + return isOpen(); +} + + +/*! \reimp + Closes a serial port. This function has no effect if the serial port associated with the class + is not currently open. +*/ +void QextSerialPort::close() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) { + // Be a good QIODevice and call QIODevice::close() before really close() + // so the aboutToClose() signal is emitted at the proper time + QIODevice::close(); // mark ourselves as closed + d->close_sys(); + d->readBuffer.clear(); + } +} + +/*! + Flushes all pending I/O to the serial port. This function has no effect if the serial port + associated with the class is not currently open. +*/ +void QextSerialPort::flush() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->flush_sys(); +} + +/*! \reimp + Returns the number of bytes waiting in the port's receive queue. This function will return 0 if + the port is not currently open, or -1 on error. +*/ +qint64 QextSerialPort::bytesAvailable() const +{ + QWriteLocker locker(&d_func()->lock); + if (isOpen()) { + qint64 bytes = d_func()->bytesAvailable_sys(); + if (bytes != -1) { + return bytes + d_func()->readBuffer.size() + + QIODevice::bytesAvailable(); + } else { + return -1; + } + } + return 0; +} + +/*! \reimp + +*/ +bool QextSerialPort::canReadLine() const +{ + QReadLocker locker(&d_func()->lock); + return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine(); +} + +/*! + * Set desired serial communication handling style. You may choose from polling + * or event driven approach. This function does nothing when port is open; to + * apply changes port must be reopened. + * + * In event driven approach read() and write() functions are acting + * asynchronously. They return immediately and the operation is performed in + * the background, so they doesn't freeze the calling thread. + * To determine when operation is finished, QextSerialPort runs separate thread + * and monitors serial port events. Whenever the event occurs, adequate signal + * is emitted. + * + * When polling is set, read() and write() are acting synchronously. Signals are + * not working in this mode and some functions may not be available. The advantage + * of polling is that it generates less overhead due to lack of signals emissions + * and it doesn't start separate thread to monitor events. + * + * Generally event driven approach is more capable and friendly, although some + * applications may need as low overhead as possible and then polling comes. + * + * \a mode query mode. + */ +void QextSerialPort::setQueryMode(QueryMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != d->queryMode) { + d->queryMode = mode; + } +} + +/*! + Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". +*/ +void QextSerialPort::setPortName(const QString &name) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + d->port = name; +} + +/*! + Returns the name set by setPortName(). +*/ +QString QextSerialPort::portName() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->port; +} + +QextSerialPort::QueryMode QextSerialPort::queryMode() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->queryMode; +} + +/*! + Reads all available data from the device, and returns it as a QByteArray. + This function has no way of reporting errors; returning an empty QByteArray() + can mean either that no data was currently available for reading, or that an error occurred. +*/ +QByteArray QextSerialPort::readAll() +{ + int avail = this->bytesAvailable(); + return (avail > 0) ? this->read(avail) : QByteArray(); +} + +/*! + Returns the baud rate of the serial port. For a list of possible return values see + the definition of the enum BaudRateType. +*/ +BaudRateType QextSerialPort::baudRate() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.BaudRate; +} + +/*! + Returns the number of data bits used by the port. For a list of possible values returned by + this function, see the definition of the enum DataBitsType. +*/ +DataBitsType QextSerialPort::dataBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.DataBits; +} + +/*! + Returns the type of parity used by the port. For a list of possible values returned by + this function, see the definition of the enum ParityType. +*/ +ParityType QextSerialPort::parity() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.Parity; +} + +/*! + Returns the number of stop bits used by the port. For a list of possible return values, see + the definition of the enum StopBitsType. +*/ +StopBitsType QextSerialPort::stopBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.StopBits; +} + +/*! + Returns the type of flow control used by the port. For a list of possible values returned + by this function, see the definition of the enum FlowType. +*/ +FlowType QextSerialPort::flowControl() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.FlowControl; +} + +/*! + \reimp + Returns true if device is sequential, otherwise returns false. Serial port is sequential device + so this function always returns true. Check QIODevice::isSequential() documentation for more + information. +*/ +bool QextSerialPort::isSequential() const +{ + return true; +} + +/*! + Return the error number, or 0 if no error occurred. +*/ +ulong QextSerialPort::lastError() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->lastErr; +} + +/*! + Returns the line status as stored by the port function. This function will retrieve the states + of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines + can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned + long with specific bits indicating which lines are high. The following constants should be used + to examine the states of individual lines: + + \code + Mask Line + ------ ---- + LS_CTS CTS + LS_DSR DSR + LS_DCD DCD + LS_RI RI + LS_RTS RTS (POSIX only) + LS_DTR DTR (POSIX only) + LS_ST Secondary TXD (POSIX only) + LS_SR Secondary RXD (POSIX only) + \endcode + + This function will return 0 if the port associated with the class is not currently open. +*/ +unsigned long QextSerialPort::lineStatus() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + return d->lineStatus_sys(); + return 0; +} + +/*! + Returns a human-readable description of the last device error that occurred. +*/ +QString QextSerialPort::errorString() +{ + Q_D(QextSerialPort); + QReadLocker locker(&d->lock); + switch(d->lastErr) { + case E_NO_ERROR: + return tr("No Error has occurred"); + case E_INVALID_FD: + return tr("Invalid file descriptor (port was not opened correctly)"); + case E_NO_MEMORY: + return tr("Unable to allocate memory tables (POSIX)"); + case E_CAUGHT_NON_BLOCKED_SIGNAL: + return tr("Caught a non-blocked signal (POSIX)"); + case E_PORT_TIMEOUT: + return tr("Operation timed out (POSIX)"); + case E_INVALID_DEVICE: + return tr("The file opened by the port is not a valid device"); + case E_BREAK_CONDITION: + return tr("The port detected a break condition"); + case E_FRAMING_ERROR: + return tr("The port detected a framing error (usually caused by incorrect baud rate settings)"); + case E_IO_ERROR: + return tr("There was an I/O error while communicating with the port"); + case E_BUFFER_OVERRUN: + return tr("Character buffer overrun"); + case E_RECEIVE_OVERFLOW: + return tr("Receive buffer overflow"); + case E_RECEIVE_PARITY_ERROR: + return tr("The port detected a parity error in the received data"); + case E_TRANSMIT_OVERFLOW: + return tr("Transmit buffer overflow"); + case E_READ_FAILED: + return tr("General read operation failure"); + case E_WRITE_FAILED: + return tr("General write operation failure"); + case E_FILE_NOT_FOUND: + return tr("The %1 file doesn't exists").arg(this->portName()); + case E_PERMISSION_DENIED: + return tr("Permission denied"); + case E_AGAIN: + return tr("Device is already locked"); + default: + return tr("Unknown error: %1").arg(d->lastErr); + } +} + +/*! + Destructs the QextSerialPort object. +*/ +QextSerialPort::~QextSerialPort() +{ + if (isOpen()) { + close(); + } + delete d_ptr; +} + +/*! + Sets the flow control used by the port to \a flow. Possible values of flow are: + \code + FLOW_OFF No flow control + FLOW_HARDWARE Hardware (RTS/CTS) flow control + FLOW_XONXOFF Software (XON/XOFF) flow control + \endcode +*/ +void QextSerialPort::setFlowControl(FlowType flow) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.FlowControl != flow) + d->setFlowControl(flow, true); +} + +/*! + Sets the parity associated with the serial port to \a parity. The possible values of parity are: + \code + PAR_SPACE Space Parity + PAR_MARK Mark Parity + PAR_NONE No Parity + PAR_EVEN Even Parity + PAR_ODD Odd Parity + \endcode +*/ +void QextSerialPort::setParity(ParityType parity) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Parity != parity) + d->setParity(parity, true); +} + +/*! + Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are: + \code + DATA_5 5 data bits + DATA_6 6 data bits + DATA_7 7 data bits + DATA_8 8 data bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 5 data bits cannot be used with 2 stop bits. + \o 1.5 stop bits can only be used with 5 data bits. + \o 8 data bits cannot be used with space parity on POSIX systems. + \endlist + */ +void QextSerialPort::setDataBits(DataBitsType dataBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.DataBits != dataBits) + d->setDataBits(dataBits, true); +} + +/*! + Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are: + \code + STOP_1 1 stop bit + STOP_1_5 1.5 stop bits + STOP_2 2 stop bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 2 stop bits cannot be used with 5 data bits. + \o 1.5 stop bits cannot be used with 6 or more data bits. + \o POSIX does not support 1.5 stop bits. + \endlist +*/ +void QextSerialPort::setStopBits(StopBitsType stopBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.StopBits != stopBits) + d->setStopBits(stopBits, true); +} + +/*! + Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on + all platforms. The following table shows translations of the various baud rate + constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * + are speeds that are usable on both Windows and POSIX. + \code + + RATE Windows Speed POSIX Speed + ----------- ------------- ----------- + BAUD50 X 50 + BAUD75 X 75 + *BAUD110 110 110 + BAUD134 X 134.5 + BAUD150 X 150 + BAUD200 X 200 + *BAUD300 300 300 + *BAUD600 600 600 + *BAUD1200 1200 1200 + BAUD1800 X 1800 + *BAUD2400 2400 2400 + *BAUD4800 4800 4800 + *BAUD9600 9600 9600 + BAUD14400 14400 X + *BAUD19200 19200 19200 + *BAUD38400 38400 38400 + BAUD56000 56000 X + *BAUD57600 57600 57600 + BAUD76800 X 76800 + *BAUD115200 115200 115200 + BAUD128000 128000 X + BAUD230400 X 230400 + BAUD256000 256000 X + BAUD460800 X 460800 + BAUD500000 X 500000 + BAUD576000 X 576000 + BAUD921600 X 921600 + BAUD1000000 X 1000000 + BAUD1152000 X 1152000 + BAUD1500000 X 1500000 + BAUD2000000 X 2000000 + BAUD2500000 X 2500000 + BAUD3000000 X 3000000 + BAUD3500000 X 3500000 + BAUD4000000 X 4000000 + \endcode +*/ + +void QextSerialPort::setBaudRate(BaudRateType baudRate) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.BaudRate != baudRate) + d->setBaudRate(baudRate, true); +} + +/*! + For Unix: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Note that this is a per-character timeout, i.e. the port will wait this long for each + individual character, not for the whole read operation. This timeout also applies to the + bytesWaiting() function. + + \bold note: + POSIX does not support millisecond-level control for I/O timeout values. Any + timeout set using this function will be set to the next lowest tenth of a second for + the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds + will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and + writing the port. However millisecond-level control is allowed by the select() system call, + so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for + the purpose of detecting available bytes in the read buffer. + + For Windows: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Setting 0 indicates that timeouts are not used for read nor write operations; + however read() and write() functions will still block. Set -1 to provide + non-blocking behaviour (read() and write() will return immediately). + + \bold note: this function does nothing in event driven mode. +*/ +void QextSerialPort::setTimeout(long millisec) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Timeout_Millisec != millisec) + d->setTimeout(millisec, true); +} + +/*! + Sets DTR line to the requested state (\a set default to high). This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setDtr(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setDtr_sys(set); +} + +/*! + Sets RTS line to the requested state \a set (high by default). + This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setRts(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setRts_sys(set); +} + +/*! \reimp + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::readData(char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + qint64 bytesFromBuffer = 0; + if (!d->readBuffer.isEmpty()) { + bytesFromBuffer = d->readBuffer.read(data, maxSize); + if (bytesFromBuffer == maxSize) + return bytesFromBuffer; + } + qint64 bytesFromDevice = d->readData_sys(data+bytesFromBuffer, maxSize-bytesFromBuffer); + if (bytesFromDevice < 0) { + return -1; + } + return bytesFromBuffer + bytesFromDevice; +} + +/*! \reimp + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::writeData(const char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + return d->writeData_sys(data, maxSize); +} + +#include "moc_qextserialport.cpp" diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport.h b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.h new file mode 100644 index 0000000..5334e94 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.h @@ -0,0 +1,240 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_H_ +#define _QEXTSERIALPORT_H_ + +#include +#include "qextserialport_global.h" +#ifdef Q_OS_UNIX +#include +#endif +/*line status constants*/ +// ### QESP2.0 move to enum +#define LS_CTS 0x01 +#define LS_DSR 0x02 +#define LS_DCD 0x04 +#define LS_RI 0x08 +#define LS_RTS 0x10 +#define LS_DTR 0x20 +#define LS_ST 0x40 +#define LS_SR 0x80 + +/*error constants*/ +// ### QESP2.0 move to enum +#define E_NO_ERROR 0 +#define E_INVALID_FD 1 +#define E_NO_MEMORY 2 +#define E_CAUGHT_NON_BLOCKED_SIGNAL 3 +#define E_PORT_TIMEOUT 4 +#define E_INVALID_DEVICE 5 +#define E_BREAK_CONDITION 6 +#define E_FRAMING_ERROR 7 +#define E_IO_ERROR 8 +#define E_BUFFER_OVERRUN 9 +#define E_RECEIVE_OVERFLOW 10 +#define E_RECEIVE_PARITY_ERROR 11 +#define E_TRANSMIT_OVERFLOW 12 +#define E_READ_FAILED 13 +#define E_WRITE_FAILED 14 +#define E_FILE_NOT_FOUND 15 +#define E_PERMISSION_DENIED 16 +#define E_AGAIN 17 + +enum BaudRateType +{ +#if defined(Q_OS_UNIX) || defined(qdoc) + BAUD50 = 50, //POSIX ONLY + BAUD75 = 75, //POSIX ONLY + BAUD134 = 134, //POSIX ONLY + BAUD150 = 150, //POSIX ONLY + BAUD200 = 200, //POSIX ONLY + BAUD1800 = 1800, //POSIX ONLY +# if defined(B76800) || defined(qdoc) + BAUD76800 = 76800, //POSIX ONLY +# endif +# if (defined(B230400) && defined(B4000000)) || defined(qdoc) + BAUD230400 = 230400, //POSIX ONLY + BAUD460800 = 460800, //POSIX ONLY + BAUD500000 = 500000, //POSIX ONLY + BAUD576000 = 576000, //POSIX ONLY + BAUD921600 = 921600, //POSIX ONLY + BAUD1000000 = 1000000, //POSIX ONLY + BAUD1152000 = 1152000, //POSIX ONLY + BAUD1500000 = 1500000, //POSIX ONLY + BAUD2000000 = 2000000, //POSIX ONLY + BAUD2500000 = 2500000, //POSIX ONLY + BAUD3000000 = 3000000, //POSIX ONLY + BAUD3500000 = 3500000, //POSIX ONLY + BAUD4000000 = 4000000, //POSIX ONLY +# endif +#endif //Q_OS_UNIX +#if defined(Q_OS_WIN) || defined(qdoc) + BAUD14400 = 14400, //WINDOWS ONLY + BAUD56000 = 56000, //WINDOWS ONLY + BAUD128000 = 128000, //WINDOWS ONLY + BAUD256000 = 256000, //WINDOWS ONLY +#endif //Q_OS_WIN + BAUD110 = 110, + BAUD300 = 300, + BAUD600 = 600, + BAUD1200 = 1200, + BAUD2400 = 2400, + BAUD4800 = 4800, + BAUD9600 = 9600, + BAUD19200 = 19200, + BAUD38400 = 38400, + BAUD57600 = 57600, + BAUD115200 = 115200 +}; + +enum DataBitsType +{ + DATA_5 = 5, + DATA_6 = 6, + DATA_7 = 7, + DATA_8 = 8 +}; + +enum ParityType +{ + PAR_NONE, + PAR_ODD, + PAR_EVEN, +#if defined(Q_OS_WIN) || defined(qdoc) + PAR_MARK, //WINDOWS ONLY +#endif + PAR_SPACE +}; + +enum StopBitsType +{ + STOP_1, +#if defined(Q_OS_WIN) || defined(qdoc) + STOP_1_5, //WINDOWS ONLY +#endif + STOP_2 +}; + +enum FlowType +{ + FLOW_OFF, + FLOW_HARDWARE, + FLOW_XONXOFF +}; + +/** + * structure to contain port settings + */ +struct PortSettings +{ + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; +}; + +class QextSerialPortPrivate; +class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialPort) + Q_ENUMS(QueryMode) + Q_PROPERTY(QString portName READ portName WRITE setPortName) + Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode) +public: + enum QueryMode { + Polling, + EventDriven + }; + + explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0); + QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent=0); + + ~QextSerialPort(); + + QString portName() const; + QueryMode queryMode() const; + BaudRateType baudRate() const; + DataBitsType dataBits() const; + ParityType parity() const; + StopBitsType stopBits() const; + FlowType flowControl() const; + + bool open(OpenMode mode); + bool isSequential() const; + void close(); + void flush(); + qint64 bytesAvailable() const; + bool canReadLine() const; + QByteArray readAll(); + + ulong lastError() const; + + ulong lineStatus(); + QString errorString(); + +public Q_SLOTS: + void setPortName(const QString &name); + void setQueryMode(QueryMode mode); + void setBaudRate(BaudRateType); + void setDataBits(DataBitsType); + void setParity(ParityType); + void setStopBits(StopBitsType); + void setFlowControl(FlowType); + void setTimeout(long); + + void setDtr(bool set=true); + void setRts(bool set=true); + +Q_SIGNALS: + void dsrChanged(bool status); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(QextSerialPort) + +#ifdef Q_OS_WIN + Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE)) +#endif + Q_PRIVATE_SLOT(d_func(), void _q_canRead()) + + QextSerialPortPrivate *const d_ptr; +}; + +#endif diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport.pri b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.pri new file mode 100644 index 0000000..461d56f --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +PUBLIC_HEADERS += $$PWD/qextserialport.h \ + $$PWD/qextserialenumerator.h \ + $$PWD/qextserialport_global.h + +HEADERS += $$PUBLIC_HEADERS \ + $$PWD/qextserialport_p.h \ + $$PWD/qextserialenumerator_p.h \ + +SOURCES += $$PWD/qextserialport.cpp \ + $$PWD/qextserialenumerator.cpp +unix { + SOURCES += $$PWD/qextserialport_unix.cpp + linux* { + SOURCES += $$PWD/qextserialenumerator_linux.cpp + } else:macx { + SOURCES += $$PWD/qextserialenumerator_osx.cpp + } else { + SOURCES += $$PWD/qextserialenumerator_unix.cpp + } +} +win32:SOURCES += $$PWD/qextserialport_win.cpp \ + $$PWD/qextserialenumerator_win.cpp + +linux*{ + !qesp_linux_udev:DEFINES += QESP_NO_UDEV + qesp_linux_udev: LIBS += -ludev +} + +macx:LIBS += -framework IOKit -framework CoreFoundation +win32:LIBS += -lsetupapi -ladvapi32 -luser32 + +# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work +linux*:DEFINES += __linux__ diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport_global.h b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_global.h new file mode 100644 index 0000000..824d455 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_global.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTSERIALPORT_GLOBAL_H +#define QEXTSERIALPORT_GLOBAL_H + +#include + +#ifdef QEXTSERIALPORT_BUILD_SHARED +# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT +#elif defined(QEXTSERIALPORT_USING_SHARED) +# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT +#else +# define QEXTSERIALPORT_EXPORT +#endif + +// ### for compatible with old version. should be removed in QESP 2.0 +#ifdef _TTY_NOWARN_ +# define QESP_NO_WARN +#endif +#ifdef _TTY_NOWARN_PORT_ +# define QESP_NO_PORTABILITY_WARN +#endif + +/*if all warning messages are turned off, flag portability warnings to be turned off as well*/ +#ifdef QESP_NO_WARN +# define QESP_NO_PORTABILITY_WARN +#endif + +/*macros for warning and debug messages*/ +#ifdef QESP_NO_PORTABILITY_WARN +# define QESP_PORTABILITY_WARNING while (false)qWarning +#else +# define QESP_PORTABILITY_WARNING qWarning +#endif /*QESP_NOWARN_PORT*/ + +#ifdef QESP_NO_WARN +# define QESP_WARNING while (false)qWarning +#else +# define QESP_WARNING qWarning +#endif /*QESP_NOWARN*/ + +#endif // QEXTSERIALPORT_GLOBAL_H + diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport_p.h b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_p.h new file mode 100644 index 0000000..d278a17 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_p.h @@ -0,0 +1,251 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_P_H_ +#define _QEXTSERIALPORT_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialport.h" +#include +#ifdef Q_OS_UNIX +# include +#elif (defined Q_OS_WIN) +# include +#endif +#include + +// This is QextSerialPort's read buffer, needed by posix system. +// ref: QRingBuffer & QIODevicePrivateLinearBuffer +class QextReadBuffer +{ +public: + inline QextReadBuffer(size_t growth=4096) + : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { + } + + ~QextReadBuffer() { + delete [] buf; + } + + inline void clear() { + first = buf; + len = 0; + } + + inline int size() const { + return len; + } + + inline bool isEmpty() const { + return len == 0; + } + + inline int read(char *target, int size) { + int r = qMin(size, len); + if (r == 1) { + *target = *first; + --len; + ++first; + } else { + memcpy(target, first, r); + len -= r; + first += r; + } + return r; + } + + inline char *reserve(size_t size) { + if ((first - buf) + len + size > capacity) { + size_t newCapacity = qMax(capacity, basicBlockSize); + while (newCapacity < len + size) + newCapacity *= 2; + if (newCapacity > capacity) { + // allocate more space + char *newBuf = new char[newCapacity]; + memmove(newBuf, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf, first, len); + } + first = buf; + } + char *writePtr = first + len; + len += (int)size; + return writePtr; + } + + inline void chop(int size) { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + + inline void squeeze() { + if (first != buf) { + memmove(buf, first, len); + first = buf; + } + size_t newCapacity = basicBlockSize; + while (newCapacity < size_t(len)) + newCapacity *= 2; + if (newCapacity < capacity) { + char *tmp = static_cast(realloc(buf, newCapacity)); + if (tmp) { + buf = tmp; + capacity = newCapacity; + } + } + } + + inline QByteArray readAll() { + char *f = first; + int l = len; + clear(); + return QByteArray(f, l); + } + + inline int readLine(char *target, int size) { + int r = qMin(size, len); + char *eol = static_cast(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return int(r); + } + + inline bool canReadLine() const { + return memchr(first, '\n', len); + } + +private: + int len; + char *first; + char *buf; + size_t capacity; + size_t basicBlockSize; +}; + +class QWinEventNotifier; +class QReadWriteLock; +class QSocketNotifier; + +class QextSerialPortPrivate +{ + Q_DECLARE_PUBLIC(QextSerialPort) +public: + QextSerialPortPrivate(QextSerialPort *q); + ~QextSerialPortPrivate(); + enum DirtyFlagEnum + { + DFE_BaudRate = 0x0001, + DFE_Parity = 0x0002, + DFE_StopBits = 0x0004, + DFE_DataBits = 0x0008, + DFE_Flow = 0x0010, + DFE_TimeOut = 0x0100, + DFE_ALL = 0x0fff, + DFE_Settings_Mask = 0x00ff //without TimeOut + }; + mutable QReadWriteLock lock; + QString port; + PortSettings settings; + QextReadBuffer readBuffer; + int settingsDirtyFlags; + ulong lastErr; + QextSerialPort::QueryMode queryMode; + + // platform specific members +#ifdef Q_OS_UNIX + int fd; + QSocketNotifier *readNotifier; + struct termios currentTermios; + struct termios oldTermios; +#elif (defined Q_OS_WIN) + HANDLE handle; + OVERLAPPED overlap; + COMMCONFIG commConfig; + COMMTIMEOUTS commTimeouts; + QWinEventNotifier *winEventNotifier; + DWORD eventMask; + QList pendingWrites; + QReadWriteLock *bytesToWriteLock; +#endif + + /*fill PortSettings*/ + void setBaudRate(BaudRateType baudRate, bool update=true); + void setDataBits(DataBitsType dataBits, bool update=true); + void setParity(ParityType parity, bool update=true); + void setStopBits(StopBitsType stopbits, bool update=true); + void setFlowControl(FlowType flow, bool update=true); + void setTimeout(long millisec, bool update=true); + void setPortSettings(const PortSettings &settings, bool update=true); + + void platformSpecificDestruct(); + void platformSpecificInit(); + void translateError(ulong error); + void updatePortSettings(); + + qint64 readData_sys(char *data, qint64 maxSize); + qint64 writeData_sys(const char *data, qint64 maxSize); + void setDtr_sys(bool set=true); + void setRts_sys(bool set=true); + bool open_sys(QIODevice::OpenMode mode); + bool close_sys(); + bool flush_sys(); + ulong lineStatus_sys(); + qint64 bytesAvailable_sys() const; + +#ifdef Q_OS_WIN + void _q_onWinEvent(HANDLE h); +#endif + void _q_canRead(); + + QextSerialPort *q_ptr; +}; + +#endif //_QEXTSERIALPORT_P_H_ diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport_unix.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_unix.cpp new file mode 100644 index 0000000..4c02a20 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_unix.cpp @@ -0,0 +1,460 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void QextSerialPortPrivate::platformSpecificInit() +{ + fd = 0; + readNotifier = 0; +} + +/*! + Standard destructor. +*/ +void QextSerialPortPrivate::platformSpecificDestruct() +{ +} + +static QString fullPortName(const QString &name) +{ + if (name.startsWith(QLatin1Char('/'))) + return name; + return QLatin1String("/dev/")+name; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + //note: linux 2.6.21 seems to ignore O_NDELAY flag + if ((fd = ::open(fullPortName(port).toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { + + /*In the Private class, We can not call QIODevice::open()*/ + q->setOpenMode(mode); // Flag the port as opened + ::tcgetattr(fd, &oldTermios); // Save the old termios + currentTermios = oldTermios; // Make a working copy + ::cfmakeraw(¤tTermios); // Enable raw access + + /*set up other port settings*/ + currentTermios.c_cflag |= CREAD|CLOCAL; + currentTermios.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + currentTermios.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + currentTermios.c_oflag &= (~OPOST); + currentTermios.c_cc[VMIN] = 0; +#ifdef _POSIX_VDISABLE // Is a disable character available on this system? + // Some systems allow for per-device disable-characters, so get the + // proper value for the configured device + const long vdisable = ::fpathconf(fd, _PC_VDISABLE); + currentTermios.c_cc[VINTR] = vdisable; + currentTermios.c_cc[VQUIT] = vdisable; + currentTermios.c_cc[VSTART] = vdisable; + currentTermios.c_cc[VSTOP] = vdisable; + currentTermios.c_cc[VSUSP] = vdisable; +#endif //_POSIX_VDISABLE + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + if (queryMode == QextSerialPort::EventDriven) { + readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); + q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead())); + } + return true; + } else { + translateError(errno); + return false; + } +} + +bool QextSerialPortPrivate::close_sys() +{ + // Force a flush and then restore the original termios + flush_sys(); + // Using both TCSAFLUSH and TCSANOW here discards any pending input + ::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios + ::close(fd); + if (readNotifier) { + delete readNotifier; + readNotifier = 0; + } + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + ::tcdrain(fd); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + int bytesQueued; + if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) { + return (qint64)-1; + } + return bytesQueued; +} + +/*! + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + switch (error) { + case EBADF: + case ENOTTY: + lastErr = E_INVALID_FD; + break; + case EINTR: + lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL; + break; + case ENOMEM: + lastErr = E_NO_MEMORY; + break; + case EACCES: + lastErr = E_PERMISSION_DENIED; + break; + case EAGAIN: + lastErr = E_AGAIN; + break; + } +} + +void QextSerialPortPrivate::setDtr_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_DTR; + else + status &= ~TIOCM_DTR; + ::ioctl(fd, TIOCMSET, &status); +} + +void QextSerialPortPrivate::setRts_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_RTS; + else + status &= ~TIOCM_RTS; + ::ioctl(fd, TIOCMSET, &status); +} + +unsigned long QextSerialPortPrivate::lineStatus_sys() +{ + unsigned long Status=0, Temp=0; + ::ioctl(fd, TIOCMGET, &Temp); + if (Temp & TIOCM_CTS) Status |= LS_CTS; + if (Temp & TIOCM_DSR) Status |= LS_DSR; + if (Temp & TIOCM_RI) Status |= LS_RI; + if (Temp & TIOCM_CD) Status |= LS_DCD; + if (Temp & TIOCM_DTR) Status |= LS_DTR; + if (Temp & TIOCM_RTS) Status |= LS_RTS; + if (Temp & TIOCM_ST) Status |= LS_ST; + if (Temp & TIOCM_SR) Status |= LS_SR; + return Status; +} + +/*! + Reads a block of data from the serial port. This function will read at most maxSize bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + int retVal = ::read(fd, data, maxSize); + if (retVal == -1) + lastErr = E_READ_FAILED; + + return retVal; +} + +/*! + Writes a block of data to the serial port. This function will write maxSize bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + int retVal = ::write(fd, data, maxSize); + if (retVal == -1) + lastErr = E_WRITE_FAILED; + + return (qint64)retVal; +} + +static void setBaudRate2Termios(termios *config, int baudRate) +{ +#ifdef CBAUD + config->c_cflag &= (~CBAUD); + config->c_cflag |= baudRate; +#else + ::cfsetispeed(config, baudRate); + ::cfsetospeed(config, baudRate); +#endif +} + +/* + All the platform settings was performed in this function. +*/ +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_func()->isOpen() || !settingsDirtyFlags) + return; + + if (settingsDirtyFlags & DFE_BaudRate) { + switch (settings.BaudRate) { + case BAUD50: + setBaudRate2Termios(¤tTermios, B50); + break; + case BAUD75: + setBaudRate2Termios(¤tTermios, B75); + break; + case BAUD110: + setBaudRate2Termios(¤tTermios, B110); + break; + case BAUD134: + setBaudRate2Termios(¤tTermios, B134); + break; + case BAUD150: + setBaudRate2Termios(¤tTermios, B150); + break; + case BAUD200: + setBaudRate2Termios(¤tTermios, B200); + break; + case BAUD300: + setBaudRate2Termios(¤tTermios, B300); + break; + case BAUD600: + setBaudRate2Termios(¤tTermios, B600); + break; + case BAUD1200: + setBaudRate2Termios(¤tTermios, B1200); + break; + case BAUD1800: + setBaudRate2Termios(¤tTermios, B1800); + break; + case BAUD2400: + setBaudRate2Termios(¤tTermios, B2400); + break; + case BAUD4800: + setBaudRate2Termios(¤tTermios, B4800); + break; + case BAUD9600: + setBaudRate2Termios(¤tTermios, B9600); + break; + case BAUD19200: + setBaudRate2Termios(¤tTermios, B19200); + break; + case BAUD38400: + setBaudRate2Termios(¤tTermios, B38400); + break; + case BAUD57600: + setBaudRate2Termios(¤tTermios, B57600); + break; +#ifdef B76800 + case BAUD76800: + setBaudRate2Termios(¤tTermios, B76800); + break; +#endif + case BAUD115200: + setBaudRate2Termios(¤tTermios, B115200); + break; +#if defined(B230400) && defined(B4000000) + case BAUD230400: + setBaudRate2Termios(¤tTermios, B230400); + break; + case BAUD460800: + setBaudRate2Termios(¤tTermios, B460800); + break; + case BAUD500000: + setBaudRate2Termios(¤tTermios, B500000); + break; + case BAUD576000: + setBaudRate2Termios(¤tTermios, B576000); + break; + case BAUD921600: + setBaudRate2Termios(¤tTermios, B921600); + break; + case BAUD1000000: + setBaudRate2Termios(¤tTermios, B1000000); + break; + case BAUD1152000: + setBaudRate2Termios(¤tTermios, B1152000); + break; + case BAUD1500000: + setBaudRate2Termios(¤tTermios, B1500000); + break; + case BAUD2000000: + setBaudRate2Termios(¤tTermios, B2000000); + break; + case BAUD2500000: + setBaudRate2Termios(¤tTermios, B2500000); + break; + case BAUD3000000: + setBaudRate2Termios(¤tTermios, B3000000); + break; + case BAUD3500000: + setBaudRate2Termios(¤tTermios, B3500000); + break; + case BAUD4000000: + setBaudRate2Termios(¤tTermios, B4000000); + break; +#endif +#ifdef Q_OS_MAC + default: + setBaudRate2Termios(¤tTermios, settings.BaudRate); + break; +#endif + } + } + if (settingsDirtyFlags & DFE_Parity) { + switch (settings.Parity) { + case PAR_SPACE: + /*space parity not directly supported - add an extra data bit to simulate it*/ + settingsDirtyFlags |= DFE_DataBits; + break; + case PAR_NONE: + currentTermios.c_cflag &= (~PARENB); + break; + case PAR_EVEN: + currentTermios.c_cflag &= (~PARODD); + currentTermios.c_cflag |= PARENB; + break; + case PAR_ODD: + currentTermios.c_cflag |= (PARENB|PARODD); + break; + } + } + /*must after Parity settings*/ + if (settingsDirtyFlags & DFE_DataBits) { + if (settings.Parity != PAR_SPACE) { + currentTermios.c_cflag &= (~CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS5; + break; + case DATA_6: + currentTermios.c_cflag |= CS6; + break; + case DATA_7: + currentTermios.c_cflag |= CS7; + break; + case DATA_8: + currentTermios.c_cflag |= CS8; + break; + } + } else { + /*space parity not directly supported - add an extra data bit to simulate it*/ + currentTermios.c_cflag &= ~(PARENB|CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS6; + break; + case DATA_6: + currentTermios.c_cflag |= CS7; + break; + case DATA_7: + currentTermios.c_cflag |= CS8; + break; + case DATA_8: + /*this will never happen, put here to Suppress an warning*/ + break; + } + } + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + currentTermios.c_cflag &= (~CSTOPB); + break; + case STOP_2: + currentTermios.c_cflag |= CSTOPB; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + case FLOW_OFF: + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + case FLOW_XONXOFF: + /*software (XON/XOFF) flow control*/ + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag |= (IXON|IXOFF|IXANY); + break; + case FLOW_HARDWARE: + currentTermios.c_cflag |= CRTSCTS; + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + } + } + + /*if any thing in currentTermios changed, flush*/ + if (settingsDirtyFlags & DFE_Settings_Mask) + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + + if (settingsDirtyFlags & DFE_TimeOut) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + ::fcntl(fd, F_SETFL, O_NDELAY); + } + else { + //O_SYNC should enable blocking ::write() + //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2) + ::fcntl(fd, F_SETFL, O_SYNC); + } + ::tcgetattr(fd, ¤tTermios); + currentTermios.c_cc[VTIME] = millisec/100; + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + } + + settingsDirtyFlags = 0; +} diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextserialport_win.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_win.cpp new file mode 100644 index 0000000..6b13b52 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextserialport_win.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +# include +#else +# include +#endif +void QextSerialPortPrivate::platformSpecificInit() +{ + handle = INVALID_HANDLE_VALUE; + ZeroMemory(&overlap, sizeof(OVERLAPPED)); + overlap.hEvent = CreateEvent(NULL, true, false, NULL); + winEventNotifier = 0; + bytesToWriteLock = new QReadWriteLock; +} + +void QextSerialPortPrivate::platformSpecificDestruct() { + CloseHandle(overlap.hEvent); + delete bytesToWriteLock; +} + + +/*! + \internal + COM ports greater than 9 need \\.\ prepended + + This is only need when open the port. +*/ +static QString fullPortNameWin(const QString &name) +{ + QRegExp rx(QLatin1String("^COM(\\d+)")); + QString fullName(name); + if (fullName.contains(rx)) + fullName.prepend(QLatin1String("\\\\.\\")); + return fullName; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + DWORD confSize = sizeof(COMMCONFIG); + commConfig.dwSize = confSize; + DWORD dwFlagsAndAttributes = 0; + if (queryMode == QextSerialPort::EventDriven) + dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; + + /*open the port*/ + handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); + if (handle != INVALID_HANDLE_VALUE) { + q->setOpenMode(mode); + /*configure port settings*/ + GetCommConfig(handle, &commConfig, &confSize); + GetCommState(handle, &(commConfig.dcb)); + + /*set up parameters*/ + commConfig.dcb.fBinary = TRUE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + commConfig.dcb.fAbortOnError = FALSE; + commConfig.dcb.fNull = FALSE; + /* Dtr default to true. See Issue 122*/ + commConfig.dcb.fDtrControl = TRUE; + /*flush all settings*/ + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + //init event driven approach + if (queryMode == QextSerialPort::EventDriven) { + if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { + QESP_WARNING()<<"failed to set Comm Mask. Error code:"<("HANDLE"); + q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection); + WaitCommEvent(handle, &eventMask, &overlap); + } + return true; + } + return false; +} + +bool QextSerialPortPrivate::close_sys() +{ + flush_sys(); + CancelIo(handle); + if (CloseHandle(handle)) + handle = INVALID_HANDLE_VALUE; + if (winEventNotifier) { + winEventNotifier->setEnabled(false); + winEventNotifier->deleteLater(); + winEventNotifier = 0; + } + + foreach (OVERLAPPED *o, pendingWrites) { + CloseHandle(o->hEvent); + delete o; + } + pendingWrites.clear(); + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + FlushFileBuffers(handle); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + DWORD Errors; + COMSTAT Status; + if (ClearCommError(handle, &Errors, &Status)) { + return Status.cbInQue; + } + return (qint64)-1; +} + +/* + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + if (error & CE_BREAK) { + lastErr = E_BREAK_CONDITION; + } + else if (error & CE_FRAME) { + lastErr = E_FRAMING_ERROR; + } + else if (error & CE_IOE) { + lastErr = E_IO_ERROR; + } + else if (error & CE_MODE) { + lastErr = E_INVALID_FD; + } + else if (error & CE_OVERRUN) { + lastErr = E_BUFFER_OVERRUN; + } + else if (error & CE_RXPARITY) { + lastErr = E_RECEIVE_PARITY_ERROR; + } + else if (error & CE_RXOVER) { + lastErr = E_RECEIVE_OVERFLOW; + } + else if (error & CE_TXFULL) { + lastErr = E_TRANSMIT_OVERFLOW; + } +} + +/* + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + DWORD bytesRead = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED overlapRead; + ZeroMemory(&overlapRead, sizeof(OVERLAPPED)); + if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) { + if (GetLastError() == ERROR_IO_PENDING) + GetOverlappedResult(handle, &overlapRead, &bytesRead, true); + else + failed = true; + } + } else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) { + failed = true; + } + if (!failed) + return (qint64)bytesRead; + + lastErr = E_READ_FAILED; + return -1; +} + +/* + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + DWORD bytesWritten = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED *newOverlapWrite = new OVERLAPPED; + ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED)); + newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL); + if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) { + CloseHandle(newOverlapWrite->hEvent); + delete newOverlapWrite; + } + else if (GetLastError() == ERROR_IO_PENDING) { + // writing asynchronously...not an error + QWriteLocker writelocker(bytesToWriteLock); + pendingWrites.append(newOverlapWrite); + } + else { + QESP_WARNING()<<"QextSerialPort write error:"<hEvent)) + QESP_WARNING("QextSerialPort: couldn't cancel IO"); + if (!CloseHandle(newOverlapWrite->hEvent)) + QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle"); + delete newOverlapWrite; + } + } else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) { + failed = true; + } + + if (!failed) + return (qint64)bytesWritten; + + lastErr = E_WRITE_FAILED; + return -1; +} + +void QextSerialPortPrivate::setDtr_sys(bool set) { + EscapeCommFunction(handle, set ? SETDTR : CLRDTR); +} + +void QextSerialPortPrivate::setRts_sys(bool set) { + EscapeCommFunction(handle, set ? SETRTS : CLRRTS); +} + +ulong QextSerialPortPrivate::lineStatus_sys(void) { + unsigned long Status = 0, Temp = 0; + GetCommModemStatus(handle, &Temp); + if (Temp & MS_CTS_ON) Status |= LS_CTS; + if (Temp & MS_DSR_ON) Status |= LS_DSR; + if (Temp & MS_RING_ON) Status |= LS_RI; + if (Temp & MS_RLSD_ON) Status |= LS_DCD; + return Status; +} + +/* + Triggered when there's activity on our HANDLE. +*/ +void QextSerialPortPrivate::_q_onWinEvent(HANDLE h) +{ + Q_Q(QextSerialPort); + if (h == overlap.hEvent) { + if (eventMask & EV_RXCHAR) { + if (q->sender() != q && bytesAvailable_sys() > 0) + _q_canRead(); + } + if (eventMask & EV_TXEMPTY) { + /* + A write completed. Run through the list of OVERLAPPED writes, and if + they completed successfully, take them off the list and delete them. + Otherwise, leave them on there so they can finish. + */ + qint64 totalBytesWritten = 0; + QList overlapsToDelete; + foreach (OVERLAPPED *o, pendingWrites) { + DWORD numBytes = 0; + if (GetOverlappedResult(handle, o, &numBytes, false)) { + overlapsToDelete.append(o); + totalBytesWritten += numBytes; + } else if (GetLastError() != ERROR_IO_INCOMPLETE) { + overlapsToDelete.append(o); + QESP_WARNING()<<"CommEvent overlapped write error:" << GetLastError(); + } + } + + if (q->sender() != q && totalBytesWritten > 0) { + QWriteLocker writelocker(bytesToWriteLock); + Q_EMIT q->bytesWritten(totalBytesWritten); + } + + foreach (OVERLAPPED *o, overlapsToDelete) { + OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o)); + CloseHandle(toDelete->hEvent); + delete toDelete; + } + } + if (eventMask & EV_DSR) { + if (lineStatus_sys() & LS_DSR) + Q_EMIT q->dsrChanged(true); + else + Q_EMIT q->dsrChanged(false); + } + } + WaitCommEvent(handle, &eventMask, &overlap); +} + +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_ptr->isOpen() || !settingsDirtyFlags) + return; + + //fill struct : COMMCONFIG + if (settingsDirtyFlags & DFE_BaudRate) { + commConfig.dcb.BaudRate = settings.BaudRate; + } + if (settingsDirtyFlags & DFE_Parity) { + commConfig.dcb.Parity = (BYTE)settings.Parity; + commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE; + } + if (settingsDirtyFlags & DFE_DataBits) { + commConfig.dcb.ByteSize = (BYTE)settings.DataBits; + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + commConfig.dcb.StopBits = ONESTOPBIT; + break; + case STOP_1_5: + commConfig.dcb.StopBits = ONE5STOPBITS; + break; + case STOP_2: + commConfig.dcb.StopBits = TWOSTOPBITS; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + /*no flow control*/ + case FLOW_OFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + /*software (XON/XOFF) flow control*/ + case FLOW_XONXOFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = TRUE; + commConfig.dcb.fOutX = TRUE; + break; + /*hardware flow control*/ + case FLOW_HARDWARE: + commConfig.dcb.fOutxCtsFlow = TRUE; + commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + } + } + + //fill struct : COMMTIMEOUTS + if (settingsDirtyFlags & DFE_TimeOut) { + if (queryMode != QextSerialPort::EventDriven) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutConstant = 0; + } else { + commTimeouts.ReadIntervalTimeout = millisec; + commTimeouts.ReadTotalTimeoutConstant = millisec; + } + commTimeouts.ReadTotalTimeoutMultiplier = 0; + // zapmaker fix for dropped sent packets on fast Windows computers + //commTimeouts.WriteTotalTimeoutMultiplier = millisec; + commTimeouts.WriteTotalTimeoutMultiplier = 500; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + else { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutMultiplier = 0; + commTimeouts.ReadTotalTimeoutConstant = 0; + commTimeouts.WriteTotalTimeoutMultiplier = 0; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + } + + + if (settingsDirtyFlags & DFE_Settings_Mask) + SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG)); + if ((settingsDirtyFlags & DFE_TimeOut)) + SetCommTimeouts(handle, &commTimeouts); + settingsDirtyFlags = 0; +} diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.cpp b/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.cpp new file mode 100644 index 0000000..f029421 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextwineventnotifier_p.h" +#include +#include +#include +#include +#include +#include +#include + +class QextWinEventNotifierPrivate +{ + Q_DECLARE_PUBLIC(QextWinEventNotifier) +public: + QextWinEventNotifierPrivate(HANDLE hEvent, QextWinEventNotifier * q) + :handleToEvent(hEvent), enabled(false), q_ptr(q) + {} + + HANDLE handleToEvent; + bool enabled; +private: + QextWinEventNotifier * q_ptr; +}; + +/* + \internal + + \class QextWinEventNotifierThread + + This class works more or less like an EventDispatcher. + + The api function WaitForMultipleObjects() is used in the new thread + to wait for the registered handle. +*/ +class QextWinEventNotifierThread:public QThread +{ +public: + explicit QextWinEventNotifierThread(QObject * parent=0); + ~QextWinEventNotifierThread(); + void stop(); + bool registerEventNotifier(QextWinEventNotifier * notifier); + void unregisterEventNotifier(QextWinEventNotifier * notifier); +protected: + void run(); +private: + HANDLE hStopEvent; //stop thread when this event signaled. + HANDLE hUpdateEvent; //make sure eventlist updated. + QMutex mutex; + QList winEventNotifierList; +}; + +Q_GLOBAL_STATIC(QextWinEventNotifierThread, notifierThread) + +QextWinEventNotifierThread::QextWinEventNotifierThread(QObject * parent) + :QThread(parent) +{ + hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hUpdateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + start(); +} + +QextWinEventNotifierThread::~QextWinEventNotifierThread() +{ + if (isRunning()) + stop(); + CloseHandle(hStopEvent); + CloseHandle(hUpdateEvent); +} + +void QextWinEventNotifierThread::stop() +{ + { + QMutexLocker locker(&mutex); + SetEvent(hStopEvent); + } + wait(); /// Is this an good idea? +} + +bool QextWinEventNotifierThread::registerEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return false; + } + if (winEventNotifierList.contains(notifier)) + return true; + if (winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 3) { + QESP_WARNING("QextWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 3); + return false; + } + winEventNotifierList.append(notifier); + SetEvent(hUpdateEvent); + return true; +} + +void QextWinEventNotifierThread::unregisterEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return; + } + + int idx = winEventNotifierList.indexOf(notifier); + if (idx != -1) { + winEventNotifierList.takeAt(idx); + SetEvent(hUpdateEvent); + } +} + +void QextWinEventNotifierThread::run() +{ + forever{ + HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; + DWORD nCount = 0; + { + QMutexLocker locker(&mutex); + nCount = winEventNotifierList.count(); + for (int i=0; i<(int)nCount; ++i) + pHandles[i] = winEventNotifierList.at(i)->handle(); + pHandles[nCount] = hUpdateEvent; + pHandles[nCount+1] = hStopEvent; + } + DWORD ret = WaitForMultipleObjects(nCount+2, pHandles, FALSE, INFINITE); + if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + nCount) { + QEvent *evt = new QEvent(QEvent::User); + QMutexLocker locker(&mutex); + ResetEvent(pHandles[ret-WAIT_OBJECT_0]); + QObject * notifier = winEventNotifierList[ret - WAIT_OBJECT_0]; + QCoreApplication::postEvent(notifier, evt); + } + else if (ret == WAIT_OBJECT_0 + nCount) { + //ResetEvent(hUpdateEvent); + } + else if (ret == WAIT_OBJECT_0 + nCount + 1) { + //qDebug()<<"quit..."; + return; + } + } +} + +/*! + \internal + \class QextWinEventNotifier + \brief The QextWinEventNotifier class provides support for the Windows Wait functions. + + The QextWinEventNotifier class makes it possible to use the wait + functions on windows in a asynchronous manner. With this class + you can register a HANDLE to an event and get notification when + that event becomes signalled. + + \bold Note: If it is a manual reset event ,it will be reset before + the notification. This is different from QWinEventNotifier. + + \bold Note: All the registered handles will be waited under a new thread. + This is different from QWinEventNotifier whose event handle will be waited + in its affinal thread. +*/ + +QextWinEventNotifier::QextWinEventNotifier(QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(0, this)) +{} + +QextWinEventNotifier::QextWinEventNotifier(HANDLE hEvent, QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(hEvent, this)) +{ + setEnabled(true); +} + +QextWinEventNotifier::~QextWinEventNotifier() +{ + setEnabled(false); +} + +void QextWinEventNotifier::setHandle(HANDLE hEvent) +{ + setEnabled(false); + Q_D(QextWinEventNotifier); + d->handleToEvent = hEvent; +} + +HANDLE QextWinEventNotifier::handle() const +{ + return d_func()->handleToEvent; +} + +bool QextWinEventNotifier::isEnabled() const +{ + return d_func()->enabled; +} + +void QextWinEventNotifier::setEnabled(bool enable) +{ + Q_D(QextWinEventNotifier); + + if (d->enabled == enable) + return; + d->enabled = enable; + + if (d->enabled) + notifierThread()->registerEventNotifier(this); + else + notifierThread()->unregisterEventNotifier(this); +} + +bool QextWinEventNotifier::event(QEvent * e) +{ + Q_D(QextWinEventNotifier); + QObject::event(e); + if (e->type() == QEvent::User) { + emit activated(d->handleToEvent); + return true; + } + return false; +} + diff --git a/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.h b/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.h new file mode 100644 index 0000000..38f1457 --- /dev/null +++ b/GC-3.6.1-T3/src/QextSerialPort/qextwineventnotifier_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTWINEVENTNOTIFIER_P_H_ +#define QEXTWINEVENTNOTIFIER_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qextserialport_global.h" + +class QextWinEventNotifierPrivate; +class QEXTSERIALPORT_EXPORT QextWinEventNotifier : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextWinEventNotifier) + +public: + explicit QextWinEventNotifier(QObject *parent = 0); + explicit QextWinEventNotifier(HANDLE hEvent, QObject *parent = 0); + ~QextWinEventNotifier(); + + void setHandle(HANDLE hEvent); + HANDLE handle() const; + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); + +Q_SIGNALS: + void activated(HANDLE hEvent); + +protected: + bool event(QEvent * e); + +private: + Q_DISABLE_COPY(QextWinEventNotifier) + QextWinEventNotifierPrivate * d_ptr; +}; + +#endif // QEXTWINEVENTNOTIFIER_P_H_ diff --git a/GC-3.6.1-T3/src/README b/GC-3.6.1-T3/src/README new file mode 100644 index 0000000..3ee05e9 --- /dev/null +++ b/GC-3.6.1-T3/src/README @@ -0,0 +1,503 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Version 3.0 is a near-complete rewrite of the C++ code fixing all known bugs. +The other major enhancement is native Mac OSX support (including older 32 bit Intel 10.5). + +The code was tested with real milling projects using the Shapeoko and works +pretty well. For a list of possible future enhancements, see file TODO. + +Prebuilt binaries/installers can be found on github's download section for this +project (GrblHoming). Alternately, if you download the (a) Qt SDK from Nokia or +(b) the Qt source from Qt Project along with the standalone Qt Creator, you can +build from source. + +Details on how to do this can be found here: +http://zapmaker.org/ + + +V3.6.1->T3 (LETARTARE proposals) + +* 3.6.1-T2 + + +- Use 'Check' mode Grbl + + + + +V3.6.1->T2 (LETARTARE proposals) + +* 3.6.1-T1 + + +- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + + +V3.6.1->T1 (LETARTARE proposals) + +- Improved to the same card 3 and 4 axis detection +- Displays the line numbers of the file if no number exists +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, + 2- Four axes 0845, future 0.8c1 (0.8c1 to 4 axes) + +V3.6.1 +Executable release rollup + +IMPORTANT: Manual/Jog control defaults to new mode which doesn't update the position. +This was done to ensure that jog motions are as fast as possible. However, if you want +to have the original 3.5.1 and earlier behavior, go to Tools | Options | Display +and change radio button to "Always Request but without Idle Check". Sending files +still updates position, it is only manual/jog that does not. + +V3.6 +Enhancements +- Options dialog is now tabbed to better fit widgets +- Ability to handle 4th axis as either A, B, or C (requires correct grbl version for axis), + please see https://github.com/zapmaker/GrblHoming/issues/56 and + https://github.com/LETARTARE/Grbl_with_Arduino/tree/master/Grbl845Mega2560 + which is the A,B,C,U,V,W axes grbl variant. +- LETARTARE: Added UVW axes +- #45: Added ability to completely or partially turn off querying position from grbl to + help improve responsiveness. The new default is to disable waiting for idle before a + jog or manual command, which speeds up those operations. Additional, you can + completely turn it off position reporting during jog or manual control which will + result in light-greyed LCD numbers. A button to query the position has been + added, which will provided up-to-date position at the time the button is pushed. + Look in Options | Display tab for new button options. You can also set the rate + at which the query takes place from 0.5-10 seconds, if it is enabled. Setting a time + that is too long may result in the system waiting too long to retrieve the final position + before control is handed back. Also, the current position dot on the Visualizer turns + from red to green when the position is not accurately known to match the color of the path. +Bug fix +- Fixed fourth axis adjust buttons and coordinate display greyed out when they shouldn't + be (under specific operating circumstances). + +V3.5.1 +Enhancements +- Made subtle modifications to the command preload when sending a file so that the + command queue on grbl is as full as possible. Previously we were depleting the + queue and then filling it again. This has possible negative performance implications, + although testing shows them to be negligible, probably because we immediately send + a command after the last ok is received. +- The status list view now supports only a maximum of 200 items when active. This was + done for the slower processors like the raspberry pi to prevent excessive CPU usage + when many commands lines exist in a file. When the user grabs the scrollbar, all + items are restored back into the view. +- A new progress bar has been added showing the current items in the grbl queue during + a file send. If the number of items for some reason drops to 0 the label text will + flash red. For this 0 count to occur is a very rare event. +- Added the ability to set the delay between sending of characters to grbl. The theory + is that grbl can drop characters if the sending computer is very fast. There is still + some debate on whether this is happening, so I provided the ability to set this value + in the options from 0 to 20 ms. Note: The default of 0 ms delay is back, like in 3.4.6 + and unlike in 3.5 which has a hardcoded 10 ms delay. +Bug fix +- Modified the status window redraw to always ensure items show on the bottom when the + redraw timer expires. + +V3.5 +Bug fix +- For very fast computers, they send characters with virtually no delay between which + requires grbl to process the serial port as fast as it can. The problem is that + grbl has an interrupt service routine that can slow down the processing it does + of incoming characters on its serial port. This causes lost characters in its input + buffer, which results in hung gcode file processing or errors. To fix, I have added + a slight delay (10ms) after sending every character. This has been confirmed to + solve the lost character problem on grbl. + +V3.4.6 +Bug fix +- Scrolling of content now completes each time. Previously there were conditions where + auto-scrolling would fail and you would have to manually scroll to see some lines +- Fixes to support 4-axis Mega2560 (tested with actual Mega2560 running 0.81 c-axis). + Includes fix to command filter to support A/B/C axis commands +- Fixed minor issue where connecting with wrong baud rate can cause long delay before + you can again control the Open/Close button +- Incorporated more translations from LETARTARE + +V3.4.5 +Bug fix +- When modifying the ui files for auto widget rescaling, broke a number of programmatically + greyed out widgets, mainly, you couldn't reopen the port after closing it. Now those are fixed. + +Enhancement +- Incorporated LETARTARE's localization file for French so that it is possible to see + locale-specific text in the installed version of Grbl Controller (see trlocale subdir) + +V3.4.4 +Bug fix +- Incorporated LETARTARE's 4-axis (C-axis) implementation - thanks! (Issues #29 and #34) + (added option to enable/disable 4-axis mode) - potential issue that needs investigating: + Can this be enabled on the fly or if it requires restart of Grbl Controller? +- Incorporated LETARTARE's translation support (French) +- Incorporated LETARTARE's fix for command history (#26) +- Incorporated Kosme's fix to issue #17 (#33). Z axis slider now moves in 0.1 inch increments + when in inches mode. +- Incorporated Kosme's fix to issue #27. If work units are inches, now displays inches, + not mm. +Enhancements +- Ability to resize entire screen and widgets. Scales down to close to 600x400 pixels + for tiny displays; also remembers last size and position of screen. (#37) +- Incorporated Kosme's fix to issue #10 (#33). Popup appears to remind you to zero position + if starting a new job. + +V3.4.3 +Bug fix +- Unsupported G43/G44 commands include following Z command which causes problems when + left standalone. The entire line must be removed. +- Now treat M2 and M30 as unsupported as they cause grbl lockup when using aggressive + preloading. +- Moved program version define into its own header file so fewer files need recompiling + with a version change. + +V3.4.2 +Bug fix +- If a gcode command line is an arc with X,Y,Z and z-rate limiting enabled, fixed to + properly split the z rate to not use the G2 command and use G1 instead as grbl + was generating an error with the G2. + +V3.4.1 +Code sync +- Fixes to code now allows code to compile under Qt5 without error and also resolves + some localization issues. Continues to properly compile under Qt4 also. No normally + noticable functional differences. + +V3.4 +Enhancements +- Z-axis slider now allows rapid control of Z-axis positioning. This feature is still + being evaluated for proper behavior due to some user-interface issues. + If you run into trouble, please report a bug. +- All axis control buttons have been permanently enabled regardless of whether or not an + axis command is in progress - this allows more rapid updating. Note - there is no error + checking for the case of entering too many commands for the Grbl buffer. This is unlikely + but possible. +- Now supports setting of baud rates from 9600 to 115200 +- Aggressive preload enabled is now the default. If the user upgraded from an older + Grbl Controller and had it disabled, a popup will warn them that it is being enabled. + They still have the option to disable, if desired +- Logging is turned on by default (only for new installs) +- All detected errors are collected and displayed after a file is run in the status view +- If filtering unsupported commands, all commands filtered out are listed after the file + is run. +- Logging now gives the line number of each command sent from the file and the corresponding + ok or error also contains the line number. +- An option has been provided to reduce the precision of lines that exceed Grbl's line buffer, + which by default is 50 characters. The code removes the arguments with the greatest precision + first and ending with at least one decimal place of precision. Errors are generated if it + cannot remove sufficient precision for the available buffer space. The buffer size on Grbl + is configurable in the options, as older Grbls have 50 characters and newer have 70. + +Bug Fixes +- If Grbl stops responding (waiting for an ok), Soft Reset Grbl now functions correctly + (so you can soft reset without having to restart Grbl Controller). This affects aggressive + preload mode only. +- Commands to start/stop coolant coupled with dwell commands and aggressive preload cause + Grbl's modal logic to stop sending OK responses (on purpose). This was solved by waiting + for the OK of the coolant off before sending additional commands. It is not clear whether + this fixes all possible such modal problems, so use carefully and report any anomalies. + +V3.3.9 +Enhancement +- We now are able to remember and restore ports that are not visible to QextSerialEnumerator + so that user doesn't have to retype the ghost port every time they start Grbl Controller. + +V3.3.8 +Enhancement/Fix +- Modified code that detects presence of Grbl upon serial port opening, the original + assumption was that we would get the version string upon serial port open, but some + Arduino-compatible boards like the AlaMode did not behave this way. Fixed the code + so that if there is no response upon serial port open, we send a soft reset (Ctrl-X) + and wait for the version string. Tested to work with AlaMode and with traditional + Ardiuno Uno. + +V3.3.7 +Enhancement +- Made COM port field editable + +V3.3.6 +Bug Fixes +- Fixed decimal on the LCD display to always show three decimal points so that + it is easier to read the display (it doesn't jump around anymore). Tested to + hold up to 9999.999 and -9999.999, which should handle 20 x 20 meter Shapeokos. + +V3.3.5 +Bug Fixes +- Changed how we detect Grbl upon opening on COM port. + ** NOTE ** This change will probably break older V0.51 capability + Previously we sent out a linefeed to trigger a response, however, this caused problems + on some arduino variants and would not result in correct sync with the controller. + Fixed by no longer sending the linefeed and instead just watch the port for Grbl response. +- Changed the default "short" wait timeout to 2 seconds from 1 second in case of slow responses. + +V3.3.4 +Enhancements +- Added option checkbox to choose to filter gcode or send it as-is to the controller. The + filtering removes gcode that is not supported in v0.8 of Grbl, which reduces the error + reports from Grbl. Some files generate unexpected codes like G91.1 which can actually + affect the motion in unexpected ways- filtering helps prevent this from happening. + + IMPORTANT: The default is to not filter, which is different than previous versions! This + may result in unexpected command processing. If using advanced gcodes, perform an air run + first. + +Bug Fixes +- Mach3 files have no whitespace in the gcode. Fixed code to handle such files. Affects + the Visualizer only. +- The filtering logic was fixed to properly filter gcode when sending a file - previous + versions would filter out gcode that Grbl supported. +- Changed validator for double (i.e. float) values so that code compiles under older Qt + versions. +- Changed Visualizer display to say Width-X and Height-Y instead of Width and Depth to make + it less confusing. + +V3.3.3 +Bug Fix +- Modal G arc (where G2 or G3 is specified once followed by X/Y/I/J) was failing for certain + arc combinations in the visualizer due to resetting the cw to false with each line. Fixed + to not reset the cw variable and retain from previous lines. + +V3.3.2 +Bug Fix +- G-command can now be set once and multiple X/Y commands then issued on lines following + (Allows "ShapeOko_Calibration_Pattern_01b.ngc to be rendered) + +V3.3.1 +Bug Fixes +- Hardened the visualizer's file parser so that it supports spaces between positional + arguments and values +- No longer skips last line in file if that line contains a valid command +- No longer crashes if line contains one or more stray whilespace characters +- Also accepts semi-colon as a comment line (in addition to existing open paren and percent) + +V3.3 +Enhancemetns +- Added "Visualizer" feature. It is now possible to see top-down view of the + file to be milled. + * Shows actual file units (inches or millimeters) independent of coordinate display + * Auto-scaling + * Supports limited subset of commands (G0/G1/G2/G3) + * Visualizer on tab panel shared with Axis control + * Actual last spindle cutter position is shown; auto-scales to include both cutter + and file + * When file is being run, overlay of all commands sent to Grbl is shown in green + * Displays dimensions of design, along with design's width and depth in file's units + +V3.2 +Enhancements +- Support for "Aggressive Preload" of commands when sending file to Grbl + * File's lines are sent to Grbl as fast as Grbl can take it, allowing + Grbl to optimize acceleration. Some files have been observed to take + 1/3 the time to complete! + * Modeled after Grbl's own python script (computes/predicts how much + space is available in Grbl's input buffer) + * Due to the additional processing, CPU usage is greater than normal mode + and it has been optimized to run fine on a Raspberry Pi + * Normal (non-preload) mode is the default + * Response processing code now waits until a line has been received rather + than collect a long stream to behave like the python script + * LCD updates have been set to be roughly once every second independent + of rate of line sends/preloads +- Z-rate limit feature now includes default xy rate setting + * Z rate limiting only occurs during file sends. If z is included with x&y + then they are split into two commands automatically and the xy rate setting + is used for the xy portion + * Since feed rate is modal, code will fix any subsequent xy items that are + missing feed rate specifiers (cambam correctly adds them, but others may not) +- Replaced basic logging with Log4Qt logging capabilities. + * Support for error, warning, info, debug message types. All messages are timestamped. + * More diagnostic messages added, mainly around sending and receiving from com ports + * Only error and warning are displayed in release build, all are displayed in debug. + * If the user enables file logging, all messages are stored regardless of build type + * File is output to user's home folder + * If you enable or disable logging to file, you must restart Grbl Controller + * You can split out diagnostic from status messages by grepping for (DIAG) or (STATUS) +- Changed menus so that the first menu is File > Exit. Menus now use accelerators + +Bug Fixes +- Fixed problems with z-rate limit feature, previous version was not implemented correctly. +- Fixed subtle issues with sending bytes to COM port + * On really fast Windows PCs, the default timeout values would occasionally result in + a line not being sent. This was fixed by changing the write timeout from 10 to + 500 ms by hardcoding it into the QextSerialPort library. This was only observed in + aggressive preload mode, never in normal mode. + +Known issues +- New reponse line detect mode requires more processing because mainly of the faster + stream of status messages. To get around this, certain features have been disabled + in the status view so that CPU usage is manageable on the Raspberry Pi, specifically + the horizontal scroll bar is not available. Turn on file logging if you wish to see + the entire line. +- When using aggressive preload, any error messages returned by Grbl are not synced + to sent messages (they come back randomly). This can be confusing. +- If running preload, it can take longer for steppers to stop after a Stop command + due to the number of items in Grbl's queue. The only way to stop sooner is to + press Close / Reset button +- Under exteme CPU loads (unlikely to occur with recent optimizations), the "runtime" + display does not display accurate times, oddly, it displays the same time that would + occur if not under load + +Tested on cardboard using file provided by user: +- Windows 7 64bit, 0.8c, aggressive mode (~4 minute run) +- Windows 7 64bit, 0.8c, normal mode (~10 minute run) +- Windows 7 64bit, 0.8a, aggressive mode(~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode (~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode and z-limit (~6 minute run) + +V3.1.2 (unofficial release, optimizations for Raspberry Pi) +Enhancements +- Optimized multiline write to status window to use faster list-based approach +- Removed unnecessary main window repaint after every line added to status window +- Fixed options window text positioning so that it appears proper on the pi + +V3.1.1 (unofficial release, adjustments for Raspberry Pi) +Enhancements +- Changed measurement units in LCD from "inches" to "in" (cosmetic) +- Shortened text and adjusted main window layout for the text size on the pi + +V3.1 +Enhancements +- Supports Grbl 0.8c. Still supports 0.8a. 0.51 is supported but without LCDs. +- Grbl settings dialog is now a table of dynamic length depending on # of params. +- LCD position data is now obtained from Grbl and is *not* computed +- Added LCD displays for both machine and work coordinates +- Cycling of Grbl via COM port toggling has been completely removed, except + that Close button has now been renamed Close / Reset. +- Position data on Grbl is persisted as long as possible to allow for repositioning, etc. +- Zero work coordinates has been added (G92) +- Go-to-home feature added (lifts tool 5 mm and traverses to x=0, y=0) +- Option to put manual command (back) into absolute mode after jog button command +- Grbl Soft reset (Ctrl-X) button added +- Z-axis rate limiting capability added. Only affects file, not jog or manual commands. +- User is required to specify which measurement mode they are using, mm or inches: + * Default is millimeters + * Grbl is configured to operate in either mm or inches + * If a file is sent in inches and user is in mm, it will auto-restore to mm + after the file has been sent (and vice-versa, mm->inches) +- 0.8c enhancements: + * Displays current Grbl state (i.e. Run, Idle, etc.) + * LCDs display whether values are in inches or millimeters + * Unlock Grbl button added ($X) + * Determines and sets parser state for current mm/inch command mode ($G) + * Determines and sets coordinate units via $13 +- Removed annoying "No movement expected for command" message +- Flags that cross threads have been changed to use QAtomicInt +- Version is now shown in title bar +- A basic log file feature has been added +- Runs on the Raspberry Pi! + +Known Issues +- The registry key product name has been changed from GCodeSender to GrblController + *** WARNING: Old settings are not migrated **** +- Switching between millimeters and inches works, but has not been fully tested +- Go to home has not been fully tested with inches mode +- Manually issuing $13 or G20/G21 can confuse the program + +V3.0 +Enhancements +- Nearly a full code rewrite to ensure ease-of-use and robustness +- Percentage complete progress bar for files; also shows time elapsed sending file. +- Reset button now cycles COM port which causes Arduino to stop steppers and + reinitialize position to 0,0,0 (No more manual Auduino resets!) +- Settings configurations are now stored using QSettings class for platform independence. +- Only available COM ports are now shown. Uses third-party QextSerialPort library. +- App remembers last COM port used, last folder, last file extension used after restart +- Ability to configure wait-for-response time +- Status list window now shows both sent and received data +- Error responses are ignored during file send (nearly 100% of the time they are not important) +- Z-jog speed using buttons is configurable +- Radio buttons to select mode have been removed in favor of enabling/disabling widgets based + on current context. This simplifies usage. +- Popups have been removed in favor of writing errors to status list window + +Bug fixes +- Overall code hardening +- Properly implementing Qt signals and slots across the board + +Build verification +- Windows 7 64 bit using MinGW +- Inno Setup for Windows, installs successfully on Windows 7 +- Mac OSX Mountain Lion, target 64 bit and 32 bit executables +- Qt Mac installer successfully installs and runs on Mountain Lion and 10.5 32 bit Intel +- Linux: Builds successfully on Debian 6, Ubuntu 12.10 + +V2.1x1 + +NOTE: Changes were only focused on Arduino GRBL capabilities with the Shapeoko, so +things like Tool Change were not tested. + +Enhancements +- Improved handling of response code - this is the most significant change as it +ensures reliable send/response handling when sending a file to the Grbl processor. +- Manual command now allows hitting return and command is sent. No need to press Go. +- Default job step size changed from 0.01 to 1 mm +- Compiles and runs under Linux now (tested with Debian and latest Qt) +- Works with old 168 Arduino processor (except that old code is buggy and not recommended) +- Disabled "go to home at end of job". The arduino code doesn't handle it correctly +and mills straight back into and through your work. Checkbox in settings has no effect. + +Bug fixes +- Fixed crash when options file is not present the first time run +- Fixed crash when trying to get GRBL settings from device +- Settings work with 168 (8 settings) and 328 processors (10 settings) +- Fixed Stop to call proper routine stopsig - now Stop button works correctly + +------------------------------------------------------------- +Fork by Zapmaker at this rev +------------------------------------------------------------- +v2.1a + +Bug fixes + +- Corrected an issue that caused the program to crash if the g-code had blank lines. + +V2.1 + +New Features + +- Gcode that is valid but is not recognized by GRBL gets filtered and it is not sent. + +Bug fixes + +- Corrected an issue that prevented manually sent Gcode for being displayed correctly. +- Corrected an issue with the images not displaying. + +V2.0 Major release + +- Improved the port handling reducing opening and closing frecuency. +- Added the ability to type and send commands directly. +- Support for tool change instructions. If enabled it pauses execution, raises the spindle, goes to a fixed location for toolchange, waits for tool change, and continues excecution. +- Added About window. + +V1.0c Minor + +Bug fixes + +- Corrected a problem when adjusting axis that caused all axis to move at the same time. Caused by grbl starting in incremental programming. + +V1.0b Minor + +Bug fixes + +- Corrected a bug in the adjusting script. + +V1.0a Minor + +Bug fixes + +- Fixed a bug reading some file formats that avoided the dials from updating. + diff --git a/GC-3.6.1-T3/src/TODO b/GC-3.6.1-T3/src/TODO new file mode 100644 index 0000000..c73577e --- /dev/null +++ b/GC-3.6.1-T3/src/TODO @@ -0,0 +1,68 @@ +This file contains enhancements the developer and user community would like to see: + + +Planned for 3.4.x +- Bug fixes +Planned for 3.5: +- (What is the problem here? Run is shown, then Idle when stopped) Detect machine state at end of run and display it properly (i.e. "transitioning" when it is still moving) +- Every second or so, if not scrolled to bottom, scroll to bottom of status +- Allow reload of same file from same location +- After a run, suppress $$ output with a single line +- Report system settings at beginning of log file. Include OS. +- Can't see drill holes under axis, move axes under toolpaths? +- Create test plan (i.e. verify all text appears correctly on all platforms) +- Display detected version of Grbl +- Speed limit for X and Y like the Z speed limit + +Planned for 3.6: +- Implement support for Grbl 0.8c "homing" feature (using limit switches) +- UI support for homing limit switches +- Restore "Tool change" feature, including popup dialog +- Option to engage stepper lock (include fade out rate setting - start time of fade, end time of fade, requires hw mod) +- Display current feedrate in mm/sec or in/sec +- Add additional rs232 error logging value (-1 is not very useful) +- Analyze file ahead of time and determine if it will go beyond extents +- Update manual since 3.3 + +Planned for 3.7 +- Switch to compiling using Qt 5 +- Auto-scale widgets to full screen size +- Localization ready code +- Don't fail on timeout waiting for command - let user continue if they want +- Pick up from where left off (if GC dies due to PC falling asleep, etc.) +- Look at all hardware connection options of Grbl on the shield and make + sure that we have some way to control those, i.e. spindle control. +- Clear log button +- Print current GRBL settings +- Add option to always use last working port, even if it isn't currently connected + +Primary: +- Save/Load current GRBL settings from disk +- Suppress some bookkeeping output from the status window +- Add local Help linked from main screen and options dialog +- When parsing for visualizer, if bad value arg, warn user +- If nothing appears in visualizer, attempt to diagnose and explain to user +- If get error from grbl, provide command that generated error on same line +- Allow user to choose how to handle unspecified units in file for visualizer +- Fix Zero position next to begin? +- Show drill holes as larger dots? +- Build in calibration pattern +- Build in "flatten table feature" +- File viewer +- Estimate bounds based on both toolpaths and tool diameter, not just toolpaths + +Secondary: +- Make GC generic to support controllers other than Grbl +- Recent files list under 'Files' +- Restore "Favorites" feature +- Provide diagnostic response view +- Provide counter showing time waiting for a response if time > 5s +- Estimated time to completion (this can acutally be computed from feedrates) + +Notes pulled from https://github.com/grbl/grbl/issues/202 + +Move Z to upper clear position. (<- another parameter?) +Stop the spindle. +X and Y to the change tool coordinates. +A way to adjust new Z (manual for me) and perhaps new speed for the spindle (manual for me). +When ready (~) start cycle? to continue with the new tool with the same X and Y initial coordinates than the last tool. \ No newline at end of file diff --git a/GC-3.6.1-T3/src/about.cpp b/GC-3.6.1-T3/src/about.cpp new file mode 100644 index 0000000..f3b8df1 --- /dev/null +++ b/GC-3.6.1-T3/src/about.cpp @@ -0,0 +1,26 @@ +/**************************************************************** + * about.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "about.h" +#include "version.h" +#include "ui_about.h" + +About::About(QWidget *parent) : + QDialog(parent), + ui(new Ui::About) +{ + ui->setupUi(this); + + ui->labelProductAndVersion->setText(GRBL_CONTROLLER_NAME_AND_VERSION); +} + +About::~About() +{ + delete ui; +} diff --git a/GC-3.6.1-T3/src/about.h b/GC-3.6.1-T3/src/about.h new file mode 100644 index 0000000..e8f7291 --- /dev/null +++ b/GC-3.6.1-T3/src/about.h @@ -0,0 +1,32 @@ +/**************************************************************** + * about.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef ABOUT_H +#define ABOUT_H + +#include +#include "definitions.h" + +namespace Ui { +class About; +} + +class About : public QDialog +{ + Q_OBJECT + +public: + explicit About(QWidget *parent = 0); + ~About(); + +private: + Ui::About *ui; +}; + +#endif // ABOUT_H diff --git a/GC-3.6.1-T3/src/about.ui b/GC-3.6.1-T3/src/about.ui new file mode 100644 index 0000000..eef05b7 --- /dev/null +++ b/GC-3.6.1-T3/src/about.ui @@ -0,0 +1,154 @@ + + + About + + + + 0 + 0 + 414 + 214 + + + + About... + + + + + 40 + 170 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + 10 + 30 + 151 + 61 + + + + + + + Qt::PlainText + + + :/img/logotiny.PNG + + + + + + 180 + 70 + 201 + 91 + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + true + + + + + + 180 + 10 + 211 + 51 + + + + + 12 + 75 + true + + + + Grbl Controller + + + + + + 330 + 10 + 71 + 16 + + + + + + + + + + 20 + 120 + 130 + 33 + + + + + + + :/img/zapmaker-logo-130.png + + + + + + + + + buttonBox + accepted() + About + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + About + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GC-3.6.1-T3/src/arcitem.cpp b/GC-3.6.1-T3/src/arcitem.cpp new file mode 100644 index 0000000..4f58670 --- /dev/null +++ b/GC-3.6.1-T3/src/arcitem.cpp @@ -0,0 +1,120 @@ +#include "arcitem.h" + +ArcItem::ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw1, int index1) + : ItemToBase(index1), sx(sx1), sy(sy1), ex(ex1), ey(ey1), centx(centx1), centy(centy1), cw(cw1), radius(0), angleStart(0), angleDelta(0) +{ +} + +PosItem ArcItem::computeExtents() +{ + PosItem extents(sx, sy, ex, ey); + + radius = qSqrt(((sx - centx) * (sx - centx)) + ((sy - centy) * (sy - centy))); + + if (cw) + { + double angle1 = qAtan2(ey - centy, ex - centx); + double angle2 = qAtan2(sy - centy, sx - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + else + { + double angle1 = qAtan2(sy - centy, sx - centx); + double angle2 = qAtan2(ey - centy, ex - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + + // sample points along the curve + double angleEnd = angleStart + angleDelta; + for (double angle = angleStart; + (angleDelta < 0 ? angle > angleEnd : angle < angleEnd); + angle += (angleDelta < 0 ? -0.4 : 0.4)) + { + double x = qCos(angle) * radius + centx; + double y = qSin(angle) * radius + centy; + + PosItem curr(x, y, x, y); + + // expand rectange if it exceeds our last rectangle + extents.expand(curr); + } + + return extents; +} + +void ArcItem::addToPath(QPainterPath& path) +{ + // need to convert our coordinates into arcTo arguments (rectangle boxes and angles, etc.) + // Also, we are at this point in screen coordinates, not machine coordinates, i.e. Y positive is down! + + // first, we know for a fact that we are dealing with a circular arc, not an ellipse + // (code could be put here to verify that is true) + // Thus our radius is also our bounding box determined from the center of the arc/circle + + if (cw) + { + path.moveTo(screenX(sx), screenY(sy)); + } + else + { + path.moveTo(screenX(ex), screenY(ey)); + } + + double x = centx - radius; + double y = centy + radius; + double wd = radius * 2; + double ht = wd; + + double fx = screenX(x); + double fy = screenY(y); + double w = wd * scale; + double h = ht * scale; + + double angleStartDeg = toDegrees(angleStart); + double angleDeltaDeg = toDegrees(angleDelta); + + path.arcTo(fx, fy, w, h, angleStartDeg, angleDeltaDeg); + + path.moveTo(screenX(ex), screenY(ey)); +} + +void ArcItem::moveToFirst(QPainterPath& path) +{ + // not applicable! generate error! + Q_UNUSED(path); +} + +double ArcItem::getXScr() +{ + return screenX(ex); +} + +double ArcItem::getYScr() +{ + return screenY(ey); +} + +double ArcItem::getXRaw() +{ + return ex; +} + +double ArcItem::getYRaw() +{ + return ey; +} + +double ArcItem::toDegrees(double rad) +{ + return 360 * rad / TWO_PI; +} diff --git a/GC-3.6.1-T3/src/arcitem.h b/GC-3.6.1-T3/src/arcitem.h new file mode 100644 index 0000000..c992472 --- /dev/null +++ b/GC-3.6.1-T3/src/arcitem.h @@ -0,0 +1,39 @@ +#ifndef ARCITEM_H +#define ARCITEM_H +#include +#include "itemtobase.h" + +#define TWO_PI (2 * 3.1415926) + +class ArcItem : public ItemToBase +{ +public: + ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw, int index); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + + double toDegrees(double rad); + +private: + double sx; + double sy; + double ex; + double ey; + double centx; + double centy; + bool cw; + + double radius; + double angleStart; + double angleDelta; + +}; + +#endif // ARCITEM_H diff --git a/GC-3.6.1-T3/src/atomicintbool.cpp b/GC-3.6.1-T3/src/atomicintbool.cpp new file mode 100644 index 0000000..630dc3c --- /dev/null +++ b/GC-3.6.1-T3/src/atomicintbool.cpp @@ -0,0 +1,22 @@ +#include "atomicintbool.h" + +AtomicIntBool::AtomicIntBool(int newValue /* = 0 */) + : value(newValue) +{ +} + +void AtomicIntBool::set(int newValue) +{ + value.fetchAndStoreRelaxed(newValue); +} + +int AtomicIntBool::get() +{ + return value.fetchAndAddRelaxed(0); +} +/* +int AtomicIntBool::getAndClear() +{ + return value.fetchAndStoreRelease(0); +} +*/ diff --git a/GC-3.6.1-T3/src/atomicintbool.h b/GC-3.6.1-T3/src/atomicintbool.h new file mode 100644 index 0000000..93f08e0 --- /dev/null +++ b/GC-3.6.1-T3/src/atomicintbool.h @@ -0,0 +1,22 @@ +#ifndef ATOMICINTBOOL_H +#define ATOMICINTBOOL_H + +#include + +// we wrap QAtomicInt because it is possible to accidentally +// access the non-atomic operations of the class (look at the +// header for QAtomicInt to see what I mean, and thus setting +// a value directly against one of these variables will access +// the non-atomic method) +class AtomicIntBool +{ +public: + AtomicIntBool(int newValue = 0); + void set(int newValue); + int get(); + +private: + QAtomicInt value; +}; + +#endif // ATOMICINTBOOL_H diff --git a/GC-3.6.1-T3/src/clean.bat b/GC-3.6.1-T3/src/clean.bat new file mode 100644 index 0000000..8a41d93 --- /dev/null +++ b/GC-3.6.1-T3/src/clean.bat @@ -0,0 +1,12 @@ +rem clean.bat +rem by LETARTARE + +mingw32-make clean + +del release\GrblController.exe + +del debug\GrblController.exe + +cd .. + + diff --git a/GC-3.6.1-T3/src/controlparams.cpp b/GC-3.6.1-T3/src/controlparams.cpp new file mode 100644 index 0000000..7e7ed6a --- /dev/null +++ b/GC-3.6.1-T3/src/controlparams.cpp @@ -0,0 +1,14 @@ +#include "controlparams.h" + +ControlParams::ControlParams() + : waitTime(LONG_WAIT_SEC), zJogRate(DEFAULT_Z_JOG_RATE), + useMm(true), zRateLimit(false), zRateLimitAmount(DEFAULT_Z_LIMIT_RATE), + xyRateAmount(DEFAULT_XY_RATE), + useAggressivePreload(false), filterFileCommands(false), + reducePrecision(false), grblLineBufferLen(DEFAULT_GRBL_LINE_BUFFER_LEN), + useFourAxis(false), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS), + fourthAxisType(FOURTH_AXIS_A), usePositionRequest(true), + positionRequestType(PREQ_ALWAYS_NO_IDLE_CHK), postionRequestTimeMilliSec(DEFAULT_POS_REQ_FREQ_MSEC), + waitForJogToComplete(true) +{ +} diff --git a/GC-3.6.1-T3/src/controlparams.h b/GC-3.6.1-T3/src/controlparams.h new file mode 100644 index 0000000..0328f2d --- /dev/null +++ b/GC-3.6.1-T3/src/controlparams.h @@ -0,0 +1,34 @@ +#ifndef CONTROLPARAMS_H +#define CONTROLPARAMS_H + +#include "definitions.h" + +#define SHORT_WAIT_SEC 2 +#define LONG_WAIT_SEC 100 + +class ControlParams +{ +public: + ControlParams(); + +public: + int waitTime; + double zJogRate; + bool useMm; + bool zRateLimit; + double zRateLimitAmount; + double xyRateAmount; + bool useAggressivePreload; + bool filterFileCommands; + bool reducePrecision; + int grblLineBufferLen; + bool useFourAxis; + int charSendDelayMs; + char fourthAxisType; + bool usePositionRequest; + QString positionRequestType; + int postionRequestTimeMilliSec; + bool waitForJogToComplete; +}; + +#endif // CONTROLPARAMS_H diff --git a/GC-3.6.1-T3/src/coord3d.cpp b/GC-3.6.1-T3/src/coord3d.cpp new file mode 100644 index 0000000..b89d175 --- /dev/null +++ b/GC-3.6.1-T3/src/coord3d.cpp @@ -0,0 +1,11 @@ +#include "coord3d.h" + +Coord3D::Coord3D() + : x(0.0), y(0.0), z(0.0), fourth(0.0), stoppedZ(true), sliderZIndex(0) +{ +} + +bool Coord3D::operator==(const Coord3D& rhs) +{ + return (x == rhs.x && y == rhs.y && z == rhs.z && fourth == rhs.fourth) ; +} diff --git a/GC-3.6.1-T3/src/coord3d.h b/GC-3.6.1-T3/src/coord3d.h new file mode 100644 index 0000000..aac648e --- /dev/null +++ b/GC-3.6.1-T3/src/coord3d.h @@ -0,0 +1,23 @@ +#ifndef COORD3D_H +#define COORD3D_H + +#include + +class Coord3D +{ +public: + Coord3D(); + bool operator==(const Coord3D& rhs); + +public: + float x; + float y; + float z; + float fourth; + bool stoppedZ; + int sliderZIndex; +}; + +Q_DECLARE_METATYPE ( Coord3D ) + +#endif // COORD3D_H diff --git a/GC-3.6.1-T3/src/definitions.h b/GC-3.6.1-T3/src/definitions.h new file mode 100644 index 0000000..527d25c --- /dev/null +++ b/GC-3.6.1-T3/src/definitions.h @@ -0,0 +1,71 @@ +/**************************************************************** + * definitions.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#include +#include +#include +#include "atomicintbool.h" + +#define DEFAULT_WAIT_TIME_SEC 100 + +#define DEFAULT_Z_JOG_RATE 260.0 +#define DEFAULT_Z_LIMIT_RATE 100.0 +#define DEFAULT_XY_RATE 2000.0 + +#define DEFAULT_GRBL_LINE_BUFFER_LEN 50 +#define DEFAULT_CHAR_SEND_DELAY_MS 0 + +#define MM_IN_AN_INCH 25.4 +#define PRE_HOME_Z_ADJ_MM 5.0 + +#define REQUEST_CURRENT_POS "?" +#define SETTINGS_COMMAND_V08a "$" +#define SETTINGS_COMMAND_V08c "$$" +/// LETARTARE T3 +#define REQUEST_MODE_CHECK "$C" +/// +#define REQUEST_PARSER_STATE_V08c "$G" +#define SET_UNLOCK_STATE_V08c "$X" + +#define REGEXP_SETTINGS_LINE "(\\d+)\\s*=\\s*([\\w\\.]+)\\s*\\(([^\\)]*)\\)" + +#define OPEN_BUTTON_TEXT "Open" +#define CLOSE_BUTTON_TEXT "Close / Reset" + +#define LOG_MSG_TYPE_DIAG "DIAG" +#define LOG_MSG_TYPE_STATUS "STATUS" + +/// LETARTARE : one axis choice U or V or W or A or B or C +#define FOURTH_AXIS_U 'U' +#define FOURTH_AXIS_V 'V' +#define FOURTH_AXIS_W 'W' +/// <-- +#define FOURTH_AXIS_A 'A' +#define FOURTH_AXIS_B 'B' +#define FOURTH_AXIS_C 'C' + +#define PREQ_ALWAYS "always" +#define PREQ_ALWAYS_NO_IDLE_CHK "alwaysWithoutIdleChk" +#define PREQ_NOT_WHEN_MANUAL "notWhenManual" + +#define DEFAULT_POS_REQ_FREQ_SEC 1.0 +#define DEFAULT_POS_REQ_FREQ_MSEC 1000 + +extern AtomicIntBool g_enableDebugLog; + +void status(const char *str, ...); +void diag(const char *str, ...); +void err(const char *str, ...); +void warn(const char *str, ...); +void info(const char *str, ...); + +#endif // DEFINITIONS_H diff --git a/GC-3.6.1-T3/src/fixqt4headers.pl b/GC-3.6.1-T3/src/fixqt4headers.pl new file mode 100644 index 0000000..bb719f7 --- /dev/null +++ b/GC-3.6.1-T3/src/fixqt4headers.pl @@ -0,0 +1,170 @@ +#!/usr/bin/env perl +############################################################################# +## +## Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +## Contact: http://www.qt-project.org/legal +## +## This file is part of the porting tools of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and Digia. For licensing terms and +## conditions see http://qt.digia.com/licensing. For further information +## use the contact form at http://qt.digia.com/contact-us. +## +## 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, Digia gives you certain additional +## rights. These rights are described in the Digia Qt LGPL Exception +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3.0 as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL included in the +## packaging of this file. Please review the following information to +## ensure the GNU General Public License version 3.0 requirements will be +## met: http://www.gnu.org/copyleft/gpl.html. +## +## +## $QT_END_LICENSE$ +## +############################################################################# + + +use Cwd; +use File::Find; +use File::Spec; +use IO::File; +use Getopt::Long; +use strict; +use warnings; + +my $dry_run = 0; +my $help = 0; +my $stripModule = 0; +my $fixedFileCount = 0; +my $fileCount = 0; +my $verbose = 0; +my $qtdir = $ENV{'QTDIR'}; + +my $USAGE=< : Point to Qt 5's qtbase directory +EOF + +if (!GetOptions('dry-run' => \$dry_run, 'help' => \$help, + 'strip-modules' => \$stripModule, 'verbose' => \$verbose, 'qtdir:s' => \$qtdir) + || $help) { + print $USAGE; + exit (1); +} + +my %headerSubst = (); +my $cwd = getcwd(); + +sub fixHeaders +{ + my $fileName = $File::Find::name; + my $relFileName = File::Spec->abs2rel($fileName, $cwd); + + # only check sources, also ignore symbolic links and directories + return unless -f $fileName && $fileName =~ /(\.h|\.cpp|\/C|\.cc|\.CC)$/; + + my $inFile = new IO::File('<' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + $fileCount++; + my @affectedClasses; + my @outLines; + + while (my $line = <$inFile>) { + if ($line =~ /^#(\s*)include(\s*)<.*?\/(.*?)>(.*)/) { + my $newHeader = $headerSubst{$3}; + if ($newHeader) { + $line = '#' . $1 . 'include' . $2 . '<' . $newHeader . '>' . $4 . "\n"; + push(@affectedClasses, $3); + } + } elsif ($line =~ /^#(\s*)include(\s*)(.*)/) { + $line = '#' . $1 . 'include' . $2 . '' . $3 . "\n"; + push(@affectedClasses, 'QtGui'); + } + push(@outLines, $line); + } + $inFile->close(); + + if (scalar(@affectedClasses)) { + $fixedFileCount++; + print $relFileName, ': ', join(', ', @affectedClasses), "\n" if ($verbose || $dry_run); + if (!$dry_run) { + my $outFile = new IO::File('>' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + map { print $outFile $_; } @outLines; + $outFile->close(); + } + } else { + print $relFileName, ": no modification.\n" if ($verbose || $dry_run); + } +} + +sub findQtHeaders +{ + my ($dirName,$baseDir) = @_; + + local (*DIR); + + opendir(DIR, $baseDir . '/include/' . $dirName) || die ('Unable to open ' .$baseDir . '/include/' . $dirName . ': ' . $!); + my @headers = readdir(DIR); + closedir(DIR); + + foreach my $header (@headers) { + next if (-d ($baseDir . '/include/' . $dirName . '/' . $header) || $header =~ /\.pri$/); + $headerSubst{$header} = $stripModule ? $header : ($dirName . '/' . $header); + } +} + +# -------- MAIN + +die "This script requires the QTDIR environment variable pointing to Qt 5\n" unless $qtdir; + +findQtHeaders('QtCore', $qtdir); +findQtHeaders('QtConcurrent', $qtdir); +findQtHeaders('QtWidgets', $qtdir); +findQtHeaders('QtPrintSupport', $qtdir); + +if (-d $qtdir . '/include/QtMultiMedia') { + findQtHeaders('QtMultiMedia', $qtdir); + findQtHeaders('QtMultiMediaWidgets', $qtdir); +} elsif (-d $qtdir . '/../qtmultimedia' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtMultiMedia', $qtdir . '/../qtmultimedia'); + findQtHeaders('QtMultiMediaWidgets', $qtdir . '/../qtmultimedia'); +} + +# Support porting from "Qt 4.99" QtDeclarative to QtQuick (QQuickItem et al) +if (-d $qtdir . '/include/QtQuick') { + findQtHeaders('QtQuick', $qtdir); +} elsif (-d $qtdir . '/../qtdeclarative' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtQuick', $qtdir . '/../qtdeclarative'); +} + +# special case +$headerSubst{'QtGui'} = 'QtWidgets/QtWidgets'; + +find({ wanted => \&fixHeaders, no_chdir => 1}, $cwd); + +print 'Done. ', ($dry_run ? 'Checked' : 'Modified'), ' ', $fixedFileCount, ' of ', $fileCount, " file(s).\n"; diff --git a/GC-3.6.1-T3/src/gcode.cpp b/GC-3.6.1-T3/src/gcode.cpp new file mode 100644 index 0000000..d151718 --- /dev/null +++ b/GC-3.6.1-T3/src/gcode.cpp @@ -0,0 +1,2059 @@ +/**************************************************************** + * gcode.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "gcode.h" + +#include + +GCode::GCode() + : errorCount(0), doubleDollarFormat(false), + incorrectMeasurementUnits(false), incorrectLcdDisplayUnits(false), + maxZ(0), motionOccurred(false), + sliderZCount(0), + positionValid(false), + numaxis(DEFAULT_AXIS_COUNT), +/// LETARTARE T3 + checkState(false) +{ + // use base class's timer - use it to capture random text from the controller + startTimer(1000); + // for position polling + pollPosTimer.start(); +} + +void GCode::openPort(QString commPortStr, QString baudRate) +{ + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + clearToHome(); + + currComPort = commPortStr; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if (port.OpenComport(commPortStr, baudRate)) + { + emit portIsOpen(true); + } + else + { + emit portIsClosed(false); + QString msg = tr("Can't open COM port ") + commPortStr; + sendMsg(msg); + addList(msg); + warn("%s", qPrintable(msg)); + + addList(tr("-Is hardware connected to USB?") ); + addList(tr("-Is correct port chosen?") ); + addList(tr("-Does current user have sufficient permissions?") ); +#if defined(Q_OS_LINUX) + addList("-Is current user in sudoers group?"); +#endif + //QMessageBox(QMessageBox::Critical,"Error","Could not open port.",QMessageBox::Ok).exec(); + } +} + +void GCode::closePort(bool reopen) +{ + port.CloseComport(); + emit portIsClosed(reopen); +} + +bool GCode::isPortOpen() +{ + return port.isPortOpen(); +} + +// Abort means stop file send after the end of this line +void GCode::setAbort() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + abortState.set(true); +} + +// Reset means immediately stop waiting for a response +void GCode::setReset() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + resetState.set(true); +} + +// Shutdown means app is shutting down - we give thread about .3 sec to exit what it is doing +void GCode::setShutdown() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + shutdownState.set(true); +} + +// Slot for interrupting current operation or doing a clean reset of grbl without changing position values +void GCode::sendGrblReset() +{ + clearToHome(); + + QString x(CTRL_X); + sendGcodeLocal(x, true, SHORT_WAIT_SEC); +} +/// LETARTARE T3 +// Slot for file Check, called by 'MainWindow::checkCode()' +void GCode::sendGrblCheck(bool checkstate) +{ + checkState = false; + if (!sendGcodeLocal(REQUEST_MODE_CHECK)) { + /// ... + + } + else + if (!sendGcodeLocal(REQUEST_CURRENT_POS )) { + /// ... + + } + else + checkState = checkstate ; +} + +void GCode::sendGrblUnlock() +{ + sendGcodeLocal(SET_UNLOCK_STATE_V08c); +} + +// Slot for gcode-based 'zero out the current position values without motion' +void GCode::grblSetHome() +{ + clearToHome(); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G92 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G92 x0 y0 z0"); +} + +void GCode::goToHome() +{ + if (!motionOccurred) + return; + + double maxZOver = maxZ; + + if (doubleDollarFormat) + { + maxZOver += (controlParams.useMm ? PRE_HOME_Z_ADJ_MM : (PRE_HOME_Z_ADJ_MM / MM_IN_AN_INCH)); + } + else + { + // all reporting is in mm + maxZOver += PRE_HOME_Z_ADJ_MM; + } + + QString zpos = QString::number(maxZOver); + + gotoXYZFourth(QString("G0 z").append(zpos)); + + if (numaxis == MAX_AXIS_COUNT) +/// LETARTARE T1 + gotoXYZFourth(QString("G1 x0 y0 z0 ").append(QString(controlParams.fourthAxisType)).toLower().append("0")); + else + gotoXYZFourth("G1 x0 y0 z0"); + + maxZ -= maxZOver; + + motionOccurred = false; +} + +// Slot called from other threads (i.e. main window, grbl dialog, etc.) +void GCode::sendGcode(QString line) +{ + bool checkMeasurementUnits = false; + + // empty line means we have just opened the com port + if (line.length() == 0) + { + resetState.set(false); + + QString result; + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, false)) + { + if (shutdownState.get() || resetState.get()) + return; + // it is possible that we are already connected and missed the + // signon banner. Force a reset (is this ok?) to get the banner + +/// LETARTARE for 0.845 !! +/* + emit addListOut("(CTRL-X)"); + + char buf[2] = {0}; + + buf[0] = CTRL_X; + + diag(qPrintable(tr("SENDING: 0x%02X (CTRL-X) to check presence of Grbl\n")), buf[0]) ; + if (!port.SendBuf(buf, 1)) + { + QString msg = tr("Sending to port failed"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return; + } +*/ +/// <-- + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, true)) + return; + } + + checkMeasurementUnits = true; + } + else + { + pollPosWaitForIdle(false); + // normal send of actual commands + sendGcodeLocal(line, false); + } + + pollPosWaitForIdle(checkMeasurementUnits); +} + +// keep polling our position and state until we are done running +void GCode::pollPosWaitForIdle(bool checkMeasurementUnits) +{ + if (controlParams.usePositionRequest + && (controlParams.positionRequestType == PREQ_ALWAYS_NO_IDLE_CHK + || controlParams.positionRequestType == PREQ_ALWAYS + || checkMeasurementUnits) + ) + { + bool immediateQuit = false; + for (int i = 0; i < 10000; i++) + { + GCode::PosReqStatus ret = positionUpdate(); + if (ret == POS_REQ_RESULT_ERROR || ret == POS_REQ_RESULT_UNAVAILABLE) + { + immediateQuit = true; + break; + } + else if (ret == POS_REQ_RESULT_TIMER_SKIP) + { + SLEEP(250); + continue; + } + + if (doubleDollarFormat) + { + if (lastState.compare("Run") != 0) + break; + } + else + { + if (machineCoordLastIdlePos == machineCoord + && workCoordLastIdlePos == workCoord) + { + break; + } + + machineCoordLastIdlePos = machineCoord; + workCoordLastIdlePos = workCoord; + } + + if (shutdownState.get()) + return; + } + + if (immediateQuit) + return; +/// LETARTARE T3 : to avoid loading too display +/// to review ... + /* + if (checkMeasurementUnits) + { + if (doubleDollarFormat) + checkAndSetCorrectMeasurementUnits(); + else + setOldFormatMeasurementUnitControl(); + } + */ + } + else + { + setLivenessState(false); + } +} + +// Slot called from other thread that returns whatever text comes back from the controller +void GCode::sendGcodeAndGetResult(int id, QString line) +{ + QString result; + + emit sendMsg(""); + resetState.set(false); + if (!sendGcodeInternal(line, result, false, SHORT_WAIT_SEC, false)) + result.clear(); + + emit gcodeResult(id, result); +} + +// To be called only from this class, not from other threads. Use above two methods for that. +// Wraps sendGcodeInternal() to allow proper handling of failure cases, etc. +bool GCode::sendGcodeLocal(QString line, bool recordResponseOnFail /* = false */, int waitSec /* = -1 */, bool aggressive /* = false */, int currLine /* = 0 */) +{ + QString result; + sendMsg(""); + resetState.set(false); + + bool ret = sendGcodeInternal(line, result, recordResponseOnFail, waitSec, aggressive, currLine); + if (shutdownState.get()) + return false; + + if (!ret && (!recordResponseOnFail || resetState.get())) + { + if (!resetState.get()) + emit stopSending(); + + if (!ret && resetState.get()) + { + resetState.set(false); + port.Reset(); + } + } + else + { + if (checkGrbl(result)) + { + emit enableGrblDialogButton(); + } + } + resetState.set(false); + return ret; +} + +bool GCode::checkGrbl(const QString& result) +{ + if (result.contains("Grbl")) + { +/// LETARTARE T2 + (\\w*) for 0.8cx + QRegExp rx("Grbl (\\d+)\\.(\\d+)(\\w*)(\\w*)"); + if (rx.indexIn(result) != -1 && rx.captureCount() > 0) + { + doubleDollarFormat = false; + + QStringList list = rx.capturedTexts(); + if (list.size() >= 3) + { + int majorVer = list.at(1).toInt(); + int minorVer = list.at(2).toInt(); + char letter = ' '; + char postVer = ' '; /// T2 + if (list.size() >= 4 && list.at(3).size() > 0) + { + letter = list.at(3).toLatin1().at(0); + /// T2 for 0.8cx + if (list.at(3).toLatin1().size() > 1) + postVer = list.at(3).toLatin1().at(1); + } + + if (majorVer > 0 || (minorVer > 8 && minorVer < 51) || letter > 'a') + { + doubleDollarFormat = true; + } +/// LETARTARE T2 + diag(qPrintable(tr("Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d)\n")), + majorVer, minorVer, letter, postVer, doubleDollarFormat); + QString resu = list.at(0); + emit setVersionGrbl(resu); +/// <-- + } + + if (!doubleDollarFormat) + setUnitsTypeDisplay(true); + } + return true; + } + return false; +} + +// Wrapped method. Should only be called from above method. +bool GCode::sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine /* = 0 */) +{ + if (!port.isPortOpen()) + { + QString msg = tr("Port not available yet") ; + err("%s", msg.toLocal8Bit().constData()); + emit addList(msg); + emit sendMsg(msg); + return false; + } + + bool ctrlX = line.size() > 0 ? (line.at(0).toLatin1() == CTRL_X) : false; + + bool sentReqForLocation = false; + bool sentReqForSettings = false; + bool sentReqForParserState = false; + + if (checkForGetPosStr(line)) + { + sentReqForLocation = true; + setLivenessState(true); + } + else if (!line.compare(REQUEST_PARSER_STATE_V08c)) + { + sentReqForParserState = true; + } + else if (!line.compare(SETTINGS_COMMAND_V08a)) + { + if (doubleDollarFormat) + line = SETTINGS_COMMAND_V08c; + + sentReqForSettings = true; + } + else + motionOccurred = true; + + // adds to UI list, but prepends a > indicating a sent command + if (ctrlX) + { + emit addListOut("(CTRL-X)"); + } + else if (!sentReqForLocation)// if requesting location, don't add that "noise" to the output view + { +/// T3 + fix bug + QString nLine(line); + if (currLine) { + nLine = QString().setNum(currLine); + emit setLinesFile(nLine, true); + if (line.at(0).toLatin1() != 'N') + nLine = "L" + nLine + " " + line; + else + nLine = line ; + } + if (!checkState) + emit addListOut(nLine); +/// <-- + } + + if (line.size() == 0 || (!line.endsWith('\r') && !ctrlX)) + line.append('\r'); + + char buf[BUF_SIZE + 1] = {0}; + if (line.length() >= BUF_SIZE) + { + QString msg = tr("Buffer size too small"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + for (int i = 0; i < line.length(); i++) + buf[i] = line.at(i).toLatin1(); + + if (ctrlX) + diag(qPrintable(tr("SENDING[%d]: 0x%02X (CTRL-X)\n")), currLine, buf[0]); + else + diag(qPrintable(tr("SENDING[%d]: %s\n")), currLine, buf); + + int waitSecActual = waitSec == -1 ? controlParams.waitTime : waitSec; + + if (aggressive) + { + if (ctrlX) + sendCount.append(CmdResponse("(CTRL-X)", line.length(), currLine)); + else + sendCount.append(CmdResponse(buf, line.length(), currLine)); + + //diag("DG Buffer Add %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + + waitForOk(result, waitSecActual, false, false, aggressive, false); + + if (shutdownState.get()) + return false; + } + + if (!port.SendBuf(buf, line.length())) + { + QString msg = tr("Sending to port failed") ; + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsg(msg); + return false; + } + else + { + sentI++; + if (!waitForOk(result, waitSecActual, sentReqForLocation, sentReqForParserState, aggressive, false)) + { + diag(qPrintable(tr("WAITFOROK FAILED\n"))); + if (shutdownState.get()) + return false; + + if (!recordResponseOnFail && !(resetState.get() || abortState.get())) + { + QString msg = tr("Wait for ok failed"); + emit addList(msg); + emit sendMsg(msg); + } + + return false; + } + else + { + if (sentReqForSettings) + { + QStringList list = result.split("$"); + for (int i = 0; i < list.size(); i++) + { + QString item = list.at(i); + const QRegExp rx(REGEXP_SETTINGS_LINE); + + if (rx.indexIn(item, 0) != -1 && rx.captureCount() == 3) + { + QStringList capList = rx.capturedTexts(); + if (!capList.at(1).compare("13")) + { + if (!capList.at(2).compare("0")) + { + if (!controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + else + { + if (controlParams.useMm) + incorrectLcdDisplayUnits = true; + } + break; + } + } + } + + settingsItemCount.set(list.size()); + } + } + } + return true; +} +///----------------------------------------------------------------------------- +bool GCode::waitForOk(QString& result, int waitSec, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize) +{ + int okcount = 0; + + if (aggressive) + { + //if (!port.bytesAvailable()) //more conservative code + if (!finalize || !port.bytesAvailable()) + { + int total = 0; + bool haveWait = false; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + if (cmdResp.waitForMe) + { + haveWait = true; + } + } + + //printf("Total out (a): %d (%d) (%d)\n", total, sendCount.size(), haveWait); + + if (!haveWait) + { + if (total < (GRBL_RX_BUFFER_SIZE - 1)) + { + return true; + } + } + } + } + + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!result.contains(RESPONSE_OK) && !result.contains(RESPONSE_ERROR) && !resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + if (aggressive && sendCount.size() == 0) + return false; + + count++; + SLEEP(100); + } + else + if (n < 0) + { + QString Mes(tr("Error reading data from COM port\n")) ; + err(qPrintable(Mes)); + + if (aggressive && sendCount.size() == 0) + return false; + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + QString received(tmp); + + if (aggressive) + { + if (received.contains(RESPONSE_OK)) + { + if (sendCount.isEmpty()) { + err(qPrintable(tr("Unexpected: list is empty (o)!"))); + } + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + diag(qPrintable(tr("GOT[%d]: '%s' for '%s' (aggressive)\n")), cmdResp.line, + qPrintable(tmpTrim), qPrintable(cmdResp.cmd.trimmed())); + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + rcvdI++; + okcount++; + } + else + if (received.contains(RESPONSE_ERROR)) + { + QString orig(tr("Error?")); + if (sendCount.isEmpty()) + err(qPrintable(tr("Unexpected: list is empty (e)!"))); + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + orig = cmdResp.cmd; + diag(qPrintable(tr("GOT[%d]: '%s' for '%s' (aggressive)\n")), cmdResp.line, + qPrintable(tmpTrim), qPrintable(cmdResp.cmd.trimmed())); + //diag("DG Buffer %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); + } + errorCount++; + QString result; + QTextStream(&result) << received << " [for " << orig << "]"; + emit addList(result); + grblCmdErrors.append(result); + rcvdI++; + } + else + { + diag(qPrintable(tr("GOT: '%s' (aggressive)\n")), qPrintable(tmpTrim.trimmed()) ); + parseCoordinates(received, aggressive); + } + + int total = 0; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + } + + //printf("Total out (b): %d (%d)\n", total, sendCount.size()); + //printf("SENT:%d RCVD:%d\n", sentI, rcvdI); + + if (total >= (GRBL_RX_BUFFER_SIZE - 1)) + { + //diag("DG Loop again\n"); + result.clear(); + continue; + } + else + if (port.bytesAvailable()) + { + // comment out this block for more conservative approach + if (!finalize && okcount > 0) + { + //diag("DG Leave early\n"); + return true; + } + + result.clear(); + continue; + } + else + { + return true; + } + } + else + { + diag(qPrintable(tr("GOT:%s\n")), qPrintable(tmpTrim)); + } + + if (!received.contains(RESPONSE_OK) && !received.contains(RESPONSE_ERROR)) + { + if (sentReqForParserState) + { + const QRegExp rx("\\[([\\s\\w\\.\\d]+)\\]"); + + if (rx.indexIn(received, 0) != -1 && rx.captureCount() == 1) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 2) + { + QStringList items = list.at(1).split(" "); + if (items.contains("G20"))// inches + { + if (controlParams.useMm) + incorrectMeasurementUnits = true; + else + incorrectMeasurementUnits = false; + } + else + if (items.contains("G21"))// millimeters + { + if (controlParams.useMm) + incorrectMeasurementUnits = false; + else + incorrectMeasurementUnits = true; + } + else + { + // not in list! + incorrectMeasurementUnits = true; + } + } + } + } + else + { + parseCoordinates(received, aggressive); + } + } + count = 0; + } + + SLEEP(100); + + if (count > waitCount) + { + // waited too long for a response, fail + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (!aggressive) + SLEEP(100); + + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !sentReqForLocation && !list.at(i).startsWith("MPos:[")) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} +///----------------------------------------------------------------------------- + +bool GCode::waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound) +{ + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + count++; + SLEEP(100); + } + else if (n < 0) + { + err(qPrintable(tr("Error reading data from COM port\n")) ); + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + diag(qPrintable(tr("GOT:%s\n")), tmpTrim.toLocal8Bit().constData()); + + if (tmpTrim.length() > 0) + { + if (!checkGrbl(tmpTrim)) + { + if (failOnNoFound) + { + QString msg(tr("Expecting Grbl version string. Unable to parse response.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + status = false; + } + else + { + emit enableGrblDialogButton(); + } + break; + } + } + + SLEEP(100); + + if (count > waitCount) + { + if (failOnNoFound) + { + // waited too long for a response, fail + + QString msg(tr("No data from COM port after connect. Expecting Grbl version string.")); + emit addList(msg); + emit sendMsg(msg); + + closePort(false); + } + + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user (startup)")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +/// LETARTARE T1 +/* +/// May 13, 2014 + 1- frame1 : < 8c (3 axes), 0.845 (4 axes) -> $$==0 + received == "MPos:[....],WPos:[....]" + 2- frame2 : 0.8c1 or 0.8c2 (4 axes) -> $$==1 + received == "" + 3- frame2 : 0.8c (3 axes) -> $$==1 + received == "" + 4- frame3 : 0.9d (3 axes), 0.9d1 (4 axes) -> $$==1 + received == "" +*/ + +void GCode::parseCoordinates(const QString& received, bool aggressive) +{ + if (aggressive) + { + int ms = parseCoordTimer.elapsed(); + if (ms < 500) + return; + + parseCoordTimer.restart(); + } + + bool good = false ; + int captureCount ; + QString state; + QString prepend; + QString append; + QString preamble = "([a-zA-Z]+),MPos:"; + if (!doubleDollarFormat) + { + prepend = "\\["; + append = "\\]"; + preamble = "MPos:" ; + } + QString coordRegExp; + QRegExp rxStateMPos; + QRegExp rxWPos; +/// 1 axis + QString format1("(-*\\d+\\.\\d+)") ; + QString sep(","); + /// 3 axes + QString format3 = format1 + sep + format1 + sep + format1 ; + /// 4 axes + QString format4 = format3 + sep + format1 ; + QString format ; + int naxis ; + for (naxis = MAX_AXIS_COUNT; naxis >= DEFAULT_AXIS_COUNT; naxis--) { + if (!doubleDollarFormat) + captureCount = naxis ; + else + captureCount = naxis + 1 ; + + if (naxis == MAX_AXIS_COUNT ) + format = format4; + else + format = format3; + + coordRegExp = prepend + format + append ; + rxStateMPos = QRegExp(preamble + coordRegExp); + rxWPos = QRegExp(QString("WPos:") + coordRegExp); + good = rxStateMPos.indexIn(received, 0) != -1 + && rxStateMPos.captureCount() == captureCount + && rxWPos.indexIn(received, 0) != -1 + && rxWPos.captureCount() == naxis + ; + + // find naxis ... + if (good) + break; + } + if (good) { /// naxis contains number axis + if (numaxis <= DEFAULT_AXIS_COUNT) + { + if (naxis > DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + else + { + if (naxis <= DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options."); + emit addList(msg); + emit sendMsg(msg); + } + } + + numaxis = naxis; + QStringList list = rxStateMPos.capturedTexts(); + int index = 1; + + if (doubleDollarFormat) + state = list.at(index++); + + machineCoord.x = list.at(index++).toFloat(); + machineCoord.y = list.at(index++).toFloat(); + machineCoord.z = list.at(index++).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + machineCoord.fourth = list.at(index++).toFloat(); + list = rxWPos.capturedTexts(); + workCoord.x = list.at(1).toFloat(); + workCoord.y = list.at(2).toFloat(); + workCoord.z = list.at(3).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + workCoord.fourth = list.at(4).toFloat(); + if (state != "Run") + workCoord.stoppedZ = true; + else + workCoord.stoppedZ = false; + + workCoord.sliderZIndex = sliderZCount; + + if (doubleDollarFormat) + diag(qPrintable(tr("Decoded: State:%s")), qPrintable(state) ); + if (numaxis == DEFAULT_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f WPos: %f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, + workCoord.x, workCoord.y, workCoord.z + ); + else if (numaxis == MAX_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, machineCoord.fourth, + workCoord.x, workCoord.y, workCoord.z, workCoord.fourth + ); + + if (workCoord.z > maxZ) + maxZ = workCoord.z; + + emit updateCoordinates(machineCoord, workCoord); + emit setLivePoint(workCoord.x, workCoord.y, controlParams.useMm, positionValid); + emit setLastState(state); + + lastState = state; + return; + } + // TODO fix to print + //if (!good /*&& received.indexOf("MPos:") != -1*/) + // err(qPrintable(tr("Error decoding position data! [%s]\n")), qPrintable(received)); + + lastState = ""; +} + +void GCode::sendStatusList(QStringList& listToSend) +{ + if (listToSend.size() > 1) + { + emit addListFull(listToSend); + } + else if (listToSend.size() == 1) + { + emit addList(listToSend.at(0)); + } +} + +// called once a second to capture any random strings that come from the controller +void GCode::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (port.isPortOpen()) + { + char tmp[BUF_SIZE + 1] = {0}; + QString result; + + for (int i = 0; i < 10 && !shutdownState.get() && !resetState.get(); i++) + { + int n = port.PollComport(tmp, BUF_SIZE); + if (n == 0) + break; + + tmp[n] = 0; + result.append(tmp); + diag(qPrintable(tr("GOT-TE:%s\n")), tmp); + } + + if (shutdownState.get()) + { + return; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && (list.at(i) != "ok" || (list.at(i) == "ok" && abortState.get()))) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + } +} +/// LETARTARE T3 +void GCode::sendFile(QString path, bool checkfile) +{ + addList(QString(tr("Sending file '%1'")).arg(path)); + + // send something to be sure the controller is ready + //sendGcodeLocal("", true, SHORT_WAIT_SEC); + + setProgress(0); + emit setQueuedCommands(0, false); + grblCmdErrors.clear(); + grblFilteredCmds.clear(); + errorCount = 0; + abortState.set(false); + QFile file(path); + if (file.open(QFile::ReadOnly)) + { +/// LETARTARE T1 float -> int + int totalLineCount = 0; + + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLineCount++; + code.readLine(); + } + if (totalLineCount == 0) + totalLineCount = 1; + + code.seek(0); + + // set here once so that it doesn't change in the middle of a file send + bool aggressive = controlParams.useAggressivePreload; + if (aggressive) + { + sendCount.clear(); + //if (sendCount.size() == 0) + //{ + // diag("DG Buffer 0 at start\n")); + //} + + emit setQueuedCommands(sendCount.size(), true); + } + + sentI = 0; + rcvdI = 0; + emit resetTimer(true); + + parseCoordTimer.restart(); + + int currLine = 0; + bool xyRateSet = false; +/// LETARTARE T1 + QString strline ; + do + { + strline = code.readLine(); +/// LETARTARE T3 + if (!checkfile) + emit setVisCurrLine(currLine + 1); + + if (controlParams.filterFileCommands) + { + trimToEnd(strline, '('); + trimToEnd(strline, ';'); + trimToEnd(strline, '%'); + } + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + if (controlParams.filterFileCommands) + { + strline = strline.toUpper(); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline = removeUnsupportedCommands(strline); + } + + if (strline.size() != 0) + { + if (controlParams.reducePrecision) + { + strline = reducePrecision(strline); + } + + QString rateLimitMsg; + QStringList outputList; + if (controlParams.zRateLimit) + { + outputList = doZRateLimit(strline, rateLimitMsg, xyRateSet); + } + else + { + outputList.append(strline); + } + + bool ret = false; + if (outputList.size() == 1) + { + ret = sendGcodeLocal(outputList.at(0), false, -1, aggressive, currLine + 1); + } + else + { + foreach (QString outputLine, outputList) + { + ret = sendGcodeLocal(outputLine, false, -1, aggressive, currLine + 1); + + if (!ret) + break; + } + } + + if (rateLimitMsg.size() > 0) + addList(rateLimitMsg); + + if (!ret) + { + abortState.set(true); + break; + } + } + } + + float percentComplete = (currLine * 100.0) / totalLineCount; + setProgress((int)percentComplete); +/// T3 + if (!checkfile) + positionUpdate(); + currLine++; + } while ((code.atEnd() == false) && (!abortState.get())); + + file.close(); + + if (aggressive) + { + int limitCount = 5000; + while (sendCount.size() > 0 && limitCount) + { + QString result; + waitForOk(result, controlParams.waitTime, false, false, aggressive, true); + SLEEP(100); + + if (shutdownState.get()) + return; + + if (abortState.get()) + break; + + limitCount--; + } + + if (!limitCount) + { + err(qPrintable(tr("Gave up waiting for OK\n"))); + } + } +/// T3 + if (!checkfile) + positionUpdate(); + + emit resetTimer(false); + + if (shutdownState.get()) + { + return; + } + + QString msg; + if (!abortState.get()) + { + setProgress(100); + if (errorCount > 0) + { + msg = QString(tr("Code sent successfully with %1 error(s):")).arg(QString::number(errorCount)); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblCmdErrors) + { + emit sendMsg(errItem); + } + emit addListFull(grblCmdErrors); + } + else + { + msg = tr("Code sent successfully with no errors."); + emit sendMsg(msg); + emit addList(msg); + } + + if (grblFilteredCmds.size() > 0) + { + msg = QString(tr("Filtered %1 commands:")).arg(QString::number(grblFilteredCmds.size())); + emit sendMsg(msg); + emit addList(msg); + + foreach(QString errItem, grblFilteredCmds) + { + emit sendMsg(errItem); + } + emit addListFull(grblFilteredCmds); + } + } + else + { + msg = tr("Process interrupted."); + emit sendMsg(msg); + emit addList(msg); + } + } + + pollPosWaitForIdle(true); + + if (!resetState.get()) + { + emit stopSending(); + } + + emit setQueuedCommands(0, false); +} + +void GCode::trimToEnd(QString& strline, QChar ch) +{ + int pos = strline.indexOf(ch); + if (pos != -1) + strline = strline.left(pos); +} + +QString GCode::removeUnsupportedCommands(QString line) +{ + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString tmp; + QString s; + QString following; + bool toEndOfLine = false; + foreach (s, components) + { + if (toEndOfLine) + { + QString msg(QString(tr("Removed unsupported command '%1' part of '%2'")).arg(s).arg(following)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + continue; + } + + if (s.at(0) == 'G') + { + float value = s.mid(1,-1).toFloat(); + if (isGCommandValid(value, toEndOfLine)) + tmp.append(s).append(" "); + else + { + if (toEndOfLine) + following = s; + QString msg(QString(tr("Removed unsupported G command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'M') + { + float value = s.mid(1,-1).toFloat(); + if (isMCommandValid(value)) + tmp.append(s).append(" "); + else + { + QString msg(QString(tr("Removed unsupported M command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'N') + { + // skip line numbers + } + else if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'Z' + || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C' +/// LETARTARE + || s.at(0) == 'U' || s.at(0) == 'V' || s.at(0) == 'W' +/// <-- + || s.at(0) == 'I' || s.at(0) == 'J' || s.at(0) == 'K' + || s.at(0) == 'F' || s.at(0) == 'L' || s.at(0) == 'S') + { + tmp.append(s).append(" "); + } + else + { + QString msg(QString(tr("Removed unsupported command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + + return tmp.trimmed(); +} + +QString GCode::reducePrecision(QString line) +{ + // first remove all spaces to determine what are line length is + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString result; + foreach(QString token, components) + { + result.append(token); + } + + if (result.length() == 0) + return line;// nothing to do + + if (!result.at(0).isLetter()) + return line;// leave as-is if not a command + + // find first comment and eliminate + int pos = result.indexOf('('); + if (pos >= 0) + result = result.left(pos); + + int charsToRemove = result.length() - (controlParams.grblLineBufferLen - 1);// subtract 1 to account for linefeed sent with command later + + if (charsToRemove > 0) + { + // ok need to do something with precision + // split apart based on letter + pos = 0; + components.clear(); + int i; + for (i = 1; i < result.length(); i++) + { + if (result.at(i).isLetter()) + { + components.append(result.mid(pos, i - pos)); + pos = i; + } + } + + if (pos == 0) + { + // we get here if only one command + components.append(result); + } + else + { + // add last item + components.append(result.mid(pos, i)); + } + + QList items; + foreach (QString tmp, components) + { + items.append(DecimalFilter(tmp)); + } + + int totalDecCount = 0; + int eligibleArgumentCount = 0; + int largestDecCount = 0; + for (int j = 0; j < items.size(); j++) + { + DecimalFilter& item = items[j]; + pos = item.token.indexOf('.'); + if ((item.token.at(1).isDigit() || item.token.at(1) == '-' || item.token.at(1) == '.') && pos >= 0) + { + // candidate to modify + // count number of decimal places + int decPlaceCount = 0; + for (i = pos + 1; i < item.token.length(); i++, decPlaceCount++) + { + if (!item.token.at(i).isDigit()) + break; + } + + // skip commands that have a single decimal place + if (decPlaceCount > 1) + { + item.decimals = decPlaceCount; + totalDecCount += decPlaceCount - 1;// leave at least the last decimal place + eligibleArgumentCount++; + if (decPlaceCount > largestDecCount) + largestDecCount = decPlaceCount; + } + } + } + + bool failRemoveSufficientDecimals = false; + if (totalDecCount < charsToRemove) + { + // remove as many as possible, then grbl will truncate + charsToRemove = totalDecCount; + failRemoveSufficientDecimals = true; + } + + if (eligibleArgumentCount > 0) + { + for (int k = largestDecCount; k > 1 && charsToRemove > 0; k--) + { + for (int j = 0; j < items.size() && charsToRemove > 0; j++) + { + DecimalFilter& item = items[j]; + if (item.decimals == k) + { + item.token.chop(1); + item.decimals--; + charsToRemove--; + } + } + } + + //chk.clear(); + //chk.append("CORRECTED:"); + result.clear(); + foreach (DecimalFilter item, items) + { + result.append(item.token); + + //chk.append("["); + //chk.append(item.token); + //chk.append("]"); + } + //diag(chk.toLocal8Bit().constData()); + + err(qPrintable(tr("Unable to remove enough decimal places for command (will be truncated): %s")), line.toLocal8Bit().constData()); + + QString msg; + if (failRemoveSufficientDecimals) + msg = QString(tr("Error, insufficent reduction '%1'")).arg(result); + else + msg = QString(tr("Precision reduced '%1'")).arg(result); + + emit addList(msg); + emit sendMsg(msg); + } + } + + return result; +} + +bool GCode::isGCommandValid(float value, bool& toEndOfLine) +{ + toEndOfLine = false; + // supported values obtained from https://github.com/grbl/grbl/wiki + const static float supported[] = + { + 0, 1, 2, 3, 4, + 10, 17, 18, 19, 20, 21, 28, 28.1, 30, 30.1, + 53, 54, 55, 56, 57, 58, 59, + 80, 90, 91, 92, 92.1, 93, 94 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + + if (value == 43 || value == 44) + { + toEndOfLine = true; + } + return false; +} + +bool GCode::isMCommandValid(float value) +{ + // supported values obtained from https://github.com/grbl/grbl/wiki + + // NOTE: M2 and M30 are supported but they cause occasional grbl lockups + // and thus have been removed from the supported list. No harm is caused + // by their removal. + const static float supported[] = + { + 0, 3, 4, 5, 8, 9 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + return false; +} + +QStringList GCode::doZRateLimit(QString inputLine, QString& msg, bool& xyRateSet) +{ + // i.e. + //G00 Z1 => G01 Z1 F100 + //G01 Z1 F260 => G01 Z1 F100 + //G01 Z1 F30 => G01 Z1 F30 + //G01 X1 Y1 Z1 F200 -> G01 X1 Y1 & G01 Z1 F100 + QStringList list; + QString line = inputLine.toUpper(); + + if (line.count("Z") > 0) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + bool foundFeed = false; + bool didLimit = false; + + // We need to build one or two command strings depending on input. + QString x, y, g, f; + + // First get all component parts + bool inLimit = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + g = s; + } + else if (s.at(0) == 'F') + { + f = s; + + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + inLimit = true; + } + else if (s.at(0) == 'X') + { + x = s; + } + else if (s.at(0) == 'Y') + { + y = s; + } + } + + // Determine whether we want to have one or two command lins + // 1 string: Have !G0 and F but not in limit + // 1 string: Have Z only + // 2 strings: All other conditions + QString line1; + QString line2; + if ((g != "G0" && f.size() > 0 && !inLimit) + || (x.size() == 0 && y.size() == 0)) + { + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value == 0) + line1.append("G1"); + else + line1.append(s); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s); + + foundFeed = true; + } + else + { + line1.append(s); + } + line1.append(" "); + } + } + else + { + // two lines + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 1) + line1.append("G1").append(" "); + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + + foundFeed = true; + } + else if (s.at(0) == 'Z') + { + line1.append(s).append(" "); + } + else + { + line2.append(s).append(" "); + } + } + } + + if (!foundFeed) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + + line1 = line1.trimmed(); + line2 = line2.trimmed(); + + if (didLimit) + { + if (line2.size() == 0) + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2]")).arg(inputLine).arg(line1); + xyRateSet = true; + } + else + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2,%3]")).arg(inputLine).arg(line1).arg(line2); + line2.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + } + } + + list.append(line1); + if (line2.size() > 0) + list.append(line2); + return list; + } + else if (xyRateSet) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + + bool addRateG = false; + bool addRateXY = false; + bool gotF = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 0) + { + addRateG = true; + } + } + else if (s.at(0) == 'F') + { + gotF = true; + } + else + if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C') + { + addRateXY = true; + } + } + + if (addRateG && addRateXY) + { + if (!gotF) + { + QString line = inputLine; + line.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + msg = QString(tr("XY-Rate Limit FIX: [%1]=>[%2]")).arg(inputLine).arg(line); + list.append(line); + } + else + { + list.append(inputLine); + } + + xyRateSet = false; + + return list; + } + } + + list.append(inputLine); + return list; + +} + +void GCode::gotoXYZFourth(QString line) +{ + bool queryPos = checkForGetPosStr(line); + if (!queryPos && controlParams.usePositionRequest + && controlParams.positionRequestType == PREQ_ALWAYS) + pollPosWaitForIdle(false); + + if (sendGcodeLocal(line)) + { + line = line.toUpper(); + + bool moveDetected = false; + + QStringList list = line.split(QRegExp("[\\s]+")); + for (int i = 0; i < list.size(); i++) + { + QString item = getMoveAmountFromString("X", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Y", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Z", list.at(i)); + moveDetected = item.length() > 0 ; + if (numaxis == MAX_AXIS_COUNT) { + item = getMoveAmountFromString(QString(controlParams.fourthAxisType), list.at(i)); + moveDetected = item.length() > 0; + } + } + + if (!moveDetected) + { + //emit addList("No movement expected for command."); + } + + if (!queryPos) + pollPosWaitForIdle(false); + } + else + { + QString msg(QString(tr("Bad command: %1")).arg(line)); + warn("%s", qPrintable(msg)); + emit addList(msg); + } + + emit setCommandText(""); +} + + +QString GCode::getMoveAmountFromString(QString prefix, QString item) +{ + int index = item.indexOf(prefix); + if (index != -1) + return item.mid(index + 1); + + return ""; +} + +void GCode::axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sZC) +{ + if (inv) + { + coord = (-coord); + } + + QString cmd = QString("G01 ").append(axis) + .append(QString::number(coord)); + + if (axis == 'Z') + { + cmd.append(" F").append(QString::number(controlParams.zJogRate)); + } + + SendJog(cmd, absoluteAfterAxisAdj); + + if (axis == 'Z') + sliderZCount = sZC; + + emit adjustedAxis(); +} + +bool GCode::SendJog(QString cmd, bool absoluteAfterAxisAdj) +{ + pollPosWaitForIdle(false); + + // G91 = distance relative to previous + bool ret = sendGcodeLocal("G91\r"); + + bool result = ret && sendGcodeLocal(cmd.append("\r")); + + if (result) + { + pollPosWaitForIdle(false); + } + + if (absoluteAfterAxisAdj) + sendGcodeLocal("G90\r"); + + return result; +} + +// settings change calls here +void GCode::setResponseWait(ControlParams controlParamsIn) +{ + bool oldMm = controlParams.useMm; + + controlParams = controlParamsIn; + + controlParams.useMm = oldMm; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if ((oldMm != controlParamsIn.useMm) && isPortOpen() && doubleDollarFormat) + { + if (controlParamsIn.useMm) + { + setConfigureMmMode(true); + } + else + { + setConfigureInchesMode(true); + } + } + + controlParams.useMm = controlParamsIn.useMm; + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + setUnitsTypeDisplay(controlParams.useMm); +} + +int GCode::getSettingsItemCount() +{ + return settingsItemCount.get(); +} + +// 0.8c and above only! +void GCode::checkAndSetCorrectMeasurementUnits() +{ + sendGcodeLocal(REQUEST_PARSER_STATE_V08c, false); // "$G" + + if (incorrectMeasurementUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl parser set for inches. Fixing.")); + setConfigureMmMode(true); + } + else + { + emit addList(tr("Options specify use inches but Grbl parser set for mm. Fixing.") ); + setConfigureInchesMode(true); + } + incorrectMeasurementUnits = false;// hope this is ok to do here + positionUpdate(true); + } + else + { + sendGcodeLocal(SETTINGS_COMMAND_V08c); // "$$" + + if (incorrectLcdDisplayUnits) + { + if (controlParams.useMm) + { + emit addList(tr("Options specify use mm but Grbl reporting set for inches. Fixing.")); + setConfigureMmMode(false); + } + else + { + emit addList(tr("Options specify use inches but Grbl reporting set for mm. Fixing.")); + setConfigureInchesMode(false); + } + } + incorrectLcdDisplayUnits = false; + } +} + +void GCode::setOldFormatMeasurementUnitControl() +{ + if (controlParams.useMm) + sendGcodeLocal("G21"); + else + sendGcodeLocal("G20"); +} + +void GCode::setConfigureMmMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=0"); + if (setGrblUnits) + sendGcodeLocal("G21"); + positionUpdate(true); +} + +void GCode::setConfigureInchesMode(bool setGrblUnits) +{ + sendGcodeLocal("$13=1"); + if (setGrblUnits) + sendGcodeLocal("G20"); + positionUpdate(true); +} + +void GCode::setUnitsTypeDisplay(bool millimeters) +{ + if (millimeters) + { + emit setUnitsWork(tr("(mm)")); + emit setUnitsMachine(tr("(mm)")); + } + else + { + emit setUnitsWork(tr("(in)")); + emit setUnitsMachine(tr("(in)")); + } +} + +void GCode::clearToHome() +{ + maxZ = 0; + motionOccurred = false; +} + +int GCode:: getNumaxis() +{ + return numaxis; +} + +GCode::PosReqStatus GCode::positionUpdate(bool forceIfEnabled /* = false */) +{ + if (controlParams.usePositionRequest) + { + if (forceIfEnabled) + { + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + int ms = pollPosTimer.elapsed(); + if (ms >= controlParams.postionRequestTimeMilliSec) + { + pollPosTimer.restart(); + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + return POS_REQ_RESULT_TIMER_SKIP; + } + } + } + return POS_REQ_RESULT_UNAVAILABLE; +} + +bool GCode::checkForGetPosStr(QString& line) +{ + return (!line.compare(REQUEST_CURRENT_POS) + || (line.startsWith(REQUEST_CURRENT_POS) && line.endsWith('\r') && line.length() == 2)); +} + +void GCode::setLivenessState(bool valid) +{ + positionValid = valid; + emit setVisualLivenessCurrPos(valid); + emit setLcdState(valid); +} diff --git a/GC-3.6.1-T3/src/gcode.h b/GC-3.6.1-T3/src/gcode.h new file mode 100644 index 0000000..0b3be41 --- /dev/null +++ b/GC-3.6.1-T3/src/gcode.h @@ -0,0 +1,196 @@ +/**************************************************************** + * gcode.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GCODE_H +#define GCODE_H + +#include "log4qtdef.h" + +#include +#include +#include +#include +#include "definitions.h" +#include "rs232.h" +#include "coord3d.h" +#include "controlparams.h" + +#define BUF_SIZE 300 + +#define RESPONSE_OK "ok" +#define RESPONSE_ERROR "error" + +// as defined in the grbl project on github... +#define GRBL_RX_BUFFER_SIZE 128 + +#define CTRL_X '\x18' + +#define DEFAULT_AXIS_COUNT 3 +#define MAX_AXIS_COUNT 4 + +class CmdResponse +{ +public: + CmdResponse(const char *buf, int c, int l) : cmd(buf), count(c), line(l) + { + waitForMe = false; + if (buf[0] == 'M') + { + int value = cmd.mid(1,-1).toInt(); + if (value == 9) + waitForMe = true; + } + } +public: + QString cmd; + int count; + int line; + bool waitForMe; +}; + +class DecimalFilter +{ +public: + DecimalFilter(QString t) : token(t), decimals(0) {} +public: + QString token; + int decimals; +}; + +class GCode : public QObject +{ + Q_OBJECT + +public: + GCode(); + void setAbort(); + void setReset(); + void setShutdown(); + int getSettingsItemCount(); + int getNumaxis(); + + static void trimToEnd(QString& strline, QChar); + +signals: + void addList(QString line); + void addListFull(QStringList list); + void addListOut(QString line); + void sendMsg(QString msg); + void stopSending(); + void portIsClosed(bool reopen); + void portIsOpen(bool sendCode); + void setCommandText(QString value); + void adjustedAxis(); + void gcodeResult(int id, QString result); + void setProgress(int); + void setQueuedCommands(int, bool); + void resetTimer(bool timeIt); + void enableGrblDialogButton(); + void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); + void setLastState(QString state); + void setUnitsWork(QString value); + void setUnitsMachine(QString value); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisCurrLine(int currLine); + void setLcdState(bool valid); + void setVisualLivenessCurrPos(bool isLiveCP); +/// LETARTARE T2 + void setVersionGrbl(QString versionGrbl ); +/// T3 + void setLinesFile(QString nbline, bool check); + +public slots: + void openPort(QString commPortStr, QString baudRate); + void closePort(bool reopen); + void sendGcode(QString line); + void sendGcodeAndGetResult(int id, QString line); +/// LETARTARE T3 + void sendFile(QString path, bool checkfile) ; + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void grblSetHome(); + void sendGrblReset(); + void sendGrblUnlock(); +/// LETARTARE T3 + void sendGrblCheck(bool); + + void goToHome(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + enum PosReqStatus + { + POS_REQ_RESULT_OK, + POS_REQ_RESULT_ERROR, + POS_REQ_RESULT_TIMER_SKIP, + POS_REQ_RESULT_UNAVAILABLE + }; +private: + bool sendGcodeLocal(QString line, bool recordResponseOnFail = false, int waitSec = -1, bool aggressive = false, int currLine = 0); + bool waitForOk(QString& result, int waitCount, bool sentReqForLocation, bool sentReqForParserState, bool aggressive, bool finalize); + bool waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound); + bool sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine = 0); + QString removeUnsupportedCommands(QString line); + QString reducePrecision(QString line); + bool isGCommandValid(float value, bool& toEndOfLine); + bool isMCommandValid(float value); + bool isPortOpen(); + QString getMoveAmountFromString(QString prefix, QString item); + bool SendJog(QString strline, bool absoluteAfterAxisAdj); + void parseCoordinates(const QString& received, bool aggressive); + void pollPosWaitForIdle(bool checkMeasurementUnits); + void checkAndSetCorrectMeasurementUnits(); + void setOldFormatMeasurementUnitControl(); + void setUnitsTypeDisplay(bool millimeters); + void setConfigureMmMode(bool setGrblUnits); + void setConfigureInchesMode(bool setGrblUnits); + QStringList doZRateLimit(QString strline, QString& msg, bool& xyRateSet); + void sendStatusList(QStringList& listToSend); + void clearToHome(); + bool checkGrbl(const QString& result); + PosReqStatus positionUpdate(bool forceIfEnabled = false); + bool checkForGetPosStr(QString& line); + void setLivenessState(bool valid); + +private: + RS232 port; + AtomicIntBool abortState; + AtomicIntBool resetState; + AtomicIntBool shutdownState; + ControlParams controlParams; + int errorCount; + QString currComPort; + bool doubleDollarFormat; + AtomicIntBool settingsItemCount; + QString lastState; + bool incorrectMeasurementUnits; + bool incorrectLcdDisplayUnits; + Coord3D machineCoord, workCoord; + Coord3D machineCoordLastIdlePos, workCoordLastIdlePos; + double maxZ; + QList sendCount; + QTime parseCoordTimer; + bool motionOccurred; + int sliderZCount; + QStringList grblCmdErrors; + QStringList grblFilteredCmds; + QTime pollPosTimer; + bool positionValid; + + int sentI; + int rcvdI; + int numaxis; +/// LETARTARE T3 + bool checkState; +}; + +#endif // GCODE_H diff --git a/GC-3.6.1-T3/src/grbl.ico b/GC-3.6.1-T3/src/grbl.ico new file mode 100644 index 0000000..d34802a Binary files /dev/null and b/GC-3.6.1-T3/src/grbl.ico differ diff --git a/GC-3.6.1-T3/src/grbl.rc b/GC-3.6.1-T3/src/grbl.rc new file mode 100644 index 0000000..14ed995 --- /dev/null +++ b/GC-3.6.1-T3/src/grbl.rc @@ -0,0 +1 @@ +IDI_ICON_GRBL ICON DISCARDABLE "grbl.ico" \ No newline at end of file diff --git a/GC-3.6.1-T3/src/grbldialog.cpp b/GC-3.6.1-T3/src/grbldialog.cpp new file mode 100644 index 0000000..da7a5c8 --- /dev/null +++ b/GC-3.6.1-T3/src/grbldialog.cpp @@ -0,0 +1,154 @@ +/**************************************************************** + * grbldialog.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "grbldialog.h" +#include "ui_grbldialog.h" + +GrblDialog::GrblDialog(QWidget *parent, GCode *gc) : + QDialog(parent), + gcode(gc), + ui(new Ui::GrblDialog), + tableRowCount(0) +{ + ui->setupUi(this); + connect(ui->btnCancel,SIGNAL(clicked()),this,SLOT(Cancel())); + connect(ui->btnOk,SIGNAL(clicked()),this,SLOT(Ok())); + connect(this, SIGNAL(sendGcodeAndGetResult(int, QString)), gcode, SLOT(sendGcodeAndGetResult(int, QString))); + connect(gcode, SIGNAL(gcodeResult(int, QString)), this, SLOT(gcodeResult(int, QString))); + + ui->btnCancel->setEnabled(false); + ui->btnOk->setEnabled(false); + + QStringList labels; + labels << tr("Value") << tr("Item"); + ui->table->setHorizontalHeaderLabels(labels); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + ui->table->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); +#else + ui->table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); +#endif + ui->table->verticalHeader()->hide(); + ui->table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + ui->table->setShowGrid(true); +} + +GrblDialog::~GrblDialog() +{ + delete ui; +} + +void GrblDialog::getSettings() +{ + emit sendGcodeAndGetResult(GDLG_CMD_ID_GET, SETTINGS_COMMAND_V08a); +} + +void GrblDialog::gcodeResult(int id, QString result) +{ + switch (id) + { + case GDLG_CMD_ID_GET: + { + originalValues.clear(); + changeFlags.clear(); + + if (result.size() > 0) + { + QRegExp rx(QString("\\$") + REGEXP_SETTINGS_LINE); + int pos = 0; + QStringList fieldValues; + QStringList descriptions; + while ((pos = rx.indexIn(result, pos)) != -1) + { + int matched = rx.matchedLength(); + //QString extracted = received.mid(pos, matched); + pos += matched; + + if (rx.captureCount() > 0) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 4) + { + fieldValues.append(list.at(2)); + descriptions.append(list.at(3)); + } + } + } + + tableRowCount = fieldValues.size(); + ui->table->setRowCount(0); + ui->table->setColumnCount(2); + + int i; + for (i = 0; i < tableRowCount; i++) + { + ui->table->insertRow(i); + ui->table->setItem(i, 0, new QTableWidgetItem(fieldValues.at(i))); + + QTableWidgetItem *descWidget = new QTableWidgetItem(descriptions.at(i)); + descWidget->setFlags(Qt::NoItemFlags); + + ui->table->setItem(i, 1, descWidget); + + ui->table->item(i, 0)->setFont(QFont("Tahoma",10,87,false)); + ui->table->item(i, 1)->setFont(QFont("Tahoma",10,-1,false)); + + originalValues.append(fieldValues.at(i)); + changeFlags.append(false); + } + + ui->table->resizeColumnsToContents(); + int colWidthValues = ui->table->columnWidth(0); + ui->table->setColumnWidth(0, colWidthValues + 10); + + connect(ui->table,SIGNAL(cellChanged(int,int)),this,SLOT(changeValues(int,int))); + } + else + { + ui->table->setRowCount(0); + ui->table->setColumnCount(2); + } + ui->btnCancel->setEnabled(true); + ui->btnOk->setEnabled(true); + break; + } + case GDLG_CMD_ID_SET: + break; + } +} + +void GrblDialog::Cancel() +{ + this->close(); +} + +void GrblDialog::changeValues(int row, int col) +{ + Q_UNUSED(col); + + if ((ui->table->item(row,0)->text() != originalValues.at(row)) + && ui->table->item(row,0)->text().length() > 0) + { + changeFlags.replace(row, true); + } +} + +void GrblDialog::Ok() +{ + for(int i = 0; i < tableRowCount; i++) + { + if (changeFlags.at(i) == true) + { + QString strline = "$"; + strline.append(QString::number(i)).append("=").append(ui->table->item(i,0)->text()).append('\r'); + emit sendGcodeAndGetResult(GDLG_CMD_ID_SET, strline); + } + } + this->close(); +} + diff --git a/GC-3.6.1-T3/src/grbldialog.h b/GC-3.6.1-T3/src/grbldialog.h new file mode 100644 index 0000000..5a194cf --- /dev/null +++ b/GC-3.6.1-T3/src/grbldialog.h @@ -0,0 +1,63 @@ +/**************************************************************** + * grbldialog.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GRBLDIALOG_H +#define GRBLDIALOG_H + +#include +#include +#include +#include +#include +#include "definitions.h" +#include "mainwindow.h" +#include "gcode.h" + +namespace Ui { +class GrblDialog; +} + +#define GDLG_CMD_ID_GET 1 +#define GDLG_CMD_ID_SET 2 + + +class GrblDialog : public QDialog +{ + Q_OBJECT + +public: + explicit GrblDialog(QWidget *parent, GCode *gcode); + ~GrblDialog(); + + //variables + GCode *gcode; + + //methods + void getSettings(); + +signals: + void sendGcodeAndGetResult(int id, QString cmd); + +public slots: + //buttons + void Ok(); + void Cancel(); + //Column Widget + void changeValues(int row, int col); + void gcodeResult(int id, QString result); + +private: + Ui::GrblDialog *ui; + QStringList originalValues; + QList changeFlags; + int tableRowCount; + +}; + +#endif // GRBLDIALOG_H diff --git a/GC-3.6.1-T3/src/grbldialog.ui b/GC-3.6.1-T3/src/grbldialog.ui new file mode 100644 index 0000000..a85b809 --- /dev/null +++ b/GC-3.6.1-T3/src/grbldialog.ui @@ -0,0 +1,96 @@ + + + GrblDialog + + + + 0 + 0 + 440 + 438 + + + + + 0 + 0 + + + + Grbl Settings + + + + + 50 + 390 + 75 + 31 + + + + Apply + + + + + + 280 + 390 + 75 + 31 + + + + Close + + + + + + 10 + 20 + 411 + 351 + + + + + 10 + 0 + + + + Qt::ImhNone + + + 30 + + + true + + + 2 + + + true + + + 40 + + + 40 + + + true + + + 30 + + + + + + + + diff --git a/GC-3.6.1-T3/src/images.rcc b/GC-3.6.1-T3/src/images.rcc new file mode 100644 index 0000000..e5149ba --- /dev/null +++ b/GC-3.6.1-T3/src/images.rcc @@ -0,0 +1,157 @@ +/**************************************************************************** +** Resource object code +** +** Created: Fri 10. Feb 22:39:40 2012 +** by: The Resource Compiler for Qt version 4.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/down.gif + 0x0,0x0,0x0,0xbe, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xc0,0xc0,0xc0,0x99,0x99,0x99,0x40,0x40,0x40,0xe0,0xe0, + 0xe0,0x10,0x10,0x10,0x80,0x80,0x80,0xb0,0xb0,0xb0,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6b, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x95,0x2,0x9c, + 0x68,0xaa,0xae,0xa8,0x72,0x1d,0x6c,0xcc,0x1e,0x18,0x21,0xdf,0x28,0x91,0x15,0xb8, + 0x5c,0x68,0x6,0x58,0x4f,0x75,0x30,0x6c,0x6c,0xc3,0x94,0x8e,0xc3,0x4b,0x2,0x7e, + 0x1d,0x83,0x13,0x60,0xf4,0x20,0x92,0x88,0xd0,0xa2,0xb7,0x10,0x31,0x7a,0x8c,0xd1, + 0x55,0x96,0x25,0x9,0x62,0x2,0x92,0x64,0x10,0x1b,0xa8,0x25,0x8d,0x55,0xe3,0x3d, + 0x39,0xa3,0xd2,0xf4,0x75,0xca,0x9d,0x97,0x4,0x4e,0x1,0x7d,0x14,0x7,0x34,0x82, + 0x13,0x9,0x9,0x86,0x8a,0x8b,0x8c,0x8d,0x8e,0x8c,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/right.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xbb,0x2a,0x86,0x2b,0x4b,0xc0, + 0xe1,0xcc,0x2d,0xa0,0x17,0x31,0x9e,0xea,0xba,0x3,0xc1,0x87,0x2,0x2,0x79,0xc4, + 0x92,0xd1,0x88,0x48,0x8e,0x96,0xc6,0x5,0xc3,0x9,0x5d,0x36,0x89,0xd5,0xe5,0x40, + 0xe0,0xcb,0x42,0x23,0x3d,0x97,0x17,0xba,0x95,0x8d,0xab,0x81,0xb0,0xea,0x5c,0x3d, + 0x24,0x58,0x6c,0xa8,0x1b,0x1e,0x7,0x6,0xc4,0xf5,0x32,0x9e,0x1d,0xc1,0xb1,0xf5, + 0x33,0x67,0xf,0x49,0x5e,0x52,0x54,0x55,0x83,0x4e,0x34,0x4b,0x48,0x8a,0x8b,0x41, + 0x43,0x8e,0x22,0x47,0x6a,0x8e,0x35,0x37,0x92,0x24,0xa,0x99,0x9c,0x9d,0x9e,0x32, + 0x21,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/up.gif + 0x0,0x0,0x0,0xbd, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xbf,0xbf,0xbf,0x99,0x99,0x99,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x80,0x80,0x80,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6a, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x61,0x92,0x90, + 0x99,0x71,0x1c,0x6,0x7a,0x5,0x0,0x10,0xb8,0xd5,0x10,0xc7,0x3,0x2d,0x19,0xc2, + 0xd,0x8,0x2d,0x5a,0xc3,0x17,0x6b,0xd0,0x6c,0x44,0x9c,0xab,0x97,0xfc,0xa1,0x10, + 0xcd,0x1b,0x62,0xc4,0x88,0xfa,0x18,0xa2,0x85,0xf5,0xb6,0x8,0x41,0xb7,0xd2,0x8f, + 0x1,0x4c,0xc,0x72,0xa,0x64,0x5f,0xa1,0x43,0x48,0x13,0x9,0x1b,0x95,0xdb,0xc7, + 0xd2,0xa0,0xe7,0xea,0x4c,0x1b,0xff,0xbe,0xc8,0xf9,0x74,0x66,0x13,0xa,0x80,0x49, + 0xa,0x3a,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x16,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/left.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xeb,0xbe,0x86,0xf2,0xba,0xce, + 0x1,0xcc,0xab,0x51,0x0,0x3c,0x9e,0x12,0x36,0xde,0xcd,0x57,0xd2,0x9,0x85,0x44, + 0x12,0xe2,0x78,0x4c,0x4a,0x18,0xb,0x66,0x93,0xb8,0x94,0x4e,0x67,0x82,0x81,0x95, + 0x39,0x33,0x44,0xb6,0xd2,0x57,0x16,0x1c,0x66,0x19,0x2,0x64,0x2b,0x2b,0x11,0x4c, + 0x73,0x57,0x6c,0x77,0x99,0x85,0x96,0x23,0x5d,0x63,0x3b,0xee,0x2b,0xf7,0xe5,0xc9, + 0x49,0xf,0x69,0x4e,0x50,0x60,0x4e,0x22,0x82,0x6a,0x87,0x12,0x46,0x6f,0x8b,0x12, + 0x40,0x57,0x8f,0x8d,0x43,0x8f,0x23,0x35,0x95,0x96,0x23,0x32,0x9a,0x9d,0x9e,0x49, + 0x21,0x0,0x3b, + +}; + +static const unsigned char qt_resource_name[] = { + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // down.gif + 0x0,0x8, + 0x6,0xe1,0x40,0x96, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // right.gif + 0x0,0x9, + 0xd,0xf7,0xbc,0x16, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // up.gif + 0x0,0x6, + 0x7,0xc3,0x4d,0xf6, + 0x0,0x75, + 0x0,0x70,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // left.gif + 0x0,0x8, + 0xb,0xd7,0x43,0xb6, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/img + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2, + // :/img/down.gif + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/up.gif + 0x0,0x0,0x0,0x3a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xba, + // :/img/left.gif + 0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0x7b, + // :/img/right.gif + 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc2, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources)) + +int QT_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources)) + diff --git a/GC-3.6.1-T3/src/img/Thumbs.db b/GC-3.6.1-T3/src/img/Thumbs.db new file mode 100644 index 0000000..7d8e59e Binary files /dev/null and b/GC-3.6.1-T3/src/img/Thumbs.db differ diff --git a/GC-3.6.1-T3/src/img/down.PNG b/GC-3.6.1-T3/src/img/down.PNG new file mode 100644 index 0000000..f157397 Binary files /dev/null and b/GC-3.6.1-T3/src/img/down.PNG differ diff --git a/GC-3.6.1-T3/src/img/down.gif b/GC-3.6.1-T3/src/img/down.gif new file mode 100644 index 0000000..d55ee1d Binary files /dev/null and b/GC-3.6.1-T3/src/img/down.gif differ diff --git a/GC-3.6.1-T3/src/img/left.PNG b/GC-3.6.1-T3/src/img/left.PNG new file mode 100644 index 0000000..7562000 Binary files /dev/null and b/GC-3.6.1-T3/src/img/left.PNG differ diff --git a/GC-3.6.1-T3/src/img/left.gif b/GC-3.6.1-T3/src/img/left.gif new file mode 100644 index 0000000..9b40ffc Binary files /dev/null and b/GC-3.6.1-T3/src/img/left.gif differ diff --git a/GC-3.6.1-T3/src/img/logotiny.PNG b/GC-3.6.1-T3/src/img/logotiny.PNG new file mode 100644 index 0000000..4cade12 Binary files /dev/null and b/GC-3.6.1-T3/src/img/logotiny.PNG differ diff --git a/GC-3.6.1-T3/src/img/logotiny.gif b/GC-3.6.1-T3/src/img/logotiny.gif new file mode 100644 index 0000000..baf6126 Binary files /dev/null and b/GC-3.6.1-T3/src/img/logotiny.gif differ diff --git a/GC-3.6.1-T3/src/img/right.PNG b/GC-3.6.1-T3/src/img/right.PNG new file mode 100644 index 0000000..858b59f Binary files /dev/null and b/GC-3.6.1-T3/src/img/right.PNG differ diff --git a/GC-3.6.1-T3/src/img/right.gif b/GC-3.6.1-T3/src/img/right.gif new file mode 100644 index 0000000..59dfad3 Binary files /dev/null and b/GC-3.6.1-T3/src/img/right.gif differ diff --git a/GC-3.6.1-T3/src/img/up.PNG b/GC-3.6.1-T3/src/img/up.PNG new file mode 100644 index 0000000..e9b3dbb Binary files /dev/null and b/GC-3.6.1-T3/src/img/up.PNG differ diff --git a/GC-3.6.1-T3/src/img/up.gif b/GC-3.6.1-T3/src/img/up.gif new file mode 100644 index 0000000..b6bf918 Binary files /dev/null and b/GC-3.6.1-T3/src/img/up.gif differ diff --git a/GC-3.6.1-T3/src/img/zapmaker-logo-130.png b/GC-3.6.1-T3/src/img/zapmaker-logo-130.png new file mode 100644 index 0000000..5963823 Binary files /dev/null and b/GC-3.6.1-T3/src/img/zapmaker-logo-130.png differ diff --git a/itemtobase.cpp b/GC-3.6.1-T3/src/itemtobase.cpp similarity index 94% rename from itemtobase.cpp rename to GC-3.6.1-T3/src/itemtobase.cpp index b567b4c..2ca5b42 100644 --- a/itemtobase.cpp +++ b/GC-3.6.1-T3/src/itemtobase.cpp @@ -5,6 +5,10 @@ ItemToBase::ItemToBase(int index1) { } +ItemToBase::~ItemToBase() +{ +} + void ItemToBase::setParams(double scale1, double height1, double offsetx1, double offsety1) { scale = scale1; @@ -21,4 +25,4 @@ double ItemToBase::screenX(double fx) double ItemToBase::screenY(double fy) { return height - ((fy * scale) + offsety); -} +} \ No newline at end of file diff --git a/GC-3.6.1-T3/src/itemtobase.h b/GC-3.6.1-T3/src/itemtobase.h new file mode 100644 index 0000000..2ad8f25 --- /dev/null +++ b/GC-3.6.1-T3/src/itemtobase.h @@ -0,0 +1,37 @@ +#ifndef ITEMTOBASE_H +#define ITEMTOBASE_H +#include +#include "stdio.h" +#include "positem.h" + +class ItemToBase +{ +public: + ItemToBase(int index); + virtual ~ItemToBase() ; + + virtual void moveToFirst(QPainterPath& path) = 0; + virtual void addToPath(QPainterPath& path) = 0; + virtual PosItem computeExtents() = 0; + + virtual double getXScr() = 0; + virtual double getYScr() = 0; + virtual double getXRaw() = 0; + virtual double getYRaw() = 0; + + void setParams(double scale, double height, double offsetx, double offsety); + + double screenX(double x); + double screenY(double y); + + int getIndex() { return index; } + +protected: + double scale; + double height; + double offsetx; + double offsety; + int index; +}; + +#endif // ITEMTOBASE_H diff --git a/GC-3.6.1-T3/src/lineitem.cpp b/GC-3.6.1-T3/src/lineitem.cpp new file mode 100644 index 0000000..8bfba6f --- /dev/null +++ b/GC-3.6.1-T3/src/lineitem.cpp @@ -0,0 +1,61 @@ +#include "lineitem.h" + +LineItem::LineItem(double x1, double y1, int index1) + : ItemToBase(index1), x(x1), y(y1) +{ +} + +LineItem::LineItem(double x1, double y1, bool stretchX1, double length1) +: ItemToBase(0), x(x1), y(y1), stretchX(stretchX1), length(length1) +{ +} + +PosItem LineItem::computeExtents() +{ + PosItem curr(x, y, x, y); + return curr; +} + +void LineItem::addToPath(QPainterPath& path) +{ + path.lineTo(screenX(x), screenY(y)); +} + +void LineItem::moveToFirst(QPainterPath& path) +{ + path.moveTo(screenX(x), screenY(y)); +} + +double LineItem::getXScr() +{ + return screenX(x); +} + +double LineItem::getYScr() +{ + return screenY(y); +} + +double LineItem::getXRaw() +{ + return x; +} + +double LineItem::getYRaw() +{ + return y; +} + +void LineItem::drawTo(QPainterPath& path) +{ + if (stretchX) + { + path.moveTo(screenX(x), screenY(y) + length); + path.lineTo(screenX(x), screenY(y) - length); + } + else + { + path.moveTo(screenX(x) + length, screenY(y)); + path.lineTo(screenX(x) - length, screenY(y)); + } +} diff --git a/GC-3.6.1-T3/src/lineitem.h b/GC-3.6.1-T3/src/lineitem.h new file mode 100644 index 0000000..6969e0e --- /dev/null +++ b/GC-3.6.1-T3/src/lineitem.h @@ -0,0 +1,29 @@ +#ifndef LINEITEM_H +#define LINEITEM_H +#include "itemtobase.h" + +class LineItem : public ItemToBase +{ +public: + LineItem(double x1, double y1, int index); + LineItem(double x1, double y1, bool stretchX, double length); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + void drawTo(QPainterPath& path); + + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; + bool stretchX; + double length; +}; + +#endif // LINEITEM_H diff --git a/GC-3.6.1-T3/src/log4qt/appender.h b/GC-3.6.1-T3/src/log4qt/appender.h new file mode 100644 index 0000000..81f6aa4 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/appender.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ********************************************************************************/ + +#ifndef LOG4QT_APPENDER_H +#define LOG4QT_APPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" + +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class LoggingEvent; + + /*! + * \brief The class Appender is the base class for all Appenders. + * + * To allow the whole hirarchy to be an ascendant of QObject Appender is + * not an interface. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Appender : public LogObject + { + Q_OBJECT + + /*! + * The property holds the Layout used by the Appender. + * + * \sa layout(), setLayout() + */ + Q_PROPERTY(Layout* layout READ layout WRITE setLayout) + + /*! + * The property holds the name of the Appender. + * + * \sa name(), setName() + */ + Q_PROPERTY(QString name READ name WRITE setName) + + /*! + * The property holds if the Appender requires a Layout or not. + * + * \sa requiresLayout(), setRequiresLayout() + */ + Q_PROPERTY(bool requiresLayout READ requiresLayout) + + public: + Appender(QObject *pParent = 0); + virtual ~Appender(); + private: + Appender(const Appender &rOther); // Not implemented + Appender &operator=(const Appender &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const = 0; + virtual QString name() const = 0; + virtual Layout *layout() const = 0; + virtual bool requiresLayout() const = 0; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout) = 0; + virtual void setName(const QString &rName) = 0; + + virtual void addFilter(Filter *pFilter) = 0; + virtual void clearFilters() = 0; + virtual void close() = 0; + virtual void doAppend(const LoggingEvent &rEvent) = 0; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender::Appender(QObject *pParent) : + LogObject(pParent) + {} + + inline Appender::~Appender() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Appender, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_APPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/appenderskeleton.cpp b/GC-3.6.1-T3/src/log4qt/appenderskeleton.cpp new file mode 100644 index 0000000..d9f784b --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/appenderskeleton.cpp @@ -0,0 +1,261 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/appenderskeleton.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" +#include "log4qt/spi/filter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + ***************************************************************************/ + + + /*! + * \brief The class RecursionGuardLocker controls a boolean flag. + * + * It is a helper class to control a boolean flag. The class sets the flag + * on creation and resets it on destruction. + */ + class RecursionGuardLocker + { + public: + RecursionGuardLocker(bool *pGuard); + ~RecursionGuardLocker(); + private: + RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented + RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented + private: + bool *mpGuard; + }; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: RecursionGuardLocker + ***************************************************************************/ + + + inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard) + { + Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null"); + + mpGuard = pGuard; + *mpGuard = true; + } + + + inline RecursionGuardLocker::~RecursionGuardLocker() + { + *mpGuard = false; + }; + + + + /************************************************************************** + * Class implementation: AppenderSkeleton + **************************************************************************/ + + + AppenderSkeleton::AppenderSkeleton(QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(true), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + AppenderSkeleton::AppenderSkeleton(const bool isActive, + QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(isActive), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + void AppenderSkeleton::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"), + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return; + } + mIsActive = true; + } + + + void AppenderSkeleton::addFilter(Filter *pFilter) + { + if(!pFilter) + { + logger()->warn("Adding null Filter to Appender '%1'", name()); + return; + } + + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = pFilter; + if (mpHeadFilter) + mpHeadFilter->setNext(pFilter); + else + mpHeadFilter = pFilter; + } + + + void AppenderSkeleton::clearFilters() + { + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = 0; + mpHeadFilter = 0; + } + + + void AppenderSkeleton::close() + { + QMutexLocker locker(&mObjectGuard); + + mIsClosed = true; + mIsActive = false; + } + + + void AppenderSkeleton::doAppend(const LoggingEvent &rEvent) + { + // The mutex serialises concurrent access from multiple threads. + // - e.g. two threads using the same logger + // - e.g. two threads using different logger with the same appender + // + // A call from the same thread will pass the mutex (QMutex::Recursive) + // and get to the recursion guard. The recursion guard blocks recursive + // invocation and prevents a possible endless loop. + // - e.g. an appender logs an error with a logger that uses it + + QMutexLocker locker(&mObjectGuard); + + if (mAppendRecursionGuard) + return; + + RecursionGuardLocker recursion_locker(&mAppendRecursionGuard); + + if (!checkEntryConditions()) + return; + if (!isAsSevereAsThreshold(rEvent.level())) + return; + + Filter *p_filter = mpHeadFilter; + while(p_filter) + { + Filter::Decision decision = p_filter->decide(rEvent); + if (decision == Filter::ACCEPT) + break; + else if (decision == Filter::DENY) + return; + else + p_filter = p_filter->next(); + } + + append(rEvent); + } + + + bool AppenderSkeleton::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!isActive()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"), + APPENDER_NOT_ACTIVATED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (isClosed()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"), + APPENDER_CLOSED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"), + APPENDER_USE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/appenderskeleton.h b/GC-3.6.1-T3/src/log4qt/appenderskeleton.h new file mode 100644 index 0000000..6f252b3 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/appenderskeleton.h @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_APPENDERSKELETON_H +#define LOG4QT_APPENDERSKELETON_H + + +/****************************************************************************** + * Dependencies +******************************************************************************/ + +#include "log4qt/appender.h" + +#include +#include "log4qt/helpers/logobjectptr.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class Logger; + class LoggingEvent; + + /*! + * \brief The class AppenderSkeleton implements general Appender functionality. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class AppenderSkeleton : public Appender + { + Q_OBJECT + + /*! + * The property holds if the Appender has been activated. + * + * \sa isActive() + */ + Q_PROPERTY(bool isActive READ isActive) + + /*! + * The property holds if the Appender has been closed. + * + * \sa isClosed() + */ + Q_PROPERTY(bool isClosed READ isClosed) + + /*! + * The property holds the threshold level used by the Appender. + * + * \sa threshold(), setThreshold() + */ + Q_PROPERTY(Level threshold READ threshold WRITE setThreshold) + + public: + AppenderSkeleton(QObject *pParent = 0); + protected: + AppenderSkeleton(const bool isActive, + QObject *pParent = 0); + public: + // virtual ~AppenderSkeleton(); Use compiler default + private: + AppenderSkeleton(const AppenderSkeleton &rOther); // Not implemented + AppenderSkeleton &operator=(const AppenderSkeleton &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const; + virtual Layout *layout() const; + bool isActive() const; + bool isClosed() const; + virtual QString name() const; + Level threshold() const; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout); + virtual void setName(const QString &rName); + void setThreshold(Level level); + + virtual void activateOptions(); + virtual void addFilter(Filter *pFilter); + virtual void clearFilters(); + virtual void close(); + + /*! + * Performs checks and delegates the actuall appending to the subclass + * specific append() function. + * + * \sa append(), checkEntryConditions(), isAsSevereAsThreshold(), Filter + */ + virtual void doAppend(const LoggingEvent &rEvent); + + // JAVA: void finalize(); + Filter* firstFilter() const; + bool isAsSevereAsThreshold(Level level) const; + + protected: + virtual void append(const LoggingEvent &rEvent) = 0; + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. + * + * The checked conditions are: + * - That the appender has been activated (APPENDER_NOT_ACTIVATED_ERROR) + * - That the appender was not closed (APPENDER_CLOSED_ERROR) + * - That the appender has a layout set, if it requires one + * (logging_error(APPENDER_USE_MISSING_LAYOUT_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by doAppend(). The doAppend() function calls the subclass + * specific checkEntryConditions() function. The function checks the + * class specific conditions and calls checkEntryConditions() of + * it's parent class. The last function called is + * AppenderSkeleton::checkEntryConditions(). + * + * \sa doAppend() + */ + virtual bool checkEntryConditions() const; + + protected: + mutable QMutex mObjectGuard; + private: + bool mAppendRecursionGuard; + volatile bool mIsActive; + volatile bool mIsClosed; + LogObjectPtr mpLayout; + Level mThreshold; + LogObjectPtr mpHeadFilter; + LogObjectPtr mpTailFilter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter *AppenderSkeleton::filter() const + { QMutexLocker locker(&mObjectGuard); + return mpHeadFilter; } + + inline Layout *AppenderSkeleton::layout() const + { QMutexLocker locker(&mObjectGuard); + return mpLayout; } + + inline QString AppenderSkeleton::name() const + { QMutexLocker locker(&mObjectGuard); + return objectName(); } + + inline Level AppenderSkeleton::threshold() const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void AppenderSkeleton::setLayout(Layout *pLayout) + { QMutexLocker locker(&mObjectGuard); + mpLayout = pLayout; } + + inline void AppenderSkeleton::setName(const QString &rName) + { QMutexLocker locker(&mObjectGuard); + setObjectName(rName); } + + inline void AppenderSkeleton::setThreshold(Level level) + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool AppenderSkeleton::isActive() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsActive; } + + inline bool AppenderSkeleton::isClosed() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsClosed; } + + inline Filter *AppenderSkeleton::firstFilter() const + { QMutexLocker locker(&mObjectGuard); + return filter(); } + + inline bool AppenderSkeleton::isAsSevereAsThreshold(Level level) const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return (mThreshold <= level); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::AppenderSkeleton, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_APPENDERSKELETON_H diff --git a/GC-3.6.1-T3/src/log4qt/basicconfigurator.cpp b/GC-3.6.1-T3/src/log4qt/basicconfigurator.cpp new file mode 100644 index 0000000..280b88d --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/basicconfigurator.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/basicconfigurator.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/logmanager.h" +#include "log4qt/patternlayout.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: BasicConfigurator + **************************************************************************/ + + + bool BasicConfigurator::configure() + { + LogObjectPtr list = new ListAppender; + list->setName(QLatin1String("BasicConfigurator")); + list->setConfiguratorList(true); + list->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(list); + + PatternLayout *p_layout = new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout->setName(QLatin1String("BasicConfigurator TTCC")); + p_layout->activateOptions(); + ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("BasicConfigurator stdout")); + p_appender->activateOptions(); + LogManager::rootLogger()->addAppender(p_appender); + + LogManager::logLogger()->removeAppender(list); + ConfiguratorHelper::setConfigureError(list->list()); + return (list->list().count() == 0); + } + + + void BasicConfigurator::configure(Appender *pAppender) + { + LogManager::rootLogger()->addAppender(pAppender); + } + + + void BasicConfigurator::resetConfiguration() + { + LogManager::resetConfiguration(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/basicconfigurator.h b/GC-3.6.1-T3/src/log4qt/basicconfigurator.h new file mode 100644 index 0000000..c301501 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/basicconfigurator.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_BASICCONFIGURATOR_H +#define LOG4QT_BASICCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Appender; + + /*! + * \brief The class BasicConfigurator provides a simple package + * configuration. + * + * \note All the functions declared in this class are thread-safe. + */ + class BasicConfigurator + { + private: + BasicConfigurator(); // Not implemented + // BasicConfigurator(const BasicConfigurator &rOther); // Use compiler default + // virtual ~BasicConfigurator(); // Use compiler default + // BasicConfigurator &operator=(const BasicConfigurator &rOther); // Use compiler default + + public: + static bool configure(); + static void configure(Appender *pAppender); + static void resetConfiguration(); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namspace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::BasicConfigurator, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_BASICCONFIGURATOR_H diff --git a/GC-3.6.1-T3/src/log4qt/consoleappender.cpp b/GC-3.6.1-T3/src/log4qt/consoleappender.cpp new file mode 100644 index 0000000..1b4fe03 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/consoleappender.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/consoleappender.h" + +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConsoleAppender + **************************************************************************/ + + + ConsoleAppender::ConsoleAppender(QObject *pParent) : + WriterAppender(pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + setTarget(rTarget); + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(target), + mpTextStream(0) + { + } + + + ConsoleAppender::~ConsoleAppender() + { + close(); + } + + + QString ConsoleAppender::target() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + if (mTarget == STDOUT_TARGET) + return QLatin1String("STDOUT_TARGET"); + else + return QLatin1String("STDERR_TARGET"); + } + + + void ConsoleAppender::setTarget(const QString &rTarget) + { + bool ok; + Target target = (Target)OptionConverter::toTarget(rTarget, &ok); + if (ok) + setTarget(target); + } + + + void ConsoleAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + closeStream(); + + if (mTarget == STDOUT_TARGET) + mpTextStream = new QTextStream(stdout); + else + mpTextStream = new QTextStream(stderr); + setWriter(mpTextStream); + + WriterAppender::activateOptions(); + } + + + void ConsoleAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeStream(); + } + + + void ConsoleAppender::closeStream() + { + // Q_ASSERT_X(, "ConsoleAppender::closeStream()", "Lock must be held by caller") + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ConsoleAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString target; + if (mTarget == STDOUT_TARGET) + target = QLatin1String("STDOUT"); + else + target = QLatin1String("STDERR"); + + rDebug.nospace() << "ConsoleAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "target:" << target << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/consoleappender.h b/GC-3.6.1-T3/src/log4qt/consoleappender.h new file mode 100644 index 0000000..466015d --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/consoleappender.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CONSOLEAPPENDER_H +#define LOG4QT_CONSOLEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class ConsoleAppender appends to stdout or stderr. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ConsoleAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds the target used by the appender. + * + * The default is STDOUT_TARGET for the standard output. + * + * \sa Target, target(), setTarget() + */ + Q_PROPERTY(QString target READ target WRITE setTarget) + + public: + /*! + * The enum defines the possible output targets + * + * \sa target(), setTarget() + */ + enum Target { + /*! The output target is standard out. */ + STDOUT_TARGET, + /*! The output target is standard error. */ + STDERR_TARGET + }; + Q_ENUMS(Target) + + ConsoleAppender(QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent = 0); + + /*! + * Creates a ConsoleAppender with the layout \a pLayout, the target + * value specified by the \a target constant and the parent + * \a pParent. + */ + ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent = 0); + + virtual ~ConsoleAppender(); + private: + ConsoleAppender(const ConsoleAppender &rOther); // Not implemented + ConsoleAppender &operator=(const ConsoleAppender &rOther); // Not implemented + + public: + // JAVA: bool follow() const; + QString target() const; + // JAVA: void setFollow(bool follow); + void setTarget(const QString &rTarget); + + /*! + * Sets the target to the value specified by the \a target constant. + */ + void setTarget(Target target); + + virtual void activateOptions(); + virtual void close(); + + protected: + void closeStream(); + + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ConsoleAppender(name:"CA" filter:0x0 isactive:true isclosed:false + * layout:"PL" target:"STDERR" referenceCount:1 + * threshold:"WARN_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + #endif // QT_NO_DEBUG_STREAM + + private: + volatile Target mTarget; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline void ConsoleAppender::setTarget(Target target) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mTarget = target; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConsoleAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CONSOLEAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.cpp b/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.cpp new file mode 100644 index 0000000..0590f16 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.cpp @@ -0,0 +1,352 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/dailyrollingfileappender.h" + +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DailyRollingFileAppender + **************************************************************************/ + + + DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mDatePattern() + { + setDatePattern(DAILY_ROLLOVER); + } + + + DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mDatePattern() + { + setDatePattern(rDatePattern); + } + + + DailyRollingFileAppender::~DailyRollingFileAppender() + { + close(); + } + + + void DailyRollingFileAppender::setDatePattern(DatePattern datePattern) + { + switch (datePattern) + { + case MINUTELY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm")); + break; + case HOURLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh")); + break; + case HALFDAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-a")); + break; + case DAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd")); + break; + case WEEKLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-ww")); + break; + case MONTHLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM")); + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant"); + setDatePattern(DAILY_ROLLOVER); + }; + } + + + void DailyRollingFileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + computeFrequency(); + if (!mActiveDatePattern.isEmpty()) + { + computeRollOverTime(); + FileAppender::activateOptions(); + } + } + + + void DailyRollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller") + + if (QDateTime::currentDateTime() > mRollOverTime) + rollOver(); + FileAppender::append(rEvent); + } + + + bool DailyRollingFileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (mActiveDatePattern.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"), + APPENDER_USE_INVALID_PATTERN_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return FileAppender::checkEntryConditions(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "DailyRollingFileAppender(" + << "name:" << name() << " " + << "activedatepattern:" << mActiveDatePattern << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "datepattern:" << datePattern() << " " + << "encoding:" << codec_name << " " + << "frequency:" << frequencyToString() << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "rollovertime:" << mRollOverTime + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void DailyRollingFileAppender::computeFrequency() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller") + + const DateTime start_time(QDate(1999, 1, 1), QTime(0, 0)); + const QString start_string = start_time.toString(mDatePattern); + mActiveDatePattern.clear(); + + if (start_string != static_cast(start_time.addSecs(60)).toString(mDatePattern)) + mFrequency = MINUTELY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60)).toString(mDatePattern)) + mFrequency = HOURLY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60 * 12)).toString(mDatePattern)) + mFrequency = HALFDAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(1)).toString(mDatePattern)) + mFrequency = DAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(7)).toString(mDatePattern)) + mFrequency = WEEKLY_ROLLOVER; + else if (start_string != static_cast(start_time.addMonths(1)).toString(mDatePattern)) + mFrequency = MONTHLY_ROLLOVER; + else + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"), + APPENDER_INVALID_PATTERN_ERROR); + e << mDatePattern << name(); + logger()->error(e); + return; + } + + mActiveDatePattern = mDatePattern; + logger()->trace("Frequency set to %2 using date pattern %1", + mActiveDatePattern, + frequencyToString()); + } + + + void DailyRollingFileAppender::computeRollOverTime() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern"); + + QDateTime now = QDateTime::currentDateTime(); + QDate now_date = now.date(); + QTime now_time = now.time(); + QDateTime start; + + switch (mFrequency) + { + case MINUTELY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + now_time.minute(), + 0, 0)); + mRollOverTime = start.addSecs(60); + } + break; + case HOURLY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + 0, 0, 0)); + mRollOverTime = start.addSecs(60*60); + } + break; + case HALFDAILY_ROLLOVER: + { + int hour = now_time.hour(); + if (hour >= 12) + hour = 12; + else + hour = 0; + start = QDateTime(now_date, + QTime(hour, 0, 0, 0)); + mRollOverTime = start.addSecs(60*60*12); + } + break; + case DAILY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(0, 0, 0, 0)); + mRollOverTime = start.addDays(1); + } + break; + case WEEKLY_ROLLOVER: + { + // QT numbers the week days 1..7. The week starts on Monday. + // Change it to being numbered 0..6, starting with Sunday. + int day = now_date.dayOfWeek(); + if (day == Qt::Sunday) + day = 0; + start = QDateTime(now_date, + QTime(0, 0, 0, 0)).addDays(-1 * day); + mRollOverTime = start.addDays(7); + } + break; + case MONTHLY_ROLLOVER: + { + start = QDateTime(QDate(now_date.year(), + now_date.month(), + 1), + QTime(0, 0, 0, 0)); + mRollOverTime = start.addMonths(1); + } + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant"); + mRollOverTime = QDateTime::fromTime_t(0); + } + + mRollOverSuffix = static_cast(start).toString(mActiveDatePattern); + Q_ASSERT_X(static_cast(now).toString(mActiveDatePattern) == mRollOverSuffix, + "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval"); + Q_ASSERT_X(mRollOverSuffix != static_cast(mRollOverTime).toString(mActiveDatePattern), + "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover"); + + logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3", + now, + start, + mRollOverTime); + } + + + QString DailyRollingFileAppender::frequencyToString() const + { + QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern")); + return QLatin1String(meta_enum.valueToKey(mFrequency)); + } + + + void DailyRollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern"); + + QString roll_over_suffix = mRollOverSuffix; + computeRollOverTime(); + if (roll_over_suffix == mRollOverSuffix) + return; + + closeFile(); + + QString target_file_name = file() + roll_over_suffix; + QFile f(target_file_name); + if (f.exists() && !removeFile(f)) + return; + f.setFileName(file()); + if (!renameFile(f, target_file_name)) + return; + openFile(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.h b/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.h new file mode 100644 index 0000000..e3fe638 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/dailyrollingfileappender.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DAILYROLLINGFILEAPPENDER_H +#define LOG4QT_DAILYROLLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DailyRollingFileAppender extends FileAppender so that the + * underlying file is rolled over at a specified frequency. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class DailyRollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the date pattern used by the appender. + * + * The default is DAILY_ROLLOVER for rollover at midnight each day. + * + * \sa datePattern(), setDatePattern() + */ + Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern) + + public: + /*! + * The enum DatePattern defines constants for date patterns. + * + * \sa setDatePattern(DatePattern) + */ + enum DatePattern + { + /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */ + MINUTELY_ROLLOVER = 0, + /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */ + HOURLY_ROLLOVER, + /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */ + HALFDAILY_ROLLOVER, + /*! The daily date pattern string is "'.'yyyy-MM-dd". */ + DAILY_ROLLOVER, + /*! The weekly date pattern string is "'.'yyyy-ww". */ + WEEKLY_ROLLOVER, + /*! The monthly date pattern string is "'.'yyyy-MM". */ + MONTHLY_ROLLOVER + }; + Q_ENUMS(DatePattern) + + DailyRollingFileAppender(QObject *pParent = 0); + DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent = 0); + virtual ~DailyRollingFileAppender(); + private: + DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented + DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented + + public: + QString datePattern() const; + + /*! + * Sets the datePattern to the value specified by the \a datePattern + * constant. + */ + void setDatePattern(DatePattern datePattern); + + void setDatePattern(const QString &rDatePattern); + + virtual void activateOptions(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * FileAppender::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm" + * appendfile:false bufferedio:true + * datepattern:"'.'yyyy-MM-dd-hh-mm" + * encoding:"" frequency:"MINUTELY_ROLLOVER" + * file:"/log.txt" filter:0x0 immediateflush:true + * isactive:true isclosed:false layout:"TTCC" + * referencecount:1 + * rollovertime:QDateTime("Mon Oct 22 05:23:00 2007") + * threshold: "NULL" writer: 0x0 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void computeFrequency(); + void computeRollOverTime(); + QString frequencyToString() const; + void rollOver(); + + private: + QString mDatePattern; + DatePattern mFrequency; + QString mActiveDatePattern; + QDateTime mRollOverTime; + QString mRollOverSuffix; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString DailyRollingFileAppender::datePattern() const + { QMutexLocker locker(&mObjectGuard); + return mDatePattern; } + + inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern) + { QMutexLocker locker(&mObjectGuard); + mDatePattern = rDatePattern; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DailyRollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DAILYROLLINGFILEAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/fileappender.cpp b/GC-3.6.1-T3/src/log4qt/fileappender.cpp new file mode 100644 index 0000000..265634f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/fileappender.cpp @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/fileappender.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: FileAppender + **************************************************************************/ + + + FileAppender::FileAppender(QObject *pParent) : + WriterAppender(pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(buffered), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::~FileAppender() + { + close(); + } + + + void FileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (mFileName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"), + APPENDER_ACTIVATE_MISSING_FILE_ERROR); + e << name(); + logger()->error(e); + return; + } + closeFile(); + openFile(); + WriterAppender::activateOptions(); + } + + + void FileAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeFile(); + } + + + bool FileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!mpFile || !mpTextStream) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"), + APPENDER_NO_OPEN_FILE_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return WriterAppender::checkEntryConditions(); + } + + + void FileAppender::closeFile() + { + // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller") + + if (mpFile) + logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name()); + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + delete mpFile; + mpFile = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug FileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "FileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool FileAppender::handleIoErrors() const + { + // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller") + + if (mpFile->error() == QFile::NoError) + return false; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"), + APPENDER_WRITING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return true; + } + + + void FileAppender::openFile() + { + Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file"); + + QFileInfo file_info(mFileName); + QDir parent_dir = file_info.dir(); + if (!parent_dir.exists()) + { + logger()->trace("Creating missing parent directory for file %1", mFileName); + QString name = parent_dir.dirName(); + parent_dir.cdUp(); + parent_dir.mkdir(name); + } + + + mpFile = new QFile(mFileName); + QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text; + if (mAppendFile) + mode |= QIODevice::Append; + else + mode |= QIODevice::Truncate; + if (!mBufferedIo) + mode |= QIODevice::Unbuffered; + if (!mpFile->open(mode)) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + APPENDER_OPENING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return; + } + mpTextStream = new QTextStream(mpFile); + setWriter(mpTextStream); + logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name()); + } + + + bool FileAppender::removeFile(QFile &rFile) const + { + if (rFile.remove()) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"), + APPENDER_REMOVE_FILE_ERROR); + e << rFile.fileName() << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + bool FileAppender::renameFile(QFile &rFile, + const QString &rFileName) const + { + logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName); + if (rFile.rename(rFileName)) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"), + APPENDER_RENAMING_FILE_ERROR); + e << rFile.fileName() << rFileName << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/fileappender.h b/GC-3.6.1-T3/src/log4qt/fileappender.h new file mode 100644 index 0000000..2479d4e --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/fileappender.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILEAPPENDER_H +#define LOG4QT_FILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class FileAppender appends log events to a file. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class FileAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds, if the output is appended to the file. + * + * The default is false for not appending. + * + * \sa appendFile(), setAppendFile() + */ + Q_PROPERTY(bool appendFile READ appendFile WRITE setAppendFile) + + /*! + * The property holds, if the output is buffered. + * + * The default is true for buffering. + * + * \sa bufferedIo(), setBufferedIo() + */ + Q_PROPERTY(bool bufferedIo READ bufferedIo WRITE setBufferedIo) + + /*! + * The property holds the name of the file. + * + * \sa file(), setFile() + */ + Q_PROPERTY(QString file READ file WRITE setFile) + + public: + FileAppender(QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent = 0); + virtual ~FileAppender(); + private: + FileAppender(const FileAppender &rOther); // Not implemented + FileAppender &operator=(const FileAppender &rOther); // Not implemented + + public: + bool appendFile() const; + QString file() const; + bool bufferedIo() const; + // JAVA: int bufferSize() const; + void setAppendFile(bool append); + void setBufferedIo(bool buffered); + // JAVA: void setBufferSize(int bufferSize); + void setFile(const QString &rFileName); + + virtual void activateOptions(); + virtual void close(); + + protected: + /*! + * Tests if all entry conditions for using append() in this class are met. + * + * If a conditions is not met, an error is logged and the function returns + * false. Otherwise the result of WriterAppender::checkEntryConditions() + * is returned. + * + * The checked conditions are: + * - That a file is set and open (APPENDER_NO_OPEN_FILE_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeFile(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %FileAppender(name:"FA" appendfile:false bufferedio:true encoding:"" + * file:"/log.txt" filter: 0x0 immediateflush:true isactive:false + * isclosed:false layout:"TTCC" referencecount:2 + * threshold:"NULL" writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Checks for file I/O errrors. If an error is found it is logged and the + * function returns true. Otherwise false is returned. + */ + virtual bool handleIoErrors() const; + + /*! + * Opens the file for the appender based on the specified file name and + * mode. A text stream is created and passed on to the super class + * WriterAppender. + * + * If the parent directory of the specified file does not exists, + * it is created. + */ + void openFile(); + + /*! + * Removes the file \a rFile. If the operation is successful, true is + * returned. Otherwise an APPENDER_REMOVE_FILE_ERROR error is logged + * and false is returned. + */ + bool removeFile(QFile &rFile) const; + + /*! + * Renames the file \a rFile to \a rFileName. If the operation is + * successful, true is returned. Otherwise an + * APPENDER_RENAMING_FILE_ERROR error is logged and false is returned. + */ + bool renameFile(QFile &rFile, + const QString &rFileName) const; + + // JAVA: void setQWForFiles(Writer writer); + + private: + volatile bool mAppendFile; + volatile bool mBufferedIo; + QString mFileName; + QFile *mpFile; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool FileAppender::appendFile() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAppendFile; } + + inline QString FileAppender::file() const + { QMutexLocker locker(&mObjectGuard); + return mFileName; } + + inline bool FileAppender::bufferedIo() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mBufferedIo; } + + inline void FileAppender::setAppendFile(bool append) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mAppendFile = append; } + + inline void FileAppender::setBufferedIo(bool buffered) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mBufferedIo = buffered; } + + inline void FileAppender::setFile(const QString &rFileName) + { QMutexLocker locker(&mObjectGuard); + mFileName = rFileName; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::FileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_FILEAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/classlogger.cpp b/GC-3.6.1-T3/src/log4qt/helpers/classlogger.cpp new file mode 100644 index 0000000..50b6c7f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/classlogger.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/classlogger.h" + +#include +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ClassLogger + **************************************************************************/ + + + ClassLogger::ClassLogger() : + mpLogger(0) + { + } + + + Logger *ClassLogger::logger(const QObject *pObject) + { + Q_ASSERT_X(pObject, "ClassLogger::logger()", "pObject must not be null"); +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + if (!mpLogger) + q_atomic_test_and_set_ptr(&mpLogger, + 0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(mpLogger); +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + if (!static_cast(mpLogger)) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger)); +#else + if (!static_cast(mpLogger.loadAcquire())) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger.loadAcquire())); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/classlogger.h b/GC-3.6.1-T3/src/log4qt/helpers/classlogger.h new file mode 100644 index 0000000..065a852 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/classlogger.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CLASSLOGGER_H +#define LOG4QT_CLASSLOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The class Log4Qt::ClassLogger is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Logger; + + /*! + * \brief The class ClassLogger provides logging for a QObject derived + * class. + * + * The class ClassLogger provides a logger for a specified QObject derived + * object. It is used by \ref LOG4QT_DECLARE_QCLASS_LOGGER to implement the + * member functions provided by the macro. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa LOG4QT_DECLARE_QCLASS_LOGGER + */ + class ClassLogger + { + public: + /*! + * Creates a ClassLogger object. + */ + ClassLogger(); + // ~ClassLogger(); // Use compiler default + // ClassLogger(const ClassLogger &rOther); // Use compiler default + // ClassLogger &operator=(const ClassLogger &rOther); // Use compiler default + + /*! + * Returns a pointer to a Logger named after the class of the object + * \a pObject. + * + * On the first invocation the Logger is requested by a call to + * LogManager::logger(const char *pName). The pointer is stored to be + * returned on subsequent invocations. + * + * \sa LogManager::logger(const char *pName) + */ + Logger *logger(const QObject *pObject); + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile Logger *mpLogger; +#else + mutable QAtomicPointer mpLogger; +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::ClassLogger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CLASSLOGGER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.cpp b/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.cpp new file mode 100644 index 0000000..3b34f40 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/configuratorhelper.h" + +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConfiguratorHelper + **************************************************************************/ + + + ConfiguratorHelper::ConfiguratorHelper() : + mObjectGuard(), + mConfigurationFile(), + mpConfigureFunc(0), + mpConfigurationFileWatch(0), + mConfigureError() + { + } + + + ConfiguratorHelper::~ConfiguratorHelper() + { + delete mpConfigurationFileWatch; + } + + + LOG4QT_IMPLEMENT_INSTANCE(ConfiguratorHelper) + + + void ConfiguratorHelper::doConfigurationFileChanged(const QString &rFileName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mpConfigureFunc) + return; + mpConfigureFunc(rFileName); + // Shall we hold the lock while emitting the signal? + emit configurationFileChanged(rFileName, mConfigureError.count() > 0); + } + + + + void ConfiguratorHelper::doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { + QMutexLocker locker(&mObjectGuard); + + mConfigurationFile.clear(); + mpConfigureFunc = 0; + delete mpConfigurationFileWatch; + if (rFileName.isEmpty()) + return; + + mConfigurationFile = rFileName; + mpConfigureFunc = pConfigureFunc; + mpConfigurationFileWatch = new QFileSystemWatcher(); + mpConfigurationFileWatch->addPath(rFileName); + connect(mpConfigurationFileWatch, + SIGNAL(fileChanged(const QString &)), + SLOT(configurationFileChanged(const QString &))); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper) + { + debug.nospace() << "ConfiguratorHelper(" + << "configurationfile:" << ConfiguratorHelper::configurationFile() + << "configurefunc:" << rConfiguratorHelper.mpConfigureFunc + << "filesystemwatcher:" << rConfiguratorHelper.mpConfigurationFileWatch + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.h b/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.h new file mode 100644 index 0000000..765f86a --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/configuratorhelper.h @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_CONFIGURATORHELPER_H +#define LOG4QT_HELPERS_CONFIGURATORHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFileSystemWatcher; + + +namespace Log4Qt +{ + + /*! + * \brief The class ConfiguratorHelper provides a confiuration file watch + * and last error for configurator classes. + * + * A configuration file can be set using setConfigurationFile(). The file + * is watched for changes. If a change occurs the configuration is reloaded + * and the ConfigurationFileChanged() signal is emitted. Error information + * for the last call to a configure function or the last configuration file + * change can be accessed using configureError(). + * + * \note All the functions declared in this class are thread-safe. + */ + class ConfiguratorHelper : public QObject + { + Q_OBJECT + + public: + /*! + * Prototype for a configure callback function. The function is called + * when then configuration file is changed and takes the + * configuration file as a parameter. + * + * \sa setConfigurationFile(), + * PropertyConfigurator::configure(const QString &) + */ + typedef bool (*ConfigureFunc)(const QString &rFileName); + + private: + ConfiguratorHelper(); + ConfiguratorHelper(const ConfiguratorHelper &rOther); // Not implemented + virtual ~ConfiguratorHelper(); + ConfiguratorHelper &operator=(const ConfiguratorHelper &rOther); // Not implemented + + public: + + /*! + * Returns the error information for the last configuration operation + * that took place. The configuration operation could be the result of + * a call to one of the configure methods or through a change + * to the configuration file. + * + * \sa setConfigureError(), PropertyConfigurator::configure(), + * setConfigurationFile() + */ + static QList configureError(); + + /*! + * Returns the current configuration file. + * + * \sa setConfigurationFile() + */ + static QString configurationFile(); + + /*! + * Returns the ConfiguratorHelper instance. + */ + static ConfiguratorHelper *instance(); + + /*! + * Sets the configuration error information for the last configuration + * operation. + * + * \sa configureError() + */ + static void setConfigureError(const QList &rConfigureError); + + /*! + * Sets the configuration file to \a rFileName. The file is watched for + * changes. On a file change the function \a pConfigureFunc will be called + * and the signal configurationFileChange() will be emitted. + * + * Setting the configuration file to an empty string stops the file watch. + * + * \sa configurationFile(), PropertyConfigurator::configureAndWatch(), + * configureError() + */ + static void setConfigurationFile(const QString &rFileName = QString(), + ConfigureFunc pConfigureFunc = 0); + + signals: + /*! + * The signal is emitted after a change to the file \a rFileName + * was processed. If an error occured during the configuration, the + * flag \a error will be true and error information is available + * over configureError(). + */ + void configurationFileChanged(const QString &rFileName, + bool error); + + private slots: + void doConfigurationFileChanged(const QString &rFileName); + + private: + void doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc); + + private: + mutable QMutex mObjectGuard; + QString mConfigurationFile; + ConfigureFunc mpConfigureFunc; + QFileSystemWatcher *mpConfigurationFileWatch; + QList mConfigureError; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates ConfiguratorHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %ConfiguratorHelper(configurationfile: "" configurefunc: false + * filesystemwatcher: QObject(0x0) ) + * + * \sa QDebug, ConfiguratorHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QList ConfiguratorHelper::configureError() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigureError; } + + inline QString ConfiguratorHelper::configurationFile() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigurationFile; } + + inline void ConfiguratorHelper::setConfigureError(const QList &rConfigureError) + { QMutexLocker locker(&instance()->mObjectGuard); + instance()->mConfigureError = rConfigureError; } + + inline void ConfiguratorHelper::setConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { instance()->doSetConfigurationFile(rFileName, pConfigureFunc); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConfiguratorHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_CONFIGURATORHELPER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/datetime.cpp b/GC-3.6.1-T3/src/log4qt/helpers/datetime.cpp new file mode 100644 index 0000000..6da69a2 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/datetime.cpp @@ -0,0 +1,326 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/datetime.h" + +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DateTime + **************************************************************************/ + + + QString DateTime::toString(const QString &rFormat) const + { + QString format(rFormat); + + if (format.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + if (format == QLatin1String("NONE")) + return QString(); + + if (format == QLatin1String("RELATIVE")) + return QString::number(toMilliSeconds() - InitialisationHelper::startTime()); + + if (format == QLatin1String("ISO8601")) + format = QLatin1String("yyyy-MM-dd hh:mm:ss.zzz"); + if (format == QLatin1String("ABSOLUTE")) + format = QLatin1String("HH:mm:ss.zzz"); + if (format == QLatin1String("DATE")) + format = QLatin1String("dd MMM YYYY HH:mm:ss.zzzz"); + + return formatDateTime(format); + } + + + QString DateTime::formatDateTime(const QString &rFormat) const + { + if (rFormat.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + + const QLatin1Char null('0'); + const QLatin1Char quote('\''); + const QString tokens = QLatin1String("\'dMyhHmszAPapw"); + const bool am_pm = hasAMPM(rFormat); + + QString result; + QString token; + QChar expected = null; + + QChar c; + int i; + for (i = 0; i < rFormat.length(); i++) + { + c = rFormat.at(i); + + // Handle literal text + if (expected == quote) + { + if (c == quote) + { + Q_ASSERT_X(i > 0, "DateTime::toString()", "Found quote with status quote at i = 0"); + if (i > 0 && rFormat.at(i - 1) == quote) + // Second of two quotes + result += quote; + expected = null; + } + else + // Next literal character + result += c; + } + else if (c == expected) + { + // Extend token + token += c; + } + else + { + // Close last token + result += formatToken(token, am_pm); + token.clear(); + expected = null; + + // Test for valid character + if (tokens.indexOf(c) >= 0) + { + if (c == QLatin1Char('a')) + expected = QLatin1Char('p'); + else if (c == QLatin1Char('A')) + expected = QLatin1Char('P'); + else if (c.toLower() == QLatin1Char('p')) + expected = null; + else + expected = c; + if (c != quote) + token += c; + } else + result += c; + } + } + + result += formatToken(token, am_pm); + return result; + } + + + QString DateTime::formatToken(const QString &rToken, bool am_pm) const + { + if (rToken.isEmpty()) + return QString(); + + const QChar c = rToken.at(0); + QString result; + int used = 0; + + // Qt data format strings + if (rToken.startsWith(QLatin1String("dddd"))) + { + result = QDate::longDayName(date().dayOfWeek()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("ddd"))) + { + result = QDate::shortDayName(date().dayOfWeek()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("dd"))) + { + result = QString::number(date().day()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('d')) + { + result = QString::number(date().day()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("MMMM"))) + { + result = QDate::longMonthName(date().month()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("MMM"))) + { + result = QDate::shortMonthName(date().month()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("MM"))) + { + result = QString::number(date().month()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('M')) + { + result = QString::number(date().month()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("yyyy"))) + { + result = QString::number(date().year()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("yy"))) + { + result = QString::number(date().year() % 100).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + + // Qt time format strings + else if (rToken.startsWith(QLatin1String("hh")) || rToken.startsWith(QLatin1String("HH"))) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('h') || c == QLatin1Char('H')) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour); + used = 2; + } + else if (rToken.startsWith(QLatin1String("mm"))) + { + result = QString::number(time().minute()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == (QLatin1Char('m'))) + { + result = QString::number(time().minute()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("ss"))) + { + result = QString::number(time().second()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('s')) + { + result = QString::number(time().second()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("zzz"))) + { + result = QString::number(time().msec()).rightJustified(3, QLatin1Char('0'), true); + used = 3; + } + else if (c == QLatin1Char('z')) + { + result = QString::number(time().msec()); + used = 1; + } + else if (c.toLower() == QLatin1Char('a')) + { + bool is_lower = c == QLatin1Char('a'); + if (time().hour() < 12) + result = QLatin1String("AM"); + else + result = QLatin1String("PM"); + if (is_lower) + result = result.toLower(); + if (rToken.size() > 1 && + ((is_lower && rToken.at(1) == QLatin1Char('p')) || + (!is_lower && rToken.at(1) == QLatin1Char('P'))) + ) + used = 2; + else + used = 1; + } + + // Extension for week number + else if (rToken.startsWith(QLatin1String("ww"))) + { + result = QString::number(date().weekNumber()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('w')) + { + result = QString::number(date().weekNumber()); + used = 1; + } + + if (used) + return result + formatToken(rToken.mid(used), am_pm); + else + return result; + } + + + bool DateTime::hasAMPM(const QString &rToken) + { + bool in_literal = false; + QChar c; + int i; + for (i = 0; i < rToken.length(); i++) + { + c = rToken.at(i); + if (c == QLatin1Char('\'')) + in_literal = !in_literal; + else if (!in_literal && c.toLower() == QLatin1Char('a')) + return true; + } + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/datetime.h b/GC-3.6.1-T3/src/log4qt/helpers/datetime.h new file mode 100644 index 0000000..2c83a47 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/datetime.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_DATETIME_H +#define LOG4QT_HELPERS_DATETIME_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class DateTime provides extended functionality for QDateTime. + * + * The class DateTime implements additional formatting options for + * toString() and provides conversion functions from and to milliseconds. + */ + class DateTime : public QDateTime + { + public: + /*! + * Constructs a null date time. + * + * \sa QDateTime::QDateTime() + */ + DateTime(); + + // DateTime(const DateTime &rOther); // Use compiler default + + /*! + * Constructs a copy of another QDateTime. + * + * \sa QDateTime::QDateTime(const QDateTime &rOther) + */ + DateTime(const QDateTime &rOther); + + /*! + * Constructs a datetime with the given \a rDate and \a rTime, using + * the time specification defined by \a timeSpec. + * + * \sa QDateTime::QDateTime(const QDate &rDate, const QTime &rTime, + * Qt::TimeSpec timeSpec = Qt::LocalTime) + */ + DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec = Qt::LocalTime); + + // virtual ~DateTime(); // Use compiler default + + /*! + * Assigns \a rOther to this DateTime and returns a reference to it. + */ + DateTime &operator=(const DateTime &rOther); + + /*! + * Returns the datetime as the number of milliseconds that have passed + * since 1970-01-01T00:00:00,000, Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::toTime_t() + */ + qint64 toMilliSeconds() const; + + /*! + * Returns the datetime as a string. The \a rFormat parameter + * determines the format of the result string. + * + * In addition to the expressions of QDateTime::toString(const QString + * &rFormat) the following expression can be used. + * + * + * + * + * + * + * + * + * + * + * + * + *
Expression Output
w the week of the year as number without a leading zero (1 to 53)
ww the week of the year as number with a leading zero (01 to 53)
+ * + * Alternatively the \a rFormat parameter can specify one of the + * following strings. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
String Format
ABSOLUTE uses the format HH:mm:ss.zzz
DATE uses the format dd MMM YYYY HH:mm:ss.zzzz
ISO8601 uses the format yyyy-MM-dd hh:mm:ss.zzz
NONE uses an empty string as format
RELATIVE returns the milliseconds since start of the program
+ * + * \sa QDateTime::toString(const QString &rFormat) + */ + QString toString(const QString &rFormat) const; + + /*! + * Returns the current datetime, as reported by the system clock, in + * the local time zone. + * + * \sa QDateTime::currentDateTime() + */ + static DateTime currentDateTime(); + + /*! + * Returns a datetime whose date and time are the number of + * milliseconds that have passed since 1970-01-01T00:00:00, + * Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::fromTime_t(uint seconds) + */ + static DateTime fromMilliSeconds(qint64 milliSeconds); + + private: + QString formatDateTime(const QString &rFormat) const; + QString formatToken(const QString &rToken, bool am_pm) const; + static bool hasAMPM(const QString &rFormat); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DateTime::DateTime() : QDateTime() + {} + + inline DateTime::DateTime(const QDateTime &rOther) : QDateTime(rOther) + {} + + inline DateTime::DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec) : + QDateTime(rDate, rTime, timeSpec) + {} + + inline DateTime &DateTime::operator=(const DateTime &rOther) + { QDateTime::operator=(rOther); return *this; } + + inline qint64 DateTime::toMilliSeconds() const + { return (qint64)1000 * toTime_t() + time().msec(); } + + inline DateTime DateTime::currentDateTime() + { return DateTime(QDateTime::currentDateTime()); } + + inline DateTime DateTime::fromMilliSeconds(qint64 milliSeconds) + { return DateTime(QDateTime::fromTime_t(milliSeconds / 1000).addMSecs(milliSeconds % 1000)); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::DateTime, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_HELPERS_DATETIME_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/factory.cpp b/GC-3.6.1-T3/src/log4qt/helpers/factory.cpp new file mode 100644 index 0000000..70c5ed0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/factory.cpp @@ -0,0 +1,456 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/factory.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/dailyrollingfileappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/patternlayout.h" +#include "log4qt/rollingfileappender.h" +#include "log4qt/simplelayout.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/debugappender.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelmatchfilter.h" +#include "log4qt/varia/levelrangefilter.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/varia/nullappender.h" +#include "log4qt/varia/stringmatchfilter.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory) + + + // Appenders + + Appender *console_file_appender() + { return new ConsoleAppender; } + + Appender *create_daily_rolling_file_appender() + { return new DailyRollingFileAppender; } + + Appender *create_debug_appender() + { return new DebugAppender; } + + Appender *create_file_appender() + { return new FileAppender; } + + Appender *create_list_appender() + { return new ListAppender; } + + Appender *create_null_appender() + { return new NullAppender; } + + Appender *create_rolling_file_appender() + { return new RollingFileAppender; } + + + // Filters + + Filter *create_deny_all_filter() + { return new DenyAllFilter; } + + Filter *create_level_match_filter() + { return new LevelMatchFilter; } + + Filter *create_level_range_filter() + { return new LevelRangeFilter; } + + Filter *create_string_match_filter() + { return new StringMatchFilter; } + + + // Layouts + + Layout *create_pattern_layout() + { return new PatternLayout; } + + Layout *create_simple_layout() + { return new SimpleLayout; } + + Layout *create_ttcc_layout() + { return new TTCCLayout; } + + + + /************************************************************************** + * Class implementation: Factory + **************************************************************************/ + + + Factory::Factory() : + mObjectGuard(), + mAppenderRegistry(), + mFilterRegistry(), + mLayoutRegistry() + { + registerDefaultAppenders(); + registerDefaultFilters(); + registerDefaultLayouts(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(Factory) + + + Appender *Factory::doCreateAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName); + return 0; + } + return mAppenderRegistry.value(rAppenderClassName)(); + } + + + Filter *Factory::doCreateFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName); + return 0; + } + return mFilterRegistry.value(rFilterClassName)(); + } + + + Layout *Factory::doCreateLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName); + return 0; + } + return mLayoutRegistry.value(rLayoutClassName)(); + } + + + void Factory::doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rAppenderClassName.isEmpty()) + { + logger()->warn("Registering Appender factory function with empty class name"); + return; + } + mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc); + } + + + void Factory::doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rFilterClassName.isEmpty()) + { + logger()->warn("Registering Filter factory function with empty class name"); + return; + } + mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc); + } + + + void Factory::doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rLayoutClassName.isEmpty()) + { + logger()->warn("Registering Layout factory function with empty class name"); + return; + } + mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc); + } + + + void Factory::doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { + // - Validate property + // - Get correct property name from meta object + // - Find specific property setter + // - If no specfifc propery setter can be found, + // find general property setter + // - Call property setter + QMetaProperty meta_property; + if (!validateObjectProperty(meta_property, rProperty, pObject)) + return; + + QString property = QLatin1String(meta_property.name()); + QString type = QLatin1String(meta_property.typeName()); + logger()->debug("Setting property '%1' on object of class '%2' to value '%3'", + property, + QLatin1String(pObject->metaObject()->className()), + rValue); + + QVariant value; + bool ok = true; + if (type == QLatin1String("bool")) + value = OptionConverter::toBoolean(rValue, &ok); + else if (type == QLatin1String("int")) + value = OptionConverter::toInt(rValue, &ok); + else if (type == QLatin1String("Log4Qt::Level")) + value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok)); + else if (type == QLatin1String("QString")) + value = rValue; + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"), + CONFIGURATOR_UNKNOWN_TYPE_ERROR, + "Log4Qt::Factory"); + e << type + << property + << QString::fromLatin1(pObject->metaObject()->className()); + logger()->error(e); + return; + } + if (!ok) + return; + + // Everything is checked and the type is the one of the property. + // Write should never return false + if (!meta_property.write(pObject, value)) + logger()->warn("Unxpected error result from QMetaProperty.write()"); + } + + + void Factory::doUnregisterAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName); + return; + } + mAppenderRegistry.remove(rAppenderClassName); + } + + + void Factory::doUnregisterFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName); + return; + } + mFilterRegistry.remove(rFilterClassName); + } + + + void Factory::doUnregisterLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName); + return; + } + mLayoutRegistry.remove(rLayoutClassName); + } + + + void Factory::registerDefaultAppenders() + { + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender); + } + + + void Factory::registerDefaultFilters() + { + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter); + } + + + void Factory::registerDefaultLayouts() + { + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout); + } + + + bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject) + { + // Validate: + // - No null object pointer + // - No empty property name + // - Property exists on the object (QT or Java name) + // - Property is readable + // - Property is writable + + const char *p_context = "Log4Qt::Factory"; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"), + CONFIGURATOR_PROPERTY_ERROR, + p_context); + + if (!pObject) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + if (rProperty.isEmpty()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + const QMetaObject *p_meta_object = pObject->metaObject(); + QString property = rProperty; + int i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + // Try name with lower case first character. Java properties names + // start upper case + property[0] = property[0].toLower(); + i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + } + rMetaProperty = p_meta_object->property(i); + if (!rMetaProperty.isWritable()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Factory &rFactory) + { + debug.nospace() << "Factory(" + << "appenderfactories:" << rFactory.registeredAppenders() + << "filterfactories:" << rFactory.registeredFilters() + << "layoutfactories:" << rFactory.registeredLayouts() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GC-3.6.1-T3/src/log4qt/helpers/factory.h b/GC-3.6.1-T3/src/log4qt/helpers/factory.h new file mode 100644 index 0000000..dfe4bfa --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/factory.h @@ -0,0 +1,443 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_FACTORY_H +#define LOG4QT_HELPERS_FACTORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Appender; + class Filter; + class Layout; + + /*! + * \brief The class Factory provides factories for Appender, Filter and + * Layout objects. + * + * The functions createAppender(), createFilter() and createLayout() + * allow to create objects by specifying their class names. By default + * all classes of the package are recognised with their Log4j and Log4Qt + * classanmes. For example an object of the class FileAppender can be + * craeted using "org.apache.log4j.FileAppender" or "Log4Qt::FileAppender". + * Additional classes can be registered using registerAppender(), + * registerFilter() and registerLayout(). + * + * An QObject property can be set from a string value with + * setObjectProperty(). The function handles the required error checking + * and type conversion. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa PropertyConfigurator + */ + class Factory + { + public: + /*! + * Prototype for an Appender factory function. The function creates + * an Appender object on the heap and returns a pointer to it. + * + * \sa registerAppender(), createAppender() + */ + typedef Appender *(*AppenderFactoryFunc)(); + + /*! + * Prototype for a Filter factory function. The function creates + * a Filter object on the heap and returns a pointer to it. + * + * \sa registerFilter(), createFilter() + */ + typedef Filter *(*FilterFactoryFunc)(); + + /*! + * Prototype for a Layout factory function. The function creates + * a Layout object on the heap and returns a pointer to it. + * + * \sa registerLayout(), createLayout() + */ + typedef Layout *(*LayoutFactoryFunc)(); + + private: + Factory(); + Factory(const Factory &rOther); // Not implemented + // virtual ~Factory(); // Use compiler default + Factory &operator=(const Factory &rOther); // Not implemented + + public: + /*! + * Creates an object for the class \a rAppenderClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerAppender(), unregisterAppender(), registeredAppenders() + */ + static Appender *createAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Appender *createAppender(const char *pAppenderClassName); + + /*! + * Creates an object for the class \a rFilterClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerFilter(), unregisterFilter(), registeredFilters() + */ + static Filter *createFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Filter *createFilter(const char *pFilterClassName); + + /*! + * Creates an object for the class \a rLayoutClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerLayout(), unregisterLayout(), registeredLayouts() + */ + static Layout *createLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Layout *createLayout(const char *pLayoutClassName); + + /*! + * Returns the Factory instance. + */ + static Factory *instance(); + + /*! + * Registers the Appender factory function \a pAppenderFactoryFunc + * for the class \a rAppenderClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pAppenderFactoryFunc. + * + * \sa unregisterAppender(), registeredAppenders(), createAppender() + */ + static void registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * Registers the Filter factory function \a pFilterFactoryFunc + * for the class \a rFilterClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pFilterFactoryFunc. + * + * \sa unregisterFilter(), registeredFilters(), createFilter() + */ + static void registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * Registers the Layout factory function \a pLayoutFactoryFunc + * for the class \a rLayoutClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pLayoutFactoryFunc. + * + * \sa unregisterLayout(), registeredLayout(), createLayout() + */ + static void registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * Returns a list of the class names for registered Appender factory + * functions. + * + * \sa registerAppender(), unregisterAppender() + */ + static QStringList registeredAppenders(); + + /*! + * Returns a list of the class names for registered Filter factory + * functions. + * + * \sa registerFilter(), unregisterFilter() + */ + static QStringList registeredFilters(); + + /*! + * Returns a list of the class names for registered Layout factory + * functions. + * + * \sa registerLayout(), unregisterLayout() + */ + static QStringList registeredLayouts(); + + /*! + * Sets the property \a rProperty of the object \a pObject to the + * value \a rValue. The function will test that the property + * \a rProperty is writeable and of a type the function can convert to. + * The types bool, int, Level and QString are supported. + * + * \sa OptionConverter + */ + static void setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue); + + /*! + * Unregisters the Appender factory function for the class + * \a rAppenderClassName. + * + * \sa registerAppender(), registeredAppenders() + */ + static void unregisterAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterAppender(const char *pAppenderClassName); + + /*! + * Unregisters the Filter factory function for the class + * \a rFilterClassName. + * + * \sa registerFilter(), registeredFilters() + */ + static void unregisterFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterFilter(const char *pFilterClassName); + + /*! + * Unregisters the Layout factory function for the class + * \a rLayoutClassName. + * + * \sa registerLayout(), registeredLayouts() + */ + static void unregisterLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterLayout(const char *pLayoutClassName); + + private: + Appender *doCreateAppender(const QString &rAppenderClassName); + Filter *doCreateFilter(const QString &rFilterClassName); + Layout *doCreateLayout(const QString &rLayoutClassName); + void doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + void doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + void doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + void doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + void doUnregisterAppender(const QString &rAppenderClassName); + void doUnregisterFilter(const QString &rFilterClassName); + void doUnregisterLayout(const QString &rLayoutClassName); + void registerDefaultAppenders(); + void registerDefaultFilters(); + void registerDefaultLayouts(); + bool validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject); + + private: + mutable QMutex mObjectGuard; + QHash mAppenderRegistry; + QHash mFilterRegistry; + QHash mLayoutRegistry; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Factory + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Factory(appenderfactories:("Log4Qt::DebugAppender", "Log4Qt::NullAppender", + * "Log4Qt::ConsoleAppender", "org.apache.log4j.varia.DebugAppender", + * "org.apache.log4j.FileAppender", "org.apache.log4j.RollingFileAppender", + * "org.apache.log4j.DailyRollingFileAppender", + * "org.apache.log4j.varia.ListAppender", + * "org.apache.log4j.varia.NullAppender", + * "Log4Qt::FileAppender", "org.apache.log4j.ConsoleAppender", + * "Log4Qt::DailyRollingFileAppender", "Log4Qt::ListAppender", + * "Log4Qt::RollingFileAppender") filterfactories: + * ("Log4Qt::DenyAllFilter", "Log4Qt::StringMatchFilter", + * "Log4Qt::LevelRangeFilter", "org.apache.log4j.varia.DenyAllFilter", + * "org.apache.log4j.varia.LevelRangeFilter", + * "org.apache.log4j.varia.StringMatchFilter", "Log4Qt::LevelMatchFilter", + * "org.apache.log4j.varia.LevelMatchFilter") layoutfactories: + * ("org.apache.log4j.SimpleLayout", "Log4Qt::PatternLayout", + * "Log4Qt::SimpleLayout", "org.apache.log4j.TTCCLayout", + * "Log4Qt::TTCCLayout", "org.apache.log4j.PatternLayout") ) + * + * \sa QDebug, Factory::logManager() + */ + QDebug operator<<(QDebug debug, + const Factory &rFactory); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender *Factory::createAppender(const QString &rAppenderClassName) + { return instance()->doCreateAppender(rAppenderClassName); } + + inline Appender *Factory::createAppender(const char *pAppenderClassName) + { return instance()->doCreateAppender(QLatin1String(pAppenderClassName)); } + + inline Filter *Factory::createFilter(const QString &rFilterClassName) + { return instance()->doCreateFilter(rFilterClassName); } + + inline Filter *Factory::createFilter(const char *pFilterClassName) + { return instance()->doCreateFilter(QLatin1String(pFilterClassName)); } + + inline Layout *Factory::createLayout(const QString &rLayoutClassName) + { return instance()->doCreateLayout(rLayoutClassName); } + + inline Layout *Factory::createLayout(const char *pLayoutClassName) + { return instance()->doCreateLayout(QLatin1String(pLayoutClassName)); } + + inline void Factory::registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(rAppenderClassName, pAppenderFactoryFunc); } + + inline void Factory::registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(QLatin1String(pAppenderClassName), pAppenderFactoryFunc); } + + inline void Factory::registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(rFilterClassName, pFilterFactoryFunc); } + + inline void Factory::registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(QLatin1String(pFilterClassName), pFilterFactoryFunc); } + + inline void Factory::registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(rLayoutClassName, pLayoutFactoryFunc); } + + inline void Factory::registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(QLatin1String(pLayoutClassName), pLayoutFactoryFunc); } + + inline QStringList Factory::registeredAppenders() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mAppenderRegistry.keys(); } + + inline QStringList Factory::registeredFilters() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mFilterRegistry.keys(); } + + inline QStringList Factory::registeredLayouts() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mLayoutRegistry.keys(); } + + inline void Factory::setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, rProperty, rValue); } + + inline void Factory::setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, QLatin1String(pProperty), rValue); } + + inline void Factory::unregisterAppender(const QString &rAppenderClassName) + { instance()->doUnregisterAppender(rAppenderClassName); } + + inline void Factory::unregisterAppender(const char *pAppenderClassName) + { instance()->doUnregisterAppender(QLatin1String(pAppenderClassName)); } + + inline void Factory::unregisterFilter(const QString &rFilterClassName) + { instance()->doUnregisterFilter(rFilterClassName); } + + inline void Factory::unregisterFilter(const char *pFilterClassName) + { instance()->doUnregisterFilter(QLatin1String(pFilterClassName)); } + + inline void Factory::unregisterLayout(const QString &rLayoutClassName) + { instance()->doUnregisterLayout(rLayoutClassName); } + + inline void Factory::unregisterLayout(const char *pLayoutClassName) + { instance()->doUnregisterLayout(QLatin1String(pLayoutClassName)); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Factory, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_FACTORY_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.cpp b/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.cpp new file mode 100644 index 0000000..783929e --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/initialisationhelper.h" + +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: InitialisationHelper + **************************************************************************/ + + + InitialisationHelper::InitialisationHelper() : + mStartTime(DateTime::currentDateTime().toMilliSeconds()), + mEnvironmentSettings() + { + doRegisterTypes(); + doInitialiseEnvironmentSettings(); + } + + + InitialisationHelper::~InitialisationHelper() + { + Q_ASSERT_X(false, "InitialisationHelper::~InitialisationHelper()", "Unexpected destruction of singleton object"); + } + + + LOG4QT_IMPLEMENT_INSTANCE(InitialisationHelper) + + + void InitialisationHelper::doInitialiseEnvironmentSettings() + { + // Is Process::systemEnvironment() safe to be used before a QCoreApplication + // object has been created? + + QStringList setting_keys; + setting_keys << QLatin1String("Debug"); + setting_keys << QLatin1String("DefaultInitOverride"); + setting_keys << QLatin1String("Configuration"); + setting_keys << QLatin1String("ConfiguratorClass"); + + QHash env_keys; + QString entry; + Q_FOREACH(entry, setting_keys) + env_keys.insert(QString::fromLatin1("log4qt_").append(entry).toUpper(), entry); + + QStringList sys_env = QProcess::systemEnvironment(); + Q_FOREACH(entry, sys_env) + { + int i = entry.indexOf(QLatin1Char('=')); + if (i == -1) + continue; + QString key = entry.left(i); + QString value = entry.mid(i + 1).trimmed(); + if (env_keys.contains(key)) + mEnvironmentSettings.insert(env_keys.value(key), value); + } + } + + + void InitialisationHelper::doRegisterTypes() + { + qRegisterMetaType("Log4Qt::LogError"); + qRegisterMetaType("Log4Qt::Level"); + qRegisterMetaType("Log4Qt::LoggingEvent"); + + #ifndef QT_NO_DATASTREAM + qRegisterMetaTypeStreamOperators("Log4Qt::LogError"); + qRegisterMetaTypeStreamOperators("Log4Qt::Level"); + qRegisterMetaTypeStreamOperators("Log4Qt::LoggingEvent"); + #endif + } + + + QString InitialisationHelper::doSetting(const QString &rKey, + const QString &rDefault) const + { + if (mEnvironmentSettings.contains(rKey)) + return mEnvironmentSettings.value(rKey); + + if (QCoreApplication::instance()) + { + QSettings s; + s.beginGroup(QLatin1String("Log4Qt")); + return s.value(rKey, rDefault).toString().trimmed(); + } + else + return rDefault; + } + + + bool InitialisationHelper::staticInitialisation() + { + instance(); + return true; + } + + + bool InitialisationHelper::msStaticInitialisation = staticInitialisation(); + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper) + { + Q_UNUSED(rInitialisationHelper); + debug.nospace() << "InitialisationHelper(" + << "starttime:" << InitialisationHelper::startTime() + << "(" << DateTime::fromMilliSeconds(InitialisationHelper::startTime()) << ")" + << "environmentsettings:" << InitialisationHelper::environmentSettings() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.h b/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.h new file mode 100644 index 0000000..95b370d --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/initialisationhelper.h @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H +#define LOG4QT_HELPERS_INITIALISATIONHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QMutex; + +namespace Log4Qt +{ + /*! + * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that + * returns a pointer to a singleton object of the type \a TYPE. + * + * The macro uses a static variable to store a pointer to the singleton + * object. On the first invocation an object of the type \a TYPE is created + * on the heap and the pointer is set. Any further invocations will return + * the stored pointer. If multiple threads are accessing the function + * without the pointer being set, each thread will create an object of the + * type \a TYPE. The threads that find the pointer already been set will + * delete their object. The singleton object will not be deleted during static + * de-initialisation. + * + * The following example uses a global global mutex object to synchronise + * access to a static member variable. + * + * \code + * #file: myclass.h + * + * class MyClass + * { + * public: + * MyClass(); + * ~MyClass(); + * private: + * static qint64 msObjectCount; + * } + * \endcode + * \code + * #file: myclass.cpp + * + * #include myclass.h + * + * LOG4QT_GLOBAL_STATIC(QMutex, class_guard) + * + * MyClass::MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount++; + * } + * + * MyClass::~MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount--; + * } + * + * qint64 MyClass::msObjectCount = 0; + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static volatile TYPE *sp_global_static_##FUNCTION = 0; \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return const_cast(sp_global_static_##FUNCTION); \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION; \ + } +#else + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a + * singleton class \a TYPE. + * + * The function works like the one created by + * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC". + * + * The following example illustrates how to use the macro to create a + * singleton class: + * + * \code + * #file: mysingleton.h + * + * class MySingleton + * { + * private: + * MySingleton(); + * ~MySingleton(); + * public: + * MySingleton *instance(); + * } + * \endcode + * \code + * #file: mysingleton.cpp + * + * #include mysingleton.h + * + * MySingleton::MySingleton() + * {} + * + * MySingleton::~MySingleton() + * {} + * + * LOG4QT_IMPLEMENT_INSTANCE(MySingleton) + * + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static TYPE *sp_singleton_##TYPE = 0; \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#else + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE.loadAcquire(); \ + } +#endif + + /*! + * \brief The class InitialisationHelper performs static initialisation + * tasks. + * + * The InitialisationHelper is either created on the first call or through + * static initialisation. It will capture the programs startup time, + * which can be retrieved using startTime(). The system environment + * is analysed for package related definitions. The result is available + * over environmentSettings(). The packages custom types are registered with + * the Qt type system. + * + * Settings for the package can be retrieved using setting(). Two macros + * are available to help with the creation of singletons / global static + * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and + * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"). + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Init "Initialization procedure", + */ + class InitialisationHelper + { + private: + InitialisationHelper(); + InitialisationHelper(const InitialisationHelper &rOther); // Not implemented + virtual ~InitialisationHelper(); + InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented + + public: + + /*! + * Returns a hash with the settings retrieved from the system + * environment on startup. + * + * The following table shows the environment variables taken into + * account and the setting key used for them. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Environment variable Setting key
LOG4QT_DEBUG Debug
LOG4QT_DEFAULTINITOVERRIDE DefaultInitOverride
LOG4QT_CONFIGURATION Configuration
LOG4QT_CONFIGURATORCLASS ConfiguratorClass
+ * + * \sa \ref Env "Environment Variables", + * setting() + */ + static QHash environmentSettings(); + + /*! + * Returns the InitialisationHelper instance. + */ + static InitialisationHelper *instance(); + + /*! + * Returns the value for the setting \a rKey or \a rDefault, if it is + * not defined. + * + * A setting can be either defined by an environment variable or by a + * key in the application setting. The function will first test the + * settings made by environment variables for the key \a rKey using + * environmentSettings(). If the key is not present and a + * QCoreApplication exists, the application settings are tested for + * the key \a rKey in the group \c %Log4Qt. + * + * The following setting exists: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Setting key Description
Debug The variable controls the Level value for the logger + * LogManager::logLogger(). If the value is a valid Level string, + * the level for the logger is set to the level. If the value is not + * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used. + * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used.
DefaultInitOverride The variable controls the \ref Init "initialization procedure" + * performed by the \ref LogManager "LogManager" on startup. + * If it is set to any other value then \c false the \ref Init + * "initialization procedure" is skipped.
Configuration Specifies the configuration file used for initialising the package.
ConfiguratorClass Specifies the configurator class used for initialising the package.
+ * + * \sa environmentSettings(), \ref Env "Environment Variables", + * \ref Init "Initialization procedure", + * LogManager::configureLogLogger(), LogManager::startup() + */ + static QString setting(const QString &rKey, + const QString &rDefault = QString()); + + /*! + * Returns the start time of the program as the number of milliseconds + * that have passed since 1970-01-01T00:00:00,000, Coordinated + * Universal Time (Qt::UTC). + * + * \sa DateTime::fromMilliSeconds(), + * DateTime::toMilliSeconds() + */ + static qint64 startTime(); + + private: + void doInitialiseEnvironmentSettings(); + void doRegisterTypes(); + QString doSetting(const QString &rKey, + const QString &rDefault) const; + static bool shutdown(); + static bool staticInitialisation(); + + private: + // QMutex mObjectGuard; + const qint64 mStartTime; + QHash mEnvironmentSettings; + static bool msStaticInitialisation; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates InitialisationHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %InitialisationHelper(InitialisationHelper(starttime:1193883677438( + * QDateTime("Wed Oct 31 21:21:17 2007") ) + * environmentsettings: QHash(("configuration", "\myapp.log4j") + * ("Debug", "DEBUG")) ) ) + * + * \sa QDebug, InitialisationHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QHash InitialisationHelper::environmentSettings() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mEnvironmentSettings; } + + inline QString InitialisationHelper::setting(const QString &rKey, + const QString &rDefault) + { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const + return instance()->doSetting(rKey, rDefault); } + + inline qint64 InitialisationHelper::startTime() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mStartTime; } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logerror.cpp b/GC-3.6.1-T3/src/log4qt/helpers/logerror.cpp new file mode 100644 index 0000000..f78d2ab --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logerror.cpp @@ -0,0 +1,354 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + *****************************************************************************/ + + +#include "log4qt/helpers/logerror.h" + +#include +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + typedef QThreadStorage ThreadError; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(ThreadError, thread_error) + + + + /************************************************************************** + * Class implementation: LogError + **************************************************************************/ + + + LogError::LogError() : + mCode(0), + mContext(), + mMessage(), + mSymbol(), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const QString &rMessage, + int code, + const QString &rSymbol, + const QString &rContext) : + mCode(code), + mContext(rContext), + mMessage(cleanMessage(rMessage)), + mSymbol(rSymbol), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const char *pMessage, + int code, + const char *pSymbol, + const char *pContext, + Encoding encoding) : + mCode(code), + mContext(QString::fromLatin1(pContext)), + mMessage(), + mSymbol(QString::fromLatin1(pSymbol)), + mArgs(), + mCausingErrors() + { + switch(encoding) + { + case LATIN1: + mMessage = QString::fromLatin1(pMessage); + break; + case CODECFORTR: +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + mMessage = QTextCodec::codecForTr()->toUnicode(pMessage); +#else + mMessage = QString::fromUtf8(pMessage); +#endif + break; + case UNICODEUTF8: + mMessage = QString::fromUtf8(pMessage); + break; + default: + Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant"); + mMessage = QString::fromLatin1(pMessage); + } + mMessage = cleanMessage(mMessage); + + if (mSymbol == QString::number(mCode)) + mSymbol.clear(); + } + + + QString LogError::translatedMessage() const + { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0, QCoreApplication::UnicodeUTF8); +#else + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0); +#endif + } + + + LogError LogError::lastError() + { + if (!thread_error()->hasLocalData()) + return LogError(); + else + return *thread_error()->localData(); + } + + + void LogError::setLastError(const LogError &rLogError) + { + if (!thread_error()->hasLocalData()) + thread_error()->setLocalData(new LogError); + + *thread_error()->localData() = rLogError; + } + + + QString LogError::toString() const + { + QString result = messageWithArgs(); + + QString context_symbol = mContext; + if (!context_symbol.isEmpty() && !mSymbol.isEmpty()) + context_symbol.append(QLatin1String("::")); + context_symbol.append(mSymbol); + + if (!context_symbol.isEmpty() || mCode) + { + result.append(QLatin1String(" (")); + if (!context_symbol.isEmpty()) + result.append(context_symbol); + if (!context_symbol.isEmpty() && mCode) + result.append(QLatin1String(", ")); + if (mCode) + result.append(QString::number(mCode)); + result.append(QLatin1String(")")); + } + + if (!mCausingErrors.isEmpty()) + { + QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString(); + int i = 1; + while (i < mCausingErrors.count()) + { + causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString()); + i++; + } + result.append(causing_errors_str); + } + + return result; + } + + + QString LogError::insertArgs(const QString &rMessage) const + { + QString result; + + /* + + // Don't use a loop to be able to handle arguments that conatin strings + // like %1. + // Using this method only 9 arguments can be handled as the %1 + // in %11 gets also replaced with the first argument. + + switch (mArgs.count()) + { + case 0: + break; + case 1: + result = rMessage.arg(mArgs.at(0)); + break; + case 2: + result = rMessage.arg(mArgs.at(0), mArgs.at(1)); + break; + case 3: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2)); + break; + case 4: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3)); + break; + case 5: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4)); + break; + case 6: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5)); + break; + case 7: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6)); + break; + case 8: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7)); + break; + default: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8)); + break; + } + + if (mArgs.count() > 9) + { + int i = 9; + while(i < mArgs.count()) + { + result = result.arg(mArgs.at(i)); + i++; + } + } + */ + + result = rMessage; + QVariant arg; + Q_FOREACH(arg, mArgs) + result = result.arg(arg.toString()); + return result; + } + + + QString LogError::cleanMessage(const QString &rMessage) + { + if (rMessage.isEmpty()) + return rMessage; + + QString result = rMessage; + if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.')) + result = rMessage.left(rMessage.size() - 1); + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLogError.mCode + << rLogError.mContext + << rLogError.mMessage + << rLogError.mSymbol + << rLogError.mArgs + << rLogError.mCausingErrors; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString level; + QString logger; + stream >> rLogError.mCode + >> rLogError.mContext + >> rLogError.mMessage + >> rLogError.mSymbol + >> rLogError.mArgs + >> rLogError.mCausingErrors; + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogError &rLogError) + { + // Escape % sign + QString message = rLogError.message(); + message.replace(QLatin1String("%"), QLatin1String("%%")); + + debug.nospace() << "LogError(" + << "code:" << rLogError.code() << " " + << "context:" << rLogError.context() << " " + << "message:" << message << " " + << "symbol:" << rLogError.symbol() << " " + << "args:" << rLogError.args() + << "translatedMessage:" << rLogError.translatedMessage() + << ")"; + return debug.maybeSpace(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logerror.h b/GC-3.6.1-T3/src/log4qt/helpers/logerror.h new file mode 100644 index 0000000..06d1a67 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logerror.h @@ -0,0 +1,550 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGERROR_H +#define LOG4QT_LOGERROR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + /*! + * Creates an LogError object with the error message \a message, the error + * code \a code and the context \a context. The symbol of the error is + * set to \a code as string value. + * + * The following example logs an error, if a character is not a digit. + * + * \code + * if (!c.isDigit()) + * { + * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + * LAYOUT_EXPECTED_DIGIT_ERROR, + * "Log4Qt::PatternFormatter"); + * e << QString(c); + * logger()->error(e); + * } + * \endcode + */ + #define LOG4QT_ERROR(message, code, context) \ + LogError(message, code, #code, context) + + /*! + * Creates an LogError object with the error message \a message and the + * error code \a code. The symbol of the error is set to \a code as string + * value. The context is set to the class name of the current object. The + * current objects class must be derived from QObject. + * + * The following example handles an error while opening a file. + * + * \code + * if (!mpFile->open(mode)) + * { + * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + * APPENDER_OPENING_FILE_ERROR); + * e << mFileName << name(); + * e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + * logger()->error(e); + * return; + * } + * \endcode + */ + #define LOG4QT_QCLASS_ERROR(message, code) \ + LogError(message, code, #code, this->metaObject()->className()) + + /*! + * \brief The class LogError represents an error. + * + * The class error allows storing error information in a structured way. + * The error message is stored separately from the information that may be + * substituted into the message string. This way it is possible to access + * all information after the error has been raised. It also allows to + * translate the error at a later point in time or to get a translated and + * a not translated error text (e.g. translated for the UI and not + * translated for a log). + * + * The message is accessed using message() and setMessage(). Arguments for + * the message can be added using addArg() or operator<<(). The arguments + * can be retrieved using args(). The message with substituted arguments + * is returned by messageWithArgs(). + * + * An error code can be set as integer value code() and/or a symbolic value + * symbol(). + * + * To allow the translation of the message the error stores the translation + * context (context(), setContext()). The translated message can be accessed + * using translatedMessage() or using translatedMessageWithArgs(), if it + * should contain the arguments. + * + * An error can have one or more related errors that caused it. An error is + * related using addCausingError(). All causing errors can be retrieved using + * causingErrors(). + * + * A per thread error can be maintained using lastError() and setLastError(). + * + * There are two macros avaiable to simplify the error creation. The macro + * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived + * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * is used with classes derived from QObject. + */ + class LogError + { + public: + + /*! + * The enum Encoding defines the 8-bit encoding of a character string + * arguments to \ref LogError::LogError(const char *, int, const char *, + * const char *, Encoding) "LogError::LogError()". + * + * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()" + */ + enum Encoding + { + /*! LATIN-1 */ + LATIN1, + /*! + * The encoding specified by QTextCodec::codecForTr() + * (Latin-1 if none has been set). + */ + CODECFORTR, + /*! UTF-8 */ + UNICODEUTF8 + }; + Q_ENUMS(Encoding) + + /*! + * Creates an empty error. The error code is set to 0 and all other + * members are set to be empty. + * + * \sa isEmpty() + */ + LogError(); + + /*! + * Creates an error with the Message \a rMessage and the error code + * \a code. The symbol for the error code is set to \a rSymbol and the + * context to \a rContext. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requested. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const QString &rMessage, + int code = 0, + const QString &rSymbol = QString(), + const QString &rContext = QString()); + + /*! + * Creates an error with the Message \a pMessage and the error code + * \a code. The symbol for the error code is set to \a pSymbol and the + * context to \a pContext. + * + * \a encoding specifies the encoding of \a pMessage. \a pSymbol and + * \a pContext are expected to be Latin-1. + * + * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" + * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * the function tests, if \a pSymbol is the string representation of + * \a code. If it is, the symbol is set to be empty. Otherwise symbol + * is set to \a pSymbol. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const char *pMessage, + int code = 0, + const char *pSymbol = 0, + const char *pContext = 0, + Encoding encoding = LATIN1); + + // LogError(const LogError &rOther); // Use compiler default + // virtual ~LogError(); // Use compiler default + // LogError &operator=(const LogError &rOther); // Use compiler default + + /*! + * Returns the error code. + * + * \sa setCode() + */ + int code() const; + + /*! + * Returns the context for the error. + * + * \sa setContext() + */ + QString context() const; + + /*! + * Returns the error message. + * + * \sa setMessage() + */ + QString message() const; + + /*! + * Returns the symbol for the error code. + * + * \sa setSymbol() + */ + QString symbol() const; + + /*! + * Returns the translated error message. + * + * The translated message is created by calling + * QCoreApplication::translate() using context().toLatin1() as + * context and message.toUtf8() as message. + * + * \sa translatedMessageWithArgs() + */ + QString translatedMessage() const; + + /*! + * Sets the error code to \a code. + * + * \sa code() + */ + void setCode(int code); + + /*! + * Sets the context to \a rClassName. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requestd. + * + * \sa context(), translatedMessage(), translatedMessageWithArgs() + */ + void setContext(const QString &rClassName); + + /*! + * Sets the error message to \a rMessage + * + * \sa message() + */ + void setMessage(const QString &rMessage); + + /*! + * Sets the symbol for the error code to \a rSymbol. + * + * \sa symbol() + */ + void setSymbol(const QString &rSymbol); + + /*! + * Returns the last error set for the current thread using + * setLastError(). + * + * \note: This function is thread-safe. + * + * \sa setLastError() + */ + static LogError lastError(); + + /*! + * Sets the last error for the current thread to \a rLogError. + * + * \note: This function is thread-safe. + * + * \sa lastError() + */ + static void setLastError(const LogError &rLogError); + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa operator<<(), args(), clearArgs() + */ + LogError &addArg(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(const QString &rArg); + + /*! + * Appends \a rLogError to the list of causing errors and returns a + * reference to this error. + * + * \sa causingErrors(), clearCausingErrors() + */ + LogError &addCausingError(const LogError &rLogError); + + /*! + * Returns the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList args() const; + + /*! + * Returns the list of causing errors that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList causingErrors() const; + + /*! + * Clears the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), args() + */ + void clearArgs(); + + /*! + * Clears the list of causing errors that have been added to this error. + * + * \sa addCausingError(), causingErrors() + */ + void clearCausingErrors(); + + /*! + * Returns true, if the error code is 0 and the message is empty. + * Otherwise it returns false. + * + * \sa code(), message() + */ + bool isEmpty() const; + + /*! + * Returns the message with arguments. The arguments are incoorporated + * into the messag using QString::arg(). + * + * \sa QString::arg(), translatedMessageWithArgs() + */ + QString messageWithArgs() const; + + /*! + * Returns the translated message with arguments. The arguments are + * incoorporated into the messag using QString::arg(). + * + * \sa QString::arg(), messageWithArgs(), translatedMessage() + */ + QString translatedMessageWithArgs() const; + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa addArg() + */ + LogError &operator<<(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(const QString &rArg); + + /*! + * Returns a string representation of the error. + * + * The string has the following format: + * + * + * message (context::symbol, code): causing_error, causing_error + * + * + * If members are empty they are omitted: + * - Omit context, if empty + * - Omit symbol, if empty + * - Omit double colon with context and symbol, if both are empty + * - Omit code, if 0 + * - Omit bracket with context/symbol and code, if all are empty + * - Omit colon with causing errors, if no causing errors exist + */ + QString toString() const; + + private: + QString insertArgs(const QString &rMessage) const; + QString cleanMessage(const QString &rMessage); + + private: + int mCode; + QString mContext; + QString mMessage; + QString mSymbol; + QList mArgs; + QList mCausingErrors; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + friend QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LogError + * + * Writes the given error \a rLogError to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + + /*! + * \relates LogError + * + * Reads an error from the given stream \a rStream into the given + * error \a rLogError, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogError + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LogError(code:7 context:"Log4Qt::FileAppender" + * message:"Unable to open file '%1' for appender '%2'" + * symbol:"APPENDER_OPENING_FILE_ERROR" + * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") ) + * translatedMessage: "Unable to open file '%1' for appender '%2'" ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogError &rLogError); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int LogError::code() const + { return mCode; } + + inline QString LogError::context() const + { return mContext; } + + inline QString LogError::message() const + { return mMessage; } + + inline QString LogError::symbol() const + { return mSymbol; } + + inline void LogError::setCode(int code) + { mCode = code; } + + inline void LogError::setContext(const QString &rContext) + { mContext = rContext; } + + inline void LogError::setMessage(const QString &rMessage) + { mMessage = cleanMessage(rMessage); } + + inline void LogError::setSymbol(const QString &rSymbol) + { mSymbol = rSymbol; } + + inline LogError &LogError::addArg(const QVariant &rArg) + { mArgs << rArg; return *this; } + + inline LogError &LogError::addArg(int arg) + { mArgs << QVariant(arg); return *this; } + + inline LogError &LogError::addArg(const QString &rArg) + { mArgs << QVariant(rArg); return *this; } + + inline LogError &LogError::addCausingError(const LogError &rLogError) + { mCausingErrors << rLogError; return *this; } + + inline QList LogError::args() const + { return mArgs; } + + inline void LogError::clearArgs() + { mArgs.clear(); } + + inline void LogError::clearCausingErrors() + { mCausingErrors.clear(); } + + inline QList LogError::causingErrors() const + { return mCausingErrors; } + + inline bool LogError::isEmpty() const + { return mCode || !mMessage.isEmpty(); } + + inline QString LogError::messageWithArgs() const + { return insertArgs(message()); } + + inline QString LogError::translatedMessageWithArgs() const + { return insertArgs(translatedMessage()); } + + inline LogError &LogError::operator<<(const QVariant &rArg) + { return addArg(rArg); } + + inline LogError &LogError::operator<<(int arg) + { return addArg(arg); } + + inline LogError &LogError::operator<<(const QString &rArg) + { return addArg(rArg); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LogError) +Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_ERROR_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logobject.cpp b/GC-3.6.1-T3/src/log4qt/helpers/logobject.cpp new file mode 100644 index 0000000..44f1121 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logobject.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobject.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObject + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogObject &rLogObject) + { + return rLogObject.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logobject.h b/GC-3.6.1-T3/src/log4qt/helpers/logobject.h new file mode 100644 index 0000000..97b02c5 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logobject.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_increment and q_atomic_decrement + * with QAtomicInt. + * Feb 2009, Martin Heinrich + * - Fixed a problem where the pParent parameter of the constructor + * was not passed on to the QObject constructor + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECT_H +#define LOG4QT_LOGOBJECT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include "log4qt/helpers/classlogger.h" +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# warning "QAtomicInt reference counting is not native. The class Log4Qt::LogObject is not thread-safe." +# endif +#endif + + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LogObject is the common base class for many classes + * in the package. + * + * The class inherits QObject to allow its subclass to be accessed using + * the Qt property system. + * + * LogObject objects provide a reference counter. A reference to the + * object is established by calling retain() and freed by calling + * release(). The object will delete itself when the reference counter + * is decremented to 0. + * + * A class specific logger can be accessed over logger(). + * + * The class also implements generic streaming to QDebug. Streaming an + * object to QDebug will invoke debug() to create class specific output. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Ownership "Object ownership", + * LOG4QT_DECLARE_QCLASS_LOGGER + */ + class LogObject : public QObject + { + Q_OBJECT + + public: + /*! + * Creates a LogObject which is a child of \a pObject. + */ + LogObject(QObject *pObject = 0); + + /*! + * Destroys the LogObject. + */ + virtual ~LogObject(); + + private: + LogObject(const LogObject &rOther); // Not implemented + LogObject &operator=(const LogObject &rOther); // Not implemented + + public: + /*! + * Returns the value of the reference counter. + */ + int referenceCount() const; + + /*! + * Decrements the reference count of the object. If the reference count + * count reaches zero and the object does not have a parent the object + * is deleted. + */ + void release(); + + /*! + * Increments the reference count of the object. + */ + void retain(); + + protected: + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to + * generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif // QT_NO_DEBUG_STREAM + + /*! + * Returns a pointer to a Logger named after of the object. + * + * \sa Logger::logger(const char *pName) + */ + Logger* logger() const; + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile int mReferenceCount; +#else + mutable QAtomicInt mReferenceCount; +#endif + mutable ClassLogger mLog4QtClassLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogObject + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle sub-classing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LogObject::LogObject(QObject *pParent) : + QObject(pParent), + mReferenceCount() + {} + + inline LogObject::~LogObject() + {} + + inline int LogObject::referenceCount() const +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + { return mReferenceCount; } +#else + { return mReferenceCount.loadAcquire(); } +#endif + + inline void LogObject::release() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { if ((q_atomic_decrement(&mReferenceCount) == 0) && !parent()) + delete(this); } +#else + { if (!mReferenceCount.deref()) + delete(this); } +#endif + + inline void LogObject::retain() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { q_atomic_increment(&mReferenceCount); } +#else + { mReferenceCount.ref(); } +#endif + + inline Logger *LogObject::logger() const + { return mLog4QtClassLogger.logger(this); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogObject, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGOBJECT_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.cpp b/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.cpp new file mode 100644 index 0000000..8084a79 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.cpp @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobjectptr.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObjectPtr + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.h b/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.h new file mode 100644 index 0000000..6a8b613 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/logobjectptr.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECTPTR_H +#define LOG4QT_LOGOBJECTPTR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +namespace Log4Qt +{ + /*! + * \brief The class LogObjectPtr implements automatic reference counting + * for LogObject objects. + */ + template + class LogObjectPtr + { + public: + /*! + * Constructs a 0 LogObject pointer. + */ + LogObjectPtr(); + + /*! + * Constructs a LogObject pointer that points to the same object then + * \a rOther. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(const LogObjectPtr &rOther); + + /*! + * Constructs a LogObject pointer that points to the object + * \a LogObject. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(T *pLogObject); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * same object that \a rOther points to. The reference counter of the + * object the LogObjectPtr pointed to before the assignment is + * decremented by one. The reference counter of the object \a rOther + * is pointing to is incremented by one. + */ + LogObjectPtr &operator=(const LogObjectPtr &rOther); + + /*! + * Destructs the object. The reference counter of the object the + * LogObjectPtr points to is decremented by one. + */ + ~LogObjectPtr(); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * object \a pLogObject. The reference counter of the object the + * LogObjectPtr pointed to before the assignment is decremented by + * one. The reference counter of the object \a pLogObject is pointing + * to is incremented by one. + */ + LogObjectPtr &operator=(T *pLogObject); + + /*! + * Arrow operator. Returns the LogObject the object points to. + */ + T *operator->() const; + + /*! + * Dereference operator. Returns a pointer to the LogObject the + * object points to. + */ + T &operator*() const; + + /*! + * Cast operator. Cast the object to the LogObject the object points + * to. + */ + operator T*() const; + + private: + void retain() const; + void release() const; + + private: + T *mpLogObject; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + template + inline LogObjectPtr::LogObjectPtr() : + mpLogObject(0) + {} + + template + inline LogObjectPtr::LogObjectPtr(const LogObjectPtr &rOther) : + mpLogObject(rOther.mpLogObject) + { retain(); } + + template + inline LogObjectPtr::LogObjectPtr(T *pLogObject) : + mpLogObject(pLogObject) + { retain(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(const LogObjectPtr &rOther) + { rOther.retain(); + release(); + mpLogObject = rOther.mpLogObject; + return *this; } + + template + inline LogObjectPtr::~LogObjectPtr() + { release(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(T *pLogObject) + { if (pLogObject) + reinterpret_cast(pLogObject)->retain(); + release(); + mpLogObject = pLogObject; + return *this; } + + template + inline T *LogObjectPtr::operator->() const + { return mpLogObject; } + + template + inline T &LogObjectPtr::operator*() const + { return *mpLogObject; } + + template + inline LogObjectPtr::operator T*() const + { return mpLogObject; } + + template + inline void LogObjectPtr::retain() const + { if (mpLogObject) + reinterpret_cast(mpLogObject)->retain(); } + + template + inline void LogObjectPtr::release() const + { + if (mpLogObject) + reinterpret_cast(mpLogObject)->release(); + } + +} // namespace Log4Qt + + +//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); // Declare within T + + +#endif // LOG4QT_LOGOBJECTPTR_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.cpp b/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.cpp new file mode 100644 index 0000000..c8dc969 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.cpp @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a problem were OptionConverter::toBoolean would not + * return the default value, if the conversion fails. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/optionconverter.h" + +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/logger.h" +#include "log4qt/consoleappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::OptionConverter) + + + + /************************************************************************** + * Class implementation: OptionConverter + **************************************************************************/ + + + QString OptionConverter::findAndSubst(const Properties &rProperties, + const QString &rKey) + { + QString value = rProperties.property(rKey); + if (value.isNull()) + return value; + + const QString begin_subst = QLatin1String("${"); + const QString end_subst = QLatin1String("}"); + const int begin_length = begin_subst.length(); + const int end_length = end_subst.length(); + + // Don't return a null string, the null string indicates that the + // property key does not exist. + QString result = QLatin1String(""); + + int i = 0; + int begin; + int end; + while (i < value.length()) + { + begin = value.indexOf(begin_subst, i); + if (begin == -1) + { + result += value.mid(i); + i = value.length(); + } + else + { + result += value.mid(i, begin - i); + end = value.indexOf(end_subst, i + begin_length); + if (end == -1) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2."), + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + "Log4Qt::OptionConverter"); + e << begin << value; + logger()->error(e); + return result; + } + else + { + result += findAndSubst(rProperties, value.mid(begin + begin_length, end - begin - end_length - 1)); + i = end + end_length; + } + } + } + return result; + } + + + QString OptionConverter::classNameJavaToCpp(const QString &rClassName) + { + const QLatin1String java_class_delimiter("."); + const QLatin1String cpp_class_delimiter("::"); + + QString result = rClassName; + return result.replace(java_class_delimiter, cpp_class_delimiter); + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool *p_ok) + { + const QLatin1String str_true("true"); + const QLatin1String str_enabled("enabled"); + const QLatin1String str_one("1"); + const QLatin1String str_false("false"); + const QLatin1String str_disabled("disabled"); + const QLatin1String str_zero("0"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == str_true || s == str_enabled || s == str_one) + return true; + if (s == str_false || s == str_disabled || s == str_zero) + return false; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a boolean"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return false; + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool default_value) + { + bool ok; + bool result = toBoolean(rOption, &ok); + if (ok) + return result; + else + return default_value; + } + + qint64 OptionConverter::toFileSize(const QString &rOption, + bool *p_ok) + { + // - Search for unit + // - Convert characters befor unit to int + // - Error, if + // - the conversion failed + // - the value < 0 + // - there is text after the unit characters + + if (p_ok) + *p_ok = false; + QString s = rOption.trimmed().toLower(); + qint64 f = 1; + int i; + i = s.indexOf(QLatin1String("kb")); + if (i >= 0) + f = 1024; + else + { + i = s.indexOf(QLatin1String("mb")); + if (i >= 0) + f = 1024 * 1024; + else + { + i = s.indexOf(QLatin1String("gb")); + if (i >= 0) + f = 1024 * 1024 * 1024; + } + } + if (i < 0) + i = s.length(); + bool ok; + qint64 value = s.left(i).toLongLong(&ok); + if (!ok || value < 0 || s.length() > i + 2) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a file size"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + if (p_ok) + *p_ok = true; + return value * f; + } + + + int OptionConverter::toInt(const QString &rOption, + bool *p_ok) + { + int value = rOption.trimmed().toInt(p_ok); + if (*p_ok) + return value; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for an integer"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + + + Level OptionConverter::toLevel(const QString &rOption, + bool *p_ok) + { + bool ok; + Level level = Level::fromString(rOption.toUpper().trimmed(), &ok); + if (p_ok) + *p_ok = ok; + if (ok) + return level; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a level"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return level; + } + + + Level OptionConverter::toLevel(const QString &rOption, + const Level &rDefaultValue) + { + bool ok; + Level result = toLevel(rOption, &ok); + if (ok) + return result; + else + return rDefaultValue; + } + + + int OptionConverter::toTarget(const QString &rOption, + bool *p_ok) + { + const QLatin1String java_stdout("system.out"); + const QLatin1String cpp_stdout("stdout_target"); + const QLatin1String java_stderr("system.err"); + const QLatin1String cpp_stderr("stderr_target"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == java_stdout || s == cpp_stdout) + return ConsoleAppender::STDOUT_TARGET; + if (s == java_stderr || s == cpp_stderr) + return ConsoleAppender::STDERR_TARGET; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a target"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return ConsoleAppender::STDOUT_TARGET; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.h b/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.h new file mode 100644 index 0000000..dda49d2 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/optionconverter.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_OPTIONCONVERTER_H +#define LOG4QT_OPTIONCONVERTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + +namespace Log4Qt +{ + class Properties; + + /*! + * \brief The class OptionConverter provides functions to convert strings + * to property values. + */ + class OptionConverter + { + private: + OptionConverter(); + OptionConverter(const OptionConverter &rOther); // Not implemented + // virtual ~OptionConverter(); // Use compiler default + OptionConverter &operator=(const OptionConverter &rOther); // Not implemented + + public: + static QString findAndSubst(const Properties &rProperties, + const QString &rKey); + + /*! + * Returns the JAVA class name \a rClassName as C++ class name by + * replacing all . characters with ::. + */ + static QString classNameJavaToCpp(const QString &rClassName); + + /*! + * Converts the option \a rOption to a boolean value. Valid strings + * for true are "true", "enabled" and "1". Valid strings + * for false are "false", "disabled" and "0". If the conversion is + * successful, the target is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and false is returned. + */ + static bool toBoolean(const QString &rOption, + bool *p_ok = 0); + + static bool toBoolean(const QString &rOption, + bool default_value); + + /*! + * Converts the option string \a rOption to a file size. The string can + * be a positive integer followed by an optional unit suffix "KB", "MB" + * or "GB". If a unit suffix is specified the the integer is + * interpreted as kilobytes, megabytes or gigabytes. If the conversion + * is successful, the size is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and 0 is returned. + */ + static qint64 toFileSize(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a integer value using + * QString::toInt(). If the conversion is successful, the integer is + * returned and \a p_ok is set to true. Otherwise an error is written + * to the log, \a p_ok is set to false and 0 is returned. + */ + static int toInt(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a level value using + * Level::fromString(). If the conversion is successful, the level + * is returned and \a p_ok is set to true. Otherwise an error is + * written to the log, \a p_ok is set to false and a level with + * the value Level::NULL_INT is returned. + * + * \sa Level::fromString() + */ + static Level toLevel(const QString &rOption, + bool *p_ok = 0); + + static Level toLevel(const QString &rOption, + const Level &rDefaultValue); + + /*! + * Converts the option \a rOption to a ConsoleAppender::Target value. + * Valid strings for \a rOption are "System.out", "STDOUT_TARGET", + * "System.err" and "STDERR_TARGET". If the conversion is successful, + * the target is returned and \a p_ok is set to true. Otherwise an + * error is written to the log, \a p_ok is set to false and + * ConsoleAppender::STDOUT_TARGET is returned. + */ + static int toTarget(const QString &rOption, + bool *p_ok = 0); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::OptionConverter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_OPTIONCONVERTER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.cpp b/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.cpp new file mode 100644 index 0000000..1fd54f0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.cpp @@ -0,0 +1,893 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in LiteralPatternConverter::convert. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/patternformatter.h" + +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + /*! + * \brief The class FormattingInfo stores the formatting modifier for a + * pattern converter. + * + * \sa PatternConverter + */ + class FormattingInfo + { + public: + FormattingInfo() + { clear(); } + // FormattingInfo(const FormattingInfo &rOther); // Use compiler default + // virtual ~FormattingInfo(); // Use compiler default + // FormattingInfo &operator=(const FormattingInfo &rOther); // Use compiler default + + void clear(); + static QString intToString(int i); + + public: + int mMinLength; + int mMaxLength; + bool mLeftAligned; + }; + + + /*! + * \brief The class PatternConverter is the abstract base class for all + * pattern converters. + * + * PatternConverter handles the minimum and maximum modifier for a + * conversion character. The actual conversion is by calling the + * convert() member function of the derived class. + * + * \sa PatternLayout::format() + */ + class PatternConverter + { + public: + PatternConverter(const FormattingInfo &rFormattingInfo = FormattingInfo()) : + mFormattingInfo(rFormattingInfo) + {}; + virtual ~PatternConverter() + {}; + private: + PatternConverter(const PatternConverter &rOther); // Not implemented + PatternConverter &operator=(const PatternConverter &rOther); // Not implemented + + public: + void format(QString &rFormat, const LoggingEvent &rLoggingEvent) const; + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const = 0; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + protected: + FormattingInfo mFormattingInfo; + }; + + + /*! + * \brief The class BasicPatternConverter converts several members of a + * LoggingEvent to a string. + * + * BasicPatternConverter is used by PatternLayout to convert members that + * do not reuquire additional formatting to a string as part of formatting + * the LoggingEvent. It handles the following conversion characters: + * 'm', 'p', 't', 'x' + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class BasicPatternConverter : public PatternConverter + { + public: + enum Type { + MESSAGE_CONVERTER, + NDC_CONVERTER, + LEVEL_CONVERTER, + THREAD_CONVERTER, + }; + + public: + BasicPatternConverter(const FormattingInfo &rFormattingInfo, + Type type) : + PatternConverter(rFormattingInfo), + mType(type) + {}; + // virtual ~BasicPatternConverter(); // Use compiler default + private: + BasicPatternConverter(const BasicPatternConverter &rOther); // Not implemented + BasicPatternConverter &operator=(const BasicPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + Type mType; + }; + + + /*! + * \brief The class DatePatternConverter converts the time stamp of a + * LoggingEvent to a string. + * + * DatePatternConverter is used by PatternLayout to convert the time stamp + * of a LoggingEvent to a string as part of formatting the LoggingEvent. + * It handles the 'd' and 'r' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class DatePatternConverter : public PatternConverter + { + public: + DatePatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rFormat) : + PatternConverter(rFormattingInfo), + mFormat(rFormat) + {}; + // virtual ~DatePatternConverter(); // Use compiler default + private: + DatePatternConverter(const DatePatternConverter &rOther); // Not implemented + DatePatternConverter &operator=(const DatePatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mFormat; + }; + + + /*! + * \brief The class LiteralPatternConverter provides string literals. + * + * LiteralPatternConverter is used by PatternLayout to embed string + * literals as part of formatting the LoggingEvent. It handles string + * literals and the 'n' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LiteralPatternConverter : public PatternConverter + { + public: + LiteralPatternConverter(const QString &rLiteral) : + PatternConverter(), + mLiteral(rLiteral) + {}; + // virtual ~LiteralPatternConverter(); // Use compiler default + private: + LiteralPatternConverter(const LiteralPatternConverter &rOther); // Not implemented + LiteralPatternConverter &operator=(const LiteralPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mLiteral; + }; + + + /*! + * \brief The class LoggerPatternConverter converts the Logger name of a + * LoggingEvent to a string. + * + * LoggerPatternConverter is used by PatternLayout to convert the Logger + * name of a LoggingEvent to a string as part of formatting the + * LoggingEvent. It handles the 'c' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LoggerPatternConverter : public PatternConverter + { + public: + LoggerPatternConverter(const FormattingInfo &rFormattingInfo, + int precision) : + PatternConverter(rFormattingInfo), + mPrecision(precision) + {}; + // virtual ~LoggerPatternConverter(); // Use compiler default + private: + LoggerPatternConverter(const LoggerPatternConverter &rOther); // Not implemented + LoggerPatternConverter &operator=(const LoggerPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + int mPrecision; + }; + + + + /*! + * \brief The class MDCPatternConverter converts the MDC data of a + * LoggingEvent to a string. + * + * MDCPatternConverter is used by PatternLayout to convert the MDC data of + * a LoggingEvent to a string as part of formatting the LoggingEvent. It + * handles the 'X' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class MDCPatternConverter : public PatternConverter + { + public: + MDCPatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rKey) : + PatternConverter(rFormattingInfo), + mKey(rKey) + {}; + // virtual ~MDCPatternConverter(); // Use compiler default + private: + MDCPatternConverter(const MDCPatternConverter &rOther); // Not implemented + MDCPatternConverter &operator=(const MDCPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mKey; + }; + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const FormattingInfo &rFormattingInfo); + #endif + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PatternFormatter) + + + + /************************************************************************** + * Class implementation: PatternFormatter + **************************************************************************/ + + + PatternFormatter::PatternFormatter(const QString &rPattern) : + mIgnoreCharacters(QLatin1String("CFlLM")), + mConversionCharacters(QLatin1String("cdmprtxX")), + mOptionCharacters(QLatin1String("cd")), + mPattern(rPattern), + mPatternConverters() + { + parse(); + } + + + PatternFormatter::~PatternFormatter() + { + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + delete p_converter; + } + + + QString PatternFormatter::format(const LoggingEvent &rLoggingEvent) const + { + QString result; + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + p_converter->format(result, rLoggingEvent); + return result; + } + + + bool PatternFormatter::addDigit(const QChar &rDigit, + int &rValue) + { + if (!rDigit.isDigit()) + return false; + + int digit_value = rDigit.digitValue(); + if (rValue > (INT_MAX - digit_value) / 10) + rValue = INT_MAX; + else + rValue = rValue * 10 + digit_value; + return true; + } + + + void PatternFormatter::createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption) + { + Q_ASSERT_X(mConversionCharacters.indexOf(rChar) >= 0, "PatternFormatter::createConverter", "Unknown conversion character" ); + + LogError e("Creating Converter for character '%1' min %2, max %3, left %4 and option '%5'"); + e << QString(rChar) + << FormattingInfo::intToString(rFormattingInfo.mMinLength) + << FormattingInfo::intToString(rFormattingInfo.mMaxLength) + << rFormattingInfo.mLeftAligned + << rOption; + logger()->trace(e); + + switch (rChar.toLatin1()) + { + case 'c': + mPatternConverters << new LoggerPatternConverter(rFormattingInfo, + parseIntegerOption(rOption)); + break; + case 'd': + { + QString option = rOption; + if (rOption.isEmpty()) + option = QLatin1String("ISO8601"); + mPatternConverters << new DatePatternConverter(rFormattingInfo, + option); + break; + } + case 'm': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::MESSAGE_CONVERTER); + break; + case 'p': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::LEVEL_CONVERTER); + break; + case 'r': + mPatternConverters << new DatePatternConverter(rFormattingInfo, + QLatin1String("RELATIVE")); + break; + case 't': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::THREAD_CONVERTER); + break; + case 'x': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::NDC_CONVERTER); + break; + case 'X': + mPatternConverters << new MDCPatternConverter(rFormattingInfo, + rOption); + break; + default: + Q_ASSERT_X(false, "PatternFormatter::createConverter", "Unknown pattern character"); + } + } + + + void PatternFormatter::createLiteralConverter(const QString &rLiteral) + { + logger()->trace("Creating literal LiteralConverter with Literal '%1'", + rLiteral); + mPatternConverters << new LiteralPatternConverter(rLiteral); + } + + + void PatternFormatter::parse() + { + enum State { + LITERAL_STATE, + ESCAPE_STATE, + MIN_STATE, + DOT_STATE, + MAX_STATE, + CHARACTER_STATE, + POSSIBLEOPTION_STATE, + OPTION_STATE + }; + + int i = 0; + QChar c; + char ch; + State state = LITERAL_STATE; + FormattingInfo formatting_info; + QString literal; + int converter_start = 0; + int option_start = 0; + while (i < mPattern.length()) + { + // i points to the current character + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character + // continue is used to change state without consuming the character + + c = mPattern.at(i); + ch = c.toLatin1(); + switch (state) + { + case LITERAL_STATE: + if (ch == '%') + { + formatting_info.clear(); + converter_start = i; + state = ESCAPE_STATE; + } else + literal += c; + break; + case ESCAPE_STATE: + if (ch == '%') + { + literal += c; + state = LITERAL_STATE; + } + else if (ch == 'n') + { + literal += Layout::endOfLine(); + state = LITERAL_STATE; + } + else + { + if (!literal.isEmpty()) + { + createLiteralConverter(literal); + literal.clear(); + } + if (ch == '-') + formatting_info.mLeftAligned = true; + else if (c.isDigit()) + { + formatting_info.mMinLength = c.digitValue(); + state = MIN_STATE; + } + else if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case MIN_STATE: + if (!addDigit(c, formatting_info.mMinLength)) + { + if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case DOT_STATE: + if (c.isDigit()) + { + formatting_info.mMaxLength = c.digitValue(); + state = MAX_STATE; + } + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + LAYOUT_EXPECTED_DIGIT_ERROR, + "Log4Qt::PatternFormatter"); + e << QString(c); + logger()->error(e); + } + break; + case MAX_STATE: + if (!addDigit(c, formatting_info.mMaxLength)) + { + state = CHARACTER_STATE; + continue; + } + break; + case CHARACTER_STATE: + if (mIgnoreCharacters.indexOf(c) >= 0) + state = LITERAL_STATE; + else if (mOptionCharacters.indexOf(c) >= 0) + state = POSSIBLEOPTION_STATE; + else if (mConversionCharacters.indexOf(c) >= 0) + { + createConverter(c, formatting_info); + state = LITERAL_STATE; + } + else + { + logger()->warn("Invalid conversion character '%1' at %2 in pattern '%3'", + c, i, mPattern); + createLiteralConverter(mPattern.mid(converter_start, i - converter_start + 1)); + state = LITERAL_STATE; + } + break; + case POSSIBLEOPTION_STATE: + if (ch == '{') + { + option_start = i; + state = OPTION_STATE; + } + else + { + createConverter(mPattern.at(i - 1), + formatting_info); + state = LITERAL_STATE; + continue; + } + break; + case OPTION_STATE: + if (ch == '}') + { + createConverter(mPattern.at(option_start - 1), + formatting_info, + mPattern.mid(option_start + 1, i - option_start - 1)); + state = LITERAL_STATE; + } + break; + default: + Q_ASSERT_X(false, "PatternFormatter::parse()", "Unknown parsing state constant"); + state = LITERAL_STATE; + } + i++; + } + + if (state != LITERAL_STATE) + { + logger()->warn("Unexptected end of pattern '%1'", mPattern); + if (state == ESCAPE_STATE) + literal += c; + else + literal += mPattern.mid(converter_start); + } + + if (!literal.isEmpty()) + createLiteralConverter(literal); + } + + + int PatternFormatter::parseIntegerOption(const QString &rOption) + { + if (rOption.isEmpty()) + return 0; + + bool ok; + int result = rOption.toInt(&ok); + if (!ok) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option '%1' cannot be converted into an integer"), + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + "Log4Qt::PatterFormatter"); + e << rOption; + logger()->error(e); + } + if (result < 0) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option %1 isn't a positive integer"), + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + "Log4Qt::PatterFormatter"); + e << result; + logger()->error(e); + result = 0; + } + return result; + } + + + /************************************************************************** + * Class implementation: FormattingInfo + **************************************************************************/ + + + void FormattingInfo::clear() + { + mMinLength = 0; + mMaxLength = INT_MAX; + mLeftAligned = false; + }; + + + QString FormattingInfo::intToString(int i) + { + if (i == INT_MAX) + return QLatin1String("INT_MAX"); + else + return QString::number(i); + } + + + + /************************************************************************** + * Class implementation: PatternConverter + **************************************************************************/ + + + void PatternConverter::format(QString &rFormat, const LoggingEvent &rLoggingEvent) const + { + const QLatin1Char space(' '); + QString s = convert(rLoggingEvent); + + if (s.length() > mFormattingInfo.mMaxLength) + rFormat += s.left(mFormattingInfo.mMaxLength); + else if (mFormattingInfo.mLeftAligned) + rFormat += s.leftJustified(mFormattingInfo.mMinLength, space, false); + else + rFormat += s.rightJustified(mFormattingInfo.mMinLength, space, false); + } + + + + /************************************************************************** + * Class implementation: BasicPatternConverter + **************************************************************************/ + + + QString BasicPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + switch (mType) + { + case MESSAGE_CONVERTER: + return rLoggingEvent.message(); + break; + case NDC_CONVERTER: + return rLoggingEvent.ndc(); + break; + case LEVEL_CONVERTER: + return rLoggingEvent.level().toString(); + break; + case THREAD_CONVERTER: + return rLoggingEvent.threadName(); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::convert()", "Unkown type constant"); + return QString(); + } + } + + + QDebug BasicPatternConverter::debug(QDebug &rDebug) const + { + QString type; + switch (mType) + { + case MESSAGE_CONVERTER: + type = QLatin1String("MESSAGE_CONVERTER"); + break; + case NDC_CONVERTER: + type = QLatin1String("NDC_CONVERTER"); + break; + case LEVEL_CONVERTER: + type = QLatin1String("LEVEL_CONVERTER"); + break; + case THREAD_CONVERTER: + type = QLatin1String("THREAD_CONVERTER"); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::debug()", "Unkown type constant"); + } + rDebug.nospace() << "BasicPatternConverter(" + << mFormattingInfo + << "type:" << type + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: DatePatternConverter + **************************************************************************/ + + + QString DatePatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()).toString(mFormat); + } + + + QDebug DatePatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DatePatternConverter(" + << mFormattingInfo + << "format:" << mFormat + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LiteralPatternConverter + **************************************************************************/ + + + QString LiteralPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + Q_UNUSED(rLoggingEvent); + return mLiteral; + }; + + + QDebug LiteralPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LiteralPatternConverter(" + << mFormattingInfo + << "literal:" << mLiteral + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LoggerPatternConverter + **************************************************************************/ + + + QString LoggerPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + if (!rLoggingEvent.logger()) + return QString(); + QString name = rLoggingEvent.logger()->name(); + if (mPrecision <= 0 || (name.isEmpty())) + return name; + + const QString separator(QLatin1String("::")); + + int i = mPrecision; + int begin = name.length(); + while ((i > 0) && (begin >= 0)) + { + begin = name.lastIndexOf(separator, begin - name.length() - 1); + i--; + } + if (begin < 0) + begin = 0; + else + begin += 2; + return name.mid(begin); + } + + + QDebug LoggerPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LoggerPatternConverter(" + << mFormattingInfo + << "precision:" << mPrecision + << ")"; + return rDebug.space(); + } + + + + /****************************************************************************** + * Class implementation: MDCPatternConverter + ******************************************************************************/ + + + QString MDCPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return rLoggingEvent.mdc().value(mKey); + }; + + + QDebug MDCPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "MDCPatternConverter(" + << mFormattingInfo + << "key:" << mKey + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternFormatter &rPatternFormatter) + { + debug.nospace() << "PatternFormatter(" + << "pattern:" << rPatternFormatter.mPattern << " " + << "converters:("; + int i; + for (i = 0; i < rPatternFormatter.mPatternConverters.size(); i++) + { + if (i > 0) + debug.nospace() << ", "; + debug.nospace() << *rPatternFormatter.mPatternConverters.at(i); + } + debug.nospace() << ") )"; + return debug.space(); + } + #endif + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const FormattingInfo &rFormattingInfo) + { + debug.nospace() << "FormattingInfo(" + << "min:" << FormattingInfo::intToString(rFormattingInfo.mMinLength) << " " + << "max:" << FormattingInfo::intToString(rFormattingInfo.mMaxLength) << " " + << "left:" << rFormattingInfo.mLeftAligned + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternConverter &rPatternConverter) + { + return rPatternConverter.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.h b/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.h new file mode 100644 index 0000000..8965e81 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/patternformatter.h @@ -0,0 +1,195 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNFORMATTER_H +#define LOG4QT_PATTERNFORMATTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class FormattingInfo; + class PatternConverter; + class LoggingEvent; + + /*! + * \brief The class PatternFormatter formats a logging event based on a + * pattern string. + * + * The class PatternFormatter formats a LoggingEvent base on a pattern + * string. It is used by the patternLayout and TTCCLayout class to + * implement the formatting. + * + * On object construction the provided patterns tring is parsed. Based on + * the information found a chain of PatternConverter is created. Each + * PatternConverter handles a certain member of a LoggingEvent. + * + * \sa PatternLayout::format() + * \sa TTCCLayout::format() + */ + class PatternFormatter + { + public: + /*! + * Creates a PatternFormatter using a the specified \a rPattern. + */ + PatternFormatter(const QString &rPattern); + + /*! + * Destroys the PatternFormatter and all PatternConverter. + */ + virtual ~PatternFormatter(); + + private: + PatternFormatter(const PatternFormatter &rOther); // Not implemented + PatternFormatter &operator=(const PatternFormatter &rOther); // Not implemented + + public: + /*! + * Formats the given \a rLoggingEvent using the chain of + * PatternConverter created during construction from the specified + * pattern. + */ + QString format(const LoggingEvent &rLoggingEvent) const; + + private: + /*! + * If the character \a rDigit is a digit the digit is added to the + * integer \a rValue and the function returns true. Otherwise the + * function returns false. + * + * The function adds the digit by multiplying the existing value + * with ten and adding the numerical value of the digit. If the + * maximum integer value would be exceeded by the operation + * \a rValue is set to INT_MAX. + */ + bool addDigit(const QChar &rDigit, + int &rValue); + + /*! + * Creates a PatternConverter based on the specified conversion + * character \a rChar, the formatting information + * \a rFormattingInfo and the option \a rOption. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption = QString()); + + /*! + * Creates a LiteralPatternConverter with the string literal + * \a rLiteral. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createLiteralConverter(const QString &rLiteral); + + /*! + * Parses the pattern string specified on construction and creates + * PatternConverter according to it. + */ + void parse(); + + /*! + * Parses an integer option from an option string. If the string is + * not a valid integer or the integer value is less then zero, zero + * is returned. Returns the end of line seperator for the operating + * system. + */ + int parseIntegerOption(const QString &rOption); + + private: + const QString mIgnoreCharacters; + const QString mConversionCharacters; + const QString mOptionCharacters; + QString mPattern; + QList mPatternConverters; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug, const PatternFormatter &rPatternFormatter); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PatternFormatter + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %PatternFormatter(pattern:"%r [%t] %p %c %x - %m%n" + * converters:( + * DatePatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) format: "RELATIVE" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " [" ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "THREAD_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "] " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "LEVEL_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * LoggerPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) precision: 0 ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "NDC_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " - " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "MESSAGE_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "" ) ) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PatternFormatter &rPatternFormatter); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::PatternFormatter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PATTERNFORMATTER_H diff --git a/GC-3.6.1-T3/src/log4qt/helpers/properties.cpp b/GC-3.6.1-T3/src/log4qt/helpers/properties.cpp new file mode 100644 index 0000000..ec74978 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/properties.cpp @@ -0,0 +1,364 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/properties.h" + +#include +#include +#include +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties) + + + + /************************************************************************** + * Class implementation: Properties + **************************************************************************/ + + + void Properties::load(QIODevice *pDevice) + { + const QLatin1Char append_char(msEscapeChar); + + if (!pDevice) + { + logger()->warn("No device specified for load."); + return; + } + + QTextStream stream(pDevice); + QString line; + int line_number = 0; + QString property; + int property_start_line = 1; + + do { + line = trimLeft(stream.readLine()); + line_number++; + + if (!line.isEmpty() && line.at(line.length() - 1) == append_char) + property += line.left(line.length() - 1); + else + { + property += line; + parseProperty(property, property_start_line); + property.clear(); + property_start_line = line_number + 1; + } + } + while (!line.isNull()); + } + + + void Properties::load(const QSettings &rSettings) + { + QStringList keys = rSettings.childKeys(); + QString key; + Q_FOREACH(key, keys) + insert(key, rSettings.value(key).toString()); + } + + + QString Properties::property(const QString &rKey) const + { + // Null string indicates the property does not contain the key. + + if (contains(rKey)) + { + QString value = this->value(rKey); + if (value.isNull()) + return QString(QLatin1String("")); + else + return value; + } + + if (mpDefaultProperties) + return mpDefaultProperties->property(rKey); + else + return QString(); + } + + + QString Properties::property(const QString &rKey, + const QString &rDefaultValue) const + { + QString value = property(rKey); + if (value.isNull()) + return rDefaultValue; + else + return value; + } + + + QStringList Properties::propertyNames() const + { + QStringList default_keys; + if (mpDefaultProperties) + default_keys = mpDefaultProperties->propertyNames(); + + QStringList keys = this->keys(); + QString key; + Q_FOREACH(key, default_keys) + if (!keys.contains(key)) + keys << key; + + return keys; + } + + + void Properties::parseProperty(const QString &rProperty, + int line) + { + Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces"); + + enum State + { + KEY_STATE, + KEYSPACE_STATE, + SPACEVALUE_STATE, + VALUE_STATE, + KEYESCAPE_STATE, + VALUEESCAPE_STATE, + UNICODEESCAPE_STATE + }; + const QString value_escape_codes =QLatin1String(msValueEscapeCodes); + const QString value_escape_chars = QLatin1String(msValueEscapeChars); + Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map"); + const QString key_escape_codes = QLatin1String(msKeyEscapeCodes); + const QString key_escape_chars = QLatin1String(msKeyEscapeChars); + Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map"); + + if (rProperty.isEmpty()) + return; + + int i = 0; + QChar c; + char ch; + State state = KEY_STATE; + QString key; + QString value; + QString *p_string = &key; + uint ucs = 0; + int ucs_digits = 0; + while (i < rProperty.length()) + { + // i points to the current character. + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character. + // continue is used to change state without consuming the character + + c = rProperty.at(i); + ch = c.toLatin1(); + + switch (state) + { + case KEY_STATE: + if (ch == '!' || ch == '#' ) + return; + else if (c.isSpace()) + { + p_string = &value; + state = KEYSPACE_STATE; + } + else if (ch == '=' || ch == ':') + { + p_string = &value; + state = SPACEVALUE_STATE; + } + else if (ch == msEscapeChar) + state = KEYESCAPE_STATE; + else + *p_string += c; + break; + case KEYSPACE_STATE: + if (ch == '=' || ch == ':') + state = SPACEVALUE_STATE; + else if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case SPACEVALUE_STATE: + if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case VALUE_STATE: + if (ch == msEscapeChar) + state = VALUEESCAPE_STATE; + else + *p_string += c; + break; + case KEYESCAPE_STATE: + { + int convert = key_escape_codes.indexOf(c); + if (convert >= 0) + *p_string += key_escape_chars.at(convert); + else + { + logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2", + QString(c), + line); + *p_string += c; + } + state = KEY_STATE; + break; + } + case VALUEESCAPE_STATE: + { + int convert = value_escape_codes.indexOf(c); + if (convert >= 0) + { + *p_string += value_escape_chars.at(convert); + state = VALUE_STATE; + } + else if (ch == 'u') + { + ucs = 0; + ucs_digits = 0; + state = UNICODEESCAPE_STATE; + } + else + { + logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line); + *p_string += c; + state = VALUE_STATE; + } + break; + } + case UNICODEESCAPE_STATE: + { + int hex = hexDigitValue(c); + if (hex >= 0) + { + ucs = ucs * 16 + hex; + ucs_digits++; + if (ucs_digits == 4 || i == rProperty.length() - 1) + { + *p_string += QChar(ucs); + state = VALUE_STATE; + } + } + else + { + if (ucs_digits > 0) + *p_string += QChar(ucs); + state = VALUE_STATE; + continue; + } + break; + } + default: + Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant"); + return; + } + i++; + } + + if (key.isEmpty() && !value.isEmpty()) + logger()->warn("Found value with no key in property starting at line %1", line); + + logger()->trace("Loaded property '%1' : '%2'", key, value); + insert(key, value); + } + + + int Properties::hexDigitValue(const QChar &rDigit) + { + bool ok; + int result = QString(rDigit).toInt(&ok, 16); + if (!ok) + return -1; + else + return result; + } + + + QString Properties::trimLeft(const QString &rLine) + { + int i = 0; + while (i < rLine.length() && rLine.at(i).isSpace()) + i++; + return rLine.right(rLine.length() - i); + } + + + const char Properties::msEscapeChar ='\\'; + const char *Properties::msValueEscapeCodes = "tnr\\\"\' "; + const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' "; + const char *Properties::msKeyEscapeCodes = " :="; + const char *Properties::msKeyEscapeChars = " :="; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Properties &rProperties) + { + debug.nospace() << "Properties(" + << "default:" << rProperties.defaultProperties() << " " + << "properties:" << *reinterpret_cast *>(&rProperties) + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/helpers/properties.h b/GC-3.6.1-T3/src/log4qt/helpers/properties.h new file mode 100644 index 0000000..a9601f4 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/helpers/properties.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.h + * created: September + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTIES_H +#define LOG4QT_PROPERTIES_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QIODevice; +class QSettings; + + +namespace Log4Qt +{ + /*! + * \brief The class Properties implements a JAVA property hash. + */ + class Properties : public QHash + { + public: + Properties(Properties *pDefaultProperties = 0); + // virtual ~Properties(); // Use compiler default + // Properties(const Properties &rOther); // Use compiler default + // Properties &operator=(const Properties &rOther); // Not implemented + + public: + Properties *defaultProperties() const; + QString property(const QString &rKey) const; + QString property(const QString &rKey, + const QString &rDefaultValue) const; + void setDefaultProperties(Properties *pDefault); + void setProperty(const QString &rKey, + const QString &rValue); + + // JAVA: void list(QTextStream &rTextStream); + void load(QIODevice *pDevice); + + /*! + * Reads all child keys from the QSettings object \a rSettings and + * inserts them into this object. The value is created using + * QVariant::toString(). Types that do not support toString() are + * resulting in an empty string. + * + * \code + * QSettings settings; + * settings.setValue("Package", "Full"); + * settings.setValue("Background", Qt::white); + * settings.setValue("Support", true); + * settings.setValue("Help/Language", "en_UK"); + * + * Properties properties + * properties.load(&settings) + * + * // properties (("Package", "Full"), ("Background", ""), ("Support", "true")) + * \endcode + */ + void load(const QSettings &rSettings); + + QStringList propertyNames() const; + // JAVA: void save(QIODevice *pDevice) const; + + private: + void parseProperty(const QString &rProperty, + int line); + static int hexDigitValue(const QChar &rDigit); + static QString trimLeft(const QString &rString); + + private: + Properties *mpDefaultProperties; + static const char msEscapeChar; + static const char *msValueEscapeCodes; + static const char *msValueEscapeChars; + static const char *msKeyEscapeCodes; + static const char *msKeyEscapeChars; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Properties + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Properties(default:0x0 properties:QHash(("log4j.appender.testAppender.layout", "org.apache.log4j.PatternLayout ") + * ("log4j.appender.testAppender.layout.ConversionPattern", "[%t] %-5p %l: %m%n") + * ("log4j.appender.testAppender.Append", "false ") + * ("log4j.appender.testAppender.File", "output/temp ") + * ("log4j.rootCategory", "TRACE, testAppender") + * ("log4j.appender.testAppender", "org.apache.log4j.FileAppender")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Properties &rProperties); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Properties::Properties(Properties *pDefaultProperties) : + mpDefaultProperties(pDefaultProperties) + {} + + inline Properties *Properties::defaultProperties() const + { return mpDefaultProperties; } + + inline void Properties::setDefaultProperties(Properties *pDefaultProperties) + { mpDefaultProperties = pDefaultProperties; } + + inline void Properties::setProperty(const QString &rKey, + const QString &rValue) + { insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::Properties, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PROPERTIES_H diff --git a/GC-3.6.1-T3/src/log4qt/hierarchy.cpp b/GC-3.6.1-T3/src/log4qt/hierarchy.cpp new file mode 100644 index 0000000..ef93d55 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/hierarchy.cpp @@ -0,0 +1,213 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/hierarchy.h" + +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LoggerRepository) + + + + /************************************************************************** + * Class implementation: Hierarchy + **************************************************************************/ + + + Hierarchy::Hierarchy() : +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mLoggers(), + mThreshold(Level::NULL_INT), + mpRootLogger(logger(QString())) + { + Q_UNUSED(mHandleQtMessages); + // Store root logger to allow rootLogger() to be const + } + + + Hierarchy::~Hierarchy() + { + static_logger()->warn("Unexpected destruction of Hierarchy"); + + // QWriteLocker locker(&mObjectGuard); + // + // resetConfiguration(); + // clear(); + // delete mpRootLogger; + } + + + bool Hierarchy::exists(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.contains(rName); + } + + + Logger *Hierarchy::logger(const QString &rName) + { + QWriteLocker locker(&mObjectGuard); + + return createLogger(rName); + } + + + QList Hierarchy::loggers() const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.values(); + } + + + void Hierarchy::setThreshold(const QString &rThreshold) + { + setThreshold(Level::fromString(rThreshold)); + } + + + void Hierarchy::resetConfiguration() + { + QWriteLocker locker(&mObjectGuard); + + // Reset all loggers. + // Leave log, qt and root logger to the last to allow debugging of shutdown. + + Logger *p_logging_logger = logger(QLatin1String("Log4Qt")); + Logger *p_qt_logger = logger(QLatin1String("Qt")); + Logger *p_root_logger = rootLogger(); + + Logger *p_logger; + Q_FOREACH(p_logger, mLoggers) + { + if ((p_logger == p_logging_logger) || (p_logger == p_qt_logger) || (p_logger == p_root_logger)) + continue; + resetLogger(p_logger, Level::NULL_INT); + } + resetLogger(p_qt_logger, Level::NULL_INT); + resetLogger(p_logging_logger, Level::NULL_INT); + resetLogger(p_root_logger, Level::DEBUG_INT); + } + + + void Hierarchy::shutdown() + { + static_logger()->debug("Shutting down Hierarchy"); + resetConfiguration(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Hierarchy::debug(QDebug &rDebug) const + { + rDebug.nospace() << "Hierarchy(" + << "loggers:" << loggers().count() << " " + << "threshold:" << threshold().toString() << " " + << "root-level:" << rootLogger()->level().toString() << " " + << "root-appenders:" << rootLogger()->appenders().count() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + Logger *Hierarchy::createLogger(const QString &rName) + { + // Q_ASSERT_X(, "Hierarchy::createLogger", "Lock must be held by caller") + + const QString name_separator = QLatin1String("::"); + + Logger *p_logger = mLoggers.value(rName, 0); + if (p_logger != 0) + return p_logger; + + if (rName.isEmpty()) + { + p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), 0); + mLoggers.insert(QString(), p_logger); + return p_logger; + } + QString parent_name; + int index = rName.lastIndexOf(name_separator); + if (index >=0) + parent_name = rName.left(index); + p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name)); + mLoggers.insert(rName, p_logger); + return p_logger; + } + + + void Hierarchy::resetLogger(Logger *pLogger, Level level) const + { + // Q_ASSERT_X(, "Hierarchy::resetLogger", "Lock must be held by caller") + + pLogger->removeAllAppenders(); + pLogger->setAdditivity(true); + pLogger->setLevel(level); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/hierarchy.h b/GC-3.6.1-T3/src/log4qt/hierarchy.h new file mode 100644 index 0000000..18a90eb --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/hierarchy.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HIERARCHY_H +#define LOG4QT_HIERARCHY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/loggerrepository.h" + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Hierarchy implements a logger repository. + * + * \note All the functions declared in this class are thread-safe. + */ + class Hierarchy : public LoggerRepository + { + public: + Hierarchy(); + // Hierarchy(const Hierarchy &rOther); // Use compiler default + virtual ~Hierarchy(); + // Hierarchy &operator=(const Hierarchy &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const; + virtual Logger *logger(const QString &rName); + virtual QList loggers() const; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual Logger *rootLogger() const; + virtual Level threshold() const; + virtual void setThreshold(Level level); + virtual void setThreshold(const QString &rThreshold); + + // JAVA: void clear(); + virtual bool isDisabled(Level level); + virtual void resetConfiguration(); + virtual void shutdown(); + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + // JAVA: void addRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + // JAVA: QHash getRendererMap() const; + // JAVA: setRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Hierarchy(loggers:6 threshold:"ALL" root-level:"DEBUG" root-appenders:0) + * + * \sa QDebug, operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rdebug) const; +#endif + + private: + Logger *createLogger(const QString &rName); + void resetLogger(Logger *pLogger, Level level) const; + + private: + mutable QReadWriteLock mObjectGuard; + QHash mLoggers; + volatile bool mHandleQtMessages; + Level mThreshold; + Logger *mpRootLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Logger *Hierarchy::rootLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpRootLogger; } + + inline Level Hierarchy::threshold() const + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void Hierarchy::setThreshold(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool Hierarchy::isDisabled(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return level < mThreshold; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Hierarchy, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_HIERARCHY_H diff --git a/GC-3.6.1-T3/src/log4qt/layout.cpp b/GC-3.6.1-T3/src/log4qt/layout.cpp new file mode 100644 index 0000000..160f80d --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/layout.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/layout.h" + +#include +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" + + + +namespace Log4Qt +{ + + + /*************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Layout + **************************************************************************/ + + + QString Layout::contentType() const + { + return QString::fromLatin1("text/plain"); + } + + + void Layout::activateOptions() + { + } + + + QString Layout::endOfLine() + { + // There seams to be no function in Qt for this + +#ifdef Q_OS_WIN32 + return QLatin1String("\r\n"); +#endif // Q_OS_WIN32 +//#ifdef Q_OS_MAC +// return QLatin1String("\r"); +//#endif // Q_OS_MAC + return QLatin1String("\n"); + } + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/layout.h b/GC-3.6.1-T3/src/log4qt/layout.h new file mode 100644 index 0000000..42f3b3e --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/layout.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LAYOUT_H +#define LOG4QT_LAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Layout is the base class for all layouts. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class Layout : public LogObject + { + Q_OBJECT + + /*! + * The property holds the content type of the layout. + * + * \sa contentType() + */ + Q_PROPERTY(QString footercontentType READ contentType) + /*! + * The property holds the footer used by the layout. + * + * \sa footer(), setFooter() + */ + Q_PROPERTY(QString footer READ footer WRITE setFooter) + /*! + * The property holds the header used by the layout. + * + * \sa header(), setHeader() + */ + Q_PROPERTY(QString header READ header WRITE setHeader) + + public: + Layout(QObject *pParent = 0); + virtual ~Layout(); + private: + Layout(const Layout &rOther); // Not implemented + Layout &operator=(const Layout &rOther); // Not implemented + + public: + virtual QString contentType() const; + QString footer() const; + QString header() const; + // JAVA: virtual bool ignoresThrowable() const; + QString name() const; + void setFooter(const QString &rFooter); + void setHeader(const QString &rHeader); + void setName(const QString &rName); + // JAVA: void setIgnoresThrowable(bool) const; + + virtual void activateOptions(); + virtual QString format(const LoggingEvent &rEvent) = 0; + + /*! + * Returns the end of line seperator for the operating system. + * + * Windows: \\r\\n + * Mac: \\r + * UNIX: \\n + */ + static QString endOfLine(); + + // Member variables + private: + QString mFooter; + QString mHeader; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Layout::Layout(QObject *pParent) : + LogObject(pParent) + {} + + inline Layout::~Layout() + {} + + inline QString Layout::footer() const + { return mFooter; } + + inline QString Layout::header() const + { return mHeader; } + + inline QString Layout::name() const + { return objectName(); } + + inline void Layout::setFooter(const QString &rFooter) + { mFooter = rFooter; } + + inline void Layout::setHeader(const QString &rHeader) + { mHeader = rHeader; } + + inline void Layout::setName(const QString &rName) + { setObjectName(rName); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Layout, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LAYOUT_H diff --git a/GC-3.6.1-T3/src/log4qt/level.cpp b/GC-3.6.1-T3/src/log4qt/level.cpp new file mode 100644 index 0000000..a55038f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/level.cpp @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/level.h" + +#include +#include +#include +#include "log4qt/logger.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Level) + + + + /************************************************************************** + * Class implementation: Level + **************************************************************************/ + + + int Level::syslogEquivalent() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + switch (mValue) + { + case NULL_INT: + case ALL_INT: + case TRACE_INT: + case DEBUG_INT: + return 7; + case INFO_INT: + return 6; + case WARN_INT: + return 4; + case ERROR_INT: + return 3; + case FATAL_INT: + case OFF_INT: + return 0; + default: + Q_ASSERT_X(false, "Level::syslogEquivalent()", "Unknown level value"); + return 7; + } + } + + + QString Level::toString() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + const char *p_context = "Level"; + + switch (mValue) + { + case NULL_INT: + return QCoreApplication::translate(p_context, "NULL"); + case ALL_INT: + return QCoreApplication::translate(p_context, "ALL"); + case TRACE_INT: + return QCoreApplication::translate(p_context, "TRACE"); + case DEBUG_INT: + return QCoreApplication::translate(p_context, "DEBUG"); + case INFO_INT: + return QCoreApplication::translate(p_context, "INFO"); + case WARN_INT: + return QCoreApplication::translate(p_context, "WARN"); + case ERROR_INT: + return QCoreApplication::translate(p_context, "ERROR"); + case FATAL_INT: + return QCoreApplication::translate(p_context, "FATAL"); + case OFF_INT: + return QCoreApplication::translate(p_context, "OFF"); + default: + Q_ASSERT_X(false, "Level::toString()", "Unknown level value"); + return QCoreApplication::translate(p_context, "NULL"); + } + } + + + Level Level::fromString(const QString &rLevel, bool *pOk) + { + const char *p_context = "Level"; + if (pOk) + *pOk = true; + + if (rLevel == QLatin1String("OFF") || + rLevel == QCoreApplication::translate(p_context, "OFF")) + return OFF_INT; + if (rLevel == QLatin1String("FATAL") || + rLevel == QCoreApplication::translate(p_context, "FATAL")) + return FATAL_INT; + if (rLevel == QLatin1String("ERROR") || + rLevel == QCoreApplication::translate(p_context, "ERROR")) + return ERROR_INT; + if (rLevel == QLatin1String("WARN") || + rLevel == QCoreApplication::translate(p_context, "WARN")) + return WARN_INT; + if (rLevel == QLatin1String("INFO") || + rLevel == QCoreApplication::translate(p_context, "INFO")) + return INFO_INT; + if (rLevel == QLatin1String("DEBUG") || + rLevel == QCoreApplication::translate(p_context, "DEBUG")) + return DEBUG_INT; + if (rLevel == QLatin1String("TRACE") || + rLevel == QCoreApplication::translate(p_context, "TRACE")) + return TRACE_INT; + if (rLevel == QLatin1String("ALL") || + rLevel == QCoreApplication::translate(p_context, "ALL")) + return ALL_INT; + if (rLevel == QLatin1String("NULL") || + rLevel == QCoreApplication::translate(p_context, "NULL")) + return NULL_INT; + + logger()->warn("Use of invalid level string '%1'. Using 'Level::NULL_INT' instead.", rLevel); + if (pOk) + *pOk = false; + return NULL_INT; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel) + { + quint8 l = rLevel.mValue; + rStream << l; + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel) + { + quint8 l; + rStream >> l; + rLevel.mValue = (Level::Value)l; + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Level &rLevel) + { + debug.nospace() << "Level(" + << rLevel.toString() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/level.h b/GC-3.6.1-T3/src/log4qt/level.h new file mode 100644 index 0000000..93914c2 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/level.h @@ -0,0 +1,193 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVEL_H +#define LOG4QT_LEVEL_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Level defines the level of a logging event. + * + * \note All the functions declared in this class are thread-safe. + */ + class Level + { + public: + // Comparisson operators rely on the order: + // NULL_INT < ALL_INT < TRACE_INT < ... + // Serialisation uses unsigned 8 bit int + + /*! + * The enumeration Value contains all possible Level values. + */ + enum Value + { + /*! NULL_INT is used for no level has been specified */ + NULL_INT = 0, + ALL_INT = 32, + TRACE_INT = 64, + DEBUG_INT = 96, + INFO_INT = 128, + WARN_INT = 150, + ERROR_INT = 182, + FATAL_INT = 214, + OFF_INT = 255 + }; + + public: + Level(Value value = NULL_INT); + // Level(const Level &rOther); // Use compiler default + // virtual ~Level(); // Use compiler default + // Level &operator=(const Level &rOther); // Use compiler default + + int syslogEquivalent() const; + int toInt() const; + + bool operator==(const Level &rOther) const; + bool operator!=(const Level &rOther) const; + bool operator<(const Level &rOther) const; + bool operator<=(const Level &rOther) const; + bool operator>(const Level &rOther) const; + bool operator>=(const Level &rOther) const; + QString toString() const; + + static Level fromString(const QString &rName, bool *pOk = 0); + + private: + // QMutex mObjectGuard; + volatile Value mValue; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + friend QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates Level + * + * Writes the given error \a rLevel to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + + /*! + * \relates Level + * + * Reads an error from the given stream \a rStream into the given + * error \a rLevel, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Level + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Level("ERROR") + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Level &rLevel); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + + inline Level::Level(Value value) : + mValue(value) + {} + + inline int Level::toInt() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue; } + + inline bool Level::operator==(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue == rOther.mValue; } + + inline bool Level::operator!=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue != rOther.mValue; } + + inline bool Level::operator<(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue < rOther.mValue; } + + inline bool Level::operator<=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue <= rOther.mValue; } + + inline bool Level::operator>(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue > rOther.mValue; } + + inline bool Level::operator>=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue >= rOther.mValue; } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::Level) +Q_DECLARE_TYPEINFO(Log4Qt::Level, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LEVEL_H diff --git a/GC-3.6.1-T3/src/log4qt/log4qt.cpp b/GC-3.6.1-T3/src/log4qt/log4qt.cpp new file mode 100644 index 0000000..9378f46 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/log4qt.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + *Dependencies + ******************************************************************************/ + + +#include "log4qt/log4qt.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + *Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/log4qt.h b/GC-3.6.1-T3/src/log4qt/log4qt.h new file mode 100644 index 0000000..73c3cfe --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/log4qt.h @@ -0,0 +1,614 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Added a compile time version check for the Qt version + * Jan 2009, Martin Heinrich: + * - Updated documentation and version information for version 0.2 + * Feb 2009, Martin Heinrich: + * - Updated version information for version 0.3 + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_H +#define LOG4QT_H + + +/*! + * \mainpage + * + * %Log4Qt is a C++ port of the Apache Software Foundation Log4j package + * using the Trolltech Qt Framework. + * + * The documentation describes classes and methods that have been added or + * changed compared to Log4j. + * + * The following sections are describing the implementation in more detail: + * - \ref Changes "Differences to Log4j" + * - \ref Ownership "Object ownership" + * - \ref LogLog "Logging within the package" + * - \ref Init "Initialization procedure" + * - \ref Env "Environment Variables" + * - \ref Undocumented "Undocumented functions" + * - \ref Assumptions "Assumptions" + * + * \author Martin Heinrich + * \version 0.3 (January 2009) + * + */ + +/*! + * \page Changes Differences to Log4j + * + * The following fundamental differences exist between %Log4Qt and Log4j: + * + * - As a JAVA package Log4j does not have to manage object ownership and + * lifetime in the same way then it is required in C++. For details on + * how object ownership is handled see \ref Ownership "Object ownership". + * - The package uses itself for its internal logging similar to Log4j 1.3. + * For details see \ref LogLog "Logging within the package". + * - The configuration using system properties was replaced with a combination + * of environment variables and application settings. For details see + * \ref Env "Environment Variables". + * - Custom levels are not supported. + * - Multiple Logger Repositories are not supported + * + * The following classes have been changed: + * + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - The procedure of checking, if logging is possible, originally used by + * \ref Log4Qt::WriterAppender "WriterAppender" was generalised and is used + * in \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" and derived classes + * (\ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()"). + * - The \ref Log4Qt::AppenderSkeleton::doAppend() "doAppend()" member function will + * check the entry conditions by calling the sub-class specific + * \ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()". + * If successful the sub-class specific + * \ref Log4Qt::AppenderSkeleton::append() "append()" function is called. + * + * - Configurator + * - Configure functions return a boolean indicating, if the configuration + * was successful. + * - Configure errors are accessible over + * \ref Log4Qt::ConfiguratorHelper::configureError() + * "ConfiguratorHelper::configureError()". + * - Watching for configuration file changes is a function performed + * centrally by the \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper". + * The class provides signals to notify on configuration change and errors. + * - The class \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" was + * extended to be able to read configuration data from a QSettings object. + * + * - \ref Log4Qt::Level "Level" + * - A new value \ref Log4Qt::Level::NULL_INT "Level::NULL_INT" was + * introduced to indicate there is no level set. + * + * - \ref Log4Qt::Logger "Logger" + * - The method \ref Log4Qt::Logger::isEnabledFor() "isEnabledFor()" + * does also take the repository threshold into account. + * - Several overloaded convenience member function are available to log + * messages with arguments of different types. + * - Two macros, \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * and \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER", + * allows retrieving and caching of a pointer to a logger object. + * + * - \ref Log4Qt::LogManager "LogManager" + * - A QtMessage handler can be installed via + * \ref Log4Qt::LogManager::setHandleQtMessages() "setHandleQtMessages()", + * to redirect all messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() to a logger. The logger is named Qt and can be + * accessed using \ref Log4Qt::LogManager::qtLogger() "qtLogger()". + * - The initialisation procedure is available over a public method + * (\ref Log4Qt::LogManager::startup() "startup()"). + * - The LogManager provides access to the logger used internally by the + * package (\ref Log4Qt::LogManager::logLogger() "logLogger()") and to + * its default initialisation procedure + * (\ref Log4Qt::LogManager::configureLogLogger() "configureLogLogger()"). + * + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - The class will call \ref Log4Qt::WriterAppender::handleIoErrors() + * "handleIoErrors()" after all I/O operations. Sub-classes should + * re-implement the function to handle errors. + * + * The following classes have been added: + * + * - An additional appender class, \ref Log4Qt::DebugAppender "DebugAppender", + * was added. The class appends logging events to the platform specific debug + * output. + * - Various helper class have been introduced: + * - \ref Log4Qt::ClassLogger "ClassLogger": The class ClassLogger provides + * logging for a QObject derived class. + * - \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper": The class + * ConfiguratorHelper provides a configuration file watch and last error + * for configurator classes. + * - \ref Log4Qt::DateTime "DateTime": The class DateTime provides extended + * functionality for QDateTime. + * - \ref Log4Qt::LogError "LogError": The class LogError represents an error. + * - \ref Log4Qt::Factory "Factory": The class Factory provides factories + * for Appender, Filter and Layout objects. + * - \ref Log4Qt::InitialisationHelper "InitialisationHelper": The class + * InitialisationHelper performs static initialisation tasks. + * - \ref Log4Qt::LogObject "LogObject": The class LogObject is the common + * base class for many classes in the package. + * - \ref Log4Qt::LogObjectPtr "LogObjectPtr": The class LogObjectPtr + * implements automatic reference counting for LogObject objects. + * - \ref Log4Qt::PatternFormatter "PatternFormatter": The class + * PatternFormatter formats a logging event based on a pattern string. + * - \ref Log4Qt::Properties "Properties": The class Properties implements a + * JAVA property hash. + */ + +/*! + * \page Ownership Object ownership + * + * In difference to the JAVA Log4j package %Log4Qt must manage ownership and + * lifetime of the objects used. This is non trivial as objects are created + * and used in different ways. + * + * In general an object can be created explicitly for example an application + * may create Loggers, Appenders and Layouts during creation of a QApplication + * object. But they can also be automatically created by the package on + * startup using a \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" + * configuration file. Objects may also be created the one way and then used + * the other. Object may be used by multiple other objects. A Layout for example + * may be used by multiple Appenders. Objects are also created from multiple + * threads. The creation may happen during static initialisation and the + * deletion during static de-initialization. + * + * The parent child model used by QObject cannot be used to handle this. It + * cannot automatically delete an object that is used by multiple others as + * for example an Appender used by multiple Loggers. In addition to this + * QObjects and their children must reside in the same thread. This would + * either mean to impose restriction on how objects can be created or to move + * objects to a specific thread. + * + * To allow an automatic deletion of not required objects the package + * implements reference counting for Appenders, Layouts and Filters. The + * reference counting is implemented in \ref Log4Qt::LogObject "LogObject", + * which is used as a common base class. The reference count can be explicitly + * changed using the methods \ref Log4Qt::LogObject::retain() "retain()" and + * \ref Log4Qt::LogObject::release() "release()". Alternatively an auto pointer + * is available \ref Log4Qt::LogObjectPtr "LogObjectPtr", which is used + * throughout the package. + * + * The reference counting mechanism will test, if an object has a QObject + * parent object set. If a parent is set, the object will not be deleted, if + * the reference count reaches 0. This allows to mix the reference counted + * paradigm with the QObject parent child one. + * + * The following example configures a logger and uses reference counting to + * manage the ownership of objects. + * + * \code + * // Create layout + * TTCCLayout *p_layout = new TTCCLayout(); + * + * // Create appender + * ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // p_appender and p_layout are deleted here + * \endcode + * + * The following example configures a logger and uses QObject ownership of + * objects. + * + * \code + * QObject *p_parent = new MyObject; + * + * // Create objects + * ConsoleAppender *p_appender = new ConsoleAppender(p_parent); + * TTCCLayout *p_layout = new TTCCLayout(p_appender); + * + * // Configure appender + * p_appender->setTarget(ConsoleAppender::STDOUT_TARGET); + * p_appender->setLayout(p_layout); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); + * + * delete p_parent; // p_appender and p_layout are deleted here + * \endcode + * + * The following example shows how to use objects created on the stack. + * + * \code + * { + * // Create layout + * TTCCLayout layout; + * layout.retain(); + * + * // Create appender + * ConsoleAppender appender(&layout, ConsoleAppender::STDOUT_TARGET); + * appender.retain(); + * appender.activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(&appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // Without retain() program crashes here + * + * } // p_appender and p_layout are deleted here + * \endcode + */ + +/*! + * \page LogLog Logging within the package + * + * The package uses itself for logging similar to Log4j 1.3. This brings much + * more flexibility over logging to stdout, stderr like in Log4j 1.2 using + * logLog. It also enables the program to capture and handle errors raised by + * the package. + * + * Using this approach introduces the issue of recursion. The following example + * explains a situation where this happens. Let's say all logger are configured + * to be additive and only the root logger has an appender set. The appender + * is a \ref Log4Qt::FileAppender "FileAppender". During the logging of an + * event an I/O error occurs. The \ref Log4Qt::FileAppender "FileAppender" logs + * an event by itself using the logger %Log4Qt::FileAppender. The event is + * passed to the root logger, which calls then the \ref Log4Qt::FileAppender + * "FileAppender". This causes another I/O error, which is logged by + * the \ref Log4Qt::FileAppender "FileAppender". + * + * To avoid an endless loop the appender will drop the event on a recursive + * invocation. This check is done by \ref Log4Qt::AppenderSkeleton + * "AppenderSkeleton" in \ref Log4Qt::AppenderSkeleton::doAppend() + * "doAppend()". + * + * The problem only occurs, if a logger, appender, layout or filter log an + * event while an event is appended. Neither the logger class nor any of the + * layout or filter classes log events during appending of an event. Most of + * the appender classes may log errors during appending. Only the + * \ref Log4Qt::ListAppender "ListAppender" and + * \ref Log4Qt::ListAppender "ConsoleAppender" are not logging events. + * + * The default configuration uses two \ref Log4Qt::ListAppender + * "ConsoleAppender", one for stderr and one for stdout. No event will be + * dropped, because no recursive invocations can occur. + */ + +/*! + * \page Init Initialization procedure + * + * The package is initialised in two stages. The first stage takes place during + * static initialization. The second stage takes place when the + * \ref Log4Qt::LogManager "LogManager" singleton is created. + * + * During static initialisation the \ref Log4Qt::InitialisationHelper + * "InitialisationHelper" singleton is created . On construction it captures + * the program startup time, reads the required values from the system + * environment and registers the package types with the Qt type system. + * + * The \ref Log4Qt::LogManager "LogManager" singleton is created on first use. + * The creation is usually triggered by the request for a \ref Log4Qt::Logger + * "Logger" object. The call to \ref Log4Qt::Logger::logger() + * "Logger::logger()" is passed through to \ref Log4Qt::LogManager::logger() + * "LogManager::logger()". On creation the \ref Log4Qt::LogManager "LogManager" + * creates a \ref Log4Qt::Hierarchy "Hierarchy" object as logger repository. + * + * After the singleton is created the logging of the package is configured to + * its default by a call to \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()". The logger + * \ref Log4Qt::LogManager::logLogger() "logLogger()" is configured to be not + * additive. Messages with the level \ref Log4Qt::Level::ERROR_INT + * "Level::ERROR_INT" and \ref Log4Qt::Level::FATAL_INT "Level::FATAL_INT" are + * written to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is read from + * the system environment or application settings using + * \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" with the key \c Debug. If a level value + * is found, but it is not a valid Level string, + * \ref Log4Qt::Level::DEBUG_INT "Level::DEBUG_INT" is used. If no level string + * is found \ref Log4Qt::Level::ERROR_INT "Level::ERROR_INT" is used. + * + * Once the logging is configured the package is initialised by a call to + * \ref Log4Qt::LogManager::startup() "LogManager::startup()". The function + * will test for the setting \c DefaultInitOverride in the system environment + * and application settings using \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()". If the value is present and set to + * anything else then \c false, the initialisation is aborted.
+ * The system environment and application settings are tested for the setting + * \c Configuration. If it is found and it is a valid path to a file, the + * package is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting \c Configuration is + * not available and a QCoreApplication object is present, the application + * settings are tested for a group \c Log4Qt/Properties. If the group exists, + * the package is configured with the setting using the + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration file nor + * configuration settings could be found, the current working directory is + * searched for the file \c "log4qt.properties". If it is found, the package + * is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * The following example shows how to use application settings to initialise the + * package. + * + * \code + * # file: myapplication.h + * + * #include qapplication.h + * + * class MyApplication : public QApplication + * { + * Q_OBJECT + * + * public: + * MyApplication(); + * ~MyApplication(); + * void setupLog4Qt(); + * } + * \endcode + * \code + * # file: myapplication.cpp + * + * #include myapplication.h + * + * MyApplication::MyApplication( + * { + * // Set Application data to allow Log4Qt initialisation to read the + * // correct values + * setApplicationName("MyApplication"); + * setOrganisationName("MyOrganisation"); + * setOrganizationDomain("www.myorganisation.com"); + * + * // Log first message, which initialises Log4Qt + * Log4Qt::Logger::logger("MyApplication")->info("Hello World"); + * } + * + * MyApplication::~MyApplication() + * { + * } + * + * void MyApplication::setupLog4Qt() + * { + * QSettings s; + * + * // Set logging level for Log4Qt to TRACE + * s.beginGroup("Log4Qt"); + * s.setValue("Debug", "TRACE"); + * + * // Configure logging to log to the file C:/myapp.log using the level TRACE + * s.beginGroup("Properties"); + * s.setValue("log4j.appender.A1", "org.apache.log4j.FileAppender"); + * s.setValue("log4j.appender.A1.file", "C:/myapp.log"); + * s.setValue("log4j.appender.A1.layout", "org.apache.log4j.TTCCLayout"); + * s.setValue("log4j.appender.A1.layout.DateFormat", "ISO8601"); + * s.setValue("log4j.rootLogger", "TRACE, A1"); + * + * // Settings will become active on next application startup + * } + * \endcode + */ + +/*! + * \page Env Environment Variables + * + * The package uses environment variables to control the initialization + * procedure. The environment variables replace the system property entries + * used by Log4j. + * + * For compability reasons the Log4j entry is recognised. Alternatively a + * environment variable style Log4Qt form can be used. The following entries + * are used: + * + * - LOG4QT_DEBUG
+ * The variable controls the \ref Log4Qt::Level "Level" value for the + * logger \ref Log4Qt::LogManager::logLogger() "LogManager::logLogger()". + * If the value is a valid \ref Log4Qt::Level "Level" string, the level for + * the is set to the level. If the value is not a valid + * \ref Log4Qt::Level "Level" string, \ref Log4Qt::Level::DEBUG_INT + * "DEBUG_INT" is used. Otherwise \ref Log4Qt::Level::ERROR_INT "ERROR_INT" + * is used. + * - \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()" + * + * - LOG4QT_DEFAULTINITOVERRIDE
+ * The variable controls the \ref Init "initialization procedure" performed + * by the \ref Log4Qt::LogManager "LogManager" on startup. If it is set to + * any other value then \c false the \ref Init "initialization procedure" + * is skipped. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATION
+ * The variable specifies the configuration file used for initialising the + * package. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATORCLASS
+ * The variable specifies the configurator class used for initialising the + * package. + * + * Environment variables are read during static initialisation on creation of + * the \ref Log4Qt::InitialisationHelper "InitialisationHelper". They can be + * accessed by calling \ref Log4Qt::InitialisationHelper::environmentSettings() + * "InitialisationHelper::environmentSettings()". + * + * All settings can also be made in the application settings under the group + * \c %Log4Qt. For example the environment variable \c LOG4QT_DEBUG is + * equivalent to the setting \c Log4Qt/Debug. If an environment variable is + * set it takes precedence over the application setting. Settings are only + * used, if an QApplication object is available, when the + * \ref Log4Qt::LogManager "LogManager" is + * initialised (see \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" for details). + */ + +/*! + * \page Undocumented Undocumented functions + * + * In general it was tried to avoid the usage of undocumented features of Qt. + * Nice to have features like for example Q_DECLARE_PRIVATE are not used. Only + * features that would have been resulted in re-coding the same functionality + * are used. + * + * - QT_WA: The macro is used to call Windows A/W functions + * - \ref Log4Qt::DebugAppender "DebugAppender" + * - QBasicAtomicPointer: The class is used instead of QAtomicPointer, because + * it allows the initialisation as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * - Q_BASIC_ATOMIC_INITIALIZER: The macro is used to initialise QAtomicPointer + * objects as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + */ + +/*! + * \page Assumptions Assumptions + * + * The following assumptions are used throughout the package: + * + * - Reading / writing of bool or int is thread-safe, if declared volatile + * - \ref Log4Qt::ListAppender "ListAppender" + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - \ref Log4Qt::ConsoleAppender "ConsoleAppender" + * - \ref Log4Qt::FileAppender "FileAppender" + * - \ref Log4Qt::Hierarchy "Hierarchy" + * - \ref Log4Qt::Level "Level" + * - \ref Log4Qt::Logger "Logger" + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - \ref Log4Qt::Layout::format() "Layout::format()" is implemented reentrant + * in all sub-classes. + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - Being able to use singleton objects during static de-initialization without + * order issues is more valuable then their destruction. + * - \ref Log4Qt::LogManager "LogManager" + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + */ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#if QT_VERSION < QT_VERSION_CHECK(4, 3, 0) +# error "Log4Qt requires Qt version 4.3.0 or higher" +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +/*! + * \brief The namespace %Log4Qt encloses all parts of the package. + */ +namespace Log4Qt +{ + /*! + * This macro expands a numeric value of the form 0xMMmmPP (MM = major, + * mm = minor, PP = patch) that specifies Log4Qt's version number. + * This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION 0x000200 + + /*! + * The macro expands to a string that specifies the Log4Qt's version + * number. This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION_STR "0.3.0" + + enum ErrorCode + { + OK = 0, + // AppenderSkeleton, FileAppender, WriterAppender + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR, + APPENDER_ACTIVATE_MISSING_WRITER_ERROR, + APPENDER_ACTIVATE_MISSING_FILE_ERROR, + APPENDER_CLOSED_ERROR, + APPENDER_INVALID_PATTERN_ERROR, + APPENDER_NO_OPEN_FILE_ERROR, + APPENDER_NOT_ACTIVATED_ERROR, + APPENDER_OPENING_FILE_ERROR, + APPENDER_RENAMING_FILE_ERROR, + APPENDER_REMOVE_FILE_ERROR, + APPENDER_USE_INVALID_PATTERN_ERROR, + APPENDER_USE_MISSING_LAYOUT_ERROR, + APPENDER_USE_MISSING_WRITER_ERROR, + APPENDER_WRITING_FILE_ERROR, + // Level + LEVEL_INVALID_LEVEL_STRING, + // Layouts, PatternFormatter + LAYOUT_EXPECTED_DIGIT_ERROR, + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + // Logger + LOGGER_INVALID_LEVEL_FOR_ROOT, + // PropertyConfigurator, OptionHandler + CONFIGURATOR_OPENING_FILE_ERROR, + CONFIGURATOR_READING_FILE_ERROR, + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + CONFIGURATOR_INVALID_OPTION_ERROR, + CONFIGURATOR_MISSING_APPENDER_ERROR, + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + CONFIGURATOR_MISSING_LAYOUT_ERROR, + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + CONFIGURATOR_PROPERTY_ERROR, + CONFIGURATOR_UNKNOWN_TYPE_ERROR + }; + + + /****************************************************************************** + * Operators, Helpers + ******************************************************************************/ + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + +} // namespace Log4Qt + + +#endif // LOG4QT_H diff --git a/GC-3.6.1-T3/src/log4qt/log4qt.pri b/GC-3.6.1-T3/src/log4qt/log4qt.pri new file mode 100644 index 0000000..f9730b9 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/log4qt.pri @@ -0,0 +1,111 @@ +# ******************************************************************************* +# +# package: Log4Qt +# file: log4qt.pri +# created: September 2007 +# author: Martin Heinrich +# +# +# Copyright 2007 Martin Heinrich +# +# 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. +# +# ******************************************************************************* + +INCLUDEPATH += $$PWD/.. +DEPENDPATH += $$PWD/.. +HEADERS += \ + $$PWD/appender.h \ + $$PWD/appenderskeleton.h \ + $$PWD/basicconfigurator.h \ + $$PWD/consoleappender.h \ + $$PWD/dailyrollingfileappender.h \ + $$PWD/fileappender.h \ + $$PWD/helpers/classlogger.h \ + $$PWD/helpers/configuratorhelper.h \ + $$PWD/helpers/datetime.h \ + $$PWD/helpers/factory.h \ + $$PWD/helpers/initialisationhelper.h \ + $$PWD/helpers/logerror.h \ + $$PWD/helpers/logobject.h \ + $$PWD/helpers/logobjectptr.h \ + $$PWD/helpers/optionconverter.h \ + $$PWD/helpers/patternformatter.h \ + $$PWD/helpers/properties.h \ + $$PWD/hierarchy.h \ + $$PWD/layout.h \ + $$PWD/level.h \ + $$PWD/log4qt.h \ + $$PWD/logger.h \ + $$PWD/loggerrepository.h \ + $$PWD/loggingevent.h \ + $$PWD/logmanager.h \ + $$PWD/mdc.h \ + $$PWD/ndc.h \ + $$PWD/patternlayout.h \ + $$PWD/propertyconfigurator.h \ + $$PWD/rollingfileappender.h \ + $$PWD/simplelayout.h \ + $$PWD/spi/filter.h \ + $$PWD/ttcclayout.h \ + $$PWD/writerappender.h \ + $$PWD/varia/debugappender.h \ + $$PWD/varia/denyallfilter.h \ + $$PWD/varia/nullappender.h \ + $$PWD/varia/levelmatchfilter.h \ + $$PWD/varia/levelrangefilter.h \ + $$PWD/varia/listappender.h \ + $$PWD/varia/stringmatchfilter.h + +SOURCES += \ + $$PWD/appenderskeleton.cpp \ + $$PWD/basicconfigurator.cpp \ + $$PWD/consoleappender.cpp \ + $$PWD/dailyrollingfileappender.cpp \ + $$PWD/fileappender.cpp \ + $$PWD/helpers/classlogger.cpp \ + $$PWD/helpers/configuratorhelper.cpp \ + $$PWD/helpers/datetime.cpp \ + $$PWD/helpers/factory.cpp \ + $$PWD/helpers/initialisationhelper.cpp \ + $$PWD/helpers/logerror.cpp \ + $$PWD/helpers/logobject.cpp \ + $$PWD/helpers/logobjectptr.cpp \ + $$PWD/helpers/optionconverter.cpp \ + $$PWD/helpers/patternformatter.cpp \ + $$PWD/helpers/properties.cpp \ + $$PWD/hierarchy.cpp \ + $$PWD/layout.cpp \ + $$PWD/level.cpp \ + $$PWD/log4qt.cpp \ + $$PWD/logger.cpp \ + $$PWD/loggerrepository.cpp \ + $$PWD/loggingevent.cpp \ + $$PWD/logmanager.cpp \ + $$PWD/mdc.cpp \ + $$PWD/ndc.cpp \ + $$PWD/patternlayout.cpp \ + $$PWD/propertyconfigurator.cpp \ + $$PWD/rollingfileappender.cpp \ + $$PWD/simplelayout.cpp \ + $$PWD/spi/filter.cpp \ + $$PWD/ttcclayout.cpp \ + $$PWD/writerappender.cpp \ + $$PWD/varia/debugappender.cpp \ + $$PWD/varia/denyallfilter.cpp \ + $$PWD/varia/nullappender.cpp \ + $$PWD/varia/levelmatchfilter.cpp \ + $$PWD/varia/levelrangefilter.cpp \ + $$PWD/varia/listappender.cpp \ + $$PWD/varia/stringmatchfilter.cpp + \ No newline at end of file diff --git a/GC-3.6.1-T3/src/log4qt/logger.cpp b/GC-3.6.1-T3/src/log4qt/logger.cpp new file mode 100644 index 0000000..d5dc936 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/logger.cpp @@ -0,0 +1,349 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logger.h" + +#include +#include "log4qt/appenderskeleton.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/loggingevent.h" +#include "log4qt/log4qt.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Logger + **************************************************************************/ + + + Logger::Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent) : + QObject(0), +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mName(rName), + mpLoggerRepository(pLoggerRepository), + mAdditivity(true), + mAppenders(), + mLevel(level), + mpParent(pParent) + { + Q_ASSERT_X(pLoggerRepository, "Logger::Logger()", "Construction of Logger with null LoggerRepository"); + + setObjectName(mName); + } + + + Logger::~Logger() + { + logger()->warn("Unexpected destruction of Logger"); + + // QWriteLocker locker(&mObjectGuard); + // + // QMutableListIterator< LogObjectPtr > i(mAppenders); + // while (i.hasNext()) + // { + // i.next(); + // i.remove(); + // } + } + + + QList Logger::appenders() const + { + QReadLocker locker(&mObjectGuard); + + QList result; + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + result << p_appender; + return result; + } + + + void Logger::setLevel(Level level) + { + // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe + + if ((parentLogger() == 0) && (level == Level::NULL_INT)) + { + logger()->warn("Invalid root logger level NULL_INT. Using DEBUG_INT instead"); + level = Level::DEBUG_INT; + } + mLevel = level; + } + + + void Logger::addAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Handle warnings, before write lock is aquired + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + { + QReadLocker locker(&mObjectGuard); + + if(!p_appender) + { + logger()->warn("Adding null Appender to Logger '%1'", name()); + return; + } + if(mAppenders.contains(p_appender)) + { + logger()->warn("Adding of duplicate appender '%2' to logger '%1'", name(), p_appender->name()); + return; + } + } + { + QWriteLocker locker(&mObjectGuard); + + if(mAppenders.contains(p_appender)) + return; + mAppenders.append(p_appender); + } + } + + + Appender *Logger::appender(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + if (p_appender->name() == rName) + return p_appender; + return 0; + } + + + + void Logger::callAppenders(const LoggingEvent &rEvent) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + p_appender->doAppend(rEvent); + if (additivity() && (parentLogger() != 0)) + parentLogger()->callAppenders(rEvent); + } + + + bool Logger::isAttached(Appender *pAppender) const + { + QReadLocker locker(&mObjectGuard); + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + return mAppenders.contains(p_appender); + } + + + void Logger::removeAllAppenders() + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to all appenders so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + logger()->trace("Removing all appenders from logger '%1'", name()); + + QList< LogObjectPtr > appenders; + { + QWriteLocker locker(&mObjectGuard); + QMutableListIterator< LogObjectPtr > i(mAppenders); + while (i.hasNext()) + { + Appender *p_appender = i.next(); + ListAppender *p_listappender = qobject_cast(p_appender); + if (p_listappender && p_listappender->configuratorList()) + continue; + else + { + appenders << p_appender; + i.remove(); + } + } + } + appenders.clear(); + } + + + void Logger::removeAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to the appender so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + LogObjectPtr p_appender = pAppender; + + if(!p_appender) + { + logger()->warn("Request to remove null Appender from Logger '%1'", name()); + return; + } + int n; + { + QWriteLocker locker(&mObjectGuard); + + n = mAppenders.removeAll(p_appender); + } + if (n == 0) + { + logger()->warn("Request to remove Appender '%2', which is not part of Logger '%1' appenders", name(), p_appender->name()); + return; + } + } + + + void Logger::removeAppender(const QString &rName) + { + Appender *p_appender = appender(rName); + if (p_appender) + removeAppender(p_appender); + } + + + Level Logger::effectiveLevel() const + { + Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT, "Logger::effectiveLevel()", "Root logger level must not be NULL_INT"); + + QReadLocker locker(&mObjectGuard); + + const Logger *p_logger = this; + while (p_logger->level() == Level::NULL_INT) + p_logger = p_logger->parentLogger(); + return p_logger->level(); + } + + + bool Logger::isEnabledFor(Level level) const + { + if (mpLoggerRepository->isDisabled(level)) + return false; + return (effectiveLevel() <= level); + } + + + Logger *Logger::logger(const QString &rName) + { + return LogManager::logger(rName); + } + + + Logger *Logger::logger(const char *pName) + { + return LogManager::logger(QLatin1String(pName)); + } + + + Logger *Logger::rootLogger() + { + return LogManager::rootLogger(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Logger::debug(QDebug &rDebug) const + { + QReadLocker locker(&mObjectGuard); + + QString parent_logger; + if (mpParent) + parent_logger = mpParent->name(); + + rDebug.nospace() << "Logger(" + << "name:" << name() << " " + << "appenders:" << mAppenders.count() << " " + << "additivity:" << mAdditivity << " " + << mLevel + << "parentLogger:" << parent_logger + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void Logger::forcedLog(Level level, const QString &rMessage) const + { + QReadLocker locker(&mObjectGuard); + + LoggingEvent event(this, level, rMessage); + callAppenders(event); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Logger &rLogger) + { + return rLogger.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/logger.h b/GC-3.6.1-T3/src/log4qt/logger.h new file mode 100644 index 0000000..1b58adc --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/logger.h @@ -0,0 +1,1665 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGER_H +#define LOG4QT_LOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/classlogger.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/level.h" + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macro Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * LOG4QT_DECLARE_STATIC_LOGGER declares a static function \a FUNCTION that + * returns a pointer to a \ref Log4Qt::Logger "Logger" named after \a CLASS. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by calling \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger( #CLASS )". The pointer is stored to be returned on + * subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class not derived from QObject. + * + * \code + * #file: counter.h + * + * #include logger.h + * + * class Counter + * { + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * LOG4QT_DECLARE_STATIC_LOGGER(logger, Counter) + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) : + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static Log4Qt::Logger *p_logger = 0; \ + if (!p_logger) \ + { \ + q_atomic_test_and_set_ptr( \ + &p_logger, \ + 0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#else + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger.loadAcquire()) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_DECLARE_QCLASS_LOGGER declares member functions to retrieve + * \ref Log4Qt::Logger "Logger" for the class it is used in. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by a call to \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger(const char *pName)". The pointer is stored to be + * returned on subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class derived from QObject. + * + * \code + * #file: counter.h + * + * #include qobject.h + * #include logger.h + * + * class Counter : public QObject + * { + * Q_OBJECT + * LOG4QT_DECLARE_QCLASS_LOGGER + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)", + * \ref Log4Qt::ClassLogger "ClassLogger" + */ + #define LOG4QT_DECLARE_QCLASS_LOGGER \ + private: \ + mutable Log4Qt::ClassLogger mLog4QtClassLogger; \ + public: \ + inline Log4Qt::Logger *logger() const \ + { return mLog4QtClassLogger.logger(this); } \ + private: + + class Appender; + class LoggingEvent; + class LoggerRepository; + + /*! + * \brief The class Logger provides logging services. + * + * A pointer to a logger can be retrieved by calling Logger::logger() or + * LogManager::logger() with the class name as argument. Because a logger + * is never destroyed it is possible to store the pointer to the logger. + * This way the lookup of the pointer in the repository is only required + * on the first logging operation. The macros \ref + * Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" and + * \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER" + * provide a thread-safe implementation to store the logger pointer. + * + * \note All the functions declared in this class are thread-safe. + */ + class Logger : public QObject + { + Q_OBJECT + + /*! + * The property holds, if the logger is additive. + * + * The default is true for being additive. + * + * \sa additive(), setAdditive() + */ + Q_PROPERTY(bool additivity READ additivity WRITE setAdditivity) + + /*! + * The property holds the level used by the logger. + * + * The default is Level::NULL_INT. + * \sa level(), setLevel() + */ + Q_PROPERTY(Level level READ level WRITE setLevel) + + /*! + * The property holds the LoggerRepository of the logger. + * + * \sa loggerRepository() + */ + Q_PROPERTY(LoggerRepository* loggerRepository READ loggerRepository) + + /*! + * The property holds the name of the logger. + * + * \sa name() + */ + Q_PROPERTY(QString name READ name) + + /*! + * The property holds the parent logger of the logger. + * + * \sa parentLogger() + */ + Q_PROPERTY(Logger* parentLogger READ parentLogger) + + LOG4QT_DECLARE_QCLASS_LOGGER + + protected: + Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent = 0); + virtual ~Logger(); + private: + Logger(const Logger &rOther); // Not implemented + Logger &operator=(const Logger &rOther); // Not implemented + + public: + bool additivity() const; + QList appenders() const; + Level level() const; + LoggerRepository *loggerRepository() const; + QString name() const; + Logger *parentLogger() const; + // JAVA: ResourceBundle *resourceBundle() const; + // JAVA: void setResourceBundle(ResourceBundle *pResourceBundle); + void setAdditivity(bool additivity); + virtual void setLevel(Level level); + + void addAppender(Appender *pAppender); + Appender *appender(const QString &rName) const; + void callAppenders(const LoggingEvent &rEvent) const; + bool isAttached(Appender *pAppender) const; + + /*! + * Removes all appenders that have been previously added from this + * Logger. + * + * To allow configurators to collect events during the configuration + * process ListAppenders with the configuratorList property set, will + * not be removed. + * + * \sa LisAppender::setConfiguratorList() + */ + void removeAllAppenders(); + + void removeAppender(Appender *pAppender); + void removeAppender(const QString &rName); + // JAVA: QString resourceBundleString(const QString &rKey) const; + + Level effectiveLevel() const; + bool isDebugEnabled() const; + + /*! + * Checks if this logger is enabled for a given Level \a level. If the + * logger is enabled the function returns true. Otherwise it returns + * false. + * + * A logger is enabled for a level, if the level is greater or equal + * then the repository threshold and greater and equal then the loggers + * effective level. + * + * \sa LoggerRepository::isDisabled(), effectiveLevel() + */ + bool isEnabledFor(Level level) const; + + bool isErrorEnabled() const; + bool isFatalEnabled() const; + bool isInfoEnabled() const; + bool isTraceEnabled() const; + bool isWarnEnabled() const; + + void debug(const QString &rMessage) const; + void debug(const LogError &rLogError) const; + void debug(const char *pMessage) const; + void debug(const char *pMessage, + const QString &rArg1) const; + void debug(const char *pMessage, + int arg1) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2) const; + void debug(const char *pMessage, + int arg1, + int arg2) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void error(const QString &rMessage) const; + void error(const LogError &rLogError) const; + void error(const char *pMessage) const; + void error(const char *pMessage, + const QString &rArg1) const; + void error(const char *pMessage, + int arg1) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void error(const char *pMessage, + const QString &rArg1, int arg2) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2) const; + void error(const char *pMessage, + int arg1, + int arg2) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void fatal(const QString &rMessage) const; + void fatal(const LogError &rLogError) const; + void fatal(const char *pMessage) const; + void fatal(const char *pMessage, + const QString &rArg1) const; + void fatal(const char *pMessage, + int arg1) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + int arg1, + int arg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void info(const QString &rMessage) const; + void info(const LogError &rLogError) const; + void info(const char *pMessage) const; + void info(const char *pMessage, + const QString &rArg1) const; + void info(const char *pMessage, + int arg1) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2) const; + void info(const char *pMessage, + int arg1, + int arg2) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void log(Level level, + const QString &rMessage) const; + void log(Level level, + const LogError &rLogError) const; + void log(Level level, + const char *pMessage) const; + void log(Level level, + const char *pMessage, + const QString &rArg1) const; + void log(Level level, + const char *pMessage, + int arg1) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // JAVA: void l7dlog(Level level, + // const QString &rKey); + // JAVA: void l7dlog(Level level, + // const QString &rKey, + // const QList rParameters); + + void trace(const QString &rMessage) const; + void trace(const LogError &rLogError) const; + void trace(const char *pMessage) const; + void trace(const char *pMessage, + const QString &rArg1) const; + void trace(const char *pMessage, + int arg1) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2) const; + void trace(const char *pMessage, + int arg1, + int arg2) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void warn(const QString &rMessage) const; + void warn(const LogError &rLogError) const; + void warn(const char *pMessage) const; + void warn(const char *pMessage, + const QString &rArg1) const; + void warn(const char *pMessage, + int arg1) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2) const; + void warn(const char *pMessage, + int arg1, + int arg2) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // LogManager operations + static Logger *logger(const QString &rName); + static Logger *logger(const char *pName); + static Logger *rootLogger(); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Logger(name:"Log4Qt" appenders:0 additivity:true Level("NULL") + * parentLogger: "root" ) + * + * \sa QDebug, operator<<(QDebug debug, const Appender &rAppender) + */ + virtual QDebug debug(QDebug &rDebug) const; + friend QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + void forcedLog(Level level, + const QString &rMessage) const; + + protected: + mutable QReadWriteLock mObjectGuard; + private: + const QString mName; + LoggerRepository* mpLoggerRepository; + volatile bool mAdditivity; + QList< LogObjectPtr > mAppenders; + Level mLevel; + Logger *mpParent; + + // Needs to be friend to create Logger objects + friend class Hierarchy; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Logger + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * To handle subclassing the function uses the virtual member function debug(). + * This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool Logger::additivity() const + { // QReadLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAdditivity; } + + inline Level Logger::level() const + { // QReadLocker locker(&mObjectGuard); // Level is thread-safe + return mLevel; } + + inline LoggerRepository *Logger::loggerRepository() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpLoggerRepository; } + + inline QString Logger::name() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mName; } + + inline Logger *Logger::parentLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpParent; } + + inline void Logger::setAdditivity(bool additivity) + { // QWriteLocker locker(&mObjectGuard); // Read/Write of int is safe + mAdditivity = additivity; } + + // Level operations + + inline bool Logger::isDebugEnabled() const + { return isEnabledFor(Level::DEBUG_INT); } + + inline bool Logger::isErrorEnabled() const + { return isEnabledFor(Level::ERROR_INT); } + + inline bool Logger::isFatalEnabled() const + { return isEnabledFor(Level::FATAL_INT); } + + inline bool Logger::isInfoEnabled() const + { return isEnabledFor(Level::INFO_INT); } + + inline bool Logger::isTraceEnabled() const + { return isEnabledFor(Level::TRACE_INT); } + + inline bool Logger::isWarnEnabled() const + { return isEnabledFor(Level::WARN_INT); } + + // Log operations: debug + + inline void Logger::debug(const LogError &rLogError) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rLogError.toString()); } + + inline void Logger::debug(const QString &rMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rMessage); } + + inline void Logger::debug(const char *pMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::debug(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: error + + inline void Logger::error(const QString &rMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rMessage); } + + inline void Logger::error(const LogError &rLogError) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rLogError.toString()); } + + inline void Logger::error(const char *pMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::error(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: fatal + + inline void Logger::fatal(const QString &rMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rMessage); } + + inline void Logger::fatal(const LogError &rLogError) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rLogError.toString()); } + + inline void Logger::fatal(const char *pMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::fatal(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: info + + inline void Logger::info(const QString &rMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rMessage); } + + inline void Logger::info(const LogError &rLogError) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rLogError.toString()); } + + inline void Logger::info(const char *pMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::info(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: log + + inline void Logger::log(Level level, + const QString &rMessage) const + { if (isEnabledFor(level)) + forcedLog(level, rMessage); } + + inline void Logger::log(Level level, + const LogError &rLogError) const + { if (isEnabledFor(level)) + forcedLog(level, rLogError.toString()); } + + inline void Logger::log(Level level, + const char *pMessage) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: trace + + inline void Logger::trace(const QString &rMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rMessage); } + + inline void Logger::trace(const LogError &rLogError) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rLogError.toString()); } + + inline void Logger::trace(const char *pMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::trace(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: warn + + inline void Logger::warn(const QString &rMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rMessage); } + + inline void Logger::warn(const LogError &rLogError) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rLogError.toString()); } + + inline void Logger::warn(const char *pMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::warn(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::Logger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGER_H diff --git a/GC-3.6.1-T3/src/log4qt/loggerrepository.cpp b/GC-3.6.1-T3/src/log4qt/loggerrepository.cpp new file mode 100644 index 0000000..b541bb2 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/loggerrepository.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggerrepository.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggerRepository + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository) + { + return rLoggerRepository.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/loggerrepository.h b/GC-3.6.1-T3/src/log4qt/loggerrepository.h new file mode 100644 index 0000000..13c0488 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/loggerrepository.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGERREPOSITORY_H +#define LOG4QT_LOGGERREPOSITORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggerRepository is abstract base class for a logger + * repository. + */ + class LoggerRepository + { + public: + // LoggerRepository(); // Use compiler default + // LoggerRepository(const LoggerRepository &rOther); // Use compiler default + // virtual ~LoggerRepository(); // Use compiler default + // LoggerRepository &operator=(const LoggerRepository &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const = 0; + virtual Logger *logger(const QString &rName) = 0; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual QList loggers() const = 0; + virtual Logger *rootLogger() const = 0; + virtual Level threshold() const = 0; + virtual void setThreshold(Level level) = 0; + virtual void setThreshold(const QString &rThreshold) = 0; + + virtual bool isDisabled(Level level) = 0; + virtual void resetConfiguration() = 0; + virtual void shutdown() = 0; + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + *\relates LoggerRepository + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + * to generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggerRepository + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle subclassing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LoggerRepository, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGERREPOSITORY_H diff --git a/GC-3.6.1-T3/src/log4qt/loggingevent.cpp b/GC-3.6.1-T3/src/log4qt/loggingevent.cpp new file mode 100644 index 0000000..161f01c --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/loggingevent.cpp @@ -0,0 +1,272 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggingevent.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggingevent.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" +#include "log4qt/mdc.h" +#include "log4qt/ndc.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(QMutex, sequence_guard) + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggingEvent + **************************************************************************/ + + + LoggingEvent::LoggingEvent() : + mLevel(Level::NULL_INT), + mpLogger(0), + mMessage(), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(timeStamp) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(rNdc), + mProperties(rProperties), + mSequenceNumber(nextSequenceNumber()), + mThreadName(rThreadName), + mTimeStamp(timeStamp) + { + } + + + QString LoggingEvent::loggerName() const + { + if (mpLogger) + return mpLogger->name(); + else + return QString(); + } + + + QString LoggingEvent::toString() const + { + return level().toString() + QLatin1Char(':') + message(); + } + + + qint64 LoggingEvent::sequenceCount() + { + QMutexLocker locker(sequence_guard()); + + return msSequenceCount; + } + + + qint64 LoggingEvent::startTime() + { + return InitialisationHelper::startTime(); + } + + + void LoggingEvent::setThreadNameToCurrent() + { + if (QThread::currentThread()) + mThreadName = QThread::currentThread()->objectName(); + } + + + qint64 LoggingEvent::nextSequenceNumber() + { + QMutexLocker locker(sequence_guard()); + + return ++msSequenceCount; + } + + + qint64 LoggingEvent::msSequenceCount = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, const LoggingEvent &rLoggingEvent) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLoggingEvent.mLevel + << rLoggingEvent.loggerName() + << rLoggingEvent.mMessage + << rLoggingEvent.mNdc + << rLoggingEvent.mProperties + << rLoggingEvent.mSequenceNumber + << rLoggingEvent.mThreadName + << rLoggingEvent.mTimeStamp; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, LoggingEvent &rLoggingEvent) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString logger; + stream >> rLoggingEvent.mLevel + >> logger + >> rLoggingEvent.mMessage + >> rLoggingEvent.mNdc + >> rLoggingEvent.mProperties + >> rLoggingEvent.mSequenceNumber + >> rLoggingEvent.mThreadName + >> rLoggingEvent.mTimeStamp; + if (logger.isEmpty()) + rLoggingEvent.mpLogger = 0; + else + rLoggingEvent.mpLogger = Logger::logger(logger); + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent) + { + QString logger; + if (rLoggingEvent.logger() != 0) + logger = rLoggingEvent.logger()->name(); + + debug.nospace() << "LoggingEvent(" + << "level:" << rLoggingEvent.level().toString() << " " + << "logger:" << logger << " " + << "message:" << rLoggingEvent.message() << " " + << "sequencenumber:" << rLoggingEvent.sequenceNumber() << " " + << "threadname:" << rLoggingEvent.threadName() << " " + << "timestamp:" << rLoggingEvent.timeStamp() + << "(" << DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()) << ")" + << "sequenceCount:" << rLoggingEvent.sequenceCount() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/loggingevent.h b/GC-3.6.1-T3/src/log4qt/loggingevent.h new file mode 100644 index 0000000..87e2ed6 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/loggingevent.h @@ -0,0 +1,221 @@ +/****************************************************************************** +* +* package: Log4Qt +* file: loggingevent.h +* created: September 2007 +* author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * +******************************************************************************/ + +#ifndef LOG4QT_LOG4QTEVENT_H +#define LOG4QT_LOG4QTEVENT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggingEvent is the internal representation of a + * logging event. + * + * The class uses milliseconds since 1970-01-01T00:00:00, Coordinated + * Universal Time for time values. For converstion from and to QDateTime + * use DateTime. + */ + class LoggingEvent + { + public: + LoggingEvent(); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp); + // LoggingEvent(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + // virtual ~LoggingEvent(); // Use compiler default + // LoggingEvent &operator=(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + + // JAVA: QString fqnOfLoggerClass() const; + Level level() const; + // LocationInformation locationInformation() const; + const Logger *logger() const; + QString message() const; + QHash mdc() const; + QString ndc() const; + QHash properties() const; + qint64 sequenceNumber() const; + QString threadName() const; + // JAVA: ThrowableInformation throwableInformation() const; + qint64 timeStamp() const; + + // JAVA: bool locationInformationExists() const; + QString loggerName() const; + QString property(const QString &rKey) const; + QStringList propertyKeys() const; + void setProperty(const QString &rKey, const QString &rValue); + // JAVA: QString throwableStrRep() const; + QString toString() const; + static qint64 sequenceCount(); + static qint64 startTime(); + + private: + void setThreadNameToCurrent(); + static qint64 nextSequenceNumber(); + + private: + Level mLevel; + const Logger *mpLogger; + QString mMessage; + QString mNdc; + QHash mProperties; + qint64 mSequenceNumber; + QString mThreadName; + qint64 mTimeStamp; + static qint64 msSequenceCount; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + friend QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LoggingEvent + * + * Writes the given error \a rLoggingEvent to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + + /*! + * \relates LoggingEvent + * + * Reads an error from the given stream \a rStream into the given + * error \a rLoggingEvent, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggingEvent + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LoggingEvent(level:"WARN" logger:"Log4Qt::Properties" + * message:"Unknown escape sequence '\j' in property starting at line 1" + * sequencenumber:14 threadname:"main" + * timestamp:1194337148937(QDateTime("Tue Nov 6 03:19:08 2007") ) + * sequenceCount: 14 ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Level LoggingEvent::level() const + { return mLevel; } + + inline const Logger *LoggingEvent::logger() const + { return mpLogger; } + + inline QString LoggingEvent::message() const + { return mMessage; } + + inline QHash LoggingEvent::mdc() const + { return mProperties; } + + inline QString LoggingEvent::ndc() const + { return mNdc; } + + inline QHash LoggingEvent::properties() const + { return mProperties; } + + inline qint64 LoggingEvent::sequenceNumber() const + { return mSequenceNumber; } + + inline QString LoggingEvent::threadName() const + { return mThreadName; } + + inline qint64 LoggingEvent::timeStamp() const + { return mTimeStamp; } + + inline QString LoggingEvent::property(const QString &rKey) const + { return mProperties.value(rKey); } + + inline QStringList LoggingEvent::propertyKeys() const + { return QStringList(mProperties.keys()); } + + inline void LoggingEvent::setProperty(const QString &rKey, const QString &rValue) + { mProperties.insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LoggingEvent) +Q_DECLARE_TYPEINFO(Log4Qt::LoggingEvent, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LOG4QTEVENT_H diff --git a/GC-3.6.1-T3/src/log4qt/logmanager.cpp b/GC-3.6.1-T3/src/log4qt/logmanager.cpp new file mode 100644 index 0000000..2c5e9ba --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/logmanager.cpp @@ -0,0 +1,504 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logmanager.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/hierarchy.h" +#include "log4qt/propertyconfigurator.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelrangefilter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) + LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) + + + + /************************************************************************** + * Class implementation: LogManager + **************************************************************************/ + + + LogManager::LogManager() : + mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() + mpLoggerRepository(new Hierarchy()), + mHandleQtMessages(false), + mOldQtMsgHandler(0) + { + } + + + LogManager::~LogManager() + { + static_logger()->warn("Unexpected destruction of LogManager"); + + // doSetConfigureHandleQtMessages(false); + // delete mpLoggerRepository; + } + + + Logger *LogManager::rootLogger() + { + return instance()->mpLoggerRepository->rootLogger(); + } + + + QList LogManager::loggers() + { + return instance()->mpLoggerRepository->loggers(); + } + + + Level LogManager::threshold() + { + return instance()->mpLoggerRepository->threshold(); + } + + + void LogManager::setThreshold(Level level) + { + instance()->mpLoggerRepository->setThreshold(level); + } + + + bool LogManager::exists(const char *pName) + { + return instance()->mpLoggerRepository->exists(QLatin1String(pName)); + } + + + LogManager *LogManager::instance() + { + // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive + // to construct, an exit handler must be set and doStartup must be + // called. + + if (!mspInstance) + { + QMutexLocker locker(singleton_guard()); + if (!mspInstance) + { + mspInstance = new LogManager; + // qAddPostRoutine(shutdown); + atexit(shutdown); + mspInstance->doConfigureLogLogger(); + mspInstance->welcome(); + mspInstance->doStartup(); + } + } + return mspInstance; + } + + + Logger *LogManager::logger(const QString &rName) + { + return instance()->mpLoggerRepository->logger(rName); + } + + + void LogManager::resetConfiguration() + { + setHandleQtMessages(false); + instance()->mpLoggerRepository->resetConfiguration(); + configureLogLogger(); + } + + + const char* LogManager::version() + { + return LOG4QT_VERSION_STR; + } + + + void LogManager::shutdown() + { + instance()->mpLoggerRepository->shutdown(); + } + + + void LogManager::doSetHandleQtMessages(bool handleQtMessages) + { + QMutexLocker locker(&mObjectGuard); + + if (instance()->mHandleQtMessages == handleQtMessages) + return; + + instance()->mHandleQtMessages = handleQtMessages; + if (instance()->mHandleQtMessages) + { + static_logger()->trace("Activate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); +#else + instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); +#endif + } + else + { + static_logger()->trace("Deactivate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + qInstallMsgHandler(instance()->mOldQtMsgHandler); +#else + qInstallMessageHandler(instance()->mOldQtMsgHandler); +#endif + } + } + + + void LogManager::doConfigureLogLogger() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Level + QString value = InitialisationHelper::setting(QLatin1String("Debug"), + QLatin1String("ERROR")); + logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); + + // Common layout + TTCCLayout *p_layout = new TTCCLayout(); + p_layout->setName(QLatin1String("LogLog TTCC")); + p_layout->setContextPrinting(false); + p_layout->activateOptions(); + + // Common deny all filter + Filter *p_denyall = new DenyAllFilter(); + p_denyall->activateOptions(); + + // ConsoleAppender on stdout for all events <= INFO + ConsoleAppender *p_appender; + LevelRangeFilter *p_filter; + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::NULL_INT); + p_filter->setLevelMax(Level::INFO_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stdout")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + + // ConsoleAppender on stderr for all events >= WARN + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::WARN_INT); + p_filter->setLevelMax(Level::OFF_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stderr")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + } + + + void LogManager::doStartup() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Override + QString default_value = QLatin1String("false"); + QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), + default_value); + if (value != default_value) + { + static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); + return; + } + + // Configuration using setting Configuration + value = InitialisationHelper::setting(QLatin1String("Configuration")); + if (QFile::exists(value)) + { + static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); + PropertyConfigurator::configure(value); + return; + } + + // Configuration using setting + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + QSettings s; + s.beginGroup(log4qt_group); + if (s.childGroups().contains(properties_group)) + { + const QString group(QLatin1String("Log4Qt/Properties")); + static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); + s.beginGroup(properties_group); + PropertyConfigurator::configure(s); + return; + } + } + + // Configuration using default file + const QString default_file(QLatin1String("log4qt.properties")); + if (QFile::exists(default_file)) + { + static_logger()->debug("Default initialisation configures from default file '%1'", default_file); + PropertyConfigurator::configure(default_file); + return; + } + + static_logger()->debug("Default initialisation leaves package unconfigured"); + } + + + void LogManager::welcome() + { + static_logger()->info(qPrintable(QObject::tr("Initialising Log4Qt %1")), + QLatin1String(LOG4QT_VERSION_STR)); + + // Debug: Info + if (static_logger()->isDebugEnabled()) + { + // Create a nice timestamp with UTC offset + DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); + QString offset; + { + QDateTime utc = start_time.toUTC(); + QDateTime local = start_time.toLocalTime(); + QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); + int min = utc.secsTo(local_as_utc) / 60; + if (min < 0) + offset += QLatin1Char('-'); + else + offset += QLatin1Char('+'); + min = abs(min); + offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); + offset += QLatin1Char(':'); + offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); + } + static_logger()->debug("Program startup time is %1 (UTC%2)", + start_time.toString(QLatin1String("ISO8601")), + offset); + static_logger()->debug("Internal logging uses the level %1", + logLogger()->level().toString()); + } + + // Trace: Dump settings + if (static_logger()->isTraceEnabled()) + { + static_logger()->trace("Settings from the system environment:"); + QString entry; + Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) + static_logger()->trace(" %1: '%2'", + entry, + InitialisationHelper::environmentSettings().value(entry)); + + static_logger()->trace("Settings from the application settings:"); + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + static_logger()->trace(" %1:", log4qt_group); + QSettings s; + s.beginGroup(log4qt_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + static_logger()->trace(" %1/%2:", log4qt_group, properties_group); + s.beginGroup(properties_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + } else + static_logger()->trace(" QCoreApplication::instance() is not available"); + } + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) + { + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, pMessage); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#else + void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) + { + Q_UNUSED(context); + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, message); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, message.toUtf8().constData()); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#endif + + + + LogManager *LogManager::mspInstance = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const LogManager &rLogManager) + { + Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 + QList loggers = rLogManager.loggers(); + debug.nospace() << "LogManager(" + << "loggerrepository:" << *rLogManager.loggerRepository() + << "log-level:" << rLogManager.logLogger()->level().toString() + << "log-appenders:" << rLogManager.logLogger()->appenders().count() + << "qt-level:" << rLogManager.qtLogger()->level().toString() + << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() + << "handleqtmessages:" << rLogManager.handleQtMessages() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/logmanager.h b/GC-3.6.1-T3/src/log4qt/logmanager.h new file mode 100644 index 0000000..27111a0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/logmanager.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGMANAGER_H +#define LOG4QT_LOGMANAGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include +#include "log4qt/level.h" +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggerRepository; + + /*! + * \brief The class LogManager manages Logger in the default + * LoggerRepository. + * + * The LogManager manages logger in a single Hierarchy instance. It + * provides access to special logger over the logLogger(), qtLogger() + * and rootLogger() member functions. + * + * The LogManager is handling the initialisation on startup. The + * initialisation procedure will first attempt to configure the package + * based on environment variables. If the attempt fails it will check for + * the existence of configuration files in several location. For detailed + * description of the initialisation procedure see \ref Init + * "Initialization procedure". + * + * Messages created by qDebug(), qWarning(), qCritical() and qFatal() can + * be can be handled by the LogManager. By default the message handling + * is disabled. It can be enabled by calling setHandleQtMessages(). Once + * enabled all messages are logged using the logger qtLogger(). + * + * The Log4Qt runtime version is accessible over version(). The macros + * \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION" and + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" provide the + * compile time version. + * + * \note All the functions declared in this class are thread-safe. + */ + class LogManager + { + private: + LogManager(); + LogManager(const LogManager &rOther); // Not implemented + virtual ~LogManager(); + LogManager &operator=(const LogManager &rOther); // Not implemented + + public: + /*! + * Returns if the handling of messages created by calls to qDebug(), + * qWarning(), qCritical() and qFatal() is activated. + * + * \sa setHandleQtMessages() + */ + static bool handleQtMessages(); + + static LoggerRepository *loggerRepository(); + + /*! + * Returns the logger used for logging internal messages. See + * \ref LogLog "Logging within the package" for more details. + * + * Calling this function is equivalent to calling logger("Log4Qt"). + */ + static Logger *logLogger(); + + /*! + * Returns a pointer to the logger used for logging messages created by + * calls to qDebug(), qWarning(), qCritical() and qFatal(). + * + * Calling this function is equivalent to calling logger("Qt"). + * + * \sa setHandleQtMessages() + */ + static Logger *qtLogger(); + + static Logger *rootLogger(); + static QList loggers(); + static Level threshold(); + static void setThreshold(Level level); + + /*! + * Activates or deactivates the handling of messages created by calls + * to qDebug(), qWarning(), qCritical() and qFatal() is activated. + * + * If activated, a Qt message handler is installed. Messages are logged + * using the logger returned by qtLogger(). For fatal messages the same + * exit procedure is implemented as for qFatal(). + * + * The following mappping is used from QtMsgType to Level: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    QtMsgType     %Level
QtDebugMsg Level::DEBUG_INT
QtWarningMsg Level::WARN_INT
QtCriticalMsg Level::ERROR_INT
QtFatalMsg Level::FATAL_INT
QtSystemMsg Level::TRACE_INT
+ * + * The default value is false for not handling Qt messages. + * + * \sa handleQtMessages(), qInstallMsgHandler(), qFatal() + */ + static void setHandleQtMessages(bool handleQtMessages); + + /*! + * Configures the logging for the package to its default behaviour. + * + * The logger logLogger() is configured to be not additive. Messages + * with the level Level::ERROR_INT and Level::FATAL_INT are written + * to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is + * read from the system environment or application settings using + * InitialisationHelper::setting() with the key \c Debug. If a level + * value is found, but it is not a valid Level string, + * Level::DEBUG_INT is used. If no level string is found + * Level::ERROR_INT is used. + * + * The function does not remove any appender from the logger + * logLogger(). + * + * \sa \ref LogLog "Logging within the package", + * \ref Env "Environment Variables", + * resetConfiguration(), InitialisationHelper::setting() + */ + static void configureLogLogger(); + + static bool exists(const char *pName); + // JAVA: void fireAddAppenderEvent(Logger *pLogger, Appender *pAppender); + + /*! + * Returns the LogManager instance. + */ + static LogManager *instance(); + + static Logger *logger(const QString &rName); + + /*! + * Reset all values contained in logger repository to their default. + * + * All appenders are removed from all loggers. The loggers are handled + * in no particular order. The last loggers to be reset are qtLogger(), + * logLogger() and rootLogger() in that order. + * + * The handling of messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() is deactivated. + * + * The internal logging is initialised to its default bahaviour + * using configureLogLogger(). + * + * \sa LoggerRepository::resetConfiguration(), setHandleQtMessages(), + * configureLogLogger() + */ + static void resetConfiguration(); + + static void shutdown(); + + /*! + * Executes the default initialisation procedure of the package. + * + * The function will test for the setting \c DefaultInitOverride in + * the system environment and application settings using + * \ref InitialisationHelper::setting(). If the value is present and + * set to anything else then \c false, the initialisation is aborted. + *
+ * The system environment and application settings are tested for the + * setting \c Configuration. If it is found and it is a valid path to + * a file, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting + * \c Configuration is not available and a QCoreApplication object is + * present, the application settings are tested for a group + * \c Log4Qt/Properties. If the group exists, the package is configured + * with the setting using the + * \ref PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration + * file nor configuration settings could be found, the current working + * directory is searched for the file \c "log4qt.properties". If it is + * found, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * \sa \ref Init "Initialization procedure", + * \ref Env "Environment Variables", + * InitialisationHelper::setting() + */ + static void startup(); + + /*! + * Returns the version number of Log4Qt at run-time. This may be a + * different version than the version the application was compiled + * against. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" + + */ + static const char* version(); + + private: + void doSetHandleQtMessages(bool handleQtMessages); + void doConfigureLogLogger(); + void doStartup(); + void welcome(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + static void qtMessageHandler(QtMsgType type, + const char *pMessage); +#else + static void qtMessageHandler(QtMsgType type, + const QMessageLogContext &context, + const QString &message); +#endif + + + private: + mutable QMutex mObjectGuard; + LoggerRepository *mpLoggerRepository; + Logger *mpNullLogger; + bool mHandleQtMessages; +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QtMsgHandler mOldQtMsgHandler; +#else + QtMessageHandler mOldQtMsgHandler; +#endif + static LogManager *mspInstance; + }; + + + /*************************************************************************** + * Operators, Helper + ***************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogManager + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %LogManager(loggerrepository:Hierarchy(loggers:6 root-level:"DEBUG" + * root-appenders:0 log-level: "NULL" log-appenders:0 + * qt-level: "NULL" qt-appenders:0 handleqtmessages: false ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogManager &rLogManager); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LoggerRepository *LogManager::loggerRepository() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mpLoggerRepository; } + + inline bool LogManager::handleQtMessages() + { // QMutexLocker locker(&instance()->mObjectGuard); // Read/Write of bool is safe + return instance()->mHandleQtMessages; } + + inline Logger *LogManager::logLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Log4Qt")); } + + inline Logger *LogManager::qtLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Qt")); } + + inline void LogManager::setHandleQtMessages(bool handleQtMessages) + { instance()->doSetHandleQtMessages(handleQtMessages); } + + inline void LogManager::configureLogLogger() + { instance()->doConfigureLogLogger(); } + + inline void LogManager::startup() + { instance()->doStartup(); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogManager, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGMANAGER_H diff --git a/GC-3.6.1-T3/src/log4qt/mdc.cpp b/GC-3.6.1-T3/src/log4qt/mdc.cpp new file mode 100644 index 0000000..5ba2ba8 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/mdc.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/mdc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: MDC + **************************************************************************/ + + + QString MDC::get(const QString &rKey) + { + if (!instance()->mHash.hasLocalData()) + return QString(); + + return instance()->mHash.localData()->value(rKey); + } + + + QHash MDC::context() + { + if (!instance()->mHash.hasLocalData()) + return QHash(); + + return *instance()->mHash.localData(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(MDC) + + + QHash *MDC::localData() + { + if (!instance()->mHash.hasLocalData()) + instance()->mHash.setLocalData(new QHash); + return instance()->mHash.localData(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const MDC &rMDC) + { + Q_UNUSED(rMDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "MDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "context:" << rMDC.context() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/mdc.h b/GC-3.6.1-T3/src/log4qt/mdc.h new file mode 100644 index 0000000..5e8fce9 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/mdc.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_MDC_H +#define LOG4QT_MDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + +/*! + * \brief The class MDC implements a mapped diagnostic context. + * + * \note All the functions declared in this class are thread-safe. + */ + class MDC + { + private: + MDC(); + MDC(const MDC &rOther); // Not implemented + // virtual ~MDC(); // Use compiler default + MDC &operator=(const MDC &rOther); // Not implemented + + public: + static QString get(const QString &rKey); + static QHash context(); + + /*! + * Returns the MDC instance. + */ + static MDC *instance(); + + static void put(const QString &rKey, const QString &rValue); + static void remove(const QString &rKey); + + private: + static QHash *localData(); + + private: + QThreadStorage< QHash * > mHash; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates MDC + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %MDC(thread:"main" context:QHash(("login", "Peter")("database", "UAT")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const MDC &rMDC); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline MDC::MDC() : + mHash() + {} + + inline void MDC::put(const QString &rKey, const QString &rValue) + { localData()->insert(rKey, rValue); } + + inline void MDC::remove(const QString &rKey) + { localData()->remove(rKey); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::MDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_MDC_H diff --git a/GC-3.6.1-T3/src/log4qt/ndc.cpp b/GC-3.6.1-T3/src/log4qt/ndc.cpp new file mode 100644 index 0000000..17ebd47 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/ndc.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ndc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt:NDC) + + + + /************************************************************************** + * Class implementation: NDC + **************************************************************************/ + + + void NDC::clear() + { + if (!instance()->mStack.hasLocalData()) + return; + + instance()->mStack.localData()->clear(); + } + + + int NDC::depth() + { + if (!instance()->mStack.hasLocalData()) + return 0; + + return instance()->mStack.localData()->count(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(NDC) + + + QString NDC::pop() + { + if (!instance()->mStack.hasLocalData() || instance()->mStack.localData()->isEmpty()) + { + logger()->warn("Requesting pop from empty NDC stack"); + return QString(); + } + + return instance()->mStack.localData()->pop(); + } + + + void NDC::push(const QString &rMessage) + { + if (!instance()->mStack.hasLocalData()) + instance()->mStack.setLocalData(new QStack); + + instance()->mStack.localData()->push(rMessage); + } + + + void NDC::setMaxDepth(int maxDepth) + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->size() <= maxDepth) + return; + + instance()->mStack.localData()->resize(maxDepth); + } + + + QString NDC::peek() + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->isEmpty()) + return QString(); + + return instance()->mStack.localData()->top(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const NDC &rNDC) + { + Q_UNUSED(rNDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "NDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "peek:" << rNDC.peek() << " " + << "depth:" << rNDC.depth() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/ndc.h b/GC-3.6.1-T3/src/log4qt/ndc.h new file mode 100644 index 0000000..e2c4210 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/ndc.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NDC_H +#define LOG4QT_NDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class NDC implements a nested diagnostic context. + * + * The method remove() is not required. QThreadStorage cleans up on thread + * exit. + * + * \note All the functions declared in this class are thread-safe. + */ + class NDC + { + private: + NDC(); + NDC(const NDC &rOther); // Not implemented + // virtual ~NDC(); // Use compiler default + NDC &operator=(const NDC &rOther); // Not implemented + + public: + static void clear(); + // JAVA: static QStack cloneStack(); + // JAVA: static QString get(); + static int depth(); + // JAVA: inherit(Stack stack) + + /*! + * Returns the NDC instance. + */ + static NDC *instance(); + + static QString pop(); + static void push(const QString &rMessage); + // JAVA: static void remove(); // Not required + static void setMaxDepth(int maxDepth); + static QString peek(); + + private: + QThreadStorage< QStack * > mStack; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates NDC + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NDC(thread:"main" peek:"i = 3" depth:4) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const NDC &rNDC); + #endif // QT_NO_DEBUG_STREAM + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + inline NDC::NDC() : + mStack() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NDC_H diff --git a/GC-3.6.1-T3/src/log4qt/patternlayout.cpp b/GC-3.6.1-T3/src/log4qt/patternlayout.cpp new file mode 100644 index 0000000..a93099f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/patternlayout.cpp @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/patternlayout.h" + +#include +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: PatternLayout + **************************************************************************/ + + + PatternLayout::PatternLayout(QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(DEFAULT_CONVERSION_PATTERN); + } + + + PatternLayout::PatternLayout(const QString &rPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(rPattern); + } + + + PatternLayout::PatternLayout(ConversionPattern conversionPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(conversionPattern); + } + + + PatternLayout::~PatternLayout() + { + delete mpPatternFormatter; + } + + + void PatternLayout::setConversionPattern(ConversionPattern conversionPattern) + { + switch (conversionPattern) + { + case DEFAULT_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%m%n")); + break; + case TTCC_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%r [%t] %p %c %x - %m%n")); + break; + default: + Q_ASSERT_X(false, "PatternLayout::setConversionFormat", "Unkown ConversionFormat"); + setConversionPattern(QString()); + } + } + + + QString PatternLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "PatternLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void PatternLayout::updatePatternFormatter() + { + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(mPattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug PatternLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "PatternLayout(" + << "name:" << name() << " " + << "pattern:" << conversionPattern() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/patternlayout.h b/GC-3.6.1-T3/src/log4qt/patternlayout.h new file mode 100644 index 0000000..2152f4b --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/patternlayout.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNLAYOUT_H +#define LOG4QT_PATTERNLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class PatternFormatter; + + /*! + * \brief The class PatternLayout outputs a logging event based on a + * pattern string. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class PatternLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds the conversion pattern used by the appender. + * + * The default is "%m%n". + * + * \sa conversionPattern(), setConversionPattern() + */ + Q_PROPERTY(QString conversionPattern READ conversionPattern WRITE setConversionPattern) + + public: + /*! + * The enum ConversionPattern defines constants for pattern strings. + * + * \sa setConversionPattern(ConversionPattern); + */ + enum ConversionPattern + { + /*! The default conversion pattern string is "%m,%n". */ + DEFAULT_CONVERSION_PATTERN, + /*! + * The ttcc conversion pattern string is + * "%r [%t] %p %c %x - %m%n". + */ + TTCC_CONVERSION_PATTERN, + }; + Q_ENUMS(ConversionPattern) + + PatternLayout(QObject *pParent = 0); + PatternLayout(const QString &rPattern, + QObject *pParent = 0); + + /*! + * Creates a PatternLayout with the conversion pattern value specified + * by the \a conversionPattern constant. + */ + PatternLayout(ConversionPattern conversionPattern, + QObject *pParent = 0); + + virtual ~PatternLayout(); + private: + PatternLayout(const PatternLayout &rOther); // Not implemented + PatternLayout &operator=(const PatternLayout &rOther); // Not implemented + + public: + QString conversionPattern() const; + void setConversionPattern(const QString &rPattern); + + /*! + * Sets the conversion pattern to the value specified by the + * \a conversionPattern constant. + */ + void setConversionPattern(ConversionPattern conversionPattern); + + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %PatternLayout(name:"PL" pattern:"%r [%t] %p %c %x - %m%n" + * "referencecount:3") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + QString mPattern; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString PatternLayout::conversionPattern() const + { return PatternLayout::mPattern; } + + inline void PatternLayout::setConversionPattern(const QString &rPattern) + { mPattern = rPattern; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::PatternLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PATTERNLAYOUT_H diff --git a/GC-3.6.1-T3/src/log4qt/propertyconfigurator.cpp b/GC-3.6.1-T3/src/log4qt/propertyconfigurator.cpp new file mode 100644 index 0000000..76f3ee0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/propertyconfigurator.cpp @@ -0,0 +1,588 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/propertyconfigurator.h" + +#include +#include +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/factory.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/appender.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/logmanager.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator) + + + + /************************************************************************** + * Class implementation: PropertyConfigurator + **************************************************************************/ + + + bool PropertyConfigurator::doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromProperties(rProperties, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromFile(rConfigFileName, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromSettings(rSettings, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::configure(const Properties &rProperties) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rProperties); + } + + + bool PropertyConfigurator::configure(const QString &rConfigFilename) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rConfigFilename); + } + + + bool PropertyConfigurator::configure(const QSettings &rSettings) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rSettings); + } + + + bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName) + { + // Stop an existing watch to avoid a possible concurrent configuration + ConfiguratorHelper::setConfigurationFile(); + if (rConfigFileName.isEmpty()) + return true; + + PropertyConfigurator configurator; + bool result = configurator.doConfigure(rConfigFileName); + ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure); + return result; + } + + + void PropertyConfigurator::configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + QFile file(rConfigFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"), + CONFIGURATOR_OPENING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + Properties properties; + properties.load(&file); + if (file.error()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"), + CONFIGURATOR_READING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + if (!pLoggerRepository) + pLoggerRepository = LogManager::loggerRepository(); + + configureGlobalSettings(rProperties, pLoggerRepository); + configureRootLogger(rProperties, pLoggerRepository); + configureNonRootElements(rProperties, pLoggerRepository); + mAppenderRegistry.clear(); + } + + + void PropertyConfigurator::configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + Properties properties; + properties.load(rSettings); + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null."); + + const QLatin1String key_reset("log4j.reset"); + const QLatin1String key_debug("log4j.Debug"); + const QLatin1String key_config_debug("log4j.configDebug"); + const QLatin1String key_threshold("log4j.threshold"); + const QLatin1String key_handle_qt_messages("log4j.handleQtMessages"); + + // Test each global setting and set it + // - Reset: log4j.reset + // - Debug: log4j.Debug, log4j.configDebug + // - Threshold: log4j.threshold + // - Handle Qt Messages: log4j.handleQtMessages + + // Reset + QString value = rProperties.property(key_reset); + if (!value.isEmpty() && OptionConverter::toBoolean(value, false)) + { + // Use LogManager and not pLoggerRepository to reset internal + // logging. + LogManager::resetConfiguration(); + logger()->debug("Reset configuration"); + } + + // Debug + value = rProperties.property(key_debug); + if (value.isNull()) + { + value = rProperties.property(key_config_debug); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug); + } + if (!value.isNull()) + { + // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting + bool ok; + Level level = Level::fromString(value, &ok); + if (!ok) + level = Level::DEBUG_INT; + LogManager::logLogger()->setLevel(level); + logger()->debug("Set level for Log4Qt logging to %1", + LogManager::logLogger()->level().toString()); + } + + // Threshold + value = rProperties.property(key_threshold); + if (!value.isNull()) + { + pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT)); + logger()->debug("Set threshold for LoggerRepository to %1", + pLoggerRepository->threshold().toString()); + } + + // Handle Qt messages + value = rProperties.property(key_handle_qt_messages); + if (!value.isNull()) + { + LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false)); + logger()->debug("Set handling of Qt messages LoggerRepository to %1", + QVariant(LogManager::handleQtMessages()).toString()); + } + } + + + void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null."); + + const QString logger_prefix = QLatin1String("log4j.logger."); + const QString category_prefix = QLatin1String("log4j.category."); + + // Iterate through all entries: + // - Test for the logger/category prefix + // - Convert JAVA class names to C++ ones + // - Parse logger data (Level, Appender) + // - Parse logger additivity + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + QString java_name; + if (key.startsWith(logger_prefix)) + java_name = key.mid(logger_prefix.length()); + else if (key.startsWith(category_prefix)) + java_name = key.mid(category_prefix.length()); + QString cpp_name = OptionConverter::classNameJavaToCpp(java_name); + if (!java_name.isEmpty()) + { + Logger *p_logger = pLoggerRepository->logger(cpp_name); + QString value = OptionConverter::findAndSubst(rProperties, key); + parseLogger(rProperties, p_logger, key, value); + parseAdditivityForLogger(rProperties, p_logger, java_name); + } + } + } + + + void PropertyConfigurator::configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null."); + + const QLatin1String key_root_logger("log4j.rootLogger"); + const QLatin1String key_root_category("log4j.rootCategory"); + + // - Test for the logger/category prefix + // - Parse logger data for root logger + + QString key = key_root_logger; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + key = key_root_category; + value = OptionConverter::findAndSubst(rProperties, key); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger); + } + + if (value.isNull()) + logger()->debug("Could not find root logger information. Is this correct?"); + else + parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value); + } + + + void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const + { + Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null."); + + const QLatin1String additivity_prefix("log4j.additivity."); + + // - Lookup additivity key for logger + // - Set additivity, if specified + + QString key = additivity_prefix + rLog4jName; + QString value = OptionConverter::findAndSubst(rProperties, key); + logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value); + if (!value.isEmpty()) + { + bool additivity = OptionConverter::toBoolean(value, true); + logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString()); + pLogger->setAdditivity(additivity); + } + } + + + LogObjectPtr PropertyConfigurator::parseAppender(const Properties &rProperties, + const QString &rName) + { + // - Test if appender has been parsed before + // - Find appender key + // - Create appender object + // - Set layout, if required by appender + // - Set properties + // - Activate options + // - Add appender to registry + + const QLatin1String appender_prefix("log4j.appender."); + + logger()->debug("Parsing appender named '%1'", rName); + + if (mAppenderRegistry.contains(rName)) + { + logger()->debug("Appender '%1' was already parsed.", rName); + return mAppenderRegistry.value(rName); + } + + QString key = appender_prefix + rName; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"), + CONFIGURATOR_MISSING_APPENDER_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rName; + logger()->error(e); + return 0; + } + LogObjectPtr p_appender = Factory::createAppender(value); + if (!p_appender) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"), + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rName; + logger()->error(e); + return 0; + } + p_appender->setName(rName); + + if (p_appender->requiresLayout()) + { + LogObjectPtr p_layout = parseLayout(rProperties, key); + if (p_layout) + p_appender->setLayout(p_layout); + else + return 0; + } + + QStringList exclusions; + exclusions << QLatin1String("layout"); + setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender); + AppenderSkeleton *p_appenderskeleton = qobject_cast(p_appender); + if (p_appenderskeleton) + p_appenderskeleton->activateOptions(); + + mAppenderRegistry.insert(rName, p_appender); + return p_appender; + } + + + LogObjectPtr PropertyConfigurator::parseLayout(const Properties &rProperties, + const QString &rAppenderKey) + { + Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty."); + + // - Find layout key + // - Create layput object + // - Set properties + // - Activate options + + const QLatin1String layout_suffix(".layout"); + + logger()->debug("Parsing layout for appender named '%1'", rAppenderKey); + + QString key = rAppenderKey + layout_suffix; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"), + CONFIGURATOR_MISSING_LAYOUT_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rAppenderKey; + logger()->error(e); + return 0; + } + LogObjectPtr p_layout = Factory::createLayout(value); + if (!p_layout) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layout of class '%1' requested by appender '%2'"), + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rAppenderKey; + logger()->error(e); + return 0; + } + + QStringList exclusions; + setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout); + p_layout->activateOptions(); + + return p_layout; + } + + + void PropertyConfigurator::parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue) + { + Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null."); + Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty."); + + const QLatin1String keyword_inherited("INHERITED"); + + // - Split value on comma + // - If level value, is specified + // - Test for NULL and INHERITED + // - Ensure root logger is not set to NULL + // - Set level + // - For each entry + // - Create Appender + + logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue); + QStringList appenders = rValue.split(QLatin1Char(',')); + QStringListIterator i (appenders); + + // First entry is the level. There will be always one entry, even if the rValue is + // empty or does not contain a comma. + QString value = i.next().trimmed(); + if (!value.isEmpty()) + { + Level level; + if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0) + level = Level::NULL_INT; + else + level = OptionConverter::toLevel(value, Level::DEBUG_INT); + if (level == Level::NULL_INT && pLogger->name() == QString()) + logger()->warn("The root logger level cannot be set to NULL."); + else + { + pLogger->setLevel(level); + logger()->debug("Set level for logger '%1' to '%2'", + pLogger->name(), pLogger->level().toString()); + } + } + + pLogger->removeAllAppenders(); + while(i.hasNext()) + { + value = i.next().trimmed(); + if(value.isEmpty()) + continue; + LogObjectPtr p_appender = parseAppender(rProperties, value); + if (p_appender) + pLogger->addAppender(p_appender); + } + } + + + void PropertyConfigurator::setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject) + { + Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty."); + Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null."); + + // Iterate through all entries: + // - Test for prefix to determine, if setting is for object + // - Skip empty property name + // - Skip property names in exclusion list + // - Set property on object + + logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'", + QLatin1String(pObject->metaObject()->className()), + rPrefix); + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + if (!key.startsWith(rPrefix)) + continue; + QString property = key.mid(rPrefix.length()); + if (property.isEmpty()) + continue; + QStringList split_property = property.split(QLatin1Char('.')); + if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive)) + continue; + QString value = OptionConverter::findAndSubst(rProperties, key); + Factory::setObjectProperty(pObject, property, value); + } + } + + + void PropertyConfigurator::startCaptureErrors() + { + Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty."); + + mpConfigureErrors = new ListAppender; + mpConfigureErrors->setName(QLatin1String("PropertyConfigurator")); + mpConfigureErrors->setConfiguratorList(true); + mpConfigureErrors->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(mpConfigureErrors); + } + + + bool PropertyConfigurator::stopCaptureErrors() + { + Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty."); + + LogManager::logLogger()->removeAppender(mpConfigureErrors); + ConfiguratorHelper::setConfigureError(mpConfigureErrors->list()); + bool result = (mpConfigureErrors->list().count() == 0); + mpConfigureErrors = 0; + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator) + { + Q_UNUSED(rPropertyConfigurator); + debug.nospace() << "PropertyConfigurator(" + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Logging diff --git a/GC-3.6.1-T3/src/log4qt/propertyconfigurator.h b/GC-3.6.1-T3/src/log4qt/propertyconfigurator.h new file mode 100644 index 0000000..ddf45e5 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/propertyconfigurator.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTYCONFIGURATOR_H +#define LOG4QT_PROPERTYCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QSettings; + +namespace Log4Qt +{ + + class Appender; + class Layout; + class ListAppender; + class Logger; + class Properties; + class LoggerRepository; + + /*! + * \brief The class PropertyConfigurator allows the configuration of the + * package from a JAVA properties file. + * + * \note All the functions declared in this class are thread-safe. + */ + class PropertyConfigurator + { + public: + PropertyConfigurator(); + // virtual ~PropertyConfigurator(); // Use compiler default + private: + PropertyConfigurator(const PropertyConfigurator &rOther); // Not implemented + PropertyConfigurator &operator=(const PropertyConfigurator &rOther); // Not implemented + + public: + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository = 0); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository = 0); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + bool doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository = 0); + + // JAVA: void doConfigure(const QUrl &rUrl, LoggerRepository *pLoggerRepository); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const Properties &rProperties); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const QString &rConfigFilename); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref doConfigure(const QSettings &, LoggerRepository *) "doConfigure()", + * \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + static bool configure(const QSettings &rSettings); + + // JAVA: static void configure(const QUrl &rUrl); + + /*! + * \sa ConfiguratorHelper::configureError(), + * ConfiguratorHelper::configurationFile() + */ + static bool configureAndWatch(const QString &rConfigFilename); + + private: + void configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository); + void configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository); + void configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const; + void configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const; + LogObjectPtr parseAppender(const Properties &rProperties, + const QString &rName); + LogObjectPtr parseLayout(const Properties &rProperties, + const QString &rAppenderName); + void parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue); + void setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject); + void startCaptureErrors(); + bool stopCaptureErrors(); + + private: + LogObjectPtr mpConfigureErrors; + QHash< QString, LogObjectPtr > mAppenderRegistry; + }; + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PropertyConfigurator + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * + * %PropertyConfigurator() + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline PropertyConfigurator::PropertyConfigurator() + {} + + +} // namspace Logging + + +// Q_DECLARE_TYPEINFO(Log4Qt::PropertyConfigurator, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PROPERTYCONFIGURATOR_H diff --git a/GC-3.6.1-T3/src/log4qt/rollingfileappender.cpp b/GC-3.6.1-T3/src/log4qt/rollingfileappender.cpp new file mode 100644 index 0000000..f9fac5f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/rollingfileappender.cpp @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/rollingfileappender.h" + +#include +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************ + Declarations + *************************************************************************/ + + + + /************************************************************************ + C helper functions + *************************************************************************/ + + + + /************************************************************************ + Class implementation: RollingFileAppender + *************************************************************************/ + + + RollingFileAppender::RollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + FileAppender(pLayout, rFileName, append, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::~RollingFileAppender() + { + close(); + } + + + void RollingFileAppender::setMaxFileSize(const QString &rMaxFileSize) + { + bool ok; + qint64 max_file_size = OptionConverter::toFileSize(rMaxFileSize, &ok); + if (ok) + setMaximumFileSize(max_file_size); + } + + QString RollingFileAppender::maxFileSize() + { + return QString("%1").arg(maximumFileSize()); + } + + + void RollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller") + + FileAppender::append(rEvent); + if (writer()->device()->size() > this->mMaximumFileSize) + rollOver(); + } + + + void RollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "RollingFileAppender::rollOver()", "Lock must be held by caller") + + logger()->debug("Rolling over with maxBackupIndex = %1", mMaxBackupIndex); + + closeFile(); + + QFile f; + f.setFileName(file() + QLatin1Char('.') + QString::number(mMaxBackupIndex)); + if (f.exists() && !removeFile(f)) + return; + + QString target_file_name; + int i; + for (i = mMaxBackupIndex - 1; i >=1; i--) + { + f.setFileName(file() + QLatin1Char('.') + QString::number(i)); + if (f.exists()) + { + target_file_name = file() + QLatin1Char('.') + QString::number(i + 1); + if (!renameFile(f, target_file_name)) + return; + } + } + + f.setFileName(file()); + target_file_name = file() + QLatin1String(".1"); + if (!renameFile(f, target_file_name)) + return; + + openFile(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug RollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "RollingFileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "maxbackupindex:" << maxBackupIndex() << " " + << "maximumfilesize:" << maximumFileSize() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/rollingfileappender.h b/GC-3.6.1-T3/src/log4qt/rollingfileappender.h new file mode 100644 index 0000000..47848a4 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/rollingfileappender.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_ROLINGFILEAPPENDER_H +#define LOG4QT_ROLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class RollingFileAppender extends FileAppender to backup + * the log files when they reach a certain size. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class RollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the maximum backup count used by the appender. + * + * The default is 1. + * + * \sa maxBackupIndex(), setMaxBackupIndex() + */ + Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex) + + /*! + * The property holds the maximum file size used by the appender. + * + * The default is 10 MB (10 * 1024 * 1024). + * + * \sa maximumFileSize(), setMaximumFileSize() + */ + Q_PROPERTY(qint64 maximumFileSize READ maximumFileSize WRITE setMaximumFileSize) + + /*! + * The property sets the maximum file size from a string value. + * + * \sa setMaxFileSize(), maximumFileSize() + */ + Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize) + + public: + RollingFileAppender(QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + virtual ~RollingFileAppender(); + private: + RollingFileAppender(const RollingFileAppender &rOther); // Not implemented + RollingFileAppender &operator=(const RollingFileAppender &rOther); // Not implemented + + public: + int maxBackupIndex() const; + qint64 maximumFileSize() const; + void setMaxBackupIndex(int maxBackupIndex); + void setMaximumFileSize(qint64 maximumFileSize); + QString maxFileSize(); + void setMaxFileSize(const QString &rMaxFileSize); + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %RollingFileAppender(name:"RFA" appendfile:false bufferedio:true + * encoding:"" file:"/log.txt" filter: 0x0 + * immediateflush:true isactive:true + * isclosed:false layout:"TTCC" maxbackupindex:2 + * maximumfilesize:40 referencecount:1 + * threshold:"NULL" writer:0x4175af8) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void rollOver(); + + private: + int mMaxBackupIndex; + qint64 mMaximumFileSize; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int RollingFileAppender::maxBackupIndex() const + { QMutexLocker locker(&mObjectGuard); + return mMaxBackupIndex; } + + inline qint64 RollingFileAppender::maximumFileSize() const + { QMutexLocker locker(&mObjectGuard); + return mMaximumFileSize; } + + inline void RollingFileAppender::setMaxBackupIndex(int maxBackupIndex) + { QMutexLocker locker(&mObjectGuard); + mMaxBackupIndex = maxBackupIndex; } + + inline void RollingFileAppender::setMaximumFileSize(qint64 maximumFileSize) + { QMutexLocker locker(&mObjectGuard); + mMaximumFileSize = maximumFileSize; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::RollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_ROLINGFILEAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/simplelayout.cpp b/GC-3.6.1-T3/src/log4qt/simplelayout.cpp new file mode 100644 index 0000000..a7d5234 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/simplelayout.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/simplelayout.h" + +#include +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: SimpleLayout + **************************************************************************/ + + + QString SimpleLayout::format(const LoggingEvent &rEvent) + { + return rEvent.level().toString() + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug SimpleLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "SimpleLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/simplelayout.h b/GC-3.6.1-T3/src/log4qt/simplelayout.h new file mode 100644 index 0000000..5ebe558 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/simplelayout.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_SIMPLELAYOUT_H +#define LOG4QT_SIMPLELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class SimpleLayout outputs the level and message of a logging + * event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class SimpleLayout : public Layout + { + Q_OBJECT + + public: + SimpleLayout(QObject *pParent = 0); + // virtual ~SimpleLayout(); // Use compiler default + private: + SimpleLayout(const SimpleLayout &rOther); // Not implemented + SimpleLayout &operator=(const SimpleLayout &rOther); // Not implemented + + public: + virtual QString format(const LoggingEvent &rEvent); + + protected: + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %SimpleLayout(name:"SL" referencecount:1) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline SimpleLayout::SimpleLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::SimpleLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_SIMPLELAYOUT_H diff --git a/GC-3.6.1-T3/src/log4qt/spi/filter.cpp b/GC-3.6.1-T3/src/log4qt/spi/filter.cpp new file mode 100644 index 0000000..8f2d10e --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/spi/filter.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/spi/filter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + void Filter::setNext(Filter *pFilter) + { + mpNext = pFilter; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/spi/filter.h b/GC-3.6.1-T3/src/log4qt/spi/filter.h new file mode 100644 index 0000000..0fd48f0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/spi/filter.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILTER_H +#define LOG4QT_FILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Filter is the base class for all filters. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Filter : public LogObject + { + Q_OBJECT + + /*! + * The property holds the next filter of this filter. + * + * The default is 0 for no next filter. + * + * \sa next(), setNext() + */ + Q_PROPERTY(Filter* next READ next WRITE setNext) + + public: + enum Decision + { + ACCEPT, + DENY, + NEUTRAL + }; + Q_ENUMS(Decision); + + public: + Filter(QObject *pObject = 0); + // Filter(const Filter &rOther); // Use compiler default + virtual ~Filter(); + // Filter &operator=(const Filter &rOther); // Use compiler default + + Filter* next() const; + void setNext(Filter *pFilter); + + virtual void activateOptions(); + virtual Decision decide(const LoggingEvent &rEvent) const = 0; + + private: + LogObjectPtr mpNext; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter::Filter(QObject *pObject) : + LogObject(pObject), + mpNext(0) + {} + + inline Filter::~Filter() + {} + + inline Filter* Filter::next() const + { return mpNext; } + + inline void Filter::activateOptions() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Filter, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_FILTER_H diff --git a/GC-3.6.1-T3/src/log4qt/ttcclayout.cpp b/GC-3.6.1-T3/src/log4qt/ttcclayout.cpp new file mode 100644 index 0000000..91baebc --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/ttcclayout.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ttcclayout.h" + +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: TTCCLayout + **************************************************************************/ + + + TTCCLayout::TTCCLayout(QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(RELATIVE); + } + + + TTCCLayout::TTCCLayout(const QString &rDateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(rDateFormat), + mThreadPrinting(true), + mpPatternFormatter(0) + { + } + + + TTCCLayout::TTCCLayout(DateFormat dateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(dateFormat); + } + + + TTCCLayout::~TTCCLayout() + { + delete mpPatternFormatter; + } + + + void TTCCLayout::setDateFormat(DateFormat dateFormat) + { + switch (dateFormat) + { + case NONE: + setDateFormat(QLatin1String("NONE")); + break; + case ISO8601: + setDateFormat(QLatin1String("ISO8601")); + break; + case ABSOLUTE: + setDateFormat(QLatin1String("ABSOLUTE")); + break; + case DATE: + setDateFormat(QLatin1String("DATE")); + break; + case RELATIVE: + setDateFormat(QLatin1String("RELATIVE")); + break; + default: + Q_ASSERT_X(false, "TTCCLayout::setDateFormat", "Unkown DateFormat"); + setDateFormat(QString()); + } + } + + + QString TTCCLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "TTCCLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void TTCCLayout::updatePatternFormatter() + { + QString pattern; + + pattern += QLatin1String("%d{") + mDateFormat + QLatin1String("}"); + if (mThreadPrinting) + pattern += QLatin1String(" [%t]"); + pattern += QLatin1String(" %-5p"); + if (mCategoryPrefixing) + pattern += QLatin1String(" %c"); + if (mContextPrinting) + pattern += QLatin1String(" %x"); + pattern += QLatin1String(" - %m%n"); + + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(pattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug TTCCLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "TTCCLayout(" + << "name:" << name() << " " + << "categoryprefixing:" << categoryPrefixing() << " " + << "contextprinting:" << contextPrinting() << " " + << "dateformat:" << dateFormat() << " " + << "referencecount:" << referenceCount() << " " + << "threadprinting:" << threadPrinting() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/ttcclayout.h b/GC-3.6.1-T3/src/log4qt/ttcclayout.h new file mode 100644 index 0000000..8987315 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/ttcclayout.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_TTCCLAYOUT_H +#define LOG4QT_TTCCLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + class PatternFormatter; + + /*! + * \brief The class TTCCLayout outputs the time, thread, logger and nested + * diagnostic context information of a logging event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class TTCCLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds if the logger name is part of the formatted output. + * + * The default value is true for including the logger name. + * + * \sa categoryPrefixing(), setCategoryPrefixing() + */ + Q_PROPERTY(bool categoryPrefixing READ categoryPrefixing WRITE setCategoryPrefixing) + + /*! + * The property holds if the nested context information is part of the + * formatted output. + * + * The default value it true for including the nested context information. + * + * \sa contextPrinting(), setContextPrinting() + */ + Q_PROPERTY(bool contextPrinting READ contextPrinting WRITE setContextPrinting) + + /*! + * The property holds the date format used by the layout. + * + * The default date format is "RELATIVE". + * + * \sa dateFormat(), setDateFormat() + */ + Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat) + + /*! + * The property holds if the thread name is part of the formatted output. + * + * The default value it true for including the thread name. + * + * \sa threadPrinting(), setThreadPrinting() + */ + Q_PROPERTY(bool threadPrinting READ threadPrinting WRITE setThreadPrinting) + + public: + /*! + * The enum DateFormat defines constants for date formats. + * + * \sa setDateFormat(DateFormat), DateTime::toString() + */ + enum DateFormat + { + /*! The none date format string is "NONE". */ + NONE, + /*! + * The iso8601 date format string is "ISO8601". The date will be + * formatted as yyyy-MM-dd hh:mm:ss.zzz. + */ + ISO8601, + /*! + * The absolute date format string is "ABSOLUTE". The date will be + * formatted as HH:mm:ss.zzz. + */ + ABSOLUTE, + /*! + * The date date format string is "DATE". The date will be formatted + * as MMM YYYY HH:mm:ss.zzzz. + */ + DATE, + /*! + * The relative date format string is "RELATIVE". The date will be + * formatted as milliseconds since start of the program. + */ + RELATIVE + }; + Q_ENUMS(DateFormat) + + TTCCLayout(QObject *pParent = 0); + TTCCLayout(const QString &rDateFormat, + QObject *pParent = 0); + + /*! + * Creates a TTCCLayout with the date formar value specified by + * the \a dateFormat constant and the parent \a pParent. + */ + TTCCLayout(DateFormat dateFormat, + QObject *pParent = 0); + + virtual ~TTCCLayout(); + private: + TTCCLayout(const TTCCLayout &rOther); // Not implemented + TTCCLayout &operator=(const TTCCLayout &rOther); // Not implemented + + public: + bool categoryPrefixing() const; + bool contextPrinting() const; + QString dateFormat() const; + // JAVA: bool ignoresThrowable() const; + bool threadPrinting() const; + void setCategoryPrefixing(bool categoryPrefixing); + void setContextPrinting(bool contextPrinting); + void setDateFormat(const QString &rDateFormat); + + /*! + * Sets the date format to the value specified by the \a dateFormat + * constant. + */ + void setDateFormat(DateFormat dateFormat); + + // JAVA: setIgnoresThrowable(bool ignoresThrowable); + void setThreadPrinting(bool threadPrinting); + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %TTCCLayout(name:"TTCC" categoryprefixing:true + * contextprinting:true dateformat:"ISO8601" + * referencecount:1 threadprinting:true) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + bool mCategoryPrefixing; + bool mContextPrinting; + QString mDateFormat; + bool mThreadPrinting; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool TTCCLayout::categoryPrefixing() const + { return mCategoryPrefixing; } + + inline bool TTCCLayout::contextPrinting() const + { return mContextPrinting; } + + inline QString TTCCLayout::dateFormat() const + { return mDateFormat; } + + inline bool TTCCLayout::threadPrinting() const + { return mThreadPrinting; } + + inline void TTCCLayout::setCategoryPrefixing(bool categoryPrefixing) + { mCategoryPrefixing = categoryPrefixing; + updatePatternFormatter(); } + + inline void TTCCLayout::setContextPrinting(bool contextPrinting) + { mContextPrinting = contextPrinting; + updatePatternFormatter(); } + + inline void TTCCLayout::setDateFormat(const QString &rDateFormat) + { mDateFormat = rDateFormat; + updatePatternFormatter(); } + + inline void TTCCLayout::setThreadPrinting(bool threadPrinting) + { mThreadPrinting = threadPrinting; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::TTCCLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_TTCCLAYOUT_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/debugappender.cpp b/GC-3.6.1-T3/src/log4qt/varia/debugappender.cpp new file mode 100644 index 0000000..fbaa351 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/debugappender.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/debugappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + +#if defined(Q_WS_WIN) +#include +#endif + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DebugAppender + **************************************************************************/ + + + DebugAppender::DebugAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(pParent) + { + setLayout(pLayout); + } + + + bool DebugAppender::requiresLayout() const + { + return true; + } + + + void DebugAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DebugAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "DebugAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); +#if defined(Q_WS_WIN) + QT_WA({ + OutputDebugStringW(reinterpret_cast(message.utf16())); + }, { + OutputDebugStringA(message.toLocal8Bit().data()); + }); +#else + fprintf(stderr, "%s", message.toLocal8Bit().data()); + fflush(stderr); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DebugAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "DebugAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namspace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/debugappender.h b/GC-3.6.1-T3/src/log4qt/varia/debugappender.h new file mode 100644 index 0000000..fc2b7f0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/debugappender.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DEBUGAPPENDER_H +#define LOG4QT_DEBUGAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DebugAppender appends logging events to the platform + * specific debug output. + * + * A DebugAppender appends to the Debugger on Windows and to stderr on all + * other systems. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DebugAppender : public AppenderSkeleton + { + Q_OBJECT + + public: + /*! + * Creates a DebugAppender. + */ + DebugAppender(QObject *pParent = 0); + + /*! + * Creates a DebugAppender with the specified layout \a pLayout + */ + DebugAppender(Layout *pLayout, + QObject *pParent = 0); + + // virtual ~DebugAppender(); // Use compiler default + private: + DebugAppender(const DebugAppender &rOther); // Not implemented + DebugAppender &operator=(const DebugAppender &rOther); // Not implemented + + public: + /*! + * The DebugAppended requires a layout. The function returns true. + * + * \sa setLayout() + */ + virtual bool requiresLayout() const; + + protected: + /*! + * Appends the specified logging event \a rEvent to the debug output. + * The output is formatted using the appender's layout. + * + * The method is called by the AppenderSkeleton::doAppend() after it + * the entry conditions have been tested and it has been found that the + * logging event needs to be appended. + * + * \sa setLayout(), AppenderSkeleton::doAppend(), checkEntryConditions() + */ + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DebugAppender(name:"DA" filter:0x3bee6b8 isactive:true isclosed:false + * layout:"SL" referencecount:1 threshold:"NULL") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DebugAppender::DebugAppender(QObject *pParent) : + AppenderSkeleton(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DebugAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DEBUGAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.cpp b/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.cpp new file mode 100644 index 0000000..31d8f64 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/denyallfilter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DenyAllFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DenyAllFilter(" + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.h b/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.h new file mode 100644 index 0000000..e67ffaa --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/denyallfilter.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a compile error on VS 2008 by using Q_UNUSED(&rEvent) + * instead of Q_UNUSED(rEvent) + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DENYALLFILTER_H +#define LOG4QT_DENYALLFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DenyAllFilter drops all logging events + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DenyAllFilter : public Filter + { + Q_OBJECT + + public: + DenyAllFilter(QObject *pParent = 0); + // DenyAllFilter(const DenyAllFilter &rOther); // Use compiler default + // virtual ~DenyAllFilter(); // Use compiler default + // DenyAllFilter &operator=(const DenyAllFilter &rOther); // Use compiler default + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DenyAllFilter(next:QObject(0x0) referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************* + * Operators, Helper + *************************************************************************/ + + + /************************************************************************* + * Inline + *************************************************************************/ + + inline DenyAllFilter::DenyAllFilter(QObject *pParent) : + Filter(pParent) + {} + + inline Filter::Decision DenyAllFilter::decide(const LoggingEvent &rEvent) const + { Q_UNUSED(&rEvent); return Filter::DENY; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DenyAllFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_DENYALLFILTER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.cpp b/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.cpp new file mode 100644 index 0000000..32a3d84 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + LevelMatchFilter::LevelMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelToMatch(Level::NULL_INT) + {} + + + Filter::Decision LevelMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (mLevelToMatch == Level::NULL_INT || + rEvent.level() != mLevelToMatch) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug LevelMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LevelMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "leveltomatch:" << mLevelToMatch.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.h b/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.h new file mode 100644 index 0000000..b2fb44c --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/levelmatchfilter.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELMATCHFILTER_H +#define LOG4QT_LEVELMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with a specified + * level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), setAcceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the level to match for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelToMatch(), setLevelToMatch() + */ + Q_PROPERTY(Level levelToMatch READ levelToMatch WRITE setLevelToMatch) + + public: + LevelMatchFilter(QObject *pParent = 0); + // LevelMatchFilter(const LevelMatchFilter &rOther); // Use compiler default + // virtual ~LevelMatchFilter(); // Use compiler default + // LevelMatchFilter &operator=(const LevelMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelToMatch() const; + void setAcceptOnMatch(bool accept); + void setLevelToMatch(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelMatchFilter(acceptonmatch:true leveltomatch:"WARN" + * next:Log4Qt::DenyAllFilter(0x3bce3a8) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + Level mLevelToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelMatchFilter::levelToMatch() const + { return mLevelToMatch; } + + inline void LevelMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelMatchFilter::setLevelToMatch(Level level) + { mLevelToMatch = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELMATCHFILTER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.cpp b/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.cpp new file mode 100644 index 0000000..b219cd9 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelrangefilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + + +/****************************************************************************** + * C helper functions + ******************************************************************************/ + + + +/****************************************************************************** + * Class implementation: Filter + ******************************************************************************/ + + +LevelRangeFilter::LevelRangeFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelMin(Level::NULL_INT), + mLevelMax(Level::OFF_INT) +{} + + +Filter::Decision LevelRangeFilter::decide(const LoggingEvent &rEvent) const +{ + if (rEvent.level() < mLevelMin) + return Filter::DENY; + + if (rEvent.level() > mLevelMax) + return Filter::DENY; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::NEUTRAL; +} + + +#ifndef QT_NO_DEBUG_STREAM +QDebug LevelRangeFilter::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "LevelRangeFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "levelmin:" << mLevelMin.toString() << " " + << "levelmax:" << mLevelMax.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.h b/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.h new file mode 100644 index 0000000..013e533 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/levelrangefilter.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELRANGEFILTER_H +#define LOG4QT_LEVELRANGEFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with levels in a + * specified range. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelRangeFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the maximum level of the range for this filter. + * + * The default is Level::OFF_INT. + * + * \sa levelMax(), setLevelMax() + */ + Q_PROPERTY(Level levelMax READ levelMax WRITE setLevelMax) + + /*! + * The property holds the minimum level of the range for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelMin(), setLevelMin() + */ + Q_PROPERTY(Level levelMin READ levelMin WRITE setLevelMin) + + public: + LevelRangeFilter(QObject *pParent = 0); + // LevelRangeFilter(const LevelRangeFilter &rOther); // Use compiler default + // virtual ~LevelRangeFilter(); // Use compiler default + // LevelRangeFilter &operator=(const LevelRangeFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelMax() const; + Level levelMin() const; + void setAcceptOnMatch(bool accept); + void setLevelMax(Level level); + void setLevelMin(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelRangeFilter(acceptonmatch:true levelmin:"ERROR" levelmax:"FATAL" + * next:Log4Qt::LevelMatchFilter(0x3bcd960) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + + private: + bool mAcceptOnMatch; + Level mLevelMin; + Level mLevelMax; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelRangeFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelRangeFilter::levelMax() const + { return mLevelMax; } + + inline Level LevelRangeFilter::levelMin() const + { return mLevelMin; } + + inline void LevelRangeFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelRangeFilter::setLevelMax(Level level) + { mLevelMax = level; } + + inline void LevelRangeFilter::setLevelMin(Level level) + { mLevelMin = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelRangeFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELRANGEFILTER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/listappender.cpp b/GC-3.6.1-T3/src/log4qt/varia/listappender.cpp new file mode 100644 index 0000000..db20284 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/listappender.cpp @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/listappender.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ListAppender + **************************************************************************/ + + + ListAppender::ListAppender(QObject *pParent) : + AppenderSkeleton(pParent), + mConfiguratorList(false), + mList(), + mMaxCount(0) + { + } + + + ListAppender::~ListAppender() + { + } + + + QList ListAppender::list() const + { + QMutexLocker locker(&mObjectGuard); + + return mList; + } + + + void ListAppender::setMaxCount(int n) + { + QMutexLocker locker(&mObjectGuard); + + if (n < 0) + { + logger()->warn("Attempt to set maximum count for appender '%1' to %2. Using zero instead", name(), n); + n = 0; + } + mMaxCount = n; + ensureMaxCount(); + } + + + QList ListAppender::clearList() + { + QMutexLocker locker(&mObjectGuard); + + QList result = mList; + mList.clear(); + return result; + } + + + // bool ListAppender::requiresLayout() const; + + + void ListAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "ListAppender::append()", "Lock must be held by caller") + + if ((mMaxCount <= 0) || (mList.size() < mMaxCount)) + mList << rEvent; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ListAppender::debug(QDebug &rDebug) const + { + rDebug.nospace() << "ListAppender(" + << "name:" << name() << " " + << "count:" << list().count() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "maxcount:" << maxCount() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void ListAppender::ensureMaxCount() + { + // Q_ASSERT_X(, "ListAppender::ensureMaxCount()", "Lock must be held by caller") + + if (mMaxCount <= 0) + return; + + while (mList.size() > mMaxCount) + mList.removeFirst(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/listappender.h b/GC-3.6.1-T3/src/log4qt/varia/listappender.h new file mode 100644 index 0000000..0b35c51 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/listappender.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LISTAPPENDER_H +#define LOG4QT_LISTAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class ListAppender appends logging events to a list for later + * processing. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ListAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds, if the Appender is used by a configurator. + * + * The default value is false for not being a configurator list. + * + * \sa configuratorList(), setConfiguratorList() + */ + Q_PROPERTY(bool configuratorList READ configuratorList WRITE setConfiguratorList) + + /*! + * The property holds the maximum count used by the appender. + * + * The default maximum count is -1 for unlimited. + * + * \sa maxCount(), setMaxCount() + */ + Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) + + public: + ListAppender(QObject *pParent = 0); + virtual ~ListAppender(); + private: + ListAppender(const ListAppender &rOther); // Not implemented + ListAppender &operator=(const ListAppender &rOther); // Not implemented + + public: + /*! + * Returns true, if the appender is used by a configurator. Otherweise it returns + * false. + * + * \sa setConfiguratorList() + */ + bool configuratorList() const; + + QList list() const; + int maxCount() const; + + /*! + * Sets that the appender is used by a configurator. If set to true, the appender + * will not be removed from a Logger when Logger::removeAllAppenders()is called. + * This way the appender can collect events raised during the configuration process. + * + * \sa configuratorList(), BasicConfigurator, PropertyConfigurator, + * ConfiguratorHelper::configureError() + */ + void setConfiguratorList(bool isConfiguratorList); + + void setMaxCount(int n); + + QList clearList(); + virtual bool requiresLayout() const; + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ListAppender(name:"LA" count:1 filter:0x41fa488 isactive:true + * isclosed:false maxcount:170 referencecount:1 + * threshold:"TRACE_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Ensures that the count of events is less or equal then the maxium + * count. If the list contains too many items, items are deleted from + * the begin of the list. + */ + void ensureMaxCount(); + + private: + volatile bool mConfiguratorList; + QList mList; + volatile int mMaxCount; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool ListAppender::configuratorList() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mConfiguratorList; } + + inline int ListAppender::maxCount() const + { return mMaxCount; } + + inline void ListAppender::setConfiguratorList(bool isConfiguratorList) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mConfiguratorList = isConfiguratorList; } + + inline bool ListAppender::requiresLayout() const + { return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ListAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LISTAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/nullappender.cpp b/GC-3.6.1-T3/src/log4qt/varia/nullappender.cpp new file mode 100644 index 0000000..a12ebf2 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/nullappender.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/nullappender.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: NullAppender + **************************************************************************/ + + + NullAppender::NullAppender(QObject *pParent) : + AppenderSkeleton(false, pParent) + { + } + + + NullAppender::~NullAppender() + { + close(); + } + + + void NullAppender::append(const LoggingEvent &rEvent) + { + Q_UNUSED(rEvent); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug NullAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "NullAppender(" + << "name:" << name() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "threshold:" << threshold().toString() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/nullappender.h b/GC-3.6.1-T3/src/log4qt/varia/nullappender.h new file mode 100644 index 0000000..becafb9 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/nullappender.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NULLAPPENDER_H +#define LOG4QT_NULLAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + +/*! + * \brief The class NullAppender ignores all requests to append. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ +class NullAppender : public AppenderSkeleton +{ + Q_OBJECT + +public: + NullAppender(QObject *pParent = 0); + virtual ~NullAppender(); +private: + NullAppender(const NullAppender &rOther); // Not implemented + NullAppender &operator=(const NullAppender &rOther); // Not implemented + +public: + virtual bool requiresLayout() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NullAppender() + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM +}; + + +/****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + +/****************************************************************************** + * Inline + ******************************************************************************/ + +inline bool NullAppender::requiresLayout() const +{ return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NullAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NULLAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.cpp b/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.cpp new file mode 100644 index 0000000..e660b21 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/stringmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + StringMatchFilter::StringMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mStringToMatch() + {} + + + Filter::Decision StringMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (rEvent.message().isEmpty() || + mStringToMatch.isEmpty() || + rEvent.message().indexOf(mStringToMatch) < 0) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug StringMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "StringMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "referencecount:" << referenceCount() << " " + << "stringtomatch:" << mStringToMatch << " " + << "next:" << next() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.h b/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.h new file mode 100644 index 0000000..921460f --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/varia/stringmatchfilter.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_STRINGMATCHFILTER_H +#define LOG4QT_STRINGMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class StringMatchFilter allows logging events with a + * specified level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class StringMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the string to match for this filter. + * + * \sa stringToMatch(), setStringToMatch() + */ + Q_PROPERTY(QString stringToMatch READ stringToMatch WRITE setStringToMatch) + + public: + StringMatchFilter(QObject *pParent = 0); + // StringMatchFilter(const StringMatchFilter &rOther); // Use compiler default + // virtual ~StringMatchFilter(); // Use compiler default + // StringMatchFilter &operator=(const StringMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + QString stringToMatch() const; + void setAcceptOnMatch(bool accept); + void setStringToMatch(const QString &rString); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %StringMatchFilter(acceptonmatch:true referencecount:1 + * stringtomatch:"LDAP_STRONG_AUTH_REQUIRED" + * next:Log4Qt::LevelMatchFilter(0x3bdd960) ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + QString mStringToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool StringMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline QString StringMatchFilter::stringToMatch() const + { return mStringToMatch; } + + inline void StringMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void StringMatchFilter::setStringToMatch(const QString &rString) + { mStringToMatch = rString; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::StringMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_STRINGMATCHFILTER_H diff --git a/GC-3.6.1-T3/src/log4qt/writerappender.cpp b/GC-3.6.1-T3/src/log4qt/writerappender.cpp new file mode 100644 index 0000000..25a633e --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/writerappender.cpp @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/writerappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: WriterAppender + **************************************************************************/ + + + WriterAppender::WriterAppender(QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(pTextStream), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::~WriterAppender() + { + close(); + } + + + void WriterAppender::setEncoding(QTextCodec *pEncoding) + { + QMutexLocker locker(&mObjectGuard); + + if (mpEncoding == pEncoding) + return; + + mpEncoding = pEncoding; + if (mpWriter) + { + if (mpEncoding) + mpWriter->setCodec(mpEncoding); + else + mpWriter->setCodec(QTextCodec::codecForLocale()); + } + } + + + void WriterAppender::setWriter(QTextStream *pTextStream) + { + QMutexLocker locker(&mObjectGuard); + + closeWriter(); + + mpWriter = pTextStream; + if (mpEncoding && mpWriter) + mpWriter->setCodec(mpEncoding); + writeHeader(); + } + + + void WriterAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires writer and has no writer set"), + APPENDER_ACTIVATE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return; + } + + AppenderSkeleton::activateOptions(); + } + + + void WriterAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + AppenderSkeleton::close(); + closeWriter(); + } + + + bool WriterAppender::requiresLayout() const + { + return true; + } + + + void WriterAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "WriterAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "WriterAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); + + *mpWriter << message; + if (handleIoErrors()) + return; + + if (immediateFlush()) + { + mpWriter->flush(); + if (handleIoErrors()) + return; + } + } + + + bool WriterAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a writer set"), + APPENDER_USE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + + void WriterAppender::closeWriter() + { + // Q_ASSERT_X(, "WriterAppender::closeWriter()", "Lock must be held by caller") + + if (!mpWriter) + return; + + writeFooter(); + mpWriter = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug WriterAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "WriterAppender(" + << "name:" << name() << " " + << "encoding:" << codec_name << " " + << "filter:" << firstFilter() + << "immediateFlush:" << immediateFlush() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool WriterAppender::handleIoErrors() const + { + return false; + } + + + void WriterAppender::writeFooter() const + { + // Q_ASSERT_X(, "WriterAppender::writeFooter()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString footer = layout()->footer(); + if (footer.isEmpty()) + return; + + *mpWriter << footer << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + void WriterAppender::writeHeader() const + { + // Q_ASSERT_X(, "WriterAppender::writeHeader()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString header = layout()->header(); + if (header.isEmpty()) + return; + + *mpWriter << header << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GC-3.6.1-T3/src/log4qt/writerappender.h b/GC-3.6.1-T3/src/log4qt/writerappender.h new file mode 100644 index 0000000..5c8da09 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qt/writerappender.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_WRITERAPPENDER_H +#define LOG4QT_WRITERAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QTextCodec; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class WriterAppender appends log events to a QTextStream. + * + * \note All the functions declared in this class are thread-safe. + *   + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class WriterAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds the codec the appender uses. + * + * The default is null to use the codec the writer has set. + * + * \sa encoding(), setEncoding() + */ + Q_PROPERTY(QTextCodec* encoding READ encoding WRITE setEncoding) + + /*! + * The property holds the writer the appender uses. + * + * \sa writer(), setWriter() + */ + Q_PROPERTY(QTextStream* writer READ writer WRITE setWriter) + + /*! + * The property holds, if the writer flushes after all write operations. + * + * The default is true for flushing. + * + * \sa immediateFlush(), setImmediateFlush() + */ + Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush) + + public: + WriterAppender(QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent = 0); + virtual ~WriterAppender(); + private: + WriterAppender(const WriterAppender &rOther); // Not implemented + WriterAppender &operator=(const WriterAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + QTextCodec *encoding() const; + bool immediateFlush() const; + QTextStream *writer() const; + + /*! + * Sets the codec used by the writer to \a pTextCoded. + * + * If a codec is set with setEncoding, it will overwrite the codec set + * in the text stream. A subsequent call with \a pTextCoded equals null + * will resets the codec to the default QTextCodec::codecForLocale(). + * + * \sa encoding(), QTextSream::setCodec(), QTextCodec::codecForLocale() + */ + void setEncoding(QTextCodec *pTextCodec); + void setImmediateFlush(bool immediateFlush); + void setWriter(QTextStream *pTextStream); + + virtual void activateOptions(); + virtual void close(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeWriter(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %WriterAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + virtual bool handleIoErrors() const; + void writeFooter() const; + void writeHeader() const; + + private: + QTextCodec *mpEncoding; + QTextStream *mpWriter; + volatile bool mImmediateFlush; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QTextCodec *WriterAppender::encoding() const + { QMutexLocker locker(&mObjectGuard); + return mpEncoding; } + + inline bool WriterAppender::immediateFlush() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mImmediateFlush; } + + inline QTextStream *WriterAppender::writer() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mpWriter; } + + inline void WriterAppender::setImmediateFlush(bool immediateFlush) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mImmediateFlush = immediateFlush; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::WriterAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_WRITERAPPENDER_H diff --git a/GC-3.6.1-T3/src/log4qtdef.h b/GC-3.6.1-T3/src/log4qtdef.h new file mode 100644 index 0000000..ce801e0 --- /dev/null +++ b/GC-3.6.1-T3/src/log4qtdef.h @@ -0,0 +1,11 @@ +#ifndef LOG4QTDEF_H +#define LOG4QTDEF_H + +#include "log4qt/consoleappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/logger.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/patternlayout.h" +#include "log4qt/logmanager.h" + +#endif // LOG4QTDEF_H diff --git a/GC-3.6.1-T3/src/main.cpp b/GC-3.6.1-T3/src/main.cpp new file mode 100644 index 0000000..0be6143 --- /dev/null +++ b/GC-3.6.1-T3/src/main.cpp @@ -0,0 +1,204 @@ +/**************************************************************** + * main.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "mainwindow.h" +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +#include +#endif + +enum GC_LOG_TYPES +{ + LOG_DEBUG_TYPE = 1, + LOG_ERROR_TYPE, + LOG_WARN_TYPE, + LOG_INFO_TYPE, + LOG_STATUS_TYPE, +}; + +void logit(GC_LOG_TYPES type, const char *str, va_list args); + +FILE *pDebugLogFile = NULL; +AtomicIntBool g_enableDebugLog; +Log4Qt::PatternLayout *p_layout; +Log4Qt::FileAppender *p_fappender; + +int main(int argc, char *argv[]) +{ + // setup logging + Log4Qt::LogManager::rootLogger(); + //Log4Qt::TTCCLayout *p_layout = new Log4Qt::TTCCLayout(Log4Qt::TTCCLayout::ISO8601); + //Log4Qt::PatternLayout *p_layout = new Log4Qt::PatternLayout(Log4Qt::PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout = new Log4Qt::PatternLayout("%d %p (%c) - %m%n"); + p_layout->setName(QLatin1String("GC Basic Layout")); + p_layout->activateOptions(); + + // Create a console appender + Log4Qt::ConsoleAppender *p_appender = new Log4Qt::ConsoleAppender(p_layout, Log4Qt::ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("GC Basic Console Appender")); +#ifdef QT_DEBUG + p_appender->setThreshold(Log4Qt::Level::TRACE_INT); +#else + p_appender->setThreshold(Log4Qt::Level::WARN_INT); +#endif + p_appender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_appender); + + // Create a file appender + p_fappender = new Log4Qt::FileAppender(); + p_fappender->setLayout(p_layout); + p_fappender->setThreshold(Log4Qt::Level::TRACE_INT); + p_fappender->setFile(QDir::homePath() + "/GrblController.log"); + p_fappender->setName(QLatin1String("GC Basic File Appender")); + // don't open until ready (later during startup) + //p_fappender->activateOptions(); + //Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + + QApplication a(argc, argv); + + QString locale = QLocale::system().name().section('_', 0, 0); + QString dir = QDir::currentPath() + "/trlocale"; + QString file = QString("GrblController_") + locale; + QTranslator translator; + bool r = translator.load(file, dir); + if (!r) + { + dir = QDir::currentPath() + "/../GrblHoming/trlocale"; + translator.load(file, dir); + } + a.installTranslator(&translator); + + QString xlatpath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + file = QString("qt_") + locale ; + QTranslator qtTranslator; + r = qtTranslator.load(file , xlatpath); + if (!r) + { + xlatpath = QDir::currentPath() + "/trlocale"; + qtTranslator.load(file, xlatpath); + } + a.installTranslator(&qtTranslator); + + MainWindow w; + w.show(); + + int result = a.exec(); + + if (pDebugLogFile != NULL) + { + fclose(pDebugLogFile); + pDebugLogFile = NULL; + } + return result; +} + + +//------------------------------ +void status(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_STATUS_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void err(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_ERROR_TYPE, str, args); + va_end(args); +} + +void warn(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_WARN_TYPE, str, args); + va_end(args); +} + +void info(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_INFO_TYPE, str, args); + va_end(args); +} + +void diag(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_DEBUG_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void logit(GC_LOG_TYPES type, const char *str, va_list args) +{ +#define PRNTBUFSIZE 500 + char buf[PRNTBUFSIZE]; + buf[PRNTBUFSIZE-1] = '\0'; + + vsnprintf(buf, sizeof(buf) - 1, str, args); + + int len = strlen(buf); + if (len > 0) + { + if (len == 1 && (buf[0] == '\r' || buf[0] == '\n')) + { + buf[0] = '\0'; + } + else if (len > 1) + { + if (buf[len - 2] == '\r' || buf[len - 2] == '\n') + buf[len - 2] = '\0'; + else if (buf[len - 1] == '\r' || buf[len - 1] == '\n') + buf[len - 1] = '\0'; + } + } + else if (len == 0) + return; + + switch (type) + { + case LOG_STATUS_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_STATUS)->info(buf); + break; + case LOG_DEBUG_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->debug(buf); + break; + case LOG_ERROR_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->error(buf); + break; + case LOG_WARN_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->warn(buf); + break; + case LOG_INFO_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->info(buf); + break; + } +} diff --git a/GC-3.6.1-T3/src/mainwindow.cpp b/GC-3.6.1-T3/src/mainwindow.cpp new file mode 100644 index 0000000..09de7b4 --- /dev/null +++ b/GC-3.6.1-T3/src/mainwindow.cpp @@ -0,0 +1,1701 @@ +/**************************************************************** + * mainwindow.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "mainwindow.h" +#include "version.h" +#include "ui_mainwindow.h" + +extern Log4Qt::FileAppender *p_fappender; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + open_button_text(tr("Open")), + close_button_text(tr("Close / Reset")), + absoluteAfterAxisAdj(false), + checkLogWrite(false), + sliderPressed(false), + sliderTo(0.0), + sliderZCount(0), + scrollRequireMove(true), scrollPressed(false), + queuedCommandsStarved(false), lastQueueCount(0), queuedCommandState(QCS_OK), + lastLcdStateValid(true) +{ + // Setup our application information to be used by QSettings + QCoreApplication::setOrganizationName(COMPANY_NAME); + QCoreApplication::setOrganizationDomain(DOMAIN_NAME); + QCoreApplication::setApplicationName(APPLICATION_NAME); + + // required if passing the object by reference into signals/slots + qRegisterMetaType("Coord3D"); + qRegisterMetaType("PosItem"); + qRegisterMetaType("ControlParams"); + + + ui->setupUi(this); +/// T3 + checkState = ui->Check->isChecked() ; + + readSettings(); + + info(qPrintable(tr("%s has started")), GRBL_CONTROLLER_NAME_AND_VERSION); + + // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/ + // The thread points out that the documentation for QThread is wrong :) and + // you should NOT subclass from QThread and override run(), rather, + // attach your QOBJECT to a thread and use events (signals/slots) to communicate. + gcode.moveToThread(&gcodeThread); + runtimeTimer.moveToThread(&runtimeTimerThread); + + ui->lcdWorkNumberX->setDigitCount(8); + ui->lcdMachNumberX->setDigitCount(8); + ui->lcdWorkNumberY->setDigitCount(8); + ui->lcdMachNumberY->setDigitCount(8); + ui->lcdWorkNumberZ->setDigitCount(8); + ui->lcdMachNumberZ->setDigitCount(8); + ui->lcdWorkNumberFourth->setDigitCount(8); + ui->lcdMachNumberFourth->setDigitCount(8); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + + //buttons + connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort())); + connect(ui->btnGRBL,SIGNAL(clicked()),this,SLOT(setGRBL())); + connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX())); + connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY())); + connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ())); + connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX())); + connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY())); + connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ())); + connect(ui->DecFourthBtn,SIGNAL(clicked()),this,SLOT(decFourth())); + connect(ui->IncFourthBtn,SIGNAL(clicked()),this,SLOT(incFourth())); + connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome())); + connect(ui->comboCommand->lineEdit(),SIGNAL(editingFinished()),this,SLOT(gotoXYZFourth())); +/// LETARTARE T3 + connect(ui->Check,SIGNAL(clicked()),this,SLOT(checkCode())); + + connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin())); + connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile())); + connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop())); + connect(ui->SpindleOn,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle())); + connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute())); + connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions())); + connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close())); + connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout())); + connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset())); + connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock())); + connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe())); + connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int))); + connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed())); + connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased())); + connect(ui->pushButtonRefreshPos,SIGNAL(clicked()),this,SLOT(refreshPosition())); + connect(ui->comboStep,SIGNAL(currentIndexChanged(QString)),this,SLOT(comboStepChanged(QString))); +/// T3 + connect(this, SIGNAL(sendFile(QString, bool)), &gcode, SLOT(sendFile(QString, bool))); + connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString))); + connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool))); + connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString))); + connect(this, SIGNAL(gotoXYZFourth(QString)), &gcode, SLOT(gotoXYZFourth(QString))); + connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int))); + connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams))); + connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit())); + connect(this, SIGNAL(shutdown()), &runtimeTimerThread, SLOT(quit())); + connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); + connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome())); + connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset())); +/// LETARTARE T3 + connect(this, SIGNAL(sendGrblCheck(bool)), &gcode, SLOT(sendGrblCheck(bool))); + + connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock())); + connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome())); + connect(this, SIGNAL(setItems(QList)), ui->wgtVisualizer, SLOT(setItems(QList))); + + connect(&gcode, SIGNAL(sendMsg(QString)),this,SLOT(receiveMsg(QString))); + connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool))); + connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool))); + connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString))); + connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList))); + connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString))); + connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending())); + connect(&gcode, SIGNAL(setCommandText(QString)), ui->comboCommand->lineEdit(), SLOT(setText(QString))); + connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(&gcode, SIGNAL(setQueuedCommands(int, bool)), this, SLOT(setQueuedCommands(int, bool))); + connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis())); + connect(&gcode, SIGNAL(resetTimer(bool)), &runtimeTimer, SLOT(resetTimer(bool))); + connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton())); + connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D))); + connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsWork(QString)), ui->outputUnitsWork, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setUnitsMachine(QString)), ui->outputUnitsMachine, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setLivePoint(double, double, bool, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool, bool))); + connect(&gcode, SIGNAL(setVisualLivenessCurrPos(bool)), ui->wgtVisualizer, SLOT(setVisualLivenessCurrPos(bool))); + connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int))); + connect(&gcode, SIGNAL(setLcdState(bool)), this, SLOT(setLcdState(bool))); + connect(&runtimeTimer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); +/// LETARTARE T2 + connect(&gcode, SIGNAL(setVersionGrbl(QString)), ui->GrblVersion, SLOT(setText(QString))); + connect(this, SIGNAL(setLinesFile(QString)), ui->outputLines, SLOT(setText(QString))); +/// T3 + connect(&gcode, SIGNAL(setLinesFile(QString, bool)), this, SLOT(setLinesFile(QString, bool))); + + // This code generates too many messages and chokes operation on raspberry pi. Do not use. + //connect(ui->statusList->model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), ui->statusList, SLOT(scrollToBottom())); + + // instead, use this one second timer-based approach + scrollTimer = new QTimer(this); + connect(scrollTimer, SIGNAL(timeout()), this, SLOT(doScroll())); + scrollTimer->start(1000); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderPressed()), this, SLOT(statusSliderPressed())); + connect(ui->statusList->verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(statusSliderReleased())); + + runtimeTimerThread.start(); + gcodeThread.start(); + + // Don't use - it will not show horizontal scrollbar for small app size + //ui->statusList->setUniformItemSizes(true); + + // Does not work correctly for horizontal scrollbar: + //MyItemDelegate *scrollDelegate = new MyItemDelegate(ui->statusList); + //scrollDelegate->setWidth(600); + //ui->statusList->setItemDelegate(scrollDelegate); + + scrollStatusTimer.start(); + queuedCommandsEmptyTimer.start(); + queuedCommandsRefreshTimer.start(); + + // Cool utility class off Google code that enumerates COM ports in platform-independent manner + QList ports = QextSerialEnumerator::getPorts(); + + int portIndex = -1; + for (int i = 0; i < ports.size(); i++) + { + ui->cmbPort->addItem(ports.at(i).portName.toLocal8Bit().constData()); + + if (ports.at(i).portName == lastOpenPort) + portIndex = i; + + //diag("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData()); + //diag("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData()); + //diag("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData()); + //diag("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData()); + //diag("===================================\n\n"); + } + + if (portIndex >= 0) + { + // found matching port + ui->cmbPort->setCurrentIndex(portIndex); + } + else if (lastOpenPort.size() > 0) + { + // did not find matching port + // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator + ui->cmbPort->addItem(lastOpenPort.toLocal8Bit().constData()); + if (ports.size() > 0) + ui->cmbPort->setCurrentIndex(ports.size()); + else + ui->cmbPort->setCurrentIndex(0); + } + + int baudRates[] = { 9600, 19200, 38400, 57600, 115200 }; + int baudRateCount = sizeof baudRates / sizeof baudRates[0]; + int baudRateIndex = 0; + for (int i = 0; i < baudRateCount; i++) + { + QString baudRate = QString::number(baudRates[i]); + ui->comboBoxBaudRate->addItem(baudRate); + if (baudRate == lastBaudRate) + { + baudRateIndex = i; + } + } + + ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex); + + ui->tabAxisVisualizer->setEnabled(false); + if (!controlParams.useFourAxis) + { + ui->lcdWorkNumberFourth->setEnabled(false);; + ui->lcdMachNumberFourth->setEnabled(false);; + ui->IncFourthBtn->setEnabled(false); + ui->DecFourthBtn->setEnabled(false); + ui->lblFourthJog->setEnabled(false); + } + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->Check->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + styleSheet = ui->btnOpenPort->styleSheet(); + ui->statusList->setEnabled(true); + ui->openFile->setEnabled(true); + + this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION); + this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + + QSettings settings; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + + if (!controlParams.useAggressivePreload && !promptedAggrPreload) + { + QMessageBox msgBox; + msgBox.setText(tr("You appear to have upgraded to the latest version of Grbl Controller. " + "Please be aware that as of version 3.4 the default behavior of sending commands " + "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n" + "Your settings have been changed to enable this mode. Why? Because it provides the most " + "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n" + "What does this mean to you? " + "Arc commands will now run smoother and faster than before, which may " + "cause your spindle to work slightly harder, so please run some tests first. " + "Alternately, go to the Options dialog and manually disable Aggressive Preload") ); + msgBox.exec(); + + controlParams.useAggressivePreload = true; + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload); + } + + promptedAggrPreload = true; + + emit setResponseWait(controlParams); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +// called when user has clicked the close application button +void MainWindow::closeEvent(QCloseEvent *event) +{ + gcode.setShutdown(); + gcode.setAbort(); + gcode.setReset(); + + writeSettings(); + + info(qPrintable(tr("%s has stopped")), GRBL_CONTROLLER_NAME_AND_VERSION); + + SLEEP(300); + + emit shutdown(); + + event->accept(); +} + +void MainWindow::begin() +{ + if (!checkState) + setLcdState(controlParams.usePositionRequest); + else + setLcdState(false); + + + ui->wgtVisualizer->setEnabled(!checkState); + ui->wgtVisualizer->setAutoFillBackground(!checkState); + + if (!checkState) + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + + //receiveList("Starting File Send."); + resetProgress(); + + int ret = QMessageBox::No; + if (!checkState) { + if((ui->lcdWorkNumberX->value()!=0)||(ui->lcdWorkNumberY->value()!=0)||(ui->lcdWorkNumberZ->value()!=0) + || (ui->lcdWorkNumberFourth->value()!=0)) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you want to zero the displayed position before proceeding?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Yes); + ret = msgBox.exec(); + if(ret == QMessageBox::Yes) + setHome(); + } + } + if(ret!=QMessageBox::Cancel) + { + ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// LETARTARE T3 + ui->Check->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(true); + ui->progressFileSend->setEnabled(true); + ui->progressQueuedCommands->setEnabled(true); + ui->labelFileSendProgress->setEnabled(true); + ui->labelQueuedCommands->setEnabled(true); + ui->outputRuntime->setEnabled(true); + ui->labelRuntime->setEnabled(true); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + + emit sendFile(ui->filePath->text(), checkState); + } +} + +void MainWindow::stop() +{ + setLcdState(controlParams.usePositionRequest); + ui->wgtVisualizer->setEnabled(true); + ui->wgtVisualizer->setAutoFillBackground(true); + + gcode.setAbort(); + + // Reenable a bunch of UI +/// LETARTARE T3 + ui->Check->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::grblReset() +{ + gcode.setAbort(); + gcode.setReset(); + emit sendGrblReset(); +} + +void MainWindow::grblUnlock() +{ + emit sendGrblUnlock(); +} + +void MainWindow::goHomeSafe() +{ + emit goToHome(); +} + +// slot called from GCode class to update our state +void MainWindow::stopSending() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); +/// LETARTARE T3 + ui->Check->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->btnOpenPort->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + ui->openFile->setEnabled(true); +} + +// User has asked to open the port +void MainWindow::openPort() +{ + QString Mes = tr("User clicked Port Open/Close"); + info(qPrintable(Mes) ); + + openPortCtl(false); +} + +// User has asked to set current position as 'home' = 0,0,0 +void MainWindow::setHome() +{ + resetProgress(); + sendSetHome(); +} + +void MainWindow::resetProgress() +{ + setProgress(0); + setQueuedCommands(0, false); + setRuntime(""); +} + +// If the port isn't open, we ask to open it +// If the port is open, we close it, but if 'reopen' is +// true, we call back to this thread to reopen it which +// is done mainly to toggle the COM port state to reset +// the controller. +void MainWindow::openPortCtl(bool reopen) +{ + if (ui->btnOpenPort->text() == open_button_text) + { + // Port is closed if the button says 'Open' + QString portStr = ui->cmbPort->currentText(); + QString baudRate = ui->comboBoxBaudRate->currentText(); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->btnOpenPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + emit openPort(portStr, baudRate); + } + else + { + if (!reopen) + resetProgress(); + + // presume button says 'Close' currently, meaning port is open + + // Tell gcode port thread to stop what it is doing immediately (within 0.1 sec) + gcode.setAbort(); + gcode.setReset(); + + // Disable a bunch of UI +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->Check->setEnabled(false); //checkState = false; + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->openFile->setEnabled(false); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + //ui->cmbPort->setEnabled(false); + //ui->comboBoxBaudRate->setEnabled(false); + //ui->btnOpenPort->setEnabled(false); + ui->btnGRBL->setEnabled(false); +/// LETARTARE T2 + ui->GrblVersion->setText(tr("none")); + + // Send event to close the port + emit closePort(reopen); + } +} + +// slot telling us that port was closed successfully +// if 'reopen' is true, reopen our port to toggle +// so we reset the controller +void MainWindow::portIsClosed(bool reopen) +{ + SLEEP(100); + + ui->tabAxisVisualizer->setEnabled(false); + ui->groupBoxSendFile->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->cmbPort->setEnabled(true); + ui->comboBoxBaudRate->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(open_button_text); + ui->btnOpenPort->setStyleSheet(styleSheet); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); + + if (reopen) + { + receiveList(tr("Resetting port to restart controller")); + openPortCtl(false); + } +} + +// slot that tells us the gcode thread successfully opened the port +void MainWindow::portIsOpen(bool sendCode) +{ + // Comm port successfully opened + if (sendCode) + sendGcode(""); +} + +void MainWindow::adjustedAxis() +{ + ui->tabAxisVisualizer->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + + if (ui->filePath->text().length() > 0) { + ui->Begin->setEnabled(true); +/// T3 + ui->Check->setEnabled(true); + } + + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + + ui->btnOpenPort->setEnabled(true); + ui->openFile->setEnabled(true); + ui->btnGRBL->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); +} + +void MainWindow::disableAllButtons() +{ + //ui->tabAxisVisualizer->setEnabled(false); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->Check->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + ui->openFile->setEnabled(false); + ui->btnGRBL->setEnabled(false); + ui->btnSetHome->setEnabled(false); + ui->btnResetGrbl->setEnabled(false); + ui->btnUnlockGrbl->setEnabled(false); + ui->btnGoHomeSafe->setEnabled(false); + ui->pushButtonRefreshPos->setEnabled(false); +} + +void MainWindow::enableGrblDialogButton() +{ + ui->openFile->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(close_button_text); + ui->btnOpenPort->setStyleSheet("* { background-color: rgb(255,125,100) }"); + ui->cmbPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + ui->tabAxisVisualizer->setEnabled(true); + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + ui->btnSetHome->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + ui->btnGoHomeSafe->setEnabled(true); + ui->pushButtonRefreshPos->setEnabled(true); + + if (ui->filePath->text().length() > 0) + { +/// LETARTARE T2 + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); +/// T3 + ui->Check->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->Check->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + ui->btnGRBL->setEnabled(true); +} + +void MainWindow::incX() +{ + disableAllButtons(); + emit axisAdj('X', jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incY() +{ + disableAllButtons(); + emit axisAdj('Y', jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incZ() +{ + disableAllButtons(); + emit axisAdj('Z', jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decX() +{ + disableAllButtons(); + emit axisAdj('X', -jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decY() +{ + disableAllButtons(); + emit axisAdj('Y', -jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decZ() +{ + disableAllButtons(); + emit axisAdj('Z', -jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, -jogStep, invFourth, absoluteAfterAxisAdj, 0); +} +void MainWindow::incFourth() +{ + disableAllButtons(); + emit axisAdj(controlParams.fourthAxisType, jogStep, invFourth, absoluteAfterAxisAdj, 0); +} + +void MainWindow::getOptions() +{ + Options opt(this); + opt.exec(); +} + +void MainWindow::gotoXYZFourth() +{ + if (ui->comboCommand->lineEdit()->text().length() == 0) + return; + + QString line = ui->comboCommand->lineEdit()->text().append("\r"); + + emit gotoXYZFourth(line); +} + +void MainWindow::openFile() +{ + QFileDialog dialog(this, tr("Open File"), + directory, + tr("NC (*.nc);;All Files (*.*)")); + + dialog.setFileMode(QFileDialog::ExistingFile); + + if (nameFilter.size() > 0) + dialog.selectNameFilter(nameFilter); + + if (fileOpenDialogState.size() > 0) + dialog.restoreState(fileOpenDialogState); + + QString fileName; + QStringList fileNames; + if (dialog.exec()) + { + fileOpenDialogState = dialog.saveState(); + + fileNames = dialog.selectedFiles(); + if (fileNames.length() > 0) + fileName = fileNames.at(0); + + nameFilter = dialog.selectedNameFilter(); + + resetProgress(); + } + + int slash = fileName.lastIndexOf('/'); + if (slash == -1) + { + slash = fileName.lastIndexOf('\\'); + } + + directory = ""; + if (slash != -1) + { + directory = fileName.left(slash); + } + + ui->filePath->setText(fileName); + if(ui->filePath->text().length() > 0 && ui->btnOpenPort->text() == close_button_text) + { +/// LETARTARE T2 + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); +/// T3 + ui->Check->setEnabled(true); + + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { +/// LETARTARE T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->Check->setEnabled(false); + + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + if (ui->filePath->text().length() > 0) + { + // read in the file to process it + preProcessFile(ui->filePath->text()); + + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISUALIZER_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISUALIZER_INDEX); + } + } +} + +void MainWindow::preProcessFile(QString filepath) +{ + QFile file(filepath); + if (file.open(QFile::ReadOnly)) + { + posList.clear(); +/// LETARTARE T2 'int totalLinesFile' -> global + totalLinesFile = 0; + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLinesFile++; + code.readLine(); + } + if (totalLinesFile == 0) + totalLinesFile = 1; +/// LETARTARE T2 + ui->outputLines->setText(QString().setNum(totalLinesFile)); + + code.seek(0); + + double x = 0; + double y = 0; + double i = 0; + double j = 0; + bool arc = false; + bool cw = false; + bool mm = true; + int index = 0; + int g = 0; + + bool zeroInsert = false; + do + { + QString strline = code.readLine(); + + index++; + + GCode::trimToEnd(strline, '('); + GCode::trimToEnd(strline, ';'); + GCode::trimToEnd(strline, '%'); + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + strline = strline.toUpper(); + strline.replace("M6", "M06"); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline.replace(QRegExp("\\s+"), " "); + //if (strline.contains("G", Qt::CaseInsensitive)) + { + if (processGCode(strline, x, y, i, j, arc, cw, mm, g)) + { + if (!zeroInsert) + { + // insert 0,0 position + posList.append(PosItem(0, 0, 0, 0, false, false, mm, 0)); + zeroInsert = true; + } + posList.append(PosItem(x, y, i, j, arc, cw, mm, index)); + + //printf("Got G command:%s (%f,%f)\n", strline.toLocal8Bit().constData(), x, y); + } + } + } + } while (code.atEnd() == false); + + file.close(); + + emit setItems(posList); + } + else + printf("Can't open file\n"); +} + +bool MainWindow::processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g) +{ + QString line = inputLine.toUpper(); + + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + arc = false; + bool valid = false; + int nextIsValue = NO_ITEM; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value >= 0 && value <= 3) + { + g = value; + if (value == 2) + cw = true; + else if (value == 3) + cw = false; + } + else if (value == 20) + mm = false; + else if (value == 21) + mm = true; + } + else if (g >= 0 && g <= 3 && s.at(0) == 'X') + { + x = decodeLineItem(s, X_ITEM, valid, nextIsValue); + } + else if (g >= 0 && g <= 3 && s.at(0) == 'Y') + { + y = decodeLineItem(s, Y_ITEM, valid, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'I') + { + i = decodeLineItem(s, I_ITEM, arc, nextIsValue); + } + else if ((g == 2 || g == 3) && s.at(0) == 'J') + { + j = decodeLineItem(s, J_ITEM, arc, nextIsValue); + } + else if (nextIsValue != NO_ITEM) + { + switch (nextIsValue) + { + case X_ITEM: + x = decodeDouble(s, valid); + break; + case Y_ITEM: + y = decodeDouble(s, valid); + break; + case I_ITEM: + i = decodeDouble(s, arc); + break; + case J_ITEM: + j = decodeDouble(s, arc); + break; + }; + nextIsValue = NO_ITEM; + } + } + + return valid; +} + +double MainWindow::decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue) +{ + if (item.size() == 1) + { + nextIsValue = next; + return 0; + } + else + { + nextIsValue = NO_ITEM; + return decodeDouble(item.mid(1,-1), valid); + } +} + +double MainWindow::decodeDouble(QString value, bool& valid) +{ + /* + QDoubleValidator v; + int pos = 0; + QValidator::State s = v.validate(value, pos); + if (s == QValidator::Invalid) + return 0; + */ + if (value.indexOf(QRegExp("^[+-]?[0-9]*\\.?[0-9]*$")) == -1) + return 0; + valid = true; + return value.toDouble(); +} + +void MainWindow::readSettings() +{ + // use platform-independent settings storage, i.e. registry under Windows + QSettings settings; + + fileOpenDialogState = settings.value(SETTINGS_FILE_OPEN_DIALOG_STATE).value(); + directory = settings.value(SETTINGS_DIRECTORY).value(); + nameFilter = settings.value(SETTINGS_NAME_FILTER).value(); + lastOpenPort = settings.value(SETTINGS_PORT).value(); + lastBaudRate = settings.value(SETTINGS_BAUD, QString::number(BAUD9600)).value(); + + promptedAggrPreload = settings.value(SETTINGS_PROMPTED_AGGR_PRELOAD, false).value(); + + QString absAfterAdj = settings.value(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, "false").value(); + absoluteAfterAxisAdj = (absAfterAdj == "true"); + ui->chkRestoreAbsolute->setChecked(absoluteAfterAxisAdj); + + jogStepStr = settings.value(SETTINGS_JOG_STEP, "1").value(); + jogStep = jogStepStr.toFloat(); + + int indexDesired = 0; + QString steps[] = { "0.01", "0.1", "1", "10", "100" }; + for (unsigned int i = 0; i < (sizeof (steps) / sizeof (steps[0])); i++) { + ui->comboStep->addItem(steps[i]); + if (jogStepStr == steps[i]) { + indexDesired = i; + } + } + ui->comboStep->setCurrentIndex(indexDesired); + + settings.beginGroup( "mainwindow" ); + + restoreGeometry(settings.value( "geometry", saveGeometry() ).toByteArray()); + restoreState(settings.value( "savestate", saveState() ).toByteArray()); + move(settings.value( "pos", pos() ).toPoint()); + resize(settings.value( "size", size() ).toSize()); + if ( settings.value( "maximized", isMaximized() ).toBool() ) + showMaximized(); + + settings.endGroup(); + + updateSettingsFromOptionDlg(settings); +} + +// Slot called from settings dialog after user made a change. Reload settings from registry. +void MainWindow::setSettings() +{ + QSettings settings; + + updateSettingsFromOptionDlg(settings); + + // update gcode thread with latest values + emit setResponseWait(controlParams); +} + +void MainWindow::updateSettingsFromOptionDlg(QSettings& settings) +{ + QString sinvX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString sinvY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString sinvZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + //QString smm = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS,"false").value(); + QString sinvFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + QString sdbgLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + g_enableDebugLog.set(sdbgLog == "true"); + + // only enable/not enable file logging at startup. There are some kind of + // multithreaded issues turning on or off file logging at runtime causing + // crashes. + if (!checkLogWrite) + { + checkLogWrite = true; + + if (g_enableDebugLog.get()) + { + p_fappender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + } + } + + invX = sinvX == "true"; + invY = sinvY == "true"; + invZ = sinvZ == "true"; + invFourth = sinvFourth == "true"; + + controlParams.waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + controlParams.zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + controlParams.useMm = useMmManualCmds == "true"; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + controlParams.waitForJogToComplete = waitForJogToComplete == "true"; + + QString useFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + controlParams.useFourAxis = useFourAxis == "true"; + if (controlParams.useFourAxis) + { + char type = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + controlParams.fourthAxisType = type; + } + + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->lblFourthJog->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + else + { + ui->DecFourthBtn->show(); + ui->IncFourthBtn->show(); + ui->lblFourthJog->show(); + ui->lcdWorkNumberFourth->show(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lcdMachNumberFourth->show(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->show(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->setText(QString(controlParams.fourthAxisType)); + + QString axisJog(tr("Z Jog"));// not correct, but a default placeholder we have a translation for already + char axis = controlParams.fourthAxisType; + if (axis == FOURTH_AXIS_A) + axisJog = tr("A Jog"); + else if (axis == FOURTH_AXIS_B) + axisJog = tr("B Jog"); + else if (axis == FOURTH_AXIS_C) + axisJog = tr("C Jog"); + else if (axis == FOURTH_AXIS_U) + axisJog = tr("U Jog"); + else if (axis == FOURTH_AXIS_V) + axisJog = tr("V Jog"); + else if (axis == FOURTH_AXIS_W) + axisJog = tr("W Jog"); + + ui->lblFourthJog->setText(axisJog); + } + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + controlParams.zRateLimit = zRateLimit == "true"; + + QString ffCommands = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + controlParams.filterFileCommands = ffCommands == "true"; + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + controlParams.reducePrecision = rPrecision == "true"; + controlParams.grblLineBufferLen = settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value(); + controlParams.charSendDelayMs = settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value(); + + controlParams.zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + controlParams.xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + controlParams.usePositionRequest = enPosReq == "true"; + controlParams.positionRequestType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_ALWAYS_NO_IDLE_CHK).value(); + double posReqFreq = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + controlParams.postionRequestTimeMilliSec = static_cast(posReqFreq) * 1000; + + setLcdState(controlParams.usePositionRequest); +} + +// save last state of settings +void MainWindow::writeSettings() +{ + QSettings settings; + + settings.setValue(SETTINGS_FILE_OPEN_DIALOG_STATE, fileOpenDialogState); + settings.setValue(SETTINGS_NAME_FILTER, nameFilter); + settings.setValue(SETTINGS_DIRECTORY, directory); + settings.setValue(SETTINGS_PORT, ui->cmbPort->currentText()); + settings.setValue(SETTINGS_BAUD, ui->comboBoxBaudRate->currentText()); + + settings.setValue(SETTINGS_PROMPTED_AGGR_PRELOAD, promptedAggrPreload); + settings.setValue(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, ui->chkRestoreAbsolute->isChecked()); + settings.setValue(SETTINGS_JOG_STEP, ui->comboStep->currentText()); + + // From http://stackoverflow.com/questions/74690/how-do-i-store-the-window-size-between-sessions-in-qt + settings.beginGroup("mainwindow"); + + settings.setValue( "geometry", saveGeometry() ); + settings.setValue( "savestate", saveState() ); + settings.setValue( "maximized", isMaximized() ); + if ( !isMaximized() ) { + settings.setValue( "pos", pos() ); + settings.setValue( "size", size() ); + } + + settings.endGroup(); +} + +void MainWindow::receiveList(QString msg) +{ + addToStatusList(true, msg); +} + +void MainWindow::receiveListFull(QStringList list) +{ + addToStatusList(list); +} + +void MainWindow::receiveListOut(QString msg) +{ + addToStatusList(false, msg); +} + +void MainWindow::addToStatusList(bool in, QString msg) +{ + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + return; + + QString nMsg(msg); + if (!in) + nMsg = "> " + msg; + + fullStatus.append(msg); + ui->statusList->addItem(nMsg); + + status("%s", nMsg.toLocal8Bit().constData()); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::addToStatusList(QStringList& list) +{ + QStringList cleanList; + foreach (QString msg, list) + { + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + continue; + + cleanList.append(msg); + + fullStatus.append(msg); + + status("%s", msg.toLocal8Bit().constData()); + } + + if (cleanList.size() == 0) + return; + + ui->statusList->addItems(cleanList); + + if (ui->statusList->count() > MAX_STATUS_LINES_WHEN_ACTIVE) + { + int count = ui->statusList->count() - MAX_STATUS_LINES_WHEN_ACTIVE; + for (int i = 0; i < count; i++) + { + ui->statusList->takeItem(0); + } + } + + scrollRequireMove = true; +} + +void MainWindow::doScroll() +{ + if (!scrollPressed && scrollRequireMove)// && scrollStatusTimer.elapsed() > 1000) + { + ui->statusList->scrollToBottom(); + QApplication::processEvents(); + scrollStatusTimer.restart(); + scrollRequireMove = false; + } +} + +void MainWindow::statusSliderPressed() +{ + scrollPressed = true; + + if (scrollStatusTimer.elapsed() > 3000) + { + ui->statusList->clear(); + ui->statusList->addItems(fullStatus); + } +} + +void MainWindow::statusSliderReleased() +{ + scrollPressed = false; +} + +/* testing optimizing scrollbar, doesn't work +int MainWindow::computeListViewMinimumWidth(QAbstractItemView* view) +{ + int minWidth = 0; + QAbstractItemModel* model = view->model(); + + QStyleOptionViewItem option; + + int rowCount = model->rowCount(); + for (int row = 0; row < rowCount; ++row) + { + QModelIndex index = model->index(row, 0); + QSize size = view->itemDelegate()->sizeHint(option, index); + scrollDelegate = new MyItemDelegate(view); + view->setItemDelegate(scrollDelegate); + + minWidth = qMax(size.width(), minWidth); + } + + if (rowCount > 0) + { + if (scrollDelegate == NULL) + { + scrollDelegate = new MyItemDelegate(view); + QModelIndex index = model->index(0, 0); + view->setItemDelegate(scrollDelegate); + } + + scrollDelegate->setWidth(minWidth); + info("Width is %d\n", minWidth); + } + return minWidth; +} +*/ + +void MainWindow::receiveMsg(QString msg) +{ + ui->centralWidget->setStatusTip(msg); +} + +void MainWindow::setGRBL() +{ + GrblDialog dlg(this, &gcode); + dlg.setParent(this); + dlg.getSettings(); + dlg.exec(); +} + +void MainWindow::showAbout() +{ + About about(this); + about.exec(); +} + +void MainWindow::toggleSpindle() +{ + if (ui->SpindleOn->QAbstractButton::isChecked()) + { + sendGcode("M03\r"); + receiveList(tr("Spindle On.")); + } + else + { + sendGcode("M05\r"); + receiveList(tr("Spindle Off.")); + } +} + +void MainWindow::toggleRestoreAbsolute() +{ + absoluteAfterAxisAdj = ui->chkRestoreAbsolute->QAbstractButton::isChecked(); +} + +void MainWindow::updateCoordinates(Coord3D machineCoord, Coord3D workCoord) +{ + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->lblFourthJog->setEnabled(controlParams.useFourAxis); + machineCoordinates = machineCoord; + workCoordinates = workCoord; +/* + if (workCoordinates.stoppedZ == false) + { + int newPos = workCoordinates.z + sliderTo; + + QString to; + to.sprintf("%d", newPos); + + ui->resultingZJogSliderPosition->setText(to); + } +*/ + refreshLcd(); +} + +void MainWindow::refreshLcd() +{ + lcdDisplay('X', true, workCoordinates.x); + lcdDisplay('Y', true, workCoordinates.y); + lcdDisplay('Z', true, workCoordinates.z); + lcdDisplay('X', false, machineCoordinates.x); + lcdDisplay('Y', false, machineCoordinates.y); + lcdDisplay('Z', false, machineCoordinates.z); + if (controlParams.useFourAxis) { + lcdDisplay(controlParams.fourthAxisType, true, workCoordinates.fourth); + lcdDisplay(controlParams.fourthAxisType, false, machineCoordinates.fourth); + } + else { + lcdDisplay(controlParams.fourthAxisType, true, 0); + lcdDisplay(controlParams.fourthAxisType, false, 0); + } +} + +void MainWindow::lcdDisplay(char axis, bool workCoord, float floatVal) +{ + QString value = QString::number(floatVal, 'f', 3); + switch (axis) + { + case 'X': + if (workCoord) + ui->lcdWorkNumberX->display(value); + else + ui->lcdMachNumberX->display(value); + break; + case 'Y': + if (workCoord) + ui->lcdWorkNumberY->display(value); + else + ui->lcdMachNumberY->display(value); + break; + case 'Z': + if (workCoord) + ui->lcdWorkNumberZ->display(value); + else + ui->lcdMachNumberZ->display(value); + break; + default: + if (axis == FOURTH_AXIS_A || axis == FOURTH_AXIS_B || axis == FOURTH_AXIS_C +/// LETARTARE + || axis == FOURTH_AXIS_U || axis == FOURTH_AXIS_V || axis == FOURTH_AXIS_W +/// <- + ) + { + if (workCoord) + ui->lcdWorkNumberFourth->display(value); + else + ui->lcdMachNumberFourth->display(value); + } + else + { + err("Unexpected type %c", axis); + } + break; + } +} + +void MainWindow::zJogSliderDisplay(int pos) +{ + QString str; + + pos -= CENTER_POS; + + if (pos > 0) + if(controlParams.useMm) + str.sprintf("+%d", pos); + else + str.sprintf("+%.1f",(double)pos/10); + else if (pos < 0) + if(controlParams.useMm) + str.sprintf("%d", pos); + else + str.sprintf("%.1f", (double)pos/10); + else + str = "0"; + + ui->currentZJogSliderDelta->setText(str); + + double newPos; + QString to; + if(controlParams.useMm) + newPos = pos + sliderTo; + else + newPos = (double)pos/10+sliderTo; + + if(controlParams.useMm) + to.sprintf("%.1f", newPos); + else + to.sprintf("%.1f", newPos); + + if (sliderPressed) + { + ui->resultingZJogSliderPosition->setText(to); + if(controlParams.useMm) + info(qPrintable(tr("Usr chg: pos=%d new=%d\n")), pos, newPos); + else + info(qPrintable(tr("Usr chg: pos=%.1f new=%.1f\n")), (double)pos/10, newPos); + } + else + { + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + if(controlParams.useMm) + info(qPrintable(tr("Usr chg no slider: %d\n")), pos); + else + info(qPrintable(tr("Usr chg no slider: %.1f\n")), (double) pos/10); + } +} + +void MainWindow::zJogSliderPressed() +{ + sliderPressed = true; + if (workCoordinates.stoppedZ && workCoordinates.sliderZIndex == sliderZCount) + { + info(qPrintable(tr("Pressed and stopped\n"))); + sliderTo = workCoordinates.z; + } + else + { + info(qPrintable(tr("Pressed not stopped\n"))); + } +} + +void MainWindow::zJogSliderReleased() +{ + info(qPrintable(tr("Released\n"))); + if (sliderPressed) + { + sliderPressed = false; + int value = ui->verticalSliderZJog->value(); + + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + + value -= CENTER_POS; + + if (value != 0) + { + if(controlParams.useMm) + sliderTo += value; + else + sliderTo += (double)value/10; + float setTo = value; + if(controlParams.useMm) + emit axisAdj('Z', setTo, invZ, absoluteAfterAxisAdj, sliderZCount++); + else + emit axisAdj('Z', setTo/10, invZ, absoluteAfterAxisAdj, sliderZCount++); + } + } + + + //ui->resultingZJogSliderPosition->setText("0"); +} + +void MainWindow::setQueuedCommands(int commandCount, bool running) +{ + if (running) + { + switch (queuedCommandState) + { + case QCS_OK: + if (lastQueueCount == 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 2000) + { + if (!queuedCommandsStarved) + { + //diag("DG >>>>Switch to red\n"); + + queuedCommandsStarved = true; + + ui->labelQueuedCommands->setStyleSheet("QLabel { background-color : rgb(255,0,0); color : white; }"); + + queuedCommandState = QCS_WAITING_FOR_ITEMS; + } + } + } + break; + case QCS_WAITING_FOR_ITEMS: + if (commandCount > 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 3000) + { + if (queuedCommandsStarved) + { + //diag("DG >>>>Switch to green\n"); + + queuedCommandsStarved = false; + + ui->labelQueuedCommands->setStyleSheet(""); + } + + queuedCommandsEmptyTimer.restart(); + + queuedCommandState = QCS_OK; + } + } + break; + } + + if (queuedCommandsRefreshTimer.elapsed() > 1000) + { + ui->progressQueuedCommands->setValue(commandCount); + queuedCommandsRefreshTimer.restart(); + } + } + else + { + queuedCommandsEmptyTimer.restart(); + queuedCommandState = QCS_OK; + ui->progressQueuedCommands->setValue(commandCount); + } + + lastQueueCount = commandCount; +} + +void MainWindow::setLcdState(bool valid) +{ + if (lastLcdStateValid != valid) + { + QString ss = ""; + if (!valid) + { + ss = "QLCDNumber { background-color: #F8F8F8; color: #F0F0F0; }"; + } + ui->lcdWorkNumberX->setStyleSheet(ss); + ui->lcdMachNumberX->setStyleSheet(ss); + ui->lcdWorkNumberY->setStyleSheet(ss); + ui->lcdMachNumberY->setStyleSheet(ss); + ui->lcdWorkNumberZ->setStyleSheet(ss); + ui->lcdMachNumberZ->setStyleSheet(ss); + ui->lcdWorkNumberFourth->setStyleSheet(ss); + ui->lcdMachNumberFourth->setStyleSheet(ss); + + lastLcdStateValid = valid; + } +} + +void MainWindow::refreshPosition() +{ + gotoXYZFourth(REQUEST_CURRENT_POS); +} + +void MainWindow::comboStepChanged(const QString& text) +{ + jogStepStr = text; + jogStep = jogStepStr.toFloat(); +} + +/// LETARTARE T2 +void MainWindow::setLinesFile(QString linesFile, bool check) +{ + if (check) /// T3 + linesFile += "/" + QString().setNum(totalLinesFile);; + + ui->outputLines->setText(linesFile); +} +/// <-- + +/// LETARTARE T3 called by pushbutton 'Check' +void MainWindow::checkCode() +{ + checkState = ui->Check->isChecked(); + /// send '$C' to Grbl + emit sendGrblCheck(checkState) ; +} +/// <-- diff --git a/GC-3.6.1-T3/src/mainwindow.h b/GC-3.6.1-T3/src/mainwindow.h new file mode 100644 index 0000000..8cc64f4 --- /dev/null +++ b/GC-3.6.1-T3/src/mainwindow.h @@ -0,0 +1,267 @@ +/**************************************************************** + * mainwindow.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "about.h" +#include "definitions.h" +#include "grbldialog.h" +#include "options.h" +#include "timer.h" +#include "positem.h" +#include "gcode.h" +#include "renderarea.h" + +#define COMPANY_NAME "zapmaker" +#define APPLICATION_NAME "GrblController" +#define DOMAIN_NAME "org.zapmaker" + +#define TAB_AXIS_INDEX 0 +#define TAB_VISUALIZER_INDEX 1 +#define TAB_ADVANCED_INDEX 2 + +#define CENTER_POS 40 + +#define MAX_STATUS_LINES_WHEN_ACTIVE 200 + +/* testing optimizing scrollbar, doesn't work right +class MyItemDelegate : public QItemDelegate +{ +private: + int width; + QAbstractItemView *parentWidget; + +public: + + MyItemDelegate(QAbstractItemView *p) : parentWidget(p) {} + + void setWidth(int w) + { + width = w; + } + + void drawDisplay(QPainter *painter,const + QStyleOptionViewItem &option,const QRect &rect,const QString &text) const{ + + QRect tempRect(rect); + tempRect.setWidth(parentWidget->width()); + QItemDelegate::drawDisplay(painter,option,tempRect,text); + + } + + QSize sizeHint(const QStyleOptionViewItem & option, const + QModelIndex & index ) const { + + QListView *list = qobject_cast(parentWidget); + QSize newSize(QItemDelegate::sizeHint(option,index)); + if( list ) newSize.setWidth( width ); + return newSize; + } +}; +*/ + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void closeEvent(QCloseEvent *event); + + //variables + int delete_nr; + +signals: + //threads + void openPort(QString port, QString baudRate); + void closePort(bool reopen); + void shutdown(); + void sendGcode(QString line, bool recordResponseOnFail = false, int waitCount = SHORT_WAIT_SEC); +/// T3 + void sendFile(QString path, bool); + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void setProgress(int percent); + void setRuntime(QString runtime); + void sendSetHome(); +/// LETARTARE T3 + void sendGrblCheck(bool); + + void sendGrblReset(); + void sendGrblUnlock(); + void goToHome(); + void setItems(QList); + +private slots: + //buttons + void openPort(); + void setGRBL(); + //Adjust + void decX(); + void decY(); + void decZ(); + void decFourth(); + void incFourth(); + void incX(); + void incY(); + void incZ(); + void setHome(); + //manual + void gotoXYZFourth(); + //send Gcode +/// LETARTARE T3 + void checkCode(); + + void begin(); + void openFile(); + void stop(); + void stopSending(); + // + void portIsOpen(bool sendCode); + void portIsClosed(bool reopen); + void adjustedAxis(); + + //check boxes + void toggleSpindle(); + void toggleRestoreAbsolute(); + + //communications + //options + void setSettings(); + //thread + void receiveList(QString msg); + void receiveListFull(QStringList list); + void receiveListOut(QString msg); + void receiveMsg(QString msg); + //menu bar + void getOptions(); + void showAbout(); + void enableGrblDialogButton(); + + void grblReset(); + void grblUnlock(); + void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); + void goHomeSafe(); + void zJogSliderDisplay(int pos); + void zJogSliderPressed(); + void zJogSliderReleased(); + void doScroll(); + void statusSliderPressed(); + void statusSliderReleased(); + void setQueuedCommands(int commandCount, bool running); + void setLcdState(bool valid); + void refreshPosition(); + void comboStepChanged(const QString& text); +/// LETARTARE T2 + void setLinesFile(QString linesFile, bool check); + +private: + // enums + enum + { + NO_ITEM = 0, + X_ITEM, + Y_ITEM, + I_ITEM, + J_ITEM, + }; + enum + { + QCS_OK = 0, + QCS_WAITING_FOR_ITEMS + }; + //objects + Ui::MainWindow *ui; + //FileSender fileSender; + //QThread fileSenderThread; + GCode gcode; + QThread gcodeThread; + + Timer runtimeTimer; + QThread runtimeTimerThread; + + //variables + bool invX; + bool invY; + bool invZ; + bool invFourth; + /// for translation + QString open_button_text ; + QString close_button_text ; + bool mm; + QString styleSheet; + QString directory; + QString nameFilter; + QString lastOpenPort; + QString lastBaudRate; + QByteArray fileOpenDialogState; + Coord3D machineCoordinates; + Coord3D workCoordinates; + bool absoluteAfterAxisAdj; + bool checkLogWrite; + QTime scrollStatusTimer; + QTime queuedCommandsEmptyTimer; + QTime queuedCommandsRefreshTimer; + QList posList; + bool sliderPressed; + double sliderTo; + int sliderZCount; + bool promptedAggrPreload; + ControlParams controlParams; + QTimer *scrollTimer; + bool scrollRequireMove; + bool scrollPressed; + bool queuedCommandsStarved; + int lastQueueCount; + int queuedCommandState; + QStringList fullStatus; + bool lastLcdStateValid; + float jogStep; + QString jogStepStr; +/// LETARTARE T3 + bool checkState; + int totalLinesFile; + + //methods + int SendJog(QString strline); + void readSettings(); + void writeSettings(); + void addToStatusList(bool in, QString msg); + void addToStatusList(QStringList& list); + void disableAllButtons(); + void openPortCtl(bool reopen); + void resetProgress(); + void refreshLcd(); + void lcdDisplay(char axis, bool workCoord, float value); + void updateSettingsFromOptionDlg(QSettings& settings); + int computeListViewMinimumWidth(QAbstractItemView* view); + void preProcessFile(QString filepath); + bool processGCode(QString inputLine, double& x, double& y, double& i, double& j, bool& arc, bool& cw, bool& mm, int& g); + double decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue); + double decodeDouble(QString value, bool& valid); +}; + + +#endif // MAINWINDOW_H diff --git a/GC-3.6.1-T3/src/mainwindow.ui b/GC-3.6.1-T3/src/mainwindow.ui new file mode 100644 index 0000000..1f4e836 --- /dev/null +++ b/GC-3.6.1-T3/src/mainwindow.ui @@ -0,0 +1,1881 @@ + + + MainWindow + + + Qt::NonModal + + + true + + + + 0 + 0 + 972 + 668 + + + + + 7 + 0 + + + + + 10000000 + 10000000 + + + + Grbl Controller + + + + + + + + 10 + + + 1 + + + 0 + + + + + 2 + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Port name + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + + + + + + + + + + 0 + 0 + + + + Open + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + + + + QFrame::NoFrame + + + Baud Rate + + + + + + + + + + + + + + Last State: + + + + + + + + 75 + true + + + + + + + + + + + + + + + + + + + false + + + Send File + + + + + + + + Stop + + + + + + + Qt::Horizontal + + + + 2 + 20 + + + + + + + + Choose file + + + + + + + Begin + + + + + + + + + + Check + + + true + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + 10 + + + 0 + + + %v + + + + + + + + 0 + 0 + + + + File progress + + + + + + + + 0 + 0 + + + + Queued Commands + + + + + + + + + + + false + + + Runtime: + + + + + + + false + + + + + + + + + + Lines: + + + + + + + 0 + + + + + + + + + + + + + + Command + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + 12 + + + + + + + + + false + + + Qt::ScrollBarAsNeeded + + + 16 + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QListView::Static + + + false + + + QListView::Adjust + + + QListView::SinglePass + + + false + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + 2 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + X + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Work Coordinates + + + + + + + + + + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + Y + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 10 + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 16777215 + 53 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Box + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + Z + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + C + + + Qt::AlignCenter + + + + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + 1 + + + 0 + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + Machine Coordinates + + + + + + + + 100 + 16777215 + + + + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Axis Control + + + + + + QLayout::SetDefaultConstraint + + + + + QLayout::SetMaximumSize + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 18 + 17 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + + + + 10 + 75 + true + + + + C Jog + + + Qt::AlignCenter + + + + + + + + + + + + + :/img/left.PNG:/img/left.PNG + + + + 24 + 24 + + + + + + + + + + + + :/img/right.PNG:/img/right.PNG + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 30 + + + 30 + + + + + + 0 + 0 + + + + 80 + + + 40 + + + 40 + + + Qt::Vertical + + + false + + + false + + + QSlider::TicksBelow + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + + + + + :/img/up.PNG:/img/up.PNG + + + + 24 + 24 + + + + + + + + + 10 + 75 + true + + + + Z Jog + + + Qt::AlignCenter + + + + + + + + + + + :/img/down.PNG:/img/down.PNG + + + + 24 + 24 + + + + + + + + + + + + + + + + + 0 + 0 + + + + Absolute coordinates after adjust + + + + + + + + 0 + 0 + + + + Spindle On + + + false + + + + + + + + + 0 + + + 4 + + + 0 + + + 5 + + + + + + 0 + 0 + + + + Step Size + + + + + + + + 0 + 0 + + + + + + + + + + + + + Visualizer + + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 244 + 237 + 187 + + + + + + + 244 + 237 + 187 + + + + + + + + true + + + + + + + + Advanced + + + + + 10 + 10 + 152 + 87 + + + + Reset Control + + + + + + + + + 0 + 0 + + + + Soft Reset Grbl + + + + + + + + 0 + 0 + + + + Unlock Grbl + + + + + + + + + + + 170 + 30 + 131 + 41 + + + + + 0 + 0 + + + + + 8 + + + + GRBL Settings + + + + + + + + + + + + 0 + 0 + + + + + 8 + + + + false + + + Zero Position + + + + + + + + 0 + 0 + + + + Go Home + + + + + + + Refresh Pos + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Firmware : + + + + + + + + 75 + true + + + + -1 + + + none + + + + + + + + + + + + + 0 + 0 + 972 + 23 + + + + + &Help + + + + + + &Tools + + + + + + &File + + + + + + + + + + + &About + + + + + &Options + + + + + E&xit + + + + + + + RenderArea + QWidget +
renderarea.h
+ 1 +
+
+ + + + +
diff --git a/GC-3.6.1-T3/src/makeWin.bat b/GC-3.6.1-T3/src/makeWin.bat new file mode 100644 index 0000000..0483953 --- /dev/null +++ b/GC-3.6.1-T3/src/makeWin.bat @@ -0,0 +1,18 @@ +rem May 30, 2014 +rem LETARTARE + +rem 3.6.1-Tx + +rem for release + +qmake -config release -spec win32-g++ GcodeSenderGUIthreads.pro +mingw32-make -fmakefile.release +rem release\GrblController.exe + +rem for debug + +rem qmake -config debug -spec win32-g++ GcodeSenderGUIthreads.pro +rem mingw32-make -fmakefile.debug +rem debug\GrblController.exe + +cd .. diff --git a/GC-3.6.1-T3/src/options.cpp b/GC-3.6.1-T3/src/options.cpp new file mode 100644 index 0000000..54a4cae --- /dev/null +++ b/GC-3.6.1-T3/src/options.cpp @@ -0,0 +1,286 @@ +/**************************************************************** + * options.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "options.h" +#include "ui_options.h" + +Options::Options(QWidget *parent) : + QDialog(parent), + ui(new Ui::Options) +{ + ui->setupUi(this); + + connect(ui->checkBoxUseMmManualCmds,SIGNAL(toggled(bool)),this,SLOT(toggleUseMm(bool))); + connect(ui->chkLimitZRate,SIGNAL(toggled(bool)),this,SLOT(toggleLimitZRate(bool))); + connect(ui->checkBoxFourAxis,SIGNAL(toggled(bool)),this,SLOT(toggleFourAxis(bool))); + connect(ui->checkBoxPositionReportEnabled,SIGNAL(toggled(bool)),this,SLOT(togglePosReporting(bool))); + + QSettings settings; + + QString invX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString invY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString invZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + + QString invFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + ui->chkInvFourth->setChecked(invFourth == "true"); + ui->chkInvX->setChecked(invX == "true"); + ui->chkInvY->setChecked(invY == "true"); + ui->chkInvZ->setChecked(invZ == "true"); + + // enable logging by default + QString enDebugLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + // default aggressive preload behavior to 'true'! + QString enAggressivePreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + QString enFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + char fourthAxisType = settings.value(SETTINGS_FOUR_AXIS_TYPE, FOURTH_AXIS_A).value(); + + if (enFourAxis == "false") + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + + ui->groupBoxFourthAxis->setEnabled(false); + } + else + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + + switch (fourthAxisType) + { + case FOURTH_AXIS_A: + default: + ui->radioButtonFourthAxisA->setChecked(true); + break; + case FOURTH_AXIS_B: + ui->radioButtonFourthAxisB->setChecked(true); + break; + case FOURTH_AXIS_C: + ui->radioButtonFourthAxisC->setChecked(true); + break; +/// LETARTARE + case FOURTH_AXIS_U: + ui->radioButtonFourthAxisU->setChecked(true); + break; + case FOURTH_AXIS_V: + ui->radioButtonFourthAxisV->setChecked(true); + break; + case FOURTH_AXIS_W: + ui->radioButtonFourthAxisW->setChecked(true); + break; +/// <-- + } + } + + ui->checkBoxEnableDebugLog->setChecked(enDebugLog == "true"); + ui->chkAggressivePreload->setChecked(enAggressivePreload == "true"); + //ui->checkBoxWaitForJogToComplete->setChecked(waitForJogToComplete == "true"); + ui->checkBoxWaitForJogToComplete->hide(); + ui->checkBoxUseMmManualCmds->setChecked(useMmManualCmds == "true"); + ui->checkBoxFourAxis->setChecked(enFourAxis == "true"); + + int waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + ui->spinResponseWaitSec->setValue(waitTime); + + double zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + ui->doubleSpinZJogRate->setValue(zJogRate); + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + ui->chkLimitZRate->setChecked(zRateLimit == "true"); + + double zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + ui->doubleSpinZRateLimit->setValue(zRateLimitAmount); + double xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + ui->doubleSpinXYRate->setValue(xyRateAmount); + + if (!ui->chkLimitZRate->isChecked()) + { + ui->doubleSpinZRateLimit->setEnabled(false); + ui->doubleSpinXYRate->setEnabled(false); + } + + QString ffCmd = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + ui->chkFilterFileCommands->setChecked(ffCmd == "true"); + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + ui->checkBoxReducePrecForLongLines->setChecked(rPrecision == "true"); + ui->spinBoxGrblLineBufferSize->setValue(settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value()); + ui->spinBoxCharSendDelay->setValue(settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value()); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + QString posReqType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_NOT_WHEN_MANUAL).value(); + double posRateFreqSec = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + + ui->checkBoxPositionReportEnabled->setChecked(enPosReq == "true"); + ui->doubleSpinBoxPosRequestFreqSec->setValue(posRateFreqSec); + if (posReqType == PREQ_NOT_WHEN_MANUAL) + { + ui->radioButton_ReqNotDuringManual->setChecked(true); + } + else if (posReqType == PREQ_ALWAYS) + { + ui->radioButton_ReqAlways->setChecked(true); + } + else + { + ui->radioButton_ReqAlwaysNoIdleCheck->setChecked(true); + } + + togglePosReporting(enPosReq == "true"); + +} + +Options::~Options() +{ + delete ui; +} + +void Options::accept() +{ + QSettings settings; + + settings.setValue(SETTINGS_INVERSE_X, ui->chkInvX->isChecked()); + settings.setValue(SETTINGS_INVERSE_Y, ui->chkInvY->isChecked()); + settings.setValue(SETTINGS_INVERSE_Z, ui->chkInvZ->isChecked()); + settings.setValue(SETTINGS_INVERSE_FOURTH, ui->chkInvFourth->isChecked()); + settings.setValue(SETTINGS_ENABLE_DEBUG_LOG, ui->checkBoxEnableDebugLog->isChecked()); + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, ui->chkAggressivePreload->isChecked()); + settings.setValue(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, ui->checkBoxWaitForJogToComplete->isChecked()); + settings.setValue(SETTINGS_USE_MM_FOR_MANUAL_CMDS, ui->checkBoxUseMmManualCmds->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_USE, ui->checkBoxFourAxis->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_TYPE, getFourthAxisType()); + + settings.setValue(SETTINGS_RESPONSE_WAIT_TIME, ui->spinResponseWaitSec->value()); + settings.setValue(SETTINGS_Z_JOG_RATE, ui->doubleSpinZJogRate->value()); + + settings.setValue(SETTINGS_Z_RATE_LIMIT, ui->chkLimitZRate->isChecked()); + settings.setValue(SETTINGS_Z_RATE_LIMIT_AMOUNT, ui->doubleSpinZRateLimit->value()); + settings.setValue(SETTINGS_XY_RATE_AMOUNT, ui->doubleSpinXYRate->value()); + + settings.setValue(SETTINGS_FILTER_FILE_COMMANDS, ui->chkFilterFileCommands->isChecked()); + settings.setValue(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, ui->checkBoxReducePrecForLongLines->isChecked()); + settings.setValue(SETTINGS_GRBL_LINE_BUFFER_LEN, ui->spinBoxGrblLineBufferSize->value()); + settings.setValue(SETTINGS_CHAR_SEND_DELAY_MS, ui->spinBoxCharSendDelay->value()); + + settings.setValue(SETTINGS_ENABLE_POS_REQ, ui->checkBoxPositionReportEnabled->isChecked()); + settings.setValue(SETTINGS_TYPE_POS_REQ, getPosReqType()); + settings.setValue(SETTINGS_POS_REQ_FREQ_SEC, ui->doubleSpinBoxPosRequestFreqSec->value()); + + connect(this, SIGNAL(setSettings()), parentWidget(), SLOT(setSettings())); + + emit setSettings(); + this->close(); +} + +void Options::toggleUseMm(bool useMm) +{ + double zJogRate = ui->doubleSpinZJogRate->value(); + double zRateLimit = ui->doubleSpinZRateLimit->value(); + double xyRate = ui->doubleSpinXYRate->value(); + + if (useMm) + { + ui->doubleSpinZJogRate->setValue(zJogRate * MM_IN_AN_INCH); + ui->doubleSpinZRateLimit->setValue(zRateLimit * MM_IN_AN_INCH); + ui->doubleSpinXYRate->setValue(xyRate * MM_IN_AN_INCH); + } + else + { + ui->doubleSpinZJogRate->setValue(zJogRate / MM_IN_AN_INCH); + ui->doubleSpinZRateLimit->setValue(zRateLimit / MM_IN_AN_INCH); + ui->doubleSpinXYRate->setValue(xyRate / MM_IN_AN_INCH); + } +} + +void Options::toggleLimitZRate(bool limitZ) +{ + ui->doubleSpinZRateLimit->setEnabled(limitZ); + ui->doubleSpinXYRate->setEnabled(limitZ); +} + +void Options::toggleFourAxis(bool four) +{ + if (four) + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + } + else + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->groupBoxFourthAxis->setEnabled(false); + } + +} + +void Options::togglePosReporting(bool usePosReporting) +{ + if (usePosReporting) + { + ui->groupBox_ReqPos->setEnabled(true); + } + else + { + ui->groupBox_ReqPos->setEnabled(false); + } +} + +char Options::getFourthAxisType() +{ + char type = FOURTH_AXIS_A; + + if (ui->radioButtonFourthAxisA->isChecked()) + { + type = FOURTH_AXIS_A; + } + else + if (ui->radioButtonFourthAxisB->isChecked()) + { + type = FOURTH_AXIS_B; + } + else + if (ui->radioButtonFourthAxisC->isChecked()) + { + type = FOURTH_AXIS_C; + } +/// LETATARE + if (ui->radioButtonFourthAxisU->isChecked()) + { + type = FOURTH_AXIS_U; + } + else + if (ui->radioButtonFourthAxisV->isChecked()) + { + type = FOURTH_AXIS_V; + } + else + if (ui->radioButtonFourthAxisW->isChecked()) + { + type = FOURTH_AXIS_W; + } +/// <-- + return type; +} + +QString Options::getPosReqType() +{ + if (ui->radioButton_ReqAlways->isChecked()) + { + return PREQ_ALWAYS; + } + else if (ui->radioButton_ReqNotDuringManual->isChecked()) + { + return PREQ_NOT_WHEN_MANUAL; + } + return PREQ_ALWAYS_NO_IDLE_CHK; +} diff --git a/GC-3.6.1-T3/src/options.h b/GC-3.6.1-T3/src/options.h new file mode 100644 index 0000000..c97ea62 --- /dev/null +++ b/GC-3.6.1-T3/src/options.h @@ -0,0 +1,89 @@ +/**************************************************************** + * options.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include +#include +#include +#include +#include + +#include "definitions.h" + +#define SETTINGS_INVERSE_FOURTH "inverse.c"// leave as 'c' for backwards compat +#define SETTINGS_INVERSE_X "inverse.x" +#define SETTINGS_INVERSE_Y "inverse.y" +#define SETTINGS_INVERSE_Z "inverse.z" +#define SETTINGS_RESPONSE_WAIT_TIME "responseWaitTime" +#define SETTINGS_Z_JOG_RATE "zJogRate" +#define SETTINGS_ENABLE_DEBUG_LOG "debugLog" +#define SETTINGS_USE_AGGRESSIVE_PRELOAD "aggressivePreload" +#define SETTINGS_WAIT_FOR_JOG_TO_COMPLETE "waitForJogToComplete" +#define SETTINGS_USE_MM_FOR_MANUAL_CMDS "useMMForManualCommands" +#define SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ "absCoordForManualAfterAxisAdj" +#define SETTINGS_Z_RATE_LIMIT "zRateLimit" +#define SETTINGS_Z_RATE_LIMIT_AMOUNT "zRateLimitAmount" +#define SETTINGS_XY_RATE_AMOUNT "xyRateAmount" +#define SETTINGS_FOUR_AXIS_USE "fourAxis" +#define SETTINGS_FOUR_AXIS_TYPE "fourAxisType" + +#define SETTINGS_FILE_OPEN_DIALOG_STATE "fileopendialogstate" +#define SETTINGS_NAME_FILTER "namefilter" +#define SETTINGS_DIRECTORY "directory" +#define SETTINGS_PORT "port" +#define SETTINGS_BAUD "baud" + +#define SETTINGS_PROMPTED_AGGR_PRELOAD "promptedAggrPreload" + +#define SETTINGS_FILTER_FILE_COMMANDS "filterFileCommands" +#define SETTINGS_REDUCE_PREC_FOR_LONG_LINES "reducePrecisionForLongLines" +#define SETTINGS_GRBL_LINE_BUFFER_LEN "grblLineBufferLen" +#define SETTINGS_CHAR_SEND_DELAY_MS "charSendDelayMs" +#define SETTINGS_JOG_STEP "jogStep" + +#define SETTINGS_ENABLE_POS_REQ "positionRequest" +#define SETTINGS_TYPE_POS_REQ "posRequestType" +#define SETTINGS_POS_REQ_FREQ_SEC "posReqFreqSec" + + +namespace Ui { +class Options; +} + +class Options : public QDialog +{ + Q_OBJECT + +public: + explicit Options(QWidget *parent = 0); + ~Options(); + void accept(); + +signals: + void setSettings(); + +private slots: + void toggleUseMm(bool useMm); + void toggleLimitZRate(bool limitZ); + void toggleFourAxis(bool four); + void togglePosReporting(bool usePosReporting); + +private: + char getFourthAxisType(); + QString getPosReqType(); +private: + Ui::Options *ui; + //variables + int settings; + +}; + +#endif // OPTIONS_H diff --git a/GC-3.6.1-T3/src/options.ui b/GC-3.6.1-T3/src/options.ui new file mode 100644 index 0000000..e4edec0 --- /dev/null +++ b/GC-3.6.1-T3/src/options.ui @@ -0,0 +1,711 @@ + + + Options + + + + 0 + 0 + 521 + 317 + + + + Options + + + + + 10 + 10 + 501 + 261 + + + + 0 + + + + General + + + + + 10 + 146 + 451 + 71 + + + + + + + Z-Jog Rate (inches or mm/min) + + + + + + + Seconds to Wait for Response + + + + + + + 1 + + + 1000 + + + 60 + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 260.000000000000000 + + + + + + + + + 10 + 10 + 451 + 121 + + + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + + + Use aggressive preload strategy for Grbl + + + + + + + false + + + Wait for each jog/manual command to complete (future feature) + + + + + + + Write debugging log to home folder (requires restart) + + + + + + + + + Filtering + + + + + 10 + 10 + 471 + 81 + + + + Z Rate Limiting + + + + + 20 + 20 + 451 + 53 + + + + + + + Limit Z Rate + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 100.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Z-Rate Limit (inches or mm/min) + + + + + + + XY Rate (inches or mm/min) + + + + + + + 2 + + + 0.100000000000000 + + + 999999.989999999990687 + + + 2000.000000000000000 + + + + + + + + + + 10 + 200 + 261 + 24 + + + + + + + Character send delay ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 100 + 461 + 61 + + + + Command Filtering + + + + + 30 + 20 + 431 + 17 + + + + Filter file commands before sending + + + + + + 30 + 40 + 431 + 17 + + + + Selectively reduce precision for excessively long lines + + + + + + + 10 + 170 + 261 + 24 + + + + + + + Grbl Line Buffer Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 270 + 200 + 50 + 22 + + + + 20 + + + 10 + + + + + + 270 + 170 + 50 + 22 + + + + 50 + + + + + + Axis + + + + + 10 + 111 + 451 + 60 + + + + Invert Axis + + + + + 20 + 20 + 431 + 31 + + + + + + + X Axis + + + + + + + Y Axis + + + + + + + Z Axis + + + + + + + Fourth Axis + + + + + + + + + + 10 + 41 + 451 + 51 + + + + Selecting the Fourth axis + + + + + 10 + 22 + 50 + 17 + + + + A + + + true + + + + + + 80 + 22 + 50 + 17 + + + + B + + + + + + 150 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + C + + + + + + 240 + 20 + 50 + 21 + + + + Qt::PreventContextMenu + + + U + + + + + + 310 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + V + + + + + + 380 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + W + + + + + + + 10 + 11 + 421 + 17 + + + + Enable 4-axis mode + + + + + + Display + + + + + 10 + 10 + 481 + 141 + + + + + + + Enable position request and report + + + + + + + Position Request + + + + + 10 + 20 + 461 + 93 + + + + + + + Always Request (most reliable/slightly slower jogging) + + + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + + + Not during manual control (no position update during jog/manual) + + + + + + + + + Request frequency (seconds) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0.500000000000000 + + + 10.000000000000000 + + + 0.500000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + + + + + 320 + 280 + 191 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + Options + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Options + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GC-3.6.1-T3/src/pointitem.cpp b/GC-3.6.1-T3/src/pointitem.cpp new file mode 100644 index 0000000..c0a3db9 --- /dev/null +++ b/GC-3.6.1-T3/src/pointitem.cpp @@ -0,0 +1,41 @@ +#include "pointitem.h" + +PointItem::PointItem(double x1, double y1) + : ItemToBase(0), x(x1), y(y1) +{ +} + +void PointItem::moveToFirst(QPainterPath& path) +{ + Q_UNUSED(path); +} + +void PointItem::addToPath(QPainterPath& path) +{ + Q_UNUSED(path); +} + +PosItem PointItem::computeExtents() +{ + return PosItem(); +} + +double PointItem::getXScr() +{ + return screenX(x); +} + +double PointItem::getYScr() +{ + return screenY(y); +} + +double PointItem::getXRaw() +{ + return x; +} + +double PointItem::getYRaw() +{ + return y; +} diff --git a/GC-3.6.1-T3/src/pointitem.h b/GC-3.6.1-T3/src/pointitem.h new file mode 100644 index 0000000..6adacf5 --- /dev/null +++ b/GC-3.6.1-T3/src/pointitem.h @@ -0,0 +1,23 @@ +#ifndef POINTITEM_H +#define POINTITEM_H +#include "itemtobase.h" + +class PointItem : public ItemToBase +{ +public: + PointItem(double x, double y); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; +}; + +#endif // POINTITEM_H diff --git a/GC-3.6.1-T3/src/positem.cpp b/GC-3.6.1-T3/src/positem.cpp new file mode 100644 index 0000000..053a35f --- /dev/null +++ b/GC-3.6.1-T3/src/positem.cpp @@ -0,0 +1,48 @@ +#include "positem.h" + +void PosItem::setCoords(double x1, double y1, double i1, double j1) +{ + x = x1; + y = y1; + i = i1; + j = j1; +} + +void PosItem::setCoords(double x1, double y1, bool mm1) +{ + x = x1; + y = y1; + i = x1; + j = y1; + mm = mm1; +} + +void PosItem::expand(const PosItem& item) +{ + if (item.x < x) + x = item.x; + if (item.y < y) + y = item.y; + if (item.i > i) + i = item.i; + if (item.j > j) + j = item.j; +} + +void PosItem::toMm() +{ + x *= MM_IN_AN_INCH; + y *= MM_IN_AN_INCH; + i *= MM_IN_AN_INCH; + j *= MM_IN_AN_INCH; + mm = true; +} + +void PosItem::toInches() +{ + x /= MM_IN_AN_INCH; + y /= MM_IN_AN_INCH; + i /= MM_IN_AN_INCH; + j /= MM_IN_AN_INCH; + mm = false; +} diff --git a/GC-3.6.1-T3/src/positem.h b/GC-3.6.1-T3/src/positem.h new file mode 100644 index 0000000..aaea573 --- /dev/null +++ b/GC-3.6.1-T3/src/positem.h @@ -0,0 +1,45 @@ +#ifndef POSITEM_H +#define POSITEM_H +#include +//#include "stdio.h" +#include "definitions.h" + +class PosItem +{ +public: + PosItem() + : x(0), y(0), i(0), j(0), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1) + : x(x1), y(y1), i(0), j(0), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1) + : x(x1), y(y1), i(i1), j(j1), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1, bool arc1, bool cw1, bool mm1, int index1) + : x(x1), y(y1), i(i1), j(j1), + arc(arc1), cw(cw1), mm(mm1), index(index1) {} + + void setCoords(double x1, double y1, double i1, double j1); + void setCoords(double x1, double y1, bool mm); + void expand(const PosItem& item); + double width() { return qAbs(i - x); } + double height() { return qAbs(j - y); } + bool isNull() { return x == 0 && y == 0 && i == 0 && j == 0 && arc == false && cw == false && index == 0; } + void toMm(); + void toInches(); + +public: + double x; + double y; + double i; + double j; + bool arc; + bool cw; + bool mm; + int index; +}; + +Q_DECLARE_METATYPE ( PosItem ) + +#endif // POSITEM_H diff --git a/GC-3.6.1-T3/src/qrc_images.cpp b/GC-3.6.1-T3/src/qrc_images.cpp new file mode 100644 index 0000000..5a4150a --- /dev/null +++ b/GC-3.6.1-T3/src/qrc_images.cpp @@ -0,0 +1,335 @@ +/**************************************************************************** +** Resource object code +** +** Created: Tue Mar 20 13:24:20 2012 +** by: The Resource Compiler for Qt version 4.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // /home/kosme/Dropbox/GcodeSender/Threaded V2/GrblController/img/down.gif + 0x0,0x0,0x0,0xbe, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xc0,0xc0,0xc0,0x99,0x99,0x99,0x40,0x40,0x40,0xe0,0xe0, + 0xe0,0x10,0x10,0x10,0x80,0x80,0x80,0xb0,0xb0,0xb0,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6b, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x95,0x2,0x9c, + 0x68,0xaa,0xae,0xa8,0x72,0x1d,0x6c,0xcc,0x1e,0x18,0x21,0xdf,0x28,0x91,0x15,0xb8, + 0x5c,0x68,0x6,0x58,0x4f,0x75,0x30,0x6c,0x6c,0xc3,0x94,0x8e,0xc3,0x4b,0x2,0x7e, + 0x1d,0x83,0x13,0x60,0xf4,0x20,0x92,0x88,0xd0,0xa2,0xb7,0x10,0x31,0x7a,0x8c,0xd1, + 0x55,0x96,0x25,0x9,0x62,0x2,0x92,0x64,0x10,0x1b,0xa8,0x25,0x8d,0x55,0xe3,0x3d, + 0x39,0xa3,0xd2,0xf4,0x75,0xca,0x9d,0x97,0x4,0x4e,0x1,0x7d,0x14,0x7,0x34,0x82, + 0x13,0x9,0x9,0x86,0x8a,0x8b,0x8c,0x8d,0x8e,0x8c,0x11,0x0,0x3b, + // /home/kosme/Dropbox/GcodeSender/Threaded V2/GrblController/img/logotiny.gif + 0x0,0x0,0xa,0x7f, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x96,0x0,0x37,0x0,0xe6,0x0,0x0,0x10,0x14,0x83,0x7b, + 0x7d,0xbb,0xd1,0xd2,0xe7,0x41,0x43,0x9c,0xb0,0xb2,0xd6,0x5c,0x60,0xab,0x99,0x99, + 0xcc,0xef,0xef,0xf7,0x33,0x33,0x99,0xc6,0xc7,0xe2,0x4d,0x51,0xa3,0x6b,0x6e,0xb3, + 0x38,0x3b,0x97,0x2b,0x2f,0x92,0x89,0x8b,0xc1,0xe1,0xe2,0xf0,0xa8,0xaa,0xd2,0xf6, + 0xf6,0xfa,0xbd,0xbe,0xdd,0x28,0x2c,0x90,0x72,0x73,0xb5,0xda,0xdb,0xec,0x54,0x58, + 0xa6,0xff,0xff,0xff,0x22,0x27,0x8c,0x47,0x4a,0x9f,0x83,0x85,0xbe,0x3a,0x3f,0x98, + 0xa0,0xa2,0xce,0x62,0x64,0xac,0x8e,0x91,0xc4,0xc0,0xc2,0xdf,0xb7,0xb8,0xda,0xe7, + 0xe7,0xf3,0x57,0x5a,0xa7,0x26,0x2a,0x8e,0x75,0x78,0xb7,0x43,0x47,0x9d,0x66,0x6a, + 0xaf,0xf8,0xf8,0xfc,0x87,0x89,0xc0,0x6e,0x71,0xb4,0xd7,0xd8,0xeb,0x1c,0x20,0x89, + 0x4a,0x4d,0xa1,0x52,0x54,0xa5,0x33,0x33,0x99,0xce,0xce,0xe5,0x92,0x94,0xc6,0x5a, + 0x5d,0xaa,0x7e,0x81,0xbc,0xad,0xae,0xd5,0xb5,0xb5,0xd8,0x8b,0x8d,0xc3,0xb8,0xba, + 0xdb,0xc4,0xc5,0xe0,0xa4,0xa5,0xd0,0x7b,0x7b,0xb5,0xd4,0xd5,0xe8,0x68,0x6b,0xb0, + 0x3a,0x3d,0x99,0x3d,0x41,0x9b,0xe5,0xe6,0xf1,0xea,0xeb,0xf4,0xde,0xde,0xee,0x17, + 0x1b,0x86,0x20,0x24,0x8b,0xc9,0xca,0xe3,0xef,0xf7,0xf7,0xa5,0xad,0xce,0x13,0x17, + 0x85,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x47,0x0,0x2c,0x0,0x0,0x0,0x0,0x96,0x0,0x37,0x0,0x0,0x7,0xff, + 0x80,0x47,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x83,0x27,0x7,0x15,0x43, + 0x20,0x38,0x1e,0x32,0x29,0x5,0x2d,0x19,0x1b,0x1b,0xd,0x23,0x9c,0x23,0xd,0xc, + 0xc,0x19,0x2d,0x5,0x29,0x32,0x1e,0x38,0x34,0x9,0x15,0x3f,0x27,0x8b,0xae,0xaf, + 0xb0,0xb1,0xb2,0xb3,0x89,0x27,0x21,0x3a,0x1f,0x33,0x30,0x1,0x3b,0x22,0x19,0x3d, + 0xa0,0xc1,0xc2,0x8,0xa0,0x3c,0x99,0x99,0x3c,0xa0,0x8,0xcb,0xcc,0xcd,0x1b,0x19, + 0x22,0x3b,0x1,0x30,0x10,0x12,0x3a,0x21,0x11,0xb4,0xda,0xdb,0xdc,0xb0,0x3f,0x2f, + 0x33,0x35,0x3b,0x2c,0xca,0xcc,0xa1,0x31,0x29,0x1a,0x30,0x38,0x4,0x12,0x43,0x3a, + 0x15,0xf,0x21,0x3f,0x7,0xf5,0x11,0xf7,0x11,0xf5,0x7,0x3f,0x21,0xf,0x15,0x3a, + 0x43,0x3e,0xd0,0xc0,0x1,0x43,0x3,0x85,0x2,0xe4,0x9a,0x2d,0xcb,0x60,0xc2,0xc1, + 0x8c,0x17,0x21,0x2e,0x74,0x9b,0x48,0x51,0xd1,0x9,0x20,0x20,0x3c,0x74,0x0,0xc6, + 0xac,0x47,0x8c,0x0,0x6,0x68,0xbc,0x0,0x72,0xa0,0x62,0xac,0x3,0xf,0x5e,0x80, + 0x30,0x10,0x20,0x46,0x8f,0x66,0x3c,0xa,0x38,0xa0,0x51,0xa1,0x95,0xc9,0x9b,0xb2, + 0xe,0x24,0x80,0xd1,0x81,0x41,0x47,0x13,0x1e,0x40,0xe8,0x28,0x89,0xf3,0xe6,0x1, + 0x15,0x36,0x60,0x2c,0x28,0xd1,0xac,0x80,0x87,0xf,0x3f,0x8a,0x4a,0x1d,0x14,0x21, + 0x81,0x7,0xb,0x1d,0x53,0x70,0x18,0x12,0x75,0xaa,0x57,0x42,0x7,0x5e,0xe0,0x20, + 0xc1,0x74,0x99,0x2,0x14,0x1f,0x88,0x7e,0xdd,0xf6,0x0,0x42,0x7,0x66,0x2c,0xff, + 0x34,0xd8,0xf0,0xb1,0xb6,0x6e,0xa2,0x10,0x12,0x50,0x28,0x60,0x56,0x80,0x3,0x10, + 0xbb,0xaf,0x80,0x18,0x68,0xb1,0x8c,0x7,0x9,0x1a,0x21,0x0,0x2b,0x5e,0xf4,0x43, + 0x82,0x8c,0x1,0x66,0x61,0xa8,0x58,0x4c,0xe8,0x7,0x4,0xb,0xd,0x1a,0x64,0x80, + 0x21,0x80,0xb2,0xe7,0x57,0x2a,0xc,0xec,0x45,0xa0,0x80,0x43,0x62,0xc0,0x2f,0x48, + 0x2c,0x2b,0x21,0xf9,0xb3,0xeb,0x58,0x82,0x59,0x2c,0x5b,0x90,0x60,0x2d,0x8d,0x16, + 0xd,0x10,0x90,0x18,0xf2,0xba,0xf7,0x2c,0x1,0x32,0x18,0x34,0x60,0x31,0xc3,0xa6, + 0xc9,0x13,0x33,0x4a,0x34,0x18,0xc0,0xa1,0xab,0xef,0xe7,0x27,0x21,0x64,0x40,0xb0, + 0x1,0x87,0xf1,0x6e,0x20,0x32,0x34,0x68,0x21,0x1,0xba,0x77,0x6d,0x12,0xb0,0xf6, + 0x98,0xd1,0x4d,0x47,0x1,0xcd,0x34,0x7c,0x1c,0xf0,0xf1,0xe0,0x1,0xce,0x1f,0xed, + 0xdb,0xab,0xfd,0x8e,0x53,0x82,0x82,0x6,0x16,0x5e,0x68,0x83,0xb1,0x8c,0x83,0xa0, + 0x1,0x99,0x7d,0x42,0x97,0x49,0x32,0x34,0x63,0x0,0x7d,0x5e,0x41,0xb0,0xc,0xa, + 0xd7,0x2d,0xf2,0x0,0x66,0x29,0x9c,0x76,0xc0,0x6,0x13,0x54,0x88,0xc0,0x80,0x15, + 0x5,0x30,0x41,0x80,0x7,0x22,0x38,0xd5,0x1,0x1,0xc,0x37,0x99,0x2b,0x1f,0x2c, + 0x43,0x0,0x21,0x11,0xf4,0x50,0xe1,0x4,0x17,0xde,0x24,0x43,0x80,0xd,0x74,0xe8, + 0xe1,0x54,0x12,0x2c,0x43,0xc3,0x22,0x33,0x20,0x90,0x41,0x5,0x85,0xa4,0xb8,0x62, + 0x8b,0x4,0xc2,0x28,0xe3,0x8c,0x52,0xf9,0x80,0x99,0x7f,0x88,0xcc,0xd0,0x40,0xff, + 0xc,0xf3,0x9,0xe2,0xa3,0x85,0x18,0x52,0xf4,0x22,0x87,0x44,0x7e,0x75,0xc2,0x2, + 0x31,0x1e,0xf2,0xc1,0x92,0xd9,0x18,0xf2,0x24,0x8b,0x51,0x4e,0x34,0x65,0x66,0x43, + 0x56,0x29,0x15,0x96,0x27,0x12,0x12,0x42,0x28,0x5d,0x7a,0xa9,0x22,0x94,0x2e,0xa, + 0xe9,0xdd,0x9,0x6d,0xda,0x75,0x2,0x56,0x3c,0xe,0xb2,0x43,0x3,0x23,0x1e,0xf2, + 0x25,0x90,0x15,0x69,0x20,0xe7,0x21,0x74,0x36,0xf8,0xca,0x3d,0xb4,0x90,0xc0,0x0, + 0xc,0xdb,0xe0,0x53,0xe7,0x22,0x3e,0x20,0x20,0xc2,0x20,0x2f,0x20,0xe0,0x81,0x22, + 0x7f,0x86,0xa9,0x4d,0x4,0x2a,0xcc,0xd0,0xc2,0x86,0x64,0x1e,0xf1,0xc3,0x7,0x2c, + 0x75,0xa0,0x40,0x9,0x3d,0xa4,0x2a,0x8a,0x9,0x32,0x70,0x0,0x15,0x21,0x2,0x40, + 0x80,0xc2,0x2,0x22,0xb0,0x30,0x40,0xaa,0x25,0x28,0x50,0x0,0x5,0x1e,0x10,0xd0, + 0xe7,0x11,0x78,0x95,0x7a,0x49,0x66,0x8,0xb0,0x60,0xc1,0xe,0x1a,0xe0,0x90,0x40, + 0x93,0x47,0xe0,0xb0,0x80,0x25,0x2c,0x94,0x70,0x6b,0xaa,0x3d,0xc,0x90,0xab,0x8, + 0x26,0x4,0x90,0xe7,0x21,0x38,0x34,0xd0,0xdd,0x11,0x29,0x30,0xf0,0xa8,0x21,0x6f, + 0xb2,0xc8,0xac,0x2b,0x8e,0x7c,0x80,0x83,0xc,0x5,0xbc,0x4,0x63,0xa8,0x82,0xae, + 0xf8,0x6e,0x66,0xf2,0xa2,0x30,0x88,0xa,0xc2,0x55,0x38,0x6f,0x3,0x2b,0x4e,0xb0, + 0x81,0x5a,0x24,0xf0,0xab,0xef,0xbc,0xf2,0x96,0x79,0x44,0x7,0x18,0xfc,0x88,0xc0, + 0xbe,0x2b,0x82,0xa0,0xc8,0x0,0x5,0x1c,0x1,0x4,0x3,0x32,0x8,0x62,0x40,0xff, + 0xa,0x14,0x64,0xac,0x31,0x5,0xb,0x2c,0x1c,0xe0,0xe,0x1b,0x87,0x1c,0xf2,0xe, + 0x1d,0x58,0x50,0x2,0x28,0xf4,0xe,0xfc,0xee,0x81,0x1a,0x4c,0x50,0x2,0xa,0x38, + 0xd8,0x30,0x84,0x0,0x3a,0x8,0x90,0x0,0xd,0x1c,0x3c,0x36,0x81,0xbd,0x82,0xa8, + 0x90,0x59,0xa,0x6,0x10,0x70,0xc3,0xb,0x3a,0x0,0x24,0x1,0x4,0x1e,0xa4,0x60, + 0x2b,0xc0,0x23,0x64,0x0,0xb3,0xcc,0x5,0x4c,0x40,0xc2,0xcd,0x2c,0x51,0x68,0xf0, + 0x2,0x23,0x98,0x20,0x33,0x3c,0xed,0x1,0xa1,0x82,0xcd,0x36,0x40,0xb0,0x4b,0x67, + 0x89,0xf0,0x67,0x15,0x2,0x1f,0x8,0x12,0xf5,0xbe,0x6c,0xb7,0xfd,0x6e,0xbf,0x6c, + 0xc3,0xcd,0xf2,0x4,0x1,0x2c,0x42,0xc2,0xce,0xf7,0x7e,0x22,0xd1,0x22,0xd7,0x91, + 0x30,0x42,0xd,0x84,0xa4,0x30,0x1,0xa3,0x83,0x98,0x30,0x81,0xc1,0x14,0x8c,0x60, + 0xb0,0x36,0x2,0x20,0x90,0x42,0xc,0xc,0xfc,0x75,0xc4,0xe,0xa0,0xba,0x6d,0xf9, + 0xe5,0xf3,0x96,0xb0,0x0,0xc,0x4,0xbc,0x50,0x52,0xcb,0x24,0x2c,0x42,0x1,0xde, + 0x3d,0x67,0x6,0x81,0xd,0x20,0xa4,0xae,0xfa,0xea,0x36,0xdc,0x40,0x88,0xdf,0x1a, + 0x10,0xb2,0xc0,0x4,0x97,0x16,0x7e,0xb8,0x20,0x36,0x10,0x40,0x3,0xd,0x16,0x8c, + 0xb0,0xc3,0xee,0xc0,0x7,0xdf,0xb9,0x37,0xa0,0xec,0x75,0x1a,0xe5,0x98,0x27,0x9f, + 0x7c,0x6,0x24,0xe0,0xf0,0x42,0x57,0xa0,0x8b,0x4e,0xfa,0x11,0x3e,0x7b,0x72,0xf9, + 0xbf,0x83,0xc0,0x2e,0x3b,0xed,0x84,0x74,0x70,0xfb,0x1,0xc,0xf4,0x2b,0xfe,0xff, + 0xf8,0x13,0x98,0x0,0x4b,0x4,0x1b,0x60,0x10,0x3,0x2,0x92,0x9f,0xa7,0xbc,0xf2, + 0x70,0x13,0xac,0x2f,0x3,0xfe,0x45,0xaf,0xc8,0xe8,0x3c,0x4b,0x1c,0x6d,0x9,0xfc, + 0xf7,0xef,0xff,0x2f,0x13,0x60,0x0,0xd3,0x62,0x37,0x88,0xd9,0xd5,0x4e,0x10,0xde, + 0x3b,0x50,0x4,0x62,0xc0,0x2,0x16,0x28,0x20,0x7c,0x3c,0x50,0x40,0x3,0x27,0x38, + 0xc1,0xc,0x0,0xee,0x15,0x3f,0x0,0x5,0x7f,0xbe,0xf5,0x1,0x8,0x78,0xf0,0x83, + 0x1e,0xe4,0x80,0x70,0x38,0x4,0xc2,0x12,0x82,0x10,0x7,0x6,0xf0,0x0,0x9,0x3a, + 0x40,0x8e,0x7c,0xa9,0x4c,0x4e,0xf6,0x4b,0x4,0xfe,0xe,0x71,0x81,0x13,0xd8,0xf0, + 0x86,0x36,0xbc,0xc0,0xb,0x3e,0x31,0xc0,0xed,0x1d,0xf0,0x60,0xb7,0x3b,0xc2,0x5, + 0x86,0x78,0x81,0x14,0x60,0xc0,0x3,0x44,0x4c,0x22,0x11,0x63,0x51,0x29,0x12,0x3c, + 0x80,0x1,0x75,0x5b,0x44,0xb9,0x10,0x30,0xae,0x57,0x1c,0x40,0x7,0x4,0x40,0x41, + 0x1,0x78,0xb0,0xaf,0xb9,0xa5,0xc0,0x50,0x8c,0x98,0x5d,0xfe,0x7e,0x0,0x2,0x20, + 0x80,0x71,0x10,0x9,0xe0,0x61,0xf6,0x46,0x40,0x40,0x41,0x18,0xb0,0x7b,0x41,0xc, + 0xdc,0x8,0x7e,0x88,0x88,0x8,0xf8,0xa0,0x8a,0x83,0xf0,0x0,0x2,0x78,0xa3,0x9a, + 0x73,0x51,0x65,0x8a,0x9a,0xa2,0x45,0x58,0x38,0xc0,0x82,0xca,0x1d,0x48,0x6,0x1b, + 0x1a,0x80,0x8,0x16,0x10,0x0,0x7,0xd4,0xa0,0x6,0x94,0x88,0x1,0x80,0xd8,0x38, + 0x8,0x1d,0x2c,0x63,0x3,0x16,0x48,0x87,0x7,0xc,0x60,0x80,0x82,0xa4,0xc0,0xff, + 0x2,0xc,0x18,0x81,0x0,0xd7,0xd8,0x46,0x20,0x96,0x32,0x81,0x86,0xc0,0x5a,0xf, + 0x48,0x41,0x2,0xd,0x38,0xc0,0x1,0x28,0x90,0x1,0x9,0x9e,0xa5,0x80,0x4c,0xe8, + 0x7,0x11,0x27,0xe8,0x41,0x7,0x4,0x21,0x80,0x6,0xe4,0xcf,0x4f,0x80,0xbc,0x89, + 0xa0,0xa8,0xc4,0x1,0xc8,0x8,0x8c,0x7c,0x2c,0x2a,0x1,0xe,0x6,0xf1,0x80,0xbd, + 0xa4,0x8c,0x7c,0xb9,0x11,0x41,0x9b,0x16,0x80,0x81,0x28,0xa,0x2,0x2,0x32,0xf8, + 0x96,0x20,0x62,0x30,0xc7,0x54,0x3e,0x13,0x99,0x15,0x62,0x0,0xd9,0xe,0x61,0x80, + 0x6,0xb8,0x4e,0x10,0x29,0x68,0xc0,0x38,0xdd,0xf4,0xa3,0x40,0x6e,0x63,0x4c,0xd, + 0x40,0x92,0xa8,0x54,0xc2,0x1,0x18,0x38,0xc0,0x95,0x30,0xe0,0x80,0x48,0x9c,0x3, + 0x16,0x15,0x48,0x80,0x20,0xb1,0x94,0x1,0xa,0xd6,0x21,0x1,0x15,0x34,0x69,0x6, + 0x1,0x70,0x98,0x22,0x38,0x10,0x80,0x73,0x82,0x45,0x0,0x12,0x98,0x41,0x3d,0x3d, + 0x70,0x4f,0x57,0x7a,0x20,0x9f,0x4,0x48,0x80,0xe4,0xe,0x1,0x4,0x4,0x44,0x6c, + 0x10,0x7,0x48,0x15,0x3f,0x51,0x14,0x4c,0x93,0x84,0x28,0x40,0x35,0x60,0x8f,0xf, + 0xe8,0x71,0x80,0x7b,0xe8,0xc3,0xa5,0xfb,0x60,0x4f,0x7c,0x1e,0xb0,0x52,0x7b,0xe4, + 0xe3,0xa5,0x37,0xd,0x81,0x4c,0xdb,0x43,0xf,0x1f,0x54,0x0,0x8,0x5d,0xab,0x80, + 0x50,0x1f,0x0,0x84,0xa,0xac,0xb4,0x1f,0x45,0xfd,0x29,0x4d,0x71,0xba,0x8f,0x1f, + 0xb0,0xb4,0xa9,0xfb,0x0,0x63,0x4,0x64,0xe3,0x1e,0x42,0xc,0x1,0x3f,0xe7,0xff, + 0xca,0xd4,0x4d,0x4,0x7,0x23,0x61,0x78,0xf5,0xab,0x60,0xd,0xab,0x58,0x85,0xa1, + 0x48,0x11,0x9c,0x2c,0x14,0x22,0x48,0xeb,0x6,0x6,0x10,0x83,0x18,0xb4,0x0,0x14, + 0x25,0x48,0xeb,0x4b,0x6,0x90,0x8c,0x60,0xc4,0x35,0xad,0x90,0x51,0x80,0x5b,0x81, + 0x91,0xb6,0x42,0x9c,0xa0,0x3,0xd,0xb0,0xc1,0x21,0x40,0x80,0x80,0x16,0x8c,0xf4, + 0x8,0x5a,0x35,0xc9,0xec,0x60,0x4,0xce,0xc6,0x3a,0xf6,0xb1,0x25,0xa0,0x1,0xc, + 0x60,0xf0,0x81,0x54,0x81,0x60,0xb2,0x30,0xa0,0x18,0xc,0x48,0x60,0x0,0xa,0x64, + 0xe0,0xb2,0x41,0x6b,0x80,0x6,0x58,0x80,0x81,0xd2,0xf2,0x80,0x0,0x9d,0x84,0xc1, + 0x0,0x16,0x40,0x0,0xf,0x70,0xc0,0x4,0x18,0xe8,0x2b,0x55,0xce,0x3,0x81,0x44, + 0xd8,0xa0,0x1,0x3d,0x58,0x27,0x62,0x4b,0x5a,0x91,0xc5,0xbe,0xef,0xb7,0x96,0xc3, + 0x80,0x6,0x4,0xa0,0x81,0xe2,0x32,0xc0,0x3,0x2,0x70,0x80,0x7,0x5a,0x10,0x4, + 0xf,0xb0,0x0,0x0,0x22,0x50,0x6e,0x2,0x64,0x30,0xdc,0x14,0xd4,0x40,0x4,0x18, + 0xc8,0x55,0x0,0x74,0xe0,0x1,0xf,0x14,0x20,0x8,0x26,0xe0,0x0,0xa,0xea,0x29, + 0x4,0xd9,0x1e,0xa1,0x2,0x2c,0x68,0x40,0x6d,0x15,0x31,0x4,0xe1,0x2c,0x93,0x2a, + 0x3c,0x68,0xe7,0x4d,0xb0,0x6,0xdc,0xfa,0xc6,0xd,0x1,0x14,0x8,0x82,0x10,0x84, + 0xc0,0x9,0x8a,0x3a,0xc0,0x0,0x3c,0x58,0x80,0x1,0x6a,0x60,0x0,0xc8,0xed,0x20, + 0x8,0x2b,0xa0,0x0,0x6,0x4c,0x30,0x60,0x3,0x74,0xc0,0x8,0x1a,0x78,0x24,0xff, + 0xc,0x14,0x30,0x80,0x7b,0x7a,0x80,0x9a,0xb2,0x25,0xc0,0x32,0xb4,0xa9,0x88,0x10, + 0x0,0xb6,0x3,0x92,0x8b,0x0,0x17,0x33,0xc3,0x0,0x77,0x6a,0xc3,0x4,0xb9,0x51, + 0x88,0x8a,0x57,0xcc,0xe2,0x16,0xbb,0x78,0x61,0xa,0xa9,0x5c,0xf2,0x3c,0x86,0x0, + 0x19,0x33,0x16,0x6d,0xc0,0x4a,0xa7,0x5,0x36,0xfa,0xa,0xe,0x2c,0x3,0x6,0xd9, + 0xf0,0x87,0x50,0xb7,0x55,0x11,0x20,0xbc,0xe0,0xc8,0x48,0x4e,0xb2,0x92,0x97,0xcc, + 0xe4,0x26,0x3b,0xf9,0xc9,0x50,0x8e,0x32,0x93,0x5,0x0,0x84,0x1f,0xf8,0x18,0x1, + 0x84,0x9b,0xc5,0x3,0xb0,0xc4,0x83,0xf5,0x9a,0xe9,0xcb,0x83,0x90,0x80,0x76,0xa, + 0xf0,0x2b,0x5a,0x7c,0x0,0x37,0x3,0x80,0x0,0x1e,0xc1,0xfc,0x9c,0x13,0x10,0x40, + 0x3b,0x9f,0x35,0x9,0x8,0x70,0xb3,0xa8,0xaa,0xb2,0x19,0x3a,0x21,0x30,0xc0,0x4b, + 0x32,0x40,0x9e,0xa2,0x7c,0x0,0xb0,0xd,0xd8,0xc1,0x7,0xce,0x78,0xe7,0xba,0x5c, + 0xe0,0x6,0x14,0x58,0x86,0x8,0x14,0xea,0x15,0x15,0x68,0x60,0x19,0xc,0xd0,0xc0, + 0xb,0xf6,0x56,0xe8,0xba,0xe8,0xc0,0x1,0x3d,0xc8,0x4d,0x0,0x74,0xfb,0x95,0x8, + 0xd0,0xe0,0x2d,0x8,0xe8,0x81,0x6,0x12,0xb0,0xe6,0x4a,0x6f,0xe3,0x4,0x43,0x70, + 0x0,0x80,0x96,0x34,0x3,0x3f,0xd6,0x25,0x4,0x10,0x28,0x0,0x33,0x76,0x0,0x1, + 0x1e,0x9b,0x9a,0x16,0xf,0x98,0x41,0xa,0x98,0x21,0x2,0xe,0xd8,0xd9,0x37,0x3f, + 0xa0,0x1,0x5,0x46,0xd8,0x3,0x12,0xcc,0x80,0xc8,0xb7,0x4e,0x4,0x10,0x8,0xdc, + 0x10,0x80,0x55,0x23,0x80,0xb5,0xa7,0xf1,0xd0,0x9,0x4,0xe0,0x60,0x73,0x74,0x0, + 0x6,0x12,0x78,0x0,0xa1,0xbf,0xec,0x83,0xf,0xc0,0xc0,0x4,0xe5,0x28,0x80,0x1, + 0x5e,0x50,0x6a,0x4,0x45,0x40,0x0,0x38,0x48,0x1,0x64,0x20,0x1d,0x3,0xd,0x40, + 0x60,0x8,0x3e,0xd8,0xf6,0x6b,0x6c,0x1,0xe,0x14,0x40,0xae,0x23,0xb,0xe0,0x0, + 0xb9,0x93,0x5d,0x88,0x10,0x24,0xa0,0xb3,0x19,0xf0,0x9,0x5c,0x76,0x0,0xb3,0xf, + 0xa8,0x0,0x1b,0x8a,0x89,0xc0,0xf,0x54,0xd0,0xc1,0x1a,0x2c,0x60,0x34,0xcc,0xc8, + 0x80,0x80,0x3f,0x60,0x62,0x7e,0xf7,0xa8,0x2,0x12,0x30,0x0,0x9,0x44,0x90,0x9, + 0x85,0xf4,0x40,0x1,0x1d,0xa0,0x80,0x3a,0xd8,0x21,0x81,0x4,0xbc,0x40,0x5,0xf1, + 0x58,0xa9,0x53,0x57,0xee,0xd4,0x7e,0x54,0xe0,0x6b,0x9,0x90,0x0,0x1,0x50,0x88, + 0x82,0x15,0xb6,0x80,0x23,0x30,0xb1,0x0,0x67,0x6d,0x60,0x50,0x8b,0x57,0x4,0x25, + 0xf4,0x54,0x61,0xc9,0x4a,0xc0,0x83,0xa2,0xbf,0xf8,0xe8,0xe6,0x28,0x41,0xb,0x3a, + 0x40,0x2,0x7,0xe8,0x73,0x8,0x24,0xf1,0x39,0x65,0x4e,0xf0,0x83,0x47,0x80,0x40, + 0x6c,0x28,0x8,0xc0,0xb3,0x2c,0x20,0xc1,0x1,0x78,0x7d,0x0,0x19,0x50,0xc0,0x28, + 0x16,0xd0,0xca,0x75,0xa4,0xe2,0xe0,0xe5,0x86,0x4e,0x20,0x0,0x0,0x3b, + // /home/kosme/Dropbox/GcodeSender/Threaded V2/GrblController/img/right.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xbb,0x2a,0x86,0x2b,0x4b,0xc0, + 0xe1,0xcc,0x2d,0xa0,0x17,0x31,0x9e,0xea,0xba,0x3,0xc1,0x87,0x2,0x2,0x79,0xc4, + 0x92,0xd1,0x88,0x48,0x8e,0x96,0xc6,0x5,0xc3,0x9,0x5d,0x36,0x89,0xd5,0xe5,0x40, + 0xe0,0xcb,0x42,0x23,0x3d,0x97,0x17,0xba,0x95,0x8d,0xab,0x81,0xb0,0xea,0x5c,0x3d, + 0x24,0x58,0x6c,0xa8,0x1b,0x1e,0x7,0x6,0xc4,0xf5,0x32,0x9e,0x1d,0xc1,0xb1,0xf5, + 0x33,0x67,0xf,0x49,0x5e,0x52,0x54,0x55,0x83,0x4e,0x34,0x4b,0x48,0x8a,0x8b,0x41, + 0x43,0x8e,0x22,0x47,0x6a,0x8e,0x35,0x37,0x92,0x24,0xa,0x99,0x9c,0x9d,0x9e,0x32, + 0x21,0x0,0x3b, + // /home/kosme/Dropbox/GcodeSender/Threaded V2/GrblController/img/up.gif + 0x0,0x0,0x0,0xbd, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xbf,0xbf,0xbf,0x99,0x99,0x99,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x80,0x80,0x80,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6a, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x61,0x92,0x90, + 0x99,0x71,0x1c,0x6,0x7a,0x5,0x0,0x10,0xb8,0xd5,0x10,0xc7,0x3,0x2d,0x19,0xc2, + 0xd,0x8,0x2d,0x5a,0xc3,0x17,0x6b,0xd0,0x6c,0x44,0x9c,0xab,0x97,0xfc,0xa1,0x10, + 0xcd,0x1b,0x62,0xc4,0x88,0xfa,0x18,0xa2,0x85,0xf5,0xb6,0x8,0x41,0xb7,0xd2,0x8f, + 0x1,0x4c,0xc,0x72,0xa,0x64,0x5f,0xa1,0x43,0x48,0x13,0x9,0x1b,0x95,0xdb,0xc7, + 0xd2,0xa0,0xe7,0xea,0x4c,0x1b,0xff,0xbe,0xc8,0xf9,0x74,0x66,0x13,0xa,0x80,0x49, + 0xa,0x3a,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x16,0x11,0x0,0x3b, + // /home/kosme/Dropbox/GcodeSender/Threaded V2/GrblController/img/left.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xeb,0xbe,0x86,0xf2,0xba,0xce, + 0x1,0xcc,0xab,0x51,0x0,0x3c,0x9e,0x12,0x36,0xde,0xcd,0x57,0xd2,0x9,0x85,0x44, + 0x12,0xe2,0x78,0x4c,0x4a,0x18,0xb,0x66,0x93,0xb8,0x94,0x4e,0x67,0x82,0x81,0x95, + 0x39,0x33,0x44,0xb6,0xd2,0x57,0x16,0x1c,0x66,0x19,0x2,0x64,0x2b,0x2b,0x11,0x4c, + 0x73,0x57,0x6c,0x77,0x99,0x85,0x96,0x23,0x5d,0x63,0x3b,0xee,0x2b,0xf7,0xe5,0xc9, + 0x49,0xf,0x69,0x4e,0x50,0x60,0x4e,0x22,0x82,0x6a,0x87,0x12,0x46,0x6f,0x8b,0x12, + 0x40,0x57,0x8f,0x8d,0x43,0x8f,0x23,0x35,0x95,0x96,0x23,0x32,0x9a,0x9d,0x9e,0x49, + 0x21,0x0,0x3b, + +}; + +static const unsigned char qt_resource_name[] = { + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // down.gif + 0x0,0x8, + 0x6,0xe1,0x40,0x96, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // logotiny.gif + 0x0,0xc, + 0x2,0x33,0x80,0xb6, + 0x0,0x6c, + 0x0,0x6f,0x0,0x67,0x0,0x6f,0x0,0x74,0x0,0x69,0x0,0x6e,0x0,0x79,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // right.gif + 0x0,0x9, + 0xd,0xf7,0xbc,0x16, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // up.gif + 0x0,0x6, + 0x7,0xc3,0x4d,0xf6, + 0x0,0x75, + 0x0,0x70,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // left.gif + 0x0,0x8, + 0xb,0xd7,0x43,0xb6, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/img + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x5,0x0,0x0,0x0,0x2, + // :/img/logotiny.gif + 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc2, + // :/img/down.gif + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/up.gif + 0x0,0x0,0x0,0x58,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xc,0x3d, + // :/img/left.gif + 0x0,0x0,0x0,0x6a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xc,0xfe, + // :/img/right.gif + 0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xb,0x45, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources_images)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_images)) + +int QT_MANGLE_NAMESPACE(qCleanupResources_images)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_images)) + diff --git a/GC-3.6.1-T3/src/renderarea.cpp b/GC-3.6.1-T3/src/renderarea.cpp new file mode 100644 index 0000000..7db52bb --- /dev/null +++ b/GC-3.6.1-T3/src/renderarea.cpp @@ -0,0 +1,75 @@ +#include "renderarea.h" + +RenderArea::RenderArea(QWidget *parent) + : QWidget(parent), + penProposedPath(QPen(Qt::blue)), penAxes(QPen(QColor(193,97,0))), + penCoveredPath(QPen(QColor(60,196,70), 2)), + penCurrPosActive(QPen(Qt::red, 6)), penCurrPosInactive(QPen(QColor(60,196,70), 6)), + penMeasure(QPen(QColor(151,111,26))), isLiveCurrPos(false) +{ + penCurrPosActive.setCapStyle(Qt::RoundCap); + penCurrPosInactive.setCapStyle(Qt::RoundCap); +} + +void RenderArea::setItems(QList itemsRcvd) +{ + items = itemsRcvd; + + listToRender.setCurrFileLine(0); + listToRender.convertList(items); + listToRender.updateLivePoint(); + update(); +} + +void RenderArea::setLivePoint(double x, double y, bool mm, bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; + livePoint.setCoords(x, y, mm); + listToRender.setLivePoint(livePoint); + update(); + +} + +void RenderArea::setVisualLivenessCurrPos(bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; +} + +void RenderArea::setVisCurrLine(int currLine) +{ + if (listToRender.setCurrFileLine(currLine)) + update(); +} + +void RenderArea::paintEvent(QPaintEvent * /* event */) +{ + if (!items.size()) + return; + + QSize size = this->size(); + + listToRender.rescale(size); + + QPainter painter(this); + + painter.setPen(penProposedPath); + listToRender.writePath(painter, false); + + painter.setPen(penAxes); + listToRender.drawAxes(painter); + + painter.setPen(penMeasure); + listToRender.drawMeasurements(painter); + + painter.setPen(penCoveredPath); + listToRender.writePath(painter, true); + + //if (!livePoint.isNull()) FIX isNull + { + if (isLiveCurrPos) + painter.setPen(penCurrPosActive); + else + painter.setPen(penCurrPosInactive); + listToRender.drawPoint(painter, livePoint); + } +} diff --git a/GC-3.6.1-T3/src/renderarea.h b/GC-3.6.1-T3/src/renderarea.h new file mode 100644 index 0000000..4023ecc --- /dev/null +++ b/GC-3.6.1-T3/src/renderarea.h @@ -0,0 +1,38 @@ +#ifndef RENDERAREA_H +#define RENDERAREA_H + +#include +#include +#include + +#include "positem.h" +#include "renderitemlist.h" +#include "arcitem.h" +#include "lineitem.h" + +class RenderArea : public QWidget +{ + Q_OBJECT +public: + explicit RenderArea(QWidget *parent = 0); + +signals: + +public slots: + void setItems(QList); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisualLivenessCurrPos(bool isLiveCP); + void setVisCurrLine(int currLine); + +protected: + void paintEvent(QPaintEvent *event); + +private: + QList items; + RenderItemList listToRender; + QPen penProposedPath, penAxes, penCoveredPath, penCurrPosActive, penCurrPosInactive, penMeasure; + PosItem livePoint; + bool isLiveCurrPos; +}; + +#endif // RENDERAREA_H diff --git a/GC-3.6.1-T3/src/renderitemlist.cpp b/GC-3.6.1-T3/src/renderitemlist.cpp new file mode 100644 index 0000000..ae94a7e --- /dev/null +++ b/GC-3.6.1-T3/src/renderitemlist.cpp @@ -0,0 +1,241 @@ +#include "renderitemlist.h" +#include + +RenderItemList::RenderItemList() + : scale(1), offsetx(50), offsety(50), mm(true), currFileLine(0) +{ + font.setStyleHint(QFont::Courier); + font.setPointSize(10); +} + +RenderItemList::~RenderItemList() +{ + clearList(); +} + +void RenderItemList::clearList() +{ + while (!list.isEmpty()) + delete list.takeFirst(); +} + +void RenderItemList::convertList(const QList& items) +{ + clearList(); + + if (items.size() == 0) + return; + + double lastx = items.at(0).x, lasty = items.at(0).y; + mm = items.at(0).mm; + foreach (PosItem item, items) + { + if (item.arc) + { + double px = lastx + item.i; + double py = lasty + item.j; + double sx = lastx; + double sy = lasty; + double ex = item.x; + double ey = item.y; + + list.append(new ArcItem( + sx, sy, ex, ey, px, py, item.cw, item.index)); + } + else + { + double sx = item.x; + double sy = item.y; + + list.append(new LineItem(sx, sy, item.index)); + } + + lastx = item.x; + lasty = item.y; + } + + extents.setCoords(0,0,0,0); + foreach (ItemToBase *item, list) + { + PosItem e = item->computeExtents(); + + // can't use QRectF because it reverses the y axis in anticipation of screendraws, which we don't want + //extents = extents.united(e); + + extents.expand(e); + } +} + +void RenderItemList::rescale(const QSize& size) +{ + PosItem liveExtents(extents); + liveExtents.expand(livePoint); + + double scalex = SCREEN_SCALE_FILE * (size.width() / (liveExtents.width())); + double scaley = SCREEN_SCALE_FILE * (size.height() / (liveExtents.height())); + + scale = qMin(scalex, scaley); + + offsetx = size.width() / 2 - ((liveExtents.x + liveExtents.i) / 2) * scale; + offsety = size.height() / 2 - ((liveExtents.y + liveExtents.j) / 2) * scale; + + windowSize = size; +} + +void RenderItemList::writePath(QPainter& painter, bool updatedFromFile) +{ + QPainterPath path; + ItemToBase *item = list.at(0); + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->moveToFirst(path); + foreach (item, list) + { + if (updatedFromFile) + { + if (item->getIndex() > currFileLine) + break; + } + + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->addToPath(path); + } + + painter.drawPath(path); +} + +void RenderItemList::drawAxes(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + + path.moveTo(x, 0); + path.lineTo(x, windowSize.height() - 1); + path.moveTo(0, y); + path.lineTo(windowSize.width() - 1, y); + + painter.drawPath(path); +} + +void RenderItemList::drawMeasurements(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + double xr = item->getXRaw(); + double yr = item->getYRaw(); + + const int length = 6; + LineItem x1(extents.x, yr, true, length); + x1.setParams(scale, windowSize.height(), offsetx, offsety); + x1.drawTo(path); + + LineItem x2(extents.i, yr, true, length); + x2.setParams(scale, windowSize.height(), offsetx, offsety); + x2.drawTo(path); + + LineItem y1(xr, extents.y, false, length); + y1.setParams(scale, windowSize.height(), offsetx, offsety); + y1.drawTo(path); + + LineItem y2(xr, extents.j, false, length); + y2.setParams(scale, windowSize.height(), offsetx, offsety); + y2.drawTo(path); + + painter.drawPath(path); + + painter.setFont(font); + + int ht = painter.fontMetrics().height(); + int wd = painter.fontMetrics().averageCharWidth(); + + QString units = mm ? QObject::tr(" mm") : QObject::tr(" inches"); + + QString info(QString::number(extents.j).append(units).append(QObject::tr(" (Width-X: ").append(QString::number(extents.width())) + .append(QObject::tr(" Height-Y: ")).append(QString::number(extents.height())).append(")")) ) ; + int xMsgTop = x + wd; + QRect br = painter.fontMetrics().boundingRect(info); + br.setWidth(br.width() + wd); + if (br.width() > (windowSize.width() - x)) + xMsgTop = wd; + +#ifdef Q_OS_MACX + writeText(painter, info, xMsgTop, (3 * ht / 4) + 4, wd); +#else + writeText(painter, info, xMsgTop, (3 * ht / 4) + 1, wd); +#endif + +#ifdef Q_OS_MACX + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 2) - 1, wd); +#else + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 4) - 1, wd); +#endif + + writeText(painter, QString::number(extents.x), wd, y - (ht / 4), wd); + + QString right = QString::number(extents.i); + br = painter.fontMetrics().boundingRect(right); + writeText(painter, right, windowSize.width() - (br.width() + wd), y - (ht / 4), wd); +} + +void RenderItemList::writeText(QPainter& painter, QString text, double x, double y, int avgCharWd) +{ + // We need to clear a rectangle into which our text will be written so it is easier to read + QRect br = painter.fontMetrics().boundingRect(text); + br.setWidth(br.width() + avgCharWd); + br.translate(x, y); + // TODO: get the background color from the window instead, otherwise + // any changes to it need to be changed here + painter.fillRect(br, QColor(244,237,187)); + painter.drawText(x, y, text); +} + +void RenderItemList::drawPoint(QPainter& painter, const PosItem& point) +{ + double divisor = 1; + if ((mm && !point.mm) || (!mm && point.mm)) + divisor = MM_IN_AN_INCH; + + PointItem p(point.x / divisor, point.y / divisor); + + p.setParams(scale, windowSize.height(), offsetx, offsety); + + painter.drawPoint(p.getXScr(), p.getYScr()); + +} + +bool RenderItemList::setCurrFileLine(const int currLine) +{ + currFileLine = currLine; + foreach (ItemToBase *item, list) + { + if (item->getIndex() == currLine) + return true; + else if (item->getIndex() > currLine) + return false; + } + return false; +} + +void RenderItemList::setLivePoint(const PosItem& livePoint1) +{ + livePoint = livePoint1; + + updateLivePoint(); +} + +void RenderItemList::updateLivePoint() +{ + if (mm && !livePoint.mm) + { + livePoint.toMm(); + } + else if (!mm && livePoint.mm) + { + livePoint.toInches(); + } +} diff --git a/GC-3.6.1-T3/src/renderitemlist.h b/GC-3.6.1-T3/src/renderitemlist.h new file mode 100644 index 0000000..8b17b9b --- /dev/null +++ b/GC-3.6.1-T3/src/renderitemlist.h @@ -0,0 +1,42 @@ +#ifndef RENDERITEMLIST_H +#define RENDERITEMLIST_H +#include "arcitem.h" +#include "lineitem.h" +#include "pointitem.h" + +#define SCREEN_SCALE_FILE 0.85 + +class RenderItemList +{ +public: + RenderItemList(); + virtual ~RenderItemList(); + + void convertList(const QList& items); + void rescale(const QSize& size); + void writePath(QPainter& painter, bool updatedFromFile); + void drawAxes(QPainter& painter); + void drawMeasurements(QPainter& painter); + void drawPoint(QPainter& painter, const PosItem& point); + bool setCurrFileLine(const int currLine); + void setLivePoint(const PosItem& livePoint); + void updateLivePoint(); + +private: + void clearList(); + void writeText(QPainter& painter, QString text, double x, double y, int avgCharWd); + +private: + QList list; + double scale; + double offsetx; + double offsety; + PosItem extents; + QSize windowSize; + bool mm; + int currFileLine; + PosItem livePoint; + QFont font; +}; + +#endif // RENDERITEMLIST_H diff --git a/GC-3.6.1-T3/src/rs232.cpp b/GC-3.6.1-T3/src/rs232.cpp new file mode 100644 index 0000000..587dd9e --- /dev/null +++ b/GC-3.6.1-T3/src/rs232.cpp @@ -0,0 +1,284 @@ +/**************************************************************** + * rs232.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "rs232.h" +#include + +RS232::RS232() + : port(NULL), detectedEOL(0), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS) +{ +} + +bool RS232::OpenComport(QString commPortStr, QString baudRate) +{ + if (port != NULL) + CloseComport(); + + bool ok; + BaudRateType baud = (BaudRateType)baudRate.toInt(&ok); + if (!ok) + { + baud = BAUD9600; + } + else + { + int possibleBaudRates[] = {BAUD110,BAUD300,BAUD600,BAUD1200,BAUD2400,BAUD4800,BAUD9600,BAUD19200,BAUD38400,BAUD57600,BAUD115200}; + int pbrCount = sizeof possibleBaudRates / sizeof possibleBaudRates[0]; + + bool found = false; + for (int i = 0; i < pbrCount; i++) + { + if (baud == possibleBaudRates[i]) + { + found = true; + break; + } + } + if (!found) + baud = BAUD9600; + } + + PortSettings settings = {baud, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10}; + + port = new QextSerialPort(commPortStr, settings, QextSerialPort::Polling); + + port->open(QIODevice::ReadWrite); + + return port->isOpen(); +} + + +int RS232::PollComport(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->read(buf, size); + return(n); +} + +// This is different than QIoDevice.readline() - this method only returns data if it has a full line in the +// input buffer by peeking at the buffer. It never removes items unless it can remove a full line. +int RS232::PollComportLine(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->peek(buf, size); + if (n <= 0) + return n; + + //printf("PEEK: %d out of %d\n", n, size); + if (detectedEOL == 0) + { + // algorithm assumes we received both eol chars if there are two in this peek + int pos = 0; + char firstEOL = 0; + char secondEOL = 0; + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == '\n' || b == '\r') + { + if (firstEOL == 0) + { + firstEOL = b; + pos = i; + } + else if ((pos + 1) == i) + { + secondEOL = b; + break; + } + else + break; + } + } + + if (firstEOL != 0) + { + if (secondEOL != 0) + { + detectedEOL = secondEOL; + detectedLineFeed = firstEOL; + detectedLineFeed += secondEOL; + } + else + { + detectedEOL = firstEOL; + detectedLineFeed = firstEOL; + } + } + } + + int toRead = 0; + if (detectedEOL) + { + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == detectedEOL) + { + toRead = i + 1; + break; + } + } + } + + // let's hope the serial subsystem's read buffer is big enough to find a linefeed + if (!toRead) + { + return 0; + } + + n = port->read(buf, toRead); + + return n; +} + +int RS232::SendBuf(const char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + if (size <= 0) + { + err( qPrintable(QObject::tr("Unexpected: Told to send %d bytes\n")), size) ; + return 1; + } + + char b[300] = {0}; + memcpy(b, buf, size); +#ifdef DIAG + printf("Sending to port %s [%s]:", port->portName().toLocal8Bit().constData(), b); + for (int x= 0; x < size; x++) + { + printf("%02X ", buf[x]); + } + printf("\n"); + fflush(stdout); +#endif + + port->waitForBytesWritten(-1);// this usually doesn't do anything, but let's put it here in case + +#if 1 + // On very fast PCs running Windows we have to slow down the sending of bytes to grbl + // because grbl loses bytes due to its interrupt service routine (ISR) taking too many clock + // cycles away from serial handling. + int result = 0; + for (int i = 0; i < size; i++) + { + result = port->write(&buf[i], 1); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + break; + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + break; + } + + if (charSendDelayMs > 0) + { + SLEEP(charSendDelayMs); + } + } + +#else + // DO NOT RUN THIS CODE + int result = port->write(buf, size); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + /* the following code doesn't seem to help. Generate an error instead + int limit = 0; + while (!result && limit < 100) + { + SLEEP(100); + result = port->write(buf, size); + limit++; + } + + if (!result) + { + err("Unable to write %d bytes to port!", size); + } + else if (result != size) + err("Unexpected: Retry send wrote %d bytes out of expected %d\n", result, size); + */ + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + } +#endif + return result; +} + + +void RS232::CloseComport() +{ + if (port != NULL) + { + port->close(); + delete port; + port = NULL; + } +} + +void RS232::Reset() //still to test +{ + if (port != NULL) + port->reset(); +} + +void RS232::flush() +{ + int n=1; + char buf[255]; + + while (n > 0) + n = PollComport(buf,255); +} + +bool RS232::isPortOpen() +{ + if (port == NULL) + return false; + + return port->isOpen(); +} + +QString RS232::getDetectedLineFeed() +{ + return detectedLineFeed; +} + +int RS232::bytesAvailable() +{ + int n = port->bytesAvailable(); + return n; +} + +void RS232::setCharSendDelayMs(int csd) +{ + charSendDelayMs = csd; +} diff --git a/GC-3.6.1-T3/src/rs232.h b/GC-3.6.1-T3/src/rs232.h new file mode 100644 index 0000000..a70ec55 --- /dev/null +++ b/GC-3.6.1-T3/src/rs232.h @@ -0,0 +1,76 @@ +/**************************************************************** + * rs232.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef RS232_H +#define RS232_H + +#include +#include + +#include +#include +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#include +#include "../termiosext.h" +#include +#include +#include +#include +#include +#include +#else +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +// TODO - R - if I leave out Windows.h then Sleep is not found??? +#include +#include +#endif +#endif + +#include +#include + +#include "definitions.h" + + +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#define SLEEP(x) usleep(1000 * x); +#else +#define SLEEP(x) Sleep(x); +#endif + + +class RS232 +{ +public: + RS232(); + //methods + bool OpenComport(QString commPortStr, QString baudRate); + int PollComport(char *buf, int size); + int PollComportLine(char *buf, int size); + int SendBuf(const char *buf, int size); + void CloseComport(); + void Reset(); + void flush(); + bool isPortOpen(); + QString getDetectedLineFeed(); + int bytesAvailable(); + void setCharSendDelayMs(int charSendDelayMs); + +private: + QextSerialPort *port; + char detectedEOL; + QString detectedLineFeed; + int charSendDelayMs; + +}; + + +#endif // RS232_H diff --git a/GC-3.6.1-T3/src/termiosext.h b/GC-3.6.1-T3/src/termiosext.h new file mode 100644 index 0000000..93ac44f --- /dev/null +++ b/GC-3.6.1-T3/src/termiosext.h @@ -0,0 +1,11 @@ +#ifndef TERMIOSEXT_H +#define TERMIOSEXT_H + +#ifdef Q_OS_ANDROID +static __inline__ int tcdrain(int fd) +{ + return ioctl(fd, TCSBRK, (void *)(intptr_t)1); +} +#endif + +#endif // TERMIOSEXT_H diff --git a/GC-3.6.1-T3/src/timer.cpp b/GC-3.6.1-T3/src/timer.cpp new file mode 100644 index 0000000..2556b7d --- /dev/null +++ b/GC-3.6.1-T3/src/timer.cpp @@ -0,0 +1,35 @@ +/**************************************************************** + * timer.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "timer.h" +Timer::Timer(QObject *parent) : + QObject(parent), timing(false) +{ + startTimer(500); +} + +void Timer::resetTimer(bool timeIt) +{ + timing = timeIt; + if (timeIt) + timer.start(); +} + +void Timer::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (timing) + { + int secs = timer.elapsed() / 1000; + int mins = (secs / 60) % 60; + int hours = (secs / 3600); + secs = secs % 60; + emit setRuntime(QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(mins, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'))); + } +} diff --git a/GC-3.6.1-T3/src/timer.h b/GC-3.6.1-T3/src/timer.h new file mode 100644 index 0000000..eed99ca --- /dev/null +++ b/GC-3.6.1-T3/src/timer.h @@ -0,0 +1,36 @@ +/**************************************************************** + * timer.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include + +class Timer : public QObject +{ + Q_OBJECT + +public: + explicit Timer(QObject *parent = 0); + +signals: + void setRuntime(QString timestr); + +public slots: + void resetTimer(bool timeIt); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QTime timer; + bool timing; +}; + +#endif // TIMER_H diff --git a/GC-3.6.1-T3/src/translate.bat b/GC-3.6.1-T3/src/translate.bat new file mode 100644 index 0000000..3f52694 --- /dev/null +++ b/GC-3.6.1-T3/src/translate.bat @@ -0,0 +1,21 @@ +rem translate.bat + +echo off + +set PATH=%PATH%;u:\DONNEES\SVN_COMPILE\qt\4.7.3\bin + +rem create "trlocale\*.ts" + +lupdate.exe GcodeSenderGUIthreads.pro + +rem create *.qm + +linguist trlocale\GrblController_fr.ts + +lrelease trlocale\GrblController_fr.ts -qm trlocale\GrblController_fr.qm + +xcopy /Y trlocale\GrblController_fr.qm release\trlocale\ + +xcopy /Y trlocale\GrblController_fr.qm ..\cons\trlocale\ + +cd .. diff --git a/GC-3.6.1-T3/src/trlocale/GrblController_fr.qm b/GC-3.6.1-T3/src/trlocale/GrblController_fr.qm new file mode 100644 index 0000000..e270929 Binary files /dev/null and b/GC-3.6.1-T3/src/trlocale/GrblController_fr.qm differ diff --git a/GC-3.6.1-T3/src/trlocale/GrblController_fr.ts b/GC-3.6.1-T3/src/trlocale/GrblController_fr.ts new file mode 100644 index 0000000..9080d52 --- /dev/null +++ b/GC-3.6.1-T3/src/trlocale/GrblController_fr.ts @@ -0,0 +1,1339 @@ + + + + + About + + + About... + A propos ... + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + Le programme est fourni en l'état SANS GARANTIE D'AUCUNE SORTE, MEME LES GARANTIES DE CONCEPTION, MARCHANDE ET D'ADAPTATION À UN USAGE PARTICULIER. + + + + Grbl Controller + Controleur Grbl + + + Grbl Controller 4 + Controleur Grbl 4 + + + + GCode + + + Can't open COM port + Impossible d'ouvrir le port série + + + + -Is hardware connected to USB? + - le périphérique est-il bien connecté sur un port USB ? + + + + -Is correct port chosen? + - le port choisi est-il correct ? + + + + -Does current user have sufficient permissions? + - l'utilisateur a-t-il les droits d'utilisation suffisants ? + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + Emis : 0x%02X (CTRL-X) pour verifier la presence de Grbl + + + + Sending to port failed + L'émission vers le port a échouée + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + Port not available yet + Le port n'est plus disponible + + + + Buffer size too small + Le tampon est trop petit + + + + SENDING[%d]: 0x%02X (CTRL-X) + + EMIS[%d]: 0x%02X (CTRL-X)\n + + + + SENDING[%d]: %s + + EMIS[%d]: %s\n + + + + WAITFOROK FAILED + + Echec lors de l'attente de Ok + + + + Wait for ok failed + L'attente d'un bon déroulement a échouée + + + + + Error reading data from COM port + + Erreur de lecture des données sur le port série + + + + Unexpected: list is empty (o)! + Liste attendue vide (o) + + + GOT[%d]:%s for %s + + Obtenu [%d]:%s pour %s\n + + + + Error? + Erreur non répertoriée + + + + Unexpected: list is empty (e)! + Liste attendue vide (e) + + + + + GOT:%s + + Obtenu : %s\n + + + + Wait interrupted by user + Attente d'interuption par l'utilisateur + + + + Expecting Grbl version string. Unable to parse response. + Attente de la version Grbl, impossible d'analyser la réponse + + + + No data from COM port after connect. Expecting Grbl version string. + Aucune données depuis le port série après la connexion, en attente de la version Grbl + + + + Wait interrupted by user (startup) + Attente d'interuption par l'utilisateur (démarrage) + + + XYUV-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XYUV : [%1]=>[%2] + + + ([a-zA-Z]+),MPos: + ([a-zA-Z]+),PosM : + + + ([a-zA-Z]+), MPos: + ([a-zA-Z]+) ,PosM : + + + MPos: + PosM : + + + WPos: + PosT : + + + Decoded: State:%s MPos: %f,%f,%f WPos: %f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f WPos: %f,%f,%f + + + + Decoded: State:%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + Error decoding position data! + + Erreur de décodage des données de position\n + + + + Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + + GOT[%d]: '%s' for '%s' (aggressive) + + Obtenu :[%d]: '%s' pour '%s' (offensif) + + + + GOT: '%s' (aggressive) + + Obtenu : '%s' (offensif) + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + L'axe supplémentaire existe matériellement. Veuillez corriger les options en cochant 4 ème axe. + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + L'axe supplémentaire n'existe pas matériellement. Veuillez corriger les options en décochant 4 ème axe. + + + + Decoded: State:%s + Decodage : Etat :%s + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + GOT-TE:%s + + Obtenu evenement temporel :%s\n + + + + Sending file '%1' + Emission du fichier '%1' + + + + Gave up waiting for OK + + Fin d'attente Ok\n + + + + Code sent successfully with %1 error(s): + Code émis correctement avec %1 erreur(s) + + + + Code sent successfully with no errors. + Code émis correctement sans erreur + + + + Filtered %1 commands: + Commande filtrée %1 + + + + Process interrupted. + Processus interrompu + + + + Removed unsupported command '%1' part of '%2' + Suppression de la commande '%1' portion de '%2 ( non supportée) + + + + Removed unsupported G command '%1' + Suppression de la commande G '%1' non supportée + + + + Removed unsupported M command '%1' + Suppression de la commande M '%1' non supportée + + + + Removed unsupported command '%1' + Suppression de la commande '%1' non supportée + + + + Unable to remove enough decimal places for command (will be truncated): %s + Impossible de supprimer assez de decimales pour la commande (sera tronquee) %s + + + + Error, insufficent reduction '%1' + Erreur : réduction insuffisante '%1' + + + + Precision reduced '%1' + Précision réduite '%1' + + + + Z-Rate Limit: [%1]=>[%2] + Limite de vitesse Z [%1]=>[%2] + + + + Z-Rate Limit: [%1]=>[%2,%3] + Limite de vitesse Z : [%1]=>[%2,%3] + + + + XY-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XY : [%1]=>[%2] + + + + Bad command: %1 + Commande erronee : %1 + + + + Options specify use mm but Grbl parser set for inches. Fixing. + Vous utiliser des 'mm' alors que l'analyse indique des 'pouces'. Corriger dans la configuration + + + + Options specify use inches but Grbl parser set for mm. Fixing. + Vous utiliser les 'pouces' alors que l'analyse indique des 'mm'. Corriger dans la configuration + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + Vous utiliser les mm alors que Grbl donne des pouces. Corriger dans la configuration + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + Vous utiliser les 'pouce's alors que Grbl donne des 'mm'. Corriger dans la configuration + + + + + (mm) + (mm) + + + + + (in) + (pouce) + + + + GrblDialog + + + Grbl Settings + Configuration GRBL + + + + Apply + Appliquer + + + + Close + Fermer + + + + Value + Valeur + + + + Item + Elément + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + Activation de 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Use of non activated appender '%1' + Utilisation de 'Appender' '%1' non activé + + + + Use of closed appender '%1' + Utilisation de 'Appender' '%1' fermé + + + + Use of appender '%1' that requires layout and has no layout set + Utiliser 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + Utiliation de 'Appender' '%1' sans un modèle valide initialisé + + + + The pattern '%1' does not specify a frequency for appender '%2' + Le modème '%1' ne spécifie aucune fréquence pour 4Appender' '%2' + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + La conversion de type '%1' de la propriété '%2' de l'objet de classe '%3' est impossible. + + + + Unable to set property value on object + Impossible d'inialiser la valeur de la propriété de l'objet. + + + + Invalid null object pointer + Pointeur d'objet 'null' invalide + + + + Invalid empty property name + Nom de propriété invalide (vide) + + + + Property '%1' does not exist in class '%2' + La propriété '%1' n'existe pas dans la classe '%2' + + + + Property '%1' is not writable in class '%2' + La propriété '%1' ne peut être modifiée dans la classe '%2' + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + L'activation de 'Appender' '%1' nécessite un fichier associé + + + + Use of appender '%1' without open file + Utilisation de 'Appender' '%1' sans fichier ouvert + + + + Unable to write to file '%1' for appender '%2' + Impossible d'écrire dans le fichier '%1' pour 'Appender' '%2' + + + + Unable to open file '%1' for appender '%2' + Impossible d'ouvrir le fichier '%1' pour 'Appender' '%2' + + + + Unable to remove file '%1' for appender '%2' + Impossible de supprimer le fichier '%1' pour 'Appender' '%2' + + + + Unable to rename file '%1' to '%2' for appender '%3' + Impossible de renommer le fichier '%1' en '%2' pour 'Appender' '%3' + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + Parenthèse fermante manquante pour la parenthèse ouvrante '%1'. Valeur de substitution '%2' invalide + + + + Invalid option string '%1' for a boolean + Option chaîne '%1' invalide pour un booléen + + + + Invalid option string '%1' for a file size + Option chaîne '%1' invalide pour la taille d'un fichier + + + + Invalid option string '%1' for an integer + Option chaîne '%1' invalide pour un entier + + + + Invalid option string '%1' for a level + Option chaîne '%1' invalide pour un niveau + + + + Invalid option string '%1' for a target + Option chaîne '%1' invalide pour une cible + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + On trouve un caractère'%1', alors qu'un chiffre est attendu. + + + + Option '%1' cannot be converted into an integer + L'option '%1' ne peut-être convertie vers un entier + + + + Option %1 isn't a positive integer + L'option '%1' n'est pas un entier positif + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + Impossible d'ouvrir le fichier de propriétés '%1' + + + + Unable to read property file '%1' + Impossible de lire le fichier de propriétés '%1' + + + + Missing appender definition for appender named '%1' + La définition de 'appender' est manquente pour 'Appender' nommé '%1' + + + + Unable to create appender of class '%1' named '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Unable to create layout of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + Unable to create appender of class '%1' namd '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Missing layout definition for appender '%1' + La définition de la structure est manquante pour 'Appender' '%1' + + + Unable to create layoput of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + Activation de 'Appender' '%1' lequel nécessite un éditeur non configuré ! + + + + Use of appender '%1' without a writer set + Utiliser 'Appender' '%1' sans éditeur configuré + + + + MainWindow + + + Grbl Controller + Contrôleur Grbl + + + + Check + Vérifier + + + + Lines: + Lignes + + + + X + X + + + + Y + Y + + + + Z + Z + + + + Send File + Envoi d'un fichier + + + + Begin + Démarrer + + + + Stop + Arrêter + + + + Choose file + Choisir un fichier + + + + Runtime: + Exécution + + + Manual GCode + Commande directe en GCode + + + + Command + Commande + + + + + Open + Ouvrir + + + + C + C + + + GRBL +settings + Configuratiion +GRBL + + + + Port name + Nom du port + + + + Reset Control + Commande RAZ + + + + Soft Reset Grbl + RAZ logiciel de Grbl + + + + Unlock Grbl + Débloquer Grbl + + + + Machine Coordinates + Coordonnées machine + + + + Work Coordinates + Coordonnées de travail + + + + Last State: + Dernier état + + + + Zero Position + Vers position zéro + + + + Go Home + Aller position repos + + + + Axis Control + Commandes d'axes + + + + + Z Jog + pilote Z + + + + Step Size + Valeur du pas + + + + Absolute coordinates after adjust + Coordonnées absolues après ajustement + + + + Spindle On + Départ broche + + + + + + 0 + + + + + + C Jog + pilote C + + + + Visualizer + Visualisateur + + + + Baud Rate + Vitesse du port + + + + %v + + + + + File progress + Avancement + + + + Queued Commands + Ordres en attente + + + Lines + Lignes + + + + Advanced + Avancé + + + + GRBL Settings + Configuratiion +GRBL + + + + Refresh Pos + Actualiser position + + + + Firmware : + Micrologiciel : + + + + + none + aucun + + + + &Help + &Aide + + + + &Tools + &Outils + + + + &File + &Fichiers + + + + &About + &A propos + + + + &Options + &Options + + + + E&xit + &Quitter + + + + Close / Reset + Fermer / Raz + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + Vous semblez avoir la dernière version du contrôleur Grbl. Soyez conscient que depuis la version 3.4 le comportement par défaut de l'envoi de commandes à Grbl a été modifié pour les envoyer aussi vite que possible (mode de précharge agressif). + +Vos paramètres ont été modifiés pour permettre ce mode. Pourquoi? Parce qu'il permet une utilisation la plus optimale de Grbl et réduit considérablement le temps de terminer un travail typique. Qu'est-ce que cela signifie pour vous ? Maintenant les commandes d'arc vont être plus continues et plus rapides qu'auparavant, ce qui peut amener votre broche à travailler un peu plus vite, s'il vous plaît donc faire quelques tests en premier. Sinon, passez à la boîte de dialogue Options et désactiver manuellement la précharge agressive + + + Wish to "zero position" before beginning? + Voulez-vous allez en postion zéro avant de démarrer ? + + + + User clicked Port Open/Close + L'utilisateur a clique Ouverture/Fermeture du port + + + + Resetting port to restart controller + L'initialisation du port initialise le contrôleur + + + + Do you want to zero the displayed position before proceeding? + Voulez-vous afficher la postion zéro avant de démarrer ? + + + + %s has started + Lancement de %s + + + + %s has stopped + Fin de %s + + + + Open File + Charger un fichier + + + + NC (*.nc);;All Files (*.*) + NC (*.nc);;Tous fichiers (*.*) + + + + A Jog + pilote A + + + + B Jog + pilote B + + + + U Jog + pilote U + + + + V Jog + pilote V + + + + W Jog + pilote W + + + + Spindle On. + Marche de la broche + + + + Spindle Off. + Arrêt de la broche + + + + Usr chg: pos=%d new=%d + + Changement de position : %d -> =%d + + + + Usr chg: pos=%.1f new=%.1f + + Changement de position : %.1f -> =%.1f + + + + Usr chg no slider: %d + + Utilisation du coulisseau : %d + + + + Usr chg no slider: %.1f + + Utilisation du coulisseau : %.1f + + + + Pressed and stopped + + Actionne et stoppe + + + + Pressed not stopped + + Actionne sans stop + + + + Released + + Relache + + + + Options + + + Options + Options + + + + Axis + Axes + + + + Invert Axis + Inverser les axes + + + + Z Axis + Axe Z + + + + Y Axis + Axe Y + + + + X Axis + Axe X + + + C Axis + Axe C + + + + Seconds to Wait for Response + Secondes d'attente lors d'une réponse + + + + Z-Jog Rate (inches or mm/min) + Vitesse manuelle Z (pouces ou mmm/min) + + + Main + Général + + + + Use millimeters when sending manual commands (v0.8c+ only) + Emission des commandes manuelles en millimètre (v0.8c+ seulement) + + + + Filtering + Filtre + + + + Z Rate Limiting + Limitation de vitesse + + + + Limit Z Rate + Vitesse max Z + + + + Z-Rate Limit (inches or mm/min) + Vitesse limite Z (pouces ou mmm/min) + + + + XY Rate (inches or mm/min) + Vitesse XY (pouces ou mmm/min) + + + + Use aggressive preload strategy for Grbl + Utiliser une stratégie offensive de pré-chargement pour Grbl + + + + General + Général + + + + Wait for each jog/manual command to complete (future feature) + Attendre à chaque commande manuelle pour terminer (option future) + + + + Write debugging log to home folder (requires restart) + Mise au point sauvée dans le répertoire d'accueil (+ redémarrage) + + + + Fourth Axis + 4 ème axe + + + + Selecting the Fourth axis + Choix du quatrième axe + + + + A + A + + + + B + B + + + + C + C + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + Valider le mode 4 axes + + + + Display + Affichage + + + + Enable position request and report + Demander la position puis l'afficher + + + + Position Request + Demande de position + + + + Always Request (most reliable/slightly slower jogging) + permanente (plus fiable, mais les commandes manuelles sont ralenties) + + + + Always Request but without Idle Check (fast jog/manual operations) + permanente mais sans controler l'inactivité (commandes manuelles rapides) + + + + Not during manual control (no position update during jog/manual) + sauf les commandes manuelles où l'actualisation de la position est inactive. + + + Always Request + Demande permanente + + + Not during manual control + Exclure des commandes manuelles + + + + Request frequency (seconds) + Période des demandes (secondes) + + + + Command Filtering + Filtrage des commandes + + + + Filter file commands before sending + Filtrage des commandes du fichier GCode avant l'émission + + + + Selectively reduce precision for excessively long lines + Réduire sélectivement la précision, lors de longues lignes de code + + + + Character send delay ms + Délai d'émission des caractères en mS + + + + Grbl Line Buffer Size + Taille du tampon d'entrée de Grbl + + + + QObject + + + Unexpected: Told to send %d bytes + + Inattendu : impossible d'envoyer%d octets + + + Unable to write bytes to port probably due to outgoing queue full. Write data lost! + Impossible d'ecrire sur le port, probablement la file d'attente de sortie est pleine.Perte de donnees en ecriture ! + + + Error writing to port. Write data lost! + Erreu d'ecriture sur le port. Les donnees a ecrire sont perdues + + + + mm + mm + + + + inches + pouces + + + + (Width-X: + (Larg-X: + + + + Height-Y: + Haut-Y: + + + Unexpected type %c + Type attendu %c + + + + Initialising Log4Qt %1 + Initialisation de LOg4Qt %1 + + + + QextSerialPort + + + No Error has occurred + Aucune erreur + + + + Invalid file descriptor (port was not opened correctly) + Descripteur de périphérique invalide (port mal ouvert) + + + + Unable to allocate memory tables (POSIX) + Impossible d'allouer les tables en mémoire (POSIX) + + + + Caught a non-blocked signal (POSIX) + Capture d'un signal non-bloqué (POSIX) + + + + Operation timed out (POSIX) + Dépassement temporel (POSIX) + + + + The file opened by the port is not a valid device + Le fichier ouvert pour le port n'est pas un périphérique valide + + + + The port detected a break condition + Le port a détecté une condition d'arrêt + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + Le port a détecté une erreur de trame (probablement due à une vitesse erronée) + + + + There was an I/O error while communicating with the port + Erreur d'entrée/sortie lors d'une communication sur le port + + + + Character buffer overrun + Dépassementt du tampon de caractères + + + + Receive buffer overflow + Débordement du tampon de réception + + + + The port detected a parity error in the received data + Le port a détecté une erreur de parité lors de la réception de données + + + + Transmit buffer overflow + Débordement du tampon d'émission + + + + General read operation failure + Echec d'une opération de lecture + + + + General write operation failure + Echec d'une opération d'écriture + + + + The %1 file doesn't exists + Le fichier %1 n'existe pas + + + + Permission denied + Non autorisé + + + + Device is already locked + Périphérique déjà bloqué + + + + Unknown error: %1 + Erreur non répertoriée : %1 + + + diff --git a/GC-3.6.1-T3/src/trlocale/GrblController_xx.qm b/GC-3.6.1-T3/src/trlocale/GrblController_xx.qm new file mode 100644 index 0000000..be651ee --- /dev/null +++ b/GC-3.6.1-T3/src/trlocale/GrblController_xx.qm @@ -0,0 +1 @@ +<¸dÊÍ!¿`¡½Ý \ No newline at end of file diff --git a/GC-3.6.1-T3/src/trlocale/GrblController_xx.ts b/GC-3.6.1-T3/src/trlocale/GrblController_xx.ts new file mode 100644 index 0000000..3b0f1b5 --- /dev/null +++ b/GC-3.6.1-T3/src/trlocale/GrblController_xx.ts @@ -0,0 +1,1224 @@ + + + + + About + + + About... + + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + + + Grbl Controller + + + + + GCode + + + Can't open COM port + + + + + -Is hardware connected to USB? + + + + + -Is correct port chosen? + + + + + -Does current user have sufficient permissions? + + + + + Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d) + + + + + + Sending to port failed + + + + + Port not available yet + + + + + Buffer size too small + + + + + SENDING[%d]: 0x%02X (CTRL-X) + + + + + + SENDING[%d]: %s + + + + + + WAITFOROK FAILED + + + + + + Wait for ok failed + + + + + + Error reading data from COM port + + + + + + Unexpected: list is empty (o)! + + + + + + GOT[%d]: '%s' for '%s' (aggressive) + + + + + + Error? + + + + + Unexpected: list is empty (e)! + + + + + GOT: '%s' (aggressive) + + + + + + + GOT:%s + + + + + + Wait interrupted by user + + + + + Expecting Grbl version string. Unable to parse response. + + + + + No data from COM port after connect. Expecting Grbl version string. + + + + + Wait interrupted by user (startup) + + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + + + + + Decoded: State:%s + + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + + GOT-TE:%s + + + + + + Sending file '%1' + + + + + Gave up waiting for OK + + + + + + Code sent successfully with %1 error(s): + + + + + Code sent successfully with no errors. + + + + + Filtered %1 commands: + + + + + Process interrupted. + + + + + Removed unsupported command '%1' part of '%2' + + + + + Removed unsupported G command '%1' + + + + + Removed unsupported M command '%1' + + + + + Removed unsupported command '%1' + + + + + Unable to remove enough decimal places for command (will be truncated): %s + + + + + Error, insufficent reduction '%1' + + + + + Precision reduced '%1' + + + + + Z-Rate Limit: [%1]=>[%2] + + + + + Z-Rate Limit: [%1]=>[%2,%3] + + + + + XY-Rate Limit FIX: [%1]=>[%2] + + + + + Bad command: %1 + + + + + Options specify use mm but Grbl parser set for inches. Fixing. + + + + + Options specify use inches but Grbl parser set for mm. Fixing. + + + + + Options specify use mm but Grbl reporting set for inches. Fixing. + + + + + Options specify use inches but Grbl reporting set for mm. Fixing. + + + + + + (mm) + + + + + + (in) + + + + + GrblDialog + + + Grbl Settings + + + + + Apply + + + + + Close + + + + + Value + + + + + Item + + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + + + + + Use of non activated appender '%1' + + + + + Use of closed appender '%1' + + + + + Use of appender '%1' that requires layout and has no layout set + + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + + + + + The pattern '%1' does not specify a frequency for appender '%2' + + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + + + + + Unable to set property value on object + + + + + Invalid null object pointer + + + + + Invalid empty property name + + + + + Property '%1' does not exist in class '%2' + + + + + Property '%1' is not writable in class '%2' + + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + + + + + Use of appender '%1' without open file + + + + + Unable to write to file '%1' for appender '%2' + + + + + Unable to open file '%1' for appender '%2' + + + + + Unable to remove file '%1' for appender '%2' + + + + + Unable to rename file '%1' to '%2' for appender '%3' + + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + + + + + Invalid option string '%1' for a boolean + + + + + Invalid option string '%1' for a file size + + + + + Invalid option string '%1' for an integer + + + + + Invalid option string '%1' for a level + + + + + Invalid option string '%1' for a target + + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + + + + + Option '%1' cannot be converted into an integer + + + + + Option %1 isn't a positive integer + + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + + + + + Unable to read property file '%1' + + + + + Missing appender definition for appender named '%1' + + + + + Unable to create appender of class '%1' named '%2' + + + + + Unable to create layout of class '%1' requested by appender '%2' + + + + + Missing layout definition for appender '%1' + + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + + + + + Use of appender '%1' without a writer set + + + + + MainWindow + + + Grbl Controller + + + + + Check + + + + + Lines: + + + + + X + + + + + Y + + + + + Z + + + + + C + + + + + Send File + + + + + Begin + + + + + Stop + + + + + Choose file + + + + + Runtime: + + + + + + Open + + + + + Port name + + + + + Reset Control + + + + + Soft Reset Grbl + + + + + Unlock Grbl + + + + + Machine Coordinates + + + + + Work Coordinates + + + + + Last State: + + + + + Zero Position + + + + + Go Home + + + + + Axis Control + + + + + + Z Jog + + + + + Step Size + + + + + Absolute coordinates after adjust + + + + + Spindle On + + + + + + + 0 + + + + + + C Jog + + + + + Visualizer + + + + + Baud Rate + + + + + %v + + + + + File progress + + + + + Queued Commands + + + + + Command + + + + + Advanced + + + + + GRBL Settings + + + + + Refresh Pos + + + + + Firmware : + + + + + + none + + + + + &Help + + + + + &Tools + + + + + &File + + + + + &About + + + + + &Options + + + + + E&xit + + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + + + + + User clicked Port Open/Close + + + + + Do you want to zero the displayed position before proceeding? + + + + + Close / Reset + + + + + %s has started + + + + + %s has stopped + + + + + Resetting port to restart controller + + + + + Open File + + + + + NC (*.nc);;All Files (*.*) + + + + + A Jog + + + + + B Jog + + + + + U Jog + + + + + V Jog + + + + + W Jog + + + + + Spindle On. + + + + + Spindle Off. + + + + + Usr chg: pos=%d new=%d + + + + + + Usr chg: pos=%.1f new=%.1f + + + + + + Usr chg no slider: %d + + + + + + Usr chg no slider: %.1f + + + + + + Pressed and stopped + + + + + + Pressed not stopped + + + + + + Released + + + + + + Options + + + Options + + + + + Axis + + + + + Invert Axis + + + + + Z Axis + + + + + Y Axis + + + + + X Axis + + + + + Seconds to Wait for Response + + + + + Z-Jog Rate (inches or mm/min) + + + + + General + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + Wait for each jog/manual command to complete (future feature) + + + + + Filtering + + + + + Z Rate Limiting + + + + + Limit Z Rate + + + + + Z-Rate Limit (inches or mm/min) + + + + + XY Rate (inches or mm/min) + + + + + Use aggressive preload strategy for Grbl + + + + + Write debugging log to home folder (requires restart) + + + + + Fourth Axis + + + + + Selecting the Fourth axis + + + + + A + + + + + B + + + + + C + + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + + + + + Display + + + + + Enable position request and report + + + + + Position Request + + + + + Always Request (most reliable/slightly slower jogging) + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + Not during manual control (no position update during jog/manual) + + + + + Request frequency (seconds) + + + + + Command Filtering + + + + + Filter file commands before sending + + + + + Selectively reduce precision for excessively long lines + + + + + Character send delay ms + + + + + Grbl Line Buffer Size + + + + + QObject + + + mm + + + + + inches + + + + + (Width-X: + + + + + Height-Y: + + + + + Unexpected: Told to send %d bytes + + + + + + Initialising Log4Qt %1 + + + + + QextSerialPort + + + No Error has occurred + + + + + Invalid file descriptor (port was not opened correctly) + + + + + Unable to allocate memory tables (POSIX) + + + + + Caught a non-blocked signal (POSIX) + + + + + Operation timed out (POSIX) + + + + + The file opened by the port is not a valid device + + + + + The port detected a break condition + + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + + + + + There was an I/O error while communicating with the port + + + + + Character buffer overrun + + + + + Receive buffer overflow + + + + + The port detected a parity error in the received data + + + + + Transmit buffer overflow + + + + + General read operation failure + + + + + General write operation failure + + + + + The %1 file doesn't exists + + + + + Permission denied + + + + + Device is already locked + + + + + Unknown error: %1 + + + + diff --git a/GC-3.6.1-T3/src/version.h b/GC-3.6.1-T3/src/version.h new file mode 100644 index 0000000..384b078 --- /dev/null +++ b/GC-3.6.1-T3/src/version.h @@ -0,0 +1,12 @@ +/**************************************************************** + * version.h + * GrblHoming - zapmaker fork on github + * + * 14 July 2013 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#ifndef VERSION_H +#define VERSION_H +#define GRBL_CONTROLLER_NAME_AND_VERSION "Grbl Controller 3.6.1-T3" +#endif // VERSION_H diff --git a/GC-3.6.1-T3/src/wininfoafter.txt b/GC-3.6.1-T3/src/wininfoafter.txt new file mode 100644 index 0000000..ab64a5b --- /dev/null +++ b/GC-3.6.1-T3/src/wininfoafter.txt @@ -0,0 +1 @@ +Thanks! Please visit www.zapmaker.org to give feedback. \ No newline at end of file diff --git a/GC-3.6.1-T3/src/wininfobefore.txt b/GC-3.6.1-T3/src/wininfobefore.txt new file mode 100644 index 0000000..a28c537 --- /dev/null +++ b/GC-3.6.1-T3/src/wininfobefore.txt @@ -0,0 +1,7 @@ +GrblController 3 - Control your Grbl Arduino and other basic CNC 3-axis systems. + +Installs a EXE file and support DLLs that communicate via COM port to Grbl Arduino using GCode. + +by Zapmaker + +Released under GPL 3.0 \ No newline at end of file diff --git a/GC-3.6.1-T3/src/winlicense.txt b/GC-3.6.1-T3/src/winlicense.txt new file mode 100644 index 0000000..720cb46 --- /dev/null +++ b/GC-3.6.1-T3/src/winlicense.txt @@ -0,0 +1,3 @@ +GrblController + +The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. \ No newline at end of file diff --git a/GC-3.6.1-T3/translate.bat b/GC-3.6.1-T3/translate.bat new file mode 100644 index 0000000..e19fc59 --- /dev/null +++ b/GC-3.6.1-T3/translate.bat @@ -0,0 +1,8 @@ +rem translate.bat +rem by LETARTARE + +cd src + +translate.bat + + diff --git a/GCV-3.6.1-T4/README b/GCV-3.6.1-T4/README new file mode 100644 index 0000000..b6cfdda --- /dev/null +++ b/GCV-3.6.1-T4/README @@ -0,0 +1,76 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Details on how to do this can be found here: +http://zapmaker.org/ + +-------------------------------------------------------------------------------- +GCV : Grbl Controller Visualizer is a 3D extension of GrblController-3.6.1 +-------------------------------------------------------------------------------- + +GCV-3.6.1-T4 Grbl Controller Visualizer (LETARTARE proposals August 22, 2014) + +An executable 'Win32' into 'winexe/GCV-3.6.1-T4-cb.jtgcv'. +This is a file Win32 compressed, change the extension 'jtgcv -> 7z' to decompress. + +* 3.6.1-T3 + + +1- Analyzes the gcode with 4 axes X, Y, Z, T ( fourth axis ), +2- New display console ('Console') commands, with the ability to copy, delete + text part, delete the selected (or all) text, print the selected (or all) text +3- Display speed rate XYZ with 'Lcd', display last spindle speed, +4- Visualizes the 'Gcode' XYZ 3D with motion mouse : + - A help button to explain the multiple possible actions on the drawing, + by utilsation keyboard and mouse, + - You can see it or not the box limits the drawing, + - Choosing a particuler tool, + - Different views are available by buttons, + - Display axes oriented, + - Display a grid in the XY plane, + - Choice of deleting lines G0. + +5- Animation 3D XYZ axes, regardless of the connection : + - When loading a file, you can read its contents in the console 'Visual', + which will launch the manual or automatic animation, + - In manual mode you can use the mouse to select a line of code or the + navigation buttons or sliders keyboard arrows, + - In automatic mode has a period setting reading 'Gcode', + +6- In addition to the periodic polling of 'Grbl', a new method is proposed + EXPERIMENTAL display named 'Synchronous simulation' based on motion prediction, + - This mode is for use rather large arcs or helical path, + - It does not work with manual controls, + - It is accessed via 'Tools->Options->Display->Synchronous simulation', + +7- The visual presentation of 'GCV' has been modified : + - a flip button to pause and resume sending gcode file at the end of the current + line, will send to 'Grbl', + - buttons for Grbl commands grouped with console, + - manual controls axes (jog) are grouped next to the display positions : + - the incremental value step manual controls is defined by a slide + and a display, and can be adjusted finely by keyboard keys, + - homing new buttons for each axis, + - homing new button for all axes, + - the feed rate movement is displayed during, + - the last spindle speed is displayed, + +8- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, 0.9f, the last 0.9g + 2- Four axes 0845, 0.8c1, 0.8c2 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c2Mega2560 + +- KNOWN BUGS + - In the mode 'Check', it does not use the command line to send '$C' + - The mode 'Simulation synchronous' does not work in manual controls + - If no file is loaded, the manual controls do not support the visualization tool + - ... + + +-------------------------------------------------------------------------------- diff --git a/GCV-3.6.1-T4/buildWin.txt b/GCV-3.6.1-T4/buildWin.txt new file mode 100644 index 0000000..a334d0b --- /dev/null +++ b/GCV-3.6.1-T4/buildWin.txt @@ -0,0 +1,34 @@ +builWin.txt by LETARTARE + + +To build the executable under Windows, you must have + +1- a 'Qt' version installed and compiled, + the tests were performed with 'Qt-4.7.3' or 'Qt-5.2'. + +2- a 'libQGlViever' version installed in 'Qt', the tests were performed with 'QGlViewer-2.5.2'. + - 'path_Qt\include\QGlviewer' received all include + - 'path_Qt\lib\libQGLViewer2.a (libQGLViewerd2.a) + - 'path_Qt\bin\QGLViewer2.dll (QGLViewerd2.dll) + +3- 'mingw32' installed to use 'mingw32-make.exe', + the tests were performed with 'MinGw32-TDM-4.7.1' or 'MinGw32-4.8' + +You have to adapt the file 'mw.bat' for the paths are correct. + +Example for Qt4 : + rem Qt4 + set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ + set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + + rem Qt5 + rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ + rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + +Open a DOS console and +1 - mw.bat +2 - execute.bat + +if you want the French translation +3 - translate.bat +4 - execute.bat diff --git a/GCV-3.6.1-T4/clean.bat b/GCV-3.6.1-T4/clean.bat new file mode 100644 index 0000000..6a4585c --- /dev/null +++ b/GCV-3.6.1-T4/clean.bat @@ -0,0 +1,26 @@ +rem clean.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +clean.bat + + diff --git a/GCV-3.6.1-T4/execute.bat b/GCV-3.6.1-T4/execute.bat new file mode 100644 index 0000000..05cdb9f --- /dev/null +++ b/GCV-3.6.1-T4/execute.bat @@ -0,0 +1,8 @@ +rem execute.bat +rem by LETARTARE + +cd src\bin\ + +GrblController.exe + +cd ..\.. \ No newline at end of file diff --git a/GCV-3.6.1-T4/mw.bat b/GCV-3.6.1-T4/mw.bat new file mode 100644 index 0000000..04df748 --- /dev/null +++ b/GCV-3.6.1-T4/mw.bat @@ -0,0 +1,24 @@ +rem mw.bat +rem by LETARTARE + +rem Change with your paths + +rem QT5 +rem set PATH_QT=o:\DevCpp\Qt-5.3\5.2.0\mingw48_32\ +rem set PATH_MINGW32=o:\DevCpp\Qt-5.3\Tools\mingw48_32\ + +rem Qt4 +set PATH_QT=u:\DONNEES\SVN_COMPILE\qt\4.7.3\ +set PATH_MINGW32o:\DevCpp\MinGw32-TDM\ + +echo off + +PATH = %PATH_QT%bin;%PATH_MINGW32%bin;%PATH%; + +set path + +cd src + +makeWin.bat + + diff --git a/GCV-3.6.1-T4/src/.gitignore b/GCV-3.6.1-T4/src/.gitignore new file mode 100644 index 0000000..f128f9d --- /dev/null +++ b/GCV-3.6.1-T4/src/.gitignore @@ -0,0 +1,19 @@ +GcodeSenderGUIthreads.pro.user +Makefile +Makefile.Debug +Makefile.Release +debug/ +release/ +favs.txt +object_script.GcodeSenderGUI.Debug +object_script.GcodeSenderGUI.Release +settings +ui_*.h +Output/ +android/ +GrblController +*.o +moc_*.cpp +qrc_*.cpp +*.stash +GrblController-local.iss diff --git a/GCV-3.6.1-T4/src/GCV.pro b/GCV-3.6.1-T4/src/GCV.pro new file mode 100644 index 0000000..905cc7e --- /dev/null +++ b/GCV-3.6.1-T4/src/GCV.pro @@ -0,0 +1,147 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-02-13 T17:48:40 +# +# Rename by LETARTARE July 28, 2014 +# GCV.pro +# +#------------------------------------------------- + +TEMPLATE = app +TARGET = GrblController + +DEFINES = QT_NO_DEBUG + +QT += core gui + +unix { + QT += widgets +} + +# LETARTARE June 12, 2014 +contains(QT_VERSION, "^5.*") { + QT *= widgets +} + +# LETARTARE July 28, 2014 +DESTDIR = bin + +CONFIG(debug, debug|release) { + # TARGET = + OBJECTS_DIR = build/debug/obj + MOC_DIR = build/debug/moc + RCC_DIR = build/debug/rcc + UI_DIR = build/debug/ui +} +else { + # TARGET = + OBJECTS_DIR = build/release/obj + MOC_DIR = build/release/moc + RCC_DIR = build/release/rcc + UI_DIR = build/release/ui +} + +# QGlViewer +QT += xml opengl +INCLUDEPATH += QGLViewer QGLWidget +LIBS += -lQGlViewer2 +HEADER += visu3D/Point3D.h visu3D/Line3D.h visu3D/Arc3D.h visu3D/Tools3D.h visu3D/Box3D.h +SOURCES += visu3D/Point3D.cpp visu3D/Line3D.cpp visu3D/Arc3D.cpp visu3D/Tools3D.cpp visu3D/Box3D.cpp + + +# Translations + TRANSLATIONS += trlocale/GrblController_xx.ts + TRANSLATIONS += trlocale/GrblController_fr.ts + +include(QextSerialPort/qextserialport.pri) +include(log4qt/log4qt.pri) + +SOURCES += main.cpp\ + mainwindow.cpp \ + rs232.cpp \ + options.cpp \ + grbldialog.cpp \ + about.cpp \ + gcode.cpp \ + timer.cpp \ + atomicintbool.cpp \ + coord3d.cpp \ + renderarea.cpp \ + positem.cpp \ + renderitemlist.cpp \ + lineitem.cpp \ + itemtobase.cpp \ + arcitem.cpp \ + pointitem.cpp \ + controlparams.cpp \ + visu3D/viewer3D.cpp + +HEADERS += mainwindow.h \ + rs232.h \ + options.h \ + grbldialog.h \ + definitions.h \ + about.h \ + images.rcc \ + gcode.h \ + timer.h \ + atomicintbool.h \ + coord3d.h \ + log4qtdef.h \ + renderarea.h \ + positem.h \ + renderitemlist.h \ + lineitem.h \ + itemtobase.h \ + arcitem.h \ + pointitem.h \ + termiosext.h \ + controlparams.h \ + version.h \ + visu3D/viewer3D.h + +FORMS += forms/mainwindow.ui \ + forms/options.ui \ + forms/grbldialog.ui \ + forms/about.ui + +RESOURCES += GrblController.qrc + +RC_FILE = grbl.rc + +OTHER_FILES += \ + android/AndroidManifest.xml \ + android/res/drawable/icon.png \ + android/res/drawable/logo.png \ + android/res/drawable-hdpi/icon.png \ + android/res/drawable-ldpi/icon.png \ + android/res/drawable-mdpi/icon.png \ + android/res/layout/splash.xml \ + android/res/values/libs.xml \ + android/res/values/strings.xml \ + android/res/values-de/strings.xml \ + android/res/values-el/strings.xml \ + android/res/values-es/strings.xml \ + android/res/values-et/strings.xml \ + android/res/values-fa/strings.xml \ + android/res/values-fr/strings.xml \ + android/res/values-id/strings.xml \ + android/res/values-it/strings.xml \ + android/res/values-ja/strings.xml \ + android/res/values-ms/strings.xml \ + android/res/values-nb/strings.xml \ + android/res/values-nl/strings.xml \ + android/res/values-pl/strings.xml \ + android/res/values-pt-rBR/strings.xml \ + android/res/values-ro/strings.xml \ + android/res/values-rs/strings.xml \ + android/res/values-ru/strings.xml \ + android/res/values-zh-rCN/strings.xml \ + android/res/values-zh-rTW/strings.xml \ + android/src/org/kde/necessitas/ministro/IMinistro.aidl \ + android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \ + android/src/org/kde/necessitas/origo/QtActivity.java \ + android/src/org/kde/necessitas/origo/QtApplication.java \ + android/version.xml + + diff --git a/GCV-3.6.1-T4/src/GrblController.iss b/GCV-3.6.1-T4/src/GrblController.iss new file mode 100644 index 0000000..49dc801 --- /dev/null +++ b/GCV-3.6.1-T4/src/GrblController.iss @@ -0,0 +1,58 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "Grbl Controller" +#define MyAppVersion "3.6.1" +#define MyAppPublisher "Zapmaker" +#define MyAppURL "http://zapmaker.org" +#define MyAppExeName "GrblController.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{2DC56D0D-0673-4954-9BDE-3D664965BA97} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=C:\dev\github\GrblHoming\winlicense.txt +InfoBeforeFile=C:\dev\github\GrblHoming\wininfobefore.txt +InfoAfterFile=C:\dev\github\GrblHoming\wininfoafter.txt +OutputBaseFilename=GrblController361Setup +Compression=lzma +SolidCompression=yes + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked +Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 + +[Files] +Source: "C:\dev\github\GrblHoming\release\GrblController.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\dev\github\GrblHoming\trlocale\*.qm"; DestDir: "{app}\trlocale"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\mingwm10.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Qt\4.8.3\bin\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\mingw\bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/GCV-3.6.1-T4/src/GrblController.qrc b/GCV-3.6.1-T4/src/GrblController.qrc new file mode 100644 index 0000000..5688988 --- /dev/null +++ b/GCV-3.6.1-T4/src/GrblController.qrc @@ -0,0 +1,24 @@ + + + img/home.png + img/homeall.png + img/down.png + img/left.png + img/logotiny.png + img/right.png + img/up.png + img/zapmaker-logo-130.png + img/gaia2.jpg + img/frontview.png + img/backview.png + img/leftview.png + img/rightview.png + img/topview.png + img/bottomview.png + img/isoview1.png + img/isoview2.png + img/isoview3.png + img/isoview4.png + img/upvector.png + + diff --git a/GCV-3.6.1-T4/src/LICENSE b/GCV-3.6.1-T4/src/LICENSE new file mode 100644 index 0000000..9e419e0 --- /dev/null +++ b/GCV-3.6.1-T4/src/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.cpp new file mode 100644 index 0000000..917acf2 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" + +#include +#include +#include + +QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator) + :q_ptr(enumrator) +{ + platformSpecificInit(); +} + +QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate() +{ + platformSpecificDestruct(); +} + +/*! + \class QextPortInfo + + \brief The QextPortInfo class containing port information. + + Structure containing port information. + + \code + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID + \endcode + */ + +/*! \class QextSerialEnumerator + + \brief The QextSerialEnumerator class provides list of ports available in the system. + + \section1 Usage + To poll the system for a list of connected devices, simply use getPorts(). Each + QextPortInfo structure will populated with information about the corresponding device. + + \bold Example + \code + QList ports = QextSerialEnumerator::getPorts(); + foreach (QextPortInfo port, ports) { + // inspect port... + } + \endcode + + To enable event-driven notification of device connection events, first call + setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() + signals. Event-driven behavior is currently available only on Windows and OS X. + + \bold Example + \code + QextSerialEnumerator *enumerator = new QextSerialEnumerator(); + connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), + myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); + connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), + myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); + \endcode + + \section1 Credits + Windows implementation is based on Zach Gorman's work from + \l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp). + + OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html + + \bold author Michal Policht, Liam Staskawicz +*/ + +/*! + \fn void QextSerialEnumerator::deviceDiscovered(const QextPortInfo &info) + A new device has been connected to the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that has been discovered. +*/ + +/*! + \fn void QextSerialEnumerator::deviceRemoved(const QextPortInfo &info); + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + + \a info The device that was disconnected. +*/ + +/*! + Constructs a QextSerialEnumerator object with the given \a parent. +*/ +QextSerialEnumerator::QextSerialEnumerator(QObject *parent) + :QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this)) +{ + if (!QMetaType::isRegistered(QMetaType::type("QextPortInfo"))) + qRegisterMetaType("QextPortInfo"); +} + +/*! + Destructs the QextSerialEnumerator object. +*/ +QextSerialEnumerator::~QextSerialEnumerator() +{ + delete d_ptr; +} + +/*! + Get list of ports. + + return list of ports currently available in the system. +*/ +QList QextSerialEnumerator::getPorts() +{ + return QextSerialEnumeratorPrivate::getPorts_sys(); +} + +/*! + Enable event-driven notifications of board discovery/removal. +*/ +void QextSerialEnumerator::setUpNotifications() +{ + Q_D(QextSerialEnumerator); + if (!d->setUpNotifications_sys(true)) + QESP_WARNING("Setup Notification Failed..."); +} + +#include "moc_qextserialenumerator.cpp" diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.h b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.h new file mode 100644 index 0000000..99f515d --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALENUMERATOR_H_ +#define _QEXTSERIALENUMERATOR_H_ + +#include +#include +#include "qextserialport_global.h" + +struct QextPortInfo { + QString portName; ///< Port name. + QString physName; ///< Physical name. + QString friendName; ///< Friendly name. + QString enumName; ///< Enumerator name. + int vendorID; ///< Vendor ID. + int productID; ///< Product ID +}; + +class QextSerialEnumeratorPrivate; +class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialEnumerator) +public: + QextSerialEnumerator(QObject *parent=0); + ~QextSerialEnumerator(); + + static QList getPorts(); + void setUpNotifications(); + +Q_SIGNALS: + void deviceDiscovered(const QextPortInfo &info); + void deviceRemoved(const QextPortInfo &info); + +private: + Q_DISABLE_COPY(QextSerialEnumerator) +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent()) +#endif + QextSerialEnumeratorPrivate *d_ptr; +}; + +#endif /*_QEXTSERIALENUMERATOR_H_*/ diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_linux.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_linux.cpp new file mode 100644 index 0000000..a57dfe6 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_linux.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifndef QESP_NO_UDEV + monitor = NULL; + notifierFd = -1; + notifier = NULL; + + udev = udev_new(); + if (!udev) + qCritical() << "Unable to initialize udev notifications"; +#endif +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifndef QESP_NO_UDEV + if (notifier) { + notifier->setEnabled(false); + delete notifier; + } + + if (monitor) + udev_monitor_unref(monitor); + + if (udev) + udev_unref(udev); +#endif +} + +#ifndef QESP_NO_UDEV +static QextPortInfo portInfoFromDevice(struct udev_device *dev) +{ + QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID")); + QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID")); + + QextPortInfo pi; + pi.vendorID = vendor.toInt(0, 16); + pi.productID = product.toInt(0, 16); + pi.portName = QString::fromLatin1(udev_device_get_devnode(dev)); + pi.physName = pi.portName; + + return pi; +} +#endif + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; +#ifndef QESP_NO_UDEV + struct udev *ud = udev_new(); + if (!ud) { + qCritical() << "Unable to enumerate ports because udev is not initialized."; + return infoList; + } + + struct udev_enumerate *enumerate = udev_enumerate_new(ud); + udev_enumerate_add_match_subsystem(enumerate, "tty"); + udev_enumerate_scan_devices(enumerate); + struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); + struct udev_list_entry *entry; + udev_list_entry_foreach(entry, list) { + const char *path; + struct udev_device *dev; + + // Have to grab the actual udev device here... + path = udev_list_entry_get_name(entry); + dev = udev_device_new_from_syspath(ud, path); + + infoList.append(portInfoFromDevice(dev)); + + // Done with this device + udev_device_unref(dev); + } + // Done with the list and this udev + udev_enumerate_unref(enumerate); + udev_unref(ud); +#else + QStringList portNamePrefixes, portNameList; + portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first + + QDir dir(QLatin1String("/dev")); + portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + // remove the values which are not serial ports for e.g. /dev/ttysa + for (int i = 0; i < portNameList.size(); i++) { + bool ok; + QString current = portNameList.at(i); + // remove the ttyS part, and check, if the other part is a number + current.remove(0,4).toInt(&ok, 10); + if (!ok) { + portNameList.removeAt(i); + i--; + } + } + + // get the non standard serial ports names + // (USB-serial, bluetooth-serial, 18F PICs, and so on) + // if you know an other name prefix for serial ports please let us know + portNamePrefixes.clear(); + portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); + portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); + + foreach (QString str , portNameList) { + QextPortInfo inf; + inf.physName = QLatin1String("/dev/")+str; + inf.portName = str; + + if (str.contains(QLatin1String("ttyS"))) { + inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); + } + else if (str.contains(QLatin1String("ttyUSB"))) { + inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); + } + else if (str.contains(QLatin1String("rfcomm"))) { + inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); + } + inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? + infoList.append(inf); + } +#endif + + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup); +#ifndef QESP_NO_UDEV + Q_Q(QextSerialEnumerator); + if (!udev) { + qCritical() << "Unable to initialize notifications because udev is not initialized."; + return false; + } + + // Emit signals immediately for devices already connected (Windows version seems to behave + // this way) + foreach (QextPortInfo i, getPorts_sys()) + Q_EMIT q->deviceDiscovered(i); + + // Look for tty devices from udev. + monitor = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL); + udev_monitor_enable_receiving(monitor); + notifierFd = udev_monitor_get_fd(monitor); + notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read); + q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent())); + notifier->setEnabled(true); + + return true; +#else + return false; +#endif +} + +#ifndef QESP_NO_UDEV +void QextSerialEnumeratorPrivate::_q_deviceEvent() +{ + Q_Q(QextSerialEnumerator); + struct udev_device *dev = udev_monitor_receive_device(monitor); + if (dev) { + QextPortInfo pi = portInfoFromDevice(dev); + + QLatin1String action(udev_device_get_action(dev)); + udev_device_unref(dev); + + if (action == QLatin1String("add")) + Q_EMIT q->deviceDiscovered(pi); + else if (action == QLatin1String("remove")) + Q_EMIT q->deviceRemoved(pi); + } +} +#endif diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_osx.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_osx.cpp new file mode 100644 index 0000000..2dd0357 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_osx.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ + IONotificationPortDestroy(notificationPortRef); +} + +// static +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + io_iterator_t serialPortIterator = 0; + kern_return_t kernResult = KERN_FAILURE; + CFMutableDictionaryRef matchingDictionary; + + // first try to get any serialbsd devices, then try any USBCDC devices + if (!(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue))) { + QESP_WARNING("IOServiceMatching returned a NULL dictionary."); + return infoList; + } + CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + // then create the iterator with all the matching devices + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + serialPortIterator = 0; + + if (!(matchingDictionary = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("IOServiceNameMatching returned a NULL dictionary."); + return infoList; + } + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) { + qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult; + return infoList; + } + iterateServicesOSX(serialPortIterator, infoList); + IOObjectRelease(serialPortIterator); + + return infoList; +} + +void QextSerialEnumeratorPrivate::iterateServicesOSX(io_object_t service, QList &infoList) +{ + // Iterate through all modems found. + io_object_t usbService; + while ((usbService = IOIteratorNext(service))) { + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + getServiceDetailsOSX(usbService, &info); + infoList.append(info); + } +} + +bool QextSerialEnumeratorPrivate::getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo) +{ + bool retval = true; + CFTypeRef bsdPathAsCFString = NULL; + CFTypeRef productNameAsCFString = NULL; + CFTypeRef vendorIdAsCFNumber = NULL; + CFTypeRef productIdAsCFNumber = NULL; + // check the name of the modem's callout device + bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, 0); + + // wander up the hierarchy until we find the level that can give us the + // vendor/product IDs and the product name, if available + io_registry_entry_t parent; + kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); + while (kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber) { + if (!productNameAsCFString) + productNameAsCFString = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR("Product Name"), + kCFAllocatorDefault, 0); + vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBVendorID), + kCFAllocatorDefault, 0); + productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent, + kIOServicePlane, + CFSTR(kUSBProductID), + kCFAllocatorDefault, 0); + io_registry_entry_t oldparent = parent; + kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent); + IOObjectRelease(oldparent); + } + + io_string_t ioPathName; + IORegistryEntryGetPath(service, kIOServicePlane, ioPathName); + portInfo->physName = ioPathName; + + if (bsdPathAsCFString) { + char path[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)bsdPathAsCFString, path, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->portName = path; + CFRelease(bsdPathAsCFString); + } + + if (productNameAsCFString) { + char productName[MAXPATHLEN]; + if (CFStringGetCString((CFStringRef)productNameAsCFString, productName, + PATH_MAX, kCFStringEncodingUTF8)) + portInfo->friendName = productName; + CFRelease(productNameAsCFString); + } + + if (vendorIdAsCFNumber) { + SInt32 vID; + if (CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID)) + portInfo->vendorID = vID; + CFRelease(vendorIdAsCFNumber); + } + + if (productIdAsCFNumber) { + SInt32 pID; + if (CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID)) + portInfo->productID = pID; + CFRelease(productIdAsCFNumber); + } + IOObjectRelease(service); + return retval; +} + +// IOKit callbacks registered via setupNotifications() +void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceDiscoveredOSX(serialService); +} + +void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator) +{ + QextSerialEnumeratorPrivate *d = (QextSerialEnumeratorPrivate *)ctxt; + io_object_t serialService; + while ((serialService = IOIteratorNext(serialPortIterator))) + d->onDeviceTerminatedOSX(serialService); +} + +/* + A device has been discovered via IOKit. + Create a QextPortInfo if possible, and emit the signal indicating that we've found it. +*/ +void QextSerialEnumeratorPrivate::onDeviceDiscoveredOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceDiscovered(info); +} + +/* + Notification via IOKit that a device has been removed. + Create a QextPortInfo if possible, and emit the signal indicating that it's gone. +*/ +void QextSerialEnumeratorPrivate::onDeviceTerminatedOSX(io_object_t service) +{ + Q_Q(QextSerialEnumerator); + QextPortInfo info; + info.vendorID = 0; + info.productID = 0; + if (getServiceDetailsOSX(service, &info)) + Q_EMIT q->deviceRemoved(info); +} + +/* + Create matching dictionaries for the devices we want to get notifications for, + and add them to the current run loop. Invoke the callbacks that will be responding + to these notifications once to arm them, and discover any devices that + are currently connected at the time notifications are setup. +*/ +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool /*setup*/) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFRunLoopSourceRef notificationRunLoopSource; + CFMutableDictionaryRef classesToMatch; + CFMutableDictionaryRef cdcClassesToMatch; + io_iterator_t portIterator; + + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) { + qDebug() << "IOMasterPort returned:" << kernResult; + return false; + } + + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch == NULL) + qDebug("IOServiceMatching returned a NULL dictionary."); + else + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + if (!(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC"))) { + QESP_WARNING("couldn't create cdc matching dict"); + return false; + } + + // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one. + classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch); + cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch); + + notificationPortRef = IONotificationPortCreate(masterPort); + if (notificationPortRef == NULL) { + qDebug("IONotificationPortCreate return a NULL IONotificationPortRef."); + return false; + } + + notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef); + if (notificationRunLoopSource == NULL) { + qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef."); + return false; + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch, + deviceDiscoveredCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and grab any devices that are already connected + deviceDiscoveredCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + + kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch, + deviceTerminatedCallbackOSX, this, &portIterator); + if (kernResult != KERN_SUCCESS) { + qDebug() << "IOServiceAddMatchingNotification return:" << kernResult; + return false; + } + + // arm the callback, and clear any devices that are terminated + deviceTerminatedCallbackOSX(this, portIterator); + return true; +} + diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_p.h b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_p.h new file mode 100644 index 0000000..c69e925 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** Copyright (c) 2012 Doug Brown +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef _QEXTSERIALENUMERATOR_P_H_ +#define _QEXTSERIALENUMERATOR_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialenumerator.h" + +#ifdef Q_OS_WIN +// needed for mingw to pull in appropriate dbt business... +// probably a better way to do this +// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html +# ifdef __MINGW32__ +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef _WIN32_WINDOWS +# define _WIN32_WINDOWS 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +# endif +# include +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC +# include +#endif /*Q_OS_MAC*/ + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) +# include +extern "C" { +# include +} +#endif + +class QextSerialRegistrationWidget; +class QextSerialEnumeratorPrivate +{ + Q_DECLARE_PUBLIC(QextSerialEnumerator) +public: + QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator); + ~QextSerialEnumeratorPrivate(); + void platformSpecificInit(); + void platformSpecificDestruct(); + + static QList getPorts_sys(); + bool setUpNotifications_sys(bool setup); + +#ifdef Q_OS_WIN + LRESULT onDeviceChanged(WPARAM wParam, LPARAM lParam); + bool matchAndDispatchChangedDevice(const QString &deviceID, const GUID &guid, WPARAM wParam); +# ifdef QT_GUI_LIB + QextSerialRegistrationWidget *notificationWidget; +# endif +#endif /*Q_OS_WIN*/ + +#ifdef Q_OS_MAC + /*! + * Search for serial ports using IOKit. + * \param infoList list with result. + */ + static void iterateServicesOSX(io_object_t service, QList &infoList); + static bool getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo); + void onDeviceDiscoveredOSX(io_object_t service); + void onDeviceTerminatedOSX(io_object_t service); + friend void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + friend void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator); + + IONotificationPortRef notificationPortRef; +#endif // Q_OS_MAC + +#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV) + QSocketNotifier *notifier; + int notifierFd; + struct udev *udev; + struct udev_monitor *monitor; + + void _q_deviceEvent(); +#endif + +private: + QextSerialEnumerator *q_ptr; +}; + +#endif //_QEXTSERIALENUMERATOR_P_H_ diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_unix.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_unix.cpp new file mode 100644 index 0000000..80a4ad4 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_unix.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +} + +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +} + +QList QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList infoList; + QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet."); + return infoList; +} + +bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) +{ + Q_UNUSED(setup) + QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet"); + return false; +} diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_win.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_win.cpp new file mode 100644 index 0000000..55b71aa --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialenumerator_win.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialenumerator.h" +#include "qextserialenumerator_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "qextserialport.h" + +#ifdef QT_GUI_LIB +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +class QextSerialRegistrationWidget : public QWidget +#else +#include +class QextSerialRegistrationWidget : public QWindow +#endif +{ +public: + QextSerialRegistrationWidget(QextSerialEnumeratorPrivate *qese) { + this->qese = qese; + } + ~QextSerialRegistrationWidget() {} + +protected: + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + bool winEvent(MSG *message, long *result) { +#else + bool nativeEvent(const QByteArray & /*eventType*/, void *msg, long *result) { + MSG *message = static_cast(msg); +#endif + if (message->message == WM_DEVICECHANGE) { + qese->onDeviceChanged(message->wParam, message->lParam); + *result = 1; + return true; + } + return false; + } +private: + QextSerialEnumeratorPrivate *qese; +}; + +#endif // QT_GUI_LIB + +void QextSerialEnumeratorPrivate::platformSpecificInit() +{ +#ifdef QT_GUI_LIB + notificationWidget = 0; +#endif // QT_GUI_LIB +} + +/*! + default +*/ +void QextSerialEnumeratorPrivate::platformSpecificDestruct() +{ +#ifdef QT_GUI_LIB + if (notificationWidget) + delete notificationWidget; +#endif +} + +// see http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426(v=vs.85).aspx +// for list of GUID classes +const GUID deviceClassGuids[] = +{ + // Ports (COM & LPT ports), Class = Ports + {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Modem, Class = Modem + {0x4D36E96D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}}, + // Bluetooth Devices, Class = Bluetooth + {0xE0CBF06C, 0xCD8B, 0x4647, {0xBB, 0x8A, 0x26, 0x3B, 0x43, 0xF0, 0xF9, 0x74}}, + // Added by Arne Kristian Jansen, for use with com0com virtual ports (See Issue 54) + {0xDF799E12, 0x3C56, 0x421B, {0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78}} +}; + +/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ +#ifdef UNICODE + #define QStringToTCHAR(x) (wchar_t *) x.utf16() + #define PQStringToTCHAR(x) (wchar_t *) x->utf16() + #define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) + #define TCHARToQStringN(x,y) QString::fromUtf16((ushort *)(x),(y)) +#else + #define QStringToTCHAR(x) x.local8Bit().constData() + #define PQStringToTCHAR(x) x->local8Bit().constData() + #define TCHARToQString(x) QString::fromLocal8Bit((char *)(x)) + #define TCHARToQStringN(x,y) QString::fromLocal8Bit((char *)(x),(y)) +#endif /*UNICODE*/ + +/*! + \internal + Get value of specified property from the registry. + \a key handle to an open key. + \a property property name. + + return property value. +*/ +static QString getRegKeyValue(HKEY key, LPCTSTR property) +{ + DWORD size = 0; + DWORD type; + ::RegQueryValueEx(key, property, NULL, NULL, NULL, &size); + BYTE *buff = new BYTE[size]; + QString result; + if (::RegQueryValueEx(key, property, NULL, &type, buff, &size) == ERROR_SUCCESS) + result = TCHARToQString(buff); + ::RegCloseKey(key); + delete [] buff; + return result; +} + +/*! + \internal + Get specific property from registry. + \a devInfo pointer to the device information set that contains the interface + and its underlying device. Returned by SetupDiGetClassDevs() function. + \a devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. + this is returned by SetupDiGetDeviceInterfaceDetail() function. + \a property registry property. One of defined SPDRP_* constants. + + return property string. + */ +static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) +{ + DWORD buffSize = 0; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); + BYTE *buff = new BYTE[buffSize]; + ::SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); + QString result = TCHARToQString(buff); + delete [] buff; + return result; +} + +/*! + \internal +*/ +static bool getDeviceDetailsWin(QextPortInfo *portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData + , WPARAM wParam = DBT_DEVICEARRIVAL) +{ + portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME); + if (wParam == DBT_DEVICEARRIVAL) + portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); + portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME); + QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID); + HKEY devKey = ::SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + portInfo->portName = getRegKeyValue(devKey, TEXT("PortName")); + QRegExp idRx(QLatin1String("VID_(\\w+)&PID_(\\w+)")); + if (hardwareIDs.toUpper().contains(idRx)) { + bool dummy; + portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16); + portInfo->productID = idRx.cap(2).toInt(&dummy, 16); + //qDebug() << "got vid:" << vid << "pid:" << pid; + } + return true; +} + +/*! + \internal +*/ +static void enumerateDevicesWin(const GUID &guid, QList *infoList) +{ + HDEVINFO devInfo; + if ((devInfo = ::SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE) { + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for(int i = 0; ::SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + QextPortInfo info; + info.productID = info.vendorID = 0; + getDeviceDetailsWin(&info, devInfo, &devInfoData); + if (!info.portName.startsWith(QLatin1String("LPT"), Qt::CaseInsensitive)) + infoList->append(info); + } + ::SetupDiDestroyDeviceInfoList(devInfo); + } +} + + +static bool lessThan(const QextPortInfo &s1, const QextPortInfo &s2) +{ + if (s1.portName.startsWith(QLatin1String("COM")) + && s2.portName.startsWith(QLatin1String("COM"))) { + return s1.portName.mid(3).toInt() QextSerialEnumeratorPrivate::getPorts_sys() +{ + QList ports; + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; iwinId(), &dbh, flags) == NULL) { + QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError(); + return false; + } + // setting up notifications doesn't tell us about devices already connected + // so get those manually + foreach (QextPortInfo port, getPorts_sys()) + Q_EMIT q->deviceDiscovered(port); + return true; +#endif // QT_GUI_LIB +} + +LRESULT QextSerialEnumeratorPrivate::onDeviceChanged(WPARAM wParam, LPARAM lParam) +{ + if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + // delimiters are different across APIs...change to backslash. ugh. + QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace(QLatin1String("#"), QLatin1String("\\")); + + const int count = sizeof(deviceClassGuids)/sizeof(deviceClassGuids[0]); + for (int i=0; ideviceDiscovered(info); + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + Q_EMIT q->deviceRemoved(info); + break; + } + } + SetupDiDestroyDeviceInfoList(devInfo); + } + return rv; +} diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.cpp new file mode 100644 index 0000000..119bef8 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.cpp @@ -0,0 +1,1011 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include + +/*! + \class PortSettings + + \brief The PortSettings class contain port settings + + Structure to contain port settings. + + \code + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; + \endcode +*/ + +QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q) + :lock(QReadWriteLock::Recursive), q_ptr(q) +{ + lastErr = E_NO_ERROR; + settings.BaudRate = BAUD9600; + settings.Parity = PAR_NONE; + settings.FlowControl = FLOW_OFF; + settings.DataBits = DATA_8; + settings.StopBits = STOP_1; + settings.Timeout_Millisec = 10; + settingsDirtyFlags = DFE_ALL; + + platformSpecificInit(); +} + +QextSerialPortPrivate::~QextSerialPortPrivate() +{ + platformSpecificDestruct(); +} + +void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update) +{ + switch (baudRate) { +#ifdef Q_OS_WIN + //Windows Special + case BAUD14400: + case BAUD56000: + case BAUD128000: + case BAUD256000: + QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<isOpen()) + updatePortSettings(); + break; +#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC)) + default: + QESP_WARNING()<<"QextSerialPort does not support baudRate:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update) +{ + switch(dataBits) { + + case DATA_5: + if (settings.StopBits == STOP_2) { + QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); + } + else { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_6: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_7: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + + case DATA_8: +#ifdef Q_OS_WIN + if (settings.StopBits == STOP_1_5) { + QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); + } + else +#endif + { + settings.DataBits = dataBits; + settingsDirtyFlags |= DFE_DataBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support Data bits:"<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update) +{ + switch (stopBits) { + + /*one stop bit*/ + case STOP_1: + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + break; + +#ifdef Q_OS_WIN + /*1.5 stop bits*/ + case STOP_1_5: + QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); + if (settings.DataBits != DATA_5) { + QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; +#endif + + /*two stop bits*/ + case STOP_2: + if (settings.DataBits == DATA_5) { + QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits"); + } + else { + settings.StopBits = stopBits; + settingsDirtyFlags |= DFE_StopBits; + } + break; + default: + QESP_WARNING()<<"QextSerialPort does not support stop bits: "<isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update) +{ + settings.FlowControl = flow; + settingsDirtyFlags |= DFE_Flow; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setTimeout(long millisec, bool update) +{ + settings.Timeout_Millisec = millisec; + settingsDirtyFlags |= DFE_TimeOut; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + +void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update) +{ + setBaudRate(settings.BaudRate, false); + setDataBits(settings.DataBits, false); + setStopBits(settings.StopBits, false); + setParity(settings.Parity, false); + setFlowControl(settings.FlowControl, false); + setTimeout(settings.Timeout_Millisec, false); + settingsDirtyFlags = DFE_ALL; + if (update && q_func()->isOpen()) + updatePortSettings(); +} + + +void QextSerialPortPrivate::_q_canRead() +{ + qint64 maxSize = bytesAvailable_sys(); + if (maxSize > 0) { + char *writePtr = readBuffer.reserve(size_t(maxSize)); + qint64 bytesRead = readData_sys(writePtr, maxSize); + if (bytesRead < maxSize) + readBuffer.chop(maxSize - bytesRead); + Q_Q(QextSerialPort); + Q_EMIT q->readyRead(); + } +} + +/*! \class QextSerialPort + + \brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems. + + \section1 Usage + QextSerialPort offers both a polling and event driven API. Event driven + is typically easier to use, since you never have to worry about checking + for new data. + + \bold Example + \code + QextSerialPort *port = new QextSerialPort("COM1"); + connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable())); + port->open(); + + void MyClass::onDataAvailable() + { + QByteArray data = port->readAll(); + processNewData(usbdata); + } + \endcode + + \section1 Compatibility + The user will be notified of errors and possible portability conflicts at run-time + by default. + + For example, if a application has used BAUD1800, when it is runing under unix, you + will get following message. + + \code + QextSerialPort Portability Warning: Windows does not support baudRate:1800 + \endcode + + This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings) + or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project. + + + \bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang +*/ + +/*! + \enum QextSerialPort::QueryMode + + This enum type specifies query mode used in a serial port: + + \value Polling + asynchronously read and write + \value EventDriven + synchronously read and write +*/ + +/*! + \fn void QextSerialPort::dsrChanged(bool status) + This signal is emitted whenever dsr line has changed its state. You may + use this signal to check if device is connected. + + \a status true when DSR signal is on, false otherwise. + */ + + +/*! + \fn QueryMode QextSerialPort::queryMode() const + Get query mode. + */ + +/*! + Default constructor. Note that the name of the device used by a QextSerialPort is dependent on + your OS. Possible naming conventions and their associated OS are: + + \code + + OS Constant Used By Naming Convention + ------------- ------------- ------------------------ + Q_OS_WIN Windows COM1, COM2 + Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2 + Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0 + Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb + Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02 + Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1 + Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01 + Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1 + /dev/ttyS0, /dev/ttyS1 + \endcode + + This constructor assigns the device name to the name of the first port on the specified system. + See the other constructors if you need to open a different port. Default \a mode is EventDriven. + As a subclass of QObject, \a parent can be specified. +*/ + +QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ +#ifdef Q_OS_WIN + setPortName(QLatin1String("COM1")); + +#elif defined(Q_OS_IRIX) + setPortName(QLatin1String("/dev/ttyf1")); + +#elif defined(Q_OS_HPUX) + setPortName(QLatin1String("/dev/tty1p0")); + +#elif defined(Q_OS_SOLARIS) + setPortName(QLatin1String("/dev/ttya")); + +#elif defined(Q_OS_OSF) //formally DIGITAL UNIX + setPortName(QLatin1String("/dev/tty01")); + +#elif defined(Q_OS_FREEBSD) + setPortName(QLatin1String("/dev/ttyd1")); + +#elif defined(Q_OS_OPENBSD) + setPortName(QLatin1String("/dev/tty00")); + +#else + setPortName(QLatin1String("/dev/ttyS0")); +#endif + setQueryMode(mode); +} + +/*! + Constructs a serial port attached to the port specified by name. + \a name is the name of the device, which is windowsystem-specific, + e.g."COM1" or "/dev/ttyS0". \a mode +*/ +QextSerialPort::QextSerialPort(const QString &name, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + setQueryMode(mode); + setPortName(name); +} + +/*! + Constructs a port with default name and specified \a settings. +*/ +QextSerialPort::QextSerialPort(const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Constructs a port with specified \a name , \a mode and \a settings. +*/ +QextSerialPort::QextSerialPort(const QString &name, const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent) + : QIODevice(parent), d_ptr(new QextSerialPortPrivate(this)) +{ + Q_D(QextSerialPort); + setPortName(name); + setQueryMode(mode); + d->setPortSettings(settings); +} + +/*! + Opens a serial port and sets its OpenMode to \a mode. + Note that this function does not specify which device to open. + Returns true if successful; otherwise returns false.This function has no effect + if the port associated with the class is already open. The port is also + configured to the current settings, as stored in the settings structure. +*/ +bool QextSerialPort::open(OpenMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != QIODevice::NotOpen && !isOpen()) + d->open_sys(mode); + + return isOpen(); +} + + +/*! \reimp + Closes a serial port. This function has no effect if the serial port associated with the class + is not currently open. +*/ +void QextSerialPort::close() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) { + // Be a good QIODevice and call QIODevice::close() before really close() + // so the aboutToClose() signal is emitted at the proper time + QIODevice::close(); // mark ourselves as closed + d->close_sys(); + d->readBuffer.clear(); + } +} + +/*! + Flushes all pending I/O to the serial port. This function has no effect if the serial port + associated with the class is not currently open. +*/ +void QextSerialPort::flush() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->flush_sys(); +} + +/*! \reimp + Returns the number of bytes waiting in the port's receive queue. This function will return 0 if + the port is not currently open, or -1 on error. +*/ +qint64 QextSerialPort::bytesAvailable() const +{ + QWriteLocker locker(&d_func()->lock); + if (isOpen()) { + qint64 bytes = d_func()->bytesAvailable_sys(); + if (bytes != -1) { + return bytes + d_func()->readBuffer.size() + + QIODevice::bytesAvailable(); + } else { + return -1; + } + } + return 0; +} + +/*! \reimp + +*/ +bool QextSerialPort::canReadLine() const +{ + QReadLocker locker(&d_func()->lock); + return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine(); +} + +/*! + * Set desired serial communication handling style. You may choose from polling + * or event driven approach. This function does nothing when port is open; to + * apply changes port must be reopened. + * + * In event driven approach read() and write() functions are acting + * asynchronously. They return immediately and the operation is performed in + * the background, so they doesn't freeze the calling thread. + * To determine when operation is finished, QextSerialPort runs separate thread + * and monitors serial port events. Whenever the event occurs, adequate signal + * is emitted. + * + * When polling is set, read() and write() are acting synchronously. Signals are + * not working in this mode and some functions may not be available. The advantage + * of polling is that it generates less overhead due to lack of signals emissions + * and it doesn't start separate thread to monitor events. + * + * Generally event driven approach is more capable and friendly, although some + * applications may need as low overhead as possible and then polling comes. + * + * \a mode query mode. + */ +void QextSerialPort::setQueryMode(QueryMode mode) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (mode != d->queryMode) { + d->queryMode = mode; + } +} + +/*! + Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". +*/ +void QextSerialPort::setPortName(const QString &name) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + d->port = name; +} + +/*! + Returns the name set by setPortName(). +*/ +QString QextSerialPort::portName() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->port; +} + +QextSerialPort::QueryMode QextSerialPort::queryMode() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->queryMode; +} + +/*! + Reads all available data from the device, and returns it as a QByteArray. + This function has no way of reporting errors; returning an empty QByteArray() + can mean either that no data was currently available for reading, or that an error occurred. +*/ +QByteArray QextSerialPort::readAll() +{ + int avail = this->bytesAvailable(); + return (avail > 0) ? this->read(avail) : QByteArray(); +} + +/*! + Returns the baud rate of the serial port. For a list of possible return values see + the definition of the enum BaudRateType. +*/ +BaudRateType QextSerialPort::baudRate() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.BaudRate; +} + +/*! + Returns the number of data bits used by the port. For a list of possible values returned by + this function, see the definition of the enum DataBitsType. +*/ +DataBitsType QextSerialPort::dataBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.DataBits; +} + +/*! + Returns the type of parity used by the port. For a list of possible values returned by + this function, see the definition of the enum ParityType. +*/ +ParityType QextSerialPort::parity() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.Parity; +} + +/*! + Returns the number of stop bits used by the port. For a list of possible return values, see + the definition of the enum StopBitsType. +*/ +StopBitsType QextSerialPort::stopBits() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.StopBits; +} + +/*! + Returns the type of flow control used by the port. For a list of possible values returned + by this function, see the definition of the enum FlowType. +*/ +FlowType QextSerialPort::flowControl() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->settings.FlowControl; +} + +/*! + \reimp + Returns true if device is sequential, otherwise returns false. Serial port is sequential device + so this function always returns true. Check QIODevice::isSequential() documentation for more + information. +*/ +bool QextSerialPort::isSequential() const +{ + return true; +} + +/*! + Return the error number, or 0 if no error occurred. +*/ +ulong QextSerialPort::lastError() const +{ + QReadLocker locker(&d_func()->lock); + return d_func()->lastErr; +} + +/*! + Returns the line status as stored by the port function. This function will retrieve the states + of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines + can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned + long with specific bits indicating which lines are high. The following constants should be used + to examine the states of individual lines: + + \code + Mask Line + ------ ---- + LS_CTS CTS + LS_DSR DSR + LS_DCD DCD + LS_RI RI + LS_RTS RTS (POSIX only) + LS_DTR DTR (POSIX only) + LS_ST Secondary TXD (POSIX only) + LS_SR Secondary RXD (POSIX only) + \endcode + + This function will return 0 if the port associated with the class is not currently open. +*/ +unsigned long QextSerialPort::lineStatus() +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + return d->lineStatus_sys(); + return 0; +} + +/*! + Returns a human-readable description of the last device error that occurred. +*/ +QString QextSerialPort::errorString() +{ + Q_D(QextSerialPort); + QReadLocker locker(&d->lock); + switch(d->lastErr) { + case E_NO_ERROR: + return tr("No Error has occurred"); + case E_INVALID_FD: + return tr("Invalid file descriptor (port was not opened correctly)"); + case E_NO_MEMORY: + return tr("Unable to allocate memory tables (POSIX)"); + case E_CAUGHT_NON_BLOCKED_SIGNAL: + return tr("Caught a non-blocked signal (POSIX)"); + case E_PORT_TIMEOUT: + return tr("Operation timed out (POSIX)"); + case E_INVALID_DEVICE: + return tr("The file opened by the port is not a valid device"); + case E_BREAK_CONDITION: + return tr("The port detected a break condition"); + case E_FRAMING_ERROR: + return tr("The port detected a framing error (usually caused by incorrect baud rate settings)"); + case E_IO_ERROR: + return tr("There was an I/O error while communicating with the port"); + case E_BUFFER_OVERRUN: + return tr("Character buffer overrun"); + case E_RECEIVE_OVERFLOW: + return tr("Receive buffer overflow"); + case E_RECEIVE_PARITY_ERROR: + return tr("The port detected a parity error in the received data"); + case E_TRANSMIT_OVERFLOW: + return tr("Transmit buffer overflow"); + case E_READ_FAILED: + return tr("General read operation failure"); + case E_WRITE_FAILED: + return tr("General write operation failure"); + case E_FILE_NOT_FOUND: + return tr("The %1 file doesn't exists").arg(this->portName()); + case E_PERMISSION_DENIED: + return tr("Permission denied"); + case E_AGAIN: + return tr("Device is already locked"); + default: + return tr("Unknown error: %1").arg(d->lastErr); + } +} + +/*! + Destructs the QextSerialPort object. +*/ +QextSerialPort::~QextSerialPort() +{ + if (isOpen()) { + close(); + } + delete d_ptr; +} + +/*! + Sets the flow control used by the port to \a flow. Possible values of flow are: + \code + FLOW_OFF No flow control + FLOW_HARDWARE Hardware (RTS/CTS) flow control + FLOW_XONXOFF Software (XON/XOFF) flow control + \endcode +*/ +void QextSerialPort::setFlowControl(FlowType flow) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.FlowControl != flow) + d->setFlowControl(flow, true); +} + +/*! + Sets the parity associated with the serial port to \a parity. The possible values of parity are: + \code + PAR_SPACE Space Parity + PAR_MARK Mark Parity + PAR_NONE No Parity + PAR_EVEN Even Parity + PAR_ODD Odd Parity + \endcode +*/ +void QextSerialPort::setParity(ParityType parity) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Parity != parity) + d->setParity(parity, true); +} + +/*! + Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are: + \code + DATA_5 5 data bits + DATA_6 6 data bits + DATA_7 7 data bits + DATA_8 8 data bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 5 data bits cannot be used with 2 stop bits. + \o 1.5 stop bits can only be used with 5 data bits. + \o 8 data bits cannot be used with space parity on POSIX systems. + \endlist + */ +void QextSerialPort::setDataBits(DataBitsType dataBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.DataBits != dataBits) + d->setDataBits(dataBits, true); +} + +/*! + Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are: + \code + STOP_1 1 stop bit + STOP_1_5 1.5 stop bits + STOP_2 2 stop bits + \endcode + + \bold note: + This function is subject to the following restrictions: + \list + \o 2 stop bits cannot be used with 5 data bits. + \o 1.5 stop bits cannot be used with 6 or more data bits. + \o POSIX does not support 1.5 stop bits. + \endlist +*/ +void QextSerialPort::setStopBits(StopBitsType stopBits) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.StopBits != stopBits) + d->setStopBits(stopBits, true); +} + +/*! + Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on + all platforms. The following table shows translations of the various baud rate + constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * + are speeds that are usable on both Windows and POSIX. + \code + + RATE Windows Speed POSIX Speed + ----------- ------------- ----------- + BAUD50 X 50 + BAUD75 X 75 + *BAUD110 110 110 + BAUD134 X 134.5 + BAUD150 X 150 + BAUD200 X 200 + *BAUD300 300 300 + *BAUD600 600 600 + *BAUD1200 1200 1200 + BAUD1800 X 1800 + *BAUD2400 2400 2400 + *BAUD4800 4800 4800 + *BAUD9600 9600 9600 + BAUD14400 14400 X + *BAUD19200 19200 19200 + *BAUD38400 38400 38400 + BAUD56000 56000 X + *BAUD57600 57600 57600 + BAUD76800 X 76800 + *BAUD115200 115200 115200 + BAUD128000 128000 X + BAUD230400 X 230400 + BAUD256000 256000 X + BAUD460800 X 460800 + BAUD500000 X 500000 + BAUD576000 X 576000 + BAUD921600 X 921600 + BAUD1000000 X 1000000 + BAUD1152000 X 1152000 + BAUD1500000 X 1500000 + BAUD2000000 X 2000000 + BAUD2500000 X 2500000 + BAUD3000000 X 3000000 + BAUD3500000 X 3500000 + BAUD4000000 X 4000000 + \endcode +*/ + +void QextSerialPort::setBaudRate(BaudRateType baudRate) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.BaudRate != baudRate) + d->setBaudRate(baudRate, true); +} + +/*! + For Unix: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Note that this is a per-character timeout, i.e. the port will wait this long for each + individual character, not for the whole read operation. This timeout also applies to the + bytesWaiting() function. + + \bold note: + POSIX does not support millisecond-level control for I/O timeout values. Any + timeout set using this function will be set to the next lowest tenth of a second for + the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds + will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and + writing the port. However millisecond-level control is allowed by the select() system call, + so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for + the purpose of detecting available bytes in the read buffer. + + For Windows: + + Sets the read and write timeouts for the port to \a millisec milliseconds. + Setting 0 indicates that timeouts are not used for read nor write operations; + however read() and write() functions will still block. Set -1 to provide + non-blocking behaviour (read() and write() will return immediately). + + \bold note: this function does nothing in event driven mode. +*/ +void QextSerialPort::setTimeout(long millisec) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (d->settings.Timeout_Millisec != millisec) + d->setTimeout(millisec, true); +} + +/*! + Sets DTR line to the requested state (\a set default to high). This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setDtr(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setDtr_sys(set); +} + +/*! + Sets RTS line to the requested state \a set (high by default). + This function will have no effect if + the port associated with the class is not currently open. +*/ +void QextSerialPort::setRts(bool set) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + if (isOpen()) + d->setRts_sys(set); +} + +/*! \reimp + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::readData(char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + qint64 bytesFromBuffer = 0; + if (!d->readBuffer.isEmpty()) { + bytesFromBuffer = d->readBuffer.read(data, maxSize); + if (bytesFromBuffer == maxSize) + return bytesFromBuffer; + } + qint64 bytesFromDevice = d->readData_sys(data+bytesFromBuffer, maxSize-bytesFromBuffer); + if (bytesFromDevice < 0) { + return -1; + } + return bytesFromBuffer + bytesFromDevice; +} + +/*! \reimp + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPort::writeData(const char *data, qint64 maxSize) +{ + Q_D(QextSerialPort); + QWriteLocker locker(&d->lock); + return d->writeData_sys(data, maxSize); +} + +#include "moc_qextserialport.cpp" diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.h b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.h new file mode 100644 index 0000000..5334e94 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.h @@ -0,0 +1,240 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_H_ +#define _QEXTSERIALPORT_H_ + +#include +#include "qextserialport_global.h" +#ifdef Q_OS_UNIX +#include +#endif +/*line status constants*/ +// ### QESP2.0 move to enum +#define LS_CTS 0x01 +#define LS_DSR 0x02 +#define LS_DCD 0x04 +#define LS_RI 0x08 +#define LS_RTS 0x10 +#define LS_DTR 0x20 +#define LS_ST 0x40 +#define LS_SR 0x80 + +/*error constants*/ +// ### QESP2.0 move to enum +#define E_NO_ERROR 0 +#define E_INVALID_FD 1 +#define E_NO_MEMORY 2 +#define E_CAUGHT_NON_BLOCKED_SIGNAL 3 +#define E_PORT_TIMEOUT 4 +#define E_INVALID_DEVICE 5 +#define E_BREAK_CONDITION 6 +#define E_FRAMING_ERROR 7 +#define E_IO_ERROR 8 +#define E_BUFFER_OVERRUN 9 +#define E_RECEIVE_OVERFLOW 10 +#define E_RECEIVE_PARITY_ERROR 11 +#define E_TRANSMIT_OVERFLOW 12 +#define E_READ_FAILED 13 +#define E_WRITE_FAILED 14 +#define E_FILE_NOT_FOUND 15 +#define E_PERMISSION_DENIED 16 +#define E_AGAIN 17 + +enum BaudRateType +{ +#if defined(Q_OS_UNIX) || defined(qdoc) + BAUD50 = 50, //POSIX ONLY + BAUD75 = 75, //POSIX ONLY + BAUD134 = 134, //POSIX ONLY + BAUD150 = 150, //POSIX ONLY + BAUD200 = 200, //POSIX ONLY + BAUD1800 = 1800, //POSIX ONLY +# if defined(B76800) || defined(qdoc) + BAUD76800 = 76800, //POSIX ONLY +# endif +# if (defined(B230400) && defined(B4000000)) || defined(qdoc) + BAUD230400 = 230400, //POSIX ONLY + BAUD460800 = 460800, //POSIX ONLY + BAUD500000 = 500000, //POSIX ONLY + BAUD576000 = 576000, //POSIX ONLY + BAUD921600 = 921600, //POSIX ONLY + BAUD1000000 = 1000000, //POSIX ONLY + BAUD1152000 = 1152000, //POSIX ONLY + BAUD1500000 = 1500000, //POSIX ONLY + BAUD2000000 = 2000000, //POSIX ONLY + BAUD2500000 = 2500000, //POSIX ONLY + BAUD3000000 = 3000000, //POSIX ONLY + BAUD3500000 = 3500000, //POSIX ONLY + BAUD4000000 = 4000000, //POSIX ONLY +# endif +#endif //Q_OS_UNIX +#if defined(Q_OS_WIN) || defined(qdoc) + BAUD14400 = 14400, //WINDOWS ONLY + BAUD56000 = 56000, //WINDOWS ONLY + BAUD128000 = 128000, //WINDOWS ONLY + BAUD256000 = 256000, //WINDOWS ONLY +#endif //Q_OS_WIN + BAUD110 = 110, + BAUD300 = 300, + BAUD600 = 600, + BAUD1200 = 1200, + BAUD2400 = 2400, + BAUD4800 = 4800, + BAUD9600 = 9600, + BAUD19200 = 19200, + BAUD38400 = 38400, + BAUD57600 = 57600, + BAUD115200 = 115200 +}; + +enum DataBitsType +{ + DATA_5 = 5, + DATA_6 = 6, + DATA_7 = 7, + DATA_8 = 8 +}; + +enum ParityType +{ + PAR_NONE, + PAR_ODD, + PAR_EVEN, +#if defined(Q_OS_WIN) || defined(qdoc) + PAR_MARK, //WINDOWS ONLY +#endif + PAR_SPACE +}; + +enum StopBitsType +{ + STOP_1, +#if defined(Q_OS_WIN) || defined(qdoc) + STOP_1_5, //WINDOWS ONLY +#endif + STOP_2 +}; + +enum FlowType +{ + FLOW_OFF, + FLOW_HARDWARE, + FLOW_XONXOFF +}; + +/** + * structure to contain port settings + */ +struct PortSettings +{ + BaudRateType BaudRate; + DataBitsType DataBits; + ParityType Parity; + StopBitsType StopBits; + FlowType FlowControl; + long Timeout_Millisec; +}; + +class QextSerialPortPrivate; +class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextSerialPort) + Q_ENUMS(QueryMode) + Q_PROPERTY(QString portName READ portName WRITE setPortName) + Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode) +public: + enum QueryMode { + Polling, + EventDriven + }; + + explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0); + explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0); + QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent=0); + + ~QextSerialPort(); + + QString portName() const; + QueryMode queryMode() const; + BaudRateType baudRate() const; + DataBitsType dataBits() const; + ParityType parity() const; + StopBitsType stopBits() const; + FlowType flowControl() const; + + bool open(OpenMode mode); + bool isSequential() const; + void close(); + void flush(); + qint64 bytesAvailable() const; + bool canReadLine() const; + QByteArray readAll(); + + ulong lastError() const; + + ulong lineStatus(); + QString errorString(); + +public Q_SLOTS: + void setPortName(const QString &name); + void setQueryMode(QueryMode mode); + void setBaudRate(BaudRateType); + void setDataBits(DataBitsType); + void setParity(ParityType); + void setStopBits(StopBitsType); + void setFlowControl(FlowType); + void setTimeout(long); + + void setDtr(bool set=true); + void setRts(bool set=true); + +Q_SIGNALS: + void dsrChanged(bool status); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(QextSerialPort) + +#ifdef Q_OS_WIN + Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE)) +#endif + Q_PRIVATE_SLOT(d_func(), void _q_canRead()) + + QextSerialPortPrivate *const d_ptr; +}; + +#endif diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.pri b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.pri new file mode 100644 index 0000000..461d56f --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +PUBLIC_HEADERS += $$PWD/qextserialport.h \ + $$PWD/qextserialenumerator.h \ + $$PWD/qextserialport_global.h + +HEADERS += $$PUBLIC_HEADERS \ + $$PWD/qextserialport_p.h \ + $$PWD/qextserialenumerator_p.h \ + +SOURCES += $$PWD/qextserialport.cpp \ + $$PWD/qextserialenumerator.cpp +unix { + SOURCES += $$PWD/qextserialport_unix.cpp + linux* { + SOURCES += $$PWD/qextserialenumerator_linux.cpp + } else:macx { + SOURCES += $$PWD/qextserialenumerator_osx.cpp + } else { + SOURCES += $$PWD/qextserialenumerator_unix.cpp + } +} +win32:SOURCES += $$PWD/qextserialport_win.cpp \ + $$PWD/qextserialenumerator_win.cpp + +linux*{ + !qesp_linux_udev:DEFINES += QESP_NO_UDEV + qesp_linux_udev: LIBS += -ludev +} + +macx:LIBS += -framework IOKit -framework CoreFoundation +win32:LIBS += -lsetupapi -ladvapi32 -luser32 + +# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work +linux*:DEFINES += __linux__ diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_global.h b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_global.h new file mode 100644 index 0000000..824d455 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_global.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTSERIALPORT_GLOBAL_H +#define QEXTSERIALPORT_GLOBAL_H + +#include + +#ifdef QEXTSERIALPORT_BUILD_SHARED +# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT +#elif defined(QEXTSERIALPORT_USING_SHARED) +# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT +#else +# define QEXTSERIALPORT_EXPORT +#endif + +// ### for compatible with old version. should be removed in QESP 2.0 +#ifdef _TTY_NOWARN_ +# define QESP_NO_WARN +#endif +#ifdef _TTY_NOWARN_PORT_ +# define QESP_NO_PORTABILITY_WARN +#endif + +/*if all warning messages are turned off, flag portability warnings to be turned off as well*/ +#ifdef QESP_NO_WARN +# define QESP_NO_PORTABILITY_WARN +#endif + +/*macros for warning and debug messages*/ +#ifdef QESP_NO_PORTABILITY_WARN +# define QESP_PORTABILITY_WARNING while (false)qWarning +#else +# define QESP_PORTABILITY_WARNING qWarning +#endif /*QESP_NOWARN_PORT*/ + +#ifdef QESP_NO_WARN +# define QESP_WARNING while (false)qWarning +#else +# define QESP_WARNING qWarning +#endif /*QESP_NOWARN*/ + +#endif // QEXTSERIALPORT_GLOBAL_H + diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_p.h b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_p.h new file mode 100644 index 0000000..d278a17 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_p.h @@ -0,0 +1,251 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _QEXTSERIALPORT_P_H_ +#define _QEXTSERIALPORT_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qextserialport.h" +#include +#ifdef Q_OS_UNIX +# include +#elif (defined Q_OS_WIN) +# include +#endif +#include + +// This is QextSerialPort's read buffer, needed by posix system. +// ref: QRingBuffer & QIODevicePrivateLinearBuffer +class QextReadBuffer +{ +public: + inline QextReadBuffer(size_t growth=4096) + : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { + } + + ~QextReadBuffer() { + delete [] buf; + } + + inline void clear() { + first = buf; + len = 0; + } + + inline int size() const { + return len; + } + + inline bool isEmpty() const { + return len == 0; + } + + inline int read(char *target, int size) { + int r = qMin(size, len); + if (r == 1) { + *target = *first; + --len; + ++first; + } else { + memcpy(target, first, r); + len -= r; + first += r; + } + return r; + } + + inline char *reserve(size_t size) { + if ((first - buf) + len + size > capacity) { + size_t newCapacity = qMax(capacity, basicBlockSize); + while (newCapacity < len + size) + newCapacity *= 2; + if (newCapacity > capacity) { + // allocate more space + char *newBuf = new char[newCapacity]; + memmove(newBuf, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf, first, len); + } + first = buf; + } + char *writePtr = first + len; + len += (int)size; + return writePtr; + } + + inline void chop(int size) { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + + inline void squeeze() { + if (first != buf) { + memmove(buf, first, len); + first = buf; + } + size_t newCapacity = basicBlockSize; + while (newCapacity < size_t(len)) + newCapacity *= 2; + if (newCapacity < capacity) { + char *tmp = static_cast(realloc(buf, newCapacity)); + if (tmp) { + buf = tmp; + capacity = newCapacity; + } + } + } + + inline QByteArray readAll() { + char *f = first; + int l = len; + clear(); + return QByteArray(f, l); + } + + inline int readLine(char *target, int size) { + int r = qMin(size, len); + char *eol = static_cast(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return int(r); + } + + inline bool canReadLine() const { + return memchr(first, '\n', len); + } + +private: + int len; + char *first; + char *buf; + size_t capacity; + size_t basicBlockSize; +}; + +class QWinEventNotifier; +class QReadWriteLock; +class QSocketNotifier; + +class QextSerialPortPrivate +{ + Q_DECLARE_PUBLIC(QextSerialPort) +public: + QextSerialPortPrivate(QextSerialPort *q); + ~QextSerialPortPrivate(); + enum DirtyFlagEnum + { + DFE_BaudRate = 0x0001, + DFE_Parity = 0x0002, + DFE_StopBits = 0x0004, + DFE_DataBits = 0x0008, + DFE_Flow = 0x0010, + DFE_TimeOut = 0x0100, + DFE_ALL = 0x0fff, + DFE_Settings_Mask = 0x00ff //without TimeOut + }; + mutable QReadWriteLock lock; + QString port; + PortSettings settings; + QextReadBuffer readBuffer; + int settingsDirtyFlags; + ulong lastErr; + QextSerialPort::QueryMode queryMode; + + // platform specific members +#ifdef Q_OS_UNIX + int fd; + QSocketNotifier *readNotifier; + struct termios currentTermios; + struct termios oldTermios; +#elif (defined Q_OS_WIN) + HANDLE handle; + OVERLAPPED overlap; + COMMCONFIG commConfig; + COMMTIMEOUTS commTimeouts; + QWinEventNotifier *winEventNotifier; + DWORD eventMask; + QList pendingWrites; + QReadWriteLock *bytesToWriteLock; +#endif + + /*fill PortSettings*/ + void setBaudRate(BaudRateType baudRate, bool update=true); + void setDataBits(DataBitsType dataBits, bool update=true); + void setParity(ParityType parity, bool update=true); + void setStopBits(StopBitsType stopbits, bool update=true); + void setFlowControl(FlowType flow, bool update=true); + void setTimeout(long millisec, bool update=true); + void setPortSettings(const PortSettings &settings, bool update=true); + + void platformSpecificDestruct(); + void platformSpecificInit(); + void translateError(ulong error); + void updatePortSettings(); + + qint64 readData_sys(char *data, qint64 maxSize); + qint64 writeData_sys(const char *data, qint64 maxSize); + void setDtr_sys(bool set=true); + void setRts_sys(bool set=true); + bool open_sys(QIODevice::OpenMode mode); + bool close_sys(); + bool flush_sys(); + ulong lineStatus_sys(); + qint64 bytesAvailable_sys() const; + +#ifdef Q_OS_WIN + void _q_onWinEvent(HANDLE h); +#endif + void _q_canRead(); + + QextSerialPort *q_ptr; +}; + +#endif //_QEXTSERIALPORT_P_H_ diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_unix.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_unix.cpp new file mode 100644 index 0000000..4c02a20 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_unix.cpp @@ -0,0 +1,460 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void QextSerialPortPrivate::platformSpecificInit() +{ + fd = 0; + readNotifier = 0; +} + +/*! + Standard destructor. +*/ +void QextSerialPortPrivate::platformSpecificDestruct() +{ +} + +static QString fullPortName(const QString &name) +{ + if (name.startsWith(QLatin1Char('/'))) + return name; + return QLatin1String("/dev/")+name; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + //note: linux 2.6.21 seems to ignore O_NDELAY flag + if ((fd = ::open(fullPortName(port).toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { + + /*In the Private class, We can not call QIODevice::open()*/ + q->setOpenMode(mode); // Flag the port as opened + ::tcgetattr(fd, &oldTermios); // Save the old termios + currentTermios = oldTermios; // Make a working copy + ::cfmakeraw(¤tTermios); // Enable raw access + + /*set up other port settings*/ + currentTermios.c_cflag |= CREAD|CLOCAL; + currentTermios.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + currentTermios.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + currentTermios.c_oflag &= (~OPOST); + currentTermios.c_cc[VMIN] = 0; +#ifdef _POSIX_VDISABLE // Is a disable character available on this system? + // Some systems allow for per-device disable-characters, so get the + // proper value for the configured device + const long vdisable = ::fpathconf(fd, _PC_VDISABLE); + currentTermios.c_cc[VINTR] = vdisable; + currentTermios.c_cc[VQUIT] = vdisable; + currentTermios.c_cc[VSTART] = vdisable; + currentTermios.c_cc[VSTOP] = vdisable; + currentTermios.c_cc[VSUSP] = vdisable; +#endif //_POSIX_VDISABLE + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + if (queryMode == QextSerialPort::EventDriven) { + readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); + q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead())); + } + return true; + } else { + translateError(errno); + return false; + } +} + +bool QextSerialPortPrivate::close_sys() +{ + // Force a flush and then restore the original termios + flush_sys(); + // Using both TCSAFLUSH and TCSANOW here discards any pending input + ::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios + ::close(fd); + if (readNotifier) { + delete readNotifier; + readNotifier = 0; + } + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + ::tcdrain(fd); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + int bytesQueued; + if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) { + return (qint64)-1; + } + return bytesQueued; +} + +/*! + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + switch (error) { + case EBADF: + case ENOTTY: + lastErr = E_INVALID_FD; + break; + case EINTR: + lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL; + break; + case ENOMEM: + lastErr = E_NO_MEMORY; + break; + case EACCES: + lastErr = E_PERMISSION_DENIED; + break; + case EAGAIN: + lastErr = E_AGAIN; + break; + } +} + +void QextSerialPortPrivate::setDtr_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_DTR; + else + status &= ~TIOCM_DTR; + ::ioctl(fd, TIOCMSET, &status); +} + +void QextSerialPortPrivate::setRts_sys(bool set) +{ + int status; + ::ioctl(fd, TIOCMGET, &status); + if (set) + status |= TIOCM_RTS; + else + status &= ~TIOCM_RTS; + ::ioctl(fd, TIOCMSET, &status); +} + +unsigned long QextSerialPortPrivate::lineStatus_sys() +{ + unsigned long Status=0, Temp=0; + ::ioctl(fd, TIOCMGET, &Temp); + if (Temp & TIOCM_CTS) Status |= LS_CTS; + if (Temp & TIOCM_DSR) Status |= LS_DSR; + if (Temp & TIOCM_RI) Status |= LS_RI; + if (Temp & TIOCM_CD) Status |= LS_DCD; + if (Temp & TIOCM_DTR) Status |= LS_DTR; + if (Temp & TIOCM_RTS) Status |= LS_RTS; + if (Temp & TIOCM_ST) Status |= LS_ST; + if (Temp & TIOCM_SR) Status |= LS_SR; + return Status; +} + +/*! + Reads a block of data from the serial port. This function will read at most maxSize bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + int retVal = ::read(fd, data, maxSize); + if (retVal == -1) + lastErr = E_READ_FAILED; + + return retVal; +} + +/*! + Writes a block of data to the serial port. This function will write maxSize bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + int retVal = ::write(fd, data, maxSize); + if (retVal == -1) + lastErr = E_WRITE_FAILED; + + return (qint64)retVal; +} + +static void setBaudRate2Termios(termios *config, int baudRate) +{ +#ifdef CBAUD + config->c_cflag &= (~CBAUD); + config->c_cflag |= baudRate; +#else + ::cfsetispeed(config, baudRate); + ::cfsetospeed(config, baudRate); +#endif +} + +/* + All the platform settings was performed in this function. +*/ +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_func()->isOpen() || !settingsDirtyFlags) + return; + + if (settingsDirtyFlags & DFE_BaudRate) { + switch (settings.BaudRate) { + case BAUD50: + setBaudRate2Termios(¤tTermios, B50); + break; + case BAUD75: + setBaudRate2Termios(¤tTermios, B75); + break; + case BAUD110: + setBaudRate2Termios(¤tTermios, B110); + break; + case BAUD134: + setBaudRate2Termios(¤tTermios, B134); + break; + case BAUD150: + setBaudRate2Termios(¤tTermios, B150); + break; + case BAUD200: + setBaudRate2Termios(¤tTermios, B200); + break; + case BAUD300: + setBaudRate2Termios(¤tTermios, B300); + break; + case BAUD600: + setBaudRate2Termios(¤tTermios, B600); + break; + case BAUD1200: + setBaudRate2Termios(¤tTermios, B1200); + break; + case BAUD1800: + setBaudRate2Termios(¤tTermios, B1800); + break; + case BAUD2400: + setBaudRate2Termios(¤tTermios, B2400); + break; + case BAUD4800: + setBaudRate2Termios(¤tTermios, B4800); + break; + case BAUD9600: + setBaudRate2Termios(¤tTermios, B9600); + break; + case BAUD19200: + setBaudRate2Termios(¤tTermios, B19200); + break; + case BAUD38400: + setBaudRate2Termios(¤tTermios, B38400); + break; + case BAUD57600: + setBaudRate2Termios(¤tTermios, B57600); + break; +#ifdef B76800 + case BAUD76800: + setBaudRate2Termios(¤tTermios, B76800); + break; +#endif + case BAUD115200: + setBaudRate2Termios(¤tTermios, B115200); + break; +#if defined(B230400) && defined(B4000000) + case BAUD230400: + setBaudRate2Termios(¤tTermios, B230400); + break; + case BAUD460800: + setBaudRate2Termios(¤tTermios, B460800); + break; + case BAUD500000: + setBaudRate2Termios(¤tTermios, B500000); + break; + case BAUD576000: + setBaudRate2Termios(¤tTermios, B576000); + break; + case BAUD921600: + setBaudRate2Termios(¤tTermios, B921600); + break; + case BAUD1000000: + setBaudRate2Termios(¤tTermios, B1000000); + break; + case BAUD1152000: + setBaudRate2Termios(¤tTermios, B1152000); + break; + case BAUD1500000: + setBaudRate2Termios(¤tTermios, B1500000); + break; + case BAUD2000000: + setBaudRate2Termios(¤tTermios, B2000000); + break; + case BAUD2500000: + setBaudRate2Termios(¤tTermios, B2500000); + break; + case BAUD3000000: + setBaudRate2Termios(¤tTermios, B3000000); + break; + case BAUD3500000: + setBaudRate2Termios(¤tTermios, B3500000); + break; + case BAUD4000000: + setBaudRate2Termios(¤tTermios, B4000000); + break; +#endif +#ifdef Q_OS_MAC + default: + setBaudRate2Termios(¤tTermios, settings.BaudRate); + break; +#endif + } + } + if (settingsDirtyFlags & DFE_Parity) { + switch (settings.Parity) { + case PAR_SPACE: + /*space parity not directly supported - add an extra data bit to simulate it*/ + settingsDirtyFlags |= DFE_DataBits; + break; + case PAR_NONE: + currentTermios.c_cflag &= (~PARENB); + break; + case PAR_EVEN: + currentTermios.c_cflag &= (~PARODD); + currentTermios.c_cflag |= PARENB; + break; + case PAR_ODD: + currentTermios.c_cflag |= (PARENB|PARODD); + break; + } + } + /*must after Parity settings*/ + if (settingsDirtyFlags & DFE_DataBits) { + if (settings.Parity != PAR_SPACE) { + currentTermios.c_cflag &= (~CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS5; + break; + case DATA_6: + currentTermios.c_cflag |= CS6; + break; + case DATA_7: + currentTermios.c_cflag |= CS7; + break; + case DATA_8: + currentTermios.c_cflag |= CS8; + break; + } + } else { + /*space parity not directly supported - add an extra data bit to simulate it*/ + currentTermios.c_cflag &= ~(PARENB|CSIZE); + switch(settings.DataBits) { + case DATA_5: + currentTermios.c_cflag |= CS6; + break; + case DATA_6: + currentTermios.c_cflag |= CS7; + break; + case DATA_7: + currentTermios.c_cflag |= CS8; + break; + case DATA_8: + /*this will never happen, put here to Suppress an warning*/ + break; + } + } + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + currentTermios.c_cflag &= (~CSTOPB); + break; + case STOP_2: + currentTermios.c_cflag |= CSTOPB; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + case FLOW_OFF: + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + case FLOW_XONXOFF: + /*software (XON/XOFF) flow control*/ + currentTermios.c_cflag &= (~CRTSCTS); + currentTermios.c_iflag |= (IXON|IXOFF|IXANY); + break; + case FLOW_HARDWARE: + currentTermios.c_cflag |= CRTSCTS; + currentTermios.c_iflag &= (~(IXON|IXOFF|IXANY)); + break; + } + } + + /*if any thing in currentTermios changed, flush*/ + if (settingsDirtyFlags & DFE_Settings_Mask) + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + + if (settingsDirtyFlags & DFE_TimeOut) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + ::fcntl(fd, F_SETFL, O_NDELAY); + } + else { + //O_SYNC should enable blocking ::write() + //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2) + ::fcntl(fd, F_SETFL, O_SYNC); + } + ::tcgetattr(fd, ¤tTermios); + currentTermios.c_cc[VTIME] = millisec/100; + ::tcsetattr(fd, TCSAFLUSH, ¤tTermios); + } + + settingsDirtyFlags = 0; +} diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_win.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_win.cpp new file mode 100644 index 0000000..6b13b52 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextserialport_win.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextserialport.h" +#include "qextserialport_p.h" +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +# include +#else +# include +#endif +void QextSerialPortPrivate::platformSpecificInit() +{ + handle = INVALID_HANDLE_VALUE; + ZeroMemory(&overlap, sizeof(OVERLAPPED)); + overlap.hEvent = CreateEvent(NULL, true, false, NULL); + winEventNotifier = 0; + bytesToWriteLock = new QReadWriteLock; +} + +void QextSerialPortPrivate::platformSpecificDestruct() { + CloseHandle(overlap.hEvent); + delete bytesToWriteLock; +} + + +/*! + \internal + COM ports greater than 9 need \\.\ prepended + + This is only need when open the port. +*/ +static QString fullPortNameWin(const QString &name) +{ + QRegExp rx(QLatin1String("^COM(\\d+)")); + QString fullName(name); + if (fullName.contains(rx)) + fullName.prepend(QLatin1String("\\\\.\\")); + return fullName; +} + +bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode) +{ + Q_Q(QextSerialPort); + DWORD confSize = sizeof(COMMCONFIG); + commConfig.dwSize = confSize; + DWORD dwFlagsAndAttributes = 0; + if (queryMode == QextSerialPort::EventDriven) + dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; + + /*open the port*/ + handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); + if (handle != INVALID_HANDLE_VALUE) { + q->setOpenMode(mode); + /*configure port settings*/ + GetCommConfig(handle, &commConfig, &confSize); + GetCommState(handle, &(commConfig.dcb)); + + /*set up parameters*/ + commConfig.dcb.fBinary = TRUE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + commConfig.dcb.fAbortOnError = FALSE; + commConfig.dcb.fNull = FALSE; + /* Dtr default to true. See Issue 122*/ + commConfig.dcb.fDtrControl = TRUE; + /*flush all settings*/ + settingsDirtyFlags = DFE_ALL; + updatePortSettings(); + + //init event driven approach + if (queryMode == QextSerialPort::EventDriven) { + if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { + QESP_WARNING()<<"failed to set Comm Mask. Error code:"<("HANDLE"); + q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection); + WaitCommEvent(handle, &eventMask, &overlap); + } + return true; + } + return false; +} + +bool QextSerialPortPrivate::close_sys() +{ + flush_sys(); + CancelIo(handle); + if (CloseHandle(handle)) + handle = INVALID_HANDLE_VALUE; + if (winEventNotifier) { + winEventNotifier->setEnabled(false); + winEventNotifier->deleteLater(); + winEventNotifier = 0; + } + + foreach (OVERLAPPED *o, pendingWrites) { + CloseHandle(o->hEvent); + delete o; + } + pendingWrites.clear(); + return true; +} + +bool QextSerialPortPrivate::flush_sys() +{ + FlushFileBuffers(handle); + return true; +} + +qint64 QextSerialPortPrivate::bytesAvailable_sys() const +{ + DWORD Errors; + COMSTAT Status; + if (ClearCommError(handle, &Errors, &Status)) { + return Status.cbInQue; + } + return (qint64)-1; +} + +/* + Translates a system-specific error code to a QextSerialPort error code. Used internally. +*/ +void QextSerialPortPrivate::translateError(ulong error) +{ + if (error & CE_BREAK) { + lastErr = E_BREAK_CONDITION; + } + else if (error & CE_FRAME) { + lastErr = E_FRAMING_ERROR; + } + else if (error & CE_IOE) { + lastErr = E_IO_ERROR; + } + else if (error & CE_MODE) { + lastErr = E_INVALID_FD; + } + else if (error & CE_OVERRUN) { + lastErr = E_BUFFER_OVERRUN; + } + else if (error & CE_RXPARITY) { + lastErr = E_RECEIVE_PARITY_ERROR; + } + else if (error & CE_RXOVER) { + lastErr = E_RECEIVE_OVERFLOW; + } + else if (error & CE_TXFULL) { + lastErr = E_TRANSMIT_OVERFLOW; + } +} + +/* + Reads a block of data from the serial port. This function will read at most maxlen bytes from + the serial port and place them in the buffer pointed to by data. Return value is the number of + bytes actually read, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize) +{ + DWORD bytesRead = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED overlapRead; + ZeroMemory(&overlapRead, sizeof(OVERLAPPED)); + if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) { + if (GetLastError() == ERROR_IO_PENDING) + GetOverlappedResult(handle, &overlapRead, &bytesRead, true); + else + failed = true; + } + } else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) { + failed = true; + } + if (!failed) + return (qint64)bytesRead; + + lastErr = E_READ_FAILED; + return -1; +} + +/* + Writes a block of data to the serial port. This function will write len bytes + from the buffer pointed to by data to the serial port. Return value is the number + of bytes actually written, or -1 on error. + + \warning before calling this function ensure that serial port associated with this class + is currently open (use isOpen() function to check if port is open). +*/ +qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize) +{ + DWORD bytesWritten = 0; + bool failed = false; + if (queryMode == QextSerialPort::EventDriven) { + OVERLAPPED *newOverlapWrite = new OVERLAPPED; + ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED)); + newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL); + if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) { + CloseHandle(newOverlapWrite->hEvent); + delete newOverlapWrite; + } + else if (GetLastError() == ERROR_IO_PENDING) { + // writing asynchronously...not an error + QWriteLocker writelocker(bytesToWriteLock); + pendingWrites.append(newOverlapWrite); + } + else { + QESP_WARNING()<<"QextSerialPort write error:"<hEvent)) + QESP_WARNING("QextSerialPort: couldn't cancel IO"); + if (!CloseHandle(newOverlapWrite->hEvent)) + QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle"); + delete newOverlapWrite; + } + } else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) { + failed = true; + } + + if (!failed) + return (qint64)bytesWritten; + + lastErr = E_WRITE_FAILED; + return -1; +} + +void QextSerialPortPrivate::setDtr_sys(bool set) { + EscapeCommFunction(handle, set ? SETDTR : CLRDTR); +} + +void QextSerialPortPrivate::setRts_sys(bool set) { + EscapeCommFunction(handle, set ? SETRTS : CLRRTS); +} + +ulong QextSerialPortPrivate::lineStatus_sys(void) { + unsigned long Status = 0, Temp = 0; + GetCommModemStatus(handle, &Temp); + if (Temp & MS_CTS_ON) Status |= LS_CTS; + if (Temp & MS_DSR_ON) Status |= LS_DSR; + if (Temp & MS_RING_ON) Status |= LS_RI; + if (Temp & MS_RLSD_ON) Status |= LS_DCD; + return Status; +} + +/* + Triggered when there's activity on our HANDLE. +*/ +void QextSerialPortPrivate::_q_onWinEvent(HANDLE h) +{ + Q_Q(QextSerialPort); + if (h == overlap.hEvent) { + if (eventMask & EV_RXCHAR) { + if (q->sender() != q && bytesAvailable_sys() > 0) + _q_canRead(); + } + if (eventMask & EV_TXEMPTY) { + /* + A write completed. Run through the list of OVERLAPPED writes, and if + they completed successfully, take them off the list and delete them. + Otherwise, leave them on there so they can finish. + */ + qint64 totalBytesWritten = 0; + QList overlapsToDelete; + foreach (OVERLAPPED *o, pendingWrites) { + DWORD numBytes = 0; + if (GetOverlappedResult(handle, o, &numBytes, false)) { + overlapsToDelete.append(o); + totalBytesWritten += numBytes; + } else if (GetLastError() != ERROR_IO_INCOMPLETE) { + overlapsToDelete.append(o); + QESP_WARNING()<<"CommEvent overlapped write error:" << GetLastError(); + } + } + + if (q->sender() != q && totalBytesWritten > 0) { + QWriteLocker writelocker(bytesToWriteLock); + Q_EMIT q->bytesWritten(totalBytesWritten); + } + + foreach (OVERLAPPED *o, overlapsToDelete) { + OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o)); + CloseHandle(toDelete->hEvent); + delete toDelete; + } + } + if (eventMask & EV_DSR) { + if (lineStatus_sys() & LS_DSR) + Q_EMIT q->dsrChanged(true); + else + Q_EMIT q->dsrChanged(false); + } + } + WaitCommEvent(handle, &eventMask, &overlap); +} + +void QextSerialPortPrivate::updatePortSettings() +{ + if (!q_ptr->isOpen() || !settingsDirtyFlags) + return; + + //fill struct : COMMCONFIG + if (settingsDirtyFlags & DFE_BaudRate) { + commConfig.dcb.BaudRate = settings.BaudRate; + } + if (settingsDirtyFlags & DFE_Parity) { + commConfig.dcb.Parity = (BYTE)settings.Parity; + commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE; + } + if (settingsDirtyFlags & DFE_DataBits) { + commConfig.dcb.ByteSize = (BYTE)settings.DataBits; + } + if (settingsDirtyFlags & DFE_StopBits) { + switch (settings.StopBits) { + case STOP_1: + commConfig.dcb.StopBits = ONESTOPBIT; + break; + case STOP_1_5: + commConfig.dcb.StopBits = ONE5STOPBITS; + break; + case STOP_2: + commConfig.dcb.StopBits = TWOSTOPBITS; + break; + } + } + if (settingsDirtyFlags & DFE_Flow) { + switch(settings.FlowControl) { + /*no flow control*/ + case FLOW_OFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + /*software (XON/XOFF) flow control*/ + case FLOW_XONXOFF: + commConfig.dcb.fOutxCtsFlow = FALSE; + commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; + commConfig.dcb.fInX = TRUE; + commConfig.dcb.fOutX = TRUE; + break; + /*hardware flow control*/ + case FLOW_HARDWARE: + commConfig.dcb.fOutxCtsFlow = TRUE; + commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + commConfig.dcb.fInX = FALSE; + commConfig.dcb.fOutX = FALSE; + break; + } + } + + //fill struct : COMMTIMEOUTS + if (settingsDirtyFlags & DFE_TimeOut) { + if (queryMode != QextSerialPort::EventDriven) { + int millisec = settings.Timeout_Millisec; + if (millisec == -1) { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutConstant = 0; + } else { + commTimeouts.ReadIntervalTimeout = millisec; + commTimeouts.ReadTotalTimeoutConstant = millisec; + } + commTimeouts.ReadTotalTimeoutMultiplier = 0; + // zapmaker fix for dropped sent packets on fast Windows computers + //commTimeouts.WriteTotalTimeoutMultiplier = millisec; + commTimeouts.WriteTotalTimeoutMultiplier = 500; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + else { + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutMultiplier = 0; + commTimeouts.ReadTotalTimeoutConstant = 0; + commTimeouts.WriteTotalTimeoutMultiplier = 0; + commTimeouts.WriteTotalTimeoutConstant = 0; + } + } + + + if (settingsDirtyFlags & DFE_Settings_Mask) + SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG)); + if ((settingsDirtyFlags & DFE_TimeOut)) + SetCommTimeouts(handle, &commTimeouts); + settingsDirtyFlags = 0; +} diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.cpp b/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.cpp new file mode 100644 index 0000000..f029421 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "qextwineventnotifier_p.h" +#include +#include +#include +#include +#include +#include +#include + +class QextWinEventNotifierPrivate +{ + Q_DECLARE_PUBLIC(QextWinEventNotifier) +public: + QextWinEventNotifierPrivate(HANDLE hEvent, QextWinEventNotifier * q) + :handleToEvent(hEvent), enabled(false), q_ptr(q) + {} + + HANDLE handleToEvent; + bool enabled; +private: + QextWinEventNotifier * q_ptr; +}; + +/* + \internal + + \class QextWinEventNotifierThread + + This class works more or less like an EventDispatcher. + + The api function WaitForMultipleObjects() is used in the new thread + to wait for the registered handle. +*/ +class QextWinEventNotifierThread:public QThread +{ +public: + explicit QextWinEventNotifierThread(QObject * parent=0); + ~QextWinEventNotifierThread(); + void stop(); + bool registerEventNotifier(QextWinEventNotifier * notifier); + void unregisterEventNotifier(QextWinEventNotifier * notifier); +protected: + void run(); +private: + HANDLE hStopEvent; //stop thread when this event signaled. + HANDLE hUpdateEvent; //make sure eventlist updated. + QMutex mutex; + QList winEventNotifierList; +}; + +Q_GLOBAL_STATIC(QextWinEventNotifierThread, notifierThread) + +QextWinEventNotifierThread::QextWinEventNotifierThread(QObject * parent) + :QThread(parent) +{ + hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hUpdateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + start(); +} + +QextWinEventNotifierThread::~QextWinEventNotifierThread() +{ + if (isRunning()) + stop(); + CloseHandle(hStopEvent); + CloseHandle(hUpdateEvent); +} + +void QextWinEventNotifierThread::stop() +{ + { + QMutexLocker locker(&mutex); + SetEvent(hStopEvent); + } + wait(); /// Is this an good idea? +} + +bool QextWinEventNotifierThread::registerEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return false; + } + if (winEventNotifierList.contains(notifier)) + return true; + if (winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 3) { + QESP_WARNING("QextWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 3); + return false; + } + winEventNotifierList.append(notifier); + SetEvent(hUpdateEvent); + return true; +} + +void QextWinEventNotifierThread::unregisterEventNotifier(QextWinEventNotifier *notifier) +{ + QMutexLocker locker(&mutex); + if (!notifier) { + QESP_WARNING("QextWinEventNotifier: Internal error"); + return; + } + + int idx = winEventNotifierList.indexOf(notifier); + if (idx != -1) { + winEventNotifierList.takeAt(idx); + SetEvent(hUpdateEvent); + } +} + +void QextWinEventNotifierThread::run() +{ + forever{ + HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; + DWORD nCount = 0; + { + QMutexLocker locker(&mutex); + nCount = winEventNotifierList.count(); + for (int i=0; i<(int)nCount; ++i) + pHandles[i] = winEventNotifierList.at(i)->handle(); + pHandles[nCount] = hUpdateEvent; + pHandles[nCount+1] = hStopEvent; + } + DWORD ret = WaitForMultipleObjects(nCount+2, pHandles, FALSE, INFINITE); + if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + nCount) { + QEvent *evt = new QEvent(QEvent::User); + QMutexLocker locker(&mutex); + ResetEvent(pHandles[ret-WAIT_OBJECT_0]); + QObject * notifier = winEventNotifierList[ret - WAIT_OBJECT_0]; + QCoreApplication::postEvent(notifier, evt); + } + else if (ret == WAIT_OBJECT_0 + nCount) { + //ResetEvent(hUpdateEvent); + } + else if (ret == WAIT_OBJECT_0 + nCount + 1) { + //qDebug()<<"quit..."; + return; + } + } +} + +/*! + \internal + \class QextWinEventNotifier + \brief The QextWinEventNotifier class provides support for the Windows Wait functions. + + The QextWinEventNotifier class makes it possible to use the wait + functions on windows in a asynchronous manner. With this class + you can register a HANDLE to an event and get notification when + that event becomes signalled. + + \bold Note: If it is a manual reset event ,it will be reset before + the notification. This is different from QWinEventNotifier. + + \bold Note: All the registered handles will be waited under a new thread. + This is different from QWinEventNotifier whose event handle will be waited + in its affinal thread. +*/ + +QextWinEventNotifier::QextWinEventNotifier(QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(0, this)) +{} + +QextWinEventNotifier::QextWinEventNotifier(HANDLE hEvent, QObject *parent) + : QObject(parent), d_ptr(new QextWinEventNotifierPrivate(hEvent, this)) +{ + setEnabled(true); +} + +QextWinEventNotifier::~QextWinEventNotifier() +{ + setEnabled(false); +} + +void QextWinEventNotifier::setHandle(HANDLE hEvent) +{ + setEnabled(false); + Q_D(QextWinEventNotifier); + d->handleToEvent = hEvent; +} + +HANDLE QextWinEventNotifier::handle() const +{ + return d_func()->handleToEvent; +} + +bool QextWinEventNotifier::isEnabled() const +{ + return d_func()->enabled; +} + +void QextWinEventNotifier::setEnabled(bool enable) +{ + Q_D(QextWinEventNotifier); + + if (d->enabled == enable) + return; + d->enabled = enable; + + if (d->enabled) + notifierThread()->registerEventNotifier(this); + else + notifierThread()->unregisterEventNotifier(this); +} + +bool QextWinEventNotifier::event(QEvent * e) +{ + Q_D(QextWinEventNotifier); + QObject::event(e); + if (e->type() == QEvent::User) { + emit activated(d->handleToEvent); + return true; + } + return false; +} + diff --git a/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.h b/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.h new file mode 100644 index 0000000..38f1457 --- /dev/null +++ b/GCV-3.6.1-T4/src/QextSerialPort/qextwineventnotifier_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** Copyright (c) 2000-2003 Wayne Roth +** Copyright (c) 2004-2007 Stefan Sander +** Copyright (c) 2007 Michal Policht +** Copyright (c) 2008 Brandon Fosdick +** Copyright (c) 2009-2010 Liam Staskawicz +** Copyright (c) 2011 Debao Zhang +** All right reserved. +** Web: http://code.google.com/p/qextserialport/ +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QEXTWINEVENTNOTIFIER_P_H_ +#define QEXTWINEVENTNOTIFIER_P_H_ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QESP API. It exists for the convenience +// of other QESP classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qextserialport_global.h" + +class QextWinEventNotifierPrivate; +class QEXTSERIALPORT_EXPORT QextWinEventNotifier : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QextWinEventNotifier) + +public: + explicit QextWinEventNotifier(QObject *parent = 0); + explicit QextWinEventNotifier(HANDLE hEvent, QObject *parent = 0); + ~QextWinEventNotifier(); + + void setHandle(HANDLE hEvent); + HANDLE handle() const; + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); + +Q_SIGNALS: + void activated(HANDLE hEvent); + +protected: + bool event(QEvent * e); + +private: + Q_DISABLE_COPY(QextWinEventNotifier) + QextWinEventNotifierPrivate * d_ptr; +}; + +#endif // QEXTWINEVENTNOTIFIER_P_H_ diff --git a/GCV-3.6.1-T4/src/README b/GCV-3.6.1-T4/src/README new file mode 100644 index 0000000..f946c02 --- /dev/null +++ b/GCV-3.6.1-T4/src/README @@ -0,0 +1,552 @@ + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Version 3.0 is a near-complete rewrite of the C++ code fixing all known bugs. +The other major enhancement is native Mac OSX support (including older 32 bit Intel 10.5). + +The code was tested with real milling projects using the Shapeoko and works +pretty well. For a list of possible future enhancements, see file TODO. + +Prebuilt binaries/installers can be found on github's download section for this +project (GrblHoming). Alternately, if you download the (a) Qt SDK from Nokia or +(b) the Qt source from Qt Project along with the standalone Qt Creator, you can +build from source. + +Details on how to do this can be found here: +http://zapmaker.org/ +///--------------------------------------------------------------------------------------- + +*GCV-3.6.1-T4 (LETARTARE proposals August 20, 2014) + +* 3.6.1-T3 + + +1- Analyzes the gcode with 4 axes X, Y, Z, T ( fourth axis ), +2- New display console ('Console') commands, with the ability to copy, delete + text part, delete the selected (or all) text, print the selected (or all) text +3- Display speed rate XYZ with 'Lcd', display last spindle speed, +4- Visualizes the 'Gcode' XYZ 3D with motion mouse : + - A help button to explain the multiple possible actions on the drawing, + by utilsation keyboard and mouse, + - You can see it or not the box limits the drawing, + - Choosing a particuler tool, + - Different views are available by buttons, + - Display axes oriented, + - Display a grid in the XY plane, + - Choice of deleting lines G0. + +5- Animation 3D XYZ axes, regardless of the connection : + - When loading a file, you can read its contents in the console 'Visual', + which will launch the manual or automatic animation, + - In manual mode you can use the mouse to select a line of code or the + navigation buttons or sliders keyboard arrows, + - In automatic mode has a period setting reading 'Gcode', + +6- In addition to the periodic polling of 'Grbl', a new method is proposed + EXPERIMENTAL display named 'Synchronous simulation' based on motion prediction, + - This mode is for use rather large arcs or helical path, + - It does not work with manual controls, + - It is accessed via 'Tools->Options->Display->Synchronous simulation', + +7- The visual presentation of 'GCV' has been modified : + - a flip button to pause and resume sending gcode file at the end of the current + line, will send to 'Grbl', + - buttons for Grbl commands grouped with console, + - manual controls axes (jog) are grouped next to the display positions : + - the incremental value step manual controls is defined by a slide + and a display, and can be adjusted finely by keyboard keys, + - homing new buttons for each axis, + - homing new button for all axes, + - the feed rate movement is displayed during, + - the last spindle speed is displayed, + +8- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, 0.9f, the last 0.9g + 2- Four axes 0845, 0.8c1, 0.8c2 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c2Mega2560 + +- KNOWN BUGS + - In the mode 'Check', it does not use the command line to send '$C' + - The mode 'Simulation synchronous' does not work in manual controls + - If no file is loaded, the manual controls do not support the visualization tool + - ... + + + +V3.6.1->T2 (LETARTARE proposals) + +* 3.6.1-T1 + + +- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + + +V3.6.1->T1 (LETARTARE proposals) + +- Improved to the same card 3 and 4 axis detection +- Displays the line numbers of the file if no number exists +- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, + 2- Four axes 0845, future 0.8c1 (0.8c1 to 4 axes) + +V3.6.1 +Executable release rollup + +IMPORTANT: Manual/Jog control defaults to new mode which doesn't update the position. +This was done to ensure that jog motions are as fast as possible. However, if you want +to have the original 3.5.1 and earlier behavior, go to Tools | Options | Display +and change radio button to "Always Request but without Idle Check". Sending files +still updates position, it is only manual/jog that does not. + +V3.6 +Enhancements +- Options dialog is now tabbed to better fit widgets +- Ability to handle 4th axis as either A, B, or C (requires correct grbl version for axis), + please see https://github.com/zapmaker/GrblHoming/issues/56 and + https://github.com/LETARTARE/Grbl_with_Arduino/tree/master/Grbl845Mega2560 + which is the A,B,C,U,V,W axes grbl variant. +- LETARTARE: Added UVW axes +- #45: Added ability to completely or partially turn off querying position from grbl to + help improve responsiveness. The new default is to disable waiting for idle before a + jog or manual command, which speeds up those operations. Additional, you can + completely turn it off position reporting during jog or manual control which will + result in light-greyed LCD numbers. A button to query the position has been + added, which will provided up-to-date position at the time the button is pushed. + Look in Options | Display tab for new button options. You can also set the rate + at which the query takes place from 0.5-10 seconds, if it is enabled. Setting a time + that is too long may result in the system waiting too long to retrieve the final position + before control is handed back. Also, the current position dot on the Visualizer turns + from red to green when the position is not accurately known to match the color of the path. +Bug fix +- Fixed fourth axis adjust buttons and coordinate display greyed out when they shouldn't + be (under specific operating circumstances). + +V3.5.1 +Enhancements +- Made subtle modifications to the command preload when sending a file so that the + command queue on grbl is as full as possible. Previously we were depleting the + queue and then filling it again. This has possible negative performance implications, + although testing shows them to be negligible, probably because we immediately send + a command after the last ok is received. +- The status list view now supports only a maximum of 200 items when active. This was + done for the slower processors like the raspberry pi to prevent excessive CPU usage + when many commands lines exist in a file. When the user grabs the scrollbar, all + items are restored back into the view. +- A new progress bar has been added showing the current items in the grbl queue during + a file send. If the number of items for some reason drops to 0 the label text will + flash red. For this 0 count to occur is a very rare event. +- Added the ability to set the delay between sending of characters to grbl. The theory + is that grbl can drop characters if the sending computer is very fast. There is still + some debate on whether this is happening, so I provided the ability to set this value + in the options from 0 to 20 ms. Note: The default of 0 ms delay is back, like in 3.4.6 + and unlike in 3.5 which has a hardcoded 10 ms delay. +Bug fix +- Modified the status window redraw to always ensure items show on the bottom when the + redraw timer expires. + +V3.5 +Bug fix +- For very fast computers, they send characters with virtually no delay between which + requires grbl to process the serial port as fast as it can. The problem is that + grbl has an interrupt service routine that can slow down the processing it does + of incoming characters on its serial port. This causes lost characters in its input + buffer, which results in hung gcode file processing or errors. To fix, I have added + a slight delay (10ms) after sending every character. This has been confirmed to + solve the lost character problem on grbl. + +V3.4.6 +Bug fix +- Scrolling of content now completes each time. Previously there were conditions where + auto-scrolling would fail and you would have to manually scroll to see some lines +- Fixes to support 4-axis Mega2560 (tested with actual Mega2560 running 0.81 c-axis). + Includes fix to command filter to support A/B/C axis commands +- Fixed minor issue where connecting with wrong baud rate can cause long delay before + you can again control the Open/Close button +- Incorporated more translations from LETARTARE + +V3.4.5 +Bug fix +- When modifying the ui files for auto widget rescaling, broke a number of programmatically + greyed out widgets, mainly, you couldn't reopen the port after closing it. Now those are fixed. + +Enhancement +- Incorporated LETARTARE's localization file for French so that it is possible to see + locale-specific text in the installed version of Grbl Controller (see trlocale subdir) + +V3.4.4 +Bug fix +- Incorporated LETARTARE's 4-axis (C-axis) implementation - thanks! (Issues #29 and #34) + (added option to enable/disable 4-axis mode) - potential issue that needs investigating: + Can this be enabled on the fly or if it requires restart of Grbl Controller? +- Incorporated LETARTARE's translation support (French) +- Incorporated LETARTARE's fix for command history (#26) +- Incorporated Kosme's fix to issue #17 (#33). Z axis slider now moves in 0.1 inch increments + when in inches mode. +- Incorporated Kosme's fix to issue #27. If work units are inches, now displays inches, + not mm. +Enhancements +- Ability to resize entire screen and widgets. Scales down to close to 600x400 pixels + for tiny displays; also remembers last size and position of screen. (#37) +- Incorporated Kosme's fix to issue #10 (#33). Popup appears to remind you to zero position + if starting a new job. + +V3.4.3 +Bug fix +- Unsupported G43/G44 commands include following Z command which causes problems when + left standalone. The entire line must be removed. +- Now treat M2 and M30 as unsupported as they cause grbl lockup when using aggressive + preloading. +- Moved program version define into its own header file so fewer files need recompiling + with a version change. + +V3.4.2 +Bug fix +- If a gcode command line is an arc with X,Y,Z and z-rate limiting enabled, fixed to + properly split the z rate to not use the G2 command and use G1 instead as grbl + was generating an error with the G2. + +V3.4.1 +Code sync +- Fixes to code now allows code to compile under Qt5 without error and also resolves + some localization issues. Continues to properly compile under Qt4 also. No normally + noticable functional differences. + +V3.4 +Enhancements +- Z-axis slider now allows rapid control of Z-axis positioning. This feature is still + being evaluated for proper behavior due to some user-interface issues. + If you run into trouble, please report a bug. +- All axis control buttons have been permanently enabled regardless of whether or not an + axis command is in progress - this allows more rapid updating. Note - there is no error + checking for the case of entering too many commands for the Grbl buffer. This is unlikely + but possible. +- Now supports setting of baud rates from 9600 to 115200 +- Aggressive preload enabled is now the default. If the user upgraded from an older + Grbl Controller and had it disabled, a popup will warn them that it is being enabled. + They still have the option to disable, if desired +- Logging is turned on by default (only for new installs) +- All detected errors are collected and displayed after a file is run in the status view +- If filtering unsupported commands, all commands filtered out are listed after the file + is run. +- Logging now gives the line number of each command sent from the file and the corresponding + ok or error also contains the line number. +- An option has been provided to reduce the precision of lines that exceed Grbl's line buffer, + which by default is 50 characters. The code removes the arguments with the greatest precision + first and ending with at least one decimal place of precision. Errors are generated if it + cannot remove sufficient precision for the available buffer space. The buffer size on Grbl + is configurable in the options, as older Grbls have 50 characters and newer have 70. + +Bug Fixes +- If Grbl stops responding (waiting for an ok), Soft Reset Grbl now functions correctly + (so you can soft reset without having to restart Grbl Controller). This affects aggressive + preload mode only. +- Commands to start/stop coolant coupled with dwell commands and aggressive preload cause + Grbl's modal logic to stop sending OK responses (on purpose). This was solved by waiting + for the OK of the coolant off before sending additional commands. It is not clear whether + this fixes all possible such modal problems, so use carefully and report any anomalies. + +V3.3.9 +Enhancement +- We now are able to remember and restore ports that are not visible to QextSerialEnumerator + so that user doesn't have to retype the ghost port every time they start Grbl Controller. + +V3.3.8 +Enhancement/Fix +- Modified code that detects presence of Grbl upon serial port opening, the original + assumption was that we would get the version string upon serial port open, but some + Arduino-compatible boards like the AlaMode did not behave this way. Fixed the code + so that if there is no response upon serial port open, we send a soft reset (Ctrl-X) + and wait for the version string. Tested to work with AlaMode and with traditional + Ardiuno Uno. + +V3.3.7 +Enhancement +- Made COM port field editable + +V3.3.6 +Bug Fixes +- Fixed decimal on the LCD display to always show three decimal points so that + it is easier to read the display (it doesn't jump around anymore). Tested to + hold up to 9999.999 and -9999.999, which should handle 20 x 20 meter Shapeokos. + +V3.3.5 +Bug Fixes +- Changed how we detect Grbl upon opening on COM port. + ** NOTE ** This change will probably break older V0.51 capability + Previously we sent out a linefeed to trigger a response, however, this caused problems + on some arduino variants and would not result in correct sync with the controller. + Fixed by no longer sending the linefeed and instead just watch the port for Grbl response. +- Changed the default "short" wait timeout to 2 seconds from 1 second in case of slow responses. + +V3.3.4 +Enhancements +- Added option checkbox to choose to filter gcode or send it as-is to the controller. The + filtering removes gcode that is not supported in v0.8 of Grbl, which reduces the error + reports from Grbl. Some files generate unexpected codes like G91.1 which can actually + affect the motion in unexpected ways- filtering helps prevent this from happening. + + IMPORTANT: The default is to not filter, which is different than previous versions! This + may result in unexpected command processing. If using advanced gcodes, perform an air run + first. + +Bug Fixes +- Mach3 files have no whitespace in the gcode. Fixed code to handle such files. Affects + the Visualizer only. +- The filtering logic was fixed to properly filter gcode when sending a file - previous + versions would filter out gcode that Grbl supported. +- Changed validator for double (i.e. float) values so that code compiles under older Qt + versions. +- Changed Visualizer display to say Width-X and Height-Y instead of Width and Depth to make + it less confusing. + +V3.3.3 +Bug Fix +- Modal G arc (where G2 or G3 is specified once followed by X/Y/I/J) was failing for certain + arc combinations in the visualizer due to resetting the cw to false with each line. Fixed + to not reset the cw variable and retain from previous lines. + +V3.3.2 +Bug Fix +- G-command can now be set once and multiple X/Y commands then issued on lines following + (Allows "ShapeOko_Calibration_Pattern_01b.ngc to be rendered) + +V3.3.1 +Bug Fixes +- Hardened the visualizer's file parser so that it supports spaces between positional + arguments and values +- No longer skips last line in file if that line contains a valid command +- No longer crashes if line contains one or more stray whilespace characters +- Also accepts semi-colon as a comment line (in addition to existing open paren and percent) + +V3.3 +Enhancemetns +- Added "Visualizer" feature. It is now possible to see top-down view of the + file to be milled. + * Shows actual file units (inches or millimeters) independent of coordinate display + * Auto-scaling + * Supports limited subset of commands (G0/G1/G2/G3) + * Visualizer on tab panel shared with Axis control + * Actual last spindle cutter position is shown; auto-scales to include both cutter + and file + * When file is being run, overlay of all commands sent to Grbl is shown in green + * Displays dimensions of design, along with design's width and depth in file's units + +V3.2 +Enhancements +- Support for "Aggressive Preload" of commands when sending file to Grbl + * File's lines are sent to Grbl as fast as Grbl can take it, allowing + Grbl to optimize acceleration. Some files have been observed to take + 1/3 the time to complete! + * Modeled after Grbl's own python script (computes/predicts how much + space is available in Grbl's input buffer) + * Due to the additional processing, CPU usage is greater than normal mode + and it has been optimized to run fine on a Raspberry Pi + * Normal (non-preload) mode is the default + * Response processing code now waits until a line has been received rather + than collect a long stream to behave like the python script + * LCD updates have been set to be roughly once every second independent + of rate of line sends/preloads +- Z-rate limit feature now includes default xy rate setting + * Z rate limiting only occurs during file sends. If z is included with x&y + then they are split into two commands automatically and the xy rate setting + is used for the xy portion + * Since feed rate is modal, code will fix any subsequent xy items that are + missing feed rate specifiers (cambam correctly adds them, but others may not) +- Replaced basic logging with Log4Qt logging capabilities. + * Support for error, warning, info, debug message types. All messages are timestamped. + * More diagnostic messages added, mainly around sending and receiving from com ports + * Only error and warning are displayed in release build, all are displayed in debug. + * If the user enables file logging, all messages are stored regardless of build type + * File is output to user's home folder + * If you enable or disable logging to file, you must restart Grbl Controller + * You can split out diagnostic from status messages by grepping for (DIAG) or (STATUS) +- Changed menus so that the first menu is File > Exit. Menus now use accelerators + +Bug Fixes +- Fixed problems with z-rate limit feature, previous version was not implemented correctly. +- Fixed subtle issues with sending bytes to COM port + * On really fast Windows PCs, the default timeout values would occasionally result in + a line not being sent. This was fixed by changing the write timeout from 10 to + 500 ms by hardcoding it into the QextSerialPort library. This was only observed in + aggressive preload mode, never in normal mode. + +Known issues +- New reponse line detect mode requires more processing because mainly of the faster + stream of status messages. To get around this, certain features have been disabled + in the status view so that CPU usage is manageable on the Raspberry Pi, specifically + the horizontal scroll bar is not available. Turn on file logging if you wish to see + the entire line. +- When using aggressive preload, any error messages returned by Grbl are not synced + to sent messages (they come back randomly). This can be confusing. +- If running preload, it can take longer for steppers to stop after a Stop command + due to the number of items in Grbl's queue. The only way to stop sooner is to + press Close / Reset button +- Under exteme CPU loads (unlikely to occur with recent optimizations), the "runtime" + display does not display accurate times, oddly, it displays the same time that would + occur if not under load + +Tested on cardboard using file provided by user: +- Windows 7 64bit, 0.8c, aggressive mode (~4 minute run) +- Windows 7 64bit, 0.8c, normal mode (~10 minute run) +- Windows 7 64bit, 0.8a, aggressive mode(~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode (~4 minute run) +- Raspberry Pi, 0.8c, aggressive mode and z-limit (~6 minute run) + +V3.1.2 (unofficial release, optimizations for Raspberry Pi) +Enhancements +- Optimized multiline write to status window to use faster list-based approach +- Removed unnecessary main window repaint after every line added to status window +- Fixed options window text positioning so that it appears proper on the pi + +V3.1.1 (unofficial release, adjustments for Raspberry Pi) +Enhancements +- Changed measurement units in LCD from "inches" to "in" (cosmetic) +- Shortened text and adjusted main window layout for the text size on the pi + +V3.1 +Enhancements +- Supports Grbl 0.8c. Still supports 0.8a. 0.51 is supported but without LCDs. +- Grbl settings dialog is now a table of dynamic length depending on # of params. +- LCD position data is now obtained from Grbl and is *not* computed +- Added LCD displays for both machine and work coordinates +- Cycling of Grbl via COM port toggling has been completely removed, except + that Close button has now been renamed Close / Reset. +- Position data on Grbl is persisted as long as possible to allow for repositioning, etc. +- Zero work coordinates has been added (G92) +- Go-to-home feature added (lifts tool 5 mm and traverses to x=0, y=0) +- Option to put manual command (back) into absolute mode after jog button command +- Grbl Soft reset (Ctrl-X) button added +- Z-axis rate limiting capability added. Only affects file, not jog or manual commands. +- User is required to specify which measurement mode they are using, mm or inches: + * Default is millimeters + * Grbl is configured to operate in either mm or inches + * If a file is sent in inches and user is in mm, it will auto-restore to mm + after the file has been sent (and vice-versa, mm->inches) +- 0.8c enhancements: + * Displays current Grbl state (i.e. Run, Idle, etc.) + * LCDs display whether values are in inches or millimeters + * Unlock Grbl button added ($X) + * Determines and sets parser state for current mm/inch command mode ($G) + * Determines and sets coordinate units via $13 +- Removed annoying "No movement expected for command" message +- Flags that cross threads have been changed to use QAtomicInt +- Version is now shown in title bar +- A basic log file feature has been added +- Runs on the Raspberry Pi! + +Known Issues +- The registry key product name has been changed from GCodeSender to GrblController + *** WARNING: Old settings are not migrated **** +- Switching between millimeters and inches works, but has not been fully tested +- Go to home has not been fully tested with inches mode +- Manually issuing $13 or G20/G21 can confuse the program + +V3.0 +Enhancements +- Nearly a full code rewrite to ensure ease-of-use and robustness +- Percentage complete progress bar for files; also shows time elapsed sending file. +- Reset button now cycles COM port which causes Arduino to stop steppers and + reinitialize position to 0,0,0 (No more manual Auduino resets!) +- Settings configurations are now stored using QSettings class for platform independence. +- Only available COM ports are now shown. Uses third-party QextSerialPort library. +- App remembers last COM port used, last folder, last file extension used after restart +- Ability to configure wait-for-response time +- Status list window now shows both sent and received data +- Error responses are ignored during file send (nearly 100% of the time they are not important) +- Z-jog speed using buttons is configurable +- Radio buttons to select mode have been removed in favor of enabling/disabling widgets based + on current context. This simplifies usage. +- Popups have been removed in favor of writing errors to status list window + +Bug fixes +- Overall code hardening +- Properly implementing Qt signals and slots across the board + +Build verification +- Windows 7 64 bit using MinGW +- Inno Setup for Windows, installs successfully on Windows 7 +- Mac OSX Mountain Lion, target 64 bit and 32 bit executables +- Qt Mac installer successfully installs and runs on Mountain Lion and 10.5 32 bit Intel +- Linux: Builds successfully on Debian 6, Ubuntu 12.10 + +V2.1x1 + +NOTE: Changes were only focused on Arduino GRBL capabilities with the Shapeoko, so +things like Tool Change were not tested. + +Enhancements +- Improved handling of response code - this is the most significant change as it +ensures reliable send/response handling when sending a file to the Grbl processor. +- Manual command now allows hitting return and command is sent. No need to press Go. +- Default job step size changed from 0.01 to 1 mm +- Compiles and runs under Linux now (tested with Debian and latest Qt) +- Works with old 168 Arduino processor (except that old code is buggy and not recommended) +- Disabled "go to home at end of job". The arduino code doesn't handle it correctly +and mills straight back into and through your work. Checkbox in settings has no effect. + +Bug fixes +- Fixed crash when options file is not present the first time run +- Fixed crash when trying to get GRBL settings from device +- Settings work with 168 (8 settings) and 328 processors (10 settings) +- Fixed Stop to call proper routine stopsig - now Stop button works correctly + +------------------------------------------------------------- +Fork by Zapmaker at this rev +------------------------------------------------------------- +v2.1a + +Bug fixes + +- Corrected an issue that caused the program to crash if the g-code had blank lines. + +V2.1 + +New Features + +- Gcode that is valid but is not recognized by GRBL gets filtered and it is not sent. + +Bug fixes + +- Corrected an issue that prevented manually sent Gcode for being displayed correctly. +- Corrected an issue with the images not displaying. + +V2.0 Major release + +- Improved the port handling reducing opening and closing frecuency. +- Added the ability to type and send commands directly. +- Support for tool change instructions. If enabled it pauses execution, raises the spindle, goes to a fixed location for toolchange, waits for tool change, and continues excecution. +- Added About window. + +V1.0c Minor + +Bug fixes + +- Corrected a problem when adjusting axis that caused all axis to move at the same time. Caused by grbl starting in incremental programming. + +V1.0b Minor + +Bug fixes + +- Corrected a bug in the adjusting script. + +V1.0a Minor + +Bug fixes + +- Fixed a bug reading some file formats that avoided the dials from updating. + diff --git a/GCV-3.6.1-T4/src/TODO b/GCV-3.6.1-T4/src/TODO new file mode 100644 index 0000000..c73577e --- /dev/null +++ b/GCV-3.6.1-T4/src/TODO @@ -0,0 +1,68 @@ +This file contains enhancements the developer and user community would like to see: + + +Planned for 3.4.x +- Bug fixes +Planned for 3.5: +- (What is the problem here? Run is shown, then Idle when stopped) Detect machine state at end of run and display it properly (i.e. "transitioning" when it is still moving) +- Every second or so, if not scrolled to bottom, scroll to bottom of status +- Allow reload of same file from same location +- After a run, suppress $$ output with a single line +- Report system settings at beginning of log file. Include OS. +- Can't see drill holes under axis, move axes under toolpaths? +- Create test plan (i.e. verify all text appears correctly on all platforms) +- Display detected version of Grbl +- Speed limit for X and Y like the Z speed limit + +Planned for 3.6: +- Implement support for Grbl 0.8c "homing" feature (using limit switches) +- UI support for homing limit switches +- Restore "Tool change" feature, including popup dialog +- Option to engage stepper lock (include fade out rate setting - start time of fade, end time of fade, requires hw mod) +- Display current feedrate in mm/sec or in/sec +- Add additional rs232 error logging value (-1 is not very useful) +- Analyze file ahead of time and determine if it will go beyond extents +- Update manual since 3.3 + +Planned for 3.7 +- Switch to compiling using Qt 5 +- Auto-scale widgets to full screen size +- Localization ready code +- Don't fail on timeout waiting for command - let user continue if they want +- Pick up from where left off (if GC dies due to PC falling asleep, etc.) +- Look at all hardware connection options of Grbl on the shield and make + sure that we have some way to control those, i.e. spindle control. +- Clear log button +- Print current GRBL settings +- Add option to always use last working port, even if it isn't currently connected + +Primary: +- Save/Load current GRBL settings from disk +- Suppress some bookkeeping output from the status window +- Add local Help linked from main screen and options dialog +- When parsing for visualizer, if bad value arg, warn user +- If nothing appears in visualizer, attempt to diagnose and explain to user +- If get error from grbl, provide command that generated error on same line +- Allow user to choose how to handle unspecified units in file for visualizer +- Fix Zero position next to begin? +- Show drill holes as larger dots? +- Build in calibration pattern +- Build in "flatten table feature" +- File viewer +- Estimate bounds based on both toolpaths and tool diameter, not just toolpaths + +Secondary: +- Make GC generic to support controllers other than Grbl +- Recent files list under 'Files' +- Restore "Favorites" feature +- Provide diagnostic response view +- Provide counter showing time waiting for a response if time > 5s +- Estimated time to completion (this can acutally be computed from feedrates) + +Notes pulled from https://github.com/grbl/grbl/issues/202 + +Move Z to upper clear position. (<- another parameter?) +Stop the spindle. +X and Y to the change tool coordinates. +A way to adjust new Z (manual for me) and perhaps new speed for the spindle (manual for me). +When ready (~) start cycle? to continue with the new tool with the same X and Y initial coordinates than the last tool. \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/about.cpp b/GCV-3.6.1-T4/src/about.cpp new file mode 100644 index 0000000..bdd705a --- /dev/null +++ b/GCV-3.6.1-T4/src/about.cpp @@ -0,0 +1,28 @@ +/**************************************************************** + * about.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "about.h" +#include "version.h" +#include "ui_about.h" + +About::About(QWidget *parent) : + QDialog(parent), + ui(new Ui::About) +{ + ui->setupUi(this); + QString title = GRBL_CONTROLLER_NAME_AND_VERSION ; + title += "\n"; + title += VERSION_BUILD ; + ui->labelProductAndVersion->setText(title); +} + +About::~About() +{ + delete ui; +} diff --git a/GCV-3.6.1-T4/src/about.h b/GCV-3.6.1-T4/src/about.h new file mode 100644 index 0000000..e8f7291 --- /dev/null +++ b/GCV-3.6.1-T4/src/about.h @@ -0,0 +1,32 @@ +/**************************************************************** + * about.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef ABOUT_H +#define ABOUT_H + +#include +#include "definitions.h" + +namespace Ui { +class About; +} + +class About : public QDialog +{ + Q_OBJECT + +public: + explicit About(QWidget *parent = 0); + ~About(); + +private: + Ui::About *ui; +}; + +#endif // ABOUT_H diff --git a/GCV-3.6.1-T4/src/arcitem.cpp b/GCV-3.6.1-T4/src/arcitem.cpp new file mode 100644 index 0000000..3ae589d --- /dev/null +++ b/GCV-3.6.1-T4/src/arcitem.cpp @@ -0,0 +1,120 @@ +#include "arcitem.h" + +ArcItem::ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw1, int index1) + : ItemToBase(index1), sx(sx1), sy(sy1), ex(ex1), ey(ey1), centx(centx1), centy(centy1), cw(cw1), radius(0), angleStart(0), angleDelta(0) +{ +} + +PosItem ArcItem::computeExtents() +{ + PosItem extents(sx, sy, ex, ey); + + radius = qSqrt(((sx - centx) * (sx - centx)) + ((sy - centy) * (sy - centy))); + + if (cw) + { + double angle1 = qAtan2(ey - centy, ex - centx); + double angle2 = qAtan2(sy - centy, sx - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + else + { + double angle1 = qAtan2(sy - centy, sx - centx); + double angle2 = qAtan2(ey - centy, ex - centx); + + if (angle1 > 0 && angle2 < 0) + angle2 += TWO_PI; + + angleStart = angle2; + angleDelta = angle1 - angle2; + } + + // sample points along the curve + double angleEnd = angleStart + angleDelta; + for (double angle = angleStart; + (angleDelta < 0 ? angle > angleEnd : angle < angleEnd); + angle += (angleDelta < 0 ? -0.4 : 0.4)) + { + double x = qCos(angle) * radius + centx; + double y = qSin(angle) * radius + centy; + + PosItem curr(x, y, x, y); + + // expand rectange if it exceeds our last rectangle + extents.expand(curr); + } + + return extents; +} + +void ArcItem::addToPath(QPainterPath& path) +{ + // need to convert our coordinates into arcTo arguments (rectangle boxes and angles, etc.) + // Also, we are at this point in screen coordinates, not machine coordinates, i.e. Y positive is down! + + // first, we know for a fact that we are dealing with a circular arc, not an ellipse + // (code could be put here to verify that is true) + // Thus our radius is also our bounding box determined from the center of the arc/circle + + if (cw) + { + path.moveTo(screenX(sx), screenY(sy)); + } + else + { + path.moveTo(screenX(ex), screenY(ey)); + } + + double x = centx - radius; + double y = centy + radius; + double wd = radius * 2; + double ht = wd; + + double fx = screenX(x); + double fy = screenY(y); + double w = wd * scale; + double h = ht * scale; + + double angleStartDeg = toDegrees(angleStart); + double angleDeltaDeg = toDegrees(angleDelta); + + path.arcTo(fx, fy, w, h, angleStartDeg, angleDeltaDeg); + + path.moveTo(screenX(ex), screenY(ey)); +} + +void ArcItem::moveToFirst(QPainterPath& path) +{ + // not applicable! generate error! + Q_UNUSED(path); +} + +double ArcItem::getXScr() +{ + return screenX(ex); +} + +double ArcItem::getYScr() +{ + return screenY(ey); +} + +double ArcItem::getXRaw() +{ + return ex; +} + +double ArcItem::getYRaw() +{ + return ey; +} + +double ArcItem::toDegrees(double rad) +{ + return 360 * rad / TWO_PI; +} diff --git a/GCV-3.6.1-T4/src/arcitem.h b/GCV-3.6.1-T4/src/arcitem.h new file mode 100644 index 0000000..6ae63c7 --- /dev/null +++ b/GCV-3.6.1-T4/src/arcitem.h @@ -0,0 +1,39 @@ +#ifndef ARCITEM_H +#define ARCITEM_H +#include +#include "itemtobase.h" + +#define TWO_PI (2 * 3.1415926) + +class ArcItem : public ItemToBase +{ +public: + ArcItem(double sx1, double sy1, double ex1, double ey1, double centx1, double centy1, bool cw, int index); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + + double toDegrees(double rad); + +private: + double sx; + double sy; + double ex; + double ey; + double centx; + double centy; + bool cw; + + double radius; + double angleStart; + double angleDelta; + +}; + +#endif // ARCITEM_H diff --git a/GCV-3.6.1-T4/src/atomicintbool.cpp b/GCV-3.6.1-T4/src/atomicintbool.cpp new file mode 100644 index 0000000..630dc3c --- /dev/null +++ b/GCV-3.6.1-T4/src/atomicintbool.cpp @@ -0,0 +1,22 @@ +#include "atomicintbool.h" + +AtomicIntBool::AtomicIntBool(int newValue /* = 0 */) + : value(newValue) +{ +} + +void AtomicIntBool::set(int newValue) +{ + value.fetchAndStoreRelaxed(newValue); +} + +int AtomicIntBool::get() +{ + return value.fetchAndAddRelaxed(0); +} +/* +int AtomicIntBool::getAndClear() +{ + return value.fetchAndStoreRelease(0); +} +*/ diff --git a/GCV-3.6.1-T4/src/atomicintbool.h b/GCV-3.6.1-T4/src/atomicintbool.h new file mode 100644 index 0000000..c705677 --- /dev/null +++ b/GCV-3.6.1-T4/src/atomicintbool.h @@ -0,0 +1,22 @@ +#ifndef ATOMICINTBOOL_H +#define ATOMICINTBOOL_H + +#include + +// we wrap QAtomicInt because it is possible to accidentally +// access the non-atomic operations of the class (look at the +// header for QAtomicInt to see what I mean, and thus setting +// a value directly against one of these variables will access +// the non-atomic method) +class AtomicIntBool +{ +public: + AtomicIntBool(int newValue = 0); + void set(int newValue); + int get(); + +private: + QAtomicInt value; +}; + +#endif // ATOMICINTBOOL_H diff --git a/GCV-3.6.1-T4/src/clean.bat b/GCV-3.6.1-T4/src/clean.bat new file mode 100644 index 0000000..6b209b5 --- /dev/null +++ b/GCV-3.6.1-T4/src/clean.bat @@ -0,0 +1,12 @@ +rem clean.bat +rem by LETARTARE + +mingw32-make clean + +del release\GrblController.exe + +rem del debug\GrblController.exe + +cd .. + + diff --git a/GCV-3.6.1-T4/src/controlparams.cpp b/GCV-3.6.1-T4/src/controlparams.cpp new file mode 100644 index 0000000..b710656 --- /dev/null +++ b/GCV-3.6.1-T4/src/controlparams.cpp @@ -0,0 +1,19 @@ +#include "controlparams.h" + +ControlParams::ControlParams() + : waitTime(LONG_WAIT_SEC), zJogRate(DEFAULT_Z_JOG_RATE), + useMm(true), zRateLimit(false), zRateLimitAmount(DEFAULT_Z_LIMIT_RATE), + xyRateAmount(DEFAULT_XY_RATE), + useAggressivePreload(false), filterFileCommands(false), + reducePrecision(false), grblLineBufferLen(DEFAULT_GRBL_LINE_BUFFER_LEN), + useFourAxis(false), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS), + fourthAxisName(FOURTH_AXIS_A), fourthAxisRotate(true), +/// T4 + posReqKind(POS_REQ), + positionSyncSimu(false), positionNoDisplay(false), usePositionRequest(true), + + positionRequestType(PREQ_ALWAYS_NO_IDLE_CHK), postionRequestTimeMilliSec(DEFAULT_POS_REQ_FREQ_MSEC), + + waitForJogToComplete(true) +{ +} diff --git a/GCV-3.6.1-T4/src/controlparams.h b/GCV-3.6.1-T4/src/controlparams.h new file mode 100644 index 0000000..7aacef5 --- /dev/null +++ b/GCV-3.6.1-T4/src/controlparams.h @@ -0,0 +1,41 @@ +#ifndef CONTROLPARAMS_H +#define CONTROLPARAMS_H + +#include "definitions.h" + +#define SHORT_WAIT_SEC 2 +#define LONG_WAIT_SEC 100 + +class ControlParams +{ +public: + ControlParams(); + +public: + int waitTime; + double zJogRate; + bool useMm; + bool zRateLimit; + double zRateLimitAmount; + double xyRateAmount; + bool useAggressivePreload; + bool filterFileCommands; + bool reducePrecision; + int grblLineBufferLen; + bool useFourAxis; + int charSendDelayMs; + char fourthAxisName; + bool fourthAxisRotate; +/// T4 + int posReqKind; + bool positionSyncSimu, positionNoDisplay; + bool usePositionRequest; + + QString positionRequestType; + int postionRequestTimeMilliSec; + +/// <-- + bool waitForJogToComplete; +}; + +#endif // CONTROLPARAMS_H diff --git a/GCV-3.6.1-T4/src/coord3d.cpp b/GCV-3.6.1-T4/src/coord3d.cpp new file mode 100644 index 0000000..f99eada --- /dev/null +++ b/GCV-3.6.1-T4/src/coord3d.cpp @@ -0,0 +1,27 @@ +#include "coord3d.h" +/* +Coord3D::Coord3D() + : x(0.0), y(0.0), fourth(0.0), stoppedZ(true), sliderZIndex(0) +{ +} + +bool Coord3D::operator==(const Coord3D& rhs) +{ + return (x == rhs.x && y == rhs.y && fourth == rhs.fourth) ; +} +*/ +Coord3D::Coord3D() + : x(0.0), y(0.0), z(0.0), fourth(0.0), stoppedZ(true), sliderZIndex(0) +{ +} +/// T4 animator +Coord3D::Coord3D(QVector3D xyz) + : x(xyz.x()), y(xyz.y()), z(xyz.z()), fourth(0.0) +{ +} + +bool Coord3D::operator==(const Coord3D& rhs) +{ + return (x == rhs.x && y == rhs.y && z == rhs.z && fourth == rhs.fourth) ; +} + diff --git a/GCV-3.6.1-T4/src/coord3d.h b/GCV-3.6.1-T4/src/coord3d.h new file mode 100644 index 0000000..c864e06 --- /dev/null +++ b/GCV-3.6.1-T4/src/coord3d.h @@ -0,0 +1,26 @@ +#ifndef COORD3D_H +#define COORD3D_H + +#include +#include + +class Coord3D +{ +public: + Coord3D(); +/// T4 animator + Coord3D(QVector3D); + bool operator==(const Coord3D& rhs); + +public: + float x; + float y; + float z; + float fourth; + bool stoppedZ; + int sliderZIndex; +}; + +Q_DECLARE_METATYPE ( Coord3D ) + +#endif // COORD3D_H diff --git a/GCV-3.6.1-T4/src/definitions.h b/GCV-3.6.1-T4/src/definitions.h new file mode 100644 index 0000000..687ce99 --- /dev/null +++ b/GCV-3.6.1-T4/src/definitions.h @@ -0,0 +1,113 @@ +/**************************************************************** + * definitions.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#include +#include +#include +#include "atomicintbool.h" + +#define DEFAULT_WAIT_TIME_SEC 100 + +#define DEFAULT_Z_JOG_RATE 260.0 +#define DEFAULT_Z_LIMIT_RATE 100.0 +#define DEFAULT_XY_RATE 2000.0 + +#define DEFAULT_GRBL_LINE_BUFFER_LEN 50 +#define DEFAULT_CHAR_SEND_DELAY_MS 0 + +#define MM_IN_AN_INCH 25.4 +#define PRE_HOME_Z_ADJ_MM 5.0 + +#define REQUEST_CURRENT_POS "?" +/// T4 +#define PAUSE_COMMAND_V08c "M1" +//#define SETTINGS_COMMAND_V08a "$" +#define HELP_COMMAND_V08c "$" +#define SETTINGS_COMMAND_V08c "$$" +#define SETTINGS_COMMAND_V$ "$" +#define SETTINGS_COMMAND_V$$ "$$" +#define HOMING_CYCLE_COMMAND "$H" +#define CYCLE_START_COMMAND "~" +#define FEED_FOLD_COMMAND "!" + +/// T3 +#define REQUEST_MODE_CHECK "$C" +/// T4 +#define REQUEST_PARSER_STATE_V08c "$G" +#define REQUEST_PARAMETERS_V08c "$#" +#define REQUEST_INFO_V09g "$I" +#define REQUEST_STARTUP_BLOCKS "$N" + +#define SET_UNLOCK_STATE_V08c "$X" +#define REQUEST_PARSER_STATE_V$$ "$G" +#define SET_UNLOCK_STATE_V$$ "$X" + +#define REGEXP_SETTINGS_LINE "(\\d+)\\s*=\\s*([\\w\\.]+)\\s*\\(([^\\)]*)\\)" + +#define LOG_MSG_TYPE_DIAG "DIAG" +#define LOG_MSG_TYPE_STATUS "STATUS" + +/// LETARTARE : one axis choice U or V or W or A or B or C +#define FOURTH_AXIS_U 'U' +#define FOURTH_AXIS_V 'V' +#define FOURTH_AXIS_W 'W' +/// <-- +#define FOURTH_AXIS_A 'A' +#define FOURTH_AXIS_B 'B' +#define FOURTH_AXIS_C 'C' +/// T4 : planes G17, G18, G19 +#define NO_PLANE -1 +#define PLANE_XY_G17 0 // G17 +#define PLANE_YZ_G18 2 // G18 +#define PLANE_ZX_G19 1 // G19 +/// T4 feedrate +#define SPEED_DEFAULT 0 // mm per mn +#define SPEED_MIN 0 +#define SPEED_MAX 24000.0 +#define SPEED_FAST 2000.0 +/// T4 tolerance +#define TOL_MM 0.01 +#define TOL_MM_STEP 0.01 +#define TOL_MM_MIN 0.01 +#define TOL_MM_MAX 1.0 +#define TOL_IN 0.0004 +#define TOL_IN_STEP 0.0004 +#define TOL_IN_MIN 0.0004 +#define TOL_IN_MAX 0.04 +/// TA min, max X, Y, Z mm +#define MIN_X 0.0 +#define MIN_Y 0.0 +#define MIN_Z 0.0 +#define MAX_X 1000.0 // 0.5 m +#define MAX_Y 1000.0 +#define MAX_Z 200.0 + +#define PREQ_ALWAYS "always" +#define PREQ_ALWAYS_NO_IDLE_CHK "alwaysWithoutIdleChk" +#define PREQ_NOT_WHEN_MANUAL "notWhenManual" + +#define DEFAULT_POS_REQ_FREQ_SEC 1.0 +#define DEFAULT_POS_REQ_FREQ_MSEC 1000 + +#define POS_REQ 0 +#define POS_SYNC 1 +#define POS_NO 2 + +extern AtomicIntBool g_enableDebugLog; + +void status(const char *str, ...); +void diag(const char *str, ...); +void err(const char *str, ...); +void warn(const char *str, ...); +void info(const char *str, ...); + +#endif // DEFINITIONS_H diff --git a/GCV-3.6.1-T4/src/fixqt4headers.pl b/GCV-3.6.1-T4/src/fixqt4headers.pl new file mode 100644 index 0000000..bb719f7 --- /dev/null +++ b/GCV-3.6.1-T4/src/fixqt4headers.pl @@ -0,0 +1,170 @@ +#!/usr/bin/env perl +############################################################################# +## +## Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +## Contact: http://www.qt-project.org/legal +## +## This file is part of the porting tools of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and Digia. For licensing terms and +## conditions see http://qt.digia.com/licensing. For further information +## use the contact form at http://qt.digia.com/contact-us. +## +## 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, Digia gives you certain additional +## rights. These rights are described in the Digia Qt LGPL Exception +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3.0 as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL included in the +## packaging of this file. Please review the following information to +## ensure the GNU General Public License version 3.0 requirements will be +## met: http://www.gnu.org/copyleft/gpl.html. +## +## +## $QT_END_LICENSE$ +## +############################################################################# + + +use Cwd; +use File::Find; +use File::Spec; +use IO::File; +use Getopt::Long; +use strict; +use warnings; + +my $dry_run = 0; +my $help = 0; +my $stripModule = 0; +my $fixedFileCount = 0; +my $fileCount = 0; +my $verbose = 0; +my $qtdir = $ENV{'QTDIR'}; + +my $USAGE=< : Point to Qt 5's qtbase directory +EOF + +if (!GetOptions('dry-run' => \$dry_run, 'help' => \$help, + 'strip-modules' => \$stripModule, 'verbose' => \$verbose, 'qtdir:s' => \$qtdir) + || $help) { + print $USAGE; + exit (1); +} + +my %headerSubst = (); +my $cwd = getcwd(); + +sub fixHeaders +{ + my $fileName = $File::Find::name; + my $relFileName = File::Spec->abs2rel($fileName, $cwd); + + # only check sources, also ignore symbolic links and directories + return unless -f $fileName && $fileName =~ /(\.h|\.cpp|\/C|\.cc|\.CC)$/; + + my $inFile = new IO::File('<' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + $fileCount++; + my @affectedClasses; + my @outLines; + + while (my $line = <$inFile>) { + if ($line =~ /^#(\s*)include(\s*)<.*?\/(.*?)>(.*)/) { + my $newHeader = $headerSubst{$3}; + if ($newHeader) { + $line = '#' . $1 . 'include' . $2 . '<' . $newHeader . '>' . $4 . "\n"; + push(@affectedClasses, $3); + } + } elsif ($line =~ /^#(\s*)include(\s*)(.*)/) { + $line = '#' . $1 . 'include' . $2 . '' . $3 . "\n"; + push(@affectedClasses, 'QtGui'); + } + push(@outLines, $line); + } + $inFile->close(); + + if (scalar(@affectedClasses)) { + $fixedFileCount++; + print $relFileName, ': ', join(', ', @affectedClasses), "\n" if ($verbose || $dry_run); + if (!$dry_run) { + my $outFile = new IO::File('>' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); + map { print $outFile $_; } @outLines; + $outFile->close(); + } + } else { + print $relFileName, ": no modification.\n" if ($verbose || $dry_run); + } +} + +sub findQtHeaders +{ + my ($dirName,$baseDir) = @_; + + local (*DIR); + + opendir(DIR, $baseDir . '/include/' . $dirName) || die ('Unable to open ' .$baseDir . '/include/' . $dirName . ': ' . $!); + my @headers = readdir(DIR); + closedir(DIR); + + foreach my $header (@headers) { + next if (-d ($baseDir . '/include/' . $dirName . '/' . $header) || $header =~ /\.pri$/); + $headerSubst{$header} = $stripModule ? $header : ($dirName . '/' . $header); + } +} + +# -------- MAIN + +die "This script requires the QTDIR environment variable pointing to Qt 5\n" unless $qtdir; + +findQtHeaders('QtCore', $qtdir); +findQtHeaders('QtConcurrent', $qtdir); +findQtHeaders('QtWidgets', $qtdir); +findQtHeaders('QtPrintSupport', $qtdir); + +if (-d $qtdir . '/include/QtMultiMedia') { + findQtHeaders('QtMultiMedia', $qtdir); + findQtHeaders('QtMultiMediaWidgets', $qtdir); +} elsif (-d $qtdir . '/../qtmultimedia' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtMultiMedia', $qtdir . '/../qtmultimedia'); + findQtHeaders('QtMultiMediaWidgets', $qtdir . '/../qtmultimedia'); +} + +# Support porting from "Qt 4.99" QtDeclarative to QtQuick (QQuickItem et al) +if (-d $qtdir . '/include/QtQuick') { + findQtHeaders('QtQuick', $qtdir); +} elsif (-d $qtdir . '/../qtdeclarative' ) { + # This is the case if QTDIR points to a source tree instead of an installed Qt + findQtHeaders('QtQuick', $qtdir . '/../qtdeclarative'); +} + +# special case +$headerSubst{'QtGui'} = 'QtWidgets/QtWidgets'; + +find({ wanted => \&fixHeaders, no_chdir => 1}, $cwd); + +print 'Done. ', ($dry_run ? 'Checked' : 'Modified'), ' ', $fixedFileCount, ' of ', $fileCount, " file(s).\n"; diff --git a/GCV-3.6.1-T4/src/forms/about.ui b/GCV-3.6.1-T4/src/forms/about.ui new file mode 100644 index 0000000..a8b1c04 --- /dev/null +++ b/GCV-3.6.1-T4/src/forms/about.ui @@ -0,0 +1,163 @@ + + + About + + + + 0 + 0 + 451 + 214 + + + + About... + + + + + 280 + 170 + 101 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + 10 + 20 + 151 + 61 + + + + + + + Qt::PlainText + + + :/img/logotiny.PNG + + + + + + 180 + 80 + 251 + 91 + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + true + + + + + + 180 + 10 + 261 + 51 + + + + + 12 + 75 + true + + + + Grbl Controller Visualizer + + + + + + 20 + 100 + 130 + 33 + + + + + + + :/img/zapmaker-logo-130.png + + + + + + 20 + 160 + 121 + 16 + + + + + 12 + 75 + true + true + + + + LETARTARE + + + + + + + + + + buttonBox + accepted() + About + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + About + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GCV-3.6.1-T4/src/forms/grbldialog.ui b/GCV-3.6.1-T4/src/forms/grbldialog.ui new file mode 100644 index 0000000..645b4f1 --- /dev/null +++ b/GCV-3.6.1-T4/src/forms/grbldialog.ui @@ -0,0 +1,100 @@ + + + GrblDialog + + + + 0 + 0 + 463 + 555 + + + + + 0 + 0 + + + + Grbl Settings + + + + + + + 1 + 1 + + + + Qt::ImhNone + + + 30 + + + true + + + 3 + + + false + + + 25 + + + 30 + + + true + + + false + + + 30 + + + false + + + + + + + + + + Apply + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/GCV-3.6.1-T4/src/forms/mainwindow.ui b/GCV-3.6.1-T4/src/forms/mainwindow.ui new file mode 100644 index 0000000..7e69d09 --- /dev/null +++ b/GCV-3.6.1-T4/src/forms/mainwindow.ui @@ -0,0 +1,3870 @@ + + + MainWindow + + + Qt::NonModal + + + true + + + + 0 + 0 + 1216 + 960 + + + + + 1 + 0 + + + + + 10000000 + 10000000 + + + + Grbl Controller Visualizer + + + + + + Qt::ToolButtonIconOnly + + + + + 10 + + + 1 + + + 0 + + + + + 2 + + + + + 4 + + + + + 0 + + + + + + 0 + 0 + + + + attempts to connect to the card containing 'Grbl' or terminates the connection + + + Open + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Port name + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + Port selection in those detected by the system + + + true + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + Baud Rate + + + + + + + + 0 + 0 + + + + connection speed to card (bauds) + + + + + + + + + + + false + + + + 1 + 0 + + + + Send File + + + + + + + + stops sending the contents of the file 'Gcode' + + + Stop + + + + + + + load a file for animation + or send to Grbl + + + Choose file + + + + + + + sending line by line the contents of the file 'Gcode' + + + Begin + + + + + + + shows the full name of the loaded file + + + true + + + + + + + Suspend the issuance of the file 'Gcode to the end of the current line + + + Pause + + + true + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + 10 + + + 0 + + + %v + + + + + + + + 0 + 0 + + + + File progress + + + + + + + + 0 + 0 + + + + Queued Commands + + + + + + + + + + + false + + + + 0 + 0 + + + + Runtime: + + + + + + + false + + + + 0 + 0 + + + + time to send a file to 'Grbl' + + + 00:00:00 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Last State: + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + 0 + 0 + + + + + 10 + 75 + true + + + + indicates the last release state Grbl + + + no state + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Lines: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 75 + true + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + Command + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + true + + + 12 + + + + + + + + + + 1 + 1 + + + + 0 + + + + Console + + + + + + + + + 1 + 1 + + + + Qt::ScrollBarAsNeeded + + + QPlainTextEdit::NoWrap + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + Grbl commands + + + Qt::RichText + + + Qt::AlignCenter + + + + + + + false + + + Shows the commands available in Grbl + + + Help + + + + + + + false + + + + 0 + 0 + + + + + 8 + + + + GRBL Settings + + + + + + + false + + + Parameters + + + + + + + false + + + Parser state + + + + + + + false + + + Build info + + + + + + + false + + + Startup blocks + + + + + + + false + + + commands are sent to 'Grbl' simply control without executing + + + Check + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + false + + + + 0 + 0 + + + + Unlock Grbl + + + + + + + false + + + Homing Cycle + + + + + + + false + + + Refresh Pos + + + + + + + false + + + + 0 + 0 + + + + Soft Reset Grbl + + + + + + + + + + + + Visual + + + + + + + + + 1 + 0 + + + + Monitoring the progress of the animation gcode + + + Qt::ScrollBarAsNeeded + + + QPlainTextEdit::NoWrap + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 4 + + + + + + 0 + 0 + + + + + 90 + 16777215 + + + + animation of the scene 3D + + + Animate + + + true + + + false + + + + + + + false + + + + 0 + 0 + + + + + 90 + 16777215 + + + + Starting and stopping the animation + + + Run + + + true + + + true + + + + + + + true + + + + 0 + 0 + + + + + + + + + 0 + 170 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 145 + 145 + 145 + + + + + + + + interpolation tolerance for viewer 3D + + + true + + + 6 + + + QLCDNumber::Flat + + + 0.010000000000000 + + + + + + + + 0 + 0 + + + + Tolerance + + + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + interpolation tolerance for viewer 3D + + + false + + + QAbstractSpinBox::PlusMinus + + + 4 + + + 0.000100000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 0.005000000000000 + + + + + + + + 0 + 0 + + + + + 20 + 16777215 + + + + mm + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + Item segments + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + + + + + 0 + 170 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 144 + 144 + 144 + + + + + + + + interpolation number of segments for 3D + + + true + + + 5 + + + QLCDNumber::Flat + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + false + + + + 0 + 0 + + + + + 90 + 16777215 + + + + Up one line in the gcode + + + + + + + :/img/up.PNG:/img/up.PNG + + + false + + + true + + + true + + + 300 + + + 100 + + + + + + + + + + 0 + 0 + + + + Line : + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Current line gcode + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + false + + + + 0 + 0 + + + + + 90 + 16777215 + + + + Down one line in the gcode + + + + + + + :/img/down.PNG:/img/down.PNG + + + false + + + true + + + true + + + 300 + + + 100 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Period mS + + + Qt::AlignCenter + + + true + + + + + + + + 0 + 0 + + + + + 90 + 16777215 + + + + + 75 + true + + + + Value of the period + + + QFrame::Box + + + QFrame::Raised + + + false + + + 3 + + + QLCDNumber::Flat + + + 200 + + + + + + + + 0 + 0 + + + + + 90 + 90 + + + + Animation period mS + + + 60 + + + 500 + + + 1 + + + 50 + + + 300 + + + 300 + + + false + + + Qt::Horizontal + + + false + + + false + + + false + + + 25.000000000000000 + + + true + + + + + + + + + + + + + + + + + false + + + + 0 + 0 + + + + Removes the selected text lines + + + Clear selection + + + + + + + false + + + + 0 + 0 + + + + Prints lines of text selected +otherwise all text + + + Print selection + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Prints lines of text selected +otherwise all text + + + Print visual + + + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + 2 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + + Feed rate + + + + + + + + 1 + 0 + + + + + + + + + 0 + 156 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 122 + 122 + 122 + + + + + + + + + 10 + + + + Speed rate gcode (mm or inches per minute) + + + false + + + 5 + + + QLCDNumber::Dec + + + QLCDNumber::Outline + + + 0.000000000000000 + + + 0 + + + + + + + + 0 + 0 + + + + + 75 + true + + + + mm/mn + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Speed spindle + + + + + + + + 0 + 0 + + + + + + + + + 6 + 6 + 6 + + + + + + + + + 6 + 6 + 6 + + + + + + + + + 6 + 6 + 6 + + + + + + + + Last spindle speed read in the Gcode + + + QFrame::Box + + + QFrame::Raised + + + 1 + + + 5 + + + QLCDNumber::Outline + + + + + + + + 0 + 0 + + + + + 75 + true + + + + rpm + + + + + + + + + 0 + + + + + + 0 + 0 + + + + Machine Coordinates + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + Work Coordinates + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + Pass in absolute coordinates after moving it occurs in relative displacement + + + G90 after adjust + + + true + + + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + X + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 8 + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Unit X axis + + + mm + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 2 + 2 + 2 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 10 + 50 + false + true + + + + QFrame::Box + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + + 0 + 0 + + + + Moves the axis at zero + + + + + + + :/img/home.png:/img/home.png + + + + + + + + 0 + 0 + + + + Move the axis to negative values + + + + + + + :/img/left.png:/img/left.png + + + + + + + + 0 + 0 + + + + Move the axis to the positive values + + + + + + + :/img/right.png:/img/right.png + + + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + Y + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Unit Y axis + + + mm + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 16 + 16 + 16 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Box + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + + 0 + 0 + + + + Moves the axis at zero + + + + + + + :/img/home.png:/img/home.png + + + + + + + + 0 + 0 + + + + Move the axis to negative values + + + + + + + :/img/down.png:/img/down.png + + + + + + + + 0 + 0 + + + + Move the axis to the positive values + + + + + + + :/img/up.png:/img/up.png + + + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 53 + + + + + 18 + + + + Z + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Unit Z axis + + + mm + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + + 0 + 0 + + + + Moves the axis at zero + + + + + + + :/img/home.png:/img/home.png + + + + + + + + 0 + 0 + + + + + + + + + 159 + 159 + 159 + + + + + + + 139 + 139 + 139 + + + + + + + + + 159 + 159 + 159 + + + + + + + 139 + 139 + 139 + + + + + + + + + 159 + 159 + 159 + + + + + + + 139 + 139 + 139 + + + + + + + + Move the axis to negative values + + + + + + + :/img/down.png:/img/down.png + + + + + + + + 0 + 0 + + + + + + + + + 159 + 159 + 159 + + + + + + + 209 + 209 + 209 + + + + + + + 0 + 0 + 0 + + + + + + + + + 159 + 159 + 159 + + + + + + + 209 + 209 + 209 + + + + + + + 0 + 0 + 0 + + + + + + + + + 159 + 159 + 159 + + + + + + + 209 + 209 + 209 + + + + + + + 96 + 96 + 96 + + + + + + + + Move the axis to the positive values + + + + + + + :/img/up.png:/img/up.png + + + + + + + + + + 0 + 0 + + + + + 29 + 0 + + + + + 16777215 + 52 + + + + + 18 + + + + T + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Unit of the fourth axis + + + deg + + + + + + + + + + 0 + 0 + + + + Moves the axis at zero + + + + + + + :/img/home.png:/img/home.png + + + + + + + + 0 + 0 + + + + Axis moves clockwise +Move the axis to negative values + + + + + + + :/img/left.png:/img/left.png + + + + + + + + 0 + 0 + + + + Moves the axis in the counterclockwise +Move the axis to the positive values + + + + + + + :/img/right.png:/img/right.png + + + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 52 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 50 + false + true + + + + QFrame::Raised + + + 1 + + + 0 + + + true + + + 7 + + + QLCDNumber::Filled + + + + + + + + + + 0 + 0 + + + + Step size, accept cursors keyboard commands + + + 1 + + + 10000 + + + 10000 + + + true + + + Qt::Vertical + + + QSlider::TicksAbove + + + 500 + + + + + + + + + + 0 + 0 + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + + 109 + 109 + 109 + + + + + + + 109 + 109 + 109 + + + + + + + + + 109 + 109 + 109 + + + + + + + 255 + 255 + 255 + + + + + + + + + 109 + 109 + 109 + + + + + + + 255 + 255 + 255 + + + + + + + + Small movements of the Z axis + + + 80 + + + 40 + + + Qt::Vertical + + + QSlider::TicksAbove + + + 4 + + + + + + + + 0 + 0 + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 23 + + + + + + + + + 86 + 86 + 86 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 6 + + + + Step value for the relative movements (G91) + + + false + + + 5 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + Go Home :first moves the Z axis + then all axes synchronously at zero + + + + + + + :/img/homeall.png:/img/homeall.png + + + + + + + The current position will be the new zero position :G92 x0 y0 z0 + + + + + + + :/img/isoview1.png:/img/isoview1.png + + + + + + + + + + 1 + 1 + + + + QTabWidget::North + + + QTabWidget::Rounded + + + 1 + + + + Visualizer + + + + 0 + + + 0 + + + + + true + + + + 1 + 1 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 255 + 255 + 255 + + + + + + + 244 + 237 + 187 + + + + + + + + + 244 + 237 + 187 + + + + + + + 244 + 237 + 187 + + + + + + + + true + + + + + + + + + 1 + 1 + + + + Viewer3D + + + + 1 + + + 2 + + + + + + 1 + 1 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + Qt::StrongFocus + + + + + + + 12 + + + QLayout::SetMinimumSize + + + 0 + + + + + Perspective view + + + + + + + :/img/isoview2.png:/img/isoview2.png + + + + + + + true + + + Front view + + + + + + + :/img/frontview.png:/img/frontview.png + + + + + + + Back view + + + + + + + :/img/backview.png:/img/backview.png + + + + + + + Left view + + + + + + + :/img/leftview.png:/img/leftview.png + + + + + + + Right view + + + + + + + :/img/rightview.png:/img/rightview.png + + + + + + + Bottom view + + + + + + + :/img/bottomview.png:/img/bottomview.png + + + + + + + Top view + + + + + + + :/img/topview.png:/img/topview.png + + + + + + + Vector up along Y axis + + + + + + + :/img/upvector.png:/img/upvector.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + tool selection + + + Qt::LeftToRight + + + Tool + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + false + + + Qt::UpArrow + + + + + + + With or without bounding box + + + Bbox + + + true + + + + + + + with or without rapid movements + + + G0 + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Help 3D + + + Help 3D + + + false + + + + + + + + + + + + + + + Firmware : + + + + + + + + 75 + true + + + + Grbl version + + + -1 + + + none + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Spindle control: running -> yellow + + + Spindle On + + + true + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Queue clear + + + + + + + false + + + + 0 + 0 + + + + + 8 + + + + The current position will be the new zero position :G92 x0 y0 z0 + + + false + + + = Zero Position + + + + + + + + + + + + + 0 + 0 + 1216 + 23 + + + + + &Help + + + + + + &Tools + + + + + + &File + + + + + + + + + + + &About + + + + + &Options + + + + + E&xit + + + + + + + Viewer + +
visu3D/viewer3D.h
+
+ + RenderArea + QWidget +
renderarea.h
+ 1 +
+
+ + + + + + doubleSpinBoxTol + valueChanged(double) + lcdTolerance + display(double) + + + 987 + 198 + + + 989 + 173 + + + + +
diff --git a/GCV-3.6.1-T4/src/forms/options.ui b/GCV-3.6.1-T4/src/forms/options.ui new file mode 100644 index 0000000..dbc846d --- /dev/null +++ b/GCV-3.6.1-T4/src/forms/options.ui @@ -0,0 +1,936 @@ + + + Options + + + + 0 + 0 + 484 + 333 + + + + + 0 + 0 + + + + Options + + + + + 10 + 10 + 461 + 281 + + + + + 1 + 1 + + + + 0 + + + + General + + + + + 10 + 146 + 431 + 82 + + + + + + + Z-Jog Rate (mm/min) + + + + + + + Seconds to Wait for Response + + + + + + + 1 + + + 1000 + + + 60 + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 260.000000000000000 + + + + + + + Qt::LeftToRight + + + 500000 + + + 500000 + + + + + + + Max Log Lines ( 0 : unlimited ) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 10 + 451 + 121 + + + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + + + Use aggressive preload strategy for Grbl + + + + + + + false + + + Wait for each jog/manual command to complete (future feature) + + + + + + + Write debugging log to home folder (requires restart) + + + + + + + + + Filtering + + + + + 10 + 10 + 441 + 81 + + + + Z Rate Limiting + + + + + 10 + 20 + 421 + 53 + + + + + + + Limit Z Rate + + + + + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + 3 + + + 0.100000000000000 + + + 9999.989999999999782 + + + 1.000000000000000 + + + 1000.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Z-Rate Limit (inches or mm/min) + + + + + + + XY Rate (inches or mm/min) + + + + + + + 2 + + + 0.100000000000000 + + + 999999.989999999990687 + + + 2000.000000000000000 + + + + + + + + + + 10 + 200 + 261 + 24 + + + + + + + Character send delay ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 10 + 100 + 441 + 61 + + + + Command Filtering + + + + + 30 + 20 + 431 + 17 + + + + Filter file commands before sending + + + + + + 30 + 40 + 431 + 17 + + + + Selectively reduce precision for excessively long lines + + + + + + + 10 + 170 + 261 + 24 + + + + + + + Grbl Line Buffer Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 270 + 200 + 50 + 22 + + + + 20 + + + 10 + + + + + + 270 + 170 + 50 + 22 + + + + 50 + + + + + + Axis + + + + + 10 + 111 + 441 + 60 + + + + Invert Axis + + + + + 20 + 20 + 411 + 31 + + + + + + + X Axis + + + + + + + Y Axis + + + + + + + Z Axis + + + + + + + Fourth Axis + + + + + + + + + + 10 + 41 + 441 + 51 + + + + Selecting the Fourth axis + + + + + 10 + 22 + 50 + 17 + + + + A + + + true + + + + + + 80 + 22 + 50 + 17 + + + + B + + + + + + 150 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + C + + + + + + 240 + 20 + 50 + 21 + + + + Qt::PreventContextMenu + + + U + + + + + + 310 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + V + + + + + + 380 + 22 + 50 + 17 + + + + Qt::PreventContextMenu + + + W + + + + + + + 10 + 11 + 421 + 17 + + + + Enable 4-axis mode + + + + + + Display + + + + + 1 + 97 + 451 + 151 + + + + + 1 + 1 + + + + Position Request + + + + + 10 + 20 + 431 + 121 + + + + + + + + 1 + 0 + + + + Always Request (most reliable/slightly slower jogging) + + + true + + + + + + + + 0 + 1 + + + + Always Request but without Idle Check (fast jog/manual operations) + + + true + + + + + + + + 0 + 1 + + + + Not during manual control (no position update during jog/manual) + + + true + + + + + + + 1 + + + + + + 1 + 0 + + + + Request frequency (seconds) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + 0.500000000000000 + + + 10.000000000000000 + + + 0.500000000000000 + + + 1.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 2 + 4 + 451 + 91 + + + + + 1 + 1 + + + + Display the position + + + + + 10 + 19 + 421 + 71 + + + + + 4 + + + 3 + + + 5 + + + + + true + + + + 1 + 1 + + + + Qt::LeftToRight + + + Enable position request and report + + + true + + + true + + + + + + + + 1 + 1 + + + + Synchronous simulation (! EXPERIMENTAL !) + + + false + + + true + + + false + + + + + + + + 1 + 1 + + + + No display + + + false + + + true + + + + + + + + + + + + 280 + 297 + 191 + 30 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + Options + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Options + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/GCV-3.6.1-T4/src/gcode.cpp b/GCV-3.6.1-T4/src/gcode.cpp new file mode 100644 index 0000000..2b8a92f --- /dev/null +++ b/GCV-3.6.1-T4/src/gcode.cpp @@ -0,0 +1,2323 @@ +/**************************************************************** + * gcode.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "gcode.h" + +#include + +GCode::GCode() + : errorCount(0), doubleDollarFormat(false), + incorrectMeasurementUnits(false), incorrectLcdDisplayUnits(false), + maxZ(0), motionOccurred(false), + sliderZCount(0), + positionValid(false), + numaxis(DEFAULT_AXIS_COUNT), +/// T3 + checkState(false) +{ + // use base class's timer - use it to capture random text from the controller + startTimer(1000); + // for position polling + pollPosTimer.start(); +} + +void GCode::openPort(QString commPortStr, QString baudRate) +{ + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + clearToHome(); + + currComPort = commPortStr; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if (port.OpenComport(commPortStr, baudRate)) + { + emit portIsOpen(true); + emit sendMsgSatusBar(""); + } + else + { + emit portIsClosed(false); + QString msg = tr("Can't open COM port ") + commPortStr; + sendMsgSatusBar(msg); + addList(msg); + warn("%s", qPrintable(msg)); + + addList(tr("-Is hardware connected to USB?") ); + addList(tr("-Is correct port chosen?") ); + addList(tr("-Does current user have sufficient permissions?") ); +#if defined(Q_OS_LINUX) + addList("-Is current user in sudoers group?"); +#endif + //QMessageBox(QMessageBox::Critical,"Error","Could not open port.",QMessageBox::Ok).exec(); + } +} + +void GCode::closePort(bool reopen) +{ + port.CloseComport(); + emit portIsClosed(reopen); +} + +bool GCode::isPortOpen() +{ + return port.isPortOpen(); +} + +// Abort means stop file send after the end of this line +void GCode::setAbort() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + abortState.set(true); +} + +// Reset means immediately stop waiting for a response +void GCode::setReset() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + resetState.set(true); +} + +// Shutdown means app is shutting down - we give thread about .3 sec to exit what it is doing +void GCode::setShutdown() +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + shutdownState.set(true); +} + +/// T4 +// Pause means pause file send after the end of this line +// calls : 'MainWindow::pauseSend()':2 +void GCode::setPause(bool valid) +{ + // cross-thread operation, only set one atomic variable in this method (bool in this case) or add critsec + pauseState.set(valid); +} + +//--------------------------------------------------- +void GCode::sendGrblHelp() +{ + sendGcodeLocal(HELP_COMMAND_V08c); +} +void GCode::sendGrblParameters() +{ + sendGcodeLocal(REQUEST_PARAMETERS_V08c); +} +void GCode::sendGrblParserState() +{ + // sendGcodeLocal(REQUEST_PARSER_STATE_V08c); + sendGcodeLocal(REQUEST_PARSER_STATE_V$$); +} +void GCode::sendGrblBuildInfo() +{ + if (versionGrbl == "0.9g") + sendGcodeLocal(REQUEST_INFO_V09g); +} +void GCode::sendGrblStartupBlocks() +{ + sendGcodeLocal(REQUEST_STARTUP_BLOCKS); +} +/// T3 +// Slot for file check +// calls : 'MainWindow::grblCheck()':1, +void GCode::sendGrblCheck(bool checkstate) +{ + checkState = false; + if (!sendGcodeLocal(REQUEST_MODE_CHECK)) { + /// ... + // emit + } + else + if (!sendGcodeLocal(REQUEST_CURRENT_POS )) { + /// ... + + } + else + checkState = checkstate ; +} +void GCode::sendGrblUnlock() +{ + // sendGcodeLocal(SET_UNLOCK_STATE_V08c); + sendGcodeLocal(SET_UNLOCK_STATE_V$$); +} +void GCode::sendGrblHomingCycle() +{ + sendGcodeLocal(HOMING_CYCLE_COMMAND); +} +void GCode::sendGrblCycleStart() +{ + sendGcodeLocal(CYCLE_START_COMMAND); +} +void GCode::sendGrblFeedHold() +{ + sendGcodeLocal(FEED_FOLD_COMMAND); +} + +void GCode::sendGrblStatus() +{ + sendGcodeLocal(REQUEST_CURRENT_POS); +} +// Slot for interrupting current operation or doing a clean reset of grbl without changing position values +void GCode::sendGrblReset() +{ + clearToHome(); + + QString x(CTRL_X); + sendGcodeLocal(x, true, SHORT_WAIT_SEC); +} +//-------------------------------------------------------- + +// Slot for gcode-based 'zero out the current position values without motion' +void GCode::grblSetHome() +{ + clearToHome(); + + QString sethome("G92 x0 y0 z0 "); + if (numaxis == MAX_AXIS_COUNT) +/// T4 + sethome.append(QString(controlParams.fourthAxisName).toLower()).append("0"); + + gotoXYZFourth(sethome); +} + +// calls : 'Mainwindow::goToHome()' +void GCode::goToHome() +{ + if (!motionOccurred) + return; + + double maxZOver = maxZ; + + if (doubleDollarFormat) + { + maxZOver += (controlParams.useMm ? PRE_HOME_Z_ADJ_MM : (PRE_HOME_Z_ADJ_MM / MM_IN_AN_INCH)); + } + else + { + // all reporting is in mm ?? + maxZOver += PRE_HOME_Z_ADJ_MM; + } + + QString zpos = QString::number(maxZOver); + +/// T4 + QString cmd = "G90 G0 z"; + gotoXYZFourth(cmd.append(zpos)); + cmd = "G90 G1 x0 y0 z0 "; + if (numaxis == MAX_AXIS_COUNT) { + QString fourth = QString(controlParams.fourthAxisName).toLower(); + cmd.append(fourth.append("0")); + } + +//diag("=========> cmd = %s", qPrintable(cmd)); + // TODO + feedrate for 0.9g ! the smallest ? -> 'controlParams.zRateLimitAmount' + cmd.append(" F").append(QString::number(controlParams.zJogRate)); + gotoXYZFourth(cmd); + + maxZ -= maxZOver; + + motionOccurred = false; +} + +/// T4 +// calls : 'MainWindow::homeX()':1, 'MainWindow::homeY()':1, 'MainWindow::homeZ()':1 +// 'MainWindow::homeFourth()':1, +void GCode::goToHomeAxis(char axis) +{ + /// verify axis + bool ok = axis == 'X' || axis == 'Y' || axis == 'Z' || + axis == 'A' || axis == 'B' || axis == 'C' || + axis == 'U' || axis == 'V' || axis == 'W' + ; + if (!ok) + return; + + QString cmd = "G90 G0 "; + if (controlParams.useFourAxis && axis == controlParams.fourthAxisName) + cmd.append(QString(controlParams.fourthAxisName)); + else // X, Y, Z + cmd.append(QString(axis) ); + + QString txt("0"); + if (axis == 'X') { + txt = QString().number(MIN_X); + } + else + if (axis == 'Y') + txt = QString().number(MIN_Y); + else + if (axis == 'Z') + txt = QString().number(MIN_Z); + + cmd = cmd.toLower().append(txt) ; + + if (controlParams.usePositionRequest + && controlParams.positionRequestType == PREQ_ALWAYS) + pollPosWaitForIdle(false); + + if (sendGcodeLocal(cmd) ) + { + pollPosWaitForIdle(false); + } + else + { + QString msg(QString(tr("Bad command: %1")).arg(cmd)); + warn("%s", qPrintable(msg)); + emit addList(msg); + } + + emit endHomeAxis(); +} + +// Slot called from other threads (i.e. main window, grbl dialog, etc.) +void GCode::sendGcode(QString line) +{ + bool checkMeasurementUnits = false; + + // empty line means we have just opened the com port + if (line.length() == 0) + { + resetState.set(false); + + QString result; + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, false)) + { + if (shutdownState.get() || resetState.get()) + return; + // it is possible that we are already connected and missed the + // signon banner. Force a reset (is this ok?) to get the banner +/// LETARTARE for 0.845 !! + if (versionGrbl != "0.845") + { + emit addListOut("(CTRL-X)"); + + char buf[2] = {0}; + + buf[0] = CTRL_X; + + diag(qPrintable(tr("SENDING: 0x%02X (CTRL-X) to check presence of Grbl\n")), buf[0]) ; + if (sendToPort(buf)) + emit sendMsgSatusBar(""); + /* + if (!port.SendBuf(buf, 1)) + { + QString msg = tr("Sending to port failed"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsgSatusBar(msg); + return; + } + else { + emit sendMsgSatusBar(""); + } + */ + } +/// <-- + if (!waitForStartupBanner(result, SHORT_WAIT_SEC, true)) + return; + } +/// T4 : to avoid loading too display +/// to review ... + checkMeasurementUnits = true; + // checkMeasurementUnits = false; + } + else + { + pollPosWaitForIdle(false); + // normal send of actual commands + sendGcodeLocal(line, false); + } + + pollPosWaitForIdle(checkMeasurementUnits); +} + +// keep polling our position and state until we are done running +void GCode::pollPosWaitForIdle(bool checkMeasurementUnits) +{ + if (controlParams.usePositionRequest + && (controlParams.positionRequestType == PREQ_ALWAYS_NO_IDLE_CHK + || controlParams.positionRequestType == PREQ_ALWAYS + || checkMeasurementUnits) + ) + { + bool immediateQuit = false; + for (int i = 0; i < 10000; i++) + { + GCode::PosReqStatus ret = positionUpdate(); + if (ret == POS_REQ_RESULT_ERROR || ret == POS_REQ_RESULT_UNAVAILABLE) + { + immediateQuit = true; + break; + } + else if (ret == POS_REQ_RESULT_TIMER_SKIP) + { + SLEEP(250); + continue; + } + + if (doubleDollarFormat) + { + if (lastState.compare("Run") != 0) + break; + } + else + { + if (machineCoordLastIdlePos == machineCoord + && workCoordLastIdlePos == workCoord) + { + break; + } + + machineCoordLastIdlePos = machineCoord; + workCoordLastIdlePos = workCoord; + } + + if (shutdownState.get()) + return; + } + + if (immediateQuit) + return; + + if (checkMeasurementUnits) + { + if (doubleDollarFormat) { + checkAndSetCorrectMeasurementUnits(); + } + else { + setOldFormatMeasurementUnitControl(); + } + } + } + else + { + setLivenessState(false); + } +} + +// calls : 'GCode::sendGcodeLocal()':1, 'GCode::waitForStartupBanner()':1 +bool GCode::checkGrbl(const QString& result) +{ + if (result.contains("Grbl")) + { +/// T2 + (\\w*) for 0.8cx + QRegExp rx("Grbl (\\d+)\\.(\\d+)(\\w*)(\\w*)"); + if (rx.indexIn(result) != -1 && rx.captureCount() > 0) + { + doubleDollarFormat = false; + + QStringList list = rx.capturedTexts(); + if (list.size() >= 3) + { + int majorVer = list.at(1).toInt(); + int minorVer = list.at(2).toInt(); + char letter = ' '; + char postVer = ' '; /// T2 + if (list.size() >= 4 && list.at(3).size() > 0) + { + letter = list.at(3).toLatin1().at(0); + /// T2 for 0.8cx + if (list.at(3).toLatin1().size() > 1) + postVer = list.at(3).toLatin1().at(1); + } + + if (majorVer > 0 || (minorVer > 8 && minorVer < 51) || letter > 'a') + { + doubleDollarFormat = true; + } +/// T2 + diag(qPrintable(tr("Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d)\n")), + majorVer, minorVer, letter, postVer, doubleDollarFormat); + QString resu = list.at(0); + emit setVersionGrbl(resu); +/// T4 + versionGrbl = resu.mid(5) ; +//diag("VersionGrbl ->%s<-", qPrintable(versionGrbl) ); +/// <-- + } + /* + if (!doubleDollarFormat) + emit setUnitMmAll(true); + */ + } + return true; + } + return false; +} + +// Slot called from other thread that returns whatever text comes back from the controller +void GCode::sendGcodeAndGetResult(int id, QString line) +{ + QString result; + + emit sendMsgSatusBar(""); + resetState.set(false); + if (!sendGcodeInternal(line, result, false, SHORT_WAIT_SEC, false)) + result.clear(); + + emit gcodeResult(id, result); +} + +// To be called only from this class, not from other threads. Use above two methods for that. +// Wraps sendGcodeInternal() to allow proper handling of failure cases, etc. +bool GCode::sendGcodeLocal(QString line, bool recordResponseOnFail /* = false */, int waitSec /* = -1 */, bool aggressive /* = false */, int currLine /* = 0 */) +{ + QString result; + emit sendMsgSatusBar(""); + resetState.set(false); + + bool ret = sendGcodeInternal(line, result, recordResponseOnFail, waitSec, aggressive, currLine); + if (shutdownState.get()) + return false; + + if (!ret && (!recordResponseOnFail || resetState.get())) + { + if (!resetState.get()) { + emit stopSending(); + } + + if (!ret && resetState.get()) + { + resetState.set(false); + port.Reset(); + } + } + else + { + if (checkGrbl(result)) + { + emit enableGrblDialogButton(); + } + } + resetState.set(false); + return ret; +} + +// Wrapped method. Should only be called from above method. +bool GCode::sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine /* = 0 */) +{ + if (!port.isPortOpen()) + { + QString msg = tr("Port not available yet") ; + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsgSatusBar(msg); + return false; + } + else + emit sendMsgSatusBar(""); + + bool ctrlX = line.size() > 0 ? (line.at(0).toLatin1() == CTRL_X) : false; + + bool sentReqForLocation = false; + bool sentReqForSettings = false; + bool sentReqForParserState = false; + + if (checkForGetPosStr(line)) + { + sentReqForLocation = true; + setLivenessState(true); + } +// else if (!line.compare(REQUEST_PARSER_STATE_V08c)) + else if (!line.compare(REQUEST_PARSER_STATE_V$$)) // "$G" + { + sentReqForParserState = true; + } +// else if (!line.compare(SETTINGS_COMMAND_V08c)) + else if (!line.compare(SETTINGS_COMMAND_V$$)) // "$$" + { +/// T4 always "$$" ... + sentReqForSettings = true; + } + else + motionOccurred = true; + + // adds to UI list, but prepends a > indicating a sent command + if (ctrlX) + { + emit addListOut("(CTRL-X)"); + } + else if (!sentReqForLocation)// if requesting location, don't add that "noise" to the output view + { +/// T3 + fix bug + QString nLine(line); + if (currLine) { + nLine = QString().setNum(currLine); + emit setLinesFile(nLine, true); + if (line.at(0).toLatin1() != 'N') + nLine = "L" + nLine + " " + line; + else + nLine = line ; + } +/// T4 - '$$', + if (!checkState && !sentReqForSettings) + emit addListOut(nLine); +/// <-- + } + + if (line.size() == 0 || (!line.endsWith('\r') && !ctrlX)) + line.append('\r'); + + char buf[BUF_SIZE + 1] = {0}; + if (line.length() >= BUF_SIZE) + { + QString msg = tr("Buffer size too small"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsgSatusBar(msg); + return false; + } + else + emit sendMsgSatusBar(""); + + for (int i = 0; i < line.length(); i++) + buf[i] = line.at(i).toLatin1(); + + if (ctrlX) + diag(qPrintable(tr("SENDING[%d]: 0x%02X (CTRL-X)\n")), currLine, buf[0]); + else + diag(qPrintable(tr("SENDING[%d]: %s\n")), currLine, buf); + + int waitSecActual = waitSec == -1 ? controlParams.waitTime : waitSec; + + if (aggressive) + { + if (ctrlX) + sendCount.append(CmdResponse("(CTRL-X)", line.length(), currLine)); + else + sendCount.append(CmdResponse(buf, line.length(), currLine)); + +//diag("DG Buffer Add %d", sendCount.size()); + + emit setQueuedCommands(sendCount.size(), true); +/// T4 + waitForOk(result, waitSecActual, false, false, false, aggressive, false); + + if (shutdownState.get()) + return false; + } + + if (!port.SendBuf(buf, line.length())) + { + QString msg = tr("Sending to port failed") ; + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsgSatusBar(msg); + return false; + } + else + { + emit sendMsgSatusBar(""); + sentI++; +/// T4 + if (!waitForOk(result, waitSecActual, sentReqForLocation, sentReqForSettings, + sentReqForParserState, aggressive, false)) + { + diag(qPrintable(tr("WAITFOROK FAILED\n"))); + if (shutdownState.get()) + return false; + + if (!recordResponseOnFail && !(resetState.get() || abortState.get())) + { + QString msg = tr("Wait for ok failed"); + emit addList(msg); + emit sendMsgSatusBar(msg); + } + else + emit sendMsgSatusBar(""); + + return false; + } + else + { + if (sentReqForSettings) + { + QStringList list = result.split("$"); + for (int i = 0; i < list.size(); i++) + { + QString item = list.at(i); + const QRegExp rx(REGEXP_SETTINGS_LINE); + + if (rx.indexIn(item, 0) != -1 && rx.captureCount() == 3) + { + QStringList capList = rx.capturedTexts(); +/// T4 with 0.9x 13 is not good !! +/// 0.8c->$13, 0.8c1/2->$14, 0.9d->$20, 0.9e/f->$19 , 09g -> $13 ( 0.845 ?? ) + QString val = getNumGrblUnit(); +//diag ("getNumGrblUnit() = %s", qPrintable(val) ) ; + if (!capList.at(1).compare(val)) + { + bool Grblg20 = capList.at(2).compare("0"), + g21 = controlParams.useMm ; + incorrectLcdDisplayUnits = Grblg20 == g21; + + break; + } + } + } + settingsItemCount.set(list.size()); + } + } + } + return true; +} + +/// T4 +// calls : 'sendGcodeInternal()':1, +// 'setConfigureMmMode()':1, 'setConfigureInchesMode(':1 +QString GCode::getNumGrblUnit() +{ + QString resu("13"); // 0.8c , 09d ?? + // if (versionGrbl == "0.845") + // resu = "14"; + // else + if (versionGrbl == "0.8c1" || versionGrbl == "0.8c2" ) + resu = "14"; + else + if (versionGrbl == "0.9d") + resu = "20"; + else + if (versionGrbl == "0.9e" || versionGrbl == "0.9f") + resu = "19"; + else + if (versionGrbl == "0.9g") + resu = "13"; + + return resu; +} + +///----------------------------------------------------------------------------- +/// T4 + 'bool sentRequestForSettings' +bool GCode::waitForOk(QString& result, int waitSec, bool sentReqForLocation, + bool sentRequestForSettings, bool sentReqForParserState, + bool aggressive, bool finalize) +{ + int okcount = 0; + + if (aggressive) + { + //if (!port.bytesAvailable()) //more conservative code + if (!finalize || !port.bytesAvailable()) + { + int total = 0; + bool haveWait = false; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + if (cmdResp.waitForMe) + { + haveWait = true; + } + } +//diag("Total out (a): %d (%d) (%d)\n", total, sendCount.size(), haveWait); + + if (!haveWait) + { + if (total < (GRBL_RX_BUFFER_SIZE - 1)) + { + return true; + } + } + } + } + + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!result.contains(RESPONSE_OK) && !result.contains(RESPONSE_ERROR) && !resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + if (aggressive && sendCount.size() == 0) + return false; + + count++; + SLEEP(100); + } + else + if (n < 0) + { + QString Mes(tr("Error reading data from COM port\n")) ; + err(qPrintable(Mes)); + + if (aggressive && sendCount.size() == 0) + return false; + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + QString received(tmp); + + if (aggressive) + { + if (received.contains(RESPONSE_OK)) + { + if (sendCount.isEmpty()) { + err(qPrintable(tr("Unexpected: list is empty (o)!"))); + } + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + diag(qPrintable(tr("GOT[%d]: '%s' for '%s' (aggressive)\n")), cmdResp.line, + qPrintable(tmpTrim), qPrintable(cmdResp.cmd.trimmed())); +//diag("DG Buffer %d", sendCount.size()); + emit setQueuedCommands(sendCount.size(), true); + } + rcvdI++; + okcount++; + } + else + if (received.contains(RESPONSE_ERROR)) + { + QString orig(tr("Error?")); + if (sendCount.isEmpty()) + err(qPrintable(tr("Unexpected: list is empty (e)!"))); + else + { + CmdResponse cmdResp = sendCount.takeFirst(); + orig = cmdResp.cmd; + diag(qPrintable(tr("GOT[%d]: '%s' for '%s' (aggressive)\n")), cmdResp.line, + qPrintable(tmpTrim), qPrintable(cmdResp.cmd.trimmed())); +//diag("DG Buffer %d", sendCount.size()); + emit setQueuedCommands(sendCount.size(), true); + } + errorCount++; + QString result; + QTextStream(&result) << received << " [for " << orig << "]"; + emit addList(result); + grblCmdErrors.append(result); + rcvdI++; + } + else + { + diag(qPrintable(tr("GOT: '%s' (aggressive)\n")), qPrintable(tmpTrim.trimmed()) ); + parseCoordinates(received, aggressive); + } + + int total = 0; + foreach (CmdResponse cmdResp, sendCount) + { + total += cmdResp.count; + } +//diag("Total out (b): %d (%d)\n", total, sendCount.size()); +//diag("SENT:%d RCVD:%d\n", sentI, rcvdI); + if (total >= (GRBL_RX_BUFFER_SIZE - 1)) + { +//diag("DG Loop again\n"); + result.clear(); + continue; + } + else + if (port.bytesAvailable()) + { + // comment out this block for more conservative approach + if (!finalize && okcount > 0) + { +//diag("DG Leave early\n"); + return true; + } + + result.clear(); + continue; + } + else + { + return true; + } + } + else + { + diag(qPrintable(tr("GOT:%s\n")), qPrintable(tmpTrim)); + } + + if (!received.contains(RESPONSE_OK) && !received.contains(RESPONSE_ERROR)) + { + if (sentReqForParserState) + { + const QRegExp rx("\\[([\\s\\w\\.\\d]+)\\]"); + + if (rx.indexIn(received, 0) != -1 && rx.captureCount() == 1) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 2) + { +/// T4 + QStringList items = list.at(1).split(" "); + if (items.contains("G20"))// inches + incorrectMeasurementUnits = controlParams.useMm == true ; + else + if (items.contains("G21"))// millimeters + incorrectMeasurementUnits = controlParams.useMm == false; + else // not in list! + incorrectMeasurementUnits = true; + } + } + } + else + { + parseCoordinates(received, aggressive); + } + } + count = 0; + } + + SLEEP(100); + + if (count > waitCount) + { + // waited too long for a response, fail + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (!aggressive) + SLEEP(100); + + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; +/// T4 + bool banned = sentReqForLocation || sentRequestForSettings; + for (int i = 0; i < list.size(); i++) + { + // if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !sentReqForLocation && !list.at(i).startsWith("MPos:[")) + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK && !banned && !list.at(i).startsWith("MPos:[")) + listToSend.append(list.at(i)); + } + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +///----------------------------------------------------------------------------- +bool GCode::waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound) +{ + char tmp[BUF_SIZE + 1] = {0}; + int count = 0; + int waitCount = waitSec * 10;// multiplier depends on sleep values below + bool status = true; + result.clear(); + while (!resetState.get()) + { + int n = port.PollComportLine(tmp, BUF_SIZE); + if (n == 0) + { + count++; + SLEEP(100); + } + else if (n < 0) + { + err(qPrintable(tr("Error reading data from COM port\n")) ); + } + else + { + tmp[n] = 0; + result.append(tmp); + + QString tmpTrim(tmp); + int pos = tmpTrim.indexOf(port.getDetectedLineFeed()); + if (pos != -1) + tmpTrim.remove(pos, port.getDetectedLineFeed().size()); + diag(qPrintable(tr("GOT:%s\n")), qPrintable(tmpTrim)); + + if (tmpTrim.length() > 0) + { + if (!checkGrbl(tmpTrim)) + { + if (failOnNoFound) + { + QString msg(tr("Expecting Grbl version string. Unable to parse response.")); + emit addList(msg); + emit sendMsgSatusBar(msg); + + closePort(false); + } + else + emit sendMsgSatusBar(""); + + status = false; + } + else + { + emit enableGrblDialogButton(); + } + break; + } + } + + SLEEP(100); + + if (count > waitCount) + { + if (failOnNoFound) + { + // waited too long for a response, fail + + QString msg(tr("No data from COM port after connect. Expecting Grbl version string.")); + emit addList(msg); + emit sendMsgSatusBar(msg); + + closePort(false); + } + else + emit sendMsgSatusBar(""); + + status = false; + break; + } + } + + if (shutdownState.get()) + { + return false; + } + + if (status) + { + if (resetState.get()) + { + QString msg(tr("Wait interrupted by user (startup)")); + err("%s", qPrintable(msg)); + emit addList(msg); + } + } + + if (result.contains(RESPONSE_ERROR)) + { + errorCount++; + // skip over errors + //status = false; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && list.at(i) != RESPONSE_OK) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + + if (resetState.get()) + { + // we have been told by the user to stop. + status = false; + } + + return status; +} + +/// T1 +/* ***************************************************************************** +/// May 13, 2014 + 1- frame1 : < 8c (3 axes), 0.845 (4 axes) -> $$==0 + received == "MPos:[....],WPos:[....]" + 2- frame2 : 0.8c1 or 0.8c2 (4 axes) -> $$==1 + received == "" + 3- frame2 : 0.8c (3 axes) -> $$==1 + received == "" + 4- frame3 : 0.9d (3 axes), 0.9d1 (4 axes) -> $$==1 + received == "" +*/ + +/// TODO : with 0.9g -> see Wiki +void GCode::parseCoordinates(const QString& received, bool aggressive) +{ + if (aggressive) + { + int ms = parseCoordTimer.elapsed(); + if (ms < 500) + return; + + parseCoordTimer.restart(); + } + + bool good = false ; + int captureCount ; + QString state; + QString prepend; + QString append; + QString preamble = "([a-zA-Z]+),MPos:"; + if (!doubleDollarFormat) + { + prepend = "\\["; + append = "\\]"; + preamble = "MPos:" ; + } + QString coordRegExp; + QRegExp rxStateMPos; + QRegExp rxWPos; +/// 1 axis + QString format1("(-*\\d+\\.\\d+)") ; + QString sep(","); + /// 3 axes + QString format3 = format1 + sep + format1 + sep + format1 ; + /// 4 axes + QString format4 = format3 + sep + format1 ; + QString format ; + int naxis ; + for (naxis = MAX_AXIS_COUNT; naxis >= DEFAULT_AXIS_COUNT; naxis--) { + if (!doubleDollarFormat) + captureCount = naxis ; + else + captureCount = naxis + 1 ; + + if (naxis == MAX_AXIS_COUNT ) + format = format4; + else + format = format3; + + coordRegExp = prepend + format + append ; + rxStateMPos = QRegExp(preamble + coordRegExp); + rxWPos = QRegExp(QString("WPos:") + coordRegExp); + good = rxStateMPos.indexIn(received, 0) != -1 + && rxStateMPos.captureCount() == captureCount + && rxWPos.indexIn(received, 0) != -1 + && rxWPos.captureCount() == naxis + ; + + // find naxis ... + if (good) + break; + } + if (good) { /// naxis contains number axis + if (numaxis <= DEFAULT_AXIS_COUNT) + { + if (naxis > DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options."); + emit addList(msg); + emit sendMsgSatusBar(msg); + } + } + else + { + if (naxis <= DEFAULT_AXIS_COUNT) + { + QString msg = tr("Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options."); + emit addList(msg); + emit sendMsgSatusBar(msg); + } + } + + numaxis = naxis; + QStringList list = rxStateMPos.capturedTexts(); + int index = 1; + + if (doubleDollarFormat) { + state = list.at(index++); + if (state == "Check") { + emit setLastState(state); + return; + } + } + lastState = state; + emit setLastState(state); + + machineCoord.x = list.at(index++).toFloat(); + machineCoord.y = list.at(index++).toFloat(); + machineCoord.z = list.at(index++).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + machineCoord.fourth = list.at(index++).toFloat(); + list = rxWPos.capturedTexts(); + workCoord.x = list.at(1).toFloat(); + workCoord.y = list.at(2).toFloat(); + workCoord.z = list.at(3).toFloat(); + if (numaxis == MAX_AXIS_COUNT) + workCoord.fourth = list.at(4).toFloat(); + /* + if (state != "Run") + workCoord.stoppedZ = true; + else + workCoord.stoppedZ = false; + */ + workCoord.stoppedZ = state != "Run" ; + workCoord.sliderZIndex = sliderZCount; + + if (doubleDollarFormat) + diag(qPrintable(tr("Decoded: State:%s")), qPrintable(state) ); + if (numaxis == DEFAULT_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f WPos: %f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, + workCoord.x, workCoord.y, workCoord.z + ); + else if (numaxis == MAX_AXIS_COUNT) + diag(qPrintable(tr("Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f\n")), + machineCoord.x, machineCoord.y, machineCoord.z, machineCoord.fourth, + workCoord.x, workCoord.y, workCoord.z, workCoord.fourth + ); + + if (workCoord.z > maxZ) + maxZ = workCoord.z; + +/// T4 3D + // if (posReqKind == POS_REQ) + emit updateCoordinates(machineCoord, workCoord); + // else { + // emit setLivePoint(QVector3D(workCoord.x, workCoord.y, workCoord.z)) ; + // } + // 2D + emit setLivePoint(workCoord.x, workCoord.y, controlParams.useMm, positionValid); + + // emit setLastState(state); + + + return; + } + // TODO fix to print + //if (!good /*&& received.indexOf("MPos:") != -1*/) + // err(qPrintable(tr("Error decoding position data! [%s]\n")), qPrintable(received)); + + lastState = ""; +} + +void GCode::sendStatusList(QStringList& listToSend) +{ + if (listToSend.size() > 1) + { + emit addListFull(listToSend); + } + else if (listToSend.size() == 1) + { + emit addList(listToSend.at(0)); + } +} + +// called once a second to capture any random strings that come from the controller +void GCode::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (port.isPortOpen()) + { + char tmp[BUF_SIZE + 1] = {0}; + QString result; + + for (int i = 0; i < 10 && !shutdownState.get() && !resetState.get(); i++) + { + int n = port.PollComport(tmp, BUF_SIZE); + if (n == 0) + break; + + tmp[n] = 0; + result.append(tmp); + diag(qPrintable(tr("GOT-TE:%s\n")), tmp); + } + + if (shutdownState.get()) + { + return; + } + + QStringList list = QString(result).split(port.getDetectedLineFeed()); + QStringList listToSend; + for (int i = 0; i < list.size(); i++) + { + if (list.at(i).length() > 0 && (list.at(i) != "ok" || (list.at(i) == "ok" && abortState.get()))) + listToSend.append(list.at(i)); + } + + sendStatusList(listToSend); + } +} +/// T3 +void GCode::sendFile(QString path, bool checkfile) +{ + addList(QString(tr("Sending file '%1'")).arg(path)); + + // send something to be sure the controller is ready + //sendGcodeLocal("", true, SHORT_WAIT_SEC); + + setProgress(0); + emit setQueuedCommands(0, false); + grblCmdErrors.clear(); + grblFilteredCmds.clear(); + errorCount = 0; + abortState.set(false); +/// T4 + pauseState.set(false); + + QFile file(path); + if (file.open(QFile::ReadOnly)) + { +/// T1 float -> int + int totalLineCount = 0; + + QTextStream code(&file); + while ((code.atEnd() == false)) + { + totalLineCount++; + code.readLine(); + } + if (totalLineCount == 0) + totalLineCount = 1; + + code.seek(0); + + // set here once so that it doesn't change in the middle of a file send + bool aggressive = controlParams.useAggressivePreload; + if (aggressive) + { + sendCount.clear(); + //if (sendCount.size() == 0) + //{ + // diag("DG Buffer 0 at start\n")); + //} + emit setQueuedCommands(sendCount.size(), true); + } + + sentI = 0; + rcvdI = 0; + emit resetTimer(true); +/// T4 + // parseCoordTimer.restart(); + parseCoordTimer.start(); + + int currLine = 0; + bool xyRateSet = false; +/// T1 + QString strline ; + do + { + strline = code.readLine(); +/// T3 + if (!checkfile) { + emit setVisCurrLine(currLine + 1); + } + + if (controlParams.filterFileCommands) + { + trimToEnd(strline, '('); + trimToEnd(strline, ';'); + trimToEnd(strline, '%'); + } + + strline = strline.trimmed(); + + if (strline.size() == 0) + {}//ignore comments + else + { + if (controlParams.filterFileCommands) + { + strline = strline.toUpper(); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline = removeUnsupportedCommands(strline); + } + + if (strline.size() != 0) + { + if (controlParams.reducePrecision) + { + strline = reducePrecision(strline); + } + + QString rateLimitMsg; + QStringList outputList; + if (controlParams.zRateLimit) + { + outputList = doZRateLimit(strline, rateLimitMsg, xyRateSet); + } + else + { + outputList.append(strline); + } +/// T4 + if (!checkfile) + emit setNumLine(QString::number(currLine + 1)); + + bool ret = false; + if (outputList.size() == 1) + { + ret = sendGcodeLocal(outputList.at(0), false, -1, aggressive, currLine + 1); + } + else + { + foreach (QString outputLine, outputList) + { + ret = sendGcodeLocal(outputLine, false, -1, aggressive, currLine + 1); + + if (!ret) + break; + } + } + + if (rateLimitMsg.size() > 0) + addList(rateLimitMsg); + + if (!ret) + { + abortState.set(true); + break; + } + } + } + + float percentComplete = (currLine * 100.0) / totalLineCount; + setProgress((int)percentComplete); +/// T3 + if (!checkfile) + positionUpdate(); +/// T4 here test if pause ... + if (pauseState.get() ) + { + gotoPause(); + } +/// end pause + if (!checkfile) + positionUpdate(); +/// <-- + currLine++; + + } while ((code.atEnd() == false) && (!abortState.get())); + + file.close(); + + if (aggressive) + { + int limitCount = 5000; + while (sendCount.size() > 0 && limitCount) + { + QString result; +/// T4 + waitForOk(result, controlParams.waitTime, false, false, false, aggressive, true); + SLEEP(100); + + if (shutdownState.get()) + return; + + if (abortState.get()) + break; + + limitCount--; + } + + if (!limitCount) + { + err(qPrintable(tr("Gave up waiting for OK\n"))); + } + } +/// T3 + if (!checkfile) + positionUpdate(); + + emit resetTimer(false); + + if (shutdownState.get()) + { + return; + } + + QString msg; + if (!abortState.get()) + { + setProgress(100); + if (errorCount > 0) + { + msg = QString(tr("Code sent successfully with %1 error(s):")).arg(QString::number(errorCount)); + emit sendMsgSatusBar(msg); + emit addList(msg); + + foreach(QString errItem, grblCmdErrors) + { + emit sendMsgSatusBar(errItem); + } + emit addListFull(grblCmdErrors); + } + else + { + msg = tr("Code sent successfully with no errors."); + emit sendMsgSatusBar(msg); + emit addList(msg); + } + + if (grblFilteredCmds.size() > 0) + { + msg = QString(tr("Filtered %1 commands:")).arg(QString::number(grblFilteredCmds.size())); + emit sendMsgSatusBar(msg); + emit addList(msg); + + foreach(QString errItem, grblFilteredCmds) + { + emit sendMsgSatusBar(errItem); + } + emit addListFull(grblFilteredCmds); + } + } + else + { + msg = tr("Process interrupted."); + emit sendMsgSatusBar(msg); + emit addList(msg); + } + } +/// Ta : TODO ... + /// pollPosWaitForIdle(true); + pollPosWaitForIdle(false); + + if (!resetState.get()) + { + emit stopSending(); + } + + emit setQueuedCommands(0, false); +} + +/// T4 +// calls : 'GCode::sendFile(..)':1, +void GCode::gotoPause() +{ + // QString oldstate = lastState; + // virtual state ! + // emit setLastState("Hold"); + QString msg(tr("Pause program Grbl ...")); + sendToPort(FEED_FOLD_COMMAND, msg) ; + msg = tr("Pause for sending 'Gcode' lines to 'Grbl'"); + msg += " ... '!'"; + emit sendMsgSatusBar(msg); + addList(msg); + + sendGcodeLocal(REQUEST_CURRENT_POS) ; +/// pause ... + while ( pauseState.get() ) + { + if (abortState.get()) break; + // if (resetState.get()) return; /// ? + }; +/// end pause + sendGcodeLocal(REQUEST_CURRENT_POS) ; + + // old state + // emit setLastState(oldstate); + msg = tr("Resume program Grbl ...") ; + sendToPort(CYCLE_START_COMMAND, msg) ; + msg = tr("Resume sending 'Gcode' lines to 'Grbl'"); + msg += "'~'"; + emit sendMsgSatusBar(msg); + addList(msg); +} + +void GCode::trimToEnd(QString& strline, QChar ch) +{ + int pos = strline.indexOf(ch); + if (pos != -1) + strline = strline.left(pos); +} + +QString GCode::removeUnsupportedCommands(QString line) +{ + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString tmp; + QString s; + QString following; + bool toEndOfLine = false; + foreach (s, components) + { + if (toEndOfLine) + { + QString msg(QString(tr("Removed unsupported command '%1' part of '%2'")).arg(s).arg(following)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + continue; + } + + if (s.at(0) == 'G') + { + float value = s.mid(1,-1).toFloat(); + if (isGCommandValid(value, toEndOfLine)) + tmp.append(s).append(" "); + else + { + if (toEndOfLine) + following = s; + QString msg(QString(tr("Removed unsupported G command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'M') + { + float value = s.mid(1,-1).toFloat(); + if (isMCommandValid(value)) + tmp.append(s).append(" "); + else + { + QString msg(QString(tr("Removed unsupported M command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + } + } + else if (s.at(0) == 'N') + { + // skip line numbers + } + else if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'Z' + || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C' + || s.at(0) == 'U' || s.at(0) == 'V' || s.at(0) == 'W' + || s.at(0) == 'I' || s.at(0) == 'J' || s.at(0) == 'K' + || s.at(0) == 'F' || s.at(0) == 'L' || s.at(0) == 'S') + { + tmp.append(s).append(" "); + } + else + { + QString msg(QString(tr("Removed unsupported command '%1'")).arg(s)); + warn("%s", qPrintable(msg)); + grblFilteredCmds.append(msg); + emit addList(msg); + tmp.append(s).append(" "); + } + } + + return tmp.trimmed(); +} + +QString GCode::reducePrecision(QString line) +{ + // first remove all spaces to determine what are line length is + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString result; + foreach(QString token, components) + { + result.append(token); + } + + if (result.length() == 0) + return line;// nothing to do + + if (!result.at(0).isLetter()) + return line;// leave as-is if not a command + + // find first comment and eliminate + int pos = result.indexOf('('); + if (pos >= 0) + result = result.left(pos); + // subtract 1 to account for linefeed sent with command later + int charsToRemove = result.length() - (controlParams.grblLineBufferLen - 1); + + if (charsToRemove > 0) + { + // ok need to do something with precision + // split apart based on letter + pos = 0; + components.clear(); + int i; + for (i = 1; i < result.length(); i++) + { + if (result.at(i).isLetter()) + { + components.append(result.mid(pos, i - pos)); + pos = i; + } + } + + if (pos == 0) + { + // we get here if only one command + components.append(result); + } + else + { + // add last item + components.append(result.mid(pos, i)); + } + + QList items; + foreach (QString tmp, components) + { + items.append(DecimalFilter(tmp)); + } + + int totalDecCount = 0; + int eligibleArgumentCount = 0; + int largestDecCount = 0; + for (int j = 0; j < items.size(); j++) + { + DecimalFilter& item = items[j]; + pos = item.token.indexOf('.'); + if ((item.token.at(1).isDigit() || item.token.at(1) == '-' || item.token.at(1) == '.') && pos >= 0) + { + // candidate to modify + // count number of decimal places + int decPlaceCount = 0; + for (i = pos + 1; i < item.token.length(); i++, decPlaceCount++) + { + if (!item.token.at(i).isDigit()) + break; + } + + // skip commands that have a single decimal place + if (decPlaceCount > 1) + { + item.decimals = decPlaceCount; + totalDecCount += decPlaceCount - 1;// leave at least the last decimal place + eligibleArgumentCount++; + if (decPlaceCount > largestDecCount) + largestDecCount = decPlaceCount; + } + } + } + + bool failRemoveSufficientDecimals = false; + if (totalDecCount < charsToRemove) + { + // remove as many as possible, then grbl will truncate + charsToRemove = totalDecCount; + failRemoveSufficientDecimals = true; + } + + if (eligibleArgumentCount > 0) + { + for (int k = largestDecCount; k > 1 && charsToRemove > 0; k--) + { + for (int j = 0; j < items.size() && charsToRemove > 0; j++) + { + DecimalFilter& item = items[j]; + if (item.decimals == k) + { + item.token.chop(1); + item.decimals--; + charsToRemove--; + } + } + } + + //chk.clear(); + //chk.append("CORRECTED:"); + result.clear(); + foreach (DecimalFilter item, items) + { + result.append(item.token); + + //chk.append("["); + //chk.append(item.token); + //chk.append("]"); + } + + err(qPrintable(tr("Unable to remove enough decimal places for command (will be truncated): %s")), qPrintable(line)); + + QString msg; + if (failRemoveSufficientDecimals) + msg = QString(tr("Error, insufficent reduction '%1'")).arg(result); + else + msg = QString(tr("Precision reduced '%1'")).arg(result); + + emit addList(msg); + emit sendMsgSatusBar(msg); + } + } + + return result; +} + +bool GCode::isGCommandValid(float value, bool& toEndOfLine) +{ + toEndOfLine = false; + // supported values obtained from https://github.com/grbl/grbl/wiki + const static float supported[] = + { + 0, 1, 2, 3, 4, + 10, 17, 18, 19, 20, 21, 28, 28.1, 30, 30.1, + 53, 54, 55, 56, 57, 58, 59, + 80, 90, 91, 92, 92.1, 93, 94 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } +/// T4 + G41, G42 + if (value == 41 || value == 42 || value == 43 || value == 44) + { + toEndOfLine = true; + } + return false; +} + +bool GCode::isMCommandValid(float value) +{ + // supported values obtained from https://github.com/grbl/grbl/wiki + + // NOTE: M2 and M30 are supported but they cause occasional grbl lockups + // and thus have been removed from the supported list. No harm is caused + // by their removal. + const static float supported[] = +/// T4 + M2, M30 (v0.8) + { + 0, 2, 3, 4, 5, 8, 9, 30 + }; + + int len = sizeof(supported) / sizeof(float); + for (int i = 0; i < len; i++) + { + if (value == supported[i]) + return true; + } + return false; +} +// calls : 'GCode::sendFile()':1, +QStringList GCode::doZRateLimit(QString inputLine, QString& msg, bool& xyRateSet) +{ + // i.e. + //G00 Z1 => G01 Z1 F100 + //G01 Z1 F260 => G01 Z1 F100 + //G01 Z1 F30 => G01 Z1 F30 + //G01 X1 Y1 Z1 F200 -> G01 X1 Y1 & G01 Z1 F100 + QStringList list; + QString line = inputLine.toUpper(); + + if (line.count("Z") > 0) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + bool foundFeed = false; + bool didLimit = false; + + // We need to build one or two command strings depending on input. + QString x, y, g, f; + + // First get all component parts + bool inLimit = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + g = s; + } + else if (s.at(0) == 'F') + { + f = s; + + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + inLimit = true; + } + else if (s.at(0) == 'X') + { + x = s; + } + else if (s.at(0) == 'Y') + { + y = s; + } + } + + // Determine whether we want to have one or two command lins + // 1 string: Have !G0 and F but not in limit + // 1 string: Have Z only + // 2 strings: All other conditions + QString line1; + QString line2; + if ((g != "G0" && f.size() > 0 && !inLimit) + || (x.size() == 0 && y.size() == 0)) + { + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value == 0) + line1.append("G1"); + else + line1.append(s); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s); + + foundFeed = true; + } + else + { + line1.append(s); + } + line1.append(" "); + } + } + else + { + // two lines + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 1) + line1.append("G1").append(" "); + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + } + else if (s.at(0) == 'F') + { + double value = s.mid(1,-1).toDouble(); + if (value > controlParams.zRateLimitAmount) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + else + line1.append(s).append(" "); + + line2.append(s).append(" "); + + foundFeed = true; + } + else if (s.at(0) == 'Z') + { + line1.append(s).append(" "); + } + else + { + line2.append(s).append(" "); + } + } + } + + if (!foundFeed) + { + line1.append("F").append(QString::number(controlParams.zRateLimitAmount)); + didLimit = true; + } + + line1 = line1.trimmed(); + line2 = line2.trimmed(); + + if (didLimit) + { + if (line2.size() == 0) + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2]")).arg(inputLine).arg(line1); + xyRateSet = true; + } + else + { + msg = QString(tr("Z-Rate Limit: [%1]=>[%2,%3]")).arg(inputLine).arg(line1).arg(line2); + line2.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + } + } + + list.append(line1); + if (line2.size() > 0) + list.append(line2); + return list; + } + else if (xyRateSet) + { + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + + bool addRateG = false; + bool addRateXY = false; + bool gotF = false; + foreach (s, components) + { + if (s.at(0) == 'G') + { + int value = s.mid(1,-1).toInt(); + if (value != 0) + { + addRateG = true; + } + } + else if (s.at(0) == 'F') + { + gotF = true; + } + else + if (s.at(0) == 'X' || s.at(0) == 'Y' || s.at(0) == 'A' || s.at(0) == 'B' || s.at(0) == 'C') + { + addRateXY = true; + } + } + + if (addRateG && addRateXY) + { + if (!gotF) + { + QString line = inputLine; + line.append(QString(" F").append(QString::number(controlParams.xyRateAmount))); + msg = QString(tr("XY-Rate Limit FIX: [%1]=>[%2]")).arg(inputLine).arg(line); + list.append(line); + } + else + { + list.append(inputLine); + } + + xyRateSet = false; + + return list; + } + } + + list.append(inputLine); + return list; + +} + +void GCode::gotoXYZFourth(QString line) +{ + bool queryPos = checkForGetPosStr(line); + if (!queryPos + && controlParams.usePositionRequest + && controlParams.positionRequestType == PREQ_ALWAYS) + pollPosWaitForIdle(false); + + if (sendGcodeLocal(line)) + { +/// T4 ?? + /* + line = line.toUpper(); + + bool moveDetected = false; + + QStringList list = line.split(QRegExp("[\\s]+")); + for (int i = 0; i < list.size(); i++) + { + QString item = getMoveAmountFromString("X", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Y", list.at(i)); + moveDetected = item.length() > 0; + + item = getMoveAmountFromString("Z", list.at(i)); + moveDetected = item.length() > 0 ; + if (numaxis == MAX_AXIS_COUNT) { + item = getMoveAmountFromString(QString(controlParams.fourthAxisName), list.at(i)); + moveDetected = item.length() > 0; + } + } + + if (!moveDetected) + { + //emit addList("No movement expected for command."); + } + */ + if (!queryPos) + pollPosWaitForIdle(false); + } + else + { + QString msg(QString(tr("Bad command: %1")).arg(line)); + warn("%s", qPrintable(msg)); + emit addList(msg); + } + // clear 'ui->comboCommand' + emit setCommandText(""); +} + +/* T4 +QString GCode::getMoveAmountFromString(QString prefix, QString item) +{ + int index = item.indexOf(prefix); + if (index != -1) + return item.mid(index + 1); + + return ""; +} +*/ + +void GCode::axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sZC) +{ + if (inv) + { + coord = (-coord); + } + + QString cmd = QString("G01 ").append(axis).append(QString::number(coord)); + + if (axis == 'Z') + { + cmd.append(" F").append(QString::number(controlParams.zJogRate)); + } +/// T4 mandatory with '0.9f' + else // X, Y, T + { + cmd.append(" F").append(QString::number(controlParams.xyRateAmount)); + } + + SendJog(cmd, absoluteAfterAxisAdj); + + if (axis == 'Z') + sliderZCount = sZC; + + emit adjustedAxis(); +} + +bool GCode::SendJog(QString cmd, bool absoluteAfterAxisAdj) +{ + pollPosWaitForIdle(false); + + // G91 = distance relative to previous + bool ret = sendGcodeLocal("G91\r"); + + bool result = ret && sendGcodeLocal(cmd.append("\r")); + + if (result) + { + pollPosWaitForIdle(false); + } + + if (absoluteAfterAxisAdj) + sendGcodeLocal("G90\r"); + + return result; +} + +// settings change calls here +// calls : 'MainWindow::MainWindow()':1, 'MainWindow::setSettingsOptionsUseMm()':1, +// 'MainWindow::setSettingsOptions()':1, +void GCode::setResponseWait(ControlParams controlParamsIn) +{ +//diag("GCode::setResponseWait(...) ..."); + bool oldMm = controlParams.useMm; + + controlParams = controlParamsIn; + + controlParams.useMm = oldMm; + + port.setCharSendDelayMs(controlParams.charSendDelayMs); + + if ((oldMm != controlParamsIn.useMm) && isPortOpen() && doubleDollarFormat) + { + if (controlParamsIn.useMm) + { + setConfigureMmMode(true); + } + else + { + setConfigureInchesMode(true); + } + } + + controlParams.useMm = controlParamsIn.useMm; + numaxis = controlParams.useFourAxis ? MAX_AXIS_COUNT : DEFAULT_AXIS_COUNT; + + // setUnitsTypeDisplay(controlParams.useMm); + emit setUnitMmAll(controlParams.useMm); +} + +int GCode::getSettingsItemCount() +{ + return settingsItemCount.get(); +} + +// 0.8c and above only! +void GCode::checkAndSetCorrectMeasurementUnits() +{ +/// T4 + // sendGcodeLocal(REQUEST_PARSER_STATE_V08c, false); // "$G" + sendGcodeLocal(REQUEST_PARSER_STATE_V$$, false); // "$G" + if (incorrectMeasurementUnits) + { + if (controlParams.useMm) + { + // emit addList(tr("Options specify use mm but Grbl parser set for inches. Fixing.")); + setConfigureMmMode(true); + } + else + { + // emit addList(tr("Options specify use inches but Grbl parser set for mm. Fixing.") ); + setConfigureInchesMode(true); + } + incorrectMeasurementUnits = false;// hope this is ok to do here + // positionUpdate(true); // ? + } + else + { + // sendGcodeLocal(SETTINGS_COMMAND_V08c); // "$$" + sendGcodeLocal(SETTINGS_COMMAND_V$$); + if (incorrectLcdDisplayUnits) + { + if (controlParams.useMm) + { + // emit addList(tr("Options specify use mm but Grbl reporting set for inches. Fixing.")); + setConfigureMmMode(false); + } + else + { + // emit addList(tr("Options specify use inches but Grbl reporting set for mm. Fixing.")); + setConfigureInchesMode(false); + } + } + incorrectLcdDisplayUnits = false; + } +} + +void GCode::setOldFormatMeasurementUnitControl() +{ + if (controlParams.useMm) + sendGcodeLocal("G21"); + else + sendGcodeLocal("G20"); +} + +// calls : 'GCode::setResponseWait()';1, +// 'GCode::checkAndSetCorrectMeasurementUnits()':2, +void GCode::setConfigureMmMode(bool setGrblUnits) +{ + QString msg ("=> " + tr("GCV use 'mm' but Grbl parser set for 'inches'") + "..."); + QString lastmsg ("<= " + tr("Correction Grbl ended.")); + emit addList(msg); + // emit sendMsgSatusBar(msg); +/// T4 // sendGcodeLocal("$13=0"); + QString val = getNumGrblUnit(); + sendGcodeLocal("$" + val + "=0"); + if (setGrblUnits) + sendGcodeLocal("G21"); + positionUpdate(true); + + emit addList(lastmsg); +} + +// calls : 'GCode::setResponseWait()';1, +// 'GCode::checkAndSetCorrectMeasurementUnits()':2, +void GCode::setConfigureInchesMode(bool setGrblUnits) +{ + QString msg ("=> " + tr("GCV use 'inches' but Grbl parser set for 'mm'") + "..."); + QString lastmsg ("<= " + tr("Correction Grbl ended.")); + emit addList(msg); + // emit sendMsgSatusBar(msg); +/// T4 // sendGcodeLocal("$13=1"); + QString val = getNumGrblUnit(); + sendGcodeLocal("$" + val + "=1"); + if (setGrblUnits) + sendGcodeLocal("G20"); + positionUpdate(true); + + emit addList(lastmsg); +} + +void GCode::clearToHome() +{ + maxZ = 0; + motionOccurred = false; +} + +int GCode:: getNumaxis() +{ + return numaxis; +} + +GCode::PosReqStatus GCode::positionUpdate(bool forceIfEnabled /* = false */) +{ + if (controlParams.usePositionRequest) + { + if (forceIfEnabled) + { + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + int ms = pollPosTimer.elapsed(); + if (ms >= controlParams.postionRequestTimeMilliSec) + { + pollPosTimer.restart(); + return sendGcodeLocal(REQUEST_CURRENT_POS) ? POS_REQ_RESULT_OK : POS_REQ_RESULT_ERROR; + } + else + { + return POS_REQ_RESULT_TIMER_SKIP; + } + } + } + return POS_REQ_RESULT_UNAVAILABLE; +} + +bool GCode::checkForGetPosStr(QString& line) +{ + return (!line.compare(REQUEST_CURRENT_POS) + || (line.startsWith(REQUEST_CURRENT_POS) && line.endsWith('\r') && line.length() == 2)); +} + +void GCode::setLivenessState(bool valid) +{ + positionValid = valid; + emit setVisualLivenessCurrPos(valid); + emit setLcdState(valid); +} + +// slot +// calls : 'MainWindow::begin()':1, 'MainWindow::updateSettingsFromOptionDlg()':1 +void GCode::setPosReqKind(int posreqkind) +{ + posReqKind = posreqkind; +} + +/// T4 : used by 'sendFile(...)' +// calls: 'GCode::sendGcode()':1, 'GCode::sendFile()':2 +bool GCode::sendToPort(const char *buf, QString txt) +{ + if (!port.SendBuf(buf, 1)) + { + QString msg = tr("Sending to port failed"); + err("%s", qPrintable(msg)); + emit addList(msg); + emit sendMsgSatusBar(msg); + return false; + } + else + diag("SENDING: '%c' %s", buf[0], qPrintable(txt)); + + return true; +} + diff --git a/GCV-3.6.1-T4/src/gcode.h b/GCV-3.6.1-T4/src/gcode.h new file mode 100644 index 0000000..6ee758b --- /dev/null +++ b/GCV-3.6.1-T4/src/gcode.h @@ -0,0 +1,230 @@ +/**************************************************************** + * gcode.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GCODE_H +#define GCODE_H + +#include "log4qtdef.h" + +#include +#include +#include +#include +#include "definitions.h" +#include "rs232.h" +#include "coord3d.h" +#include "controlparams.h" + +#define BUF_SIZE 300 + +#define RESPONSE_OK "ok" +#define RESPONSE_ERROR "error" + +// as defined in the grbl project on github... +#define GRBL_RX_BUFFER_SIZE 128 + +#define CTRL_X '\x18' + +#define DEFAULT_AXIS_COUNT 3 +#define MAX_AXIS_COUNT 4 + +class CmdResponse +{ +public: + CmdResponse(const char *buf, int c, int l) : cmd(buf), count(c), line(l) + { + waitForMe = false; + if (buf[0] == 'M') + { + int value = cmd.mid(1,-1).toInt(); + if (value == 9) + waitForMe = true; + } + } +public: + QString cmd; + int count; + int line; + bool waitForMe; +}; + +class DecimalFilter +{ +public: + DecimalFilter(QString t) : token(t), decimals(0) {} +public: + QString token; + int decimals; +}; + +class GCode : public QObject +{ + Q_OBJECT + +public: + GCode(); +/// T4 + void setPause(bool); + void setAbort(); + void setReset(); + void setShutdown(); + int getSettingsItemCount(); + int getNumaxis(); + + static void trimToEnd(QString& strline, QChar); + +signals: + void addList(QString line); + void addListFull(QStringList list); + void addListOut(QString line); + void sendMsgSatusBar(QString msg); + void stopSending(); + void portIsClosed(bool reopen); + void portIsOpen(bool sendCode); + void setCommandText(QString value); + void adjustedAxis(); + void gcodeResult(int id, QString result); + void setProgress(int); + void setQueuedCommands(int, bool); + void resetTimer(bool timeIt); + void enableGrblDialogButton(); + void updateCoordinates(Coord3D maposReqKindchineCoord, Coord3D workCoord); + void setLastState(QString state); + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); +/// T4 + void setLivePoint(QVector3D); + void setNumLine(QString); + + void setVisCurrLine(int currLine); + void setLcdState(bool valid); + void setVisualLivenessCurrPos(bool isLiveCP); +/// T2 + void setVersionGrbl(QString versionGrbl ); +/// T3 + void setLinesFile(QString nbline, bool check); +/// T4 + void setUnitMmAll(bool usemm); + + void endHomeAxis(); + +public slots: + void openPort(QString commPortStr, QString baudRate); + void closePort(bool reopen); + void sendGcode(QString line); + void sendGcodeAndGetResult(int id, QString line); +/// T3 + void sendFile(QString path, bool checkfile) ; + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void grblSetHome(); +/// T4 + void sendGrblHelp(); + void sendGrblParameters() ; + void sendGrblParserState(); + void sendGrblBuildInfo(); + void sendGrblStartupBlocks(); + void sendGrblCheck(bool); + void sendGrblUnlock(); + void sendGrblHomingCycle(); + void sendGrblCycleStart(); + void sendGrblFeedHold() ; + void sendGrblStatus(); + void sendGrblReset(); +/// T3 + void setPosReqKind(int); + + void goToHome(); + void goToHomeAxis(char axis); + + QString removeUnsupportedCommands(QString line); + +protected: + void timerEvent(QTimerEvent *event); + +private: + enum PosReqStatus + { + POS_REQ_RESULT_OK, + POS_REQ_RESULT_ERROR, + POS_REQ_RESULT_TIMER_SKIP, + POS_REQ_RESULT_UNAVAILABLE + }; +private: + bool sendGcodeLocal(QString line, bool recordResponseOnFail = false, int waitSec = -1, bool aggressive = false, int currLine = 0); +/// T4 + bool waitForOk(QString& result, int waitCount, bool sentReqForLocation, + bool sentRequestForSettings, bool sentReqForParserState, + bool aggressive, bool finalize); + bool waitForStartupBanner(QString& result, int waitSec, bool failOnNoFound); + bool sendGcodeInternal(QString line, QString& result, bool recordResponseOnFail, int waitSec, bool aggressive, int currLine = 0); + QString reducePrecision(QString line); + bool isGCommandValid(float value, bool& toEndOfLine); + bool isMCommandValid(float value); + bool isPortOpen(); + QString getMoveAmountFromString(QString prefix, QString item); + bool SendJog(QString strline, bool absoluteAfterAxisAdj); + void parseCoordinates(const QString& received, bool aggressive); + void pollPosWaitForIdle(bool checkMeasurementUnits); + void checkAndSetCorrectMeasurementUnits(); + void setOldFormatMeasurementUnitControl(); + void setConfigureMmMode(bool setGrblUnits); + void setConfigureInchesMode(bool setGrblUnits); + QStringList doZRateLimit(QString strline, QString& msg, bool& xyRateSet); + void sendStatusList(QStringList& listToSend); + void clearToHome(); + bool checkGrbl(const QString& result); + PosReqStatus positionUpdate(bool forceIfEnabled = false); + bool checkForGetPosStr(QString& line); + void setLivenessState(bool valid); +/// T4 + QString getNumGrblUnit(); + bool sendToPort(const char *buf, QString txt=QString()); + + void gotoPause(); + +private: + RS232 port; + AtomicIntBool abortState; + AtomicIntBool resetState; + AtomicIntBool shutdownState; +/// T4 + AtomicIntBool pauseState; + + ControlParams controlParams; + int errorCount; + QString currComPort; + bool doubleDollarFormat; + AtomicIntBool settingsItemCount; + QString lastState; + bool incorrectMeasurementUnits; + bool incorrectLcdDisplayUnits; + Coord3D machineCoord, workCoord; + Coord3D machineCoordLastIdlePos, workCoordLastIdlePos; + double maxZ; + QList sendCount; + QTime parseCoordTimer; + bool motionOccurred; + int sliderZCount; + QStringList grblCmdErrors; + QStringList grblFilteredCmds; + QTime pollPosTimer; + bool positionValid; + + int sentI; + int rcvdI; + int numaxis; +/// T3 + bool checkState; +/// T4 + int posReqKind; + QString versionGrbl; +}; + +#endif // GCODE_H diff --git a/GCV-3.6.1-T4/src/grbl.ico b/GCV-3.6.1-T4/src/grbl.ico new file mode 100644 index 0000000..d34802a Binary files /dev/null and b/GCV-3.6.1-T4/src/grbl.ico differ diff --git a/GCV-3.6.1-T4/src/grbl.rc b/GCV-3.6.1-T4/src/grbl.rc new file mode 100644 index 0000000..14ed995 --- /dev/null +++ b/GCV-3.6.1-T4/src/grbl.rc @@ -0,0 +1 @@ +IDI_ICON_GRBL ICON DISCARDABLE "grbl.ico" \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/grbldialog.cpp b/GCV-3.6.1-T4/src/grbldialog.cpp new file mode 100644 index 0000000..ff5824d --- /dev/null +++ b/GCV-3.6.1-T4/src/grbldialog.cpp @@ -0,0 +1,170 @@ +/**************************************************************** + * grbldialog.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "grbldialog.h" +#include "ui_grbldialog.h" + +GrblDialog::GrblDialog(QWidget *parent, GCode *gc) : + QDialog(parent), + gcode(gc), + ui(new Ui::GrblDialog), + tableRowCount(0) +{ + ui->setupUi(this); + connect(ui->btnCancel,SIGNAL(clicked()),this,SLOT(Cancel())); + connect(ui->btnOk,SIGNAL(clicked()),this,SLOT(Ok())); + connect(this, SIGNAL(sendGcodeAndGetResult(int, QString)), gcode, SLOT(sendGcodeAndGetResult(int, QString))); + connect(gcode, SIGNAL(gcodeResult(int, QString)), this, SLOT(gcodeResult(int, QString))); + + ui->btnCancel->setEnabled(false); + ui->btnOk->setEnabled(false); + + QStringList labels; +/// T4 + labels << tr("Rank"); + labels << tr("Value") << tr("Description"); + ui->table->setHorizontalHeaderLabels(labels); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + ui->table->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); +#else + ui->table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); +#endif + ui->table->verticalHeader()->hide(); + ui->table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + ui->table->setShowGrid(true); +} + +GrblDialog::~GrblDialog() +{ + delete ui; +} + +void GrblDialog::getSettings() +{ +/// T4 0.8a -> 0.8c !!! + emit sendGcodeAndGetResult(GDLG_CMD_ID_GET, SETTINGS_COMMAND_V$$); +} + +void GrblDialog::gcodeResult(int id, QString result) +{ + switch (id) + { + case GDLG_CMD_ID_GET: + { + originalValues.clear(); + changeFlags.clear(); + + if (result.size() > 0) + { + /// #define REGEXP_SETTINGS_LINE "(\\d+)\\s*=\\s*([\\w\\.]+)\\s*\\(([^\\)]*)\\)" + QRegExp rx(QString("\\$") + REGEXP_SETTINGS_LINE); + int pos = 0; +/// T4 + QStringList fieldRank; + QStringList fieldValues; + QStringList descriptions; + while ((pos = rx.indexIn(result, pos)) != -1) + { + int matched = rx.matchedLength(); + //QString extracted = received.mid(pos, matched); + pos += matched; + + if (rx.captureCount() > 0) + { + QStringList list = rx.capturedTexts(); + if (list.size() == 4) + { +/// T4 + fieldRank.append(list.at(1)); + fieldValues.append(list.at(2)); + descriptions.append(list.at(3)); + } + } + } + + tableRowCount = fieldValues.size() ; + ui->table->setRowCount(0); + /// 2 -> 3 + ui->table->setColumnCount(3); + + int i; + for (i = 0; i < tableRowCount; i++) + { + ui->table->insertRow(i); + + QTableWidgetItem *descWidget0 = new QTableWidgetItem(fieldRank.at(i)); + descWidget0->setFlags(Qt::NoItemFlags); + ui->table->setItem(i, 0, descWidget0); + + ui->table->setItem(i, 1, new QTableWidgetItem(fieldValues.at(i))); + + QTableWidgetItem *descWidget2 = new QTableWidgetItem(descriptions.at(i)); + descWidget2->setFlags(Qt::NoItemFlags); + + ui->table->setItem(i, 2, descWidget2); + + ui->table->item(i, 0)->setFont(QFont("Tahoma",10,-1,false)); + ui->table->item(i, 1)->setFont(QFont("Tahoma",10,87,false)); + ui->table->item(i, 2)->setFont(QFont("Tahoma",10,-1,false)); + + originalValues.append(fieldValues.at(i)); + changeFlags.append(false); + } + + ui->table->resizeColumnsToContents(); + int colWidthValues = ui->table->columnWidth(1); + ui->table->setColumnWidth(0, colWidthValues + 10); + + connect(ui->table,SIGNAL(cellChanged(int,int)),this,SLOT(changeValues(int,int))); + } + else + { + ui->table->setRowCount(0); + ui->table->setColumnCount(3); + } + ui->btnCancel->setEnabled(true); + ui->btnOk->setEnabled(true); + break; + } + case GDLG_CMD_ID_SET: + break; + } +} + +void GrblDialog::Cancel() +{ + this->close(); +} + +void GrblDialog::changeValues(int row, int col) +{ + Q_UNUSED(col); + + if ((ui->table->item(row,1)->text() != originalValues.at(row)) + && ui->table->item(row,1)->text().length() > 0) + { + changeFlags.replace(row, true); + } +} + +void GrblDialog::Ok() +{ + for(int i = 0; i < tableRowCount; i++) + { + if (changeFlags.at(i) == true) + { + QString strline = "$"; + strline.append(ui->table->item(i,0)->text()); + strline.append("=").append(ui->table->item(i,1)->text()).append('\r'); + emit sendGcodeAndGetResult(GDLG_CMD_ID_SET, strline); + } + } + this->close(); +} + diff --git a/GCV-3.6.1-T4/src/grbldialog.h b/GCV-3.6.1-T4/src/grbldialog.h new file mode 100644 index 0000000..5a194cf --- /dev/null +++ b/GCV-3.6.1-T4/src/grbldialog.h @@ -0,0 +1,63 @@ +/**************************************************************** + * grbldialog.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef GRBLDIALOG_H +#define GRBLDIALOG_H + +#include +#include +#include +#include +#include +#include "definitions.h" +#include "mainwindow.h" +#include "gcode.h" + +namespace Ui { +class GrblDialog; +} + +#define GDLG_CMD_ID_GET 1 +#define GDLG_CMD_ID_SET 2 + + +class GrblDialog : public QDialog +{ + Q_OBJECT + +public: + explicit GrblDialog(QWidget *parent, GCode *gcode); + ~GrblDialog(); + + //variables + GCode *gcode; + + //methods + void getSettings(); + +signals: + void sendGcodeAndGetResult(int id, QString cmd); + +public slots: + //buttons + void Ok(); + void Cancel(); + //Column Widget + void changeValues(int row, int col); + void gcodeResult(int id, QString result); + +private: + Ui::GrblDialog *ui; + QStringList originalValues; + QList changeFlags; + int tableRowCount; + +}; + +#endif // GRBLDIALOG_H diff --git a/GCV-3.6.1-T4/src/images.rcc b/GCV-3.6.1-T4/src/images.rcc new file mode 100644 index 0000000..e5149ba --- /dev/null +++ b/GCV-3.6.1-T4/src/images.rcc @@ -0,0 +1,157 @@ +/**************************************************************************** +** Resource object code +** +** Created: Fri 10. Feb 22:39:40 2012 +** by: The Resource Compiler for Qt version 4.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/down.gif + 0x0,0x0,0x0,0xbe, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xc0,0xc0,0xc0,0x99,0x99,0x99,0x40,0x40,0x40,0xe0,0xe0, + 0xe0,0x10,0x10,0x10,0x80,0x80,0x80,0xb0,0xb0,0xb0,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6b, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x95,0x2,0x9c, + 0x68,0xaa,0xae,0xa8,0x72,0x1d,0x6c,0xcc,0x1e,0x18,0x21,0xdf,0x28,0x91,0x15,0xb8, + 0x5c,0x68,0x6,0x58,0x4f,0x75,0x30,0x6c,0x6c,0xc3,0x94,0x8e,0xc3,0x4b,0x2,0x7e, + 0x1d,0x83,0x13,0x60,0xf4,0x20,0x92,0x88,0xd0,0xa2,0xb7,0x10,0x31,0x7a,0x8c,0xd1, + 0x55,0x96,0x25,0x9,0x62,0x2,0x92,0x64,0x10,0x1b,0xa8,0x25,0x8d,0x55,0xe3,0x3d, + 0x39,0xa3,0xd2,0xf4,0x75,0xca,0x9d,0x97,0x4,0x4e,0x1,0x7d,0x14,0x7,0x34,0x82, + 0x13,0x9,0x9,0x86,0x8a,0x8b,0x8c,0x8d,0x8e,0x8c,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/right.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xbb,0x2a,0x86,0x2b,0x4b,0xc0, + 0xe1,0xcc,0x2d,0xa0,0x17,0x31,0x9e,0xea,0xba,0x3,0xc1,0x87,0x2,0x2,0x79,0xc4, + 0x92,0xd1,0x88,0x48,0x8e,0x96,0xc6,0x5,0xc3,0x9,0x5d,0x36,0x89,0xd5,0xe5,0x40, + 0xe0,0xcb,0x42,0x23,0x3d,0x97,0x17,0xba,0x95,0x8d,0xab,0x81,0xb0,0xea,0x5c,0x3d, + 0x24,0x58,0x6c,0xa8,0x1b,0x1e,0x7,0x6,0xc4,0xf5,0x32,0x9e,0x1d,0xc1,0xb1,0xf5, + 0x33,0x67,0xf,0x49,0x5e,0x52,0x54,0x55,0x83,0x4e,0x34,0x4b,0x48,0x8a,0x8b,0x41, + 0x43,0x8e,0x22,0x47,0x6a,0x8e,0x35,0x37,0x92,0x24,0xa,0x99,0x9c,0x9d,0x9e,0x32, + 0x21,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/up.gif + 0x0,0x0,0x0,0xbd, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xb3,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0x20,0x20,0x20,0xbf,0xbf,0xbf,0x99,0x99,0x99,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x80,0x80,0x80,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x70,0x70,0x70,0x99,0x99,0x99,0xff,0xff,0xff,0x21,0xf9,0x4,0x5, + 0x14,0x0,0xf,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x4,0x6a, + 0xf0,0xc9,0x49,0xab,0xbd,0x38,0xeb,0xcd,0xbb,0xff,0x60,0x28,0x8e,0x61,0x92,0x90, + 0x99,0x71,0x1c,0x6,0x7a,0x5,0x0,0x10,0xb8,0xd5,0x10,0xc7,0x3,0x2d,0x19,0xc2, + 0xd,0x8,0x2d,0x5a,0xc3,0x17,0x6b,0xd0,0x6c,0x44,0x9c,0xab,0x97,0xfc,0xa1,0x10, + 0xcd,0x1b,0x62,0xc4,0x88,0xfa,0x18,0xa2,0x85,0xf5,0xb6,0x8,0x41,0xb7,0xd2,0x8f, + 0x1,0x4c,0xc,0x72,0xa,0x64,0x5f,0xa1,0x43,0x48,0x13,0x9,0x1b,0x95,0xdb,0xc7, + 0xd2,0xa0,0xe7,0xea,0x4c,0x1b,0xff,0xbe,0xc8,0xf9,0x74,0x66,0x13,0xa,0x80,0x49, + 0xa,0x3a,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x16,0x11,0x0,0x3b, + // C:/Documents and Settings/kosme/GrblHoming/Homer/HomerGUI/img/left.gif + 0x0,0x0,0x0,0xf4, + 0x47, + 0x49,0x46,0x38,0x39,0x61,0x20,0x0,0x20,0x0,0xc4,0x0,0x0,0x0,0x0,0x0,0x66, + 0x66,0x66,0xbf,0xbf,0xbf,0x20,0x20,0x20,0x8f,0x8f,0x8f,0x40,0x40,0x40,0xdf,0xdf, + 0xdf,0x10,0x10,0x10,0x7f,0x7f,0x7f,0xaf,0xaf,0xaf,0x50,0x50,0x50,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0x66,0x66,0x66,0x99,0x99,0x99,0x80,0x80,0x80,0x99,0x99,0x99,0x70, + 0x70,0x70,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0xf9,0x4,0x5, + 0x14,0x0,0x12,0x0,0x2c,0x0,0x0,0x0,0x0,0x20,0x0,0x20,0x0,0x0,0x5,0x71, + 0xa0,0x24,0x8e,0x64,0x69,0x9e,0x68,0xaa,0xae,0x6c,0xeb,0xbe,0x86,0xf2,0xba,0xce, + 0x1,0xcc,0xab,0x51,0x0,0x3c,0x9e,0x12,0x36,0xde,0xcd,0x57,0xd2,0x9,0x85,0x44, + 0x12,0xe2,0x78,0x4c,0x4a,0x18,0xb,0x66,0x93,0xb8,0x94,0x4e,0x67,0x82,0x81,0x95, + 0x39,0x33,0x44,0xb6,0xd2,0x57,0x16,0x1c,0x66,0x19,0x2,0x64,0x2b,0x2b,0x11,0x4c, + 0x73,0x57,0x6c,0x77,0x99,0x85,0x96,0x23,0x5d,0x63,0x3b,0xee,0x2b,0xf7,0xe5,0xc9, + 0x49,0xf,0x69,0x4e,0x50,0x60,0x4e,0x22,0x82,0x6a,0x87,0x12,0x46,0x6f,0x8b,0x12, + 0x40,0x57,0x8f,0x8d,0x43,0x8f,0x23,0x35,0x95,0x96,0x23,0x32,0x9a,0x9d,0x9e,0x49, + 0x21,0x0,0x3b, + +}; + +static const unsigned char qt_resource_name[] = { + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // down.gif + 0x0,0x8, + 0x6,0xe1,0x40,0x96, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // right.gif + 0x0,0x9, + 0xd,0xf7,0xbc,0x16, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // up.gif + 0x0,0x6, + 0x7,0xc3,0x4d,0xf6, + 0x0,0x75, + 0x0,0x70,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + // left.gif + 0x0,0x8, + 0xb,0xd7,0x43,0xb6, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/img + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2, + // :/img/down.gif + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/up.gif + 0x0,0x0,0x0,0x3a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xba, + // :/img/left.gif + 0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0x7b, + // :/img/right.gif + 0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc2, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources)) + +int QT_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources)) + diff --git a/GCV-3.6.1-T4/src/img/Thumbs.db b/GCV-3.6.1-T4/src/img/Thumbs.db new file mode 100644 index 0000000..7d8e59e Binary files /dev/null and b/GCV-3.6.1-T4/src/img/Thumbs.db differ diff --git a/GCV-3.6.1-T4/src/img/backview.png b/GCV-3.6.1-T4/src/img/backview.png new file mode 100644 index 0000000..348d9f3 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/backview.png differ diff --git a/GCV-3.6.1-T4/src/img/bottomview.png b/GCV-3.6.1-T4/src/img/bottomview.png new file mode 100644 index 0000000..b479145 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/bottomview.png differ diff --git a/GCV-3.6.1-T4/src/img/down.png b/GCV-3.6.1-T4/src/img/down.png new file mode 100644 index 0000000..f157397 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/down.png differ diff --git a/GCV-3.6.1-T4/src/img/frontview.png b/GCV-3.6.1-T4/src/img/frontview.png new file mode 100644 index 0000000..5edd006 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/frontview.png differ diff --git a/GCV-3.6.1-T4/src/img/gaia2.jpg b/GCV-3.6.1-T4/src/img/gaia2.jpg new file mode 100644 index 0000000..4729642 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/gaia2.jpg differ diff --git a/GCV-3.6.1-T4/src/img/home.png b/GCV-3.6.1-T4/src/img/home.png new file mode 100644 index 0000000..607e8d5 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/home.png differ diff --git a/GCV-3.6.1-T4/src/img/homeall.png b/GCV-3.6.1-T4/src/img/homeall.png new file mode 100644 index 0000000..78d1cb8 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/homeall.png differ diff --git a/GCV-3.6.1-T4/src/img/isoview1.png b/GCV-3.6.1-T4/src/img/isoview1.png new file mode 100644 index 0000000..dcaa14b Binary files /dev/null and b/GCV-3.6.1-T4/src/img/isoview1.png differ diff --git a/GCV-3.6.1-T4/src/img/isoview2.png b/GCV-3.6.1-T4/src/img/isoview2.png new file mode 100644 index 0000000..50590cb Binary files /dev/null and b/GCV-3.6.1-T4/src/img/isoview2.png differ diff --git a/GCV-3.6.1-T4/src/img/isoview3.png b/GCV-3.6.1-T4/src/img/isoview3.png new file mode 100644 index 0000000..e943999 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/isoview3.png differ diff --git a/GCV-3.6.1-T4/src/img/isoview4.png b/GCV-3.6.1-T4/src/img/isoview4.png new file mode 100644 index 0000000..00f2f49 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/isoview4.png differ diff --git a/GCV-3.6.1-T4/src/img/left.png b/GCV-3.6.1-T4/src/img/left.png new file mode 100644 index 0000000..7562000 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/left.png differ diff --git a/GCV-3.6.1-T4/src/img/leftview.png b/GCV-3.6.1-T4/src/img/leftview.png new file mode 100644 index 0000000..e1239aa Binary files /dev/null and b/GCV-3.6.1-T4/src/img/leftview.png differ diff --git a/GCV-3.6.1-T4/src/img/logotiny.png b/GCV-3.6.1-T4/src/img/logotiny.png new file mode 100644 index 0000000..4cade12 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/logotiny.png differ diff --git a/GCV-3.6.1-T4/src/img/right.png b/GCV-3.6.1-T4/src/img/right.png new file mode 100644 index 0000000..858b59f Binary files /dev/null and b/GCV-3.6.1-T4/src/img/right.png differ diff --git a/GCV-3.6.1-T4/src/img/rightview.png b/GCV-3.6.1-T4/src/img/rightview.png new file mode 100644 index 0000000..c66e3c5 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/rightview.png differ diff --git a/GCV-3.6.1-T4/src/img/topview.png b/GCV-3.6.1-T4/src/img/topview.png new file mode 100644 index 0000000..f479f20 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/topview.png differ diff --git a/GCV-3.6.1-T4/src/img/up.png b/GCV-3.6.1-T4/src/img/up.png new file mode 100644 index 0000000..e9b3dbb Binary files /dev/null and b/GCV-3.6.1-T4/src/img/up.png differ diff --git a/GCV-3.6.1-T4/src/img/upvector.png b/GCV-3.6.1-T4/src/img/upvector.png new file mode 100644 index 0000000..758b5e1 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/upvector.png differ diff --git a/GCV-3.6.1-T4/src/img/zapmaker-logo-130.png b/GCV-3.6.1-T4/src/img/zapmaker-logo-130.png new file mode 100644 index 0000000..5963823 Binary files /dev/null and b/GCV-3.6.1-T4/src/img/zapmaker-logo-130.png differ diff --git a/GCV-3.6.1-T4/src/itemtobase.cpp b/GCV-3.6.1-T4/src/itemtobase.cpp new file mode 100644 index 0000000..114668d --- /dev/null +++ b/GCV-3.6.1-T4/src/itemtobase.cpp @@ -0,0 +1,28 @@ +#include "itemtobase.h" + +ItemToBase::ItemToBase(int index1) + : scale(1), height(100), offsetx(50), offsety(50), index(index1) +{ +} + +ItemToBase::~ItemToBase() +{ +} + +void ItemToBase::setParams(double scale1, double height1, double offsetx1, double offsety1) +{ + scale = scale1; + height = height1; + offsetx = offsetx1; + offsety = offsety1; +} + +double ItemToBase::screenX(double fx) +{ + return (fx * scale) + offsetx; +} + +double ItemToBase::screenY(double fy) +{ + return height - ((fy * scale) + offsety); +} diff --git a/GCV-3.6.1-T4/src/itemtobase.h b/GCV-3.6.1-T4/src/itemtobase.h new file mode 100644 index 0000000..bacd872 --- /dev/null +++ b/GCV-3.6.1-T4/src/itemtobase.h @@ -0,0 +1,37 @@ +#ifndef ITEMTOBASE_H +#define ITEMTOBASE_H +#include +#include "stdio.h" +#include "positem.h" + +class ItemToBase +{ +public: + ItemToBase(int index); + virtual ~ItemToBase() ; + + virtual void moveToFirst(QPainterPath& path) = 0; + virtual void addToPath(QPainterPath& path) = 0; + virtual PosItem computeExtents() = 0; + + virtual double getXScr() = 0; + virtual double getYScr() = 0; + virtual double getXRaw() = 0; + virtual double getYRaw() = 0; + + void setParams(double scale, double height, double offsetx, double offsety); + + double screenX(double x); + double screenY(double y); + + int getIndex() { return index; } + +protected: + double scale; + double height; + double offsetx; + double offsety; + int index; +}; + +#endif // ITEMTOBASE_H diff --git a/GCV-3.6.1-T4/src/lineitem.cpp b/GCV-3.6.1-T4/src/lineitem.cpp new file mode 100644 index 0000000..e440cfb --- /dev/null +++ b/GCV-3.6.1-T4/src/lineitem.cpp @@ -0,0 +1,61 @@ +#include "lineitem.h" + +LineItem::LineItem(double x1, double y1, int index1) + : ItemToBase(index1), x(x1), y(y1) +{ +} + +LineItem::LineItem(double x1, double y1, bool stretchX1, double length1) +: ItemToBase(0), x(x1), y(y1), stretchX(stretchX1), length(length1) +{ +} + +PosItem LineItem::computeExtents() +{ + PosItem curr(x, y, x, y); + return curr; +} + +void LineItem::addToPath(QPainterPath& path) +{ + path.lineTo(screenX(x), screenY(y)); +} + +void LineItem::moveToFirst(QPainterPath& path) +{ + path.moveTo(screenX(x), screenY(y)); +} + +double LineItem::getXScr() +{ + return screenX(x); +} + +double LineItem::getYScr() +{ + return screenY(y); +} + +double LineItem::getXRaw() +{ + return x; +} + +double LineItem::getYRaw() +{ + return y; +} + +void LineItem::drawTo(QPainterPath& path) +{ + if (stretchX) + { + path.moveTo(screenX(x), screenY(y) + length); + path.lineTo(screenX(x), screenY(y) - length); + } + else + { + path.moveTo(screenX(x) + length, screenY(y)); + path.lineTo(screenX(x) - length, screenY(y)); + } +} diff --git a/GCV-3.6.1-T4/src/lineitem.h b/GCV-3.6.1-T4/src/lineitem.h new file mode 100644 index 0000000..44e54aa --- /dev/null +++ b/GCV-3.6.1-T4/src/lineitem.h @@ -0,0 +1,38 @@ +#ifndef LINEITEM_H +#define LINEITEM_H +#include "itemtobase.h" + +class LineItem : public ItemToBase +{ +public: + LineItem(double x1, double y1, int index); + LineItem(double x1, double y1, bool stretchX, double length); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + + void drawTo(QPainterPath& path); + + void setColor(QColor); + void gdraw3D() ; + + double getXScr(); + double getYScr(); + + + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; + + bool stretchX; + double length; + + /** The color with which this item should be displayed */ + const QColor color; +}; + +#endif // LINEITEM_H diff --git a/GCV-3.6.1-T4/src/log4qt/appender.h b/GCV-3.6.1-T4/src/log4qt/appender.h new file mode 100644 index 0000000..81f6aa4 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/appender.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ********************************************************************************/ + +#ifndef LOG4QT_APPENDER_H +#define LOG4QT_APPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" + +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class LoggingEvent; + + /*! + * \brief The class Appender is the base class for all Appenders. + * + * To allow the whole hirarchy to be an ascendant of QObject Appender is + * not an interface. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Appender : public LogObject + { + Q_OBJECT + + /*! + * The property holds the Layout used by the Appender. + * + * \sa layout(), setLayout() + */ + Q_PROPERTY(Layout* layout READ layout WRITE setLayout) + + /*! + * The property holds the name of the Appender. + * + * \sa name(), setName() + */ + Q_PROPERTY(QString name READ name WRITE setName) + + /*! + * The property holds if the Appender requires a Layout or not. + * + * \sa requiresLayout(), setRequiresLayout() + */ + Q_PROPERTY(bool requiresLayout READ requiresLayout) + + public: + Appender(QObject *pParent = 0); + virtual ~Appender(); + private: + Appender(const Appender &rOther); // Not implemented + Appender &operator=(const Appender &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const = 0; + virtual QString name() const = 0; + virtual Layout *layout() const = 0; + virtual bool requiresLayout() const = 0; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout) = 0; + virtual void setName(const QString &rName) = 0; + + virtual void addFilter(Filter *pFilter) = 0; + virtual void clearFilters() = 0; + virtual void close() = 0; + virtual void doAppend(const LoggingEvent &rEvent) = 0; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender::Appender(QObject *pParent) : + LogObject(pParent) + {} + + inline Appender::~Appender() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Appender, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_APPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/appenderskeleton.cpp b/GCV-3.6.1-T4/src/log4qt/appenderskeleton.cpp new file mode 100644 index 0000000..d9f784b --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/appenderskeleton.cpp @@ -0,0 +1,261 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/appenderskeleton.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" +#include "log4qt/spi/filter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + ***************************************************************************/ + + + /*! + * \brief The class RecursionGuardLocker controls a boolean flag. + * + * It is a helper class to control a boolean flag. The class sets the flag + * on creation and resets it on destruction. + */ + class RecursionGuardLocker + { + public: + RecursionGuardLocker(bool *pGuard); + ~RecursionGuardLocker(); + private: + RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented + RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented + private: + bool *mpGuard; + }; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: RecursionGuardLocker + ***************************************************************************/ + + + inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard) + { + Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null"); + + mpGuard = pGuard; + *mpGuard = true; + } + + + inline RecursionGuardLocker::~RecursionGuardLocker() + { + *mpGuard = false; + }; + + + + /************************************************************************** + * Class implementation: AppenderSkeleton + **************************************************************************/ + + + AppenderSkeleton::AppenderSkeleton(QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(true), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + AppenderSkeleton::AppenderSkeleton(const bool isActive, + QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(isActive), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + void AppenderSkeleton::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"), + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return; + } + mIsActive = true; + } + + + void AppenderSkeleton::addFilter(Filter *pFilter) + { + if(!pFilter) + { + logger()->warn("Adding null Filter to Appender '%1'", name()); + return; + } + + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = pFilter; + if (mpHeadFilter) + mpHeadFilter->setNext(pFilter); + else + mpHeadFilter = pFilter; + } + + + void AppenderSkeleton::clearFilters() + { + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = 0; + mpHeadFilter = 0; + } + + + void AppenderSkeleton::close() + { + QMutexLocker locker(&mObjectGuard); + + mIsClosed = true; + mIsActive = false; + } + + + void AppenderSkeleton::doAppend(const LoggingEvent &rEvent) + { + // The mutex serialises concurrent access from multiple threads. + // - e.g. two threads using the same logger + // - e.g. two threads using different logger with the same appender + // + // A call from the same thread will pass the mutex (QMutex::Recursive) + // and get to the recursion guard. The recursion guard blocks recursive + // invocation and prevents a possible endless loop. + // - e.g. an appender logs an error with a logger that uses it + + QMutexLocker locker(&mObjectGuard); + + if (mAppendRecursionGuard) + return; + + RecursionGuardLocker recursion_locker(&mAppendRecursionGuard); + + if (!checkEntryConditions()) + return; + if (!isAsSevereAsThreshold(rEvent.level())) + return; + + Filter *p_filter = mpHeadFilter; + while(p_filter) + { + Filter::Decision decision = p_filter->decide(rEvent); + if (decision == Filter::ACCEPT) + break; + else if (decision == Filter::DENY) + return; + else + p_filter = p_filter->next(); + } + + append(rEvent); + } + + + bool AppenderSkeleton::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!isActive()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"), + APPENDER_NOT_ACTIVATED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (isClosed()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"), + APPENDER_CLOSED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"), + APPENDER_USE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/appenderskeleton.h b/GCV-3.6.1-T4/src/log4qt/appenderskeleton.h new file mode 100644 index 0000000..6f252b3 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/appenderskeleton.h @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: appenderskeleton.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_APPENDERSKELETON_H +#define LOG4QT_APPENDERSKELETON_H + + +/****************************************************************************** + * Dependencies +******************************************************************************/ + +#include "log4qt/appender.h" + +#include +#include "log4qt/helpers/logobjectptr.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class Logger; + class LoggingEvent; + + /*! + * \brief The class AppenderSkeleton implements general Appender functionality. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class AppenderSkeleton : public Appender + { + Q_OBJECT + + /*! + * The property holds if the Appender has been activated. + * + * \sa isActive() + */ + Q_PROPERTY(bool isActive READ isActive) + + /*! + * The property holds if the Appender has been closed. + * + * \sa isClosed() + */ + Q_PROPERTY(bool isClosed READ isClosed) + + /*! + * The property holds the threshold level used by the Appender. + * + * \sa threshold(), setThreshold() + */ + Q_PROPERTY(Level threshold READ threshold WRITE setThreshold) + + public: + AppenderSkeleton(QObject *pParent = 0); + protected: + AppenderSkeleton(const bool isActive, + QObject *pParent = 0); + public: + // virtual ~AppenderSkeleton(); Use compiler default + private: + AppenderSkeleton(const AppenderSkeleton &rOther); // Not implemented + AppenderSkeleton &operator=(const AppenderSkeleton &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const; + virtual Layout *layout() const; + bool isActive() const; + bool isClosed() const; + virtual QString name() const; + Level threshold() const; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout); + virtual void setName(const QString &rName); + void setThreshold(Level level); + + virtual void activateOptions(); + virtual void addFilter(Filter *pFilter); + virtual void clearFilters(); + virtual void close(); + + /*! + * Performs checks and delegates the actuall appending to the subclass + * specific append() function. + * + * \sa append(), checkEntryConditions(), isAsSevereAsThreshold(), Filter + */ + virtual void doAppend(const LoggingEvent &rEvent); + + // JAVA: void finalize(); + Filter* firstFilter() const; + bool isAsSevereAsThreshold(Level level) const; + + protected: + virtual void append(const LoggingEvent &rEvent) = 0; + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. + * + * The checked conditions are: + * - That the appender has been activated (APPENDER_NOT_ACTIVATED_ERROR) + * - That the appender was not closed (APPENDER_CLOSED_ERROR) + * - That the appender has a layout set, if it requires one + * (logging_error(APPENDER_USE_MISSING_LAYOUT_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by doAppend(). The doAppend() function calls the subclass + * specific checkEntryConditions() function. The function checks the + * class specific conditions and calls checkEntryConditions() of + * it's parent class. The last function called is + * AppenderSkeleton::checkEntryConditions(). + * + * \sa doAppend() + */ + virtual bool checkEntryConditions() const; + + protected: + mutable QMutex mObjectGuard; + private: + bool mAppendRecursionGuard; + volatile bool mIsActive; + volatile bool mIsClosed; + LogObjectPtr mpLayout; + Level mThreshold; + LogObjectPtr mpHeadFilter; + LogObjectPtr mpTailFilter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter *AppenderSkeleton::filter() const + { QMutexLocker locker(&mObjectGuard); + return mpHeadFilter; } + + inline Layout *AppenderSkeleton::layout() const + { QMutexLocker locker(&mObjectGuard); + return mpLayout; } + + inline QString AppenderSkeleton::name() const + { QMutexLocker locker(&mObjectGuard); + return objectName(); } + + inline Level AppenderSkeleton::threshold() const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void AppenderSkeleton::setLayout(Layout *pLayout) + { QMutexLocker locker(&mObjectGuard); + mpLayout = pLayout; } + + inline void AppenderSkeleton::setName(const QString &rName) + { QMutexLocker locker(&mObjectGuard); + setObjectName(rName); } + + inline void AppenderSkeleton::setThreshold(Level level) + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool AppenderSkeleton::isActive() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsActive; } + + inline bool AppenderSkeleton::isClosed() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsClosed; } + + inline Filter *AppenderSkeleton::firstFilter() const + { QMutexLocker locker(&mObjectGuard); + return filter(); } + + inline bool AppenderSkeleton::isAsSevereAsThreshold(Level level) const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return (mThreshold <= level); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::AppenderSkeleton, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_APPENDERSKELETON_H diff --git a/GCV-3.6.1-T4/src/log4qt/basicconfigurator.cpp b/GCV-3.6.1-T4/src/log4qt/basicconfigurator.cpp new file mode 100644 index 0000000..280b88d --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/basicconfigurator.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/basicconfigurator.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/logmanager.h" +#include "log4qt/patternlayout.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: BasicConfigurator + **************************************************************************/ + + + bool BasicConfigurator::configure() + { + LogObjectPtr list = new ListAppender; + list->setName(QLatin1String("BasicConfigurator")); + list->setConfiguratorList(true); + list->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(list); + + PatternLayout *p_layout = new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout->setName(QLatin1String("BasicConfigurator TTCC")); + p_layout->activateOptions(); + ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("BasicConfigurator stdout")); + p_appender->activateOptions(); + LogManager::rootLogger()->addAppender(p_appender); + + LogManager::logLogger()->removeAppender(list); + ConfiguratorHelper::setConfigureError(list->list()); + return (list->list().count() == 0); + } + + + void BasicConfigurator::configure(Appender *pAppender) + { + LogManager::rootLogger()->addAppender(pAppender); + } + + + void BasicConfigurator::resetConfiguration() + { + LogManager::resetConfiguration(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/basicconfigurator.h b/GCV-3.6.1-T4/src/log4qt/basicconfigurator.h new file mode 100644 index 0000000..c301501 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/basicconfigurator.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: basicconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_BASICCONFIGURATOR_H +#define LOG4QT_BASICCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Appender; + + /*! + * \brief The class BasicConfigurator provides a simple package + * configuration. + * + * \note All the functions declared in this class are thread-safe. + */ + class BasicConfigurator + { + private: + BasicConfigurator(); // Not implemented + // BasicConfigurator(const BasicConfigurator &rOther); // Use compiler default + // virtual ~BasicConfigurator(); // Use compiler default + // BasicConfigurator &operator=(const BasicConfigurator &rOther); // Use compiler default + + public: + static bool configure(); + static void configure(Appender *pAppender); + static void resetConfiguration(); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namspace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::BasicConfigurator, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_BASICCONFIGURATOR_H diff --git a/GCV-3.6.1-T4/src/log4qt/consoleappender.cpp b/GCV-3.6.1-T4/src/log4qt/consoleappender.cpp new file mode 100644 index 0000000..1b4fe03 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/consoleappender.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/consoleappender.h" + +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConsoleAppender + **************************************************************************/ + + + ConsoleAppender::ConsoleAppender(QObject *pParent) : + WriterAppender(pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + setTarget(rTarget); + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(target), + mpTextStream(0) + { + } + + + ConsoleAppender::~ConsoleAppender() + { + close(); + } + + + QString ConsoleAppender::target() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + if (mTarget == STDOUT_TARGET) + return QLatin1String("STDOUT_TARGET"); + else + return QLatin1String("STDERR_TARGET"); + } + + + void ConsoleAppender::setTarget(const QString &rTarget) + { + bool ok; + Target target = (Target)OptionConverter::toTarget(rTarget, &ok); + if (ok) + setTarget(target); + } + + + void ConsoleAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + closeStream(); + + if (mTarget == STDOUT_TARGET) + mpTextStream = new QTextStream(stdout); + else + mpTextStream = new QTextStream(stderr); + setWriter(mpTextStream); + + WriterAppender::activateOptions(); + } + + + void ConsoleAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeStream(); + } + + + void ConsoleAppender::closeStream() + { + // Q_ASSERT_X(, "ConsoleAppender::closeStream()", "Lock must be held by caller") + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ConsoleAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString target; + if (mTarget == STDOUT_TARGET) + target = QLatin1String("STDOUT"); + else + target = QLatin1String("STDERR"); + + rDebug.nospace() << "ConsoleAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "target:" << target << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/consoleappender.h b/GCV-3.6.1-T4/src/log4qt/consoleappender.h new file mode 100644 index 0000000..466015d --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/consoleappender.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: consoleappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CONSOLEAPPENDER_H +#define LOG4QT_CONSOLEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class ConsoleAppender appends to stdout or stderr. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ConsoleAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds the target used by the appender. + * + * The default is STDOUT_TARGET for the standard output. + * + * \sa Target, target(), setTarget() + */ + Q_PROPERTY(QString target READ target WRITE setTarget) + + public: + /*! + * The enum defines the possible output targets + * + * \sa target(), setTarget() + */ + enum Target { + /*! The output target is standard out. */ + STDOUT_TARGET, + /*! The output target is standard error. */ + STDERR_TARGET + }; + Q_ENUMS(Target) + + ConsoleAppender(QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent = 0); + + /*! + * Creates a ConsoleAppender with the layout \a pLayout, the target + * value specified by the \a target constant and the parent + * \a pParent. + */ + ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent = 0); + + virtual ~ConsoleAppender(); + private: + ConsoleAppender(const ConsoleAppender &rOther); // Not implemented + ConsoleAppender &operator=(const ConsoleAppender &rOther); // Not implemented + + public: + // JAVA: bool follow() const; + QString target() const; + // JAVA: void setFollow(bool follow); + void setTarget(const QString &rTarget); + + /*! + * Sets the target to the value specified by the \a target constant. + */ + void setTarget(Target target); + + virtual void activateOptions(); + virtual void close(); + + protected: + void closeStream(); + + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ConsoleAppender(name:"CA" filter:0x0 isactive:true isclosed:false + * layout:"PL" target:"STDERR" referenceCount:1 + * threshold:"WARN_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + #endif // QT_NO_DEBUG_STREAM + + private: + volatile Target mTarget; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline void ConsoleAppender::setTarget(Target target) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mTarget = target; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConsoleAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CONSOLEAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.cpp b/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.cpp new file mode 100644 index 0000000..0590f16 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.cpp @@ -0,0 +1,352 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/dailyrollingfileappender.h" + +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DailyRollingFileAppender + **************************************************************************/ + + + DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mDatePattern() + { + setDatePattern(DAILY_ROLLOVER); + } + + + DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mDatePattern() + { + setDatePattern(rDatePattern); + } + + + DailyRollingFileAppender::~DailyRollingFileAppender() + { + close(); + } + + + void DailyRollingFileAppender::setDatePattern(DatePattern datePattern) + { + switch (datePattern) + { + case MINUTELY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm")); + break; + case HOURLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh")); + break; + case HALFDAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-a")); + break; + case DAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd")); + break; + case WEEKLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-ww")); + break; + case MONTHLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM")); + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant"); + setDatePattern(DAILY_ROLLOVER); + }; + } + + + void DailyRollingFileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + computeFrequency(); + if (!mActiveDatePattern.isEmpty()) + { + computeRollOverTime(); + FileAppender::activateOptions(); + } + } + + + void DailyRollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller") + + if (QDateTime::currentDateTime() > mRollOverTime) + rollOver(); + FileAppender::append(rEvent); + } + + + bool DailyRollingFileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (mActiveDatePattern.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"), + APPENDER_USE_INVALID_PATTERN_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return FileAppender::checkEntryConditions(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "DailyRollingFileAppender(" + << "name:" << name() << " " + << "activedatepattern:" << mActiveDatePattern << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "datepattern:" << datePattern() << " " + << "encoding:" << codec_name << " " + << "frequency:" << frequencyToString() << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "rollovertime:" << mRollOverTime + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void DailyRollingFileAppender::computeFrequency() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller") + + const DateTime start_time(QDate(1999, 1, 1), QTime(0, 0)); + const QString start_string = start_time.toString(mDatePattern); + mActiveDatePattern.clear(); + + if (start_string != static_cast(start_time.addSecs(60)).toString(mDatePattern)) + mFrequency = MINUTELY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60)).toString(mDatePattern)) + mFrequency = HOURLY_ROLLOVER; + else if (start_string != static_cast(start_time.addSecs(60 * 60 * 12)).toString(mDatePattern)) + mFrequency = HALFDAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(1)).toString(mDatePattern)) + mFrequency = DAILY_ROLLOVER; + else if (start_string != static_cast(start_time.addDays(7)).toString(mDatePattern)) + mFrequency = WEEKLY_ROLLOVER; + else if (start_string != static_cast(start_time.addMonths(1)).toString(mDatePattern)) + mFrequency = MONTHLY_ROLLOVER; + else + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"), + APPENDER_INVALID_PATTERN_ERROR); + e << mDatePattern << name(); + logger()->error(e); + return; + } + + mActiveDatePattern = mDatePattern; + logger()->trace("Frequency set to %2 using date pattern %1", + mActiveDatePattern, + frequencyToString()); + } + + + void DailyRollingFileAppender::computeRollOverTime() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern"); + + QDateTime now = QDateTime::currentDateTime(); + QDate now_date = now.date(); + QTime now_time = now.time(); + QDateTime start; + + switch (mFrequency) + { + case MINUTELY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + now_time.minute(), + 0, 0)); + mRollOverTime = start.addSecs(60); + } + break; + case HOURLY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + 0, 0, 0)); + mRollOverTime = start.addSecs(60*60); + } + break; + case HALFDAILY_ROLLOVER: + { + int hour = now_time.hour(); + if (hour >= 12) + hour = 12; + else + hour = 0; + start = QDateTime(now_date, + QTime(hour, 0, 0, 0)); + mRollOverTime = start.addSecs(60*60*12); + } + break; + case DAILY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(0, 0, 0, 0)); + mRollOverTime = start.addDays(1); + } + break; + case WEEKLY_ROLLOVER: + { + // QT numbers the week days 1..7. The week starts on Monday. + // Change it to being numbered 0..6, starting with Sunday. + int day = now_date.dayOfWeek(); + if (day == Qt::Sunday) + day = 0; + start = QDateTime(now_date, + QTime(0, 0, 0, 0)).addDays(-1 * day); + mRollOverTime = start.addDays(7); + } + break; + case MONTHLY_ROLLOVER: + { + start = QDateTime(QDate(now_date.year(), + now_date.month(), + 1), + QTime(0, 0, 0, 0)); + mRollOverTime = start.addMonths(1); + } + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant"); + mRollOverTime = QDateTime::fromTime_t(0); + } + + mRollOverSuffix = static_cast(start).toString(mActiveDatePattern); + Q_ASSERT_X(static_cast(now).toString(mActiveDatePattern) == mRollOverSuffix, + "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval"); + Q_ASSERT_X(mRollOverSuffix != static_cast(mRollOverTime).toString(mActiveDatePattern), + "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover"); + + logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3", + now, + start, + mRollOverTime); + } + + + QString DailyRollingFileAppender::frequencyToString() const + { + QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern")); + return QLatin1String(meta_enum.valueToKey(mFrequency)); + } + + + void DailyRollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern"); + + QString roll_over_suffix = mRollOverSuffix; + computeRollOverTime(); + if (roll_over_suffix == mRollOverSuffix) + return; + + closeFile(); + + QString target_file_name = file() + roll_over_suffix; + QFile f(target_file_name); + if (f.exists() && !removeFile(f)) + return; + f.setFileName(file()); + if (!renameFile(f, target_file_name)) + return; + openFile(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.h b/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.h new file mode 100644 index 0000000..e3fe638 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/dailyrollingfileappender.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: dailyrollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DAILYROLLINGFILEAPPENDER_H +#define LOG4QT_DAILYROLLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DailyRollingFileAppender extends FileAppender so that the + * underlying file is rolled over at a specified frequency. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class DailyRollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the date pattern used by the appender. + * + * The default is DAILY_ROLLOVER for rollover at midnight each day. + * + * \sa datePattern(), setDatePattern() + */ + Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern) + + public: + /*! + * The enum DatePattern defines constants for date patterns. + * + * \sa setDatePattern(DatePattern) + */ + enum DatePattern + { + /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */ + MINUTELY_ROLLOVER = 0, + /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */ + HOURLY_ROLLOVER, + /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */ + HALFDAILY_ROLLOVER, + /*! The daily date pattern string is "'.'yyyy-MM-dd". */ + DAILY_ROLLOVER, + /*! The weekly date pattern string is "'.'yyyy-ww". */ + WEEKLY_ROLLOVER, + /*! The monthly date pattern string is "'.'yyyy-MM". */ + MONTHLY_ROLLOVER + }; + Q_ENUMS(DatePattern) + + DailyRollingFileAppender(QObject *pParent = 0); + DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent = 0); + virtual ~DailyRollingFileAppender(); + private: + DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented + DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented + + public: + QString datePattern() const; + + /*! + * Sets the datePattern to the value specified by the \a datePattern + * constant. + */ + void setDatePattern(DatePattern datePattern); + + void setDatePattern(const QString &rDatePattern); + + virtual void activateOptions(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * FileAppender::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm" + * appendfile:false bufferedio:true + * datepattern:"'.'yyyy-MM-dd-hh-mm" + * encoding:"" frequency:"MINUTELY_ROLLOVER" + * file:"/log.txt" filter:0x0 immediateflush:true + * isactive:true isclosed:false layout:"TTCC" + * referencecount:1 + * rollovertime:QDateTime("Mon Oct 22 05:23:00 2007") + * threshold: "NULL" writer: 0x0 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void computeFrequency(); + void computeRollOverTime(); + QString frequencyToString() const; + void rollOver(); + + private: + QString mDatePattern; + DatePattern mFrequency; + QString mActiveDatePattern; + QDateTime mRollOverTime; + QString mRollOverSuffix; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString DailyRollingFileAppender::datePattern() const + { QMutexLocker locker(&mObjectGuard); + return mDatePattern; } + + inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern) + { QMutexLocker locker(&mObjectGuard); + mDatePattern = rDatePattern; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DailyRollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DAILYROLLINGFILEAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/fileappender.cpp b/GCV-3.6.1-T4/src/log4qt/fileappender.cpp new file mode 100644 index 0000000..265634f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/fileappender.cpp @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/fileappender.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: FileAppender + **************************************************************************/ + + + FileAppender::FileAppender(QObject *pParent) : + WriterAppender(pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(buffered), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::~FileAppender() + { + close(); + } + + + void FileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (mFileName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"), + APPENDER_ACTIVATE_MISSING_FILE_ERROR); + e << name(); + logger()->error(e); + return; + } + closeFile(); + openFile(); + WriterAppender::activateOptions(); + } + + + void FileAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeFile(); + } + + + bool FileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!mpFile || !mpTextStream) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"), + APPENDER_NO_OPEN_FILE_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return WriterAppender::checkEntryConditions(); + } + + + void FileAppender::closeFile() + { + // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller") + + if (mpFile) + logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name()); + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + delete mpFile; + mpFile = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug FileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "FileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool FileAppender::handleIoErrors() const + { + // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller") + + if (mpFile->error() == QFile::NoError) + return false; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"), + APPENDER_WRITING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return true; + } + + + void FileAppender::openFile() + { + Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file"); + + QFileInfo file_info(mFileName); + QDir parent_dir = file_info.dir(); + if (!parent_dir.exists()) + { + logger()->trace("Creating missing parent directory for file %1", mFileName); + QString name = parent_dir.dirName(); + parent_dir.cdUp(); + parent_dir.mkdir(name); + } + + + mpFile = new QFile(mFileName); + QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text; + if (mAppendFile) + mode |= QIODevice::Append; + else + mode |= QIODevice::Truncate; + if (!mBufferedIo) + mode |= QIODevice::Unbuffered; + if (!mpFile->open(mode)) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + APPENDER_OPENING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return; + } + mpTextStream = new QTextStream(mpFile); + setWriter(mpTextStream); + logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name()); + } + + + bool FileAppender::removeFile(QFile &rFile) const + { + if (rFile.remove()) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"), + APPENDER_REMOVE_FILE_ERROR); + e << rFile.fileName() << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + bool FileAppender::renameFile(QFile &rFile, + const QString &rFileName) const + { + logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName); + if (rFile.rename(rFileName)) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"), + APPENDER_RENAMING_FILE_ERROR); + e << rFile.fileName() << rFileName << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/fileappender.h b/GCV-3.6.1-T4/src/log4qt/fileappender.h new file mode 100644 index 0000000..2479d4e --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/fileappender.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: fileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILEAPPENDER_H +#define LOG4QT_FILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class FileAppender appends log events to a file. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class FileAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds, if the output is appended to the file. + * + * The default is false for not appending. + * + * \sa appendFile(), setAppendFile() + */ + Q_PROPERTY(bool appendFile READ appendFile WRITE setAppendFile) + + /*! + * The property holds, if the output is buffered. + * + * The default is true for buffering. + * + * \sa bufferedIo(), setBufferedIo() + */ + Q_PROPERTY(bool bufferedIo READ bufferedIo WRITE setBufferedIo) + + /*! + * The property holds the name of the file. + * + * \sa file(), setFile() + */ + Q_PROPERTY(QString file READ file WRITE setFile) + + public: + FileAppender(QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent = 0); + virtual ~FileAppender(); + private: + FileAppender(const FileAppender &rOther); // Not implemented + FileAppender &operator=(const FileAppender &rOther); // Not implemented + + public: + bool appendFile() const; + QString file() const; + bool bufferedIo() const; + // JAVA: int bufferSize() const; + void setAppendFile(bool append); + void setBufferedIo(bool buffered); + // JAVA: void setBufferSize(int bufferSize); + void setFile(const QString &rFileName); + + virtual void activateOptions(); + virtual void close(); + + protected: + /*! + * Tests if all entry conditions for using append() in this class are met. + * + * If a conditions is not met, an error is logged and the function returns + * false. Otherwise the result of WriterAppender::checkEntryConditions() + * is returned. + * + * The checked conditions are: + * - That a file is set and open (APPENDER_NO_OPEN_FILE_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeFile(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %FileAppender(name:"FA" appendfile:false bufferedio:true encoding:"" + * file:"/log.txt" filter: 0x0 immediateflush:true isactive:false + * isclosed:false layout:"TTCC" referencecount:2 + * threshold:"NULL" writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Checks for file I/O errrors. If an error is found it is logged and the + * function returns true. Otherwise false is returned. + */ + virtual bool handleIoErrors() const; + + /*! + * Opens the file for the appender based on the specified file name and + * mode. A text stream is created and passed on to the super class + * WriterAppender. + * + * If the parent directory of the specified file does not exists, + * it is created. + */ + void openFile(); + + /*! + * Removes the file \a rFile. If the operation is successful, true is + * returned. Otherwise an APPENDER_REMOVE_FILE_ERROR error is logged + * and false is returned. + */ + bool removeFile(QFile &rFile) const; + + /*! + * Renames the file \a rFile to \a rFileName. If the operation is + * successful, true is returned. Otherwise an + * APPENDER_RENAMING_FILE_ERROR error is logged and false is returned. + */ + bool renameFile(QFile &rFile, + const QString &rFileName) const; + + // JAVA: void setQWForFiles(Writer writer); + + private: + volatile bool mAppendFile; + volatile bool mBufferedIo; + QString mFileName; + QFile *mpFile; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool FileAppender::appendFile() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAppendFile; } + + inline QString FileAppender::file() const + { QMutexLocker locker(&mObjectGuard); + return mFileName; } + + inline bool FileAppender::bufferedIo() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mBufferedIo; } + + inline void FileAppender::setAppendFile(bool append) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mAppendFile = append; } + + inline void FileAppender::setBufferedIo(bool buffered) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mBufferedIo = buffered; } + + inline void FileAppender::setFile(const QString &rFileName) + { QMutexLocker locker(&mObjectGuard); + mFileName = rFileName; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::FileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_FILEAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.cpp new file mode 100644 index 0000000..50b6c7f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/classlogger.h" + +#include +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ClassLogger + **************************************************************************/ + + + ClassLogger::ClassLogger() : + mpLogger(0) + { + } + + + Logger *ClassLogger::logger(const QObject *pObject) + { + Q_ASSERT_X(pObject, "ClassLogger::logger()", "pObject must not be null"); +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + if (!mpLogger) + q_atomic_test_and_set_ptr(&mpLogger, + 0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(mpLogger); +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + if (!static_cast(mpLogger)) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger)); +#else + if (!static_cast(mpLogger.loadAcquire())) + mpLogger.testAndSetOrdered(0, + LogManager::logger(QLatin1String(pObject->metaObject()->className()))); + return const_cast(static_cast(mpLogger.loadAcquire())); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.h b/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.h new file mode 100644 index 0000000..065a852 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/classlogger.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: classlogger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_CLASSLOGGER_H +#define LOG4QT_CLASSLOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The class Log4Qt::ClassLogger is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Logger; + + /*! + * \brief The class ClassLogger provides logging for a QObject derived + * class. + * + * The class ClassLogger provides a logger for a specified QObject derived + * object. It is used by \ref LOG4QT_DECLARE_QCLASS_LOGGER to implement the + * member functions provided by the macro. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa LOG4QT_DECLARE_QCLASS_LOGGER + */ + class ClassLogger + { + public: + /*! + * Creates a ClassLogger object. + */ + ClassLogger(); + // ~ClassLogger(); // Use compiler default + // ClassLogger(const ClassLogger &rOther); // Use compiler default + // ClassLogger &operator=(const ClassLogger &rOther); // Use compiler default + + /*! + * Returns a pointer to a Logger named after the class of the object + * \a pObject. + * + * On the first invocation the Logger is requested by a call to + * LogManager::logger(const char *pName). The pointer is stored to be + * returned on subsequent invocations. + * + * \sa LogManager::logger(const char *pName) + */ + Logger *logger(const QObject *pObject); + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile Logger *mpLogger; +#else + mutable QAtomicPointer mpLogger; +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::ClassLogger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_CLASSLOGGER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.cpp new file mode 100644 index 0000000..3b34f40 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/configuratorhelper.h" + +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConfiguratorHelper + **************************************************************************/ + + + ConfiguratorHelper::ConfiguratorHelper() : + mObjectGuard(), + mConfigurationFile(), + mpConfigureFunc(0), + mpConfigurationFileWatch(0), + mConfigureError() + { + } + + + ConfiguratorHelper::~ConfiguratorHelper() + { + delete mpConfigurationFileWatch; + } + + + LOG4QT_IMPLEMENT_INSTANCE(ConfiguratorHelper) + + + void ConfiguratorHelper::doConfigurationFileChanged(const QString &rFileName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mpConfigureFunc) + return; + mpConfigureFunc(rFileName); + // Shall we hold the lock while emitting the signal? + emit configurationFileChanged(rFileName, mConfigureError.count() > 0); + } + + + + void ConfiguratorHelper::doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { + QMutexLocker locker(&mObjectGuard); + + mConfigurationFile.clear(); + mpConfigureFunc = 0; + delete mpConfigurationFileWatch; + if (rFileName.isEmpty()) + return; + + mConfigurationFile = rFileName; + mpConfigureFunc = pConfigureFunc; + mpConfigurationFileWatch = new QFileSystemWatcher(); + mpConfigurationFileWatch->addPath(rFileName); + connect(mpConfigurationFileWatch, + SIGNAL(fileChanged(const QString &)), + SLOT(configurationFileChanged(const QString &))); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper) + { + debug.nospace() << "ConfiguratorHelper(" + << "configurationfile:" << ConfiguratorHelper::configurationFile() + << "configurefunc:" << rConfiguratorHelper.mpConfigureFunc + << "filesystemwatcher:" << rConfiguratorHelper.mpConfigurationFileWatch + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.h b/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.h new file mode 100644 index 0000000..765f86a --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/configuratorhelper.h @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: configuratorhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_CONFIGURATORHELPER_H +#define LOG4QT_HELPERS_CONFIGURATORHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFileSystemWatcher; + + +namespace Log4Qt +{ + + /*! + * \brief The class ConfiguratorHelper provides a confiuration file watch + * and last error for configurator classes. + * + * A configuration file can be set using setConfigurationFile(). The file + * is watched for changes. If a change occurs the configuration is reloaded + * and the ConfigurationFileChanged() signal is emitted. Error information + * for the last call to a configure function or the last configuration file + * change can be accessed using configureError(). + * + * \note All the functions declared in this class are thread-safe. + */ + class ConfiguratorHelper : public QObject + { + Q_OBJECT + + public: + /*! + * Prototype for a configure callback function. The function is called + * when then configuration file is changed and takes the + * configuration file as a parameter. + * + * \sa setConfigurationFile(), + * PropertyConfigurator::configure(const QString &) + */ + typedef bool (*ConfigureFunc)(const QString &rFileName); + + private: + ConfiguratorHelper(); + ConfiguratorHelper(const ConfiguratorHelper &rOther); // Not implemented + virtual ~ConfiguratorHelper(); + ConfiguratorHelper &operator=(const ConfiguratorHelper &rOther); // Not implemented + + public: + + /*! + * Returns the error information for the last configuration operation + * that took place. The configuration operation could be the result of + * a call to one of the configure methods or through a change + * to the configuration file. + * + * \sa setConfigureError(), PropertyConfigurator::configure(), + * setConfigurationFile() + */ + static QList configureError(); + + /*! + * Returns the current configuration file. + * + * \sa setConfigurationFile() + */ + static QString configurationFile(); + + /*! + * Returns the ConfiguratorHelper instance. + */ + static ConfiguratorHelper *instance(); + + /*! + * Sets the configuration error information for the last configuration + * operation. + * + * \sa configureError() + */ + static void setConfigureError(const QList &rConfigureError); + + /*! + * Sets the configuration file to \a rFileName. The file is watched for + * changes. On a file change the function \a pConfigureFunc will be called + * and the signal configurationFileChange() will be emitted. + * + * Setting the configuration file to an empty string stops the file watch. + * + * \sa configurationFile(), PropertyConfigurator::configureAndWatch(), + * configureError() + */ + static void setConfigurationFile(const QString &rFileName = QString(), + ConfigureFunc pConfigureFunc = 0); + + signals: + /*! + * The signal is emitted after a change to the file \a rFileName + * was processed. If an error occured during the configuration, the + * flag \a error will be true and error information is available + * over configureError(). + */ + void configurationFileChanged(const QString &rFileName, + bool error); + + private slots: + void doConfigurationFileChanged(const QString &rFileName); + + private: + void doSetConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc); + + private: + mutable QMutex mObjectGuard; + QString mConfigurationFile; + ConfigureFunc mpConfigureFunc; + QFileSystemWatcher *mpConfigurationFileWatch; + QList mConfigureError; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates ConfiguratorHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %ConfiguratorHelper(configurationfile: "" configurefunc: false + * filesystemwatcher: QObject(0x0) ) + * + * \sa QDebug, ConfiguratorHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const ConfiguratorHelper &rConfiguratorHelper); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QList ConfiguratorHelper::configureError() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigureError; } + + inline QString ConfiguratorHelper::configurationFile() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mConfigurationFile; } + + inline void ConfiguratorHelper::setConfigureError(const QList &rConfigureError) + { QMutexLocker locker(&instance()->mObjectGuard); + instance()->mConfigureError = rConfigureError; } + + inline void ConfiguratorHelper::setConfigurationFile(const QString &rFileName, + ConfigureFunc pConfigureFunc) + { instance()->doSetConfigurationFile(rFileName, pConfigureFunc); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ConfiguratorHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_CONFIGURATORHELPER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/datetime.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/datetime.cpp new file mode 100644 index 0000000..6da69a2 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/datetime.cpp @@ -0,0 +1,326 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/datetime.h" + +#include +#include "log4qt/helpers/initialisationhelper.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DateTime + **************************************************************************/ + + + QString DateTime::toString(const QString &rFormat) const + { + QString format(rFormat); + + if (format.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + if (format == QLatin1String("NONE")) + return QString(); + + if (format == QLatin1String("RELATIVE")) + return QString::number(toMilliSeconds() - InitialisationHelper::startTime()); + + if (format == QLatin1String("ISO8601")) + format = QLatin1String("yyyy-MM-dd hh:mm:ss.zzz"); + if (format == QLatin1String("ABSOLUTE")) + format = QLatin1String("HH:mm:ss.zzz"); + if (format == QLatin1String("DATE")) + format = QLatin1String("dd MMM YYYY HH:mm:ss.zzzz"); + + return formatDateTime(format); + } + + + QString DateTime::formatDateTime(const QString &rFormat) const + { + if (rFormat.isEmpty()) + return QString(); + if (!isValid()) + return QString(); + + const QLatin1Char null('0'); + const QLatin1Char quote('\''); + const QString tokens = QLatin1String("\'dMyhHmszAPapw"); + const bool am_pm = hasAMPM(rFormat); + + QString result; + QString token; + QChar expected = null; + + QChar c; + int i; + for (i = 0; i < rFormat.length(); i++) + { + c = rFormat.at(i); + + // Handle literal text + if (expected == quote) + { + if (c == quote) + { + Q_ASSERT_X(i > 0, "DateTime::toString()", "Found quote with status quote at i = 0"); + if (i > 0 && rFormat.at(i - 1) == quote) + // Second of two quotes + result += quote; + expected = null; + } + else + // Next literal character + result += c; + } + else if (c == expected) + { + // Extend token + token += c; + } + else + { + // Close last token + result += formatToken(token, am_pm); + token.clear(); + expected = null; + + // Test for valid character + if (tokens.indexOf(c) >= 0) + { + if (c == QLatin1Char('a')) + expected = QLatin1Char('p'); + else if (c == QLatin1Char('A')) + expected = QLatin1Char('P'); + else if (c.toLower() == QLatin1Char('p')) + expected = null; + else + expected = c; + if (c != quote) + token += c; + } else + result += c; + } + } + + result += formatToken(token, am_pm); + return result; + } + + + QString DateTime::formatToken(const QString &rToken, bool am_pm) const + { + if (rToken.isEmpty()) + return QString(); + + const QChar c = rToken.at(0); + QString result; + int used = 0; + + // Qt data format strings + if (rToken.startsWith(QLatin1String("dddd"))) + { + result = QDate::longDayName(date().dayOfWeek()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("ddd"))) + { + result = QDate::shortDayName(date().dayOfWeek()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("dd"))) + { + result = QString::number(date().day()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('d')) + { + result = QString::number(date().day()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("MMMM"))) + { + result = QDate::longMonthName(date().month()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("MMM"))) + { + result = QDate::shortMonthName(date().month()); + used = 3; + } + else if (rToken.startsWith(QLatin1String("MM"))) + { + result = QString::number(date().month()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('M')) + { + result = QString::number(date().month()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("yyyy"))) + { + result = QString::number(date().year()); + used = 4; + } + else if (rToken.startsWith(QLatin1String("yy"))) + { + result = QString::number(date().year() % 100).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + + // Qt time format strings + else if (rToken.startsWith(QLatin1String("hh")) || rToken.startsWith(QLatin1String("HH"))) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('h') || c == QLatin1Char('H')) + { + int hour = time().hour(); + if (am_pm && c == QLatin1Char('h') && hour > 12) + hour -= 12; + result = QString::number(hour); + used = 2; + } + else if (rToken.startsWith(QLatin1String("mm"))) + { + result = QString::number(time().minute()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == (QLatin1Char('m'))) + { + result = QString::number(time().minute()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("ss"))) + { + result = QString::number(time().second()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('s')) + { + result = QString::number(time().second()); + used = 1; + } + else if (rToken.startsWith(QLatin1String("zzz"))) + { + result = QString::number(time().msec()).rightJustified(3, QLatin1Char('0'), true); + used = 3; + } + else if (c == QLatin1Char('z')) + { + result = QString::number(time().msec()); + used = 1; + } + else if (c.toLower() == QLatin1Char('a')) + { + bool is_lower = c == QLatin1Char('a'); + if (time().hour() < 12) + result = QLatin1String("AM"); + else + result = QLatin1String("PM"); + if (is_lower) + result = result.toLower(); + if (rToken.size() > 1 && + ((is_lower && rToken.at(1) == QLatin1Char('p')) || + (!is_lower && rToken.at(1) == QLatin1Char('P'))) + ) + used = 2; + else + used = 1; + } + + // Extension for week number + else if (rToken.startsWith(QLatin1String("ww"))) + { + result = QString::number(date().weekNumber()).rightJustified(2, QLatin1Char('0'), true); + used = 2; + } + else if (c == QLatin1Char('w')) + { + result = QString::number(date().weekNumber()); + used = 1; + } + + if (used) + return result + formatToken(rToken.mid(used), am_pm); + else + return result; + } + + + bool DateTime::hasAMPM(const QString &rToken) + { + bool in_literal = false; + QChar c; + int i; + for (i = 0; i < rToken.length(); i++) + { + c = rToken.at(i); + if (c == QLatin1Char('\'')) + in_literal = !in_literal; + else if (!in_literal && c.toLower() == QLatin1Char('a')) + return true; + } + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/datetime.h b/GCV-3.6.1-T4/src/log4qt/helpers/datetime.h new file mode 100644 index 0000000..2c83a47 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/datetime.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: datetime.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_DATETIME_H +#define LOG4QT_HELPERS_DATETIME_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class DateTime provides extended functionality for QDateTime. + * + * The class DateTime implements additional formatting options for + * toString() and provides conversion functions from and to milliseconds. + */ + class DateTime : public QDateTime + { + public: + /*! + * Constructs a null date time. + * + * \sa QDateTime::QDateTime() + */ + DateTime(); + + // DateTime(const DateTime &rOther); // Use compiler default + + /*! + * Constructs a copy of another QDateTime. + * + * \sa QDateTime::QDateTime(const QDateTime &rOther) + */ + DateTime(const QDateTime &rOther); + + /*! + * Constructs a datetime with the given \a rDate and \a rTime, using + * the time specification defined by \a timeSpec. + * + * \sa QDateTime::QDateTime(const QDate &rDate, const QTime &rTime, + * Qt::TimeSpec timeSpec = Qt::LocalTime) + */ + DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec = Qt::LocalTime); + + // virtual ~DateTime(); // Use compiler default + + /*! + * Assigns \a rOther to this DateTime and returns a reference to it. + */ + DateTime &operator=(const DateTime &rOther); + + /*! + * Returns the datetime as the number of milliseconds that have passed + * since 1970-01-01T00:00:00,000, Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::toTime_t() + */ + qint64 toMilliSeconds() const; + + /*! + * Returns the datetime as a string. The \a rFormat parameter + * determines the format of the result string. + * + * In addition to the expressions of QDateTime::toString(const QString + * &rFormat) the following expression can be used. + * + * + * + * + * + * + * + * + * + * + * + * + *
Expression Output
w the week of the year as number without a leading zero (1 to 53)
ww the week of the year as number with a leading zero (01 to 53)
+ * + * Alternatively the \a rFormat parameter can specify one of the + * following strings. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
String Format
ABSOLUTE uses the format HH:mm:ss.zzz
DATE uses the format dd MMM YYYY HH:mm:ss.zzzz
ISO8601 uses the format yyyy-MM-dd hh:mm:ss.zzz
NONE uses an empty string as format
RELATIVE returns the milliseconds since start of the program
+ * + * \sa QDateTime::toString(const QString &rFormat) + */ + QString toString(const QString &rFormat) const; + + /*! + * Returns the current datetime, as reported by the system clock, in + * the local time zone. + * + * \sa QDateTime::currentDateTime() + */ + static DateTime currentDateTime(); + + /*! + * Returns a datetime whose date and time are the number of + * milliseconds that have passed since 1970-01-01T00:00:00, + * Coordinated Universal Time (Qt::UTC). + * + * \sa QDateTime::fromTime_t(uint seconds) + */ + static DateTime fromMilliSeconds(qint64 milliSeconds); + + private: + QString formatDateTime(const QString &rFormat) const; + QString formatToken(const QString &rToken, bool am_pm) const; + static bool hasAMPM(const QString &rFormat); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DateTime::DateTime() : QDateTime() + {} + + inline DateTime::DateTime(const QDateTime &rOther) : QDateTime(rOther) + {} + + inline DateTime::DateTime(const QDate &rDate, + const QTime &rTime, + Qt::TimeSpec timeSpec) : + QDateTime(rDate, rTime, timeSpec) + {} + + inline DateTime &DateTime::operator=(const DateTime &rOther) + { QDateTime::operator=(rOther); return *this; } + + inline qint64 DateTime::toMilliSeconds() const + { return (qint64)1000 * toTime_t() + time().msec(); } + + inline DateTime DateTime::currentDateTime() + { return DateTime(QDateTime::currentDateTime()); } + + inline DateTime DateTime::fromMilliSeconds(qint64 milliSeconds) + { return DateTime(QDateTime::fromTime_t(milliSeconds / 1000).addMSecs(milliSeconds % 1000)); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::DateTime, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_HELPERS_DATETIME_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/factory.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/factory.cpp new file mode 100644 index 0000000..70c5ed0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/factory.cpp @@ -0,0 +1,456 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/factory.h" + +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/dailyrollingfileappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/patternlayout.h" +#include "log4qt/rollingfileappender.h" +#include "log4qt/simplelayout.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/debugappender.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelmatchfilter.h" +#include "log4qt/varia/levelrangefilter.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/varia/nullappender.h" +#include "log4qt/varia/stringmatchfilter.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory) + + + // Appenders + + Appender *console_file_appender() + { return new ConsoleAppender; } + + Appender *create_daily_rolling_file_appender() + { return new DailyRollingFileAppender; } + + Appender *create_debug_appender() + { return new DebugAppender; } + + Appender *create_file_appender() + { return new FileAppender; } + + Appender *create_list_appender() + { return new ListAppender; } + + Appender *create_null_appender() + { return new NullAppender; } + + Appender *create_rolling_file_appender() + { return new RollingFileAppender; } + + + // Filters + + Filter *create_deny_all_filter() + { return new DenyAllFilter; } + + Filter *create_level_match_filter() + { return new LevelMatchFilter; } + + Filter *create_level_range_filter() + { return new LevelRangeFilter; } + + Filter *create_string_match_filter() + { return new StringMatchFilter; } + + + // Layouts + + Layout *create_pattern_layout() + { return new PatternLayout; } + + Layout *create_simple_layout() + { return new SimpleLayout; } + + Layout *create_ttcc_layout() + { return new TTCCLayout; } + + + + /************************************************************************** + * Class implementation: Factory + **************************************************************************/ + + + Factory::Factory() : + mObjectGuard(), + mAppenderRegistry(), + mFilterRegistry(), + mLayoutRegistry() + { + registerDefaultAppenders(); + registerDefaultFilters(); + registerDefaultLayouts(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(Factory) + + + Appender *Factory::doCreateAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName); + return 0; + } + return mAppenderRegistry.value(rAppenderClassName)(); + } + + + Filter *Factory::doCreateFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName); + return 0; + } + return mFilterRegistry.value(rFilterClassName)(); + } + + + Layout *Factory::doCreateLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName); + return 0; + } + return mLayoutRegistry.value(rLayoutClassName)(); + } + + + void Factory::doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rAppenderClassName.isEmpty()) + { + logger()->warn("Registering Appender factory function with empty class name"); + return; + } + mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc); + } + + + void Factory::doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rFilterClassName.isEmpty()) + { + logger()->warn("Registering Filter factory function with empty class name"); + return; + } + mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc); + } + + + void Factory::doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { + QMutexLocker locker(&mObjectGuard); + + if(rLayoutClassName.isEmpty()) + { + logger()->warn("Registering Layout factory function with empty class name"); + return; + } + mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc); + } + + + void Factory::doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { + // - Validate property + // - Get correct property name from meta object + // - Find specific property setter + // - If no specfifc propery setter can be found, + // find general property setter + // - Call property setter + QMetaProperty meta_property; + if (!validateObjectProperty(meta_property, rProperty, pObject)) + return; + + QString property = QLatin1String(meta_property.name()); + QString type = QLatin1String(meta_property.typeName()); + logger()->debug("Setting property '%1' on object of class '%2' to value '%3'", + property, + QLatin1String(pObject->metaObject()->className()), + rValue); + + QVariant value; + bool ok = true; + if (type == QLatin1String("bool")) + value = OptionConverter::toBoolean(rValue, &ok); + else if (type == QLatin1String("int")) + value = OptionConverter::toInt(rValue, &ok); + else if (type == QLatin1String("Log4Qt::Level")) + value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok)); + else if (type == QLatin1String("QString")) + value = rValue; + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"), + CONFIGURATOR_UNKNOWN_TYPE_ERROR, + "Log4Qt::Factory"); + e << type + << property + << QString::fromLatin1(pObject->metaObject()->className()); + logger()->error(e); + return; + } + if (!ok) + return; + + // Everything is checked and the type is the one of the property. + // Write should never return false + if (!meta_property.write(pObject, value)) + logger()->warn("Unxpected error result from QMetaProperty.write()"); + } + + + void Factory::doUnregisterAppender(const QString &rAppenderClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mAppenderRegistry.contains(rAppenderClassName)) + { + logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName); + return; + } + mAppenderRegistry.remove(rAppenderClassName); + } + + + void Factory::doUnregisterFilter(const QString &rFilterClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mFilterRegistry.contains(rFilterClassName)) + { + logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName); + return; + } + mFilterRegistry.remove(rFilterClassName); + } + + + void Factory::doUnregisterLayout(const QString &rLayoutClassName) + { + QMutexLocker locker(&mObjectGuard); + + if (!mLayoutRegistry.contains(rLayoutClassName)) + { + logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName); + return; + } + mLayoutRegistry.remove(rLayoutClassName); + } + + + void Factory::registerDefaultAppenders() + { + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender); + mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender); + mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender); + } + + + void Factory::registerDefaultFilters() + { + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter); + mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter); + mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter); + } + + + void Factory::registerDefaultLayouts() + { + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout); + mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout); + mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout); + } + + + bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject) + { + // Validate: + // - No null object pointer + // - No empty property name + // - Property exists on the object (QT or Java name) + // - Property is readable + // - Property is writable + + const char *p_context = "Log4Qt::Factory"; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"), + CONFIGURATOR_PROPERTY_ERROR, + p_context); + + if (!pObject) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + if (rProperty.isEmpty()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"), + 0, + p_context); + e.addCausingError(ce); + logger()->error(e); + return false; + } + const QMetaObject *p_meta_object = pObject->metaObject(); + QString property = rProperty; + int i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + // Try name with lower case first character. Java properties names + // start upper case + property[0] = property[0].toLower(); + i = p_meta_object->indexOfProperty(property.toLatin1()); + if (i < 0) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + } + rMetaProperty = p_meta_object->property(i); + if (!rMetaProperty.isWritable()) + { + LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"), + 0, + p_context); + ce << property + << QString::fromLatin1(pObject->metaObject()->className()); + e.addCausingError(ce); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Factory &rFactory) + { + debug.nospace() << "Factory(" + << "appenderfactories:" << rFactory.registeredAppenders() + << "filterfactories:" << rFactory.registeredFilters() + << "layoutfactories:" << rFactory.registeredLayouts() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt + diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/factory.h b/GCV-3.6.1-T4/src/log4qt/helpers/factory.h new file mode 100644 index 0000000..dfe4bfa --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/factory.h @@ -0,0 +1,443 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: factory.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_FACTORY_H +#define LOG4QT_HELPERS_FACTORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Appender; + class Filter; + class Layout; + + /*! + * \brief The class Factory provides factories for Appender, Filter and + * Layout objects. + * + * The functions createAppender(), createFilter() and createLayout() + * allow to create objects by specifying their class names. By default + * all classes of the package are recognised with their Log4j and Log4Qt + * classanmes. For example an object of the class FileAppender can be + * craeted using "org.apache.log4j.FileAppender" or "Log4Qt::FileAppender". + * Additional classes can be registered using registerAppender(), + * registerFilter() and registerLayout(). + * + * An QObject property can be set from a string value with + * setObjectProperty(). The function handles the required error checking + * and type conversion. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa PropertyConfigurator + */ + class Factory + { + public: + /*! + * Prototype for an Appender factory function. The function creates + * an Appender object on the heap and returns a pointer to it. + * + * \sa registerAppender(), createAppender() + */ + typedef Appender *(*AppenderFactoryFunc)(); + + /*! + * Prototype for a Filter factory function. The function creates + * a Filter object on the heap and returns a pointer to it. + * + * \sa registerFilter(), createFilter() + */ + typedef Filter *(*FilterFactoryFunc)(); + + /*! + * Prototype for a Layout factory function. The function creates + * a Layout object on the heap and returns a pointer to it. + * + * \sa registerLayout(), createLayout() + */ + typedef Layout *(*LayoutFactoryFunc)(); + + private: + Factory(); + Factory(const Factory &rOther); // Not implemented + // virtual ~Factory(); // Use compiler default + Factory &operator=(const Factory &rOther); // Not implemented + + public: + /*! + * Creates an object for the class \a rAppenderClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerAppender(), unregisterAppender(), registeredAppenders() + */ + static Appender *createAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Appender *createAppender(const char *pAppenderClassName); + + /*! + * Creates an object for the class \a rFilterClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerFilter(), unregisterFilter(), registeredFilters() + */ + static Filter *createFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Filter *createFilter(const char *pFilterClassName); + + /*! + * Creates an object for the class \a rLayoutClassName on the heap + * and returns a pointer to it. If the class has no registered factory + * function a null pointer is returned. + * + * \sa registerLayout(), unregisterLayout(), registeredLayouts() + */ + static Layout *createLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static Layout *createLayout(const char *pLayoutClassName); + + /*! + * Returns the Factory instance. + */ + static Factory *instance(); + + /*! + * Registers the Appender factory function \a pAppenderFactoryFunc + * for the class \a rAppenderClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pAppenderFactoryFunc. + * + * \sa unregisterAppender(), registeredAppenders(), createAppender() + */ + static void registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + + /*! + * Registers the Filter factory function \a pFilterFactoryFunc + * for the class \a rFilterClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pFilterFactoryFunc. + * + * \sa unregisterFilter(), registeredFilters(), createFilter() + */ + static void registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + + /*! + * Registers the Layout factory function \a pLayoutFactoryFunc + * for the class \a rLayoutClassName. If a registered factory + * function exists for the class, it is replaced with + * \a pLayoutFactoryFunc. + * + * \sa unregisterLayout(), registeredLayout(), createLayout() + */ + static void registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + + /*! + * Returns a list of the class names for registered Appender factory + * functions. + * + * \sa registerAppender(), unregisterAppender() + */ + static QStringList registeredAppenders(); + + /*! + * Returns a list of the class names for registered Filter factory + * functions. + * + * \sa registerFilter(), unregisterFilter() + */ + static QStringList registeredFilters(); + + /*! + * Returns a list of the class names for registered Layout factory + * functions. + * + * \sa registerLayout(), unregisterLayout() + */ + static QStringList registeredLayouts(); + + /*! + * Sets the property \a rProperty of the object \a pObject to the + * value \a rValue. The function will test that the property + * \a rProperty is writeable and of a type the function can convert to. + * The types bool, int, Level and QString are supported. + * + * \sa OptionConverter + */ + static void setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue); + + /*! + * Unregisters the Appender factory function for the class + * \a rAppenderClassName. + * + * \sa registerAppender(), registeredAppenders() + */ + static void unregisterAppender(const QString &rAppenderClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterAppender(const char *pAppenderClassName); + + /*! + * Unregisters the Filter factory function for the class + * \a rFilterClassName. + * + * \sa registerFilter(), registeredFilters() + */ + static void unregisterFilter(const QString &rFilterClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterFilter(const char *pFilterClassName); + + /*! + * Unregisters the Layout factory function for the class + * \a rLayoutClassName. + * + * \sa registerLayout(), registeredLayouts() + */ + static void unregisterLayout(const QString &rLayoutClassName); + + /*! + * This is an overloaded member function, provided for convenience. + */ + static void unregisterLayout(const char *pLayoutClassName); + + private: + Appender *doCreateAppender(const QString &rAppenderClassName); + Filter *doCreateFilter(const QString &rFilterClassName); + Layout *doCreateLayout(const QString &rLayoutClassName); + void doRegisterAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc); + void doRegisterFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc); + void doRegisterLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc); + void doSetObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue); + void doUnregisterAppender(const QString &rAppenderClassName); + void doUnregisterFilter(const QString &rFilterClassName); + void doUnregisterLayout(const QString &rLayoutClassName); + void registerDefaultAppenders(); + void registerDefaultFilters(); + void registerDefaultLayouts(); + bool validateObjectProperty(QMetaProperty &rMetaProperty, + const QString &rProperty, + QObject *pObject); + + private: + mutable QMutex mObjectGuard; + QHash mAppenderRegistry; + QHash mFilterRegistry; + QHash mLayoutRegistry; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Factory + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Factory(appenderfactories:("Log4Qt::DebugAppender", "Log4Qt::NullAppender", + * "Log4Qt::ConsoleAppender", "org.apache.log4j.varia.DebugAppender", + * "org.apache.log4j.FileAppender", "org.apache.log4j.RollingFileAppender", + * "org.apache.log4j.DailyRollingFileAppender", + * "org.apache.log4j.varia.ListAppender", + * "org.apache.log4j.varia.NullAppender", + * "Log4Qt::FileAppender", "org.apache.log4j.ConsoleAppender", + * "Log4Qt::DailyRollingFileAppender", "Log4Qt::ListAppender", + * "Log4Qt::RollingFileAppender") filterfactories: + * ("Log4Qt::DenyAllFilter", "Log4Qt::StringMatchFilter", + * "Log4Qt::LevelRangeFilter", "org.apache.log4j.varia.DenyAllFilter", + * "org.apache.log4j.varia.LevelRangeFilter", + * "org.apache.log4j.varia.StringMatchFilter", "Log4Qt::LevelMatchFilter", + * "org.apache.log4j.varia.LevelMatchFilter") layoutfactories: + * ("org.apache.log4j.SimpleLayout", "Log4Qt::PatternLayout", + * "Log4Qt::SimpleLayout", "org.apache.log4j.TTCCLayout", + * "Log4Qt::TTCCLayout", "org.apache.log4j.PatternLayout") ) + * + * \sa QDebug, Factory::logManager() + */ + QDebug operator<<(QDebug debug, + const Factory &rFactory); +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender *Factory::createAppender(const QString &rAppenderClassName) + { return instance()->doCreateAppender(rAppenderClassName); } + + inline Appender *Factory::createAppender(const char *pAppenderClassName) + { return instance()->doCreateAppender(QLatin1String(pAppenderClassName)); } + + inline Filter *Factory::createFilter(const QString &rFilterClassName) + { return instance()->doCreateFilter(rFilterClassName); } + + inline Filter *Factory::createFilter(const char *pFilterClassName) + { return instance()->doCreateFilter(QLatin1String(pFilterClassName)); } + + inline Layout *Factory::createLayout(const QString &rLayoutClassName) + { return instance()->doCreateLayout(rLayoutClassName); } + + inline Layout *Factory::createLayout(const char *pLayoutClassName) + { return instance()->doCreateLayout(QLatin1String(pLayoutClassName)); } + + inline void Factory::registerAppender(const QString &rAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(rAppenderClassName, pAppenderFactoryFunc); } + + inline void Factory::registerAppender(const char *pAppenderClassName, + AppenderFactoryFunc pAppenderFactoryFunc) + { instance()->doRegisterAppender(QLatin1String(pAppenderClassName), pAppenderFactoryFunc); } + + inline void Factory::registerFilter(const QString &rFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(rFilterClassName, pFilterFactoryFunc); } + + inline void Factory::registerFilter(const char *pFilterClassName, + FilterFactoryFunc pFilterFactoryFunc) + { instance()->doRegisterFilter(QLatin1String(pFilterClassName), pFilterFactoryFunc); } + + inline void Factory::registerLayout(const QString &rLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(rLayoutClassName, pLayoutFactoryFunc); } + + inline void Factory::registerLayout(const char *pLayoutClassName, + LayoutFactoryFunc pLayoutFactoryFunc) + { instance()->doRegisterLayout(QLatin1String(pLayoutClassName), pLayoutFactoryFunc); } + + inline QStringList Factory::registeredAppenders() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mAppenderRegistry.keys(); } + + inline QStringList Factory::registeredFilters() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mFilterRegistry.keys(); } + + inline QStringList Factory::registeredLayouts() + { QMutexLocker locker(&instance()->mObjectGuard); + return instance()->mLayoutRegistry.keys(); } + + inline void Factory::setObjectProperty(QObject *pObject, + const QString &rProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, rProperty, rValue); } + + inline void Factory::setObjectProperty(QObject *pObject, + const char *pProperty, + const QString &rValue) + { instance()->doSetObjectProperty(pObject, QLatin1String(pProperty), rValue); } + + inline void Factory::unregisterAppender(const QString &rAppenderClassName) + { instance()->doUnregisterAppender(rAppenderClassName); } + + inline void Factory::unregisterAppender(const char *pAppenderClassName) + { instance()->doUnregisterAppender(QLatin1String(pAppenderClassName)); } + + inline void Factory::unregisterFilter(const QString &rFilterClassName) + { instance()->doUnregisterFilter(rFilterClassName); } + + inline void Factory::unregisterFilter(const char *pFilterClassName) + { instance()->doUnregisterFilter(QLatin1String(pFilterClassName)); } + + inline void Factory::unregisterLayout(const QString &rLayoutClassName) + { instance()->doUnregisterLayout(rLayoutClassName); } + + inline void Factory::unregisterLayout(const char *pLayoutClassName) + { instance()->doUnregisterLayout(QLatin1String(pLayoutClassName)); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Factory, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_FACTORY_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.cpp new file mode 100644 index 0000000..783929e --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/initialisationhelper.h" + +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: InitialisationHelper + **************************************************************************/ + + + InitialisationHelper::InitialisationHelper() : + mStartTime(DateTime::currentDateTime().toMilliSeconds()), + mEnvironmentSettings() + { + doRegisterTypes(); + doInitialiseEnvironmentSettings(); + } + + + InitialisationHelper::~InitialisationHelper() + { + Q_ASSERT_X(false, "InitialisationHelper::~InitialisationHelper()", "Unexpected destruction of singleton object"); + } + + + LOG4QT_IMPLEMENT_INSTANCE(InitialisationHelper) + + + void InitialisationHelper::doInitialiseEnvironmentSettings() + { + // Is Process::systemEnvironment() safe to be used before a QCoreApplication + // object has been created? + + QStringList setting_keys; + setting_keys << QLatin1String("Debug"); + setting_keys << QLatin1String("DefaultInitOverride"); + setting_keys << QLatin1String("Configuration"); + setting_keys << QLatin1String("ConfiguratorClass"); + + QHash env_keys; + QString entry; + Q_FOREACH(entry, setting_keys) + env_keys.insert(QString::fromLatin1("log4qt_").append(entry).toUpper(), entry); + + QStringList sys_env = QProcess::systemEnvironment(); + Q_FOREACH(entry, sys_env) + { + int i = entry.indexOf(QLatin1Char('=')); + if (i == -1) + continue; + QString key = entry.left(i); + QString value = entry.mid(i + 1).trimmed(); + if (env_keys.contains(key)) + mEnvironmentSettings.insert(env_keys.value(key), value); + } + } + + + void InitialisationHelper::doRegisterTypes() + { + qRegisterMetaType("Log4Qt::LogError"); + qRegisterMetaType("Log4Qt::Level"); + qRegisterMetaType("Log4Qt::LoggingEvent"); + + #ifndef QT_NO_DATASTREAM + qRegisterMetaTypeStreamOperators("Log4Qt::LogError"); + qRegisterMetaTypeStreamOperators("Log4Qt::Level"); + qRegisterMetaTypeStreamOperators("Log4Qt::LoggingEvent"); + #endif + } + + + QString InitialisationHelper::doSetting(const QString &rKey, + const QString &rDefault) const + { + if (mEnvironmentSettings.contains(rKey)) + return mEnvironmentSettings.value(rKey); + + if (QCoreApplication::instance()) + { + QSettings s; + s.beginGroup(QLatin1String("Log4Qt")); + return s.value(rKey, rDefault).toString().trimmed(); + } + else + return rDefault; + } + + + bool InitialisationHelper::staticInitialisation() + { + instance(); + return true; + } + + + bool InitialisationHelper::msStaticInitialisation = staticInitialisation(); + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper) + { + Q_UNUSED(rInitialisationHelper); + debug.nospace() << "InitialisationHelper(" + << "starttime:" << InitialisationHelper::startTime() + << "(" << DateTime::fromMilliSeconds(InitialisationHelper::startTime()) << ")" + << "environmentsettings:" << InitialisationHelper::environmentSettings() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.h b/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.h new file mode 100644 index 0000000..95b370d --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/initialisationhelper.h @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: initialisationhelper.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H +#define LOG4QT_HELPERS_INITIALISATIONHELPER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QMutex; + +namespace Log4Qt +{ + /*! + * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that + * returns a pointer to a singleton object of the type \a TYPE. + * + * The macro uses a static variable to store a pointer to the singleton + * object. On the first invocation an object of the type \a TYPE is created + * on the heap and the pointer is set. Any further invocations will return + * the stored pointer. If multiple threads are accessing the function + * without the pointer being set, each thread will create an object of the + * type \a TYPE. The threads that find the pointer already been set will + * delete their object. The singleton object will not be deleted during static + * de-initialisation. + * + * The following example uses a global global mutex object to synchronise + * access to a static member variable. + * + * \code + * #file: myclass.h + * + * class MyClass + * { + * public: + * MyClass(); + * ~MyClass(); + * private: + * static qint64 msObjectCount; + * } + * \endcode + * \code + * #file: myclass.cpp + * + * #include myclass.h + * + * LOG4QT_GLOBAL_STATIC(QMutex, class_guard) + * + * MyClass::MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount++; + * } + * + * MyClass::~MyClass() + * { + * QMutexLocker(class_guard()); + * msObjectCount--; + * } + * + * qint64 MyClass::msObjectCount = 0; + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static volatile TYPE *sp_global_static_##FUNCTION = 0; \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return const_cast(sp_global_static_##FUNCTION); \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION; \ + } +#else + #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \ + static QBasicAtomicPointer sp_global_static_##FUNCTION = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *FUNCTION() \ + { \ + if (!sp_global_static_##FUNCTION.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \ + p_temp)) \ + delete p_temp; \ + } \ + return sp_global_static_##FUNCTION.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a + * singleton class \a TYPE. + * + * The function works like the one created by + * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC". + * + * The following example illustrates how to use the macro to create a + * singleton class: + * + * \code + * #file: mysingleton.h + * + * class MySingleton + * { + * private: + * MySingleton(); + * ~MySingleton(); + * public: + * MySingleton *instance(); + * } + * \endcode + * \code + * #file: mysingleton.cpp + * + * #include mysingleton.h + * + * MySingleton::MySingleton() + * {} + * + * MySingleton::~MySingleton() + * {} + * + * LOG4QT_IMPLEMENT_INSTANCE(MySingleton) + * + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC", + * \ref Log4Qt::InitialisationHelper "InitialisationHelper" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static TYPE *sp_singleton_##TYPE = 0; \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \ + 0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE; \ + } +#else + #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \ + static QBasicAtomicPointer sp_singleton_##TYPE = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + TYPE *TYPE::instance() \ + { \ + if (!sp_singleton_##TYPE.loadAcquire()) \ + { \ + TYPE *p_temp = new TYPE; \ + if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \ + delete p_temp; \ + } \ + return sp_singleton_##TYPE.loadAcquire(); \ + } +#endif + + /*! + * \brief The class InitialisationHelper performs static initialisation + * tasks. + * + * The InitialisationHelper is either created on the first call or through + * static initialisation. It will capture the programs startup time, + * which can be retrieved using startTime(). The system environment + * is analysed for package related definitions. The result is available + * over environmentSettings(). The packages custom types are registered with + * the Qt type system. + * + * Settings for the package can be retrieved using setting(). Two macros + * are available to help with the creation of singletons / global static + * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and + * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"). + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Init "Initialization procedure", + */ + class InitialisationHelper + { + private: + InitialisationHelper(); + InitialisationHelper(const InitialisationHelper &rOther); // Not implemented + virtual ~InitialisationHelper(); + InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented + + public: + + /*! + * Returns a hash with the settings retrieved from the system + * environment on startup. + * + * The following table shows the environment variables taken into + * account and the setting key used for them. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Environment variable Setting key
LOG4QT_DEBUG Debug
LOG4QT_DEFAULTINITOVERRIDE DefaultInitOverride
LOG4QT_CONFIGURATION Configuration
LOG4QT_CONFIGURATORCLASS ConfiguratorClass
+ * + * \sa \ref Env "Environment Variables", + * setting() + */ + static QHash environmentSettings(); + + /*! + * Returns the InitialisationHelper instance. + */ + static InitialisationHelper *instance(); + + /*! + * Returns the value for the setting \a rKey or \a rDefault, if it is + * not defined. + * + * A setting can be either defined by an environment variable or by a + * key in the application setting. The function will first test the + * settings made by environment variables for the key \a rKey using + * environmentSettings(). If the key is not present and a + * QCoreApplication exists, the application settings are tested for + * the key \a rKey in the group \c %Log4Qt. + * + * The following setting exists: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Setting key Description
Debug The variable controls the Level value for the logger + * LogManager::logLogger(). If the value is a valid Level string, + * the level for the logger is set to the level. If the value is not + * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used. + * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used.
DefaultInitOverride The variable controls the \ref Init "initialization procedure" + * performed by the \ref LogManager "LogManager" on startup. + * If it is set to any other value then \c false the \ref Init + * "initialization procedure" is skipped.
Configuration Specifies the configuration file used for initialising the package.
ConfiguratorClass Specifies the configurator class used for initialising the package.
+ * + * \sa environmentSettings(), \ref Env "Environment Variables", + * \ref Init "Initialization procedure", + * LogManager::configureLogLogger(), LogManager::startup() + */ + static QString setting(const QString &rKey, + const QString &rDefault = QString()); + + /*! + * Returns the start time of the program as the number of milliseconds + * that have passed since 1970-01-01T00:00:00,000, Coordinated + * Universal Time (Qt::UTC). + * + * \sa DateTime::fromMilliSeconds(), + * DateTime::toMilliSeconds() + */ + static qint64 startTime(); + + private: + void doInitialiseEnvironmentSettings(); + void doRegisterTypes(); + QString doSetting(const QString &rKey, + const QString &rDefault) const; + static bool shutdown(); + static bool staticInitialisation(); + + private: + // QMutex mObjectGuard; + const qint64 mStartTime; + QHash mEnvironmentSettings; + static bool msStaticInitialisation; + +#ifndef QT_NO_DEBUG_STREAM + // Needs to be friend to access details + friend QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates InitialisationHelper + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %InitialisationHelper(InitialisationHelper(starttime:1193883677438( + * QDateTime("Wed Oct 31 21:21:17 2007") ) + * environmentsettings: QHash(("configuration", "\myapp.log4j") + * ("Debug", "DEBUG")) ) ) + * + * \sa QDebug, InitialisationHelper::logManager() + */ + QDebug operator<<(QDebug debug, + const InitialisationHelper &rInitialisationHelper); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QHash InitialisationHelper::environmentSettings() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mEnvironmentSettings; } + + inline QString InitialisationHelper::setting(const QString &rKey, + const QString &rDefault) + { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const + return instance()->doSetting(rKey, rDefault); } + + inline qint64 InitialisationHelper::startTime() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mStartTime; } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default + + +#endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logerror.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/logerror.cpp new file mode 100644 index 0000000..f78d2ab --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logerror.cpp @@ -0,0 +1,354 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + *****************************************************************************/ + + +#include "log4qt/helpers/logerror.h" + +#include +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + typedef QThreadStorage ThreadError; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(ThreadError, thread_error) + + + + /************************************************************************** + * Class implementation: LogError + **************************************************************************/ + + + LogError::LogError() : + mCode(0), + mContext(), + mMessage(), + mSymbol(), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const QString &rMessage, + int code, + const QString &rSymbol, + const QString &rContext) : + mCode(code), + mContext(rContext), + mMessage(cleanMessage(rMessage)), + mSymbol(rSymbol), + mArgs(), + mCausingErrors() + { + } + + + LogError::LogError(const char *pMessage, + int code, + const char *pSymbol, + const char *pContext, + Encoding encoding) : + mCode(code), + mContext(QString::fromLatin1(pContext)), + mMessage(), + mSymbol(QString::fromLatin1(pSymbol)), + mArgs(), + mCausingErrors() + { + switch(encoding) + { + case LATIN1: + mMessage = QString::fromLatin1(pMessage); + break; + case CODECFORTR: +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + mMessage = QTextCodec::codecForTr()->toUnicode(pMessage); +#else + mMessage = QString::fromUtf8(pMessage); +#endif + break; + case UNICODEUTF8: + mMessage = QString::fromUtf8(pMessage); + break; + default: + Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant"); + mMessage = QString::fromLatin1(pMessage); + } + mMessage = cleanMessage(mMessage); + + if (mSymbol == QString::number(mCode)) + mSymbol.clear(); + } + + + QString LogError::translatedMessage() const + { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0, QCoreApplication::UnicodeUTF8); +#else + return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0); +#endif + } + + + LogError LogError::lastError() + { + if (!thread_error()->hasLocalData()) + return LogError(); + else + return *thread_error()->localData(); + } + + + void LogError::setLastError(const LogError &rLogError) + { + if (!thread_error()->hasLocalData()) + thread_error()->setLocalData(new LogError); + + *thread_error()->localData() = rLogError; + } + + + QString LogError::toString() const + { + QString result = messageWithArgs(); + + QString context_symbol = mContext; + if (!context_symbol.isEmpty() && !mSymbol.isEmpty()) + context_symbol.append(QLatin1String("::")); + context_symbol.append(mSymbol); + + if (!context_symbol.isEmpty() || mCode) + { + result.append(QLatin1String(" (")); + if (!context_symbol.isEmpty()) + result.append(context_symbol); + if (!context_symbol.isEmpty() && mCode) + result.append(QLatin1String(", ")); + if (mCode) + result.append(QString::number(mCode)); + result.append(QLatin1String(")")); + } + + if (!mCausingErrors.isEmpty()) + { + QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString(); + int i = 1; + while (i < mCausingErrors.count()) + { + causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString()); + i++; + } + result.append(causing_errors_str); + } + + return result; + } + + + QString LogError::insertArgs(const QString &rMessage) const + { + QString result; + + /* + + // Don't use a loop to be able to handle arguments that conatin strings + // like %1. + // Using this method only 9 arguments can be handled as the %1 + // in %11 gets also replaced with the first argument. + + switch (mArgs.count()) + { + case 0: + break; + case 1: + result = rMessage.arg(mArgs.at(0)); + break; + case 2: + result = rMessage.arg(mArgs.at(0), mArgs.at(1)); + break; + case 3: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2)); + break; + case 4: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3)); + break; + case 5: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4)); + break; + case 6: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5)); + break; + case 7: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6)); + break; + case 8: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7)); + break; + default: + result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8)); + break; + } + + if (mArgs.count() > 9) + { + int i = 9; + while(i < mArgs.count()) + { + result = result.arg(mArgs.at(i)); + i++; + } + } + */ + + result = rMessage; + QVariant arg; + Q_FOREACH(arg, mArgs) + result = result.arg(arg.toString()); + return result; + } + + + QString LogError::cleanMessage(const QString &rMessage) + { + if (rMessage.isEmpty()) + return rMessage; + + QString result = rMessage; + if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.')) + result = rMessage.left(rMessage.size() - 1); + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLogError.mCode + << rLogError.mContext + << rLogError.mMessage + << rLogError.mSymbol + << rLogError.mArgs + << rLogError.mCausingErrors; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString level; + QString logger; + stream >> rLogError.mCode + >> rLogError.mContext + >> rLogError.mMessage + >> rLogError.mSymbol + >> rLogError.mArgs + >> rLogError.mCausingErrors; + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogError &rLogError) + { + // Escape % sign + QString message = rLogError.message(); + message.replace(QLatin1String("%"), QLatin1String("%%")); + + debug.nospace() << "LogError(" + << "code:" << rLogError.code() << " " + << "context:" << rLogError.context() << " " + << "message:" << message << " " + << "symbol:" << rLogError.symbol() << " " + << "args:" << rLogError.args() + << "translatedMessage:" << rLogError.translatedMessage() + << ")"; + return debug.maybeSpace(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logerror.h b/GCV-3.6.1-T4/src/log4qt/helpers/logerror.h new file mode 100644 index 0000000..06d1a67 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logerror.h @@ -0,0 +1,550 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logerror.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGERROR_H +#define LOG4QT_LOGERROR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + /*! + * Creates an LogError object with the error message \a message, the error + * code \a code and the context \a context. The symbol of the error is + * set to \a code as string value. + * + * The following example logs an error, if a character is not a digit. + * + * \code + * if (!c.isDigit()) + * { + * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + * LAYOUT_EXPECTED_DIGIT_ERROR, + * "Log4Qt::PatternFormatter"); + * e << QString(c); + * logger()->error(e); + * } + * \endcode + */ + #define LOG4QT_ERROR(message, code, context) \ + LogError(message, code, #code, context) + + /*! + * Creates an LogError object with the error message \a message and the + * error code \a code. The symbol of the error is set to \a code as string + * value. The context is set to the class name of the current object. The + * current objects class must be derived from QObject. + * + * The following example handles an error while opening a file. + * + * \code + * if (!mpFile->open(mode)) + * { + * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), + * APPENDER_OPENING_FILE_ERROR); + * e << mFileName << name(); + * e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + * logger()->error(e); + * return; + * } + * \endcode + */ + #define LOG4QT_QCLASS_ERROR(message, code) \ + LogError(message, code, #code, this->metaObject()->className()) + + /*! + * \brief The class LogError represents an error. + * + * The class error allows storing error information in a structured way. + * The error message is stored separately from the information that may be + * substituted into the message string. This way it is possible to access + * all information after the error has been raised. It also allows to + * translate the error at a later point in time or to get a translated and + * a not translated error text (e.g. translated for the UI and not + * translated for a log). + * + * The message is accessed using message() and setMessage(). Arguments for + * the message can be added using addArg() or operator<<(). The arguments + * can be retrieved using args(). The message with substituted arguments + * is returned by messageWithArgs(). + * + * An error code can be set as integer value code() and/or a symbolic value + * symbol(). + * + * To allow the translation of the message the error stores the translation + * context (context(), setContext()). The translated message can be accessed + * using translatedMessage() or using translatedMessageWithArgs(), if it + * should contain the arguments. + * + * An error can have one or more related errors that caused it. An error is + * related using addCausingError(). All causing errors can be retrieved using + * causingErrors(). + * + * A per thread error can be maintained using lastError() and setLastError(). + * + * There are two macros avaiable to simplify the error creation. The macro + * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived + * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * is used with classes derived from QObject. + */ + class LogError + { + public: + + /*! + * The enum Encoding defines the 8-bit encoding of a character string + * arguments to \ref LogError::LogError(const char *, int, const char *, + * const char *, Encoding) "LogError::LogError()". + * + * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()" + */ + enum Encoding + { + /*! LATIN-1 */ + LATIN1, + /*! + * The encoding specified by QTextCodec::codecForTr() + * (Latin-1 if none has been set). + */ + CODECFORTR, + /*! UTF-8 */ + UNICODEUTF8 + }; + Q_ENUMS(Encoding) + + /*! + * Creates an empty error. The error code is set to 0 and all other + * members are set to be empty. + * + * \sa isEmpty() + */ + LogError(); + + /*! + * Creates an error with the Message \a rMessage and the error code + * \a code. The symbol for the error code is set to \a rSymbol and the + * context to \a rContext. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requested. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const QString &rMessage, + int code = 0, + const QString &rSymbol = QString(), + const QString &rContext = QString()); + + /*! + * Creates an error with the Message \a pMessage and the error code + * \a code. The symbol for the error code is set to \a pSymbol and the + * context to \a pContext. + * + * \a encoding specifies the encoding of \a pMessage. \a pSymbol and + * \a pContext are expected to be Latin-1. + * + * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" + * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR" + * the function tests, if \a pSymbol is the string representation of + * \a code. If it is, the symbol is set to be empty. Otherwise symbol + * is set to \a pSymbol. + * + * \sa translatedMessage(), translatedMessageWithArgs() + */ + LogError(const char *pMessage, + int code = 0, + const char *pSymbol = 0, + const char *pContext = 0, + Encoding encoding = LATIN1); + + // LogError(const LogError &rOther); // Use compiler default + // virtual ~LogError(); // Use compiler default + // LogError &operator=(const LogError &rOther); // Use compiler default + + /*! + * Returns the error code. + * + * \sa setCode() + */ + int code() const; + + /*! + * Returns the context for the error. + * + * \sa setContext() + */ + QString context() const; + + /*! + * Returns the error message. + * + * \sa setMessage() + */ + QString message() const; + + /*! + * Returns the symbol for the error code. + * + * \sa setSymbol() + */ + QString symbol() const; + + /*! + * Returns the translated error message. + * + * The translated message is created by calling + * QCoreApplication::translate() using context().toLatin1() as + * context and message.toUtf8() as message. + * + * \sa translatedMessageWithArgs() + */ + QString translatedMessage() const; + + /*! + * Sets the error code to \a code. + * + * \sa code() + */ + void setCode(int code); + + /*! + * Sets the context to \a rClassName. + * + * \a rContext must be string that can be converted to Latin-1. The + * Latin-1 representation of the string is used with + * QApplication::translate(), if a translation for \a rMessage is + * requestd. + * + * \sa context(), translatedMessage(), translatedMessageWithArgs() + */ + void setContext(const QString &rClassName); + + /*! + * Sets the error message to \a rMessage + * + * \sa message() + */ + void setMessage(const QString &rMessage); + + /*! + * Sets the symbol for the error code to \a rSymbol. + * + * \sa symbol() + */ + void setSymbol(const QString &rSymbol); + + /*! + * Returns the last error set for the current thread using + * setLastError(). + * + * \note: This function is thread-safe. + * + * \sa setLastError() + */ + static LogError lastError(); + + /*! + * Sets the last error for the current thread to \a rLogError. + * + * \note: This function is thread-safe. + * + * \sa lastError() + */ + static void setLastError(const LogError &rLogError); + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa operator<<(), args(), clearArgs() + */ + LogError &addArg(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &addArg(const QString &rArg); + + /*! + * Appends \a rLogError to the list of causing errors and returns a + * reference to this error. + * + * \sa causingErrors(), clearCausingErrors() + */ + LogError &addCausingError(const LogError &rLogError); + + /*! + * Returns the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList args() const; + + /*! + * Returns the list of causing errors that have been added to this error. + * + * \sa addArg(), operator<<(), clearArgs() + */ + QList causingErrors() const; + + /*! + * Clears the list of arguments that have been added to this error. + * + * \sa addArg(), operator<<(), args() + */ + void clearArgs(); + + /*! + * Clears the list of causing errors that have been added to this error. + * + * \sa addCausingError(), causingErrors() + */ + void clearCausingErrors(); + + /*! + * Returns true, if the error code is 0 and the message is empty. + * Otherwise it returns false. + * + * \sa code(), message() + */ + bool isEmpty() const; + + /*! + * Returns the message with arguments. The arguments are incoorporated + * into the messag using QString::arg(). + * + * \sa QString::arg(), translatedMessageWithArgs() + */ + QString messageWithArgs() const; + + /*! + * Returns the translated message with arguments. The arguments are + * incoorporated into the messag using QString::arg(). + * + * \sa QString::arg(), messageWithArgs(), translatedMessage() + */ + QString translatedMessageWithArgs() const; + + /*! + * Appends \a rArg to the list of arguments and returns a reference to + * this error. + * + * \sa addArg() + */ + LogError &operator<<(const QVariant &rArg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(int arg); + + /*! + * This is an overloaded member function, provided for convenience. + */ + LogError &operator<<(const QString &rArg); + + /*! + * Returns a string representation of the error. + * + * The string has the following format: + * + * + * message (context::symbol, code): causing_error, causing_error + * + * + * If members are empty they are omitted: + * - Omit context, if empty + * - Omit symbol, if empty + * - Omit double colon with context and symbol, if both are empty + * - Omit code, if 0 + * - Omit bracket with context/symbol and code, if all are empty + * - Omit colon with causing errors, if no causing errors exist + */ + QString toString() const; + + private: + QString insertArgs(const QString &rMessage) const; + QString cleanMessage(const QString &rMessage); + + private: + int mCode; + QString mContext; + QString mMessage; + QString mSymbol; + QList mArgs; + QList mCausingErrors; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + friend QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LogError + * + * Writes the given error \a rLogError to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LogError &rLogError); + + /*! + * \relates LogError + * + * Reads an error from the given stream \a rStream into the given + * error \a rLogError, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LogError &rLogError); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogError + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LogError(code:7 context:"Log4Qt::FileAppender" + * message:"Unable to open file '%1' for appender '%2'" + * symbol:"APPENDER_OPENING_FILE_ERROR" + * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") ) + * translatedMessage: "Unable to open file '%1' for appender '%2'" ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogError &rLogError); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int LogError::code() const + { return mCode; } + + inline QString LogError::context() const + { return mContext; } + + inline QString LogError::message() const + { return mMessage; } + + inline QString LogError::symbol() const + { return mSymbol; } + + inline void LogError::setCode(int code) + { mCode = code; } + + inline void LogError::setContext(const QString &rContext) + { mContext = rContext; } + + inline void LogError::setMessage(const QString &rMessage) + { mMessage = cleanMessage(rMessage); } + + inline void LogError::setSymbol(const QString &rSymbol) + { mSymbol = rSymbol; } + + inline LogError &LogError::addArg(const QVariant &rArg) + { mArgs << rArg; return *this; } + + inline LogError &LogError::addArg(int arg) + { mArgs << QVariant(arg); return *this; } + + inline LogError &LogError::addArg(const QString &rArg) + { mArgs << QVariant(rArg); return *this; } + + inline LogError &LogError::addCausingError(const LogError &rLogError) + { mCausingErrors << rLogError; return *this; } + + inline QList LogError::args() const + { return mArgs; } + + inline void LogError::clearArgs() + { mArgs.clear(); } + + inline void LogError::clearCausingErrors() + { mCausingErrors.clear(); } + + inline QList LogError::causingErrors() const + { return mCausingErrors; } + + inline bool LogError::isEmpty() const + { return mCode || !mMessage.isEmpty(); } + + inline QString LogError::messageWithArgs() const + { return insertArgs(message()); } + + inline QString LogError::translatedMessageWithArgs() const + { return insertArgs(translatedMessage()); } + + inline LogError &LogError::operator<<(const QVariant &rArg) + { return addArg(rArg); } + + inline LogError &LogError::operator<<(int arg) + { return addArg(arg); } + + inline LogError &LogError::operator<<(const QString &rArg) + { return addArg(rArg); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LogError) +Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_ERROR_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logobject.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/logobject.cpp new file mode 100644 index 0000000..44f1121 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logobject.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobject.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObject + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LogObject &rLogObject) + { + return rLogObject.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logobject.h b/GCV-3.6.1-T4/src/log4qt/helpers/logobject.h new file mode 100644 index 0000000..97b02c5 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logobject.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobject.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_increment and q_atomic_decrement + * with QAtomicInt. + * Feb 2009, Martin Heinrich + * - Fixed a problem where the pParent parameter of the constructor + * was not passed on to the QObject constructor + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECT_H +#define LOG4QT_LOGOBJECT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include "log4qt/helpers/classlogger.h" +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# include +# ifndef Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# warning "QAtomicInt reference counting is not native. The class Log4Qt::LogObject is not thread-safe." +# endif +#endif + + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LogObject is the common base class for many classes + * in the package. + * + * The class inherits QObject to allow its subclass to be accessed using + * the Qt property system. + * + * LogObject objects provide a reference counter. A reference to the + * object is established by calling retain() and freed by calling + * release(). The object will delete itself when the reference counter + * is decremented to 0. + * + * A class specific logger can be accessed over logger(). + * + * The class also implements generic streaming to QDebug. Streaming an + * object to QDebug will invoke debug() to create class specific output. + * + * \note All the functions declared in this class are thread-safe. + * + * \sa \ref Ownership "Object ownership", + * LOG4QT_DECLARE_QCLASS_LOGGER + */ + class LogObject : public QObject + { + Q_OBJECT + + public: + /*! + * Creates a LogObject which is a child of \a pObject. + */ + LogObject(QObject *pObject = 0); + + /*! + * Destroys the LogObject. + */ + virtual ~LogObject(); + + private: + LogObject(const LogObject &rOther); // Not implemented + LogObject &operator=(const LogObject &rOther); // Not implemented + + public: + /*! + * Returns the value of the reference counter. + */ + int referenceCount() const; + + /*! + * Decrements the reference count of the object. If the reference count + * count reaches zero and the object does not have a parent the object + * is deleted. + */ + void release(); + + /*! + * Increments the reference count of the object. + */ + void retain(); + + protected: + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to + * generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif // QT_NO_DEBUG_STREAM + + /*! + * Returns a pointer to a Logger named after of the object. + * + * \sa Logger::logger(const char *pName) + */ + Logger* logger() const; + + private: +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + volatile int mReferenceCount; +#else + mutable QAtomicInt mReferenceCount; +#endif + mutable ClassLogger mLog4QtClassLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogObject + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle sub-classing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LogObject &rLogObject); + #endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LogObject::LogObject(QObject *pParent) : + QObject(pParent), + mReferenceCount() + {} + + inline LogObject::~LogObject() + {} + + inline int LogObject::referenceCount() const +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + { return mReferenceCount; } +#else + { return mReferenceCount.loadAcquire(); } +#endif + + inline void LogObject::release() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { if ((q_atomic_decrement(&mReferenceCount) == 0) && !parent()) + delete(this); } +#else + { if (!mReferenceCount.deref()) + delete(this); } +#endif + + inline void LogObject::retain() +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + { q_atomic_increment(&mReferenceCount); } +#else + { mReferenceCount.ref(); } +#endif + + inline Logger *LogObject::logger() const + { return mLog4QtClassLogger.logger(this); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogObject, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGOBJECT_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.cpp new file mode 100644 index 0000000..8084a79 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.cpp @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/logobjectptr.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LogObjectPtr + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.h b/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.h new file mode 100644 index 0000000..6a8b613 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/logobjectptr.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logobjectptr.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGOBJECTPTR_H +#define LOG4QT_LOGOBJECTPTR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +namespace Log4Qt +{ + /*! + * \brief The class LogObjectPtr implements automatic reference counting + * for LogObject objects. + */ + template + class LogObjectPtr + { + public: + /*! + * Constructs a 0 LogObject pointer. + */ + LogObjectPtr(); + + /*! + * Constructs a LogObject pointer that points to the same object then + * \a rOther. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(const LogObjectPtr &rOther); + + /*! + * Constructs a LogObject pointer that points to the object + * \a LogObject. The reference counter of the object is incremented by + * one. + */ + LogObjectPtr(T *pLogObject); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * same object that \a rOther points to. The reference counter of the + * object the LogObjectPtr pointed to before the assignment is + * decremented by one. The reference counter of the object \a rOther + * is pointing to is incremented by one. + */ + LogObjectPtr &operator=(const LogObjectPtr &rOther); + + /*! + * Destructs the object. The reference counter of the object the + * LogObjectPtr points to is decremented by one. + */ + ~LogObjectPtr(); + + /*! + * Assignment operator. Sets the LogObject pointer to point to the + * object \a pLogObject. The reference counter of the object the + * LogObjectPtr pointed to before the assignment is decremented by + * one. The reference counter of the object \a pLogObject is pointing + * to is incremented by one. + */ + LogObjectPtr &operator=(T *pLogObject); + + /*! + * Arrow operator. Returns the LogObject the object points to. + */ + T *operator->() const; + + /*! + * Dereference operator. Returns a pointer to the LogObject the + * object points to. + */ + T &operator*() const; + + /*! + * Cast operator. Cast the object to the LogObject the object points + * to. + */ + operator T*() const; + + private: + void retain() const; + void release() const; + + private: + T *mpLogObject; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + template + inline LogObjectPtr::LogObjectPtr() : + mpLogObject(0) + {} + + template + inline LogObjectPtr::LogObjectPtr(const LogObjectPtr &rOther) : + mpLogObject(rOther.mpLogObject) + { retain(); } + + template + inline LogObjectPtr::LogObjectPtr(T *pLogObject) : + mpLogObject(pLogObject) + { retain(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(const LogObjectPtr &rOther) + { rOther.retain(); + release(); + mpLogObject = rOther.mpLogObject; + return *this; } + + template + inline LogObjectPtr::~LogObjectPtr() + { release(); } + + template + inline LogObjectPtr &LogObjectPtr::operator=(T *pLogObject) + { if (pLogObject) + reinterpret_cast(pLogObject)->retain(); + release(); + mpLogObject = pLogObject; + return *this; } + + template + inline T *LogObjectPtr::operator->() const + { return mpLogObject; } + + template + inline T &LogObjectPtr::operator*() const + { return *mpLogObject; } + + template + inline LogObjectPtr::operator T*() const + { return mpLogObject; } + + template + inline void LogObjectPtr::retain() const + { if (mpLogObject) + reinterpret_cast(mpLogObject)->retain(); } + + template + inline void LogObjectPtr::release() const + { + if (mpLogObject) + reinterpret_cast(mpLogObject)->release(); + } + +} // namespace Log4Qt + + +//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); // Declare within T + + +#endif // LOG4QT_LOGOBJECTPTR_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.cpp new file mode 100644 index 0000000..c8dc969 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.cpp @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a problem were OptionConverter::toBoolean would not + * return the default value, if the conversion fails. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/optionconverter.h" + +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/logger.h" +#include "log4qt/consoleappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::OptionConverter) + + + + /************************************************************************** + * Class implementation: OptionConverter + **************************************************************************/ + + + QString OptionConverter::findAndSubst(const Properties &rProperties, + const QString &rKey) + { + QString value = rProperties.property(rKey); + if (value.isNull()) + return value; + + const QString begin_subst = QLatin1String("${"); + const QString end_subst = QLatin1String("}"); + const int begin_length = begin_subst.length(); + const int end_length = end_subst.length(); + + // Don't return a null string, the null string indicates that the + // property key does not exist. + QString result = QLatin1String(""); + + int i = 0; + int begin; + int end; + while (i < value.length()) + { + begin = value.indexOf(begin_subst, i); + if (begin == -1) + { + result += value.mid(i); + i = value.length(); + } + else + { + result += value.mid(i, begin - i); + end = value.indexOf(end_subst, i + begin_length); + if (end == -1) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2."), + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + "Log4Qt::OptionConverter"); + e << begin << value; + logger()->error(e); + return result; + } + else + { + result += findAndSubst(rProperties, value.mid(begin + begin_length, end - begin - end_length - 1)); + i = end + end_length; + } + } + } + return result; + } + + + QString OptionConverter::classNameJavaToCpp(const QString &rClassName) + { + const QLatin1String java_class_delimiter("."); + const QLatin1String cpp_class_delimiter("::"); + + QString result = rClassName; + return result.replace(java_class_delimiter, cpp_class_delimiter); + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool *p_ok) + { + const QLatin1String str_true("true"); + const QLatin1String str_enabled("enabled"); + const QLatin1String str_one("1"); + const QLatin1String str_false("false"); + const QLatin1String str_disabled("disabled"); + const QLatin1String str_zero("0"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == str_true || s == str_enabled || s == str_one) + return true; + if (s == str_false || s == str_disabled || s == str_zero) + return false; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a boolean"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return false; + } + + + bool OptionConverter::toBoolean(const QString &rOption, + bool default_value) + { + bool ok; + bool result = toBoolean(rOption, &ok); + if (ok) + return result; + else + return default_value; + } + + qint64 OptionConverter::toFileSize(const QString &rOption, + bool *p_ok) + { + // - Search for unit + // - Convert characters befor unit to int + // - Error, if + // - the conversion failed + // - the value < 0 + // - there is text after the unit characters + + if (p_ok) + *p_ok = false; + QString s = rOption.trimmed().toLower(); + qint64 f = 1; + int i; + i = s.indexOf(QLatin1String("kb")); + if (i >= 0) + f = 1024; + else + { + i = s.indexOf(QLatin1String("mb")); + if (i >= 0) + f = 1024 * 1024; + else + { + i = s.indexOf(QLatin1String("gb")); + if (i >= 0) + f = 1024 * 1024 * 1024; + } + } + if (i < 0) + i = s.length(); + bool ok; + qint64 value = s.left(i).toLongLong(&ok); + if (!ok || value < 0 || s.length() > i + 2) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a file size"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + if (p_ok) + *p_ok = true; + return value * f; + } + + + int OptionConverter::toInt(const QString &rOption, + bool *p_ok) + { + int value = rOption.trimmed().toInt(p_ok); + if (*p_ok) + return value; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for an integer"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return 0; + } + + + Level OptionConverter::toLevel(const QString &rOption, + bool *p_ok) + { + bool ok; + Level level = Level::fromString(rOption.toUpper().trimmed(), &ok); + if (p_ok) + *p_ok = ok; + if (ok) + return level; + + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a level"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return level; + } + + + Level OptionConverter::toLevel(const QString &rOption, + const Level &rDefaultValue) + { + bool ok; + Level result = toLevel(rOption, &ok); + if (ok) + return result; + else + return rDefaultValue; + } + + + int OptionConverter::toTarget(const QString &rOption, + bool *p_ok) + { + const QLatin1String java_stdout("system.out"); + const QLatin1String cpp_stdout("stdout_target"); + const QLatin1String java_stderr("system.err"); + const QLatin1String cpp_stderr("stderr_target"); + + if (p_ok) + *p_ok = true; + QString s = rOption.trimmed().toLower(); + if (s == java_stdout || s == cpp_stdout) + return ConsoleAppender::STDOUT_TARGET; + if (s == java_stderr || s == cpp_stderr) + return ConsoleAppender::STDERR_TARGET; + + if (p_ok) + *p_ok = false; + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a target"), + CONFIGURATOR_INVALID_OPTION_ERROR, + "Log4Qt::OptionConverter"); + e << rOption; + logger()->error(e); + return ConsoleAppender::STDOUT_TARGET; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.h b/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.h new file mode 100644 index 0000000..dda49d2 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/optionconverter.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: optionconverter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_OPTIONCONVERTER_H +#define LOG4QT_OPTIONCONVERTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + +namespace Log4Qt +{ + class Properties; + + /*! + * \brief The class OptionConverter provides functions to convert strings + * to property values. + */ + class OptionConverter + { + private: + OptionConverter(); + OptionConverter(const OptionConverter &rOther); // Not implemented + // virtual ~OptionConverter(); // Use compiler default + OptionConverter &operator=(const OptionConverter &rOther); // Not implemented + + public: + static QString findAndSubst(const Properties &rProperties, + const QString &rKey); + + /*! + * Returns the JAVA class name \a rClassName as C++ class name by + * replacing all . characters with ::. + */ + static QString classNameJavaToCpp(const QString &rClassName); + + /*! + * Converts the option \a rOption to a boolean value. Valid strings + * for true are "true", "enabled" and "1". Valid strings + * for false are "false", "disabled" and "0". If the conversion is + * successful, the target is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and false is returned. + */ + static bool toBoolean(const QString &rOption, + bool *p_ok = 0); + + static bool toBoolean(const QString &rOption, + bool default_value); + + /*! + * Converts the option string \a rOption to a file size. The string can + * be a positive integer followed by an optional unit suffix "KB", "MB" + * or "GB". If a unit suffix is specified the the integer is + * interpreted as kilobytes, megabytes or gigabytes. If the conversion + * is successful, the size is returned and \a p_ok is set to true. + * Otherwise an error is written to the log, \a p_ok is set to false + * and 0 is returned. + */ + static qint64 toFileSize(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a integer value using + * QString::toInt(). If the conversion is successful, the integer is + * returned and \a p_ok is set to true. Otherwise an error is written + * to the log, \a p_ok is set to false and 0 is returned. + */ + static int toInt(const QString &rOption, + bool *p_ok = 0); + + /*! + * Converts the option \a rOption to a level value using + * Level::fromString(). If the conversion is successful, the level + * is returned and \a p_ok is set to true. Otherwise an error is + * written to the log, \a p_ok is set to false and a level with + * the value Level::NULL_INT is returned. + * + * \sa Level::fromString() + */ + static Level toLevel(const QString &rOption, + bool *p_ok = 0); + + static Level toLevel(const QString &rOption, + const Level &rDefaultValue); + + /*! + * Converts the option \a rOption to a ConsoleAppender::Target value. + * Valid strings for \a rOption are "System.out", "STDOUT_TARGET", + * "System.err" and "STDERR_TARGET". If the conversion is successful, + * the target is returned and \a p_ok is set to true. Otherwise an + * error is written to the log, \a p_ok is set to false and + * ConsoleAppender::STDOUT_TARGET is returned. + */ + static int toTarget(const QString &rOption, + bool *p_ok = 0); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::OptionConverter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_OPTIONCONVERTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.cpp new file mode 100644 index 0000000..1fd54f0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.cpp @@ -0,0 +1,893 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in LiteralPatternConverter::convert. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/patternformatter.h" + +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/logerror.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + /*! + * \brief The class FormattingInfo stores the formatting modifier for a + * pattern converter. + * + * \sa PatternConverter + */ + class FormattingInfo + { + public: + FormattingInfo() + { clear(); } + // FormattingInfo(const FormattingInfo &rOther); // Use compiler default + // virtual ~FormattingInfo(); // Use compiler default + // FormattingInfo &operator=(const FormattingInfo &rOther); // Use compiler default + + void clear(); + static QString intToString(int i); + + public: + int mMinLength; + int mMaxLength; + bool mLeftAligned; + }; + + + /*! + * \brief The class PatternConverter is the abstract base class for all + * pattern converters. + * + * PatternConverter handles the minimum and maximum modifier for a + * conversion character. The actual conversion is by calling the + * convert() member function of the derived class. + * + * \sa PatternLayout::format() + */ + class PatternConverter + { + public: + PatternConverter(const FormattingInfo &rFormattingInfo = FormattingInfo()) : + mFormattingInfo(rFormattingInfo) + {}; + virtual ~PatternConverter() + {}; + private: + PatternConverter(const PatternConverter &rOther); // Not implemented + PatternConverter &operator=(const PatternConverter &rOther); // Not implemented + + public: + void format(QString &rFormat, const LoggingEvent &rLoggingEvent) const; + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const = 0; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + protected: + FormattingInfo mFormattingInfo; + }; + + + /*! + * \brief The class BasicPatternConverter converts several members of a + * LoggingEvent to a string. + * + * BasicPatternConverter is used by PatternLayout to convert members that + * do not reuquire additional formatting to a string as part of formatting + * the LoggingEvent. It handles the following conversion characters: + * 'm', 'p', 't', 'x' + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class BasicPatternConverter : public PatternConverter + { + public: + enum Type { + MESSAGE_CONVERTER, + NDC_CONVERTER, + LEVEL_CONVERTER, + THREAD_CONVERTER, + }; + + public: + BasicPatternConverter(const FormattingInfo &rFormattingInfo, + Type type) : + PatternConverter(rFormattingInfo), + mType(type) + {}; + // virtual ~BasicPatternConverter(); // Use compiler default + private: + BasicPatternConverter(const BasicPatternConverter &rOther); // Not implemented + BasicPatternConverter &operator=(const BasicPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + Type mType; + }; + + + /*! + * \brief The class DatePatternConverter converts the time stamp of a + * LoggingEvent to a string. + * + * DatePatternConverter is used by PatternLayout to convert the time stamp + * of a LoggingEvent to a string as part of formatting the LoggingEvent. + * It handles the 'd' and 'r' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class DatePatternConverter : public PatternConverter + { + public: + DatePatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rFormat) : + PatternConverter(rFormattingInfo), + mFormat(rFormat) + {}; + // virtual ~DatePatternConverter(); // Use compiler default + private: + DatePatternConverter(const DatePatternConverter &rOther); // Not implemented + DatePatternConverter &operator=(const DatePatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mFormat; + }; + + + /*! + * \brief The class LiteralPatternConverter provides string literals. + * + * LiteralPatternConverter is used by PatternLayout to embed string + * literals as part of formatting the LoggingEvent. It handles string + * literals and the 'n' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LiteralPatternConverter : public PatternConverter + { + public: + LiteralPatternConverter(const QString &rLiteral) : + PatternConverter(), + mLiteral(rLiteral) + {}; + // virtual ~LiteralPatternConverter(); // Use compiler default + private: + LiteralPatternConverter(const LiteralPatternConverter &rOther); // Not implemented + LiteralPatternConverter &operator=(const LiteralPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mLiteral; + }; + + + /*! + * \brief The class LoggerPatternConverter converts the Logger name of a + * LoggingEvent to a string. + * + * LoggerPatternConverter is used by PatternLayout to convert the Logger + * name of a LoggingEvent to a string as part of formatting the + * LoggingEvent. It handles the 'c' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class LoggerPatternConverter : public PatternConverter + { + public: + LoggerPatternConverter(const FormattingInfo &rFormattingInfo, + int precision) : + PatternConverter(rFormattingInfo), + mPrecision(precision) + {}; + // virtual ~LoggerPatternConverter(); // Use compiler default + private: + LoggerPatternConverter(const LoggerPatternConverter &rOther); // Not implemented + LoggerPatternConverter &operator=(const LoggerPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + int mPrecision; + }; + + + + /*! + * \brief The class MDCPatternConverter converts the MDC data of a + * LoggingEvent to a string. + * + * MDCPatternConverter is used by PatternLayout to convert the MDC data of + * a LoggingEvent to a string as part of formatting the LoggingEvent. It + * handles the 'X' conversion character. + * + * \sa PatternLayout::format() + * \sa PatternConverter::format() + */ + class MDCPatternConverter : public PatternConverter + { + public: + MDCPatternConverter(const FormattingInfo &rFormattingInfo, + const QString &rKey) : + PatternConverter(rFormattingInfo), + mKey(rKey) + {}; + // virtual ~MDCPatternConverter(); // Use compiler default + private: + MDCPatternConverter(const MDCPatternConverter &rOther); // Not implemented + MDCPatternConverter &operator=(const MDCPatternConverter &rOther); // Not implemented + + protected: + virtual QString convert(const LoggingEvent &rLoggingEvent) const; + #ifndef QT_NO_DEBUG_STREAM + virtual QDebug debug(QDebug &rDebug) const; + #endif + + private: + QString mKey; + }; + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const FormattingInfo &rFormattingInfo); + #endif + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug, const PatternConverter &rPatternConverter); + #endif + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PatternFormatter) + + + + /************************************************************************** + * Class implementation: PatternFormatter + **************************************************************************/ + + + PatternFormatter::PatternFormatter(const QString &rPattern) : + mIgnoreCharacters(QLatin1String("CFlLM")), + mConversionCharacters(QLatin1String("cdmprtxX")), + mOptionCharacters(QLatin1String("cd")), + mPattern(rPattern), + mPatternConverters() + { + parse(); + } + + + PatternFormatter::~PatternFormatter() + { + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + delete p_converter; + } + + + QString PatternFormatter::format(const LoggingEvent &rLoggingEvent) const + { + QString result; + PatternConverter *p_converter; + Q_FOREACH(p_converter, mPatternConverters) + p_converter->format(result, rLoggingEvent); + return result; + } + + + bool PatternFormatter::addDigit(const QChar &rDigit, + int &rValue) + { + if (!rDigit.isDigit()) + return false; + + int digit_value = rDigit.digitValue(); + if (rValue > (INT_MAX - digit_value) / 10) + rValue = INT_MAX; + else + rValue = rValue * 10 + digit_value; + return true; + } + + + void PatternFormatter::createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption) + { + Q_ASSERT_X(mConversionCharacters.indexOf(rChar) >= 0, "PatternFormatter::createConverter", "Unknown conversion character" ); + + LogError e("Creating Converter for character '%1' min %2, max %3, left %4 and option '%5'"); + e << QString(rChar) + << FormattingInfo::intToString(rFormattingInfo.mMinLength) + << FormattingInfo::intToString(rFormattingInfo.mMaxLength) + << rFormattingInfo.mLeftAligned + << rOption; + logger()->trace(e); + + switch (rChar.toLatin1()) + { + case 'c': + mPatternConverters << new LoggerPatternConverter(rFormattingInfo, + parseIntegerOption(rOption)); + break; + case 'd': + { + QString option = rOption; + if (rOption.isEmpty()) + option = QLatin1String("ISO8601"); + mPatternConverters << new DatePatternConverter(rFormattingInfo, + option); + break; + } + case 'm': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::MESSAGE_CONVERTER); + break; + case 'p': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::LEVEL_CONVERTER); + break; + case 'r': + mPatternConverters << new DatePatternConverter(rFormattingInfo, + QLatin1String("RELATIVE")); + break; + case 't': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::THREAD_CONVERTER); + break; + case 'x': + mPatternConverters << new BasicPatternConverter(rFormattingInfo, + BasicPatternConverter::NDC_CONVERTER); + break; + case 'X': + mPatternConverters << new MDCPatternConverter(rFormattingInfo, + rOption); + break; + default: + Q_ASSERT_X(false, "PatternFormatter::createConverter", "Unknown pattern character"); + } + } + + + void PatternFormatter::createLiteralConverter(const QString &rLiteral) + { + logger()->trace("Creating literal LiteralConverter with Literal '%1'", + rLiteral); + mPatternConverters << new LiteralPatternConverter(rLiteral); + } + + + void PatternFormatter::parse() + { + enum State { + LITERAL_STATE, + ESCAPE_STATE, + MIN_STATE, + DOT_STATE, + MAX_STATE, + CHARACTER_STATE, + POSSIBLEOPTION_STATE, + OPTION_STATE + }; + + int i = 0; + QChar c; + char ch; + State state = LITERAL_STATE; + FormattingInfo formatting_info; + QString literal; + int converter_start = 0; + int option_start = 0; + while (i < mPattern.length()) + { + // i points to the current character + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character + // continue is used to change state without consuming the character + + c = mPattern.at(i); + ch = c.toLatin1(); + switch (state) + { + case LITERAL_STATE: + if (ch == '%') + { + formatting_info.clear(); + converter_start = i; + state = ESCAPE_STATE; + } else + literal += c; + break; + case ESCAPE_STATE: + if (ch == '%') + { + literal += c; + state = LITERAL_STATE; + } + else if (ch == 'n') + { + literal += Layout::endOfLine(); + state = LITERAL_STATE; + } + else + { + if (!literal.isEmpty()) + { + createLiteralConverter(literal); + literal.clear(); + } + if (ch == '-') + formatting_info.mLeftAligned = true; + else if (c.isDigit()) + { + formatting_info.mMinLength = c.digitValue(); + state = MIN_STATE; + } + else if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case MIN_STATE: + if (!addDigit(c, formatting_info.mMinLength)) + { + if (ch == '.') + state = DOT_STATE; + else + { + state = CHARACTER_STATE; + continue; + } + } + break; + case DOT_STATE: + if (c.isDigit()) + { + formatting_info.mMaxLength = c.digitValue(); + state = MAX_STATE; + } + else + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."), + LAYOUT_EXPECTED_DIGIT_ERROR, + "Log4Qt::PatternFormatter"); + e << QString(c); + logger()->error(e); + } + break; + case MAX_STATE: + if (!addDigit(c, formatting_info.mMaxLength)) + { + state = CHARACTER_STATE; + continue; + } + break; + case CHARACTER_STATE: + if (mIgnoreCharacters.indexOf(c) >= 0) + state = LITERAL_STATE; + else if (mOptionCharacters.indexOf(c) >= 0) + state = POSSIBLEOPTION_STATE; + else if (mConversionCharacters.indexOf(c) >= 0) + { + createConverter(c, formatting_info); + state = LITERAL_STATE; + } + else + { + logger()->warn("Invalid conversion character '%1' at %2 in pattern '%3'", + c, i, mPattern); + createLiteralConverter(mPattern.mid(converter_start, i - converter_start + 1)); + state = LITERAL_STATE; + } + break; + case POSSIBLEOPTION_STATE: + if (ch == '{') + { + option_start = i; + state = OPTION_STATE; + } + else + { + createConverter(mPattern.at(i - 1), + formatting_info); + state = LITERAL_STATE; + continue; + } + break; + case OPTION_STATE: + if (ch == '}') + { + createConverter(mPattern.at(option_start - 1), + formatting_info, + mPattern.mid(option_start + 1, i - option_start - 1)); + state = LITERAL_STATE; + } + break; + default: + Q_ASSERT_X(false, "PatternFormatter::parse()", "Unknown parsing state constant"); + state = LITERAL_STATE; + } + i++; + } + + if (state != LITERAL_STATE) + { + logger()->warn("Unexptected end of pattern '%1'", mPattern); + if (state == ESCAPE_STATE) + literal += c; + else + literal += mPattern.mid(converter_start); + } + + if (!literal.isEmpty()) + createLiteralConverter(literal); + } + + + int PatternFormatter::parseIntegerOption(const QString &rOption) + { + if (rOption.isEmpty()) + return 0; + + bool ok; + int result = rOption.toInt(&ok); + if (!ok) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option '%1' cannot be converted into an integer"), + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + "Log4Qt::PatterFormatter"); + e << rOption; + logger()->error(e); + } + if (result < 0) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option %1 isn't a positive integer"), + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + "Log4Qt::PatterFormatter"); + e << result; + logger()->error(e); + result = 0; + } + return result; + } + + + /************************************************************************** + * Class implementation: FormattingInfo + **************************************************************************/ + + + void FormattingInfo::clear() + { + mMinLength = 0; + mMaxLength = INT_MAX; + mLeftAligned = false; + }; + + + QString FormattingInfo::intToString(int i) + { + if (i == INT_MAX) + return QLatin1String("INT_MAX"); + else + return QString::number(i); + } + + + + /************************************************************************** + * Class implementation: PatternConverter + **************************************************************************/ + + + void PatternConverter::format(QString &rFormat, const LoggingEvent &rLoggingEvent) const + { + const QLatin1Char space(' '); + QString s = convert(rLoggingEvent); + + if (s.length() > mFormattingInfo.mMaxLength) + rFormat += s.left(mFormattingInfo.mMaxLength); + else if (mFormattingInfo.mLeftAligned) + rFormat += s.leftJustified(mFormattingInfo.mMinLength, space, false); + else + rFormat += s.rightJustified(mFormattingInfo.mMinLength, space, false); + } + + + + /************************************************************************** + * Class implementation: BasicPatternConverter + **************************************************************************/ + + + QString BasicPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + switch (mType) + { + case MESSAGE_CONVERTER: + return rLoggingEvent.message(); + break; + case NDC_CONVERTER: + return rLoggingEvent.ndc(); + break; + case LEVEL_CONVERTER: + return rLoggingEvent.level().toString(); + break; + case THREAD_CONVERTER: + return rLoggingEvent.threadName(); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::convert()", "Unkown type constant"); + return QString(); + } + } + + + QDebug BasicPatternConverter::debug(QDebug &rDebug) const + { + QString type; + switch (mType) + { + case MESSAGE_CONVERTER: + type = QLatin1String("MESSAGE_CONVERTER"); + break; + case NDC_CONVERTER: + type = QLatin1String("NDC_CONVERTER"); + break; + case LEVEL_CONVERTER: + type = QLatin1String("LEVEL_CONVERTER"); + break; + case THREAD_CONVERTER: + type = QLatin1String("THREAD_CONVERTER"); + break; + default: + Q_ASSERT_X(false, "BasicPatternConverter::debug()", "Unkown type constant"); + } + rDebug.nospace() << "BasicPatternConverter(" + << mFormattingInfo + << "type:" << type + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: DatePatternConverter + **************************************************************************/ + + + QString DatePatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()).toString(mFormat); + } + + + QDebug DatePatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DatePatternConverter(" + << mFormattingInfo + << "format:" << mFormat + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LiteralPatternConverter + **************************************************************************/ + + + QString LiteralPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + Q_UNUSED(rLoggingEvent); + return mLiteral; + }; + + + QDebug LiteralPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LiteralPatternConverter(" + << mFormattingInfo + << "literal:" << mLiteral + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Class implementation: LoggerPatternConverter + **************************************************************************/ + + + QString LoggerPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + if (!rLoggingEvent.logger()) + return QString(); + QString name = rLoggingEvent.logger()->name(); + if (mPrecision <= 0 || (name.isEmpty())) + return name; + + const QString separator(QLatin1String("::")); + + int i = mPrecision; + int begin = name.length(); + while ((i > 0) && (begin >= 0)) + { + begin = name.lastIndexOf(separator, begin - name.length() - 1); + i--; + } + if (begin < 0) + begin = 0; + else + begin += 2; + return name.mid(begin); + } + + + QDebug LoggerPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LoggerPatternConverter(" + << mFormattingInfo + << "precision:" << mPrecision + << ")"; + return rDebug.space(); + } + + + + /****************************************************************************** + * Class implementation: MDCPatternConverter + ******************************************************************************/ + + + QString MDCPatternConverter::convert(const LoggingEvent &rLoggingEvent) const + { + return rLoggingEvent.mdc().value(mKey); + }; + + + QDebug MDCPatternConverter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "MDCPatternConverter(" + << mFormattingInfo + << "key:" << mKey + << ")"; + return rDebug.space(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternFormatter &rPatternFormatter) + { + debug.nospace() << "PatternFormatter(" + << "pattern:" << rPatternFormatter.mPattern << " " + << "converters:("; + int i; + for (i = 0; i < rPatternFormatter.mPatternConverters.size(); i++) + { + if (i > 0) + debug.nospace() << ", "; + debug.nospace() << *rPatternFormatter.mPatternConverters.at(i); + } + debug.nospace() << ") )"; + return debug.space(); + } + #endif + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const FormattingInfo &rFormattingInfo) + { + debug.nospace() << "FormattingInfo(" + << "min:" << FormattingInfo::intToString(rFormattingInfo.mMinLength) << " " + << "max:" << FormattingInfo::intToString(rFormattingInfo.mMaxLength) << " " + << "left:" << rFormattingInfo.mLeftAligned + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const PatternConverter &rPatternConverter) + { + return rPatternConverter.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.h b/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.h new file mode 100644 index 0000000..8965e81 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/patternformatter.h @@ -0,0 +1,195 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternformatter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNFORMATTER_H +#define LOG4QT_PATTERNFORMATTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class FormattingInfo; + class PatternConverter; + class LoggingEvent; + + /*! + * \brief The class PatternFormatter formats a logging event based on a + * pattern string. + * + * The class PatternFormatter formats a LoggingEvent base on a pattern + * string. It is used by the patternLayout and TTCCLayout class to + * implement the formatting. + * + * On object construction the provided patterns tring is parsed. Based on + * the information found a chain of PatternConverter is created. Each + * PatternConverter handles a certain member of a LoggingEvent. + * + * \sa PatternLayout::format() + * \sa TTCCLayout::format() + */ + class PatternFormatter + { + public: + /*! + * Creates a PatternFormatter using a the specified \a rPattern. + */ + PatternFormatter(const QString &rPattern); + + /*! + * Destroys the PatternFormatter and all PatternConverter. + */ + virtual ~PatternFormatter(); + + private: + PatternFormatter(const PatternFormatter &rOther); // Not implemented + PatternFormatter &operator=(const PatternFormatter &rOther); // Not implemented + + public: + /*! + * Formats the given \a rLoggingEvent using the chain of + * PatternConverter created during construction from the specified + * pattern. + */ + QString format(const LoggingEvent &rLoggingEvent) const; + + private: + /*! + * If the character \a rDigit is a digit the digit is added to the + * integer \a rValue and the function returns true. Otherwise the + * function returns false. + * + * The function adds the digit by multiplying the existing value + * with ten and adding the numerical value of the digit. If the + * maximum integer value would be exceeded by the operation + * \a rValue is set to INT_MAX. + */ + bool addDigit(const QChar &rDigit, + int &rValue); + + /*! + * Creates a PatternConverter based on the specified conversion + * character \a rChar, the formatting information + * \a rFormattingInfo and the option \a rOption. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createConverter(const QChar &rChar, + const FormattingInfo &rFormattingInfo, + const QString &rOption = QString()); + + /*! + * Creates a LiteralPatternConverter with the string literal + * \a rLiteral. + * + * The PatternConverter converter is appended to the list of + * PatternConverters. + */ + void createLiteralConverter(const QString &rLiteral); + + /*! + * Parses the pattern string specified on construction and creates + * PatternConverter according to it. + */ + void parse(); + + /*! + * Parses an integer option from an option string. If the string is + * not a valid integer or the integer value is less then zero, zero + * is returned. Returns the end of line seperator for the operating + * system. + */ + int parseIntegerOption(const QString &rOption); + + private: + const QString mIgnoreCharacters; + const QString mConversionCharacters; + const QString mOptionCharacters; + QString mPattern; + QList mPatternConverters; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug, const PatternFormatter &rPatternFormatter); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PatternFormatter + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %PatternFormatter(pattern:"%r [%t] %p %c %x - %m%n" + * converters:( + * DatePatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) format: "RELATIVE" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " [" ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "THREAD_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "] " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "LEVEL_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * LoggerPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) precision: 0 ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "NDC_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " - " ) , + * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "MESSAGE_CONVERTER" ) , + * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "" ) ) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PatternFormatter &rPatternFormatter); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::PatternFormatter, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PATTERNFORMATTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/properties.cpp b/GCV-3.6.1-T4/src/log4qt/helpers/properties.cpp new file mode 100644 index 0000000..ec74978 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/properties.cpp @@ -0,0 +1,364 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/helpers/properties.h" + +#include +#include +#include +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + + /************************************************************************** + *Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties) + + + + /************************************************************************** + * Class implementation: Properties + **************************************************************************/ + + + void Properties::load(QIODevice *pDevice) + { + const QLatin1Char append_char(msEscapeChar); + + if (!pDevice) + { + logger()->warn("No device specified for load."); + return; + } + + QTextStream stream(pDevice); + QString line; + int line_number = 0; + QString property; + int property_start_line = 1; + + do { + line = trimLeft(stream.readLine()); + line_number++; + + if (!line.isEmpty() && line.at(line.length() - 1) == append_char) + property += line.left(line.length() - 1); + else + { + property += line; + parseProperty(property, property_start_line); + property.clear(); + property_start_line = line_number + 1; + } + } + while (!line.isNull()); + } + + + void Properties::load(const QSettings &rSettings) + { + QStringList keys = rSettings.childKeys(); + QString key; + Q_FOREACH(key, keys) + insert(key, rSettings.value(key).toString()); + } + + + QString Properties::property(const QString &rKey) const + { + // Null string indicates the property does not contain the key. + + if (contains(rKey)) + { + QString value = this->value(rKey); + if (value.isNull()) + return QString(QLatin1String("")); + else + return value; + } + + if (mpDefaultProperties) + return mpDefaultProperties->property(rKey); + else + return QString(); + } + + + QString Properties::property(const QString &rKey, + const QString &rDefaultValue) const + { + QString value = property(rKey); + if (value.isNull()) + return rDefaultValue; + else + return value; + } + + + QStringList Properties::propertyNames() const + { + QStringList default_keys; + if (mpDefaultProperties) + default_keys = mpDefaultProperties->propertyNames(); + + QStringList keys = this->keys(); + QString key; + Q_FOREACH(key, default_keys) + if (!keys.contains(key)) + keys << key; + + return keys; + } + + + void Properties::parseProperty(const QString &rProperty, + int line) + { + Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces"); + + enum State + { + KEY_STATE, + KEYSPACE_STATE, + SPACEVALUE_STATE, + VALUE_STATE, + KEYESCAPE_STATE, + VALUEESCAPE_STATE, + UNICODEESCAPE_STATE + }; + const QString value_escape_codes =QLatin1String(msValueEscapeCodes); + const QString value_escape_chars = QLatin1String(msValueEscapeChars); + Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map"); + const QString key_escape_codes = QLatin1String(msKeyEscapeCodes); + const QString key_escape_chars = QLatin1String(msKeyEscapeChars); + Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map"); + + if (rProperty.isEmpty()) + return; + + int i = 0; + QChar c; + char ch; + State state = KEY_STATE; + QString key; + QString value; + QString *p_string = &key; + uint ucs = 0; + int ucs_digits = 0; + while (i < rProperty.length()) + { + // i points to the current character. + // c contains the current character + // ch contains the Latin1 equivalent of the current character + // i is incremented at the end of the loop to consume the character. + // continue is used to change state without consuming the character + + c = rProperty.at(i); + ch = c.toLatin1(); + + switch (state) + { + case KEY_STATE: + if (ch == '!' || ch == '#' ) + return; + else if (c.isSpace()) + { + p_string = &value; + state = KEYSPACE_STATE; + } + else if (ch == '=' || ch == ':') + { + p_string = &value; + state = SPACEVALUE_STATE; + } + else if (ch == msEscapeChar) + state = KEYESCAPE_STATE; + else + *p_string += c; + break; + case KEYSPACE_STATE: + if (ch == '=' || ch == ':') + state = SPACEVALUE_STATE; + else if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case SPACEVALUE_STATE: + if (!c.isSpace()) + { + *p_string += c; + state = VALUE_STATE; + } + break; + case VALUE_STATE: + if (ch == msEscapeChar) + state = VALUEESCAPE_STATE; + else + *p_string += c; + break; + case KEYESCAPE_STATE: + { + int convert = key_escape_codes.indexOf(c); + if (convert >= 0) + *p_string += key_escape_chars.at(convert); + else + { + logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2", + QString(c), + line); + *p_string += c; + } + state = KEY_STATE; + break; + } + case VALUEESCAPE_STATE: + { + int convert = value_escape_codes.indexOf(c); + if (convert >= 0) + { + *p_string += value_escape_chars.at(convert); + state = VALUE_STATE; + } + else if (ch == 'u') + { + ucs = 0; + ucs_digits = 0; + state = UNICODEESCAPE_STATE; + } + else + { + logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line); + *p_string += c; + state = VALUE_STATE; + } + break; + } + case UNICODEESCAPE_STATE: + { + int hex = hexDigitValue(c); + if (hex >= 0) + { + ucs = ucs * 16 + hex; + ucs_digits++; + if (ucs_digits == 4 || i == rProperty.length() - 1) + { + *p_string += QChar(ucs); + state = VALUE_STATE; + } + } + else + { + if (ucs_digits > 0) + *p_string += QChar(ucs); + state = VALUE_STATE; + continue; + } + break; + } + default: + Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant"); + return; + } + i++; + } + + if (key.isEmpty() && !value.isEmpty()) + logger()->warn("Found value with no key in property starting at line %1", line); + + logger()->trace("Loaded property '%1' : '%2'", key, value); + insert(key, value); + } + + + int Properties::hexDigitValue(const QChar &rDigit) + { + bool ok; + int result = QString(rDigit).toInt(&ok, 16); + if (!ok) + return -1; + else + return result; + } + + + QString Properties::trimLeft(const QString &rLine) + { + int i = 0; + while (i < rLine.length() && rLine.at(i).isSpace()) + i++; + return rLine.right(rLine.length() - i); + } + + + const char Properties::msEscapeChar ='\\'; + const char *Properties::msValueEscapeCodes = "tnr\\\"\' "; + const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' "; + const char *Properties::msKeyEscapeCodes = " :="; + const char *Properties::msKeyEscapeChars = " :="; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Properties &rProperties) + { + debug.nospace() << "Properties(" + << "default:" << rProperties.defaultProperties() << " " + << "properties:" << *reinterpret_cast *>(&rProperties) + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/helpers/properties.h b/GCV-3.6.1-T4/src/log4qt/helpers/properties.h new file mode 100644 index 0000000..a9601f4 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/helpers/properties.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: properties.h + * created: September + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTIES_H +#define LOG4QT_PROPERTIES_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QIODevice; +class QSettings; + + +namespace Log4Qt +{ + /*! + * \brief The class Properties implements a JAVA property hash. + */ + class Properties : public QHash + { + public: + Properties(Properties *pDefaultProperties = 0); + // virtual ~Properties(); // Use compiler default + // Properties(const Properties &rOther); // Use compiler default + // Properties &operator=(const Properties &rOther); // Not implemented + + public: + Properties *defaultProperties() const; + QString property(const QString &rKey) const; + QString property(const QString &rKey, + const QString &rDefaultValue) const; + void setDefaultProperties(Properties *pDefault); + void setProperty(const QString &rKey, + const QString &rValue); + + // JAVA: void list(QTextStream &rTextStream); + void load(QIODevice *pDevice); + + /*! + * Reads all child keys from the QSettings object \a rSettings and + * inserts them into this object. The value is created using + * QVariant::toString(). Types that do not support toString() are + * resulting in an empty string. + * + * \code + * QSettings settings; + * settings.setValue("Package", "Full"); + * settings.setValue("Background", Qt::white); + * settings.setValue("Support", true); + * settings.setValue("Help/Language", "en_UK"); + * + * Properties properties + * properties.load(&settings) + * + * // properties (("Package", "Full"), ("Background", ""), ("Support", "true")) + * \endcode + */ + void load(const QSettings &rSettings); + + QStringList propertyNames() const; + // JAVA: void save(QIODevice *pDevice) const; + + private: + void parseProperty(const QString &rProperty, + int line); + static int hexDigitValue(const QChar &rDigit); + static QString trimLeft(const QString &rString); + + private: + Properties *mpDefaultProperties; + static const char msEscapeChar; + static const char *msValueEscapeCodes; + static const char *msValueEscapeChars; + static const char *msKeyEscapeCodes; + static const char *msKeyEscapeChars; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Properties + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Properties(default:0x0 properties:QHash(("log4j.appender.testAppender.layout", "org.apache.log4j.PatternLayout ") + * ("log4j.appender.testAppender.layout.ConversionPattern", "[%t] %-5p %l: %m%n") + * ("log4j.appender.testAppender.Append", "false ") + * ("log4j.appender.testAppender.File", "output/temp ") + * ("log4j.rootCategory", "TRACE, testAppender") + * ("log4j.appender.testAppender", "org.apache.log4j.FileAppender")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Properties &rProperties); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Properties::Properties(Properties *pDefaultProperties) : + mpDefaultProperties(pDefaultProperties) + {} + + inline Properties *Properties::defaultProperties() const + { return mpDefaultProperties; } + + inline void Properties::setDefaultProperties(Properties *pDefaultProperties) + { mpDefaultProperties = pDefaultProperties; } + + inline void Properties::setProperty(const QString &rKey, + const QString &rValue) + { insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_TYPEINFO(Log4Qt::Properties, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_PROPERTIES_H diff --git a/GCV-3.6.1-T4/src/log4qt/hierarchy.cpp b/GCV-3.6.1-T4/src/log4qt/hierarchy.cpp new file mode 100644 index 0000000..ef93d55 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/hierarchy.cpp @@ -0,0 +1,213 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/hierarchy.h" + +#include +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LoggerRepository) + + + + /************************************************************************** + * Class implementation: Hierarchy + **************************************************************************/ + + + Hierarchy::Hierarchy() : +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mLoggers(), + mThreshold(Level::NULL_INT), + mpRootLogger(logger(QString())) + { + Q_UNUSED(mHandleQtMessages); + // Store root logger to allow rootLogger() to be const + } + + + Hierarchy::~Hierarchy() + { + static_logger()->warn("Unexpected destruction of Hierarchy"); + + // QWriteLocker locker(&mObjectGuard); + // + // resetConfiguration(); + // clear(); + // delete mpRootLogger; + } + + + bool Hierarchy::exists(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.contains(rName); + } + + + Logger *Hierarchy::logger(const QString &rName) + { + QWriteLocker locker(&mObjectGuard); + + return createLogger(rName); + } + + + QList Hierarchy::loggers() const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.values(); + } + + + void Hierarchy::setThreshold(const QString &rThreshold) + { + setThreshold(Level::fromString(rThreshold)); + } + + + void Hierarchy::resetConfiguration() + { + QWriteLocker locker(&mObjectGuard); + + // Reset all loggers. + // Leave log, qt and root logger to the last to allow debugging of shutdown. + + Logger *p_logging_logger = logger(QLatin1String("Log4Qt")); + Logger *p_qt_logger = logger(QLatin1String("Qt")); + Logger *p_root_logger = rootLogger(); + + Logger *p_logger; + Q_FOREACH(p_logger, mLoggers) + { + if ((p_logger == p_logging_logger) || (p_logger == p_qt_logger) || (p_logger == p_root_logger)) + continue; + resetLogger(p_logger, Level::NULL_INT); + } + resetLogger(p_qt_logger, Level::NULL_INT); + resetLogger(p_logging_logger, Level::NULL_INT); + resetLogger(p_root_logger, Level::DEBUG_INT); + } + + + void Hierarchy::shutdown() + { + static_logger()->debug("Shutting down Hierarchy"); + resetConfiguration(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Hierarchy::debug(QDebug &rDebug) const + { + rDebug.nospace() << "Hierarchy(" + << "loggers:" << loggers().count() << " " + << "threshold:" << threshold().toString() << " " + << "root-level:" << rootLogger()->level().toString() << " " + << "root-appenders:" << rootLogger()->appenders().count() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + Logger *Hierarchy::createLogger(const QString &rName) + { + // Q_ASSERT_X(, "Hierarchy::createLogger", "Lock must be held by caller") + + const QString name_separator = QLatin1String("::"); + + Logger *p_logger = mLoggers.value(rName, 0); + if (p_logger != 0) + return p_logger; + + if (rName.isEmpty()) + { + p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), 0); + mLoggers.insert(QString(), p_logger); + return p_logger; + } + QString parent_name; + int index = rName.lastIndexOf(name_separator); + if (index >=0) + parent_name = rName.left(index); + p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name)); + mLoggers.insert(rName, p_logger); + return p_logger; + } + + + void Hierarchy::resetLogger(Logger *pLogger, Level level) const + { + // Q_ASSERT_X(, "Hierarchy::resetLogger", "Lock must be held by caller") + + pLogger->removeAllAppenders(); + pLogger->setAdditivity(true); + pLogger->setLevel(level); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/hierarchy.h b/GCV-3.6.1-T4/src/log4qt/hierarchy.h new file mode 100644 index 0000000..18a90eb --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/hierarchy.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: hierarchy.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_HIERARCHY_H +#define LOG4QT_HIERARCHY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/loggerrepository.h" + +#include +#include + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Hierarchy implements a logger repository. + * + * \note All the functions declared in this class are thread-safe. + */ + class Hierarchy : public LoggerRepository + { + public: + Hierarchy(); + // Hierarchy(const Hierarchy &rOther); // Use compiler default + virtual ~Hierarchy(); + // Hierarchy &operator=(const Hierarchy &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const; + virtual Logger *logger(const QString &rName); + virtual QList loggers() const; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual Logger *rootLogger() const; + virtual Level threshold() const; + virtual void setThreshold(Level level); + virtual void setThreshold(const QString &rThreshold); + + // JAVA: void clear(); + virtual bool isDisabled(Level level); + virtual void resetConfiguration(); + virtual void shutdown(); + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + // JAVA: void addRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + // JAVA: QHash getRendererMap() const; + // JAVA: setRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %Hierarchy(loggers:6 threshold:"ALL" root-level:"DEBUG" root-appenders:0) + * + * \sa QDebug, operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rdebug) const; +#endif + + private: + Logger *createLogger(const QString &rName); + void resetLogger(Logger *pLogger, Level level) const; + + private: + mutable QReadWriteLock mObjectGuard; + QHash mLoggers; + volatile bool mHandleQtMessages; + Level mThreshold; + Logger *mpRootLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Logger *Hierarchy::rootLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpRootLogger; } + + inline Level Hierarchy::threshold() const + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void Hierarchy::setThreshold(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool Hierarchy::isDisabled(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return level < mThreshold; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Hierarchy, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_HIERARCHY_H diff --git a/GCV-3.6.1-T4/src/log4qt/layout.cpp b/GCV-3.6.1-T4/src/log4qt/layout.cpp new file mode 100644 index 0000000..160f80d --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/layout.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/layout.h" + +#include +#include "log4qt/loggingevent.h" +#include "log4qt/logmanager.h" + + + +namespace Log4Qt +{ + + + /*************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Layout + **************************************************************************/ + + + QString Layout::contentType() const + { + return QString::fromLatin1("text/plain"); + } + + + void Layout::activateOptions() + { + } + + + QString Layout::endOfLine() + { + // There seams to be no function in Qt for this + +#ifdef Q_OS_WIN32 + return QLatin1String("\r\n"); +#endif // Q_OS_WIN32 +//#ifdef Q_OS_MAC +// return QLatin1String("\r"); +//#endif // Q_OS_MAC + return QLatin1String("\n"); + } + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/layout.h b/GCV-3.6.1-T4/src/log4qt/layout.h new file mode 100644 index 0000000..42f3b3e --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/layout.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LAYOUT_H +#define LOG4QT_LAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Layout is the base class for all layouts. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class Layout : public LogObject + { + Q_OBJECT + + /*! + * The property holds the content type of the layout. + * + * \sa contentType() + */ + Q_PROPERTY(QString footercontentType READ contentType) + /*! + * The property holds the footer used by the layout. + * + * \sa footer(), setFooter() + */ + Q_PROPERTY(QString footer READ footer WRITE setFooter) + /*! + * The property holds the header used by the layout. + * + * \sa header(), setHeader() + */ + Q_PROPERTY(QString header READ header WRITE setHeader) + + public: + Layout(QObject *pParent = 0); + virtual ~Layout(); + private: + Layout(const Layout &rOther); // Not implemented + Layout &operator=(const Layout &rOther); // Not implemented + + public: + virtual QString contentType() const; + QString footer() const; + QString header() const; + // JAVA: virtual bool ignoresThrowable() const; + QString name() const; + void setFooter(const QString &rFooter); + void setHeader(const QString &rHeader); + void setName(const QString &rName); + // JAVA: void setIgnoresThrowable(bool) const; + + virtual void activateOptions(); + virtual QString format(const LoggingEvent &rEvent) = 0; + + /*! + * Returns the end of line seperator for the operating system. + * + * Windows: \\r\\n + * Mac: \\r + * UNIX: \\n + */ + static QString endOfLine(); + + // Member variables + private: + QString mFooter; + QString mHeader; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Layout::Layout(QObject *pParent) : + LogObject(pParent) + {} + + inline Layout::~Layout() + {} + + inline QString Layout::footer() const + { return mFooter; } + + inline QString Layout::header() const + { return mHeader; } + + inline QString Layout::name() const + { return objectName(); } + + inline void Layout::setFooter(const QString &rFooter) + { mFooter = rFooter; } + + inline void Layout::setHeader(const QString &rHeader) + { mHeader = rHeader; } + + inline void Layout::setName(const QString &rName) + { setObjectName(rName); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Layout, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LAYOUT_H diff --git a/GCV-3.6.1-T4/src/log4qt/level.cpp b/GCV-3.6.1-T4/src/log4qt/level.cpp new file mode 100644 index 0000000..a55038f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/level.cpp @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/level.h" + +#include +#include +#include +#include "log4qt/logger.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Level) + + + + /************************************************************************** + * Class implementation: Level + **************************************************************************/ + + + int Level::syslogEquivalent() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + switch (mValue) + { + case NULL_INT: + case ALL_INT: + case TRACE_INT: + case DEBUG_INT: + return 7; + case INFO_INT: + return 6; + case WARN_INT: + return 4; + case ERROR_INT: + return 3; + case FATAL_INT: + case OFF_INT: + return 0; + default: + Q_ASSERT_X(false, "Level::syslogEquivalent()", "Unknown level value"); + return 7; + } + } + + + QString Level::toString() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + const char *p_context = "Level"; + + switch (mValue) + { + case NULL_INT: + return QCoreApplication::translate(p_context, "NULL"); + case ALL_INT: + return QCoreApplication::translate(p_context, "ALL"); + case TRACE_INT: + return QCoreApplication::translate(p_context, "TRACE"); + case DEBUG_INT: + return QCoreApplication::translate(p_context, "DEBUG"); + case INFO_INT: + return QCoreApplication::translate(p_context, "INFO"); + case WARN_INT: + return QCoreApplication::translate(p_context, "WARN"); + case ERROR_INT: + return QCoreApplication::translate(p_context, "ERROR"); + case FATAL_INT: + return QCoreApplication::translate(p_context, "FATAL"); + case OFF_INT: + return QCoreApplication::translate(p_context, "OFF"); + default: + Q_ASSERT_X(false, "Level::toString()", "Unknown level value"); + return QCoreApplication::translate(p_context, "NULL"); + } + } + + + Level Level::fromString(const QString &rLevel, bool *pOk) + { + const char *p_context = "Level"; + if (pOk) + *pOk = true; + + if (rLevel == QLatin1String("OFF") || + rLevel == QCoreApplication::translate(p_context, "OFF")) + return OFF_INT; + if (rLevel == QLatin1String("FATAL") || + rLevel == QCoreApplication::translate(p_context, "FATAL")) + return FATAL_INT; + if (rLevel == QLatin1String("ERROR") || + rLevel == QCoreApplication::translate(p_context, "ERROR")) + return ERROR_INT; + if (rLevel == QLatin1String("WARN") || + rLevel == QCoreApplication::translate(p_context, "WARN")) + return WARN_INT; + if (rLevel == QLatin1String("INFO") || + rLevel == QCoreApplication::translate(p_context, "INFO")) + return INFO_INT; + if (rLevel == QLatin1String("DEBUG") || + rLevel == QCoreApplication::translate(p_context, "DEBUG")) + return DEBUG_INT; + if (rLevel == QLatin1String("TRACE") || + rLevel == QCoreApplication::translate(p_context, "TRACE")) + return TRACE_INT; + if (rLevel == QLatin1String("ALL") || + rLevel == QCoreApplication::translate(p_context, "ALL")) + return ALL_INT; + if (rLevel == QLatin1String("NULL") || + rLevel == QCoreApplication::translate(p_context, "NULL")) + return NULL_INT; + + logger()->warn("Use of invalid level string '%1'. Using 'Level::NULL_INT' instead.", rLevel); + if (pOk) + *pOk = false; + return NULL_INT; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel) + { + quint8 l = rLevel.mValue; + rStream << l; + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel) + { + quint8 l; + rStream >> l; + rLevel.mValue = (Level::Value)l; + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Level &rLevel) + { + debug.nospace() << "Level(" + << rLevel.toString() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/level.h b/GCV-3.6.1-T4/src/log4qt/level.h new file mode 100644 index 0000000..93914c2 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/level.h @@ -0,0 +1,193 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVEL_H +#define LOG4QT_LEVEL_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Level defines the level of a logging event. + * + * \note All the functions declared in this class are thread-safe. + */ + class Level + { + public: + // Comparisson operators rely on the order: + // NULL_INT < ALL_INT < TRACE_INT < ... + // Serialisation uses unsigned 8 bit int + + /*! + * The enumeration Value contains all possible Level values. + */ + enum Value + { + /*! NULL_INT is used for no level has been specified */ + NULL_INT = 0, + ALL_INT = 32, + TRACE_INT = 64, + DEBUG_INT = 96, + INFO_INT = 128, + WARN_INT = 150, + ERROR_INT = 182, + FATAL_INT = 214, + OFF_INT = 255 + }; + + public: + Level(Value value = NULL_INT); + // Level(const Level &rOther); // Use compiler default + // virtual ~Level(); // Use compiler default + // Level &operator=(const Level &rOther); // Use compiler default + + int syslogEquivalent() const; + int toInt() const; + + bool operator==(const Level &rOther) const; + bool operator!=(const Level &rOther) const; + bool operator<(const Level &rOther) const; + bool operator<=(const Level &rOther) const; + bool operator>(const Level &rOther) const; + bool operator>=(const Level &rOther) const; + QString toString() const; + + static Level fromString(const QString &rName, bool *pOk = 0); + + private: + // QMutex mObjectGuard; + volatile Value mValue; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + friend QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates Level + * + * Writes the given error \a rLevel to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + + /*! + * \relates Level + * + * Reads an error from the given stream \a rStream into the given + * error \a rLevel, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Level + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Level("ERROR") + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Level &rLevel); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + + inline Level::Level(Value value) : + mValue(value) + {} + + inline int Level::toInt() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue; } + + inline bool Level::operator==(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue == rOther.mValue; } + + inline bool Level::operator!=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue != rOther.mValue; } + + inline bool Level::operator<(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue < rOther.mValue; } + + inline bool Level::operator<=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue <= rOther.mValue; } + + inline bool Level::operator>(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue > rOther.mValue; } + + inline bool Level::operator>=(const Level &rOther) const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue >= rOther.mValue; } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::Level) +Q_DECLARE_TYPEINFO(Log4Qt::Level, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LEVEL_H diff --git a/GCV-3.6.1-T4/src/log4qt/log4qt.cpp b/GCV-3.6.1-T4/src/log4qt/log4qt.cpp new file mode 100644 index 0000000..9378f46 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/log4qt.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + *Dependencies + ******************************************************************************/ + + +#include "log4qt/log4qt.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + *Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/log4qt.h b/GCV-3.6.1-T4/src/log4qt/log4qt.h new file mode 100644 index 0000000..73c3cfe --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/log4qt.h @@ -0,0 +1,614 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Added a compile time version check for the Qt version + * Jan 2009, Martin Heinrich: + * - Updated documentation and version information for version 0.2 + * Feb 2009, Martin Heinrich: + * - Updated version information for version 0.3 + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_H +#define LOG4QT_H + + +/*! + * \mainpage + * + * %Log4Qt is a C++ port of the Apache Software Foundation Log4j package + * using the Trolltech Qt Framework. + * + * The documentation describes classes and methods that have been added or + * changed compared to Log4j. + * + * The following sections are describing the implementation in more detail: + * - \ref Changes "Differences to Log4j" + * - \ref Ownership "Object ownership" + * - \ref LogLog "Logging within the package" + * - \ref Init "Initialization procedure" + * - \ref Env "Environment Variables" + * - \ref Undocumented "Undocumented functions" + * - \ref Assumptions "Assumptions" + * + * \author Martin Heinrich + * \version 0.3 (January 2009) + * + */ + +/*! + * \page Changes Differences to Log4j + * + * The following fundamental differences exist between %Log4Qt and Log4j: + * + * - As a JAVA package Log4j does not have to manage object ownership and + * lifetime in the same way then it is required in C++. For details on + * how object ownership is handled see \ref Ownership "Object ownership". + * - The package uses itself for its internal logging similar to Log4j 1.3. + * For details see \ref LogLog "Logging within the package". + * - The configuration using system properties was replaced with a combination + * of environment variables and application settings. For details see + * \ref Env "Environment Variables". + * - Custom levels are not supported. + * - Multiple Logger Repositories are not supported + * + * The following classes have been changed: + * + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - The procedure of checking, if logging is possible, originally used by + * \ref Log4Qt::WriterAppender "WriterAppender" was generalised and is used + * in \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" and derived classes + * (\ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()"). + * - The \ref Log4Qt::AppenderSkeleton::doAppend() "doAppend()" member function will + * check the entry conditions by calling the sub-class specific + * \ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()". + * If successful the sub-class specific + * \ref Log4Qt::AppenderSkeleton::append() "append()" function is called. + * + * - Configurator + * - Configure functions return a boolean indicating, if the configuration + * was successful. + * - Configure errors are accessible over + * \ref Log4Qt::ConfiguratorHelper::configureError() + * "ConfiguratorHelper::configureError()". + * - Watching for configuration file changes is a function performed + * centrally by the \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper". + * The class provides signals to notify on configuration change and errors. + * - The class \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" was + * extended to be able to read configuration data from a QSettings object. + * + * - \ref Log4Qt::Level "Level" + * - A new value \ref Log4Qt::Level::NULL_INT "Level::NULL_INT" was + * introduced to indicate there is no level set. + * + * - \ref Log4Qt::Logger "Logger" + * - The method \ref Log4Qt::Logger::isEnabledFor() "isEnabledFor()" + * does also take the repository threshold into account. + * - Several overloaded convenience member function are available to log + * messages with arguments of different types. + * - Two macros, \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * and \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER", + * allows retrieving and caching of a pointer to a logger object. + * + * - \ref Log4Qt::LogManager "LogManager" + * - A QtMessage handler can be installed via + * \ref Log4Qt::LogManager::setHandleQtMessages() "setHandleQtMessages()", + * to redirect all messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() to a logger. The logger is named Qt and can be + * accessed using \ref Log4Qt::LogManager::qtLogger() "qtLogger()". + * - The initialisation procedure is available over a public method + * (\ref Log4Qt::LogManager::startup() "startup()"). + * - The LogManager provides access to the logger used internally by the + * package (\ref Log4Qt::LogManager::logLogger() "logLogger()") and to + * its default initialisation procedure + * (\ref Log4Qt::LogManager::configureLogLogger() "configureLogLogger()"). + * + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - The class will call \ref Log4Qt::WriterAppender::handleIoErrors() + * "handleIoErrors()" after all I/O operations. Sub-classes should + * re-implement the function to handle errors. + * + * The following classes have been added: + * + * - An additional appender class, \ref Log4Qt::DebugAppender "DebugAppender", + * was added. The class appends logging events to the platform specific debug + * output. + * - Various helper class have been introduced: + * - \ref Log4Qt::ClassLogger "ClassLogger": The class ClassLogger provides + * logging for a QObject derived class. + * - \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper": The class + * ConfiguratorHelper provides a configuration file watch and last error + * for configurator classes. + * - \ref Log4Qt::DateTime "DateTime": The class DateTime provides extended + * functionality for QDateTime. + * - \ref Log4Qt::LogError "LogError": The class LogError represents an error. + * - \ref Log4Qt::Factory "Factory": The class Factory provides factories + * for Appender, Filter and Layout objects. + * - \ref Log4Qt::InitialisationHelper "InitialisationHelper": The class + * InitialisationHelper performs static initialisation tasks. + * - \ref Log4Qt::LogObject "LogObject": The class LogObject is the common + * base class for many classes in the package. + * - \ref Log4Qt::LogObjectPtr "LogObjectPtr": The class LogObjectPtr + * implements automatic reference counting for LogObject objects. + * - \ref Log4Qt::PatternFormatter "PatternFormatter": The class + * PatternFormatter formats a logging event based on a pattern string. + * - \ref Log4Qt::Properties "Properties": The class Properties implements a + * JAVA property hash. + */ + +/*! + * \page Ownership Object ownership + * + * In difference to the JAVA Log4j package %Log4Qt must manage ownership and + * lifetime of the objects used. This is non trivial as objects are created + * and used in different ways. + * + * In general an object can be created explicitly for example an application + * may create Loggers, Appenders and Layouts during creation of a QApplication + * object. But they can also be automatically created by the package on + * startup using a \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" + * configuration file. Objects may also be created the one way and then used + * the other. Object may be used by multiple other objects. A Layout for example + * may be used by multiple Appenders. Objects are also created from multiple + * threads. The creation may happen during static initialisation and the + * deletion during static de-initialization. + * + * The parent child model used by QObject cannot be used to handle this. It + * cannot automatically delete an object that is used by multiple others as + * for example an Appender used by multiple Loggers. In addition to this + * QObjects and their children must reside in the same thread. This would + * either mean to impose restriction on how objects can be created or to move + * objects to a specific thread. + * + * To allow an automatic deletion of not required objects the package + * implements reference counting for Appenders, Layouts and Filters. The + * reference counting is implemented in \ref Log4Qt::LogObject "LogObject", + * which is used as a common base class. The reference count can be explicitly + * changed using the methods \ref Log4Qt::LogObject::retain() "retain()" and + * \ref Log4Qt::LogObject::release() "release()". Alternatively an auto pointer + * is available \ref Log4Qt::LogObjectPtr "LogObjectPtr", which is used + * throughout the package. + * + * The reference counting mechanism will test, if an object has a QObject + * parent object set. If a parent is set, the object will not be deleted, if + * the reference count reaches 0. This allows to mix the reference counted + * paradigm with the QObject parent child one. + * + * The following example configures a logger and uses reference counting to + * manage the ownership of objects. + * + * \code + * // Create layout + * TTCCLayout *p_layout = new TTCCLayout(); + * + * // Create appender + * ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // p_appender and p_layout are deleted here + * \endcode + * + * The following example configures a logger and uses QObject ownership of + * objects. + * + * \code + * QObject *p_parent = new MyObject; + * + * // Create objects + * ConsoleAppender *p_appender = new ConsoleAppender(p_parent); + * TTCCLayout *p_layout = new TTCCLayout(p_appender); + * + * // Configure appender + * p_appender->setTarget(ConsoleAppender::STDOUT_TARGET); + * p_appender->setLayout(p_layout); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); + * + * delete p_parent; // p_appender and p_layout are deleted here + * \endcode + * + * The following example shows how to use objects created on the stack. + * + * \code + * { + * // Create layout + * TTCCLayout layout; + * layout.retain(); + * + * // Create appender + * ConsoleAppender appender(&layout, ConsoleAppender::STDOUT_TARGET); + * appender.retain(); + * appender.activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(&appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // Without retain() program crashes here + * + * } // p_appender and p_layout are deleted here + * \endcode + */ + +/*! + * \page LogLog Logging within the package + * + * The package uses itself for logging similar to Log4j 1.3. This brings much + * more flexibility over logging to stdout, stderr like in Log4j 1.2 using + * logLog. It also enables the program to capture and handle errors raised by + * the package. + * + * Using this approach introduces the issue of recursion. The following example + * explains a situation where this happens. Let's say all logger are configured + * to be additive and only the root logger has an appender set. The appender + * is a \ref Log4Qt::FileAppender "FileAppender". During the logging of an + * event an I/O error occurs. The \ref Log4Qt::FileAppender "FileAppender" logs + * an event by itself using the logger %Log4Qt::FileAppender. The event is + * passed to the root logger, which calls then the \ref Log4Qt::FileAppender + * "FileAppender". This causes another I/O error, which is logged by + * the \ref Log4Qt::FileAppender "FileAppender". + * + * To avoid an endless loop the appender will drop the event on a recursive + * invocation. This check is done by \ref Log4Qt::AppenderSkeleton + * "AppenderSkeleton" in \ref Log4Qt::AppenderSkeleton::doAppend() + * "doAppend()". + * + * The problem only occurs, if a logger, appender, layout or filter log an + * event while an event is appended. Neither the logger class nor any of the + * layout or filter classes log events during appending of an event. Most of + * the appender classes may log errors during appending. Only the + * \ref Log4Qt::ListAppender "ListAppender" and + * \ref Log4Qt::ListAppender "ConsoleAppender" are not logging events. + * + * The default configuration uses two \ref Log4Qt::ListAppender + * "ConsoleAppender", one for stderr and one for stdout. No event will be + * dropped, because no recursive invocations can occur. + */ + +/*! + * \page Init Initialization procedure + * + * The package is initialised in two stages. The first stage takes place during + * static initialization. The second stage takes place when the + * \ref Log4Qt::LogManager "LogManager" singleton is created. + * + * During static initialisation the \ref Log4Qt::InitialisationHelper + * "InitialisationHelper" singleton is created . On construction it captures + * the program startup time, reads the required values from the system + * environment and registers the package types with the Qt type system. + * + * The \ref Log4Qt::LogManager "LogManager" singleton is created on first use. + * The creation is usually triggered by the request for a \ref Log4Qt::Logger + * "Logger" object. The call to \ref Log4Qt::Logger::logger() + * "Logger::logger()" is passed through to \ref Log4Qt::LogManager::logger() + * "LogManager::logger()". On creation the \ref Log4Qt::LogManager "LogManager" + * creates a \ref Log4Qt::Hierarchy "Hierarchy" object as logger repository. + * + * After the singleton is created the logging of the package is configured to + * its default by a call to \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()". The logger + * \ref Log4Qt::LogManager::logLogger() "logLogger()" is configured to be not + * additive. Messages with the level \ref Log4Qt::Level::ERROR_INT + * "Level::ERROR_INT" and \ref Log4Qt::Level::FATAL_INT "Level::FATAL_INT" are + * written to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is read from + * the system environment or application settings using + * \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" with the key \c Debug. If a level value + * is found, but it is not a valid Level string, + * \ref Log4Qt::Level::DEBUG_INT "Level::DEBUG_INT" is used. If no level string + * is found \ref Log4Qt::Level::ERROR_INT "Level::ERROR_INT" is used. + * + * Once the logging is configured the package is initialised by a call to + * \ref Log4Qt::LogManager::startup() "LogManager::startup()". The function + * will test for the setting \c DefaultInitOverride in the system environment + * and application settings using \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()". If the value is present and set to + * anything else then \c false, the initialisation is aborted.
+ * The system environment and application settings are tested for the setting + * \c Configuration. If it is found and it is a valid path to a file, the + * package is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting \c Configuration is + * not available and a QCoreApplication object is present, the application + * settings are tested for a group \c Log4Qt/Properties. If the group exists, + * the package is configured with the setting using the + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration file nor + * configuration settings could be found, the current working directory is + * searched for the file \c "log4qt.properties". If it is found, the package + * is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * The following example shows how to use application settings to initialise the + * package. + * + * \code + * # file: myapplication.h + * + * #include qapplication.h + * + * class MyApplication : public QApplication + * { + * Q_OBJECT + * + * public: + * MyApplication(); + * ~MyApplication(); + * void setupLog4Qt(); + * } + * \endcode + * \code + * # file: myapplication.cpp + * + * #include myapplication.h + * + * MyApplication::MyApplication( + * { + * // Set Application data to allow Log4Qt initialisation to read the + * // correct values + * setApplicationName("MyApplication"); + * setOrganisationName("MyOrganisation"); + * setOrganizationDomain("www.myorganisation.com"); + * + * // Log first message, which initialises Log4Qt + * Log4Qt::Logger::logger("MyApplication")->info("Hello World"); + * } + * + * MyApplication::~MyApplication() + * { + * } + * + * void MyApplication::setupLog4Qt() + * { + * QSettings s; + * + * // Set logging level for Log4Qt to TRACE + * s.beginGroup("Log4Qt"); + * s.setValue("Debug", "TRACE"); + * + * // Configure logging to log to the file C:/myapp.log using the level TRACE + * s.beginGroup("Properties"); + * s.setValue("log4j.appender.A1", "org.apache.log4j.FileAppender"); + * s.setValue("log4j.appender.A1.file", "C:/myapp.log"); + * s.setValue("log4j.appender.A1.layout", "org.apache.log4j.TTCCLayout"); + * s.setValue("log4j.appender.A1.layout.DateFormat", "ISO8601"); + * s.setValue("log4j.rootLogger", "TRACE, A1"); + * + * // Settings will become active on next application startup + * } + * \endcode + */ + +/*! + * \page Env Environment Variables + * + * The package uses environment variables to control the initialization + * procedure. The environment variables replace the system property entries + * used by Log4j. + * + * For compability reasons the Log4j entry is recognised. Alternatively a + * environment variable style Log4Qt form can be used. The following entries + * are used: + * + * - LOG4QT_DEBUG
+ * The variable controls the \ref Log4Qt::Level "Level" value for the + * logger \ref Log4Qt::LogManager::logLogger() "LogManager::logLogger()". + * If the value is a valid \ref Log4Qt::Level "Level" string, the level for + * the is set to the level. If the value is not a valid + * \ref Log4Qt::Level "Level" string, \ref Log4Qt::Level::DEBUG_INT + * "DEBUG_INT" is used. Otherwise \ref Log4Qt::Level::ERROR_INT "ERROR_INT" + * is used. + * - \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()" + * + * - LOG4QT_DEFAULTINITOVERRIDE
+ * The variable controls the \ref Init "initialization procedure" performed + * by the \ref Log4Qt::LogManager "LogManager" on startup. If it is set to + * any other value then \c false the \ref Init "initialization procedure" + * is skipped. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATION
+ * The variable specifies the configuration file used for initialising the + * package. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATORCLASS
+ * The variable specifies the configurator class used for initialising the + * package. + * + * Environment variables are read during static initialisation on creation of + * the \ref Log4Qt::InitialisationHelper "InitialisationHelper". They can be + * accessed by calling \ref Log4Qt::InitialisationHelper::environmentSettings() + * "InitialisationHelper::environmentSettings()". + * + * All settings can also be made in the application settings under the group + * \c %Log4Qt. For example the environment variable \c LOG4QT_DEBUG is + * equivalent to the setting \c Log4Qt/Debug. If an environment variable is + * set it takes precedence over the application setting. Settings are only + * used, if an QApplication object is available, when the + * \ref Log4Qt::LogManager "LogManager" is + * initialised (see \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" for details). + */ + +/*! + * \page Undocumented Undocumented functions + * + * In general it was tried to avoid the usage of undocumented features of Qt. + * Nice to have features like for example Q_DECLARE_PRIVATE are not used. Only + * features that would have been resulted in re-coding the same functionality + * are used. + * + * - QT_WA: The macro is used to call Windows A/W functions + * - \ref Log4Qt::DebugAppender "DebugAppender" + * - QBasicAtomicPointer: The class is used instead of QAtomicPointer, because + * it allows the initialisation as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * - Q_BASIC_ATOMIC_INITIALIZER: The macro is used to initialise QAtomicPointer + * objects as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + */ + +/*! + * \page Assumptions Assumptions + * + * The following assumptions are used throughout the package: + * + * - Reading / writing of bool or int is thread-safe, if declared volatile + * - \ref Log4Qt::ListAppender "ListAppender" + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - \ref Log4Qt::ConsoleAppender "ConsoleAppender" + * - \ref Log4Qt::FileAppender "FileAppender" + * - \ref Log4Qt::Hierarchy "Hierarchy" + * - \ref Log4Qt::Level "Level" + * - \ref Log4Qt::Logger "Logger" + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - \ref Log4Qt::Layout::format() "Layout::format()" is implemented reentrant + * in all sub-classes. + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - Being able to use singleton objects during static de-initialization without + * order issues is more valuable then their destruction. + * - \ref Log4Qt::LogManager "LogManager" + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + */ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#if QT_VERSION < QT_VERSION_CHECK(4, 3, 0) +# error "Log4Qt requires Qt version 4.3.0 or higher" +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +/*! + * \brief The namespace %Log4Qt encloses all parts of the package. + */ +namespace Log4Qt +{ + /*! + * This macro expands a numeric value of the form 0xMMmmPP (MM = major, + * mm = minor, PP = patch) that specifies Log4Qt's version number. + * This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION 0x000200 + + /*! + * The macro expands to a string that specifies the Log4Qt's version + * number. This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + #define LOG4QT_VERSION_STR "0.3.0" + + enum ErrorCode + { + OK = 0, + // AppenderSkeleton, FileAppender, WriterAppender + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR, + APPENDER_ACTIVATE_MISSING_WRITER_ERROR, + APPENDER_ACTIVATE_MISSING_FILE_ERROR, + APPENDER_CLOSED_ERROR, + APPENDER_INVALID_PATTERN_ERROR, + APPENDER_NO_OPEN_FILE_ERROR, + APPENDER_NOT_ACTIVATED_ERROR, + APPENDER_OPENING_FILE_ERROR, + APPENDER_RENAMING_FILE_ERROR, + APPENDER_REMOVE_FILE_ERROR, + APPENDER_USE_INVALID_PATTERN_ERROR, + APPENDER_USE_MISSING_LAYOUT_ERROR, + APPENDER_USE_MISSING_WRITER_ERROR, + APPENDER_WRITING_FILE_ERROR, + // Level + LEVEL_INVALID_LEVEL_STRING, + // Layouts, PatternFormatter + LAYOUT_EXPECTED_DIGIT_ERROR, + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + // Logger + LOGGER_INVALID_LEVEL_FOR_ROOT, + // PropertyConfigurator, OptionHandler + CONFIGURATOR_OPENING_FILE_ERROR, + CONFIGURATOR_READING_FILE_ERROR, + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + CONFIGURATOR_INVALID_OPTION_ERROR, + CONFIGURATOR_MISSING_APPENDER_ERROR, + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + CONFIGURATOR_MISSING_LAYOUT_ERROR, + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + CONFIGURATOR_PROPERTY_ERROR, + CONFIGURATOR_UNKNOWN_TYPE_ERROR + }; + + + /****************************************************************************** + * Operators, Helpers + ******************************************************************************/ + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + +} // namespace Log4Qt + + +#endif // LOG4QT_H diff --git a/GCV-3.6.1-T4/src/log4qt/log4qt.pri b/GCV-3.6.1-T4/src/log4qt/log4qt.pri new file mode 100644 index 0000000..f9730b9 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/log4qt.pri @@ -0,0 +1,111 @@ +# ******************************************************************************* +# +# package: Log4Qt +# file: log4qt.pri +# created: September 2007 +# author: Martin Heinrich +# +# +# Copyright 2007 Martin Heinrich +# +# 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. +# +# ******************************************************************************* + +INCLUDEPATH += $$PWD/.. +DEPENDPATH += $$PWD/.. +HEADERS += \ + $$PWD/appender.h \ + $$PWD/appenderskeleton.h \ + $$PWD/basicconfigurator.h \ + $$PWD/consoleappender.h \ + $$PWD/dailyrollingfileappender.h \ + $$PWD/fileappender.h \ + $$PWD/helpers/classlogger.h \ + $$PWD/helpers/configuratorhelper.h \ + $$PWD/helpers/datetime.h \ + $$PWD/helpers/factory.h \ + $$PWD/helpers/initialisationhelper.h \ + $$PWD/helpers/logerror.h \ + $$PWD/helpers/logobject.h \ + $$PWD/helpers/logobjectptr.h \ + $$PWD/helpers/optionconverter.h \ + $$PWD/helpers/patternformatter.h \ + $$PWD/helpers/properties.h \ + $$PWD/hierarchy.h \ + $$PWD/layout.h \ + $$PWD/level.h \ + $$PWD/log4qt.h \ + $$PWD/logger.h \ + $$PWD/loggerrepository.h \ + $$PWD/loggingevent.h \ + $$PWD/logmanager.h \ + $$PWD/mdc.h \ + $$PWD/ndc.h \ + $$PWD/patternlayout.h \ + $$PWD/propertyconfigurator.h \ + $$PWD/rollingfileappender.h \ + $$PWD/simplelayout.h \ + $$PWD/spi/filter.h \ + $$PWD/ttcclayout.h \ + $$PWD/writerappender.h \ + $$PWD/varia/debugappender.h \ + $$PWD/varia/denyallfilter.h \ + $$PWD/varia/nullappender.h \ + $$PWD/varia/levelmatchfilter.h \ + $$PWD/varia/levelrangefilter.h \ + $$PWD/varia/listappender.h \ + $$PWD/varia/stringmatchfilter.h + +SOURCES += \ + $$PWD/appenderskeleton.cpp \ + $$PWD/basicconfigurator.cpp \ + $$PWD/consoleappender.cpp \ + $$PWD/dailyrollingfileappender.cpp \ + $$PWD/fileappender.cpp \ + $$PWD/helpers/classlogger.cpp \ + $$PWD/helpers/configuratorhelper.cpp \ + $$PWD/helpers/datetime.cpp \ + $$PWD/helpers/factory.cpp \ + $$PWD/helpers/initialisationhelper.cpp \ + $$PWD/helpers/logerror.cpp \ + $$PWD/helpers/logobject.cpp \ + $$PWD/helpers/logobjectptr.cpp \ + $$PWD/helpers/optionconverter.cpp \ + $$PWD/helpers/patternformatter.cpp \ + $$PWD/helpers/properties.cpp \ + $$PWD/hierarchy.cpp \ + $$PWD/layout.cpp \ + $$PWD/level.cpp \ + $$PWD/log4qt.cpp \ + $$PWD/logger.cpp \ + $$PWD/loggerrepository.cpp \ + $$PWD/loggingevent.cpp \ + $$PWD/logmanager.cpp \ + $$PWD/mdc.cpp \ + $$PWD/ndc.cpp \ + $$PWD/patternlayout.cpp \ + $$PWD/propertyconfigurator.cpp \ + $$PWD/rollingfileappender.cpp \ + $$PWD/simplelayout.cpp \ + $$PWD/spi/filter.cpp \ + $$PWD/ttcclayout.cpp \ + $$PWD/writerappender.cpp \ + $$PWD/varia/debugappender.cpp \ + $$PWD/varia/denyallfilter.cpp \ + $$PWD/varia/nullappender.cpp \ + $$PWD/varia/levelmatchfilter.cpp \ + $$PWD/varia/levelrangefilter.cpp \ + $$PWD/varia/listappender.cpp \ + $$PWD/varia/stringmatchfilter.cpp + \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/log4qt/logger.cpp b/GCV-3.6.1-T4/src/log4qt/logger.cpp new file mode 100644 index 0000000..d5dc936 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/logger.cpp @@ -0,0 +1,349 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logger.h" + +#include +#include "log4qt/appenderskeleton.h" +#include "log4qt/varia/listappender.h" +#include "log4qt/loggingevent.h" +#include "log4qt/log4qt.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/logmanager.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Logger + **************************************************************************/ + + + Logger::Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent) : + QObject(0), +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mName(rName), + mpLoggerRepository(pLoggerRepository), + mAdditivity(true), + mAppenders(), + mLevel(level), + mpParent(pParent) + { + Q_ASSERT_X(pLoggerRepository, "Logger::Logger()", "Construction of Logger with null LoggerRepository"); + + setObjectName(mName); + } + + + Logger::~Logger() + { + logger()->warn("Unexpected destruction of Logger"); + + // QWriteLocker locker(&mObjectGuard); + // + // QMutableListIterator< LogObjectPtr > i(mAppenders); + // while (i.hasNext()) + // { + // i.next(); + // i.remove(); + // } + } + + + QList Logger::appenders() const + { + QReadLocker locker(&mObjectGuard); + + QList result; + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + result << p_appender; + return result; + } + + + void Logger::setLevel(Level level) + { + // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe + + if ((parentLogger() == 0) && (level == Level::NULL_INT)) + { + logger()->warn("Invalid root logger level NULL_INT. Using DEBUG_INT instead"); + level = Level::DEBUG_INT; + } + mLevel = level; + } + + + void Logger::addAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Handle warnings, before write lock is aquired + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + { + QReadLocker locker(&mObjectGuard); + + if(!p_appender) + { + logger()->warn("Adding null Appender to Logger '%1'", name()); + return; + } + if(mAppenders.contains(p_appender)) + { + logger()->warn("Adding of duplicate appender '%2' to logger '%1'", name(), p_appender->name()); + return; + } + } + { + QWriteLocker locker(&mObjectGuard); + + if(mAppenders.contains(p_appender)) + return; + mAppenders.append(p_appender); + } + } + + + Appender *Logger::appender(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + if (p_appender->name() == rName) + return p_appender; + return 0; + } + + + + void Logger::callAppenders(const LoggingEvent &rEvent) const + { + QReadLocker locker(&mObjectGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + p_appender->doAppend(rEvent); + if (additivity() && (parentLogger() != 0)) + parentLogger()->callAppenders(rEvent); + } + + + bool Logger::isAttached(Appender *pAppender) const + { + QReadLocker locker(&mObjectGuard); + + // Keep objects with a 0 reference count safe + LogObjectPtr p_appender = pAppender; + + return mAppenders.contains(p_appender); + } + + + void Logger::removeAllAppenders() + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to all appenders so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + logger()->trace("Removing all appenders from logger '%1'", name()); + + QList< LogObjectPtr > appenders; + { + QWriteLocker locker(&mObjectGuard); + QMutableListIterator< LogObjectPtr > i(mAppenders); + while (i.hasNext()) + { + Appender *p_appender = i.next(); + ListAppender *p_listappender = qobject_cast(p_appender); + if (p_listappender && p_listappender->configuratorList()) + continue; + else + { + appenders << p_appender; + i.remove(); + } + } + } + appenders.clear(); + } + + + void Logger::removeAppender(Appender *pAppender) + { + // Avoid deadlock: + // - Only log warnings without having the write log aquired + // - Hold a reference to the appender so that the remove does not + // destruct the appender over the reference count while the write + // log is held. The appender may log messages. + + LogObjectPtr p_appender = pAppender; + + if(!p_appender) + { + logger()->warn("Request to remove null Appender from Logger '%1'", name()); + return; + } + int n; + { + QWriteLocker locker(&mObjectGuard); + + n = mAppenders.removeAll(p_appender); + } + if (n == 0) + { + logger()->warn("Request to remove Appender '%2', which is not part of Logger '%1' appenders", name(), p_appender->name()); + return; + } + } + + + void Logger::removeAppender(const QString &rName) + { + Appender *p_appender = appender(rName); + if (p_appender) + removeAppender(p_appender); + } + + + Level Logger::effectiveLevel() const + { + Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT, "Logger::effectiveLevel()", "Root logger level must not be NULL_INT"); + + QReadLocker locker(&mObjectGuard); + + const Logger *p_logger = this; + while (p_logger->level() == Level::NULL_INT) + p_logger = p_logger->parentLogger(); + return p_logger->level(); + } + + + bool Logger::isEnabledFor(Level level) const + { + if (mpLoggerRepository->isDisabled(level)) + return false; + return (effectiveLevel() <= level); + } + + + Logger *Logger::logger(const QString &rName) + { + return LogManager::logger(rName); + } + + + Logger *Logger::logger(const char *pName) + { + return LogManager::logger(QLatin1String(pName)); + } + + + Logger *Logger::rootLogger() + { + return LogManager::rootLogger(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Logger::debug(QDebug &rDebug) const + { + QReadLocker locker(&mObjectGuard); + + QString parent_logger; + if (mpParent) + parent_logger = mpParent->name(); + + rDebug.nospace() << "Logger(" + << "name:" << name() << " " + << "appenders:" << mAppenders.count() << " " + << "additivity:" << mAdditivity << " " + << mLevel + << "parentLogger:" << parent_logger + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void Logger::forcedLog(Level level, const QString &rMessage) const + { + QReadLocker locker(&mObjectGuard); + + LoggingEvent event(this, level, rMessage); + callAppenders(event); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Logger &rLogger) + { + return rLogger.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/logger.h b/GCV-3.6.1-T4/src/log4qt/logger.h new file mode 100644 index 0000000..1b58adc --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/logger.h @@ -0,0 +1,1665 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Replaced usage of q_atomic_test_and_set_ptr with + * QBasicAtomicPointer + * + * + * Copyright 2007 - 2008 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGER_H +#define LOG4QT_LOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include "log4qt/helpers/logerror.h" +#include "log4qt/helpers/classlogger.h" +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/level.h" + +#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) +# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# warning "QAtomicPointer test and set is not native. The macro Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * LOG4QT_DECLARE_STATIC_LOGGER declares a static function \a FUNCTION that + * returns a pointer to a \ref Log4Qt::Logger "Logger" named after \a CLASS. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by calling \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger( #CLASS )". The pointer is stored to be returned on + * subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class not derived from QObject. + * + * \code + * #file: counter.h + * + * #include logger.h + * + * class Counter + * { + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * LOG4QT_DECLARE_STATIC_LOGGER(logger, Counter) + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) : + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static Log4Qt::Logger *p_logger = 0; \ + if (!p_logger) \ + { \ + q_atomic_test_and_set_ptr( \ + &p_logger, \ + 0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#else + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger.loadAcquire()) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_DECLARE_QCLASS_LOGGER declares member functions to retrieve + * \ref Log4Qt::Logger "Logger" for the class it is used in. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by a call to \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger(const char *pName)". The pointer is stored to be + * returned on subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class derived from QObject. + * + * \code + * #file: counter.h + * + * #include qobject.h + * #include logger.h + * + * class Counter : public QObject + * { + * Q_OBJECT + * LOG4QT_DECLARE_QCLASS_LOGGER + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)", + * \ref Log4Qt::ClassLogger "ClassLogger" + */ + #define LOG4QT_DECLARE_QCLASS_LOGGER \ + private: \ + mutable Log4Qt::ClassLogger mLog4QtClassLogger; \ + public: \ + inline Log4Qt::Logger *logger() const \ + { return mLog4QtClassLogger.logger(this); } \ + private: + + class Appender; + class LoggingEvent; + class LoggerRepository; + + /*! + * \brief The class Logger provides logging services. + * + * A pointer to a logger can be retrieved by calling Logger::logger() or + * LogManager::logger() with the class name as argument. Because a logger + * is never destroyed it is possible to store the pointer to the logger. + * This way the lookup of the pointer in the repository is only required + * on the first logging operation. The macros \ref + * Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" and + * \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER" + * provide a thread-safe implementation to store the logger pointer. + * + * \note All the functions declared in this class are thread-safe. + */ + class Logger : public QObject + { + Q_OBJECT + + /*! + * The property holds, if the logger is additive. + * + * The default is true for being additive. + * + * \sa additive(), setAdditive() + */ + Q_PROPERTY(bool additivity READ additivity WRITE setAdditivity) + + /*! + * The property holds the level used by the logger. + * + * The default is Level::NULL_INT. + * \sa level(), setLevel() + */ + Q_PROPERTY(Level level READ level WRITE setLevel) + + /*! + * The property holds the LoggerRepository of the logger. + * + * \sa loggerRepository() + */ + Q_PROPERTY(LoggerRepository* loggerRepository READ loggerRepository) + + /*! + * The property holds the name of the logger. + * + * \sa name() + */ + Q_PROPERTY(QString name READ name) + + /*! + * The property holds the parent logger of the logger. + * + * \sa parentLogger() + */ + Q_PROPERTY(Logger* parentLogger READ parentLogger) + + LOG4QT_DECLARE_QCLASS_LOGGER + + protected: + Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent = 0); + virtual ~Logger(); + private: + Logger(const Logger &rOther); // Not implemented + Logger &operator=(const Logger &rOther); // Not implemented + + public: + bool additivity() const; + QList appenders() const; + Level level() const; + LoggerRepository *loggerRepository() const; + QString name() const; + Logger *parentLogger() const; + // JAVA: ResourceBundle *resourceBundle() const; + // JAVA: void setResourceBundle(ResourceBundle *pResourceBundle); + void setAdditivity(bool additivity); + virtual void setLevel(Level level); + + void addAppender(Appender *pAppender); + Appender *appender(const QString &rName) const; + void callAppenders(const LoggingEvent &rEvent) const; + bool isAttached(Appender *pAppender) const; + + /*! + * Removes all appenders that have been previously added from this + * Logger. + * + * To allow configurators to collect events during the configuration + * process ListAppenders with the configuratorList property set, will + * not be removed. + * + * \sa LisAppender::setConfiguratorList() + */ + void removeAllAppenders(); + + void removeAppender(Appender *pAppender); + void removeAppender(const QString &rName); + // JAVA: QString resourceBundleString(const QString &rKey) const; + + Level effectiveLevel() const; + bool isDebugEnabled() const; + + /*! + * Checks if this logger is enabled for a given Level \a level. If the + * logger is enabled the function returns true. Otherwise it returns + * false. + * + * A logger is enabled for a level, if the level is greater or equal + * then the repository threshold and greater and equal then the loggers + * effective level. + * + * \sa LoggerRepository::isDisabled(), effectiveLevel() + */ + bool isEnabledFor(Level level) const; + + bool isErrorEnabled() const; + bool isFatalEnabled() const; + bool isInfoEnabled() const; + bool isTraceEnabled() const; + bool isWarnEnabled() const; + + void debug(const QString &rMessage) const; + void debug(const LogError &rLogError) const; + void debug(const char *pMessage) const; + void debug(const char *pMessage, + const QString &rArg1) const; + void debug(const char *pMessage, + int arg1) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2) const; + void debug(const char *pMessage, + int arg1, + int arg2) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void error(const QString &rMessage) const; + void error(const LogError &rLogError) const; + void error(const char *pMessage) const; + void error(const char *pMessage, + const QString &rArg1) const; + void error(const char *pMessage, + int arg1) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void error(const char *pMessage, + const QString &rArg1, int arg2) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2) const; + void error(const char *pMessage, + int arg1, + int arg2) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void fatal(const QString &rMessage) const; + void fatal(const LogError &rLogError) const; + void fatal(const char *pMessage) const; + void fatal(const char *pMessage, + const QString &rArg1) const; + void fatal(const char *pMessage, + int arg1) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + int arg1, + int arg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void info(const QString &rMessage) const; + void info(const LogError &rLogError) const; + void info(const char *pMessage) const; + void info(const char *pMessage, + const QString &rArg1) const; + void info(const char *pMessage, + int arg1) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2) const; + void info(const char *pMessage, + int arg1, + int arg2) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void log(Level level, + const QString &rMessage) const; + void log(Level level, + const LogError &rLogError) const; + void log(Level level, + const char *pMessage) const; + void log(Level level, + const char *pMessage, + const QString &rArg1) const; + void log(Level level, + const char *pMessage, + int arg1) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // JAVA: void l7dlog(Level level, + // const QString &rKey); + // JAVA: void l7dlog(Level level, + // const QString &rKey, + // const QList rParameters); + + void trace(const QString &rMessage) const; + void trace(const LogError &rLogError) const; + void trace(const char *pMessage) const; + void trace(const char *pMessage, + const QString &rArg1) const; + void trace(const char *pMessage, + int arg1) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2) const; + void trace(const char *pMessage, + int arg1, + int arg2) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + void warn(const QString &rMessage) const; + void warn(const LogError &rLogError) const; + void warn(const char *pMessage) const; + void warn(const char *pMessage, + const QString &rArg1) const; + void warn(const char *pMessage, + int arg1) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2) const; + void warn(const char *pMessage, + int arg1, + int arg2) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // LogManager operations + static Logger *logger(const QString &rName); + static Logger *logger(const char *pName); + static Logger *rootLogger(); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %Logger(name:"Log4Qt" appenders:0 additivity:true Level("NULL") + * parentLogger: "root" ) + * + * \sa QDebug, operator<<(QDebug debug, const Appender &rAppender) + */ + virtual QDebug debug(QDebug &rDebug) const; + friend QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + void forcedLog(Level level, + const QString &rMessage) const; + + protected: + mutable QReadWriteLock mObjectGuard; + private: + const QString mName; + LoggerRepository* mpLoggerRepository; + volatile bool mAdditivity; + QList< LogObjectPtr > mAppenders; + Level mLevel; + Logger *mpParent; + + // Needs to be friend to create Logger objects + friend class Hierarchy; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Logger + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * To handle subclassing the function uses the virtual member function debug(). + * This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool Logger::additivity() const + { // QReadLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAdditivity; } + + inline Level Logger::level() const + { // QReadLocker locker(&mObjectGuard); // Level is thread-safe + return mLevel; } + + inline LoggerRepository *Logger::loggerRepository() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpLoggerRepository; } + + inline QString Logger::name() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mName; } + + inline Logger *Logger::parentLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpParent; } + + inline void Logger::setAdditivity(bool additivity) + { // QWriteLocker locker(&mObjectGuard); // Read/Write of int is safe + mAdditivity = additivity; } + + // Level operations + + inline bool Logger::isDebugEnabled() const + { return isEnabledFor(Level::DEBUG_INT); } + + inline bool Logger::isErrorEnabled() const + { return isEnabledFor(Level::ERROR_INT); } + + inline bool Logger::isFatalEnabled() const + { return isEnabledFor(Level::FATAL_INT); } + + inline bool Logger::isInfoEnabled() const + { return isEnabledFor(Level::INFO_INT); } + + inline bool Logger::isTraceEnabled() const + { return isEnabledFor(Level::TRACE_INT); } + + inline bool Logger::isWarnEnabled() const + { return isEnabledFor(Level::WARN_INT); } + + // Log operations: debug + + inline void Logger::debug(const LogError &rLogError) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rLogError.toString()); } + + inline void Logger::debug(const QString &rMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rMessage); } + + inline void Logger::debug(const char *pMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::debug(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: error + + inline void Logger::error(const QString &rMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rMessage); } + + inline void Logger::error(const LogError &rLogError) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rLogError.toString()); } + + inline void Logger::error(const char *pMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::error(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::error(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: fatal + + inline void Logger::fatal(const QString &rMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rMessage); } + + inline void Logger::fatal(const LogError &rLogError) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rLogError.toString()); } + + inline void Logger::fatal(const char *pMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::fatal(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: info + + inline void Logger::info(const QString &rMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rMessage); } + + inline void Logger::info(const LogError &rLogError) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rLogError.toString()); } + + inline void Logger::info(const char *pMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::info(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::info(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: log + + inline void Logger::log(Level level, + const QString &rMessage) const + { if (isEnabledFor(level)) + forcedLog(level, rMessage); } + + inline void Logger::log(Level level, + const LogError &rLogError) const + { if (isEnabledFor(level)) + forcedLog(level, rLogError.toString()); } + + inline void Logger::log(Level level, + const char *pMessage) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: trace + + inline void Logger::trace(const QString &rMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rMessage); } + + inline void Logger::trace(const LogError &rLogError) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rLogError.toString()); } + + inline void Logger::trace(const char *pMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::trace(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: warn + + inline void Logger::warn(const QString &rMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rMessage); } + + inline void Logger::warn(const LogError &rLogError) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rLogError.toString()); } + + inline void Logger::warn(const char *pMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + inline void Logger::warn(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + inline void Logger::warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + inline void Logger::warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::Logger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGER_H diff --git a/GCV-3.6.1-T4/src/log4qt/loggerrepository.cpp b/GCV-3.6.1-T4/src/log4qt/loggerrepository.cpp new file mode 100644 index 0000000..b541bb2 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/loggerrepository.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggerrepository.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggerRepository + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository) + { + return rLoggerRepository.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/loggerrepository.h b/GCV-3.6.1-T4/src/log4qt/loggerrepository.h new file mode 100644 index 0000000..13c0488 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/loggerrepository.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGGERREPOSITORY_H +#define LOG4QT_LOGGERREPOSITORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggerRepository is abstract base class for a logger + * repository. + */ + class LoggerRepository + { + public: + // LoggerRepository(); // Use compiler default + // LoggerRepository(const LoggerRepository &rOther); // Use compiler default + // virtual ~LoggerRepository(); // Use compiler default + // LoggerRepository &operator=(const LoggerRepository &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const = 0; + virtual Logger *logger(const QString &rName) = 0; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual QList loggers() const = 0; + virtual Logger *rootLogger() const = 0; + virtual Level threshold() const = 0; + virtual void setThreshold(Level level) = 0; + virtual void setThreshold(const QString &rThreshold) = 0; + + virtual bool isDisabled(Level level) = 0; + virtual void resetConfiguration() = 0; + virtual void shutdown() = 0; + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + *\relates LoggerRepository + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * The member function is used by + * QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + * to generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggerRepository + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle subclassing the function uses the virtual member function + * debug(). This allows each class to generate its own output. + * + * \sa QDebug, debug() + */ + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LoggerRepository, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGERREPOSITORY_H diff --git a/GCV-3.6.1-T4/src/log4qt/loggingevent.cpp b/GCV-3.6.1-T4/src/log4qt/loggingevent.cpp new file mode 100644 index 0000000..161f01c --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/loggingevent.cpp @@ -0,0 +1,272 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggingevent.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/loggingevent.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" +#include "log4qt/mdc.h" +#include "log4qt/ndc.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(QMutex, sequence_guard) + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggingEvent + **************************************************************************/ + + + LoggingEvent::LoggingEvent() : + mLevel(Level::NULL_INT), + mpLogger(0), + mMessage(), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(timeStamp) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp) : + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(rNdc), + mProperties(rProperties), + mSequenceNumber(nextSequenceNumber()), + mThreadName(rThreadName), + mTimeStamp(timeStamp) + { + } + + + QString LoggingEvent::loggerName() const + { + if (mpLogger) + return mpLogger->name(); + else + return QString(); + } + + + QString LoggingEvent::toString() const + { + return level().toString() + QLatin1Char(':') + message(); + } + + + qint64 LoggingEvent::sequenceCount() + { + QMutexLocker locker(sequence_guard()); + + return msSequenceCount; + } + + + qint64 LoggingEvent::startTime() + { + return InitialisationHelper::startTime(); + } + + + void LoggingEvent::setThreadNameToCurrent() + { + if (QThread::currentThread()) + mThreadName = QThread::currentThread()->objectName(); + } + + + qint64 LoggingEvent::nextSequenceNumber() + { + QMutexLocker locker(sequence_guard()); + + return ++msSequenceCount; + } + + + qint64 LoggingEvent::msSequenceCount = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, const LoggingEvent &rLoggingEvent) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLoggingEvent.mLevel + << rLoggingEvent.loggerName() + << rLoggingEvent.mMessage + << rLoggingEvent.mNdc + << rLoggingEvent.mProperties + << rLoggingEvent.mSequenceNumber + << rLoggingEvent.mThreadName + << rLoggingEvent.mTimeStamp; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, LoggingEvent &rLoggingEvent) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString logger; + stream >> rLoggingEvent.mLevel + >> logger + >> rLoggingEvent.mMessage + >> rLoggingEvent.mNdc + >> rLoggingEvent.mProperties + >> rLoggingEvent.mSequenceNumber + >> rLoggingEvent.mThreadName + >> rLoggingEvent.mTimeStamp; + if (logger.isEmpty()) + rLoggingEvent.mpLogger = 0; + else + rLoggingEvent.mpLogger = Logger::logger(logger); + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent) + { + QString logger; + if (rLoggingEvent.logger() != 0) + logger = rLoggingEvent.logger()->name(); + + debug.nospace() << "LoggingEvent(" + << "level:" << rLoggingEvent.level().toString() << " " + << "logger:" << logger << " " + << "message:" << rLoggingEvent.message() << " " + << "sequencenumber:" << rLoggingEvent.sequenceNumber() << " " + << "threadname:" << rLoggingEvent.threadName() << " " + << "timestamp:" << rLoggingEvent.timeStamp() + << "(" << DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()) << ")" + << "sequenceCount:" << rLoggingEvent.sequenceCount() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/loggingevent.h b/GCV-3.6.1-T4/src/log4qt/loggingevent.h new file mode 100644 index 0000000..87e2ed6 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/loggingevent.h @@ -0,0 +1,221 @@ +/****************************************************************************** +* +* package: Log4Qt +* file: loggingevent.h +* created: September 2007 +* author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * +******************************************************************************/ + +#ifndef LOG4QT_LOG4QTEVENT_H +#define LOG4QT_LOG4QTEVENT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggingEvent is the internal representation of a + * logging event. + * + * The class uses milliseconds since 1970-01-01T00:00:00, Coordinated + * Universal Time for time values. For converstion from and to QDateTime + * use DateTime. + */ + class LoggingEvent + { + public: + LoggingEvent(); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash &rProperties, + const QString &rThreadName, + qint64 timeStamp); + // LoggingEvent(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + // virtual ~LoggingEvent(); // Use compiler default + // LoggingEvent &operator=(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + + // JAVA: QString fqnOfLoggerClass() const; + Level level() const; + // LocationInformation locationInformation() const; + const Logger *logger() const; + QString message() const; + QHash mdc() const; + QString ndc() const; + QHash properties() const; + qint64 sequenceNumber() const; + QString threadName() const; + // JAVA: ThrowableInformation throwableInformation() const; + qint64 timeStamp() const; + + // JAVA: bool locationInformationExists() const; + QString loggerName() const; + QString property(const QString &rKey) const; + QStringList propertyKeys() const; + void setProperty(const QString &rKey, const QString &rValue); + // JAVA: QString throwableStrRep() const; + QString toString() const; + static qint64 sequenceCount(); + static qint64 startTime(); + + private: + void setThreadNameToCurrent(); + static qint64 nextSequenceNumber(); + + private: + Level mLevel; + const Logger *mpLogger; + QString mMessage; + QString mNdc; + QHash mProperties; + qint64 mSequenceNumber; + QString mThreadName; + qint64 mTimeStamp; + static qint64 msSequenceCount; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + friend QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LoggingEvent + * + * Writes the given error \a rLoggingEvent to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + + /*! + * \relates LoggingEvent + * + * Reads an error from the given stream \a rStream into the given + * error \a rLoggingEvent, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggingEvent + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * + * %LoggingEvent(level:"WARN" logger:"Log4Qt::Properties" + * message:"Unknown escape sequence '\j' in property starting at line 1" + * sequencenumber:14 threadname:"main" + * timestamp:1194337148937(QDateTime("Tue Nov 6 03:19:08 2007") ) + * sequenceCount: 14 ) + * + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Level LoggingEvent::level() const + { return mLevel; } + + inline const Logger *LoggingEvent::logger() const + { return mpLogger; } + + inline QString LoggingEvent::message() const + { return mMessage; } + + inline QHash LoggingEvent::mdc() const + { return mProperties; } + + inline QString LoggingEvent::ndc() const + { return mNdc; } + + inline QHash LoggingEvent::properties() const + { return mProperties; } + + inline qint64 LoggingEvent::sequenceNumber() const + { return mSequenceNumber; } + + inline QString LoggingEvent::threadName() const + { return mThreadName; } + + inline qint64 LoggingEvent::timeStamp() const + { return mTimeStamp; } + + inline QString LoggingEvent::property(const QString &rKey) const + { return mProperties.value(rKey); } + + inline QStringList LoggingEvent::propertyKeys() const + { return QStringList(mProperties.keys()); } + + inline void LoggingEvent::setProperty(const QString &rKey, const QString &rValue) + { mProperties.insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LoggingEvent) +Q_DECLARE_TYPEINFO(Log4Qt::LoggingEvent, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LOG4QTEVENT_H diff --git a/GCV-3.6.1-T4/src/log4qt/logmanager.cpp b/GCV-3.6.1-T4/src/log4qt/logmanager.cpp new file mode 100644 index 0000000..2c5e9ba --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/logmanager.cpp @@ -0,0 +1,504 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/logmanager.h" + +#include +#include +#include +#include +#include +#include +#include "log4qt/consoleappender.h" +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/hierarchy.h" +#include "log4qt/propertyconfigurator.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/varia/denyallfilter.h" +#include "log4qt/varia/levelrangefilter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) + LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) + + + + /************************************************************************** + * Class implementation: LogManager + **************************************************************************/ + + + LogManager::LogManager() : + mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() + mpLoggerRepository(new Hierarchy()), + mHandleQtMessages(false), + mOldQtMsgHandler(0) + { + } + + + LogManager::~LogManager() + { + static_logger()->warn("Unexpected destruction of LogManager"); + + // doSetConfigureHandleQtMessages(false); + // delete mpLoggerRepository; + } + + + Logger *LogManager::rootLogger() + { + return instance()->mpLoggerRepository->rootLogger(); + } + + + QList LogManager::loggers() + { + return instance()->mpLoggerRepository->loggers(); + } + + + Level LogManager::threshold() + { + return instance()->mpLoggerRepository->threshold(); + } + + + void LogManager::setThreshold(Level level) + { + instance()->mpLoggerRepository->setThreshold(level); + } + + + bool LogManager::exists(const char *pName) + { + return instance()->mpLoggerRepository->exists(QLatin1String(pName)); + } + + + LogManager *LogManager::instance() + { + // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive + // to construct, an exit handler must be set and doStartup must be + // called. + + if (!mspInstance) + { + QMutexLocker locker(singleton_guard()); + if (!mspInstance) + { + mspInstance = new LogManager; + // qAddPostRoutine(shutdown); + atexit(shutdown); + mspInstance->doConfigureLogLogger(); + mspInstance->welcome(); + mspInstance->doStartup(); + } + } + return mspInstance; + } + + + Logger *LogManager::logger(const QString &rName) + { + return instance()->mpLoggerRepository->logger(rName); + } + + + void LogManager::resetConfiguration() + { + setHandleQtMessages(false); + instance()->mpLoggerRepository->resetConfiguration(); + configureLogLogger(); + } + + + const char* LogManager::version() + { + return LOG4QT_VERSION_STR; + } + + + void LogManager::shutdown() + { + instance()->mpLoggerRepository->shutdown(); + } + + + void LogManager::doSetHandleQtMessages(bool handleQtMessages) + { + QMutexLocker locker(&mObjectGuard); + + if (instance()->mHandleQtMessages == handleQtMessages) + return; + + instance()->mHandleQtMessages = handleQtMessages; + if (instance()->mHandleQtMessages) + { + static_logger()->trace("Activate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); +#else + instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); +#endif + } + else + { + static_logger()->trace("Deactivate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + qInstallMsgHandler(instance()->mOldQtMsgHandler); +#else + qInstallMessageHandler(instance()->mOldQtMsgHandler); +#endif + } + } + + + void LogManager::doConfigureLogLogger() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Level + QString value = InitialisationHelper::setting(QLatin1String("Debug"), + QLatin1String("ERROR")); + logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); + + // Common layout + TTCCLayout *p_layout = new TTCCLayout(); + p_layout->setName(QLatin1String("LogLog TTCC")); + p_layout->setContextPrinting(false); + p_layout->activateOptions(); + + // Common deny all filter + Filter *p_denyall = new DenyAllFilter(); + p_denyall->activateOptions(); + + // ConsoleAppender on stdout for all events <= INFO + ConsoleAppender *p_appender; + LevelRangeFilter *p_filter; + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::NULL_INT); + p_filter->setLevelMax(Level::INFO_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stdout")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + + // ConsoleAppender on stderr for all events >= WARN + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::WARN_INT); + p_filter->setLevelMax(Level::OFF_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stderr")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + } + + + void LogManager::doStartup() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Override + QString default_value = QLatin1String("false"); + QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), + default_value); + if (value != default_value) + { + static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); + return; + } + + // Configuration using setting Configuration + value = InitialisationHelper::setting(QLatin1String("Configuration")); + if (QFile::exists(value)) + { + static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); + PropertyConfigurator::configure(value); + return; + } + + // Configuration using setting + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + QSettings s; + s.beginGroup(log4qt_group); + if (s.childGroups().contains(properties_group)) + { + const QString group(QLatin1String("Log4Qt/Properties")); + static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); + s.beginGroup(properties_group); + PropertyConfigurator::configure(s); + return; + } + } + + // Configuration using default file + const QString default_file(QLatin1String("log4qt.properties")); + if (QFile::exists(default_file)) + { + static_logger()->debug("Default initialisation configures from default file '%1'", default_file); + PropertyConfigurator::configure(default_file); + return; + } + + static_logger()->debug("Default initialisation leaves package unconfigured"); + } + + + void LogManager::welcome() + { + static_logger()->info(qPrintable(QObject::tr("Initialising Log4Qt %1")), + QLatin1String(LOG4QT_VERSION_STR)); + + // Debug: Info + if (static_logger()->isDebugEnabled()) + { + // Create a nice timestamp with UTC offset + DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); + QString offset; + { + QDateTime utc = start_time.toUTC(); + QDateTime local = start_time.toLocalTime(); + QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); + int min = utc.secsTo(local_as_utc) / 60; + if (min < 0) + offset += QLatin1Char('-'); + else + offset += QLatin1Char('+'); + min = abs(min); + offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); + offset += QLatin1Char(':'); + offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); + } + static_logger()->debug("Program startup time is %1 (UTC%2)", + start_time.toString(QLatin1String("ISO8601")), + offset); + static_logger()->debug("Internal logging uses the level %1", + logLogger()->level().toString()); + } + + // Trace: Dump settings + if (static_logger()->isTraceEnabled()) + { + static_logger()->trace("Settings from the system environment:"); + QString entry; + Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) + static_logger()->trace(" %1: '%2'", + entry, + InitialisationHelper::environmentSettings().value(entry)); + + static_logger()->trace("Settings from the application settings:"); + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + static_logger()->trace(" %1:", log4qt_group); + QSettings s; + s.beginGroup(log4qt_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + static_logger()->trace(" %1/%2:", log4qt_group, properties_group); + s.beginGroup(properties_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + } else + static_logger()->trace(" QCoreApplication::instance() is not available"); + } + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) + { + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, pMessage); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#else + void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) + { + Q_UNUSED(context); + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, message); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, message.toUtf8().constData()); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } +#endif + + + + LogManager *LogManager::mspInstance = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const LogManager &rLogManager) + { + Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 + QList loggers = rLogManager.loggers(); + debug.nospace() << "LogManager(" + << "loggerrepository:" << *rLogManager.loggerRepository() + << "log-level:" << rLogManager.logLogger()->level().toString() + << "log-appenders:" << rLogManager.logLogger()->appenders().count() + << "qt-level:" << rLogManager.qtLogger()->level().toString() + << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() + << "handleqtmessages:" << rLogManager.handleQtMessages() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/logmanager.h b/GCV-3.6.1-T4/src/log4qt/logmanager.h new file mode 100644 index 0000000..27111a0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/logmanager.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LOGMANAGER_H +#define LOG4QT_LOGMANAGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include + +#include +#include +#include +#include +#include "log4qt/level.h" +#include "log4qt/logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggerRepository; + + /*! + * \brief The class LogManager manages Logger in the default + * LoggerRepository. + * + * The LogManager manages logger in a single Hierarchy instance. It + * provides access to special logger over the logLogger(), qtLogger() + * and rootLogger() member functions. + * + * The LogManager is handling the initialisation on startup. The + * initialisation procedure will first attempt to configure the package + * based on environment variables. If the attempt fails it will check for + * the existence of configuration files in several location. For detailed + * description of the initialisation procedure see \ref Init + * "Initialization procedure". + * + * Messages created by qDebug(), qWarning(), qCritical() and qFatal() can + * be can be handled by the LogManager. By default the message handling + * is disabled. It can be enabled by calling setHandleQtMessages(). Once + * enabled all messages are logged using the logger qtLogger(). + * + * The Log4Qt runtime version is accessible over version(). The macros + * \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION" and + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" provide the + * compile time version. + * + * \note All the functions declared in this class are thread-safe. + */ + class LogManager + { + private: + LogManager(); + LogManager(const LogManager &rOther); // Not implemented + virtual ~LogManager(); + LogManager &operator=(const LogManager &rOther); // Not implemented + + public: + /*! + * Returns if the handling of messages created by calls to qDebug(), + * qWarning(), qCritical() and qFatal() is activated. + * + * \sa setHandleQtMessages() + */ + static bool handleQtMessages(); + + static LoggerRepository *loggerRepository(); + + /*! + * Returns the logger used for logging internal messages. See + * \ref LogLog "Logging within the package" for more details. + * + * Calling this function is equivalent to calling logger("Log4Qt"). + */ + static Logger *logLogger(); + + /*! + * Returns a pointer to the logger used for logging messages created by + * calls to qDebug(), qWarning(), qCritical() and qFatal(). + * + * Calling this function is equivalent to calling logger("Qt"). + * + * \sa setHandleQtMessages() + */ + static Logger *qtLogger(); + + static Logger *rootLogger(); + static QList loggers(); + static Level threshold(); + static void setThreshold(Level level); + + /*! + * Activates or deactivates the handling of messages created by calls + * to qDebug(), qWarning(), qCritical() and qFatal() is activated. + * + * If activated, a Qt message handler is installed. Messages are logged + * using the logger returned by qtLogger(). For fatal messages the same + * exit procedure is implemented as for qFatal(). + * + * The following mappping is used from QtMsgType to Level: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    QtMsgType     %Level
QtDebugMsg Level::DEBUG_INT
QtWarningMsg Level::WARN_INT
QtCriticalMsg Level::ERROR_INT
QtFatalMsg Level::FATAL_INT
QtSystemMsg Level::TRACE_INT
+ * + * The default value is false for not handling Qt messages. + * + * \sa handleQtMessages(), qInstallMsgHandler(), qFatal() + */ + static void setHandleQtMessages(bool handleQtMessages); + + /*! + * Configures the logging for the package to its default behaviour. + * + * The logger logLogger() is configured to be not additive. Messages + * with the level Level::ERROR_INT and Level::FATAL_INT are written + * to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is + * read from the system environment or application settings using + * InitialisationHelper::setting() with the key \c Debug. If a level + * value is found, but it is not a valid Level string, + * Level::DEBUG_INT is used. If no level string is found + * Level::ERROR_INT is used. + * + * The function does not remove any appender from the logger + * logLogger(). + * + * \sa \ref LogLog "Logging within the package", + * \ref Env "Environment Variables", + * resetConfiguration(), InitialisationHelper::setting() + */ + static void configureLogLogger(); + + static bool exists(const char *pName); + // JAVA: void fireAddAppenderEvent(Logger *pLogger, Appender *pAppender); + + /*! + * Returns the LogManager instance. + */ + static LogManager *instance(); + + static Logger *logger(const QString &rName); + + /*! + * Reset all values contained in logger repository to their default. + * + * All appenders are removed from all loggers. The loggers are handled + * in no particular order. The last loggers to be reset are qtLogger(), + * logLogger() and rootLogger() in that order. + * + * The handling of messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() is deactivated. + * + * The internal logging is initialised to its default bahaviour + * using configureLogLogger(). + * + * \sa LoggerRepository::resetConfiguration(), setHandleQtMessages(), + * configureLogLogger() + */ + static void resetConfiguration(); + + static void shutdown(); + + /*! + * Executes the default initialisation procedure of the package. + * + * The function will test for the setting \c DefaultInitOverride in + * the system environment and application settings using + * \ref InitialisationHelper::setting(). If the value is present and + * set to anything else then \c false, the initialisation is aborted. + *
+ * The system environment and application settings are tested for the + * setting \c Configuration. If it is found and it is a valid path to + * a file, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting + * \c Configuration is not available and a QCoreApplication object is + * present, the application settings are tested for a group + * \c Log4Qt/Properties. If the group exists, the package is configured + * with the setting using the + * \ref PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration + * file nor configuration settings could be found, the current working + * directory is searched for the file \c "log4qt.properties". If it is + * found, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * \sa \ref Init "Initialization procedure", + * \ref Env "Environment Variables", + * InitialisationHelper::setting() + */ + static void startup(); + + /*! + * Returns the version number of Log4Qt at run-time. This may be a + * different version than the version the application was compiled + * against. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" + + */ + static const char* version(); + + private: + void doSetHandleQtMessages(bool handleQtMessages); + void doConfigureLogLogger(); + void doStartup(); + void welcome(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + static void qtMessageHandler(QtMsgType type, + const char *pMessage); +#else + static void qtMessageHandler(QtMsgType type, + const QMessageLogContext &context, + const QString &message); +#endif + + + private: + mutable QMutex mObjectGuard; + LoggerRepository *mpLoggerRepository; + Logger *mpNullLogger; + bool mHandleQtMessages; +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QtMsgHandler mOldQtMsgHandler; +#else + QtMessageHandler mOldQtMsgHandler; +#endif + static LogManager *mspInstance; + }; + + + /*************************************************************************** + * Operators, Helper + ***************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogManager + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %LogManager(loggerrepository:Hierarchy(loggers:6 root-level:"DEBUG" + * root-appenders:0 log-level: "NULL" log-appenders:0 + * qt-level: "NULL" qt-appenders:0 handleqtmessages: false ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogManager &rLogManager); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LoggerRepository *LogManager::loggerRepository() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mpLoggerRepository; } + + inline bool LogManager::handleQtMessages() + { // QMutexLocker locker(&instance()->mObjectGuard); // Read/Write of bool is safe + return instance()->mHandleQtMessages; } + + inline Logger *LogManager::logLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Log4Qt")); } + + inline Logger *LogManager::qtLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Qt")); } + + inline void LogManager::setHandleQtMessages(bool handleQtMessages) + { instance()->doSetHandleQtMessages(handleQtMessages); } + + inline void LogManager::configureLogLogger() + { instance()->doConfigureLogLogger(); } + + inline void LogManager::startup() + { instance()->doStartup(); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogManager, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGMANAGER_H diff --git a/GCV-3.6.1-T4/src/log4qt/mdc.cpp b/GCV-3.6.1-T4/src/log4qt/mdc.cpp new file mode 100644 index 0000000..5ba2ba8 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/mdc.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/mdc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: MDC + **************************************************************************/ + + + QString MDC::get(const QString &rKey) + { + if (!instance()->mHash.hasLocalData()) + return QString(); + + return instance()->mHash.localData()->value(rKey); + } + + + QHash MDC::context() + { + if (!instance()->mHash.hasLocalData()) + return QHash(); + + return *instance()->mHash.localData(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(MDC) + + + QHash *MDC::localData() + { + if (!instance()->mHash.hasLocalData()) + instance()->mHash.setLocalData(new QHash); + return instance()->mHash.localData(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const MDC &rMDC) + { + Q_UNUSED(rMDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "MDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "context:" << rMDC.context() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/mdc.h b/GCV-3.6.1-T4/src/log4qt/mdc.h new file mode 100644 index 0000000..5e8fce9 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/mdc.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_MDC_H +#define LOG4QT_MDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + +/*! + * \brief The class MDC implements a mapped diagnostic context. + * + * \note All the functions declared in this class are thread-safe. + */ + class MDC + { + private: + MDC(); + MDC(const MDC &rOther); // Not implemented + // virtual ~MDC(); // Use compiler default + MDC &operator=(const MDC &rOther); // Not implemented + + public: + static QString get(const QString &rKey); + static QHash context(); + + /*! + * Returns the MDC instance. + */ + static MDC *instance(); + + static void put(const QString &rKey, const QString &rValue); + static void remove(const QString &rKey); + + private: + static QHash *localData(); + + private: + QThreadStorage< QHash * > mHash; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates MDC + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %MDC(thread:"main" context:QHash(("login", "Peter")("database", "UAT")) ) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const MDC &rMDC); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline MDC::MDC() : + mHash() + {} + + inline void MDC::put(const QString &rKey, const QString &rValue) + { localData()->insert(rKey, rValue); } + + inline void MDC::remove(const QString &rKey) + { localData()->remove(rKey); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::MDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_MDC_H diff --git a/GCV-3.6.1-T4/src/log4qt/ndc.cpp b/GCV-3.6.1-T4/src/log4qt/ndc.cpp new file mode 100644 index 0000000..17ebd47 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/ndc.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + *****************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ndc.h" + +#include +#include +#include +#include "log4qt/helpers/initialisationhelper.h" +#include "log4qt/logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt:NDC) + + + + /************************************************************************** + * Class implementation: NDC + **************************************************************************/ + + + void NDC::clear() + { + if (!instance()->mStack.hasLocalData()) + return; + + instance()->mStack.localData()->clear(); + } + + + int NDC::depth() + { + if (!instance()->mStack.hasLocalData()) + return 0; + + return instance()->mStack.localData()->count(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(NDC) + + + QString NDC::pop() + { + if (!instance()->mStack.hasLocalData() || instance()->mStack.localData()->isEmpty()) + { + logger()->warn("Requesting pop from empty NDC stack"); + return QString(); + } + + return instance()->mStack.localData()->pop(); + } + + + void NDC::push(const QString &rMessage) + { + if (!instance()->mStack.hasLocalData()) + instance()->mStack.setLocalData(new QStack); + + instance()->mStack.localData()->push(rMessage); + } + + + void NDC::setMaxDepth(int maxDepth) + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->size() <= maxDepth) + return; + + instance()->mStack.localData()->resize(maxDepth); + } + + + QString NDC::peek() + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->isEmpty()) + return QString(); + + return instance()->mStack.localData()->top(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const NDC &rNDC) + { + Q_UNUSED(rNDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "NDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "peek:" << rNDC.peek() << " " + << "depth:" << rNDC.depth() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/ndc.h b/GCV-3.6.1-T4/src/log4qt/ndc.h new file mode 100644 index 0000000..e2c4210 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/ndc.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NDC_H +#define LOG4QT_NDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include +#include +#include +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class NDC implements a nested diagnostic context. + * + * The method remove() is not required. QThreadStorage cleans up on thread + * exit. + * + * \note All the functions declared in this class are thread-safe. + */ + class NDC + { + private: + NDC(); + NDC(const NDC &rOther); // Not implemented + // virtual ~NDC(); // Use compiler default + NDC &operator=(const NDC &rOther); // Not implemented + + public: + static void clear(); + // JAVA: static QStack cloneStack(); + // JAVA: static QString get(); + static int depth(); + // JAVA: inherit(Stack stack) + + /*! + * Returns the NDC instance. + */ + static NDC *instance(); + + static QString pop(); + static void push(const QString &rMessage); + // JAVA: static void remove(); // Not required + static void setMaxDepth(int maxDepth); + static QString peek(); + + private: + QThreadStorage< QStack * > mStack; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates NDC + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NDC(thread:"main" peek:"i = 3" depth:4) + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const NDC &rNDC); + #endif // QT_NO_DEBUG_STREAM + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + inline NDC::NDC() : + mStack() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NDC_H diff --git a/GCV-3.6.1-T4/src/log4qt/patternlayout.cpp b/GCV-3.6.1-T4/src/log4qt/patternlayout.cpp new file mode 100644 index 0000000..a93099f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/patternlayout.cpp @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/patternlayout.h" + +#include +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: PatternLayout + **************************************************************************/ + + + PatternLayout::PatternLayout(QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(DEFAULT_CONVERSION_PATTERN); + } + + + PatternLayout::PatternLayout(const QString &rPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(rPattern); + } + + + PatternLayout::PatternLayout(ConversionPattern conversionPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(conversionPattern); + } + + + PatternLayout::~PatternLayout() + { + delete mpPatternFormatter; + } + + + void PatternLayout::setConversionPattern(ConversionPattern conversionPattern) + { + switch (conversionPattern) + { + case DEFAULT_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%m%n")); + break; + case TTCC_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%r [%t] %p %c %x - %m%n")); + break; + default: + Q_ASSERT_X(false, "PatternLayout::setConversionFormat", "Unkown ConversionFormat"); + setConversionPattern(QString()); + } + } + + + QString PatternLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "PatternLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void PatternLayout::updatePatternFormatter() + { + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(mPattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug PatternLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "PatternLayout(" + << "name:" << name() << " " + << "pattern:" << conversionPattern() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/patternlayout.h b/GCV-3.6.1-T4/src/log4qt/patternlayout.h new file mode 100644 index 0000000..2152f4b --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/patternlayout.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PATTERNLAYOUT_H +#define LOG4QT_PATTERNLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class PatternFormatter; + + /*! + * \brief The class PatternLayout outputs a logging event based on a + * pattern string. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class PatternLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds the conversion pattern used by the appender. + * + * The default is "%m%n". + * + * \sa conversionPattern(), setConversionPattern() + */ + Q_PROPERTY(QString conversionPattern READ conversionPattern WRITE setConversionPattern) + + public: + /*! + * The enum ConversionPattern defines constants for pattern strings. + * + * \sa setConversionPattern(ConversionPattern); + */ + enum ConversionPattern + { + /*! The default conversion pattern string is "%m,%n". */ + DEFAULT_CONVERSION_PATTERN, + /*! + * The ttcc conversion pattern string is + * "%r [%t] %p %c %x - %m%n". + */ + TTCC_CONVERSION_PATTERN, + }; + Q_ENUMS(ConversionPattern) + + PatternLayout(QObject *pParent = 0); + PatternLayout(const QString &rPattern, + QObject *pParent = 0); + + /*! + * Creates a PatternLayout with the conversion pattern value specified + * by the \a conversionPattern constant. + */ + PatternLayout(ConversionPattern conversionPattern, + QObject *pParent = 0); + + virtual ~PatternLayout(); + private: + PatternLayout(const PatternLayout &rOther); // Not implemented + PatternLayout &operator=(const PatternLayout &rOther); // Not implemented + + public: + QString conversionPattern() const; + void setConversionPattern(const QString &rPattern); + + /*! + * Sets the conversion pattern to the value specified by the + * \a conversionPattern constant. + */ + void setConversionPattern(ConversionPattern conversionPattern); + + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %PatternLayout(name:"PL" pattern:"%r [%t] %p %c %x - %m%n" + * "referencecount:3") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + QString mPattern; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString PatternLayout::conversionPattern() const + { return PatternLayout::mPattern; } + + inline void PatternLayout::setConversionPattern(const QString &rPattern) + { mPattern = rPattern; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::PatternLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PATTERNLAYOUT_H diff --git a/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.cpp b/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.cpp new file mode 100644 index 0000000..76f3ee0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.cpp @@ -0,0 +1,588 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/propertyconfigurator.h" + +#include +#include +#include "log4qt/helpers/configuratorhelper.h" +#include "log4qt/helpers/factory.h" +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/helpers/properties.h" +#include "log4qt/appender.h" +#include "log4qt/layout.h" +#include "log4qt/logger.h" +#include "log4qt/logmanager.h" +#include "log4qt/loggerrepository.h" +#include "log4qt/varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator) + + + + /************************************************************************** + * Class implementation: PropertyConfigurator + **************************************************************************/ + + + bool PropertyConfigurator::doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromProperties(rProperties, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromFile(rConfigFileName, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromSettings(rSettings, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::configure(const Properties &rProperties) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rProperties); + } + + + bool PropertyConfigurator::configure(const QString &rConfigFilename) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rConfigFilename); + } + + + bool PropertyConfigurator::configure(const QSettings &rSettings) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rSettings); + } + + + bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName) + { + // Stop an existing watch to avoid a possible concurrent configuration + ConfiguratorHelper::setConfigurationFile(); + if (rConfigFileName.isEmpty()) + return true; + + PropertyConfigurator configurator; + bool result = configurator.doConfigure(rConfigFileName); + ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure); + return result; + } + + + void PropertyConfigurator::configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + QFile file(rConfigFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"), + CONFIGURATOR_OPENING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + Properties properties; + properties.load(&file); + if (file.error()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"), + CONFIGURATOR_READING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + if (!pLoggerRepository) + pLoggerRepository = LogManager::loggerRepository(); + + configureGlobalSettings(rProperties, pLoggerRepository); + configureRootLogger(rProperties, pLoggerRepository); + configureNonRootElements(rProperties, pLoggerRepository); + mAppenderRegistry.clear(); + } + + + void PropertyConfigurator::configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + Properties properties; + properties.load(rSettings); + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null."); + + const QLatin1String key_reset("log4j.reset"); + const QLatin1String key_debug("log4j.Debug"); + const QLatin1String key_config_debug("log4j.configDebug"); + const QLatin1String key_threshold("log4j.threshold"); + const QLatin1String key_handle_qt_messages("log4j.handleQtMessages"); + + // Test each global setting and set it + // - Reset: log4j.reset + // - Debug: log4j.Debug, log4j.configDebug + // - Threshold: log4j.threshold + // - Handle Qt Messages: log4j.handleQtMessages + + // Reset + QString value = rProperties.property(key_reset); + if (!value.isEmpty() && OptionConverter::toBoolean(value, false)) + { + // Use LogManager and not pLoggerRepository to reset internal + // logging. + LogManager::resetConfiguration(); + logger()->debug("Reset configuration"); + } + + // Debug + value = rProperties.property(key_debug); + if (value.isNull()) + { + value = rProperties.property(key_config_debug); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug); + } + if (!value.isNull()) + { + // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting + bool ok; + Level level = Level::fromString(value, &ok); + if (!ok) + level = Level::DEBUG_INT; + LogManager::logLogger()->setLevel(level); + logger()->debug("Set level for Log4Qt logging to %1", + LogManager::logLogger()->level().toString()); + } + + // Threshold + value = rProperties.property(key_threshold); + if (!value.isNull()) + { + pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT)); + logger()->debug("Set threshold for LoggerRepository to %1", + pLoggerRepository->threshold().toString()); + } + + // Handle Qt messages + value = rProperties.property(key_handle_qt_messages); + if (!value.isNull()) + { + LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false)); + logger()->debug("Set handling of Qt messages LoggerRepository to %1", + QVariant(LogManager::handleQtMessages()).toString()); + } + } + + + void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null."); + + const QString logger_prefix = QLatin1String("log4j.logger."); + const QString category_prefix = QLatin1String("log4j.category."); + + // Iterate through all entries: + // - Test for the logger/category prefix + // - Convert JAVA class names to C++ ones + // - Parse logger data (Level, Appender) + // - Parse logger additivity + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + QString java_name; + if (key.startsWith(logger_prefix)) + java_name = key.mid(logger_prefix.length()); + else if (key.startsWith(category_prefix)) + java_name = key.mid(category_prefix.length()); + QString cpp_name = OptionConverter::classNameJavaToCpp(java_name); + if (!java_name.isEmpty()) + { + Logger *p_logger = pLoggerRepository->logger(cpp_name); + QString value = OptionConverter::findAndSubst(rProperties, key); + parseLogger(rProperties, p_logger, key, value); + parseAdditivityForLogger(rProperties, p_logger, java_name); + } + } + } + + + void PropertyConfigurator::configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null."); + + const QLatin1String key_root_logger("log4j.rootLogger"); + const QLatin1String key_root_category("log4j.rootCategory"); + + // - Test for the logger/category prefix + // - Parse logger data for root logger + + QString key = key_root_logger; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + key = key_root_category; + value = OptionConverter::findAndSubst(rProperties, key); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger); + } + + if (value.isNull()) + logger()->debug("Could not find root logger information. Is this correct?"); + else + parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value); + } + + + void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const + { + Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null."); + + const QLatin1String additivity_prefix("log4j.additivity."); + + // - Lookup additivity key for logger + // - Set additivity, if specified + + QString key = additivity_prefix + rLog4jName; + QString value = OptionConverter::findAndSubst(rProperties, key); + logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value); + if (!value.isEmpty()) + { + bool additivity = OptionConverter::toBoolean(value, true); + logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString()); + pLogger->setAdditivity(additivity); + } + } + + + LogObjectPtr PropertyConfigurator::parseAppender(const Properties &rProperties, + const QString &rName) + { + // - Test if appender has been parsed before + // - Find appender key + // - Create appender object + // - Set layout, if required by appender + // - Set properties + // - Activate options + // - Add appender to registry + + const QLatin1String appender_prefix("log4j.appender."); + + logger()->debug("Parsing appender named '%1'", rName); + + if (mAppenderRegistry.contains(rName)) + { + logger()->debug("Appender '%1' was already parsed.", rName); + return mAppenderRegistry.value(rName); + } + + QString key = appender_prefix + rName; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"), + CONFIGURATOR_MISSING_APPENDER_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rName; + logger()->error(e); + return 0; + } + LogObjectPtr p_appender = Factory::createAppender(value); + if (!p_appender) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"), + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rName; + logger()->error(e); + return 0; + } + p_appender->setName(rName); + + if (p_appender->requiresLayout()) + { + LogObjectPtr p_layout = parseLayout(rProperties, key); + if (p_layout) + p_appender->setLayout(p_layout); + else + return 0; + } + + QStringList exclusions; + exclusions << QLatin1String("layout"); + setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender); + AppenderSkeleton *p_appenderskeleton = qobject_cast(p_appender); + if (p_appenderskeleton) + p_appenderskeleton->activateOptions(); + + mAppenderRegistry.insert(rName, p_appender); + return p_appender; + } + + + LogObjectPtr PropertyConfigurator::parseLayout(const Properties &rProperties, + const QString &rAppenderKey) + { + Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty."); + + // - Find layout key + // - Create layput object + // - Set properties + // - Activate options + + const QLatin1String layout_suffix(".layout"); + + logger()->debug("Parsing layout for appender named '%1'", rAppenderKey); + + QString key = rAppenderKey + layout_suffix; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"), + CONFIGURATOR_MISSING_LAYOUT_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rAppenderKey; + logger()->error(e); + return 0; + } + LogObjectPtr p_layout = Factory::createLayout(value); + if (!p_layout) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layout of class '%1' requested by appender '%2'"), + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rAppenderKey; + logger()->error(e); + return 0; + } + + QStringList exclusions; + setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout); + p_layout->activateOptions(); + + return p_layout; + } + + + void PropertyConfigurator::parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue) + { + Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null."); + Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty."); + + const QLatin1String keyword_inherited("INHERITED"); + + // - Split value on comma + // - If level value, is specified + // - Test for NULL and INHERITED + // - Ensure root logger is not set to NULL + // - Set level + // - For each entry + // - Create Appender + + logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue); + QStringList appenders = rValue.split(QLatin1Char(',')); + QStringListIterator i (appenders); + + // First entry is the level. There will be always one entry, even if the rValue is + // empty or does not contain a comma. + QString value = i.next().trimmed(); + if (!value.isEmpty()) + { + Level level; + if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0) + level = Level::NULL_INT; + else + level = OptionConverter::toLevel(value, Level::DEBUG_INT); + if (level == Level::NULL_INT && pLogger->name() == QString()) + logger()->warn("The root logger level cannot be set to NULL."); + else + { + pLogger->setLevel(level); + logger()->debug("Set level for logger '%1' to '%2'", + pLogger->name(), pLogger->level().toString()); + } + } + + pLogger->removeAllAppenders(); + while(i.hasNext()) + { + value = i.next().trimmed(); + if(value.isEmpty()) + continue; + LogObjectPtr p_appender = parseAppender(rProperties, value); + if (p_appender) + pLogger->addAppender(p_appender); + } + } + + + void PropertyConfigurator::setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject) + { + Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty."); + Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null."); + + // Iterate through all entries: + // - Test for prefix to determine, if setting is for object + // - Skip empty property name + // - Skip property names in exclusion list + // - Set property on object + + logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'", + QLatin1String(pObject->metaObject()->className()), + rPrefix); + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + if (!key.startsWith(rPrefix)) + continue; + QString property = key.mid(rPrefix.length()); + if (property.isEmpty()) + continue; + QStringList split_property = property.split(QLatin1Char('.')); + if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive)) + continue; + QString value = OptionConverter::findAndSubst(rProperties, key); + Factory::setObjectProperty(pObject, property, value); + } + } + + + void PropertyConfigurator::startCaptureErrors() + { + Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty."); + + mpConfigureErrors = new ListAppender; + mpConfigureErrors->setName(QLatin1String("PropertyConfigurator")); + mpConfigureErrors->setConfiguratorList(true); + mpConfigureErrors->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(mpConfigureErrors); + } + + + bool PropertyConfigurator::stopCaptureErrors() + { + Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty."); + + LogManager::logLogger()->removeAppender(mpConfigureErrors); + ConfiguratorHelper::setConfigureError(mpConfigureErrors->list()); + bool result = (mpConfigureErrors->list().count() == 0); + mpConfigureErrors = 0; + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator) + { + Q_UNUSED(rPropertyConfigurator); + debug.nospace() << "PropertyConfigurator(" + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Logging diff --git a/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.h b/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.h new file mode 100644 index 0000000..ddf45e5 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/propertyconfigurator.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_PROPERTYCONFIGURATOR_H +#define LOG4QT_PROPERTYCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QSettings; + +namespace Log4Qt +{ + + class Appender; + class Layout; + class ListAppender; + class Logger; + class Properties; + class LoggerRepository; + + /*! + * \brief The class PropertyConfigurator allows the configuration of the + * package from a JAVA properties file. + * + * \note All the functions declared in this class are thread-safe. + */ + class PropertyConfigurator + { + public: + PropertyConfigurator(); + // virtual ~PropertyConfigurator(); // Use compiler default + private: + PropertyConfigurator(const PropertyConfigurator &rOther); // Not implemented + PropertyConfigurator &operator=(const PropertyConfigurator &rOther); // Not implemented + + public: + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository = 0); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository = 0); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + bool doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository = 0); + + // JAVA: void doConfigure(const QUrl &rUrl, LoggerRepository *pLoggerRepository); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const Properties &rProperties); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const QString &rConfigFilename); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref doConfigure(const QSettings &, LoggerRepository *) "doConfigure()", + * \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + static bool configure(const QSettings &rSettings); + + // JAVA: static void configure(const QUrl &rUrl); + + /*! + * \sa ConfiguratorHelper::configureError(), + * ConfiguratorHelper::configurationFile() + */ + static bool configureAndWatch(const QString &rConfigFilename); + + private: + void configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository); + void configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository); + void configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const; + void configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const; + LogObjectPtr parseAppender(const Properties &rProperties, + const QString &rName); + LogObjectPtr parseLayout(const Properties &rProperties, + const QString &rAppenderName); + void parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue); + void setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject); + void startCaptureErrors(); + bool stopCaptureErrors(); + + private: + LogObjectPtr mpConfigureErrors; + QHash< QString, LogObjectPtr > mAppenderRegistry; + }; + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PropertyConfigurator + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * + * %PropertyConfigurator() + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline PropertyConfigurator::PropertyConfigurator() + {} + + +} // namspace Logging + + +// Q_DECLARE_TYPEINFO(Log4Qt::PropertyConfigurator, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PROPERTYCONFIGURATOR_H diff --git a/GCV-3.6.1-T4/src/log4qt/rollingfileappender.cpp b/GCV-3.6.1-T4/src/log4qt/rollingfileappender.cpp new file mode 100644 index 0000000..f9fac5f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/rollingfileappender.cpp @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/rollingfileappender.h" + +#include +#include +#include +#include "log4qt/helpers/optionconverter.h" +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************ + Declarations + *************************************************************************/ + + + + /************************************************************************ + C helper functions + *************************************************************************/ + + + + /************************************************************************ + Class implementation: RollingFileAppender + *************************************************************************/ + + + RollingFileAppender::RollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + FileAppender(pLayout, rFileName, append, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::~RollingFileAppender() + { + close(); + } + + + void RollingFileAppender::setMaxFileSize(const QString &rMaxFileSize) + { + bool ok; + qint64 max_file_size = OptionConverter::toFileSize(rMaxFileSize, &ok); + if (ok) + setMaximumFileSize(max_file_size); + } + + QString RollingFileAppender::maxFileSize() + { + return QString("%1").arg(maximumFileSize()); + } + + + void RollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller") + + FileAppender::append(rEvent); + if (writer()->device()->size() > this->mMaximumFileSize) + rollOver(); + } + + + void RollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "RollingFileAppender::rollOver()", "Lock must be held by caller") + + logger()->debug("Rolling over with maxBackupIndex = %1", mMaxBackupIndex); + + closeFile(); + + QFile f; + f.setFileName(file() + QLatin1Char('.') + QString::number(mMaxBackupIndex)); + if (f.exists() && !removeFile(f)) + return; + + QString target_file_name; + int i; + for (i = mMaxBackupIndex - 1; i >=1; i--) + { + f.setFileName(file() + QLatin1Char('.') + QString::number(i)); + if (f.exists()) + { + target_file_name = file() + QLatin1Char('.') + QString::number(i + 1); + if (!renameFile(f, target_file_name)) + return; + } + } + + f.setFileName(file()); + target_file_name = file() + QLatin1String(".1"); + if (!renameFile(f, target_file_name)) + return; + + openFile(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug RollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "RollingFileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "maxbackupindex:" << maxBackupIndex() << " " + << "maximumfilesize:" << maximumFileSize() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/rollingfileappender.h b/GCV-3.6.1-T4/src/log4qt/rollingfileappender.h new file mode 100644 index 0000000..47848a4 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/rollingfileappender.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_ROLINGFILEAPPENDER_H +#define LOG4QT_ROLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/fileappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class RollingFileAppender extends FileAppender to backup + * the log files when they reach a certain size. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class RollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the maximum backup count used by the appender. + * + * The default is 1. + * + * \sa maxBackupIndex(), setMaxBackupIndex() + */ + Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex) + + /*! + * The property holds the maximum file size used by the appender. + * + * The default is 10 MB (10 * 1024 * 1024). + * + * \sa maximumFileSize(), setMaximumFileSize() + */ + Q_PROPERTY(qint64 maximumFileSize READ maximumFileSize WRITE setMaximumFileSize) + + /*! + * The property sets the maximum file size from a string value. + * + * \sa setMaxFileSize(), maximumFileSize() + */ + Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize) + + public: + RollingFileAppender(QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + virtual ~RollingFileAppender(); + private: + RollingFileAppender(const RollingFileAppender &rOther); // Not implemented + RollingFileAppender &operator=(const RollingFileAppender &rOther); // Not implemented + + public: + int maxBackupIndex() const; + qint64 maximumFileSize() const; + void setMaxBackupIndex(int maxBackupIndex); + void setMaximumFileSize(qint64 maximumFileSize); + QString maxFileSize(); + void setMaxFileSize(const QString &rMaxFileSize); + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %RollingFileAppender(name:"RFA" appendfile:false bufferedio:true + * encoding:"" file:"/log.txt" filter: 0x0 + * immediateflush:true isactive:true + * isclosed:false layout:"TTCC" maxbackupindex:2 + * maximumfilesize:40 referencecount:1 + * threshold:"NULL" writer:0x4175af8) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void rollOver(); + + private: + int mMaxBackupIndex; + qint64 mMaximumFileSize; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int RollingFileAppender::maxBackupIndex() const + { QMutexLocker locker(&mObjectGuard); + return mMaxBackupIndex; } + + inline qint64 RollingFileAppender::maximumFileSize() const + { QMutexLocker locker(&mObjectGuard); + return mMaximumFileSize; } + + inline void RollingFileAppender::setMaxBackupIndex(int maxBackupIndex) + { QMutexLocker locker(&mObjectGuard); + mMaxBackupIndex = maxBackupIndex; } + + inline void RollingFileAppender::setMaximumFileSize(qint64 maximumFileSize) + { QMutexLocker locker(&mObjectGuard); + mMaximumFileSize = maximumFileSize; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::RollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_ROLINGFILEAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/simplelayout.cpp b/GCV-3.6.1-T4/src/log4qt/simplelayout.cpp new file mode 100644 index 0000000..a7d5234 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/simplelayout.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/simplelayout.h" + +#include +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: SimpleLayout + **************************************************************************/ + + + QString SimpleLayout::format(const LoggingEvent &rEvent) + { + return rEvent.level().toString() + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug SimpleLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "SimpleLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/simplelayout.h b/GCV-3.6.1-T4/src/log4qt/simplelayout.h new file mode 100644 index 0000000..5ebe558 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/simplelayout.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_SIMPLELAYOUT_H +#define LOG4QT_SIMPLELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class SimpleLayout outputs the level and message of a logging + * event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class SimpleLayout : public Layout + { + Q_OBJECT + + public: + SimpleLayout(QObject *pParent = 0); + // virtual ~SimpleLayout(); // Use compiler default + private: + SimpleLayout(const SimpleLayout &rOther); // Not implemented + SimpleLayout &operator=(const SimpleLayout &rOther); // Not implemented + + public: + virtual QString format(const LoggingEvent &rEvent); + + protected: + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %SimpleLayout(name:"SL" referencecount:1) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline SimpleLayout::SimpleLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::SimpleLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_SIMPLELAYOUT_H diff --git a/GCV-3.6.1-T4/src/log4qt/spi/filter.cpp b/GCV-3.6.1-T4/src/log4qt/spi/filter.cpp new file mode 100644 index 0000000..8f2d10e --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/spi/filter.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/spi/filter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + void Filter::setNext(Filter *pFilter) + { + mpNext = pFilter; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/spi/filter.h b/GCV-3.6.1-T4/src/log4qt/spi/filter.h new file mode 100644 index 0000000..0fd48f0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/spi/filter.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_FILTER_H +#define LOG4QT_FILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/helpers/logobject.h" + +#include "log4qt/helpers/logobjectptr.h" +#include "log4qt/log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Filter is the base class for all filters. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class Filter : public LogObject + { + Q_OBJECT + + /*! + * The property holds the next filter of this filter. + * + * The default is 0 for no next filter. + * + * \sa next(), setNext() + */ + Q_PROPERTY(Filter* next READ next WRITE setNext) + + public: + enum Decision + { + ACCEPT, + DENY, + NEUTRAL + }; + Q_ENUMS(Decision); + + public: + Filter(QObject *pObject = 0); + // Filter(const Filter &rOther); // Use compiler default + virtual ~Filter(); + // Filter &operator=(const Filter &rOther); // Use compiler default + + Filter* next() const; + void setNext(Filter *pFilter); + + virtual void activateOptions(); + virtual Decision decide(const LoggingEvent &rEvent) const = 0; + + private: + LogObjectPtr mpNext; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter::Filter(QObject *pObject) : + LogObject(pObject), + mpNext(0) + {} + + inline Filter::~Filter() + {} + + inline Filter* Filter::next() const + { return mpNext; } + + inline void Filter::activateOptions() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Filter, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_FILTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/ttcclayout.cpp b/GCV-3.6.1-T4/src/log4qt/ttcclayout.cpp new file mode 100644 index 0000000..91baebc --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/ttcclayout.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/ttcclayout.h" + +#include +#include +#include "log4qt/helpers/datetime.h" +#include "log4qt/helpers/patternformatter.h" +#include "log4qt/logger.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: TTCCLayout + **************************************************************************/ + + + TTCCLayout::TTCCLayout(QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(RELATIVE); + } + + + TTCCLayout::TTCCLayout(const QString &rDateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(rDateFormat), + mThreadPrinting(true), + mpPatternFormatter(0) + { + } + + + TTCCLayout::TTCCLayout(DateFormat dateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(dateFormat); + } + + + TTCCLayout::~TTCCLayout() + { + delete mpPatternFormatter; + } + + + void TTCCLayout::setDateFormat(DateFormat dateFormat) + { + switch (dateFormat) + { + case NONE: + setDateFormat(QLatin1String("NONE")); + break; + case ISO8601: + setDateFormat(QLatin1String("ISO8601")); + break; + case ABSOLUTE: + setDateFormat(QLatin1String("ABSOLUTE")); + break; + case DATE: + setDateFormat(QLatin1String("DATE")); + break; + case RELATIVE: + setDateFormat(QLatin1String("RELATIVE")); + break; + default: + Q_ASSERT_X(false, "TTCCLayout::setDateFormat", "Unkown DateFormat"); + setDateFormat(QString()); + } + } + + + QString TTCCLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "TTCCLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void TTCCLayout::updatePatternFormatter() + { + QString pattern; + + pattern += QLatin1String("%d{") + mDateFormat + QLatin1String("}"); + if (mThreadPrinting) + pattern += QLatin1String(" [%t]"); + pattern += QLatin1String(" %-5p"); + if (mCategoryPrefixing) + pattern += QLatin1String(" %c"); + if (mContextPrinting) + pattern += QLatin1String(" %x"); + pattern += QLatin1String(" - %m%n"); + + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(pattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug TTCCLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "TTCCLayout(" + << "name:" << name() << " " + << "categoryprefixing:" << categoryPrefixing() << " " + << "contextprinting:" << contextPrinting() << " " + << "dateformat:" << dateFormat() << " " + << "referencecount:" << referenceCount() << " " + << "threadprinting:" << threadPrinting() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/ttcclayout.h b/GCV-3.6.1-T4/src/log4qt/ttcclayout.h new file mode 100644 index 0000000..8987315 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/ttcclayout.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_TTCCLAYOUT_H +#define LOG4QT_TTCCLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + class PatternFormatter; + + /*! + * \brief The class TTCCLayout outputs the time, thread, logger and nested + * diagnostic context information of a logging event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class TTCCLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds if the logger name is part of the formatted output. + * + * The default value is true for including the logger name. + * + * \sa categoryPrefixing(), setCategoryPrefixing() + */ + Q_PROPERTY(bool categoryPrefixing READ categoryPrefixing WRITE setCategoryPrefixing) + + /*! + * The property holds if the nested context information is part of the + * formatted output. + * + * The default value it true for including the nested context information. + * + * \sa contextPrinting(), setContextPrinting() + */ + Q_PROPERTY(bool contextPrinting READ contextPrinting WRITE setContextPrinting) + + /*! + * The property holds the date format used by the layout. + * + * The default date format is "RELATIVE". + * + * \sa dateFormat(), setDateFormat() + */ + Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat) + + /*! + * The property holds if the thread name is part of the formatted output. + * + * The default value it true for including the thread name. + * + * \sa threadPrinting(), setThreadPrinting() + */ + Q_PROPERTY(bool threadPrinting READ threadPrinting WRITE setThreadPrinting) + + public: + /*! + * The enum DateFormat defines constants for date formats. + * + * \sa setDateFormat(DateFormat), DateTime::toString() + */ + enum DateFormat + { + /*! The none date format string is "NONE". */ + NONE, + /*! + * The iso8601 date format string is "ISO8601". The date will be + * formatted as yyyy-MM-dd hh:mm:ss.zzz. + */ + ISO8601, + /*! + * The absolute date format string is "ABSOLUTE". The date will be + * formatted as HH:mm:ss.zzz. + */ + ABSOLUTE, + /*! + * The date date format string is "DATE". The date will be formatted + * as MMM YYYY HH:mm:ss.zzzz. + */ + DATE, + /*! + * The relative date format string is "RELATIVE". The date will be + * formatted as milliseconds since start of the program. + */ + RELATIVE + }; + Q_ENUMS(DateFormat) + + TTCCLayout(QObject *pParent = 0); + TTCCLayout(const QString &rDateFormat, + QObject *pParent = 0); + + /*! + * Creates a TTCCLayout with the date formar value specified by + * the \a dateFormat constant and the parent \a pParent. + */ + TTCCLayout(DateFormat dateFormat, + QObject *pParent = 0); + + virtual ~TTCCLayout(); + private: + TTCCLayout(const TTCCLayout &rOther); // Not implemented + TTCCLayout &operator=(const TTCCLayout &rOther); // Not implemented + + public: + bool categoryPrefixing() const; + bool contextPrinting() const; + QString dateFormat() const; + // JAVA: bool ignoresThrowable() const; + bool threadPrinting() const; + void setCategoryPrefixing(bool categoryPrefixing); + void setContextPrinting(bool contextPrinting); + void setDateFormat(const QString &rDateFormat); + + /*! + * Sets the date format to the value specified by the \a dateFormat + * constant. + */ + void setDateFormat(DateFormat dateFormat); + + // JAVA: setIgnoresThrowable(bool ignoresThrowable); + void setThreadPrinting(bool threadPrinting); + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %TTCCLayout(name:"TTCC" categoryprefixing:true + * contextprinting:true dateformat:"ISO8601" + * referencecount:1 threadprinting:true) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + bool mCategoryPrefixing; + bool mContextPrinting; + QString mDateFormat; + bool mThreadPrinting; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool TTCCLayout::categoryPrefixing() const + { return mCategoryPrefixing; } + + inline bool TTCCLayout::contextPrinting() const + { return mContextPrinting; } + + inline QString TTCCLayout::dateFormat() const + { return mDateFormat; } + + inline bool TTCCLayout::threadPrinting() const + { return mThreadPrinting; } + + inline void TTCCLayout::setCategoryPrefixing(bool categoryPrefixing) + { mCategoryPrefixing = categoryPrefixing; + updatePatternFormatter(); } + + inline void TTCCLayout::setContextPrinting(bool contextPrinting) + { mContextPrinting = contextPrinting; + updatePatternFormatter(); } + + inline void TTCCLayout::setDateFormat(const QString &rDateFormat) + { mDateFormat = rDateFormat; + updatePatternFormatter(); } + + inline void TTCCLayout::setThreadPrinting(bool threadPrinting) + { mThreadPrinting = threadPrinting; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::TTCCLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_TTCCLAYOUT_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/debugappender.cpp b/GCV-3.6.1-T4/src/log4qt/varia/debugappender.cpp new file mode 100644 index 0000000..fbaa351 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/debugappender.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/debugappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + +#if defined(Q_WS_WIN) +#include +#endif + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DebugAppender + **************************************************************************/ + + + DebugAppender::DebugAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(pParent) + { + setLayout(pLayout); + } + + + bool DebugAppender::requiresLayout() const + { + return true; + } + + + void DebugAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DebugAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "DebugAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); +#if defined(Q_WS_WIN) + QT_WA({ + OutputDebugStringW(reinterpret_cast(message.utf16())); + }, { + OutputDebugStringA(message.toLocal8Bit().data()); + }); +#else + fprintf(stderr, "%s", message.toLocal8Bit().data()); + fflush(stderr); +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DebugAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "DebugAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namspace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/debugappender.h b/GCV-3.6.1-T4/src/log4qt/varia/debugappender.h new file mode 100644 index 0000000..fc2b7f0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/debugappender.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DEBUGAPPENDER_H +#define LOG4QT_DEBUGAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DebugAppender appends logging events to the platform + * specific debug output. + * + * A DebugAppender appends to the Debugger on Windows and to stderr on all + * other systems. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DebugAppender : public AppenderSkeleton + { + Q_OBJECT + + public: + /*! + * Creates a DebugAppender. + */ + DebugAppender(QObject *pParent = 0); + + /*! + * Creates a DebugAppender with the specified layout \a pLayout + */ + DebugAppender(Layout *pLayout, + QObject *pParent = 0); + + // virtual ~DebugAppender(); // Use compiler default + private: + DebugAppender(const DebugAppender &rOther); // Not implemented + DebugAppender &operator=(const DebugAppender &rOther); // Not implemented + + public: + /*! + * The DebugAppended requires a layout. The function returns true. + * + * \sa setLayout() + */ + virtual bool requiresLayout() const; + + protected: + /*! + * Appends the specified logging event \a rEvent to the debug output. + * The output is formatted using the appender's layout. + * + * The method is called by the AppenderSkeleton::doAppend() after it + * the entry conditions have been tested and it has been found that the + * logging event needs to be appended. + * + * \sa setLayout(), AppenderSkeleton::doAppend(), checkEntryConditions() + */ + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DebugAppender(name:"DA" filter:0x3bee6b8 isactive:true isclosed:false + * layout:"SL" referencecount:1 threshold:"NULL") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DebugAppender::DebugAppender(QObject *pParent) : + AppenderSkeleton(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DebugAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DEBUGAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.cpp b/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.cpp new file mode 100644 index 0000000..31d8f64 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/denyallfilter.h" + +#include + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DenyAllFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DenyAllFilter(" + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.h b/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.h new file mode 100644 index 0000000..e67ffaa --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/denyallfilter.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a compile error on VS 2008 by using Q_UNUSED(&rEvent) + * instead of Q_UNUSED(rEvent) + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_DENYALLFILTER_H +#define LOG4QT_DENYALLFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DenyAllFilter drops all logging events + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class DenyAllFilter : public Filter + { + Q_OBJECT + + public: + DenyAllFilter(QObject *pParent = 0); + // DenyAllFilter(const DenyAllFilter &rOther); // Use compiler default + // virtual ~DenyAllFilter(); // Use compiler default + // DenyAllFilter &operator=(const DenyAllFilter &rOther); // Use compiler default + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %DenyAllFilter(next:QObject(0x0) referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************* + * Operators, Helper + *************************************************************************/ + + + /************************************************************************* + * Inline + *************************************************************************/ + + inline DenyAllFilter::DenyAllFilter(QObject *pParent) : + Filter(pParent) + {} + + inline Filter::Decision DenyAllFilter::decide(const LoggingEvent &rEvent) const + { Q_UNUSED(&rEvent); return Filter::DENY; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DenyAllFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_DENYALLFILTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.cpp b/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.cpp new file mode 100644 index 0000000..32a3d84 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + LevelMatchFilter::LevelMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelToMatch(Level::NULL_INT) + {} + + + Filter::Decision LevelMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (mLevelToMatch == Level::NULL_INT || + rEvent.level() != mLevelToMatch) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug LevelMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LevelMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "leveltomatch:" << mLevelToMatch.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.h b/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.h new file mode 100644 index 0000000..b2fb44c --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/levelmatchfilter.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELMATCHFILTER_H +#define LOG4QT_LEVELMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with a specified + * level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), setAcceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the level to match for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelToMatch(), setLevelToMatch() + */ + Q_PROPERTY(Level levelToMatch READ levelToMatch WRITE setLevelToMatch) + + public: + LevelMatchFilter(QObject *pParent = 0); + // LevelMatchFilter(const LevelMatchFilter &rOther); // Use compiler default + // virtual ~LevelMatchFilter(); // Use compiler default + // LevelMatchFilter &operator=(const LevelMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelToMatch() const; + void setAcceptOnMatch(bool accept); + void setLevelToMatch(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelMatchFilter(acceptonmatch:true leveltomatch:"WARN" + * next:Log4Qt::DenyAllFilter(0x3bce3a8) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + Level mLevelToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelMatchFilter::levelToMatch() const + { return mLevelToMatch; } + + inline void LevelMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelMatchFilter::setLevelToMatch(Level level) + { mLevelToMatch = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELMATCHFILTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.cpp b/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.cpp new file mode 100644 index 0000000..b219cd9 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/levelrangefilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + + +/****************************************************************************** + * C helper functions + ******************************************************************************/ + + + +/****************************************************************************** + * Class implementation: Filter + ******************************************************************************/ + + +LevelRangeFilter::LevelRangeFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelMin(Level::NULL_INT), + mLevelMax(Level::OFF_INT) +{} + + +Filter::Decision LevelRangeFilter::decide(const LoggingEvent &rEvent) const +{ + if (rEvent.level() < mLevelMin) + return Filter::DENY; + + if (rEvent.level() > mLevelMax) + return Filter::DENY; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::NEUTRAL; +} + + +#ifndef QT_NO_DEBUG_STREAM +QDebug LevelRangeFilter::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "LevelRangeFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "levelmin:" << mLevelMin.toString() << " " + << "levelmax:" << mLevelMax.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.h b/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.h new file mode 100644 index 0000000..013e533 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/levelrangefilter.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LEVELRANGEFILTER_H +#define LOG4QT_LEVELRANGEFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + +#include "log4qt/level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with levels in a + * specified range. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LevelRangeFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the maximum level of the range for this filter. + * + * The default is Level::OFF_INT. + * + * \sa levelMax(), setLevelMax() + */ + Q_PROPERTY(Level levelMax READ levelMax WRITE setLevelMax) + + /*! + * The property holds the minimum level of the range for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelMin(), setLevelMin() + */ + Q_PROPERTY(Level levelMin READ levelMin WRITE setLevelMin) + + public: + LevelRangeFilter(QObject *pParent = 0); + // LevelRangeFilter(const LevelRangeFilter &rOther); // Use compiler default + // virtual ~LevelRangeFilter(); // Use compiler default + // LevelRangeFilter &operator=(const LevelRangeFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelMax() const; + Level levelMin() const; + void setAcceptOnMatch(bool accept); + void setLevelMax(Level level); + void setLevelMin(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * + * %LevelRangeFilter(acceptonmatch:true levelmin:"ERROR" levelmax:"FATAL" + * next:Log4Qt::LevelMatchFilter(0x3bcd960) + * referencecount:1 ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + + private: + bool mAcceptOnMatch; + Level mLevelMin; + Level mLevelMax; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelRangeFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelRangeFilter::levelMax() const + { return mLevelMax; } + + inline Level LevelRangeFilter::levelMin() const + { return mLevelMin; } + + inline void LevelRangeFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelRangeFilter::setLevelMax(Level level) + { mLevelMax = level; } + + inline void LevelRangeFilter::setLevelMin(Level level) + { mLevelMin = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelRangeFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELRANGEFILTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/listappender.cpp b/GCV-3.6.1-T4/src/log4qt/varia/listappender.cpp new file mode 100644 index 0000000..db20284 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/listappender.cpp @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/listappender.h" + +#include + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ListAppender + **************************************************************************/ + + + ListAppender::ListAppender(QObject *pParent) : + AppenderSkeleton(pParent), + mConfiguratorList(false), + mList(), + mMaxCount(0) + { + } + + + ListAppender::~ListAppender() + { + } + + + QList ListAppender::list() const + { + QMutexLocker locker(&mObjectGuard); + + return mList; + } + + + void ListAppender::setMaxCount(int n) + { + QMutexLocker locker(&mObjectGuard); + + if (n < 0) + { + logger()->warn("Attempt to set maximum count for appender '%1' to %2. Using zero instead", name(), n); + n = 0; + } + mMaxCount = n; + ensureMaxCount(); + } + + + QList ListAppender::clearList() + { + QMutexLocker locker(&mObjectGuard); + + QList result = mList; + mList.clear(); + return result; + } + + + // bool ListAppender::requiresLayout() const; + + + void ListAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "ListAppender::append()", "Lock must be held by caller") + + if ((mMaxCount <= 0) || (mList.size() < mMaxCount)) + mList << rEvent; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ListAppender::debug(QDebug &rDebug) const + { + rDebug.nospace() << "ListAppender(" + << "name:" << name() << " " + << "count:" << list().count() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "maxcount:" << maxCount() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void ListAppender::ensureMaxCount() + { + // Q_ASSERT_X(, "ListAppender::ensureMaxCount()", "Lock must be held by caller") + + if (mMaxCount <= 0) + return; + + while (mList.size() > mMaxCount) + mList.removeFirst(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/listappender.h b/GCV-3.6.1-T4/src/log4qt/varia/listappender.h new file mode 100644 index 0000000..0b35c51 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/listappender.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_LISTAPPENDER_H +#define LOG4QT_LISTAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + +#include +#include +#include "log4qt/loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class ListAppender appends logging events to a list for later + * processing. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class ListAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds, if the Appender is used by a configurator. + * + * The default value is false for not being a configurator list. + * + * \sa configuratorList(), setConfiguratorList() + */ + Q_PROPERTY(bool configuratorList READ configuratorList WRITE setConfiguratorList) + + /*! + * The property holds the maximum count used by the appender. + * + * The default maximum count is -1 for unlimited. + * + * \sa maxCount(), setMaxCount() + */ + Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) + + public: + ListAppender(QObject *pParent = 0); + virtual ~ListAppender(); + private: + ListAppender(const ListAppender &rOther); // Not implemented + ListAppender &operator=(const ListAppender &rOther); // Not implemented + + public: + /*! + * Returns true, if the appender is used by a configurator. Otherweise it returns + * false. + * + * \sa setConfiguratorList() + */ + bool configuratorList() const; + + QList list() const; + int maxCount() const; + + /*! + * Sets that the appender is used by a configurator. If set to true, the appender + * will not be removed from a Logger when Logger::removeAllAppenders()is called. + * This way the appender can collect events raised during the configuration process. + * + * \sa configuratorList(), BasicConfigurator, PropertyConfigurator, + * ConfiguratorHelper::configureError() + */ + void setConfiguratorList(bool isConfiguratorList); + + void setMaxCount(int n); + + QList clearList(); + virtual bool requiresLayout() const; + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %ListAppender(name:"LA" count:1 filter:0x41fa488 isactive:true + * isclosed:false maxcount:170 referencecount:1 + * threshold:"TRACE_SET") + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Ensures that the count of events is less or equal then the maxium + * count. If the list contains too many items, items are deleted from + * the begin of the list. + */ + void ensureMaxCount(); + + private: + volatile bool mConfiguratorList; + QList mList; + volatile int mMaxCount; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool ListAppender::configuratorList() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mConfiguratorList; } + + inline int ListAppender::maxCount() const + { return mMaxCount; } + + inline void ListAppender::setConfiguratorList(bool isConfiguratorList) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mConfiguratorList = isConfiguratorList; } + + inline bool ListAppender::requiresLayout() const + { return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ListAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LISTAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/nullappender.cpp b/GCV-3.6.1-T4/src/log4qt/varia/nullappender.cpp new file mode 100644 index 0000000..a12ebf2 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/nullappender.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/nullappender.h" + +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: NullAppender + **************************************************************************/ + + + NullAppender::NullAppender(QObject *pParent) : + AppenderSkeleton(false, pParent) + { + } + + + NullAppender::~NullAppender() + { + close(); + } + + + void NullAppender::append(const LoggingEvent &rEvent) + { + Q_UNUSED(rEvent); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug NullAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "NullAppender(" + << "name:" << name() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "threshold:" << threshold().toString() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/nullappender.h b/GCV-3.6.1-T4/src/log4qt/varia/nullappender.h new file mode 100644 index 0000000..becafb9 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/nullappender.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_NULLAPPENDER_H +#define LOG4QT_NULLAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + +/*! + * \brief The class NullAppender ignores all requests to append. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ +class NullAppender : public AppenderSkeleton +{ + Q_OBJECT + +public: + NullAppender(QObject *pParent = 0); + virtual ~NullAppender(); +private: + NullAppender(const NullAppender &rOther); // Not implemented + NullAppender &operator=(const NullAppender &rOther); // Not implemented + +public: + virtual bool requiresLayout() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * + * %NullAppender() + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM +}; + + +/****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + +/****************************************************************************** + * Inline + ******************************************************************************/ + +inline bool NullAppender::requiresLayout() const +{ return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NullAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NULLAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.cpp b/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.cpp new file mode 100644 index 0000000..e660b21 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/varia/stringmatchfilter.h" + +#include +#include "log4qt/loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + StringMatchFilter::StringMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mStringToMatch() + {} + + + Filter::Decision StringMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (rEvent.message().isEmpty() || + mStringToMatch.isEmpty() || + rEvent.message().indexOf(mStringToMatch) < 0) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug StringMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "StringMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "referencecount:" << referenceCount() << " " + << "stringtomatch:" << mStringToMatch << " " + << "next:" << next() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.h b/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.h new file mode 100644 index 0000000..921460f --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/varia/stringmatchfilter.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_STRINGMATCHFILTER_H +#define LOG4QT_STRINGMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class StringMatchFilter allows logging events with a + * specified level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class StringMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the string to match for this filter. + * + * \sa stringToMatch(), setStringToMatch() + */ + Q_PROPERTY(QString stringToMatch READ stringToMatch WRITE setStringToMatch) + + public: + StringMatchFilter(QObject *pParent = 0); + // StringMatchFilter(const StringMatchFilter &rOther); // Use compiler default + // virtual ~StringMatchFilter(); // Use compiler default + // StringMatchFilter &operator=(const StringMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + QString stringToMatch() const; + void setAcceptOnMatch(bool accept); + void setStringToMatch(const QString &rString); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %StringMatchFilter(acceptonmatch:true referencecount:1 + * stringtomatch:"LDAP_STRONG_AUTH_REQUIRED" + * next:Log4Qt::LevelMatchFilter(0x3bdd960) ) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + QString mStringToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool StringMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline QString StringMatchFilter::stringToMatch() const + { return mStringToMatch; } + + inline void StringMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void StringMatchFilter::setStringToMatch(const QString &rString) + { mStringToMatch = rString; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::StringMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_STRINGMATCHFILTER_H diff --git a/GCV-3.6.1-T4/src/log4qt/writerappender.cpp b/GCV-3.6.1-T4/src/log4qt/writerappender.cpp new file mode 100644 index 0000000..25a633e --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/writerappender.cpp @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "log4qt/writerappender.h" + +#include +#include +#include "log4qt/layout.h" +#include "log4qt/loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: WriterAppender + **************************************************************************/ + + + WriterAppender::WriterAppender(QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(pTextStream), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::~WriterAppender() + { + close(); + } + + + void WriterAppender::setEncoding(QTextCodec *pEncoding) + { + QMutexLocker locker(&mObjectGuard); + + if (mpEncoding == pEncoding) + return; + + mpEncoding = pEncoding; + if (mpWriter) + { + if (mpEncoding) + mpWriter->setCodec(mpEncoding); + else + mpWriter->setCodec(QTextCodec::codecForLocale()); + } + } + + + void WriterAppender::setWriter(QTextStream *pTextStream) + { + QMutexLocker locker(&mObjectGuard); + + closeWriter(); + + mpWriter = pTextStream; + if (mpEncoding && mpWriter) + mpWriter->setCodec(mpEncoding); + writeHeader(); + } + + + void WriterAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires writer and has no writer set"), + APPENDER_ACTIVATE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return; + } + + AppenderSkeleton::activateOptions(); + } + + + void WriterAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + AppenderSkeleton::close(); + closeWriter(); + } + + + bool WriterAppender::requiresLayout() const + { + return true; + } + + + void WriterAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "WriterAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "WriterAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); + + *mpWriter << message; + if (handleIoErrors()) + return; + + if (immediateFlush()) + { + mpWriter->flush(); + if (handleIoErrors()) + return; + } + } + + + bool WriterAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a writer set"), + APPENDER_USE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + + void WriterAppender::closeWriter() + { + // Q_ASSERT_X(, "WriterAppender::closeWriter()", "Lock must be held by caller") + + if (!mpWriter) + return; + + writeFooter(); + mpWriter = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug WriterAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "WriterAppender(" + << "name:" << name() << " " + << "encoding:" << codec_name << " " + << "filter:" << firstFilter() + << "immediateFlush:" << immediateFlush() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool WriterAppender::handleIoErrors() const + { + return false; + } + + + void WriterAppender::writeFooter() const + { + // Q_ASSERT_X(, "WriterAppender::writeFooter()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString footer = layout()->footer(); + if (footer.isEmpty()) + return; + + *mpWriter << footer << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + void WriterAppender::writeHeader() const + { + // Q_ASSERT_X(, "WriterAppender::writeHeader()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString header = layout()->header(); + if (header.isEmpty()) + return; + + *mpWriter << header << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/GCV-3.6.1-T4/src/log4qt/writerappender.h b/GCV-3.6.1-T4/src/log4qt/writerappender.h new file mode 100644 index 0000000..5c8da09 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qt/writerappender.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.h + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * 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. + * + ******************************************************************************/ + +#ifndef LOG4QT_WRITERAPPENDER_H +#define LOG4QT_WRITERAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "log4qt/appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QTextCodec; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class WriterAppender appends log events to a QTextStream. + * + * \note All the functions declared in this class are thread-safe. + *   + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class WriterAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds the codec the appender uses. + * + * The default is null to use the codec the writer has set. + * + * \sa encoding(), setEncoding() + */ + Q_PROPERTY(QTextCodec* encoding READ encoding WRITE setEncoding) + + /*! + * The property holds the writer the appender uses. + * + * \sa writer(), setWriter() + */ + Q_PROPERTY(QTextStream* writer READ writer WRITE setWriter) + + /*! + * The property holds, if the writer flushes after all write operations. + * + * The default is true for flushing. + * + * \sa immediateFlush(), setImmediateFlush() + */ + Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush) + + public: + WriterAppender(QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent = 0); + virtual ~WriterAppender(); + private: + WriterAppender(const WriterAppender &rOther); // Not implemented + WriterAppender &operator=(const WriterAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + QTextCodec *encoding() const; + bool immediateFlush() const; + QTextStream *writer() const; + + /*! + * Sets the codec used by the writer to \a pTextCoded. + * + * If a codec is set with setEncoding, it will overwrite the codec set + * in the text stream. A subsequent call with \a pTextCoded equals null + * will resets the codec to the default QTextCodec::codecForLocale(). + * + * \sa encoding(), QTextSream::setCodec(), QTextCodec::codecForLocale() + */ + void setEncoding(QTextCodec *pTextCodec); + void setImmediateFlush(bool immediateFlush); + void setWriter(QTextStream *pTextStream); + + virtual void activateOptions(); + virtual void close(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeWriter(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * + * %WriterAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + virtual bool handleIoErrors() const; + void writeFooter() const; + void writeHeader() const; + + private: + QTextCodec *mpEncoding; + QTextStream *mpWriter; + volatile bool mImmediateFlush; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QTextCodec *WriterAppender::encoding() const + { QMutexLocker locker(&mObjectGuard); + return mpEncoding; } + + inline bool WriterAppender::immediateFlush() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mImmediateFlush; } + + inline QTextStream *WriterAppender::writer() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mpWriter; } + + inline void WriterAppender::setImmediateFlush(bool immediateFlush) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mImmediateFlush = immediateFlush; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::WriterAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_WRITERAPPENDER_H diff --git a/GCV-3.6.1-T4/src/log4qtdef.h b/GCV-3.6.1-T4/src/log4qtdef.h new file mode 100644 index 0000000..ce801e0 --- /dev/null +++ b/GCV-3.6.1-T4/src/log4qtdef.h @@ -0,0 +1,11 @@ +#ifndef LOG4QTDEF_H +#define LOG4QTDEF_H + +#include "log4qt/consoleappender.h" +#include "log4qt/fileappender.h" +#include "log4qt/logger.h" +#include "log4qt/ttcclayout.h" +#include "log4qt/patternlayout.h" +#include "log4qt/logmanager.h" + +#endif // LOG4QTDEF_H diff --git a/GCV-3.6.1-T4/src/main.cpp b/GCV-3.6.1-T4/src/main.cpp new file mode 100644 index 0000000..0be6143 --- /dev/null +++ b/GCV-3.6.1-T4/src/main.cpp @@ -0,0 +1,204 @@ +/**************************************************************** + * main.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "mainwindow.h" +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +#include +#endif + +enum GC_LOG_TYPES +{ + LOG_DEBUG_TYPE = 1, + LOG_ERROR_TYPE, + LOG_WARN_TYPE, + LOG_INFO_TYPE, + LOG_STATUS_TYPE, +}; + +void logit(GC_LOG_TYPES type, const char *str, va_list args); + +FILE *pDebugLogFile = NULL; +AtomicIntBool g_enableDebugLog; +Log4Qt::PatternLayout *p_layout; +Log4Qt::FileAppender *p_fappender; + +int main(int argc, char *argv[]) +{ + // setup logging + Log4Qt::LogManager::rootLogger(); + //Log4Qt::TTCCLayout *p_layout = new Log4Qt::TTCCLayout(Log4Qt::TTCCLayout::ISO8601); + //Log4Qt::PatternLayout *p_layout = new Log4Qt::PatternLayout(Log4Qt::PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout = new Log4Qt::PatternLayout("%d %p (%c) - %m%n"); + p_layout->setName(QLatin1String("GC Basic Layout")); + p_layout->activateOptions(); + + // Create a console appender + Log4Qt::ConsoleAppender *p_appender = new Log4Qt::ConsoleAppender(p_layout, Log4Qt::ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("GC Basic Console Appender")); +#ifdef QT_DEBUG + p_appender->setThreshold(Log4Qt::Level::TRACE_INT); +#else + p_appender->setThreshold(Log4Qt::Level::WARN_INT); +#endif + p_appender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_appender); + + // Create a file appender + p_fappender = new Log4Qt::FileAppender(); + p_fappender->setLayout(p_layout); + p_fappender->setThreshold(Log4Qt::Level::TRACE_INT); + p_fappender->setFile(QDir::homePath() + "/GrblController.log"); + p_fappender->setName(QLatin1String("GC Basic File Appender")); + // don't open until ready (later during startup) + //p_fappender->activateOptions(); + //Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + + QApplication a(argc, argv); + + QString locale = QLocale::system().name().section('_', 0, 0); + QString dir = QDir::currentPath() + "/trlocale"; + QString file = QString("GrblController_") + locale; + QTranslator translator; + bool r = translator.load(file, dir); + if (!r) + { + dir = QDir::currentPath() + "/../GrblHoming/trlocale"; + translator.load(file, dir); + } + a.installTranslator(&translator); + + QString xlatpath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + file = QString("qt_") + locale ; + QTranslator qtTranslator; + r = qtTranslator.load(file , xlatpath); + if (!r) + { + xlatpath = QDir::currentPath() + "/trlocale"; + qtTranslator.load(file, xlatpath); + } + a.installTranslator(&qtTranslator); + + MainWindow w; + w.show(); + + int result = a.exec(); + + if (pDebugLogFile != NULL) + { + fclose(pDebugLogFile); + pDebugLogFile = NULL; + } + return result; +} + + +//------------------------------ +void status(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_STATUS_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void err(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_ERROR_TYPE, str, args); + va_end(args); +} + +void warn(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_WARN_TYPE, str, args); + va_end(args); +} + +void info(const char *str, ...) +{ + va_list args; + + va_start(args, str ); + logit(LOG_INFO_TYPE, str, args); + va_end(args); +} + +void diag(const char *str, ...) +{ +#ifndef QT_DEBUG + if (g_enableDebugLog.get()) { +#endif + va_list args; + + va_start(args, str ); + logit(LOG_DEBUG_TYPE, str, args); + va_end(args); +#ifndef QT_DEBUG + } +#endif +} + +void logit(GC_LOG_TYPES type, const char *str, va_list args) +{ +#define PRNTBUFSIZE 500 + char buf[PRNTBUFSIZE]; + buf[PRNTBUFSIZE-1] = '\0'; + + vsnprintf(buf, sizeof(buf) - 1, str, args); + + int len = strlen(buf); + if (len > 0) + { + if (len == 1 && (buf[0] == '\r' || buf[0] == '\n')) + { + buf[0] = '\0'; + } + else if (len > 1) + { + if (buf[len - 2] == '\r' || buf[len - 2] == '\n') + buf[len - 2] = '\0'; + else if (buf[len - 1] == '\r' || buf[len - 1] == '\n') + buf[len - 1] = '\0'; + } + } + else if (len == 0) + return; + + switch (type) + { + case LOG_STATUS_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_STATUS)->info(buf); + break; + case LOG_DEBUG_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->debug(buf); + break; + case LOG_ERROR_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->error(buf); + break; + case LOG_WARN_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->warn(buf); + break; + case LOG_INFO_TYPE: + Log4Qt::Logger::logger(LOG_MSG_TYPE_DIAG)->info(buf); + break; + } +} diff --git a/GCV-3.6.1-T4/src/mainwindow.cpp b/GCV-3.6.1-T4/src/mainwindow.cpp new file mode 100644 index 0000000..f7a36b4 --- /dev/null +++ b/GCV-3.6.1-T4/src/mainwindow.cpp @@ -0,0 +1,2570 @@ +/**************************************************************** + * mainwindow.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include +#include "mainwindow.h" +#include "version.h" +#include "ui_mainwindow.h" + +extern Log4Qt::FileAppender *p_fappender; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), opt(this), + open_button_text(tr("Open")), + close_button_text(tr("Close / Reset")), + absoluteAfterAxisAdj(false), + checkLogWrite(false), + sliderPressed(false), + sliderTo(0.0), + sliderZCount(0), +/// T4 + // scrollRequireMove(true), scrollPressed(false), + queuedCommandsStarved(false), lastQueueCount(0), queuedCommandState(QCS_OK), + lastLcdStateValid(true), + activeLine(0), cmdMan(false) +{ + // Setup our application information to be used by QSettings + QCoreApplication::setOrganizationName(COMPANY_NAME); + QCoreApplication::setOrganizationDomain(DOMAIN_NAME); + QCoreApplication::setApplicationName(APPLICATION_NAME); + + // required if passing the object by reference into signals/slots + qRegisterMetaType("Coord3D"); + qRegisterMetaType("PosItem"); + qRegisterMetaType("ControlParams"); + + ui->setupUi(this); +/// T3 + checkState = ui->btnCheck->isChecked() ; +/// T4 to display the comma correctly : before read 'sliderStep->value' + connect(ui->sliderStep, SIGNAL(valueChanged(int)), this, SLOT(stepChanged(int)) ); +// 'Options' + opt.init(); + + readSettings(); + + info(qPrintable(tr("%s has started")), GRBL_CONTROLLER_NAME_AND_VERSION); + + // see http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/ + // The thread points out that the documentation for QThread is wrong :) and + // you should NOT subclass from QThread and override run(), rather, + // attach your QOBJECT to a thread and use events (signals/slots) to communicate. + gcode.moveToThread(&gcodeThread); + runtimeTimer.moveToThread(&runtimeTimerThread); + + ui->lcdWorkNumberX->setDigitCount(8); + ui->lcdMachNumberX->setDigitCount(8); + ui->lcdWorkNumberY->setDigitCount(8); + ui->lcdMachNumberY->setDigitCount(8); + ui->lcdWorkNumberZ->setDigitCount(8); + ui->lcdMachNumberZ->setDigitCount(8); + ui->lcdWorkNumberFourth->setDigitCount(8); + ui->lcdMachNumberFourth->setDigitCount(8); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->HomeFourthBtn->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); +/// T4 + ui->unitFourth->hide(); + ui->unitFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } +///************************ connect *********************************** +///T4 + connect(ui->btnPause,SIGNAL(toggled(bool)),this,SLOT(pauseSend(bool))); + // GRbl command + connect(ui->btnHelp,SIGNAL(clicked()),this,SLOT(grblHelp())); + connect(ui->btnGrblSettings,SIGNAL(clicked()),this,SLOT(grblSettings())); + connect(ui->btnParameters, SIGNAL(clicked()),this, SLOT(grblParameters())); + connect(ui->btnParserState, SIGNAL(clicked()),this, SLOT(grblParserState())); + connect(ui->btnBuildInfo, SIGNAL(clicked()),this, SLOT(grblBuildInfo())); + connect(ui->btnStartupBlocks, SIGNAL(clicked()),this, SLOT(grblStartupBlocks())); + connect(ui->btnCheck,SIGNAL(toggled(bool)),this,SLOT(grblCheck(bool) )); + connect(ui->btnUnlockGrbl,SIGNAL(clicked()),this,SLOT(grblUnlock())); + connect(ui->btnHomingCycle, SIGNAL(clicked()),this,SLOT(grblHomingCycle())); + // connect(ui->btnCycleStart, SIGNAL(clicked()),this, SLOT(grblCycleStart())); + // connect(ui->btnFeedHold, SIGNAL(clicked()),this, SLOT(grblFeedHold())); + connect(ui->btnStatus, SIGNAL(clicked()),this,SLOT(grblStatus())); + connect(ui->btnResetGrbl,SIGNAL(clicked()),this,SLOT(grblReset())); + /// to gcode + // connect(this, SIGNAL(sendGrblPause(bool)), &gcode, SLOT(sendGrblPause(bool))); + connect(this, SIGNAL(sendGrblHelp()), &gcode, SLOT(sendGrblHelp())); + + connect(this, SIGNAL(sendGrblParameters()), &gcode, SLOT(sendGrblParameters())); + connect(this, SIGNAL(sendGrblParserState()), &gcode, SLOT(sendGrblParserState())); + connect(this, SIGNAL(sendGrblBuildInfo()), &gcode, SLOT(sendGrblBuildInfo())); + connect(this, SIGNAL(sendGrblStartupBlocks()), &gcode, SLOT(sendGrblStartupBlocks())); + // connect(this, SIGNAL(sendGrblCheck(bool)), &gcode, SLOT(grblCheck(bool))); + connect(this, SIGNAL(sendGrblCheck(bool)), &gcode, SLOT(sendGrblCheck(bool))); + connect(this, SIGNAL(sendGrblUnlock()), &gcode, SLOT(sendGrblUnlock())); + connect(this, SIGNAL(sendGrblHomingCycle()), &gcode, SLOT(sendGrblHomingCycle())); + connect(this, SIGNAL(sendGrblCycleStart()), &gcode, SLOT(sendGrblCycleStart())); + connect(this, SIGNAL(sendGrblFeedHold()), &gcode, SLOT(sendGrblFeedHold())); + connect(this, SIGNAL(sendGrblStatus()), &gcode, SLOT(sendGrblStatus())); + connect(this, SIGNAL(sendGrblReset()), &gcode, SLOT(sendGrblReset())); + //buttons + connect(ui->btnOpenPort,SIGNAL(clicked()),this,SLOT(openPort())); + connect(ui->DecXBtn,SIGNAL(clicked()),this,SLOT(decX())); + connect(ui->DecYBtn,SIGNAL(clicked()),this,SLOT(decY())); + connect(ui->DecZBtn,SIGNAL(clicked()),this,SLOT(decZ())); + connect(ui->IncXBtn,SIGNAL(clicked()),this,SLOT(incX())); + connect(ui->IncYBtn,SIGNAL(clicked()),this,SLOT(incY())); + connect(ui->IncZBtn,SIGNAL(clicked()),this,SLOT(incZ())); + connect(ui->DecFourthBtn,SIGNAL(clicked()),this,SLOT(decFourth())); + connect(ui->IncFourthBtn,SIGNAL(clicked()),this,SLOT(incFourth())); +/// T4 + connect(ui->HomeXBtn,SIGNAL(clicked()),this,SLOT(homeX())); + connect(ui->HomeYBtn,SIGNAL(clicked()),this,SLOT(homeY())); + connect(ui->HomeZBtn,SIGNAL(clicked()),this,SLOT(homeZ())); + connect(ui->HomeFourthBtn,SIGNAL(clicked()),this,SLOT(homeFourth())); + connect(this, SIGNAL(goToHomeAxis(char)), &gcode, SLOT(goToHomeAxis(char) )); + connect(&gcode, SIGNAL(endHomeAxis()), this, SLOT(endHomeAxis() )); + + // connect(ui->btnSetHome,SIGNAL(clicked()),this,SLOT(setHome())); + connect(ui->btnSetG92,SIGNAL(clicked()),this,SLOT(setHome())); + connect(ui->comboCommand->lineEdit(), SIGNAL(editingFinished()),this, SLOT(gotoXYZFourth())); +/// T3 + connect(ui->Begin,SIGNAL(clicked()),this,SLOT(begin())); + connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile())); + connect(ui->Stop,SIGNAL(clicked()),this,SLOT(stop())); + +/// T4 + connect(ui->spindleButton,SIGNAL(toggled(bool)),this,SLOT(toggleSpindle(bool))); + connect(ui->chkRestoreAbsolute,SIGNAL(toggled(bool)),this,SLOT(toggleRestoreAbsolute())); + connect(ui->actionOptions,SIGNAL(triggered()),this,SLOT(getOptions())); + connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close())); + connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout())); + + connect(ui->btnGoHomeSafe,SIGNAL(clicked()),this,SLOT(goHomeSafe())); + connect(ui->verticalSliderZJog,SIGNAL(valueChanged(int)),this,SLOT(zJogSliderDisplay(int))); + connect(ui->verticalSliderZJog,SIGNAL(sliderPressed()),this,SLOT(zJogSliderPressed())); + connect(ui->verticalSliderZJog,SIGNAL(sliderReleased()),this,SLOT(zJogSliderReleased())); + // connect(ui->pushButtonRefreshPos,SIGNAL(clicked()),this,SLOT(refreshPosition())); + +/// T3 + connect(this, SIGNAL(sendFile(QString, bool)), &gcode, SLOT(sendFile(QString, bool))); + connect(this, SIGNAL(openPort(QString,QString)), &gcode, SLOT(openPort(QString,QString))); + connect(this, SIGNAL(closePort(bool)), &gcode, SLOT(closePort(bool))); + connect(this, SIGNAL(sendGcode(QString)), &gcode, SLOT(sendGcode(QString))); + connect(this, SIGNAL(gotoXYZFourth(QString)), &gcode, SLOT(gotoXYZFourth(QString))); + connect(this, SIGNAL(axisAdj(char, float, bool, bool, int)), &gcode, SLOT(axisAdj(char, float, bool, bool, int))); + connect(this, SIGNAL(setResponseWait(ControlParams)), &gcode, SLOT(setResponseWait(ControlParams))); + connect(this, SIGNAL(shutdown()), &gcodeThread, SLOT(quit())); + connect(this, SIGNAL(shutdown()), &runtimeTimerThread, SLOT(quit())); + connect(this, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(this, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); + connect(this, SIGNAL(sendSetHome()), &gcode, SLOT(grblSetHome())); + +/// T3 + connect(this, SIGNAL(goToHome()), &gcode, SLOT(goToHome())); + connect(this, SIGNAL(setItems(QList)), ui->wgtVisualizer, SLOT(setItems(QList))); +/// T4 + connect(this, SIGNAL(setItems(QList)), ui->visu3D, SLOT(setItems(QList))); + connect(ui->View3DButton, SIGNAL(clicked()), ui->visu3D, SLOT(set3DView()) ) ; + connect(ui->FrontViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setFrontView()) ) ; + connect(ui->BackViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setBackView()) ) ; + connect(ui->LeftViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setLeftView()) ) ; + connect(ui->RightViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setRightView()) ) ; + connect(ui->TopViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setTopView()) ) ; + connect(ui->BottomViewButton, SIGNAL(clicked()), ui->visu3D, SLOT(setBottomView()) ) ; + connect(ui->VectorUpButton, SIGNAL(clicked()), ui->visu3D, SLOT(setVectorUp()) ) ; + connect(ui->Help3DButton, SIGNAL(clicked()), ui->visu3D, SLOT(Help3D()) ) ; + + connect(ui->BBcheckBox, SIGNAL(clicked(bool)), ui->visu3D, SLOT(setBbox(bool)) ) ; + connect(ui->G0checkBox, SIGNAL(clicked(bool)), ui->visu3D, SLOT(setG0(bool)) ) ; +/// ==> undetected by gcc 4.7.1 error ---> + // connect(ui->BBcheckBox, SIGNAL(clicked(bool)), ui->visu3D, SLOT(setBbox(bool)() ) ) ; + + connect(&gcode, SIGNAL(sendMsgSatusBar(QString)),this,SLOT(receiveMsgSatusBar(QString))); + connect(&gcode, SIGNAL(portIsClosed(bool)), this, SLOT(portIsClosed(bool))); + connect(&gcode, SIGNAL(portIsOpen(bool)), this, SLOT(portIsOpen(bool))); + connect(&gcode, SIGNAL(addList(QString)),this,SLOT(receiveList(QString))); + connect(&gcode, SIGNAL(addListFull(QStringList)),this,SLOT(receiveListFull(QStringList))); + connect(&gcode, SIGNAL(addListOut(QString)),this,SLOT(receiveListOut(QString))); + connect(&gcode, SIGNAL(stopSending()), this, SLOT(stopSending())); + connect(&gcode, SIGNAL(setCommandText(QString)), ui->comboCommand->lineEdit(), SLOT(setText(QString))); + connect(&gcode, SIGNAL(setProgress(int)), ui->progressFileSend, SLOT(setValue(int))); + connect(&gcode, SIGNAL(setQueuedCommands(int, bool)), this, SLOT(setQueuedCommands(int, bool))); + connect(&gcode, SIGNAL(adjustedAxis()), this, SLOT(adjustedAxis())); + connect(&gcode, SIGNAL(resetTimer(bool)), &runtimeTimer, SLOT(resetTimer(bool))); + connect(&gcode, SIGNAL(enableGrblDialogButton()), this, SLOT(enableGrblDialogButton())); + connect(&gcode, SIGNAL(updateCoordinates(Coord3D,Coord3D)), this, SLOT(updateCoordinates(Coord3D,Coord3D))); +/// T4 3D animator + connect(ui->visu3D, SIGNAL(updateLCD(QVector3D)), this, SLOT(updateLCD(QVector3D))); + // connect(&gcode, SIGNAL(setLastState(QString)), ui->outputLastState, SLOT(setText(QString))); + connect(&gcode, SIGNAL(setLastState(QString)), this, SLOT(setLastState(QString))); + connect(&gcode, SIGNAL(setUnitMmAll(bool)), this, SLOT(setUnitMmAll(bool))); + + /// 2D + connect(&gcode, SIGNAL(setLivePoint(double, double, bool, bool)), ui->wgtVisualizer, SLOT(setLivePoint(double, double, bool, bool))); + connect(&gcode, SIGNAL(setVisualLivenessCurrPos(bool)), ui->wgtVisualizer, SLOT(setVisualLivenessCurrPos(bool))); + connect(&gcode, SIGNAL(setVisCurrLine(int)), ui->wgtVisualizer, SLOT(setVisCurrLine(int))); +/// T4 for visu3D + connect(&gcode, SIGNAL(setLivePoint(QVector3D)), ui->visu3D, SLOT(setLivePoint(QVector3D))); + // connect(this, SIGNAL(setLiveRelPoint(QVector3D)), ui->visu3D, SLOT(setLiveRelPoint(QVector3D))); + connect(this, SIGNAL(setLivePoint(QVector3D, bool)), ui->visu3D, SLOT(setLivePoint(QVector3D, bool))); + + connect(&gcode, SIGNAL(setLcdState(bool)), this, SLOT(setLcdState(bool))); + connect(&runtimeTimer, SIGNAL(setRuntime(QString)), ui->outputRuntime, SLOT(setText(QString))); +/// T2 + connect(&gcode, SIGNAL(setVersionGrbl(QString)), ui->GrblVersion, SLOT(setText(QString))); +/// T3 + connect(&gcode, SIGNAL(setLinesFile(QString, bool)), this, SLOT(setLinesFile(QString, bool))); +/// T4 for visuGcode + connect(ui->visuGcode, SIGNAL(cursorPositionChanged() ), this, SLOT(on_cursorVisuGcode()) ) ; + connect(this, SIGNAL(setLineCode(QString) ), ui->lineCode, SLOT(setText(QString)) ) ; + connect(this, SIGNAL(setNumLine(QString) ), ui->visu3D, SLOT(setNumLine(QString)) ) ; + connect(&gcode, SIGNAL(setNumLine(QString) ), ui->visu3D, SLOT(setNumLine(QString)) ) ; + connect(ui->visu3D, SIGNAL(setLineNum(QString) ), ui->lineCode, SLOT(setText(QString)) ) ; + connect(this, SIGNAL(setTotalNumLine(QString) ), ui->visu3D, SLOT(setTotalNumLine(QString)) ) ; + connect(this, SIGNAL(setFeedRateToLine(QList)), ui->visu3D, SLOT(setFeedRateToLine(QList))) ; + connect(this, SIGNAL(setSpeedSpindleToLine(QList)), ui->visu3D, SLOT(setSpeedSpindleToLine(QList))) ; + connect(ui->visu3D, SIGNAL(setActiveLineVisuGcode(int, bool)), this, SLOT(setActiveLineVisuGcode(int, bool)) ); +/// T4 for animator + connect(ui->visualButton, SIGNAL(toggled(bool) ), this, SLOT(toVisual(bool)) ) ; + connect(this, SIGNAL(setVisual(bool) ), ui->visu3D, SLOT(setVisual(bool)) ) ; + connect(ui->pauseButton, SIGNAL(toggled(bool) ), this, SLOT(toPause(bool)) ) ; + connect(this, SIGNAL(setPause(bool) ), ui->visu3D, SLOT(setPause(bool)) ) ; + connect(ui->prevButton, SIGNAL(clicked() ), ui->visu3D, SLOT(setPrev()) ) ; + connect(ui->nextButton, SIGNAL(clicked() ), ui->visu3D, SLOT(setNext()) ) ; + connect(this, SIGNAL(runCode(bool, int) ), ui->visu3D, SLOT(runCode(bool, int)) ) ; + connect(this, SIGNAL(setPosReqKind(int)), &gcode, SLOT(setPosReqKind(int)) ); + + connect(ui->dialPeriodRepeat, SIGNAL(valueChanged(int)),ui->visu3D,SLOT(setPeriod(int))); + connect(ui->dialPeriodRepeat, SIGNAL(valueChanged(int)),ui->lcdPeriodAnim, SLOT(display(int))); + + connect(ui->visu3D, SIGNAL(setPauseVisual(bool)), ui->pauseButton, SLOT(setChecked(bool)) ); + + connect(ui->visu3D, SIGNAL(setFeedRateGcode(double)), ui->lcdFeedRateGcode, SLOT(display(double)) ); + connect(ui->visu3D, SIGNAL(setSpeedSpindleGcode(double)), ui->lcdSpeedSpindleGcode, SLOT(display(double)) ); + + connect(ui->visu3D, SIGNAL(setSegments(int)), ui->lcdSegments, SLOT(display(int)) ); + connect (ui->doubleSpinBoxTol, SIGNAL(valueChanged(double)), ui->visu3D, SLOT(setTolerance(double) )); + + connect(ui->btnClearStatusList, SIGNAL(clicked() ), this, SLOT(toClearSatusList()) ) ; + connect(ui->btnPrintStatusList, SIGNAL(clicked() ), this, SLOT(toPrintStatusList()) ) ; + connect(ui->btnPrintVisual, SIGNAL(clicked() ), this, SLOT(toPrintVisual()) ) ; + +/// end connect + /// start threads + runtimeTimerThread.start(); + gcodeThread.start(); + + queuedCommandsEmptyTimer.start(); + queuedCommandsRefreshTimer.start(); + + // Cool utility class off Google code that enumerates COM ports in platform-independent manner + QList ports = QextSerialEnumerator::getPorts(); + + int portIndex = -1; + for (int i = 0; i < ports.size(); i++) + { + ui->cmbPort->addItem(qPrintable(ports.at(i).portName)); + + if (ports.at(i).portName == lastOpenPort) + portIndex = i; + +//diag("port name: %s\n", qPrintable(ports.at(i).portName)); +//diag("friendly name: %s\n", qPrintable(ports.at(i).friendName)); +//diag("physical name: %s\n", qPrintable(ports.at(i).physName))); +//diag("enumerator name: %s\n", qPrintable(ports.at(i).enumName))); +//diag("===================================\n\n"); + } + + if (portIndex >= 0) + { + // found matching port + ui->cmbPort->setCurrentIndex(portIndex); + } + else if (lastOpenPort.size() > 0) + { + // did not find matching port + // This code block is used to restore a port to view that isn't visible to QextSerialEnumerator + ui->cmbPort->addItem(qPrintable(lastOpenPort)); + if (ports.size() > 0) + ui->cmbPort->setCurrentIndex(ports.size()); + else + ui->cmbPort->setCurrentIndex(0); + } + + int baudRates[] = { 9600, 19200, 38400, 57600, 115200 }; + int baudRateCount = sizeof baudRates / sizeof baudRates[0]; + int baudRateIndex = 0; + for (int i = 0; i < baudRateCount; i++) + { + QString baudRate = QString::number(baudRates[i]); + ui->comboBoxBaudRate->addItem(baudRate); + if (baudRate == lastBaudRate) + { + baudRateIndex = i; + } + } + ui->comboBoxBaudRate->setCurrentIndex(baudRateIndex); + + ui->tabAxisVisualizer->setEnabled(false); +/// T4 + // manual controls + enableManualControl(false); + + if (!controlParams.useFourAxis) + { + ui->lcdWorkNumberFourth->setEnabled(false);; + ui->lcdMachNumberFourth->setEnabled(false);; + ui->IncFourthBtn->setEnabled(false); + ui->DecFourthBtn->setEnabled(false); + ui->HomeFourthBtn->setEnabled(false); + } + ui->groupBoxSendFile->setEnabled(true); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } +/// T4 + // Grbl commands + enableButtonGrblControls(false); + + styleSheet = ui->btnOpenPort->styleSheet(); + ui->statusList->setEnabled(true); + ui->openFile->setEnabled(true); +/// T4 animator + ui->tabGcode->setEnabled(false); + + this->setWindowTitle(GRBL_CONTROLLER_NAME_AND_VERSION VERSION_BUILD); + this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + + QSettings settings; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + + if (!controlParams.useAggressivePreload && !promptedAggrPreload) + { + QMessageBox msgBox; + msgBox.setText(tr("You appear to have upgraded to the latest version of Grbl Controller. " + "Please be aware that as of version 3.4 the default behavior of sending commands " + "to Grbl has been changed to send them as fast as possible (Aggressive preload mode).\n\n" + "Your settings have been changed to enable this mode. Why? Because it provides the most " + "optimal use of Grbl and greatly reduces the time to finish a typical job.\n\n" + "What does this mean to you? " + "Arc commands will now run smoother and faster than before, which may " + "cause your spindle to work slightly harder, so please run some tests first. " + "Alternately, go to the Options dialog and manually disable Aggressive Preload") ); + msgBox.exec(); + + controlParams.useAggressivePreload = true; + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, controlParams.useAggressivePreload); + } + + promptedAggrPreload = true; + +/// --> T4 associate to 'QToolButton toolButton' + /// actions + QAction * noToolAction = new QAction(tr("No tool"), this); + connect(noToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(noTool())); + QAction * miniToolAction = new QAction(tr("Mini 1 mm"), this); + connect(miniToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(miniTool())); + QAction * hemiToolAction = new QAction(tr("Hemi 3 mm"), this); + connect(hemiToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(hemiTool())); + QAction * rightToolAction = new QAction(tr("Right 3 mm"), this); + connect(rightToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(rightTool())); + QAction * sharpToolAction = new QAction(tr("Sharp 3 mm"), this); + connect(sharpToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(sharpTool()) ); + QAction * shortToolAction = new QAction(tr("Short 3 mm"), this); + connect(shortToolAction, SIGNAL(triggered()), ui->visu3D, SLOT(shortTool()) ); + /// menus + + QMenu * menuTool = new QMenu(this); + menuTool->addAction(noToolAction); + menuTool->addAction(miniToolAction); + menuTool->addAction(hemiToolAction); + menuTool->addAction(rightToolAction); + menuTool->addAction(sharpToolAction); + menuTool->addAction(shortToolAction); + /// associate 'menuTool' and 'toolButton' + ui->toolButton->setMenu(menuTool); +/// T4 + // period animation mS + ui->dialPeriodRepeat->setValue(100); + +/// <-- T4 call 'setUnitMmAll(..)' + emit setResponseWait(controlParams); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +// called when user has clicked the close application button +void MainWindow::closeEvent(QCloseEvent *event) +{ + gcode.setShutdown(); + gcode.setAbort(); + gcode.setReset(); + + writeSettings(); + + info(qPrintable(tr("%s has stopped")), GRBL_CONTROLLER_NAME_AND_VERSION); + + SLEEP(300); + + emit shutdown(); + + event->accept(); +} + +void MainWindow::begin() +{ + // TODO : verify 'ui->filePath->text()' + // ... + if (!checkState) + setLcdState(controlParams.usePositionRequest); + else + setLcdState(false); + + // 2D + ui->wgtVisualizer->setEnabled(!checkState); + ui->wgtVisualizer->setAutoFillBackground(!checkState); + +/// T4 3D + /// -> ui->visu3D::runCode(true, posRegKind); + runFile = true; + cmdMan = false; + emit runCode(runFile, posReqKind); + + // -> 'gcode::setPosReqKind(posRegKind)' + emit setPosReqKind(posReqKind); + + ui->visualButton->setChecked(false); + ui->pauseButton->setChecked(true); + // invalid manual controls + enableManualControl(false); + if (!checkState) + { + ui->tabAxisVisualizer->setTabEnabled(TAB_VISU3D_INDEX, true); + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISU3D_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISU3D_INDEX); + } + } + if (ui->tabVisu->currentIndex() != TAB_CONSOLE_INDEX) + { + emit ui->tabVisu->setCurrentIndex(TAB_CONSOLE_INDEX); + } + + //receiveList("Starting File Send."); + resetProgress(); + + int ret = QMessageBox::No; + if (!checkState) { + if((ui->lcdWorkNumberX->value()!=0)||(ui->lcdWorkNumberY->value()!=0)||(ui->lcdWorkNumberZ->value()!=0) + || (ui->lcdWorkNumberFourth->value()!=0)) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you want to zero the displayed position before proceeding?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Yes); + ret = msgBox.exec(); + if(ret == QMessageBox::Yes) + setHome(); + } + } + if(ret!=QMessageBox::Cancel) + { + ui->btnClearStatusList->setEnabled(false); + ui->btnPrintStatusList->setEnabled(false); + ui->btnPrintVisual->setEnabled(false) ; + + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); +/// T3 + ui->openFile->setEnabled(false); + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(true); + ui->btnPause->setEnabled(true); + ui->progressFileSend->setEnabled(true); + ui->progressQueuedCommands->setEnabled(true); + ui->labelFileSendProgress->setEnabled(true); + ui->labelQueuedCommands->setEnabled(true); + ui->outputRuntime->setEnabled(true); + ui->labelRuntime->setEnabled(true); + } + +/// T4 + // Grbl commands + enableButtonGrblControls(false); + // commands 'tabVisu' + enableTabVisuControls(false); + + emit sendFile(ui->filePath->text(), checkState); + } +} + +void MainWindow::stop() +{ + setLcdState(controlParams.usePositionRequest); + ui->wgtVisualizer->setEnabled(true); + ui->wgtVisualizer->setAutoFillBackground(true); +/// T4 + runFile = false; + emit runCode(runFile, posReqKind); + ui->visu3D->setEnabled(true); + ui->tabGcode->setEnabled(true); + ui->tabVisu->setTabEnabled(TAB_VISUGCODE_INDEX, true); + + gcode.setAbort(); +/// T4 + if (!ui->btnPause->isChecked()) + ui->btnPause->setChecked(true); + + // Reenable a bunch of UI +/// T3 + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->openFile->setEnabled(true); + + ui->btnClearStatusList->setEnabled(true); + ui->btnPrintStatusList->setEnabled(true); + ui->btnPrintVisual->setEnabled(true) ; +/// T4 + // valid commands 'tabVisu' + enableTabVisuControls(true); + + // valid manual controls + enableManualControl(true); + + // Grbl commands + enableButtonGrblControls(true); +} +//------------------------------------------ +/// T4 suspend/resume 'gcode::sendFile(...)' +// calls : 'ui->btnPause' +void MainWindow::pauseSend(bool valid) +{ + // to gcode + gcode.setPause(!valid); + + QPalette palette; + if (ui->btnPause->isChecked()) { + ui->btnPause->setText(tr("Pause")) ; + palette.setColor(QPalette::Button,Qt::gray) ; + } + else { + ui->btnPause->setText(tr("Resume")) ; + palette.setColor(QPalette::Button,Qt::yellow) ; + } + // color 'pauseButton' + ui->btnPause->setPalette(palette); +} + +void MainWindow::grblHelp() +{ + emit sendGrblHelp(); +} +void MainWindow::grblParameters() +{ + emit sendGrblParameters(); +} +void MainWindow::grblParserState() +{ + emit sendGrblParserState(); +} + +void MainWindow::grblBuildInfo() +{ + emit sendGrblBuildInfo(); +} +void MainWindow::grblStartupBlocks() +{ + emit sendGrblStartupBlocks(); +} + +// calls : 'ui->btnCheck::toggled(valid)' +void MainWindow::grblCheck(bool valid) +{ +/// TODO : fix bug with command '$C' + checkState = ui->btnCheck->isChecked(); + if (checkState) + { + QString txt(tr("During the mode 'Check 'does not use the command '$C' please")); + receiveMsgSatusBar(txt); + info(qPrintable(txt)); + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setText(txt); + msgBox.exec(); + + addToStatusList(true, txt); + + ui->btnCheck->setText(tr("No check")) ; + } + else { + ui->btnCheck->setText(tr("Check")) ; + } + + ui->tabAxisVisualizer->setEnabled(valid); + + enableButtonGrblControls(!valid); + if(valid) { + ui->btnCheck->setEnabled(true); + ui->btnStatus->setEnabled(true); + ui->btnResetGrbl->setEnabled(true); + ui->btnUnlockGrbl->setEnabled(true); + } + // (in)valid manual controls + enableManualControl(!valid); + ui->tabVisu->setTabEnabled(TAB_VISUGCODE_INDEX, !valid); + + /// send '$C' to Grbl + emit sendGrblCheck(checkState) ; +} + +void MainWindow::grblUnlock() +{ + emit sendGrblUnlock(); +} +void MainWindow::grblHomingCycle() +{ + // user message + QString msg(tr("With 'Grbl Settings' you must validate the homing cycle" )); + info(qPrintable(msg)); + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setText(msg); + msgBox.exec(); + + addToStatusList(true, msg); + + emit sendGrblHomingCycle(); +} +///---- not used +void MainWindow::grblCycleStart() +{ + emit sendGrblCycleStart() ; +} +void MainWindow::grblFeedHold() +{ + emit sendGrblFeedHold() ; +} +//-- +void MainWindow::grblStatus() +{ + emit sendGrblStatus(); +} +void MainWindow::grblReset() +{ + gcode.setAbort(); + gcode.setReset(); + emit sendGrblReset(); +} +//------------------------------------------- + +void MainWindow::goHomeSafe() +{ + /// tool position !! + cmdMan = true; + emit goToHome(); +} + +// slot called from GCode class to update our state +void MainWindow::stopSending() +{ + ui->tabAxisVisualizer->setEnabled(true); + // valid manual controls + enableManualControl(true); + if (!ui->btnPause->isChecked()) + ui->btnPause->setChecked(true); + // lcd + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->HomeFourthBtn->setEnabled(controlParams.useFourAxis); + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); +/// T3 + { + ui->Begin->setEnabled(true); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + ui->btnOpenPort->setEnabled(true); +/// T4 + // Grbl commands + enableButtonGrblControls(true); + + ui->openFile->setEnabled(true); +/// T4 + // commands 'tabVisu' + enableTabVisuControls(true); +} + +// User has asked to open the port +void MainWindow::openPort() +{ + QString Mes = tr("User clicked Port Open/Close"); + info(qPrintable(Mes) ); + + openPortCtl(false); +} + +// User has asked to set current position as 'home' = 0,0,0 +void MainWindow::setHome() +{ + resetProgress(); + // sendSetHome(); // ? + cmdMan = true; + emit sendSetHome(); +} + +void MainWindow::resetProgress() +{ + setProgress(0); + setQueuedCommands(0, false); + setRuntime(""); +} + +// If the port isn't open, we ask to open it +// If the port is open, we close it, but if 'reopen' is +// true, we call back to this thread to reopen it which +// is done mainly to toggle the COM port state to reset +// the controller. +void MainWindow::openPortCtl(bool reopen) +{ + if (ui->btnOpenPort->text() == open_button_text) + { + // Port is closed if the button says 'Open' + QString portStr = ui->cmbPort->currentText(); + QString baudRate = ui->comboBoxBaudRate->currentText(); +/// T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->btnOpenPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + + ui->btnClearStatusList->setEnabled(true); + ui->btnPrintStatusList->setEnabled(true); +/// T4 + if (ui->tabVisu->currentIndex() != TAB_CONSOLE_INDEX) + { + emit ui->tabVisu->setCurrentIndex(TAB_CONSOLE_INDEX); + } + + emit openPort(portStr, baudRate); + } + else + { + if (!reopen) + resetProgress(); + + // presume button says 'Close' currently, meaning port is open + + // Tell gcode port thread to stop what it is doing immediately (within 0.1 sec) + gcode.setAbort(); + gcode.setReset(); + + // Disable a bunch of UI +/// T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + ui->openFile->setEnabled(true); + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } +/// T4 + ui->tabAxisVisualizer->setEnabled(ui->visualButton->isChecked()); + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + + enableButtonGrblControls(false) ; + // invalid manual controls + enableManualControl(false); +/// T2 + ui->GrblVersion->setText(tr("none")); + // Send event to close the port + emit closePort(reopen); + } +} + +// slot telling us that port was closed successfully +// if 'reopen' is true, reopen our port to toggle +// so we reset the controller +void MainWindow::portIsClosed(bool reopen) +{ + SLEEP(100); + + ui->tabAxisVisualizer->setEnabled(false); + + ui->btnClearStatusList->setEnabled(false); + ui->btnPrintStatusList->setEnabled(false); + +/// T4 + // invalid manual controls + enableManualControl(false); + + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + + ui->openFile->setEnabled(true); + + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + styleSheet = ui->btnOpenPort->styleSheet(); + ui->statusList->setEnabled(true); + ui->tabGcode->setEnabled(true); +///<-- + ui->comboCommand->setEnabled(false); + ui->labelCommand->setEnabled(false); + ui->cmbPort->setEnabled(true); + ui->comboBoxBaudRate->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(open_button_text); + ui->btnOpenPort->setStyleSheet(styleSheet); +/// T4 + // Grbl commands + enableButtonGrblControls(false); + + if (reopen) + { + receiveList(tr("Resetting port to restart controller")); + openPortCtl(false); + } +/// T4 + openState = false; +} + +// slot that tells us the gcode thread successfully opened the port +void MainWindow::portIsOpen(bool sendCode) +{ + // Comm port successfully opened + if (sendCode) + sendGcode(""); + openState = sendCode; +} +// called by 'GCode::axisAdj(...)' +void MainWindow::adjustedAxis() +{ + cmdMan = false; + ui->tabAxisVisualizer->setEnabled(true); +/// T4 + // valid manual controls + enableManualControl(true); + + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + + if (ui->filePath->text().length() > 0) + { + ui->Begin->setEnabled(true); + } + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + + ui->btnOpenPort->setEnabled(true); + ui->openFile->setEnabled(true); +/// T4 + // Grbl commands + enableButtonGrblControls(true); +} + +void MainWindow::enableAllButtons(bool v) +{ + ui->comboCommand->setEnabled(v); + ui->labelCommand->setEnabled(v); +/// T2 + ui->labelLines->setEnabled(v); + ui->outputLines->setEnabled(v); +/// T3 + ui->openFile->setEnabled(v); + { // enableBlockFile + ui->Begin->setEnabled(v); + ui->Stop->setEnabled(v); + ui->btnPause->setEnabled(v); + ui->progressFileSend->setEnabled(v); + ui->progressQueuedCommands->setEnabled(v); + ui->labelFileSendProgress->setEnabled(v); + ui->labelQueuedCommands->setEnabled(v); + ui->outputRuntime->setEnabled(v); + ui->labelRuntime->setEnabled(v); + } +/// T4 + // Grbl commands + enableButtonGrblControls(v); +/// T4 + // manual controls + enableManualControl(v); +} +// called by 'GCode::waitForStartupBanner( ...)' +void MainWindow::enableGrblDialogButton() +{ + ui->openFile->setEnabled(true); + ui->btnOpenPort->setEnabled(true); + ui->btnOpenPort->setText(close_button_text); + ui->btnOpenPort->setStyleSheet("* { background-color: rgb(255,125,100) }"); + ui->cmbPort->setEnabled(false); + ui->comboBoxBaudRate->setEnabled(false); + + ui->tabAxisVisualizer->setEnabled(true); + // valid manual controls + enableManualControl(true); + { // blockCoordinate + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->HomeFourthBtn->setEnabled(controlParams.useFourAxis); + } + ui->groupBoxSendFile->setEnabled(true); + + ui->comboCommand->setEnabled(true); + ui->labelCommand->setEnabled(true); + + ui->btnSetHome->setEnabled(true); +/// T4 + // Grbl commands + enableButtonGrblControls(true); + + if (ui->filePath->text().length() > 0) + { +/// T2 + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); +/// T3 + if (!ui->visualButton->isChecked()) { + ui->btnCheck->setEnabled(true); + ui->Begin->setEnabled(true); + } + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + else + { +/// T2 + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); +/// T3 + { + ui->Begin->setEnabled(false); + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + } +} + +void MainWindow::incX() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj('X', jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incY() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj('Y', jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::incZ() +{ + enableAllButtons(false); +/// T4 + cmdMan = true; + ui->lcdFeedRateGcode->display(controlParams.zJogRate); + emit axisAdj('Z', jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decX() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj('X', -jogStep, invX, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decY() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj('Y', -jogStep, invY, absoluteAfterAxisAdj, 0); +} + +void MainWindow::decZ() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.zJogRate); + cmdMan = true; + emit axisAdj('Z', -jogStep, invZ, absoluteAfterAxisAdj, sliderZCount++); +} + +void MainWindow::decFourth() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj(controlParams.fourthAxisName, -jogStep, invFourth, absoluteAfterAxisAdj, 0); +} +void MainWindow::incFourth() +{ + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit axisAdj(controlParams.fourthAxisName, jogStep, invFourth, absoluteAfterAxisAdj, 0); +} + +// ui->HomeXBtn->clicked() -> homeX() +void MainWindow::homeX() +{ + if (ui->lcdWorkNumberX->value()==0) + return; + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit goToHomeAxis('X'); +} +void MainWindow::homeY() +{ + if (ui->lcdWorkNumberY->value()==0) + return; + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit goToHomeAxis('Y'); +} + +void MainWindow::homeZ() +{ + if (ui->lcdWorkNumberZ->value()==0) + return; + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.zJogRate); + cmdMan = true; + emit goToHomeAxis('Z'); +} + +void MainWindow::homeFourth() +{ + if (ui->lcdWorkNumberFourth->value()==0) + return; + enableAllButtons(false); +/// T4 + ui->lcdFeedRateGcode->display(controlParams.xyRateAmount); + cmdMan = true; + emit goToHomeAxis(controlParams.fourthAxisName); +} + +// calls : 'GCode::goToHomeAxis()':1, +void MainWindow::endHomeAxis() +{ + cmdMan = false; + enableManualControl(true); + enableButtonGrblControls(true); + ui->comboCommand->setEnabled(true); + ui->openFile->setEnabled(true); + if (ui->filePath->text().length() > 0) + ui->Begin->setEnabled(true); + /// others ... TODO +} + +void MainWindow::getOptions() +{ +/// T4 + // Options opt(this); + opt.move(geometry().x(), geometry().y()); + opt.exec(); +} + +void MainWindow::gotoXYZFourth() +{ + if (ui->comboCommand->lineEdit()->text().length() == 0) + return; + + QString line = ui->comboCommand->lineEdit()->text().append("\r"); + + emit gotoXYZFourth(line); +} + +void MainWindow::openFile() +{ + QFileDialog dialog(this, tr("Open File"), + directory, + tr("NC (*.nc);;All Files (*.*)")); + + dialog.setFileMode(QFileDialog::ExistingFile); + + if (nameFilter.size() > 0) + dialog.selectNameFilter(nameFilter); + + if (fileOpenDialogState.size() > 0) + dialog.restoreState(fileOpenDialogState); + + QString fileName; + QStringList fileNames; + if (dialog.exec()) + { + fileOpenDialogState = dialog.saveState(); + + fileNames = dialog.selectedFiles(); + if (fileNames.length() > 0) + fileName = fileNames.at(0); + + nameFilter = dialog.selectedNameFilter(); + + resetProgress(); + } + + int slash = fileName.lastIndexOf('/'); + if (slash == -1) + { + slash = fileName.lastIndexOf('\\'); + } + + directory = ""; + if (slash != -1) + { + directory = fileName.left(slash); + } + + ui->filePath->setText(fileName); +/// T3 // cpmport open + if (ui->btnOpenPort->text() == close_button_text) + { + ui->Begin->setEnabled(true); + } + else // close + { + ui->Begin->setEnabled(false); + } + + { + ui->Stop->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->progressFileSend->setEnabled(false); + ui->progressQueuedCommands->setEnabled(false); + ui->labelFileSendProgress->setEnabled(false); + ui->labelQueuedCommands->setEnabled(false); + ui->outputRuntime->setEnabled(false); + ui->labelRuntime->setEnabled(false); + } + + if (ui->filePath->text().length() > 0) + { + ui->labelLines->setEnabled(true); + ui->outputLines->setEnabled(true); + ui->btnPrintVisual->setEnabled(true) ; +/// T4 visu3D and visuGcode + if (ui->tabAxisVisualizer->currentIndex() != TAB_VISU3D_INDEX) + { + emit ui->tabAxisVisualizer->setCurrentIndex(TAB_VISU3D_INDEX); + } + if (ui->tabVisu->currentIndex() != TAB_VISUGCODE_INDEX) + { + emit ui->tabVisu->setCurrentIndex(TAB_VISUGCODE_INDEX); + } + ui->tabGcode->setEnabled(true); + // read in the file to process it + preProcessFile(ui->filePath->text()); + } + else + { + ui->labelLines->setEnabled(false); + ui->outputLines->setEnabled(false); + } +} + +void MainWindow::preProcessFile(QString filepath) +{ + QFile file(filepath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QTextStream code(&file); + posList.clear(); +/// T4 + ui->visuGcode->clear() ; + int plane = NO_PLANE; + double x, y, z, i, j, k ; + x=y=z=i=j=k=0; + QVector3D xyz, ijk; + int p = 0; // arc revolutions + int g = 0; + bool helix = false; + // feedrate 'Fxxxx' + double fr, prevfr = 0.0; + QList feedRateToLine; + feedRateToLine.append(prevfr);// case 0 + // Spindle Speed Sxxxxx + double ss, prevss = 0.0; + QList speedSpindleToLine; + speedSpindleToLine.append(prevss); // case 0 + +/// T4 animator + QString codeText; + QString line; + bool arc = false, cw = false, mm = true; + int index = 0; + // bool zeroInsert = false; // ??? + bool zeroInsert = true; + QString strline; + /// total lines + QString alltext = code.readAll() ; + totalLinesFile = alltext.count(QChar('\n')) ; + QString strmax = QString().number(totalLinesFile); + int n = strmax.size(); + + code.seek(0); + do + { + strline = code.readLine(); + +/// T4 test line analyze TODO ... + // line = gcode.removeUnsupportedCommands(strline); +//diag("gcode:line = %s", qPrintable(line)); +///<-- + index++; +/// T4 construct strline with index + line = "%1"; + line = line.arg(index, n , 10 , QChar(' ') ) + " : " + strline; + codeText.append(line + "\n"); +/// <-- + GCode::trimToEnd(strline, '('); + GCode::trimToEnd(strline, ';'); + GCode::trimToEnd(strline, '%'); + + strline = strline.trimmed(); + g=0; p=0; fr=0.0; ss = 0.0; + if (strline.size() == 0) + { // ignore the white lines + } + else + { + strline = strline.toUpper(); + strline.replace("M6", "M06"); + strline.replace(QRegExp("([A-Z])"), " \\1"); + strline.replace(QRegExp("\\s+"), " "); +/// T4 + if (processGCode(strline, x, y, z, i, j, k, + p, arc, cw, mm, g, + plane, helix, fr, ss + ) + ) + { + if (!zeroInsert) + { + // insert 0,0 position + posList.append(PosItem()); + zeroInsert = true; + } + xyz = QVector3D(x, y, z); ijk = QVector3D(i,j,k); + posList.append(PosItem(strline, xyz, ijk, p, arc, cw, mm, g, plane, helix, index, fr, ss)); + } + } + /// Fxxxx + if (fr > 0) + prevfr = fr; + feedRateToLine.append(prevfr); + /// Sxxxx + if (ss > 0) + prevss = ss; + speedSpindleToLine.append(prevss); + + } while (code.atEnd() == false); + + /// number of lines + strline = QString().setNum(index) ; + ui->outputLines->setText(strline); + /// write all lines + ui->visuGcode->setPlainText(codeText); + + file.close(); + + /// to 'ui-visu3D::setTotalNumLine(QString)' + emit setTotalNumLine(strline) ; + /// to 'ui->wgtVisualizer::setItems(posList)' and 'ui->visu3D::setItems(posList)' + emit setItems(posList); + /// to to 'ui-visu3D::setFeedRateToLine(QList)' + emit setFeedRateToLine(feedRateToLine); + /// to to 'ui-visu3D::setSpeedSpindleToLine(QList)' + emit setSpeedSpindleToLine(speedSpindleToLine); + // the correct unit + setUseMm(mm); + } + else + printf("Can't open file\n"); +} + +/// T4 +bool MainWindow::processGCode(QString inputLine, + double& x, double& y, double& z, + double& i, double& j, double& k, + int& p, bool& arc, bool& cw, bool& mm, int& g, + int& plane, bool& helix, double& f, double& sp + ) +{ + QString line = inputLine.toUpper(); + QStringList components = line.split(" ", QString::SkipEmptyParts); + QString s; + arc = false; + bool valid = false; + f = 0.0; + sp = 0.0; + int nextIsValue = NO_ITEM; + int value; + bool bi(false), bj(false), bk(false); + // bool bx(false), by(false), bz(false); + foreach (s, components) + { +//diag("s= %s", qPrintable(s) ); + if (s.at(0) == 'F') { + f = decodeLineItem(s, F_ITEM, valid, nextIsValue); + } + else + if (s.at(0) == 'S') { + sp = decodeLineItem(s, S_ITEM, valid, nextIsValue); + } + else + if (s.at(0) == 'G') + { + value = s.mid(1).toInt(); + if (value >= 0 && value <= 3) + { + g = value; + if (value == 2) + cw = true; + else if (value == 3) + cw = false; + } + else if (value == 20) + mm = false; + else if (value == 21) + mm = true; +/// T4 for arcs + else if (value == 17) // plane XY + plane = PLANE_XY_G17; + else if (value == 18) // plane ZX + plane = PLANE_ZX_G19; + else if (value == 19) // plane YZ + plane = PLANE_YZ_G18; + } + else if (g >= 0 && g <= 3 && s.at(0) == 'X') + { + x = decodeLineItem(s, X_ITEM, valid, nextIsValue); + helix = plane == PLANE_YZ_G18; + } + else if (g >= 0 && g <= 3 && s.at(0) == 'Y') + { + y = decodeLineItem(s, Y_ITEM, valid, nextIsValue); + helix = plane == PLANE_ZX_G19; + } +/// T4 + else if (g >= 0 && g <= 3 && s.at(0) == 'Z') + { + z = decodeLineItem(s, Z_ITEM, valid, nextIsValue); + helix = plane == PLANE_XY_G17; + } + else if ((g == 2 || g == 3) && s.at(0) == 'I') + { + i = decodeLineItem(s, I_ITEM, arc, nextIsValue); + bi = true; + } + else if ((g == 2 || g == 3) && s.at(0) == 'J') + { + j = decodeLineItem(s, J_ITEM, arc, nextIsValue); + bj = true; + } +/// T4 + else if ((g == 2 || g == 3) && s.at(0) == 'K') + { + k = decodeLineItem(s, K_ITEM, arc, nextIsValue); + bk = true; + } + else if ((g == 2 || g == 3) && s.at(0) == 'P') + { + p = decodeLineItem(s, P_ITEM, valid, nextIsValue); + } +/// Fxxxx + else if ((g == 1 || g == 2 || g == 3) && s.at(0) == 'F') + { + f = decodeLineItem(s, F_ITEM, valid, nextIsValue); + } + else if ((g == 1 || g == 2 || g == 3) && s.at(0) == 'S') + { + sp = decodeLineItem(s, S_ITEM, valid, nextIsValue); + } +/// <-- + else if (nextIsValue != NO_ITEM) + { + switch (nextIsValue) + { + case X_ITEM: + x = decodeDouble(s, valid); + break; + case Y_ITEM: + y = decodeDouble(s, valid); + break; +/// T4 + case Z_ITEM: + z = decodeDouble(s, valid); + break; + case I_ITEM: + i = decodeDouble(s, arc); + break; + case J_ITEM: + j = decodeDouble(s, arc); + break; +/// T4 + case K_ITEM: + k = decodeDouble(s, arc); + break; + case P_ITEM: + p = decodeDouble(s, valid); + break; + case F_ITEM: + f = decodeDouble(s, valid); + break; + case S_ITEM: + sp = decodeDouble(s, valid); + break; + }; + nextIsValue = NO_ITEM; + } + // plane if NO_PLANE + if (!(plane == PLANE_XY_G17 || plane == PLANE_YZ_G18 || plane == PLANE_ZX_G19) ) + { + if (bi && bj && !bk) + plane = PLANE_XY_G17 ; + else + if (bi && !bj && bk) + plane = PLANE_ZX_G19 ; + else + if (!bi && bj && bk) + plane = PLANE_YZ_G18 ; + } + } + return valid; +} + +double MainWindow::decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue) +{ + if (item.size() == 1) + { + nextIsValue = next; + return 0; + } + else + { + nextIsValue = NO_ITEM; + return decodeDouble(item.mid(1,-1), valid); + } +} + +double MainWindow::decodeDouble(QString value, bool& valid) +{ + if (value.indexOf(QRegExp("^[+-]?[0-9]*\\.?[0-9]*$")) == -1) + return 0; + valid = true; + return value.toDouble(); +} + +void MainWindow::readSettings() +{ + // use platform-independent settings storage, i.e. registry under Windows + QSettings settings; + + fileOpenDialogState = settings.value(SETTINGS_FILE_OPEN_DIALOG_STATE).value(); + directory = settings.value(SETTINGS_DIRECTORY).value(); + nameFilter = settings.value(SETTINGS_NAME_FILTER).value(); + lastOpenPort = settings.value(SETTINGS_PORT).value(); + lastBaudRate = settings.value(SETTINGS_BAUD, QString::number(BAUD9600)).value(); + + promptedAggrPreload = settings.value(SETTINGS_PROMPTED_AGGR_PRELOAD, false).value(); + + QString absAfterAdj = settings.value(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, "false").value(); + absoluteAfterAxisAdj = (absAfterAdj == "true"); + ui->chkRestoreAbsolute->setChecked(absoluteAfterAxisAdj); + + QString jogStepStr = settings.value(SETTINGS_JOG_STEP, "10").value(); + jogStep = jogStepStr.toFloat() ; + ui->sliderStep->setValue(int(jogStep*100)); + + settings.beginGroup( "mainwindow" ); + restoreGeometry(settings.value( "geometry", saveGeometry() ).toByteArray()); + restoreState(settings.value( "savestate", saveState() ).toByteArray()); + move(settings.value( "pos", pos() ).toPoint()); + resize(settings.value( "size", size() ).toSize()); + if ( settings.value( "maximized", isMaximized() ).toBool() ) + showMaximized(); + + settings.endGroup(); + + updateSettingsFromOptionDlg(settings); +} + +// calls : 'Options::toggleUseMm(bool useMm'):1, +void MainWindow::setSettingsOptionsUseMm() +{ +//diag(" MainWindow::setSettingsOptionsUseMm() ..."); + controlParams.useMm = opt.getUseMm(); + controlParams.zJogRate = opt.getZJogRate(); + // controlParams.zRateLimit = opt.getzRateLimit(); + controlParams.xyRateAmount = opt.getXYRate(); + // update gcode thread with latest values + emit setResponseWait(controlParams); +} + +// Slot called from settings 'Options' dialog after user made a change. +// Reload settings from registry. +// calls: 'Options::accept()':1, +void MainWindow::setSettingsOptions() +{ + QSettings settings; + updateSettingsFromOptionDlg(settings); + // update gcode thread with latest values + emit setResponseWait(controlParams); +} + +// calls : 'setSettingsOptions()':1, +void MainWindow::updateSettingsFromOptionDlg(QSettings& settings) +{ +/// T4 + ui->statusList->setMaximumBlockCount( settings.value( SETTINGS_MAX_STATUS_LINES, 0 ).value() ); + + QString sinvX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString sinvY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString sinvZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + //QString smm = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS,"false").value(); + QString sinvFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + QString sdbgLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + g_enableDebugLog.set(sdbgLog == "true"); + + // only enable/not enable file logging at startup. There are some kind of + // multithreaded issues turning on or off file logging at runtime causing + // crashes. + if (!checkLogWrite) + { + checkLogWrite = true; + + if (g_enableDebugLog.get()) + { + p_fappender->activateOptions(); + Log4Qt::Logger::rootLogger()->addAppender(p_fappender); + } + } + + invX = sinvX == "true"; + invY = sinvY == "true"; + invZ = sinvZ == "true"; + invFourth = sinvFourth == "true"; + + controlParams.waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + controlParams.zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + controlParams.useMm = useMmManualCmds == "true"; + QString useAggrPreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + controlParams.useAggressivePreload = useAggrPreload == "true"; + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + controlParams.waitForJogToComplete = waitForJogToComplete == "true"; + + QString useFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + controlParams.useFourAxis = useFourAxis == "true"; + + char name = settings.value(SETTINGS_FOUR_AXIS_NAME, FOURTH_AXIS_A).value(); + controlParams.fourthAxisName = name; + bool rot = settings.value(SETTINGS_FOUR_AXIS_ROTATE, true).value(); + controlParams.fourthAxisRotate = rot; + + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->HomeFourthBtn->setEnabled(controlParams.useFourAxis); + + if (!controlParams.useFourAxis) + { + ui->DecFourthBtn->hide(); + ui->IncFourthBtn->hide(); + ui->HomeFourthBtn->hide(); + ui->lcdWorkNumberFourth->hide(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lcdMachNumberFourth->hide(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->lblFourth->hide(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, true); +/// T4 ui->chkRestoreAbsolute->setEnabled(v); + ui->unitFourth->hide(); + ui->unitFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + } + else + { + ui->DecFourthBtn->show(); + ui->IncFourthBtn->show(); + ui->HomeFourthBtn->show(); + ui->lcdWorkNumberFourth->show(); + ui->lcdWorkNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lcdMachNumberFourth->show(); + ui->lcdMachNumberFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->show(); + ui->lblFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->lblFourth->setText(QString(controlParams.fourthAxisName)); + ui->unitFourth->setText(controlParams.fourthAxisRotate == true ?QString("deg."):QString("mm") ); +/// T4 + ui->unitFourth->show(); + ui->unitFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + + QString axisJog(tr("Z Jog"));// not correct, but a default placeholder we have a translation for already + char axis = controlParams.fourthAxisName; + if (axis == FOURTH_AXIS_A) { + axisJog = tr("A Jog"); + } + else if (axis == FOURTH_AXIS_B){ + axisJog = tr("B Jog"); + } + else if (axis == FOURTH_AXIS_C) { + axisJog = tr("C Jog"); + } + else if (axis == FOURTH_AXIS_U) { + axisJog = tr("U Jog"); + } + else if (axis == FOURTH_AXIS_V) { + axisJog = tr("V Jog"); + } + else if (axis == FOURTH_AXIS_W){ + axisJog = tr("W Jog"); + } + } + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + controlParams.zRateLimit = zRateLimit == "true"; + + QString ffCommands = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + controlParams.filterFileCommands = ffCommands == "true"; + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + controlParams.reducePrecision = rPrecision == "true"; + controlParams.grblLineBufferLen = settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value(); + controlParams.charSendDelayMs = settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value(); + + controlParams.zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + controlParams.xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + // controlParams.usePositionRequest = enPosReq == "true"; + controlParams.positionRequestType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_ALWAYS_NO_IDLE_CHK).value(); + double posReqFreq = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + controlParams.postionRequestTimeMilliSec = static_cast(posReqFreq) * 1000; + + controlParams.posReqKind = settings.value(SETTINGS_POS_REQ_KIND, POS_REQ).value(); + +/// T4 + posReqKind = controlParams.posReqKind; + switch (posReqKind) { + case POS_REQ: + controlParams.usePositionRequest = true; + controlParams.positionSyncSimu = false; + controlParams.positionNoDisplay = false; + break; + case POS_SYNC: + controlParams.usePositionRequest = false; + controlParams.positionSyncSimu = true; + controlParams.positionNoDisplay = false; + break; + case POS_NO: + controlParams.usePositionRequest = false; + controlParams.positionSyncSimu = false; + controlParams.positionNoDisplay = true; + break; + } + // -> 'gcode::setPosReqKind(posRegKind)' + emit setPosReqKind(posReqKind) ; + + setLcdState(controlParams.usePositionRequest /*|| controlParams.positionSyncSimu */ ); +/// <-- +} + +// save last state of settings +// calls : 'MainWindow::closeEvent()':1, +void MainWindow::writeSettings() +{ + QSettings settings; + + settings.setValue(SETTINGS_FILE_OPEN_DIALOG_STATE, fileOpenDialogState); + settings.setValue(SETTINGS_NAME_FILTER, nameFilter); + settings.setValue(SETTINGS_DIRECTORY, directory); + settings.setValue(SETTINGS_PORT, ui->cmbPort->currentText()); + settings.setValue(SETTINGS_BAUD, ui->comboBoxBaudRate->currentText()); + + settings.setValue(SETTINGS_PROMPTED_AGGR_PRELOAD, promptedAggrPreload); + settings.setValue(SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ, ui->chkRestoreAbsolute->isChecked()); + settings.setValue(SETTINGS_JOG_STEP, QString().number(jogStep)); + + // From http://stackoverflow.com/questions/74690/how-do-i-store-the-window-size-between-sessions-in-qt + settings.beginGroup("mainwindow"); + + settings.setValue( "geometry", saveGeometry() ); + settings.setValue( "savestate", saveState() ); + settings.setValue( "maximized", isMaximized() ); + if ( !isMaximized() ) { + settings.setValue( "pos", pos() ); + settings.setValue( "size", size() ); + } + + settings.endGroup(); +} + +void MainWindow::receiveList(QString msg) +{ + addToStatusList(true, msg); +} + +void MainWindow::receiveListFull(QStringList list) +{ + addToStatusList(list); +} + +void MainWindow::receiveListOut(QString msg) +{ + addToStatusList(false, msg); +} + +void MainWindow::addToStatusList(bool in, QString msg) +{ + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + return; + + QString nMsg(msg); + if (!in) + nMsg = "> " + msg; + + ui->statusList->appendPlainText( nMsg ); +} + +void MainWindow::addToStatusList(QStringList& list) +{ + foreach (QString msg, list) + { + msg = msg.trimmed(); + msg.remove('\r'); + msg.remove('\n'); + + if (msg.length() == 0) + continue; + + ui->statusList->appendPlainText( msg ); + + status("%s", qPrintable(msg) ); + } +} + +void MainWindow::receiveMsgSatusBar(QString msg) +{ + // ui->centralWidget->setStatusTip(msg); +/// T4 Status bar leaves old error displayed even after error corrected #57 + ui->statusBar->showMessage(msg); +} + +void MainWindow::grblSettings() +{ + GrblDialog dlg(this, &gcode); + dlg.setParent(this); + dlg.getSettings(); + dlg.exec(); +} + +void MainWindow::showAbout() +{ + About about(this); + about.exec(); +} + +// calls : 'ui->spindleButton::toggled(valid)' +void MainWindow::toggleSpindle(bool) +{ +/// T4 + QPalette palette; + QString stateon(tr("Spindle On")), stateoff(tr("Spindle Off")); + if (ui->spindleButton->isChecked()) + { + sendGcode("M05\r"); + receiveList(stateoff); + + ui->spindleButton->setText(stateon) ; + palette.setColor(QPalette::Button,Qt::gray) ; + } + else + { + sendGcode("M03\r"); + receiveList(stateon); + + ui->spindleButton->setText(stateoff) ; + palette.setColor(QPalette::Button,Qt::yellow) ; + } + // color 'spindleButton' + ui->spindleButton->setPalette(palette); +} + +void MainWindow::toggleRestoreAbsolute() +{ + absoluteAfterAxisAdj = ui->chkRestoreAbsolute->QAbstractButton::isChecked(); +} + +/// T4 animator, +// calls : 'Viewer::setLivePoint()':1, 'Viewer::setLiveRelPoint()':1, +void MainWindow::updateLCD(QVector3D coord) +{ + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->HomeFourthBtn->setEnabled(controlParams.useFourAxis); + // + machineCoordinates = Coord3D(); + workCoordinates = Coord3D(coord); +// T4 !!! + cmdMan = false; + refreshLcd(); +} +///<-- + +void MainWindow::updateCoordinates(Coord3D machineCoord, Coord3D workCoord) +{ + ui->lcdWorkNumberFourth->setEnabled(controlParams.useFourAxis); + ui->lcdMachNumberFourth->setEnabled(controlParams.useFourAxis); + ui->IncFourthBtn->setEnabled(controlParams.useFourAxis); + ui->DecFourthBtn->setEnabled(controlParams.useFourAxis); + ui->HomeFourthBtn->setEnabled(controlParams.useFourAxis); + machineCoordinates = machineCoord; + workCoordinates = workCoord; + + refreshLcd(); +} + +void MainWindow::refreshLcd() +{ + lcdDisplay('X', true, workCoordinates.x); + lcdDisplay('Y', true, workCoordinates.y); + lcdDisplay('Z', true, workCoordinates.z); + lcdDisplay('X', false, machineCoordinates.x); + lcdDisplay('Y', false, machineCoordinates.y); + lcdDisplay('Z', false, machineCoordinates.z); + if (controlParams.useFourAxis) { + lcdDisplay(controlParams.fourthAxisName, true, workCoordinates.fourth); + lcdDisplay(controlParams.fourthAxisName, false, machineCoordinates.fourth); + } + else { + lcdDisplay(controlParams.fourthAxisName, true, 0); + lcdDisplay(controlParams.fourthAxisName, false, 0); + } +} + +void MainWindow::lcdDisplay(char axis, bool workCoord, float floatVal) +{ + QString value = QString::number(floatVal, 'f', 3); + switch (axis) + { + case 'X': + if (workCoord) + ui->lcdWorkNumberX->display(value); + else + ui->lcdMachNumberX->display(value); + break; + case 'Y': + if (workCoord) + ui->lcdWorkNumberY->display(value); + else + ui->lcdMachNumberY->display(value); + break; + case 'Z': + if (workCoord) + ui->lcdWorkNumberZ->display(value); + else + ui->lcdMachNumberZ->display(value); + break; + default: + if (axis == FOURTH_AXIS_A || axis == FOURTH_AXIS_B || axis == FOURTH_AXIS_C + || axis == FOURTH_AXIS_U || axis == FOURTH_AXIS_V || axis == FOURTH_AXIS_W + ) + { + if (workCoord) + ui->lcdWorkNumberFourth->display(value); + else + ui->lcdMachNumberFourth->display(value); + } + else + { + err( qPrintable(tr("Unexpected type %c")), axis) ; + } + break; + } +/// T4 + if (cmdMan && !runFile) { + // tool + float x = ui->lcdWorkNumberX->value(), + y = ui->lcdWorkNumberY->value(), + z = ui->lcdWorkNumberZ->value(); + emit setLivePoint(QVector3D(x, y, z), controlParams.useMm ); +//diag(" =====>cmdMan = %s", cmdMan==true ?"true" : "false"); + } +} + +void MainWindow::zJogSliderDisplay(int pos) +{ + QString str; + + pos -= CENTER_POS; + + if (pos > 0) + if(controlParams.useMm) + str.sprintf("+%d", pos); + else + str.sprintf("+%.1f",(double)pos/10); + else if (pos < 0) + if(controlParams.useMm) + str.sprintf("%d", pos); + else + str.sprintf("%.1f", (double)pos/10); + else + str = "0"; + + ui->currentZJogSliderDelta->setText(str); + + double newPos; + QString to; + if(controlParams.useMm) + newPos = pos + sliderTo; + else + newPos = (double)pos/10+sliderTo; + + if(controlParams.useMm) + to.sprintf("%.1f", newPos); + else + to.sprintf("%.1f", newPos); + + if (sliderPressed) + { + ui->resultingZJogSliderPosition->setText(to); + if(controlParams.useMm) + info(qPrintable(tr("Usr chg: pos=%d new=%d\n")), pos, newPos); + else + info(qPrintable(tr("Usr chg: pos=%.1f new=%.1f\n")), (double)pos/10, newPos); + } + else + { + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + if(controlParams.useMm) + info(qPrintable(tr("Usr chg no slider: %d\n")), pos); + else + info(qPrintable(tr("Usr chg no slider: %.1f\n")), (double) pos/10); + } +} + +void MainWindow::zJogSliderPressed() +{ + sliderPressed = true; + if (workCoordinates.stoppedZ && workCoordinates.sliderZIndex == sliderZCount) + { + info(qPrintable(tr("Pressed and stopped\n"))); + sliderTo = workCoordinates.z; + } + else + { + info(qPrintable(tr("Pressed not stopped\n"))); + } +} + +void MainWindow::zJogSliderReleased() +{ + info(qPrintable(tr("Released\n"))); + + if (sliderPressed) + { + sliderPressed = false; + int value = ui->verticalSliderZJog->value(); + + ui->verticalSliderZJog->setSliderPosition(CENTER_POS); + ui->currentZJogSliderDelta->setText("0"); + + value -= CENTER_POS; + + if (value != 0) + { +/// T4 + enableAllButtons(false); + + if(controlParams.useMm) + sliderTo += value; + else + sliderTo += (double)value/10; + float setTo = value; + ui->lcdFeedRateGcode->display(controlParams.zJogRate); + cmdMan = true; + if(controlParams.useMm) + emit axisAdj('Z', setTo, invZ, absoluteAfterAxisAdj, sliderZCount++); + else + emit axisAdj('Z', setTo/10, invZ, absoluteAfterAxisAdj, sliderZCount++); + } + } +} + +void MainWindow::setQueuedCommands(int commandCount, bool running) +{ + if (running) + { + switch (queuedCommandState) + { + case QCS_OK: + if (lastQueueCount == 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 2000) + { + if (!queuedCommandsStarved) + { +//diag("DG >>>>Switch to red\n"); + + queuedCommandsStarved = true; + + ui->labelQueuedCommands->setStyleSheet("QLabel { background-color : rgb(255,0,0); color : white; }"); + + queuedCommandState = QCS_WAITING_FOR_ITEMS; + } + } + } + break; + case QCS_WAITING_FOR_ITEMS: + if (commandCount > 0) + { + if (queuedCommandsEmptyTimer.elapsed() > 3000) + { + if (queuedCommandsStarved) + { +//diag("DG >>>>Switch to green\n"); + + queuedCommandsStarved = false; + + ui->labelQueuedCommands->setStyleSheet(""); + } + + queuedCommandsEmptyTimer.restart(); + + queuedCommandState = QCS_OK; + } + } + break; + } + + if (queuedCommandsRefreshTimer.elapsed() > 1000) + { + ui->progressQueuedCommands->setValue(commandCount); + queuedCommandsRefreshTimer.restart(); + } + } + else + { + queuedCommandsEmptyTimer.restart(); + queuedCommandState = QCS_OK; + ui->progressQueuedCommands->setValue(commandCount); + } + + lastQueueCount = commandCount; +} +/// T4 +// calls : +void MainWindow::setQueueClear() +{ + resetProgress() ; +} + +void MainWindow::setLcdState(bool valid) +{ + if (lastLcdStateValid != valid) + { + QString ss = ""; + if (!valid) + { + if (checkState) + ss = "QLCDNumber { background-color: #F8F8F8; color: yellow; }"; + else + ss = "QLCDNumber { background-color: #F8F8F8; color: #F0F0F0; }"; + } + ui->lcdWorkNumberX->setStyleSheet(ss); + ui->lcdMachNumberX->setStyleSheet(ss); + ui->lcdWorkNumberY->setStyleSheet(ss); + ui->lcdMachNumberY->setStyleSheet(ss); + ui->lcdWorkNumberZ->setStyleSheet(ss); + ui->lcdMachNumberZ->setStyleSheet(ss); + ui->lcdWorkNumberFourth->setStyleSheet(ss); + ui->lcdMachNumberFourth->setStyleSheet(ss); + + lastLcdStateValid = valid; + } +} +/* +void MainWindow::refreshPosition() +{ + // gotoXYZFourth(REQUEST_CURRENT_POS); ?? + emit gotoXYZFourth(REQUEST_CURRENT_POS); +} +*/ + +// calls : 'sliderStep::valueChanged(int)' +void MainWindow::stepChanged(int newstep) +{ // newstep into [0..10000] mm*100 + float fs = newstep/100.0; + if (!controlParams.useMm) + fs /= MM_IN_AN_INCH ; + ui->lcdStep->display(fs); + jogStep = fs; +} + +///----------------------------------------------------------------------------- +/// T2 +// calls : 'GCode::sendGcodeInternal()':1, +void MainWindow::setLinesFile(QString linesFile, bool check) +{ + if (check) /// T3 + linesFile += "/" + QString().setNum(totalLinesFile);; + + ui->outputLines->setText(linesFile); +} + +///----------------------------------------------------------------------------- +/// for visuGode and visu3D +/// T4 +// calls : 'ui->visualButton::toggled(valid)' +void MainWindow::toVisual(bool valid) +{ + ui->prevButton->setEnabled(valid); + ui->nextButton->setEnabled(valid); + ui->pauseButton->setEnabled(valid); + + ui->btnClearStatusList->setEnabled(!valid); + ui->btnPrintStatusList->setEnabled(!valid); + ui->btnPrintVisual->setEnabled(!valid) ; + + if (ui->visualButton->isChecked()) + ui->visualButton->setText(tr("No animate")) ; + else + ui->visualButton->setText(tr("Animate")) ; + // no openFile if valid + ui->openFile->setEnabled(!valid); + if (!valid) { // no animate + ui->btnCheck->setEnabled(openState); + ui->Begin->setEnabled(openState); + } + else { + ui->btnCheck->setEnabled(!valid); + ui->Begin->setEnabled(!valid); + } + // tab + bool openport = ui->btnOpenPort->text() != open_button_text ; + if (!openport) { + ui->tabAxisVisualizer->setEnabled(valid); + ui->tabVisu->setTabEnabled(TAB_CONSOLE_INDEX, !valid); + // (in)valid manual controls + enableManualControl(false); + } + else { + ui->tabAxisVisualizer->setEnabled(true); + ui->tabAxisVisualizer->setTabEnabled(TAB_VISU3D_INDEX, true); + // invalid manual controls + enableManualControl(!valid); + } + ui->tabVisu->setTabEnabled(TAB_CONSOLE_INDEX, !valid); + ui->tabAxisVisualizer->setTabEnabled(TAB_VISUALIZER_INDEX, !valid); + // to ui->Viewer + emit setVisual(valid); +} + +// calls :'ui->pauseButton::toggled(valid)' +void MainWindow::toPause(bool valid) +{ + QPalette palette; + ui->prevButton->setEnabled(valid); + ui->nextButton->setEnabled(valid); + if (ui->pauseButton->isChecked()) { + ui->pauseButton->setText(tr("Run")) ; + palette.setColor(QPalette::Button,Qt::gray) ; + // mouse and keyboard key + connect(ui->visuGcode, SIGNAL(cursorPositionChanged() ), this, SLOT(on_cursorVisuGcode()) ) ; + } + else { + ui->pauseButton->setText(tr("Pause")) ; + palette.setColor(QPalette::Button,Qt::yellow); + // no mouse and no keyboard key + disconnect(ui->visuGcode, SIGNAL(cursorPositionChanged() ), this, SLOT(on_cursorVisuGcode()) ) ; + } + // color 'pauseButton' + ui->pauseButton->setPalette(palette); + // to ui->Viewer + emit setPause(valid); +} + +// calls : 'ui->visuGcode::cursorPositionChanged()' +void MainWindow::on_cursorVisuGcode() +{ + int line = ui->visuGcode->textCursor().blockNumber(); + if (line <= totalLinesFile) + setActiveLineVisuGcode(line +1, false); +} + +// calls : MainWindow::on_cursorVisuGcode()':1, 'Viewer::setLivePoint()':1, +// 'Viewer::setLiveRelPoint()':1 +void MainWindow::setActiveLineVisuGcode( int line, bool visu ) +{ + if (!line) return ; + + QTextBlock block; + QTextCursor cursor; + QTextBlockFormat blockFormat; + + block = ui->visuGcode->document()->findBlockByNumber( activeLine - 1 ); + cursor = QTextCursor( block ); + blockFormat = cursor.blockFormat(); + blockFormat.clearBackground(); + cursor.setBlockFormat( blockFormat ); + + activeLine = line ; + + block = ui->visuGcode->document()->findBlockByNumber( activeLine - 1 ); + cursor = QTextCursor( block ); + blockFormat = cursor.blockFormat(); + blockFormat.setBackground( Qt::lightGray ); + cursor.setBlockFormat( blockFormat ); + ui->visuGcode->setTextCursor( cursor ); + /// emission line number + QString strline = QString().setNum(activeLine) ; + // to 'ui->lineCode' (QLabel) + emit setLineCode(strline); + // to Viewer : 'ui->visu3D::setNumLine(activeLine)' + if (!visu) { + emit setNumLine(strline); + } +} + +/// display timer period animation +// calls : none ? +void MainWindow::setLCDValue(int value) +{ + ui->lcdPeriodAnim->display(value); +} + +// display the correct unit +// calls : 'GCode::setResponseWait( )':1, 'GCode::checkGrbl()':0, +void MainWindow::setUnitMmAll (bool useMm ) +{ +//diag("MainWindow::setUnitMmAll (..) ..."); +//1- display + QString unit(tr("mm")); + double val = ui->doubleSpinBoxTol->value(); + if (useMm) { + ui->doubleSpinBoxTol->setDecimals(3); + ui->doubleSpinBoxTol->setSingleStep(TOL_MM_STEP); + ui->doubleSpinBoxTol->setMinimum(TOL_MM_MIN); + ui->doubleSpinBoxTol->setMaximum(TOL_MM_MAX); + if (ui->labelTolUnit->text() != unit) + val = TOL_MM ; + } + else { + ui->doubleSpinBoxTol->setDecimals(4); + ui->doubleSpinBoxTol->setSingleStep(TOL_IN_STEP); + ui->doubleSpinBoxTol->setMinimum(TOL_IN_MIN); + ui->doubleSpinBoxTol->setMaximum(TOL_IN_MAX); + unit = QString(tr("in")); + if (ui->labelTolUnit->text() != unit) + val = TOL_IN; + } + ui->doubleSpinBoxTol->setValue(val) ; + + ui->lcdFeedRateGcode->display(0.0); + + ui->labelFeedRateUnit->setText( unit + "/" + tr("mn")); + ui->labelTolUnit->setText(unit); + unit += " "; + ui->unitX->setText(unit); + ui->unitY->setText(unit); + ui->unitZ->setText(unit); + if (controlParams.fourthAxisRotate) + unit = tr("deg."); + else + unit = tr("mm"); + + ui->unitFourth->setText(unit); + // slider + int step = ui->sliderStep->value(); + ui->sliderStep->setValue(0); + ui->sliderStep->setValue(step); +// Grbl + if (useMm) { + + } + else { + + } +} + +/// T4 +void MainWindow::enableManualControl(bool v) +{ + ui->chkRestoreAbsolute->setEnabled(v); + // step + ui->sliderStep->setEnabled(v); + ui->lcdStep->setEnabled(v); + // dZ + ui->verticalSliderZJog->setEnabled(v); + ui->currentZJogSliderDelta->setEnabled(v); + ui->resultingZJogSliderPosition->setEnabled(v); + // axes buttons + ui->DecXBtn->setEnabled(v); ui->IncXBtn->setEnabled(v); ui->HomeXBtn->setEnabled(v) ; + if (ui->lcdWorkNumberX->value()==0) + ui->HomeXBtn->setEnabled(false) ; + ui->DecYBtn->setEnabled(v); ui->IncYBtn->setEnabled(v);ui->HomeYBtn->setEnabled(v); + if (ui->lcdWorkNumberY->value()==0) + ui->HomeYBtn->setEnabled(false); + ui->DecZBtn->setEnabled(v); ui->IncZBtn->setEnabled(v); ui->HomeZBtn->setEnabled(v) ; + if (ui->lcdWorkNumberZ->value()==0) + ui->HomeZBtn->setEnabled(false) ; + if (controlParams.useFourAxis ) { + ui->DecFourthBtn->setEnabled(v); ui->IncFourthBtn->setEnabled(v); + ui->HomeFourthBtn->setEnabled(v) ; + if (ui->lcdWorkNumberFourth->value()==0) + ui->HomeFourthBtn->setEnabled(false) ; + } + // spindle + ui->spindleButton->setEnabled(v); +} + +void MainWindow::enableTabVisuControls(bool v) +{ + // animation period + ui->lcdPeriodAnim->setEnabled(v); + ui->labelPeriod->setEnabled(v); + ui->dialPeriodRepeat->setEnabled(v); + // animation cursors + ui->nextButton->setEnabled(v); + ui->lineCode->setEnabled(v); + ui->nline->setEnabled(v); + ui->prevButton->setEnabled(v); + // segments interpolation + ui->lcdSegments->setEnabled(v); + ui->labelSegments->setEnabled(v); + // tolerance + ui->doubleSpinBoxTol->setEnabled(v); + ui->labelTol->setEnabled(v); + ui->labelTolUnit->setEnabled(v); + ui->lcdTolerance->setEnabled(v); + // on off + ui->pauseButton->setEnabled(v); + ui->visualButton->setEnabled(v); +} + +// Grbl commands +void MainWindow::enableButtonGrblControls(bool v) +{ + ui->btnHelp->setEnabled(v); + ui->btnParameters->setEnabled(v); + ui->btnParserState->setEnabled(v); + ui->btnBuildInfo->setEnabled(v); + ui->btnStartupBlocks->setEnabled(v); + ui->btnCheck->setEnabled(v); + ui->btnGrblSettings->setEnabled(v); + ui->btnUnlockGrbl->setEnabled(v); + ui->btnHomingCycle->setEnabled(v); + // ui->btnCycleStart->setEnabled(v); + // ui->btnFeedHold->setEnabled(v); + ui->btnStatus->setEnabled(v); + ui->btnResetGrbl->setEnabled(v); + + ui->btnSetG92->setEnabled(v); + ui->btnSetHome->setEnabled(v); + ui->btnGoHomeSafe->setEnabled(v); + // = 'btnStatus' + // ui->pushButtonRefreshPos->setEnabled(v); +} + +// calls : 'ui->btnClearStatusList' +void MainWindow::toClearSatusList() +{ + if (ui->statusList->textCursor().hasSelection()) { + ui->statusList->textCursor().removeSelectedText(); + } +} + +// calls : 'ui->btnPrintStatusList' +void MainWindow::toPrintStatusList() +{ + QPrinter printer; + QString txt = GRBL_CONTROLLER_NAME_AND_VERSION VERSION_BUILD; + txt += "\n\n"; + // file title + txt += ui->filePath->text(); + txt += "\n\n"; + QPrintDialog *dialog = new QPrintDialog(&printer, this); + if (ui->statusList->textCursor().hasSelection()) { + dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); + printer.setPrintRange(QPrinter::Selection); + txt += ui->statusList->textCursor().selectedText(); + } + else { + txt += ui->statusList->document()->toPlainText(); + } + if (dialog->exec() == QDialog::Accepted) { + QTextDocument doc(txt); + doc.print(&printer); + } +} + +// calls : 'ui->btnPrintVisual' +void MainWindow::toPrintVisual() +{ + QPrinter printer; + QString txt = GRBL_CONTROLLER_NAME_AND_VERSION VERSION_BUILD; + txt += "\n\n"; + // file title + txt += ui->filePath->text(); + txt += "\n\n"; + QPrintDialog *dialog = new QPrintDialog(&printer, this); + if (ui->visuGcode->textCursor().hasSelection()) { + dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); + printer.setPrintRange(QPrinter::Selection); + txt += ui->visuGcode->textCursor().selectedText(); + } + else { + txt += ui->visuGcode->document()->toPlainText(); + } + if (dialog->exec() == QDialog::Accepted) { + QTextDocument doc(txt); + doc.print(&printer); + } +} + +// calls : 'processGCode(...)':1, +void MainWindow::setUseMm(bool useMm) +{ + /// acces to "Options::checkBoxUseMmManualCmds" + if (opt.getUseMm() != useMm ) { +//diag("MainWindow::setUseMm(..) ..."); + opt.setUseMm(useMm); + } +} +// calls : 'GCode::parseCoordinates(..)':2, +void MainWindow::setLastState(QString state) +{ + QPalette palette = ui->outputLastState->palette(); + palette.setColor(ui->outputLastState->backgroundRole(), Qt::black); + if(state == "Idle") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::black); + else + if(state == "Alarm") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::red); + else + if(state == "Run") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::darkGreen); + else + if(state == "Hold") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::magenta); + else + if(state == "Check") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::yellow); + else + if(state == "Home") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::blue); + else + if(state == "Queue") + palette.setColor(ui->outputLastState->foregroundRole(), Qt::darkCyan); + else + palette.setColor(ui->outputLastState->backgroundRole(), Qt::black); + + ui->outputLastState->setPalette(palette); + ui->outputLastState->setText(state); +} +//------------------------------------------------------------------------------ diff --git a/GCV-3.6.1-T4/src/mainwindow.h b/GCV-3.6.1-T4/src/mainwindow.h new file mode 100644 index 0000000..be6b8ec --- /dev/null +++ b/GCV-3.6.1-T4/src/mainwindow.h @@ -0,0 +1,315 @@ +/**************************************************************** + * mainwindow.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +/// T4 +#include +#include "about.h" +#include "definitions.h" +#include "grbldialog.h" +#include "options.h" +#include "timer.h" +#include "positem.h" +#include "gcode.h" +#include "renderarea.h" +#include "visu3D/viewer3D.h" + +#define COMPANY_NAME "zapmaker" +#define APPLICATION_NAME "GrblController" +#define DOMAIN_NAME "org.zapmaker" + +/// T4 +#define TAB_VISUALIZER_INDEX 0 +#define TAB_VISU3D_INDEX 1 + +#define TAB_CONSOLE_INDEX 0 +#define TAB_VISUGCODE_INDEX 1 + +#define CENTER_POS 40 + +#define MAX_STATUS_LINES_WHEN_ACTIVE 200 + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void closeEvent(QCloseEvent *event); + + //variables + int delete_nr; + +signals: + //threads + void openPort(QString port, QString baudRate); + void closePort(bool reopen); + void shutdown(); + void sendGcode(QString line, bool recordResponseOnFail = false, int waitCount = SHORT_WAIT_SEC); +/// T3 + void sendFile(QString path, bool); + void gotoXYZFourth(QString line); + void axisAdj(char axis, float coord, bool inv, bool absoluteAfterAxisAdj, int sliderZCount); + void setResponseWait(ControlParams controlParams); + void setProgress(int percent); + void setRuntime(QString runtime); + void sendSetHome(); +/// T3, T4 + // void sendGrblPause(bool); + void sendGrblHelp(); + void sendGrblParserState(); + void sendGrblParameters(); + void sendGrblBuildInfo(); + void sendGrblStartupBlocks(); + void sendGrblCheck(bool); + void sendGrblUnlock(); + void sendGrblHomingCycle(); + void sendGrblCycleStart(); + void sendGrblFeedHold() ; + void sendGrblStatus(); + void sendGrblReset(); + + void goToHome(); +/// T4 + void goToHomeAxis(char axis); + void setLineCode(QString) ; + void setItems(QList); + void setTotalNumLine(QString); + void setNumLine(QString); + void setLivePoint(QVector3D, bool) ; + void setLiveRelPoint(QVector3D) ; +/// T4 + void setFeedRateToLine(QList) ; + void setSpeedSpindleToLine(QList) ; + void runCode(bool, int); + void setVisual(bool); + void setPause(bool); + void setTol(double); + void setPosReqKind(int); +/// <- + +private slots: +/// T4 + void pauseSend(bool); // suspend sendFile() + void grblHelp(); + void grblSettings(); + void grblParameters() ; + void grblParserState() ; + void grblBuildInfo(); + void grblStartupBlocks(); + void grblCheck(bool); + void grblUnlock(); + void grblHomingCycle() ; +// not used +void grblCycleStart(); +void grblFeedHold(); + void grblStatus(); + void grblReset(); + + //buttons + void openPort(); + //Adjust + void decX(); + void decY(); + void decZ(); + void decFourth(); + void incFourth(); + void incX(); + void incY(); + void incZ(); +/// T5 + void homeX(); + void homeY(); + void homeZ(); + void homeFourth(); + + void endHomeAxis(); + void setHome(); + //manualhomeFourth() + void gotoXYZFourth(); + +/// T3 + void begin(); + void openFile(); + void stop(); + void stopSending(); + // + void portIsOpen(bool sendCode); + void portIsClosed(bool reopen); + void adjustedAxis(); + + void toggleSpindle(bool); + //check boxes + void toggleRestoreAbsolute(); + + //communications + //options + void setSettingsOptions(); + void setSettingsOptionsUseMm(); + //thread + void receiveList(QString msg); + void receiveListFull(QStringList list); + void receiveListOut(QString msg); + void receiveMsgSatusBar(QString msg); + //menu bar + void getOptions(); + void showAbout(); + void enableGrblDialogButton(); + + void updateCoordinates(Coord3D machineCoord, Coord3D workCoord); + + void goHomeSafe(); + void zJogSliderDisplay(int pos); + void zJogSliderPressed(); + void zJogSliderReleased(); + + void setQueuedCommands(int commandCount, bool running); +/// T4 + void setQueueClear(); + void setLcdState(bool valid); + // void refreshPosition(); + +/// T2 + void setLinesFile(QString linesFile, bool check); +/// T4 3D + void updateLCD(QVector3D); +/// T4 for 'visuGcode' + void toVisual(bool); + void toPause(bool); + void on_cursorVisuGcode(); + void setActiveLineVisuGcode(int, bool); + void setLCDValue(int value); + // change text "mm" <=> "in" + void setUnitMmAll(bool); + void stepChanged(int); + void enableManualControl(bool); + void enableTabVisuControls(bool); + void enableButtonGrblControls(bool); + + void toClearSatusList(); + void toPrintStatusList(); + void toPrintVisual(); + + void setLastState(QString state); + +private: + // enums + enum + { + NO_ITEM = 0, X_ITEM, Y_ITEM, Z_ITEM, I_ITEM, J_ITEM, K_ITEM, + P_ITEM, F_ITEM, S_ITEM + }; + enum + { + QCS_OK = 0, QCS_WAITING_FOR_ITEMS + }; + //objects + Ui::MainWindow *ui; + //FileSender fileSender; + //QThread fileSenderThread; + GCode gcode; + QThread gcodeThread; + + Timer runtimeTimer; + QThread runtimeTimerThread; + + Options opt; + + //variables + bool invX; + bool invY; + bool invZ; + bool invFourth; + /// for translation + QString open_button_text ; + QString close_button_text ; + bool mm; + QString styleSheet; + QString directory; + QString nameFilter; + QString lastOpenPort; + QString lastBaudRate; + QByteArray fileOpenDialogState; + Coord3D machineCoordinates; + Coord3D workCoordinates; + bool absoluteAfterAxisAdj; + bool checkLogWrite; +/// T4 + QTime queuedCommandsEmptyTimer; + QTime queuedCommandsRefreshTimer; + QList posList; + bool sliderPressed; + double sliderTo; + int sliderZCount; + bool promptedAggrPreload; + ControlParams controlParams; + + bool queuedCommandsStarved; + int lastQueueCount; + int queuedCommandState; + QStringList fullStatus; + bool lastLcdStateValid; + float jogStep; + // QString jogStepStr; +/// T3 + bool checkState; + bool sendButtonCheck; + bool openState; + int totalLinesFile; +/// T4 for 'visuGcode' + int activeLine; + bool runFile, cmdMan; + /// mode display request + int posReqKind; + +private: +// methods + void setUseMm(bool); + int SendJog(QString strline); + void readSettings(); + void writeSettings(); + void addToStatusList(bool in, QString msg); + void addToStatusList(QStringList& list); + void enableAllButtons(bool); + void openPortCtl(bool reopen); + void resetProgress(); + void refreshLcd(); + void lcdDisplay(char axis, bool workCoord, float value); + void updateSettingsFromOptionDlg(QSettings& settings); + int computeListViewMinimumWidth(QAbstractItemView* view); + void preProcessFile(QString filepath); + +/// T4 3 axes + plane + bool processGCode(QString inputLine, + double& x, double& y, double& z, + double& i, double& j, double& k, + int& p, bool& arc, bool& cw, bool& mm, + int& g, int& plane, bool& helix, + double& f, double& ss + ); +/// <- + double decodeLineItem(const QString& item, const int next, bool& valid, int& nextIsValue); + double decodeDouble(QString value, bool& valid); +}; + +#endif // MAINWINDOW_H diff --git a/GCV-3.6.1-T4/src/makeWin.bat b/GCV-3.6.1-T4/src/makeWin.bat new file mode 100644 index 0000000..8f4d8bf --- /dev/null +++ b/GCV-3.6.1-T4/src/makeWin.bat @@ -0,0 +1,16 @@ +rem May 30, 2014 +rem LETARTARE + +rem 3.6.1-Tx + +rem for release + +qmake -config release -spec win32-g++ GCV.pro +mingw32-make -fmakefile.release + +rem for debug + +rem qmake -config debug -spec win32-g++ GCV.pro +rem mingw32-make -fmakefile.debug + +cd .. diff --git a/GCV-3.6.1-T4/src/options.cpp b/GCV-3.6.1-T4/src/options.cpp new file mode 100644 index 0000000..b3dc147 --- /dev/null +++ b/GCV-3.6.1-T4/src/options.cpp @@ -0,0 +1,377 @@ +/**************************************************************** + * options.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "options.h" +#include "ui_options.h" + +Options::Options(QWidget *parent) : + QDialog(parent), + ui(new Ui::Options) +{ + ui->setupUi(this); +} + +Options::~Options() +{ + +} +/// T4 +void Options::init() +{ + connect(ui->checkBoxUseMmManualCmds,SIGNAL(toggled(bool)),this,SLOT(toggleUseMm(bool))); + connect(ui->chkLimitZRate,SIGNAL(toggled(bool)),this,SLOT(toggleLimitZRate(bool))); + connect(ui->checkBoxFourAxis,SIGNAL(toggled(bool)),this,SLOT(toggleFourAxis(bool))); + connect(ui->checkBoxPositionReportEnabled,SIGNAL(toggled(bool)),this,SLOT(togglePosReporting(bool))); + connect(this, SIGNAL(setSettingsOptionsUseMm()), parentWidget(), SLOT(setSettingsOptionsUseMm())); + + QSettings settings; + + QString invX = settings.value(SETTINGS_INVERSE_X, "false").value(); + QString invY = settings.value(SETTINGS_INVERSE_Y, "false").value(); + QString invZ = settings.value(SETTINGS_INVERSE_Z, "false").value(); + QString invFourth = settings.value(SETTINGS_INVERSE_FOURTH, "false").value(); + ui->chkInvFourth->setChecked(invFourth == "true"); + ui->chkInvX->setChecked(invX == "true"); + ui->chkInvY->setChecked(invY == "true"); + ui->chkInvZ->setChecked(invZ == "true"); + + // enable logging by default + QString enDebugLog = settings.value(SETTINGS_ENABLE_DEBUG_LOG, "true").value(); + // default aggressive preload behavior to 'true'! + QString enAggressivePreload = settings.value(SETTINGS_USE_AGGRESSIVE_PRELOAD, "true").value(); + QString waitForJogToComplete = settings.value(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, "true").value(); + QString useMmManualCmds = settings.value(SETTINGS_USE_MM_FOR_MANUAL_CMDS, "true").value(); + QString enFourAxis = settings.value(SETTINGS_FOUR_AXIS_USE, "false").value(); + char fourthAxisType = settings.value(SETTINGS_FOUR_AXIS_NAME, FOURTH_AXIS_A).value(); + + if (enFourAxis == "false") + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + + ui->groupBoxFourthAxis->setEnabled(false); + } + else + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + + switch (fourthAxisType) + { + case FOURTH_AXIS_A: + default: + ui->radioButtonFourthAxisA->setChecked(true); + break; + case FOURTH_AXIS_B: + ui->radioButtonFourthAxisB->setChecked(true); + break; + case FOURTH_AXIS_C: + ui->radioButtonFourthAxisC->setChecked(true); + break; + case FOURTH_AXIS_U: + ui->radioButtonFourthAxisU->setChecked(true); + break; + case FOURTH_AXIS_V: + ui->radioButtonFourthAxisV->setChecked(true); + break; + case FOURTH_AXIS_W: + ui->radioButtonFourthAxisW->setChecked(true); + break; + } + } + + ui->checkBoxEnableDebugLog->setChecked(enDebugLog == "true"); + ui->chkAggressivePreload->setChecked(enAggressivePreload == "true"); + //ui->checkBoxWaitForJogToComplete->setChecked(waitForJogToComplete == "true"); + ui->checkBoxWaitForJogToComplete->hide(); + ui->checkBoxUseMmManualCmds->setChecked(useMmManualCmds == "true"); + ui->checkBoxFourAxis->setChecked(enFourAxis == "true"); + + int waitTime = settings.value(SETTINGS_RESPONSE_WAIT_TIME, DEFAULT_WAIT_TIME_SEC).value(); + ui->spinResponseWaitSec->setValue(waitTime); + + double zJogRate = settings.value(SETTINGS_Z_JOG_RATE, DEFAULT_Z_JOG_RATE).value(); + ui->doubleSpinZJogRate->setValue(zJogRate); + +/// T4 + ui->spinMaxStatusLines->setValue( settings.value( SETTINGS_MAX_STATUS_LINES, 0 ).value() ); + + QString zRateLimit = settings.value(SETTINGS_Z_RATE_LIMIT, "false").value(); + ui->chkLimitZRate->setChecked(zRateLimit == "true"); + + double zRateLimitAmount = settings.value(SETTINGS_Z_RATE_LIMIT_AMOUNT, DEFAULT_Z_LIMIT_RATE).value(); + ui->doubleSpinZRateLimit->setValue(zRateLimitAmount); + double xyRateAmount = settings.value(SETTINGS_XY_RATE_AMOUNT, DEFAULT_XY_RATE).value(); + ui->doubleSpinXYRate->setValue(xyRateAmount); + + if (!ui->chkLimitZRate->isChecked()) + { + ui->doubleSpinZRateLimit->setEnabled(false); + ui->doubleSpinXYRate->setEnabled(false); + } + + QString ffCmd = settings.value(SETTINGS_FILTER_FILE_COMMANDS, "false").value(); + ui->chkFilterFileCommands->setChecked(ffCmd == "true"); + QString rPrecision = settings.value(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, "false").value(); + ui->checkBoxReducePrecForLongLines->setChecked(rPrecision == "true"); + ui->spinBoxGrblLineBufferSize->setValue(settings.value(SETTINGS_GRBL_LINE_BUFFER_LEN, DEFAULT_GRBL_LINE_BUFFER_LEN).value()); + ui->spinBoxCharSendDelay->setValue(settings.value(SETTINGS_CHAR_SEND_DELAY_MS, DEFAULT_CHAR_SEND_DELAY_MS).value()); +/// T4 + int posReqKind = settings.value(SETTINGS_POS_REQ_KIND, POS_REQ).value(); + switch (posReqKind) { + case POS_REQ: + ui->checkBoxPositionReportEnabled->setChecked(true); + break; + case POS_SYNC: + ui->checkBoxSynchronousSimulation->setChecked(true); + break; + case POS_NO: + ui->checkBoxNoDisplay->setChecked(true); + break; + } +/// <-- + QString enPosReq = settings.value(SETTINGS_ENABLE_POS_REQ, "true").value(); + // ui->checkBoxPositionReportEnabled->setChecked(enPosReq == "true"); + QString posReqType = settings.value(SETTINGS_TYPE_POS_REQ, PREQ_NOT_WHEN_MANUAL).value(); + double posRateFreqSec = settings.value(SETTINGS_POS_REQ_FREQ_SEC, DEFAULT_POS_REQ_FREQ_SEC).value(); + ui->doubleSpinBoxPosRequestFreqSec->setValue(posRateFreqSec); + if (posReqType == PREQ_NOT_WHEN_MANUAL) + { + ui->radioButton_ReqNotDuringManual->setChecked(true); + } + else if (posReqType == PREQ_ALWAYS) + { + ui->radioButton_ReqAlways->setChecked(true); + } + else + { + ui->radioButton_ReqAlwaysNoIdleCheck->setChecked(true); + } + + togglePosReporting(enPosReq == "true"); + +} + +void Options::accept() +{ + QSettings settings; +// tab Axis + settings.setValue(SETTINGS_INVERSE_X, ui->chkInvX->isChecked()); + settings.setValue(SETTINGS_INVERSE_Y, ui->chkInvY->isChecked()); + settings.setValue(SETTINGS_INVERSE_Z, ui->chkInvZ->isChecked()); + settings.setValue(SETTINGS_INVERSE_FOURTH, ui->chkInvFourth->isChecked()); + settings.setValue(SETTINGS_ENABLE_DEBUG_LOG, ui->checkBoxEnableDebugLog->isChecked()); + settings.setValue(SETTINGS_USE_AGGRESSIVE_PRELOAD, ui->chkAggressivePreload->isChecked()); + settings.setValue(SETTINGS_WAIT_FOR_JOG_TO_COMPLETE, ui->checkBoxWaitForJogToComplete->isChecked()); + settings.setValue(SETTINGS_USE_MM_FOR_MANUAL_CMDS, ui->checkBoxUseMmManualCmds->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_USE, ui->checkBoxFourAxis->isChecked()); + settings.setValue(SETTINGS_FOUR_AXIS_NAME, getFourthAxisName()); + settings.setValue(SETTINGS_FOUR_AXIS_ROTATE, getFourthAxisRotate()); + +// tab General + settings.setValue(SETTINGS_RESPONSE_WAIT_TIME, ui->spinResponseWaitSec->value()); + settings.setValue(SETTINGS_Z_JOG_RATE, ui->doubleSpinZJogRate->value()); + + settings.setValue(SETTINGS_Z_RATE_LIMIT, ui->chkLimitZRate->isChecked()); + settings.setValue(SETTINGS_Z_RATE_LIMIT_AMOUNT, ui->doubleSpinZRateLimit->value()); + settings.setValue(SETTINGS_XY_RATE_AMOUNT, ui->doubleSpinXYRate->value()); +/// T4 + settings.setValue(SETTINGS_MAX_STATUS_LINES, ui->spinMaxStatusLines->value()); + +// tab Filtering + settings.setValue(SETTINGS_FILTER_FILE_COMMANDS, ui->chkFilterFileCommands->isChecked()); + settings.setValue(SETTINGS_REDUCE_PREC_FOR_LONG_LINES, ui->checkBoxReducePrecForLongLines->isChecked()); + settings.setValue(SETTINGS_GRBL_LINE_BUFFER_LEN, ui->spinBoxGrblLineBufferSize->value()); + settings.setValue(SETTINGS_CHAR_SEND_DELAY_MS, ui->spinBoxCharSendDelay->value()); + +// tab Display + settings.setValue(SETTINGS_ENABLE_POS_REQ, ui->checkBoxPositionReportEnabled->isChecked()); + settings.setValue(SETTINGS_TYPE_POS_REQ, getPosReqType()); + settings.setValue(SETTINGS_POS_REQ_FREQ_SEC, ui->doubleSpinBoxPosRequestFreqSec->value()); +/// T4 + int posreq = getPosReqKind(); + settings.setValue(SETTINGS_POS_REQ_KIND, posreq); + connect(this, SIGNAL(setPosReqKind(int)), parentWidget(), SLOT(setPosReqKind(int) )); + // -> 'Mainwindow::setSettingsOptions()' + connect(this, SIGNAL(setSettingsOptions()), parentWidget(), SLOT(setSettingsOptions())); + + emit setSettingsOptions(); + + this->close(); +} + +/// T4 +void Options::setUseMm(bool mm) +{ +//diag("Options::setUseMm = %s", mm==true?"true":"false"); + externUseMm = mm; +// update gcode thread with latest values + //ui->checkBoxUseMmManualCmds->setEnabled(ui->checkBoxUseMmManualCmds->isChecked() == mm ); + ui->checkBoxUseMmManualCmds->setChecked(mm); +} +bool Options::getUseMm() +{ +//diag("Options::checkBoxUseMmManualCmds->isChecked() = %s", ui->checkBoxUseMmManualCmds->isChecked()==true?"true":"false"); + return ui->checkBoxUseMmManualCmds->isChecked(); +} +double Options::getZJogRate() +{ + return ui->doubleSpinZJogRate->value(); +} +double Options::getzRateLimit() +{ +//diag("Options::getzRateLimit() = %0.2f", ui->doubleSpinZRateLimit->value()); + return ui->doubleSpinZRateLimit->value(); +} +double Options::getXYRate() +{ + return ui->doubleSpinXYRate->value(); +} +/// <-- + +void Options::toggleUseMm(bool useMm) +{ +//diag("Options::toggleUseMm() ..."); + double zJogRate = ui->doubleSpinZJogRate->value(); + double zRateLimit = ui->doubleSpinZRateLimit->value(); + double xyRate = ui->doubleSpinXYRate->value(); +/// T4 + QString txt = "Z-Jog Rate "; + if (useMm) + { + txt += "(mm/min)"; + zJogRate *= MM_IN_AN_INCH ; // zJogRate = int(zJogRate*100 + 0.5)/100.0 ; + zRateLimit *= MM_IN_AN_INCH ; // zRateLimit = int(zRateLimit*100 + 0.5)/100.0 ; + xyRate *= MM_IN_AN_INCH ; // xyRate = int(xyRate *100 + 0.5)/100.0 ; + } + else + { txt += "(inches/min)"; + zJogRate /= MM_IN_AN_INCH ; + zRateLimit /= MM_IN_AN_INCH ; + xyRate /= MM_IN_AN_INCH ; + } + ui->labelZJogRate->setText(txt); + ui->doubleSpinZJogRate->setValue(zJogRate); + ui->doubleSpinZRateLimit->setValue(zRateLimit); + ui->doubleSpinXYRate->setValue(xyRate); +/// <-- + emit setSettingsOptionsUseMm(); +} + +void Options::toggleLimitZRate(bool limitZ) +{ + ui->doubleSpinZRateLimit->setEnabled(limitZ); + ui->doubleSpinXYRate->setEnabled(limitZ); +} + +void Options::toggleFourAxis(bool four) +{ + if (four) + { + ui->chkInvFourth->show(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, false); + ui->groupBoxFourthAxis->setEnabled(true); + } + else + { + ui->chkInvFourth->hide(); + ui->chkInvFourth->setAttribute(Qt::WA_DontShowOnScreen, true); + ui->groupBoxFourthAxis->setEnabled(false); + } + +} + +void Options::togglePosReporting(bool usePosReporting) +{ + if (usePosReporting) + { + ui->groupBox_ReqPos->setEnabled(true); + } + else + { + ui->groupBox_ReqPos->setEnabled(false); + } +} + +/// T4 +bool Options::getFourthAxisRotate() +{ + char name = getFourthAxisName(); + + return (name == FOURTH_AXIS_A || name == FOURTH_AXIS_B || name == FOURTH_AXIS_C ); + +} + +char Options::getFourthAxisName() +{ +// update gcode thread with latest values + char type = FOURTH_AXIS_A; + + if (ui->radioButtonFourthAxisA->isChecked()) + { + type = FOURTH_AXIS_A; + } + else + if (ui->radioButtonFourthAxisB->isChecked()) + { + type = FOURTH_AXIS_B; + } + else + if (ui->radioButtonFourthAxisC->isChecked()) + { + type = FOURTH_AXIS_C; + } + if (ui->radioButtonFourthAxisU->isChecked()) + { + type = FOURTH_AXIS_U; + } + else + if (ui->radioButtonFourthAxisV->isChecked()) + { + type = FOURTH_AXIS_V; + } + else + if (ui->radioButtonFourthAxisW->isChecked()) + { + type = FOURTH_AXIS_W; + } + + return type; +} + +/// T4 +int Options::getPosReqKind() +{ + int choice = POS_REQ ; + if (ui->checkBoxPositionReportEnabled->isChecked() ) + choice = POS_REQ ; +// update gcode thread with latest values + else + if (ui->checkBoxSynchronousSimulation->isChecked()) + choice = POS_SYNC; + else + if (ui->checkBoxNoDisplay->isChecked() ) + choice = POS_NO ; + + return choice; +} + +QString Options::getPosReqType() +{ + if (ui->radioButton_ReqAlways->isChecked()) + { + return PREQ_ALWAYS; + } + else if (ui->radioButton_ReqNotDuringManual->isChecked()) + { + return PREQ_NOT_WHEN_MANUAL; + } + return PREQ_ALWAYS_NO_IDLE_CHK; +} diff --git a/GCV-3.6.1-T4/src/options.h b/GCV-3.6.1-T4/src/options.h new file mode 100644 index 0000000..2ba8457 --- /dev/null +++ b/GCV-3.6.1-T4/src/options.h @@ -0,0 +1,109 @@ +/**************************************************************** + * options.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include +#include +#include +#include +#include + +#include "definitions.h" + +#define SETTINGS_INVERSE_FOURTH "inverse.c"// leave as 'c' for backwards compat +#define SETTINGS_INVERSE_X "inverse.x" +#define SETTINGS_INVERSE_Y "inverse.y" +#define SETTINGS_INVERSE_Z "inverse.z" +#define SETTINGS_RESPONSE_WAIT_TIME "responseWaitTime" +#define SETTINGS_Z_JOG_RATE "zJogRate" +#define SETTINGS_ENABLE_DEBUG_LOG "debugLog" +#define SETTINGS_USE_AGGRESSIVE_PRELOAD "aggressivePreload" +#define SETTINGS_WAIT_FOR_JOG_TO_COMPLETE "waitForJogToComplete" +#define SETTINGS_USE_MM_FOR_MANUAL_CMDS "useMMForManualCommands" +#define SETTINGS_ABSOLUTE_AFTER_AXIS_ADJ "absCoordForManualAfterAxisAdj" +#define SETTINGS_Z_RATE_LIMIT "zRateLimit" +#define SETTINGS_Z_RATE_LIMIT_AMOUNT "zRateLimitAmount" +#define SETTINGS_XY_RATE_AMOUNT "xyRateAmount" +#define SETTINGS_FOUR_AXIS_USE "fourAxis" +/// T4 +// #define SETTINGS_FOUR_AXIS_TYPE "fourAxisType" +#define SETTINGS_FOUR_AXIS_NAME "fourAxisName" +#define SETTINGS_FOUR_AXIS_ROTATE "fourAxisRotate" + +#define SETTINGS_FILE_OPEN_DIALOG_STATE "fileopendialogstate" +#define SETTINGS_NAME_FILTER "namefilter" +#define SETTINGS_DIRECTORY "directory" +#define SETTINGS_PORT "port" +#define SETTINGS_BAUD "baud" + +#define SETTINGS_PROMPTED_AGGR_PRELOAD "promptedAggrPreload" + +#define SETTINGS_FILTER_FILE_COMMANDS "filterFileCommands" +#define SETTINGS_REDUCE_PREC_FOR_LONG_LINES "reducePrecisionForLongLines" +#define SETTINGS_GRBL_LINE_BUFFER_LEN "grblLineBufferLen" +#define SETTINGS_CHAR_SEND_DELAY_MS "charSendDelayMs" +#define SETTINGS_JOG_STEP "jogStep" + +#define SETTINGS_ENABLE_POS_REQ "positionRequest" +#define SETTINGS_TYPE_POS_REQ "posRequestType" +#define SETTINGS_POS_REQ_FREQ_SEC "posReqFreqSec" +/// T4 +#define SETTINGS_POS_REQ_KIND "positionReqKind" +#define SETTINGS_MAX_STATUS_LINES "maxStatusLines" + +namespace Ui { +class Options; +} + +class Options : public QDialog +{ + Q_OBJECT + +public: + explicit Options(QWidget *parent = 0); + ~Options(); +/// T4 + void init(); + void setUseMm(bool); + bool getUseMm(); + double getZJogRate(); + double getzRateLimit(); + double getXYRate(); +/// <-- + void accept(); + +signals: + void setSettingsOptions(); + void setSettingsOptionsUseMm(); + void setPosReqKind(int); + +private slots: + void toggleUseMm(bool useMm); + void toggleLimitZRate(bool limitZ); + void toggleFourAxis(bool four); + void togglePosReporting(bool usePosReporting); + +private: + // char getFourthAxisType(); + char getFourthAxisName(); + QString getPosReqType(); +/// T4 + int getPosReqKind(); + bool getFourthAxisRotate(); +private: + Ui::Options *ui; + //variables + int settings; + bool externUseMm; + +}; + +#endif // OPTIONS_H diff --git a/GCV-3.6.1-T4/src/pointitem.cpp b/GCV-3.6.1-T4/src/pointitem.cpp new file mode 100644 index 0000000..126712e --- /dev/null +++ b/GCV-3.6.1-T4/src/pointitem.cpp @@ -0,0 +1,41 @@ +#include "pointitem.h" + +PointItem::PointItem(double x1, double y1) + : ItemToBase(0), x(x1), y(y1) +{ +} + +void PointItem::moveToFirst(QPainterPath& path) +{ + Q_UNUSED(path); +} + +void PointItem::addToPath(QPainterPath& path) +{ + Q_UNUSED(path); +} + +PosItem PointItem::computeExtents() +{ + return PosItem(); +} + +double PointItem::getXScr() +{ + return screenX(x); +} + +double PointItem::getYScr() +{ + return screenY(y); +} + +double PointItem::getXRaw() +{ + return x; +} + +double PointItem::getYRaw() +{ + return y; +} diff --git a/GCV-3.6.1-T4/src/pointitem.h b/GCV-3.6.1-T4/src/pointitem.h new file mode 100644 index 0000000..806589f --- /dev/null +++ b/GCV-3.6.1-T4/src/pointitem.h @@ -0,0 +1,23 @@ +#ifndef POINTITEM_H +#define POINTITEM_H +#include "itemtobase.h" + +class PointItem : public ItemToBase +{ +public: + PointItem(double x, double y); + + void moveToFirst(QPainterPath& path); + void addToPath(QPainterPath& path); + PosItem computeExtents(); + double getXScr(); + double getYScr(); + double getXRaw(); + double getYRaw(); + +private: + double x; + double y; +}; + +#endif // POINTITEM_H diff --git a/GCV-3.6.1-T4/src/positem.cpp b/GCV-3.6.1-T4/src/positem.cpp new file mode 100644 index 0000000..5ff49b1 --- /dev/null +++ b/GCV-3.6.1-T4/src/positem.cpp @@ -0,0 +1,88 @@ +#include "positem.h" + +/// 2 axes +void PosItem::setCoords(double x1, double y1, double i1, double j1) +{ + x = x1; + y = y1; + i = i1; + j = j1; +} + +void PosItem::setCoords(double x1, double y1, bool mm1) +{ + x = x1; + y = y1; + i = x1; + j = y1; + mm = mm1; +} + +void PosItem::expand(const PosItem& item) +{ + if (item.x < x) + x = item.x; + if (item.y < y) + y = item.y; + if (item.i > i) + i = item.i; + if (item.j > j) + j = item.j; +} + +/// 3 axes +void PosItem::setCoords(double x1, double y1, double z1, double i1, double j1, double k1) +{ + x = x1; + y = y1; + z = z1; + i = i1; + j = j1; + k = k1; +} +/// 3 axes +void PosItem::setCoords(QVector3D xyz, QVector3D ijk) +{ + x = xyz.x(); + y = xyz.y(); + z = xyz.z(); + i = ijk.x(); + j = ijk.y(); + k = ijk.z(); +} + +void PosItem::setCoords(double x1, double y1, double z1, bool mm1) +{ + x = x1; + y = y1; + z = z1; + i = x1; + j = y1; + k = z1; + mm = mm1; +} + +///----------------------------------------------------------------------------- +/// common 2 or 3 axes + +void PosItem::toMm() +{ + x *= MM_IN_AN_INCH; + y *= MM_IN_AN_INCH; + z *= MM_IN_AN_INCH; + i *= MM_IN_AN_INCH; + j *= MM_IN_AN_INCH; + k *= MM_IN_AN_INCH; + mm = true; +} + +void PosItem::toInches() +{ + x /= MM_IN_AN_INCH; + y /= MM_IN_AN_INCH; + z /= MM_IN_AN_INCH; + i /= MM_IN_AN_INCH; + j /= MM_IN_AN_INCH; + k /= MM_IN_AN_INCH; + mm = false; +} diff --git a/GCV-3.6.1-T4/src/positem.h b/GCV-3.6.1-T4/src/positem.h new file mode 100644 index 0000000..5a5020f --- /dev/null +++ b/GCV-3.6.1-T4/src/positem.h @@ -0,0 +1,139 @@ +#ifndef POSITEM_H +#define POSITEM_H +#include +#include + +#include "stdint.h" +#include "definitions.h" + +/// T4 uses z, k, p + +class PosItem +{ +public: +/// 1- visu XY + /// constructor 2 axes + PosItem(double x1, double y1) + : x(x1), y(y1), i(0), j(0), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1) + : x(x1), y(y1), i(i1), j(j1), + arc(false), cw(false), mm(true), index(0) {} + PosItem(double x1, double y1, double i1, double j1, bool arc1, bool cw1, bool mm1, int index1) + : x(x1), y(y1), i(i1), j(j1), + arc(arc1), cw(cw1), mm(mm1), index(index1) {} + + void setCoords(double x1, double y1, double i1, double j1); + void setCoords(double x1, double y1, bool mm); + void expand(const PosItem& item); + double width() { return qAbs(i - x); } + double height() { return qAbs(j - y); } + bool isNull() { return x == 0 && y == 0 && i == 0 && j == 0 && arc == false && cw == false && index == 0; } + +/// 2- visu XYZ + /// constructor 2, 3 axes + PosItem() + : x(0), y(0), z(0), + i(0), j(0), k(0) , + p(0), arc(false), cw(true), + mm(true), g(0), + plane(PLANE_XY_G17), helix(false), + index(0), feedrate(0) + {} + /// constructeur 3 axes + PosItem(double x1, double y1, double z1) + : x(x1), y(y1), z(z1), i(0), j(0), k(0), p(0), + arc(false), cw(false), mm(true), g(0), plane(0), index() {} + /// constructeur 3 axes + PosItem(double x1, double y1, double z1, double i1, double j1, double k1) + : x(x1), y(y1), z(z1), i(i1), j(j1), k(k1) , + arc(false), cw(false), mm(true), g(0), plane(0), index(0) {} +/// T4 + /// constructeur 3 axes with real + PosItem(double x1, double y1, double z1, + double i1, double j1, double k1, + int pr1, bool arc1, bool cw1, + bool mm1, int g1, + int pl, bool hel, int index1, double f + ) + : x(x1), y(y1), z(z1), + i(i1), j(j1), k(k1) , + p(pr1), arc(arc1), cw(cw1), + mm(mm1), g(g1), + plane(pl), helix(hel), index(index1) , feedrate(f) {} + /// + line gcode + PosItem(QString linecode, + double x1, double y1, double z1, + double i1, double j1, double k1, + int pr1, bool arc1, bool cw1, + bool mm1, int g1, + int pl, bool hel , int index1, double f + ) + : line(linecode), + x(x1), y(y1), z(z1), + i(i1), j(j1), k(k1) , + p(pr1), arc(arc1), cw(cw1), + mm(mm1), g(g1), + plane(pl), helix(hel), index(index1), feedrate(f) {} + + + /// constructeur 3 axes with Vector + PosItem(QVector3D xyz, + QVector3D ijk, + int pr1, bool arc1, bool cw1, + bool mm1, int g1, + int pl, bool hel, + int index1, double f1, double s1 + ) + : x(xyz.x()), y(xyz.y()), z(xyz.z()), + i(ijk.x()), j(ijk.y()), k(ijk.z()), + p(pr1), arc(arc1), cw(cw1), + mm(mm1), g(g1), + plane(pl), helix(hel), index(index1) , feedrate (f1), speedspindle(s1) {} + + /// constructeur 3 axes with Vector + line gcode + PosItem( QString linecode, + QVector3D xyz, + QVector3D ijk, + int pr1, bool arc1, bool cw1, + bool mm1, int g1, + int pl, bool hel, + int index1 , double f1, double s1 + ) + : line(linecode), + x(xyz.x()), y(xyz.y()), z(xyz.z()), + i(ijk.x()), j(ijk.y()), k(ijk.z()), + p(pr1), arc(arc1), cw(cw1), + mm(mm1), g(g1), + plane(pl), helix(hel), index(index1) , feedrate(f1), speedspindle(s1) {} + + void setCoords(double x1, double y1, double z1, double i1, double j1, double k1); + void setCoords(QVector3D xyz1, QVector3D ijk1); + void setCoords(double x1, double y1, double z1, bool mm); + +/// T4 + void toMm(); + void toInches(); + +public: + QString line; + double x, y, z; + double i, j, k; + + int p; // arc revolutions + bool arc ; + bool cw; + bool mm; + int g; // in [0..3] for Gx +/// T4 + int plane; + bool helix; + // ligne GCode + int index; + double feedrate; + double speedspindle ; +}; + +Q_DECLARE_METATYPE ( PosItem ) + +#endif // POSITEM_H diff --git a/GCV-3.6.1-T4/src/renderarea.cpp b/GCV-3.6.1-T4/src/renderarea.cpp new file mode 100644 index 0000000..304bcc5 --- /dev/null +++ b/GCV-3.6.1-T4/src/renderarea.cpp @@ -0,0 +1,75 @@ +#include "renderarea.h" + +RenderArea::RenderArea(QWidget *parent) + : QWidget(parent), + penProposedPath(QPen(Qt::blue)), penAxes(QPen(QColor(193,97,0))), + penCoveredPath(QPen(QColor(60,196,70), 2)), + penCurrPosActive(QPen(Qt::red, 6)), penCurrPosInactive(QPen(QColor(60,196,70), 6)), + penMeasure(QPen(QColor(151,111,26))), isLiveCurrPos(false) +{ + penCurrPosActive.setCapStyle(Qt::RoundCap); + penCurrPosInactive.setCapStyle(Qt::RoundCap); +} + +void RenderArea::setItems(QList itemsRcvd) +{ + items = itemsRcvd; + + listToRender.setCurrFileLine(0); + listToRender.convertList(items); + listToRender.updateLivePoint(); + update(); +} +/// T4 +void RenderArea::setLivePoint(double x, double y, bool mm, bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; + livePoint.setCoords(x, y, mm); + listToRender.setLivePoint(livePoint); + update(); + +} + +void RenderArea::setVisualLivenessCurrPos(bool isLiveCP) +{ + isLiveCurrPos = isLiveCP; +} + +void RenderArea::setVisCurrLine(int currLine) +{ + if (listToRender.setCurrFileLine(currLine)) + update(); +} + +void RenderArea::paintEvent(QPaintEvent * /* event */) +{ + if (!items.size()) + return; + + QSize size = this->size(); + + listToRender.rescale(size); + + QPainter painter(this); + + painter.setPen(penProposedPath); + listToRender.writePath(painter, false); + + painter.setPen(penAxes); + listToRender.drawAxes(painter); + + painter.setPen(penMeasure); + listToRender.drawMeasurements(painter); + + painter.setPen(penCoveredPath); + listToRender.writePath(painter, true); + + //if (!livePoint.isNull()) FIX isNull + { + if (isLiveCurrPos) + painter.setPen(penCurrPosActive); + else + painter.setPen(penCurrPosInactive); + listToRender.drawPoint(painter, livePoint); + } +} diff --git a/GCV-3.6.1-T4/src/renderarea.h b/GCV-3.6.1-T4/src/renderarea.h new file mode 100644 index 0000000..9d84d0b --- /dev/null +++ b/GCV-3.6.1-T4/src/renderarea.h @@ -0,0 +1,39 @@ +#ifndef RENDERAREA_H +#define RENDERAREA_H + +#include +#include +#include + +#include "positem.h" +#include "renderitemlist.h" +#include "arcitem.h" +#include "lineitem.h" + +class RenderArea : public QWidget +{ + Q_OBJECT +public: + explicit RenderArea(QWidget *parent = 0); + +signals: + +public slots: + void setItems(QList); +/// T4 + void setLivePoint(double x, double y, bool isMM, bool isLiveCP); + void setVisualLivenessCurrPos(bool isLiveCP); + void setVisCurrLine(int currLine); + +protected: + void paintEvent(QPaintEvent *event); + +private: + QList items; + RenderItemList listToRender; + QPen penProposedPath, penAxes, penCoveredPath, penCurrPosActive, penCurrPosInactive, penMeasure; + PosItem livePoint; + bool isLiveCurrPos; +}; + +#endif // RENDERAREA_H diff --git a/GCV-3.6.1-T4/src/renderitemlist.cpp b/GCV-3.6.1-T4/src/renderitemlist.cpp new file mode 100644 index 0000000..442670a --- /dev/null +++ b/GCV-3.6.1-T4/src/renderitemlist.cpp @@ -0,0 +1,240 @@ +#include "renderitemlist.h" +#include + +RenderItemList::RenderItemList() + : scale(1), offsetx(50), offsety(50), mm(true), currFileLine(0) +{ + font.setStyleHint(QFont::Courier); + font.setPointSize(10); +} + +RenderItemList::~RenderItemList() +{ + clearList(); +} + +void RenderItemList::clearList() +{ + while (!list.isEmpty()) + delete list.takeFirst(); +} + +void RenderItemList::convertList(const QList& items) +{ + clearList(); + + if (items.size() == 0) + return; + + double lastx = items.at(0).x, lasty = items.at(0).y; + mm = items.at(0).mm; + foreach (PosItem item, items) + { + if (item.arc) + { + double px = lastx + item.i; + double py = lasty + item.j; + double sx = lastx; + double sy = lasty; + double ex = item.x; + double ey = item.y; + + list.append(new ArcItem(sx, sy, ex, ey, px, py, item.cw, item.index ) ); + } + else + { + double sx = item.x; + double sy = item.y; + + list.append(new LineItem(sx, sy, item.index)); + } + + lastx = item.x; + lasty = item.y; + } + + extents.setCoords(0.0,0.0,0.0,0.0); + foreach (ItemToBase *item, list) + { + PosItem e = item->computeExtents(); + + // can't use QRectF because it reverses the y axis in anticipation of screendraws, which we don't want + //extents = extents.united(e); + + extents.expand(e); + } +} + +void RenderItemList::rescale(const QSize& size) +{ + PosItem liveExtents(extents); + liveExtents.expand(livePoint); + + double scalex = SCREEN_SCALE_FILE * (size.width() / (liveExtents.width())); + double scaley = SCREEN_SCALE_FILE * (size.height() / (liveExtents.height())); + + scale = qMin(scalex, scaley); + + offsetx = size.width() / 2 - ((liveExtents.x + liveExtents.i) / 2) * scale; + offsety = size.height() / 2 - ((liveExtents.y + liveExtents.j) / 2) * scale; + + windowSize = size; +} + +void RenderItemList::writePath(QPainter& painter, bool updatedFromFile) +{ + QPainterPath path; + ItemToBase *item = list.at(0); + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->moveToFirst(path); + foreach (item, list) + { + if (updatedFromFile) + { + if (item->getIndex() > currFileLine) + break; + } + + item->setParams(scale, windowSize.height(), offsetx, offsety); + item->addToPath(path); + } + + painter.drawPath(path); +} + +void RenderItemList::drawAxes(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + + path.moveTo(x, 0); + path.lineTo(x, windowSize.height() - 1); + path.moveTo(0, y); + path.lineTo(windowSize.width() - 1, y); + + painter.drawPath(path); +} + +void RenderItemList::drawMeasurements(QPainter& painter) +{ + QPainterPath path; + + ItemToBase *item = list.at(0); + double x = item->getXScr(); + double y = item->getYScr(); + double xr = item->getXRaw(); + double yr = item->getYRaw(); + + const int length = 6; + LineItem x1(extents.x, yr, true, length); + x1.setParams(scale, windowSize.height(), offsetx, offsety); + x1.drawTo(path); + + LineItem x2(extents.i, yr, true, length); + x2.setParams(scale, windowSize.height(), offsetx, offsety); + x2.drawTo(path); + + LineItem y1(xr, extents.y, false, length); + y1.setParams(scale, windowSize.height(), offsetx, offsety); + y1.drawTo(path); + + LineItem y2(xr, extents.j, false, length); + y2.setParams(scale, windowSize.height(), offsetx, offsety); + y2.drawTo(path); + + painter.drawPath(path); + + painter.setFont(font); + + int ht = painter.fontMetrics().height(); + int wd = painter.fontMetrics().averageCharWidth(); + + QString units = mm ? QObject::tr(" mm") : QObject::tr(" inches"); + + QString info(QString::number(extents.j).append(units).append(QObject::tr(" (Width-X: ").append(QString::number(extents.width())) + .append(QObject::tr(" Height-Y: ")).append(QString::number(extents.height())).append(")")) ) ; + int xMsgTop = x + wd; + QRect br = painter.fontMetrics().boundingRect(info); + br.setWidth(br.width() + wd); + if (br.width() > (windowSize.width() - x)) + xMsgTop = wd; + +#ifdef Q_OS_MACX + writeText(painter, info, xMsgTop, (3 * ht / 4) + 4, wd); +#else + writeText(painter, info, xMsgTop, (3 * ht / 4) + 1, wd); +#endif + +#ifdef Q_OS_MACX + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 2) - 1, wd); +#else + writeText(painter, QString::number(extents.y), x + wd, windowSize.height() - (ht / 4) - 1, wd); +#endif + + writeText(painter, QString::number(extents.x), wd, y - (ht / 4), wd); + + QString right = QString::number(extents.i); + br = painter.fontMetrics().boundingRect(right); + writeText(painter, right, windowSize.width() - (br.width() + wd), y - (ht / 4), wd); +} + +void RenderItemList::writeText(QPainter& painter, QString text, double x, double y, int avgCharWd) +{ + // We need to clear a rectangle into which our text will be written so it is easier to read + QRect br = painter.fontMetrics().boundingRect(text); + br.setWidth(br.width() + avgCharWd); + br.translate(x, y); + // TODO: get the background color from the window instead, otherwise + // any changes to it need to be changed here + painter.fillRect(br, QColor(244,237,187)); + painter.drawText(x, y, text); +} + +void RenderItemList::drawPoint(QPainter& painter, const PosItem& point) +{ + double divisor = 1; + if ((mm && !point.mm) || (!mm && point.mm)) + divisor = MM_IN_AN_INCH; + + PointItem p(point.x / divisor, point.y / divisor); + + p.setParams(scale, windowSize.height(), offsetx, offsety); + + painter.drawPoint(p.getXScr(), p.getYScr()); + +} + +bool RenderItemList::setCurrFileLine(const int currLine) +{ + currFileLine = currLine; + foreach (ItemToBase *item, list) + { + if (item->getIndex() == currLine) + return true; + else if (item->getIndex() > currLine) + return false; + } + return false; +} + +void RenderItemList::setLivePoint(const PosItem& livePoint1) +{ + livePoint = livePoint1; + + updateLivePoint(); +} + +void RenderItemList::updateLivePoint() +{ + if (mm && !livePoint.mm) + { + livePoint.toMm(); + } + else if (!mm && livePoint.mm) + { + livePoint.toInches(); + } +} diff --git a/GCV-3.6.1-T4/src/renderitemlist.h b/GCV-3.6.1-T4/src/renderitemlist.h new file mode 100644 index 0000000..4ca2121 --- /dev/null +++ b/GCV-3.6.1-T4/src/renderitemlist.h @@ -0,0 +1,42 @@ +#ifndef RENDERITEMLIST_H +#define RENDERITEMLIST_H +#include "arcitem.h" +#include "lineitem.h" +#include "pointitem.h" + +#define SCREEN_SCALE_FILE 0.85 + +class RenderItemList +{ +public: + RenderItemList(); + virtual ~RenderItemList(); + + void convertList(const QList& items); + void rescale(const QSize& size); + void writePath(QPainter& painter, bool updatedFromFile); + void drawAxes(QPainter& painter); + void drawMeasurements(QPainter& painter); + void drawPoint(QPainter& painter, const PosItem& point); + bool setCurrFileLine(const int currLine); + void setLivePoint(const PosItem& livePoint); + void updateLivePoint(); + +private: + void clearList(); + void writeText(QPainter& painter, QString text, double x, double y, int avgCharWd); + +private: + QList list; + double scale; + double offsetx; + double offsety; + PosItem extents; + QSize windowSize; + bool mm; + int currFileLine; + PosItem livePoint; + QFont font; +}; + +#endif // RENDERITEMLIST_H diff --git a/GCV-3.6.1-T4/src/rs232.cpp b/GCV-3.6.1-T4/src/rs232.cpp new file mode 100644 index 0000000..8ef54a1 --- /dev/null +++ b/GCV-3.6.1-T4/src/rs232.cpp @@ -0,0 +1,284 @@ +/**************************************************************** + * rs232.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#include "rs232.h" +#include + +RS232::RS232() + : port(NULL), detectedEOL(0), charSendDelayMs(DEFAULT_CHAR_SEND_DELAY_MS) +{ +} + +bool RS232::OpenComport(QString commPortStr, QString baudRate) +{ + if (port != NULL) + CloseComport(); + + bool ok; + BaudRateType baud = (BaudRateType)baudRate.toInt(&ok); + if (!ok) + { + baud = BAUD9600; + } + else + { + int possibleBaudRates[] = {BAUD110,BAUD300,BAUD600,BAUD1200,BAUD2400,BAUD4800,BAUD9600,BAUD19200,BAUD38400,BAUD57600,BAUD115200}; + int pbrCount = sizeof possibleBaudRates / sizeof possibleBaudRates[0]; + + bool found = false; + for (int i = 0; i < pbrCount; i++) + { + if (baud == possibleBaudRates[i]) + { + found = true; + break; + } + } + if (!found) + baud = BAUD9600; + } + + PortSettings settings = {baud, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10}; + + port = new QextSerialPort(commPortStr, settings, QextSerialPort::Polling); + + port->open(QIODevice::ReadWrite); + + return port->isOpen(); +} + + +int RS232::PollComport(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->read(buf, size); + return(n); +} + +// This is different than QIoDevice.readline() - this method only returns data if it has a full line in the +// input buffer by peeking at the buffer. It never removes items unless it can remove a full line. +int RS232::PollComportLine(char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + int n = port->bytesAvailable(); + if (!n) + return 0; + + n = port->peek(buf, size); + if (n <= 0) + return n; + + //printf("PEEK: %d out of %d\n", n, size); + if (detectedEOL == 0) + { + // algorithm assumes we received both eol chars if there are two in this peek + int pos = 0; + char firstEOL = 0; + char secondEOL = 0; + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == '\n' || b == '\r') + { + if (firstEOL == 0) + { + firstEOL = b; + pos = i; + } + else if ((pos + 1) == i) + { + secondEOL = b; + break; + } + else + break; + } + } + + if (firstEOL != 0) + { + if (secondEOL != 0) + { + detectedEOL = secondEOL; + detectedLineFeed = firstEOL; + detectedLineFeed += secondEOL; + } + else + { + detectedEOL = firstEOL; + detectedLineFeed = firstEOL; + } + } + } + + int toRead = 0; + if (detectedEOL) + { + for (int i = 0; i < n; i++) + { + char b = buf[i]; + if (b == detectedEOL) + { + toRead = i + 1; + break; + } + } + } + + // let's hope the serial subsystem's read buffer is big enough to find a linefeed + if (!toRead) + { + return 0; + } + + n = port->read(buf, toRead); + + return n; +} + +int RS232::SendBuf(const char *buf, int size) +{ + if (port == NULL || !port->isOpen()) + return 0; + + if (size <= 0) + { + err( qPrintable(QObject::tr("Unexpected: Told to send %d bytes\n")), size) ; + return 1; + } + + char b[300] = {0}; + memcpy(b, buf, size); +#ifdef DIAG + printf("Sending to port %s [%s]:", qPrintable(port->portName()), b); + for (int x= 0; x < size; x++) + { + printf("%02X ", buf[x]); + } + printf("\n"); + fflush(stdout); +#endif + + port->waitForBytesWritten(-1);// this usually doesn't do anything, but let's put it here in case + +#if 1 + // On very fast PCs running Windows we have to slow down the sending of bytes to grbl + // because grbl loses bytes due to its interrupt service routine (ISR) taking too many clock + // cycles away from serial handling. + int result = 0; + for (int i = 0; i < size; i++) + { + result = port->write(&buf[i], 1); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + break; + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + break; + } + + if (charSendDelayMs > 0) + { + SLEEP(charSendDelayMs); + } + } + +#else + // DO NOT RUN THIS CODE + int result = port->write(buf, size); + if (result == 0) + { + err("Unable to write bytes to port probably due to outgoing queue full. Write data lost!"); + /* the following code doesn't seem to help. Generate an error instead + int limit = 0; + while (!result && limit < 100) + { + SLEEP(100); + result = port->write(buf, size); + limit++; + } + + if (!result) + { + err("Unable to write %d bytes to port!", size); + } + else if (result != size) + err("Unexpected: Retry send wrote %d bytes out of expected %d\n", result, size); + */ + } + else if (result == -1) + { + err("Error writing to port. Write data lost!"); + result = 0; + } +#endif + return result; +} + + +void RS232::CloseComport() +{ + if (port != NULL) + { + port->close(); + delete port; + port = NULL; + } +} + +void RS232::Reset() //still to test +{ + if (port != NULL) + port->reset(); +} + +void RS232::flush() +{ + int n=1; + char buf[255]; + + while (n > 0) + n = PollComport(buf,255); +} + +bool RS232::isPortOpen() +{ + if (port == NULL) + return false; + + return port->isOpen(); +} + +QString RS232::getDetectedLineFeed() +{ + return detectedLineFeed; +} + +int RS232::bytesAvailable() +{ + int n = port->bytesAvailable(); + return n; +} + +void RS232::setCharSendDelayMs(int csd) +{ + charSendDelayMs = csd; +} diff --git a/GCV-3.6.1-T4/src/rs232.h b/GCV-3.6.1-T4/src/rs232.h new file mode 100644 index 0000000..a70ec55 --- /dev/null +++ b/GCV-3.6.1-T4/src/rs232.h @@ -0,0 +1,76 @@ +/**************************************************************** + * rs232.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef RS232_H +#define RS232_H + +#include +#include + +#include +#include +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#include +#include "../termiosext.h" +#include +#include +#include +#include +#include +#include +#else +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include +#else +// TODO - R - if I leave out Windows.h then Sleep is not found??? +#include +#include +#endif +#endif + +#include +#include + +#include "definitions.h" + + +#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_ANDROID) +#define SLEEP(x) usleep(1000 * x); +#else +#define SLEEP(x) Sleep(x); +#endif + + +class RS232 +{ +public: + RS232(); + //methods + bool OpenComport(QString commPortStr, QString baudRate); + int PollComport(char *buf, int size); + int PollComportLine(char *buf, int size); + int SendBuf(const char *buf, int size); + void CloseComport(); + void Reset(); + void flush(); + bool isPortOpen(); + QString getDetectedLineFeed(); + int bytesAvailable(); + void setCharSendDelayMs(int charSendDelayMs); + +private: + QextSerialPort *port; + char detectedEOL; + QString detectedLineFeed; + int charSendDelayMs; + +}; + + +#endif // RS232_H diff --git a/GCV-3.6.1-T4/src/termiosext.h b/GCV-3.6.1-T4/src/termiosext.h new file mode 100644 index 0000000..93ac44f --- /dev/null +++ b/GCV-3.6.1-T4/src/termiosext.h @@ -0,0 +1,11 @@ +#ifndef TERMIOSEXT_H +#define TERMIOSEXT_H + +#ifdef Q_OS_ANDROID +static __inline__ int tcdrain(int fd) +{ + return ioctl(fd, TCSBRK, (void *)(intptr_t)1); +} +#endif + +#endif // TERMIOSEXT_H diff --git a/GCV-3.6.1-T4/src/timer.cpp b/GCV-3.6.1-T4/src/timer.cpp new file mode 100644 index 0000000..2556b7d --- /dev/null +++ b/GCV-3.6.1-T4/src/timer.cpp @@ -0,0 +1,35 @@ +/**************************************************************** + * timer.cpp + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#include "timer.h" +Timer::Timer(QObject *parent) : + QObject(parent), timing(false) +{ + startTimer(500); +} + +void Timer::resetTimer(bool timeIt) +{ + timing = timeIt; + if (timeIt) + timer.start(); +} + +void Timer::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (timing) + { + int secs = timer.elapsed() / 1000; + int mins = (secs / 60) % 60; + int hours = (secs / 3600); + secs = secs % 60; + emit setRuntime(QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(mins, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'))); + } +} diff --git a/GCV-3.6.1-T4/src/timer.h b/GCV-3.6.1-T4/src/timer.h new file mode 100644 index 0000000..eed99ca --- /dev/null +++ b/GCV-3.6.1-T4/src/timer.h @@ -0,0 +1,36 @@ +/**************************************************************** + * timer.h + * GrblHoming - zapmaker fork on github + * + * 15 Nov 2012 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include + +class Timer : public QObject +{ + Q_OBJECT + +public: + explicit Timer(QObject *parent = 0); + +signals: + void setRuntime(QString timestr); + +public slots: + void resetTimer(bool timeIt); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QTime timer; + bool timing; +}; + +#endif // TIMER_H diff --git a/GCV-3.6.1-T4/src/translate.bat b/GCV-3.6.1-T4/src/translate.bat new file mode 100644 index 0000000..d9b6ce6 --- /dev/null +++ b/GCV-3.6.1-T4/src/translate.bat @@ -0,0 +1,21 @@ +rem translate.bat + +echo off + +set PATH=%PATH%;u:\DONNEES\SVN_COMPILE\qt\4.7.3\bin + +rem create "src\trlocale\*.ts" + +lupdate.exe GCV.pro + +rem create *.qm + +linguist trlocale\GrblController_fr.ts + +lrelease trlocale\GrblController_fr.ts -qm trlocale\GrblController_fr.qm + +xcopy /Y trlocale\GrblController_fr.qm bin\trlocale\ + +xcopy /Y trlocale\GrblController_fr.qm ..\cons\trlocale\ + +cd .. diff --git a/GCV-3.6.1-T4/src/trlocale/GrblController_fr.qm b/GCV-3.6.1-T4/src/trlocale/GrblController_fr.qm new file mode 100644 index 0000000..052a05f Binary files /dev/null and b/GCV-3.6.1-T4/src/trlocale/GrblController_fr.qm differ diff --git a/GCV-3.6.1-T4/src/trlocale/GrblController_fr.ts b/GCV-3.6.1-T4/src/trlocale/GrblController_fr.ts new file mode 100644 index 0000000..14910f1 --- /dev/null +++ b/GCV-3.6.1-T4/src/trlocale/GrblController_fr.ts @@ -0,0 +1,2094 @@ + + + + + About + + + About... + A propos ... + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + Le programme est fourni en l'état SANS GARANTIE D'AUCUNE SORTE, MEME LES GARANTIES DE CONCEPTION, MARCHANDE ET D'ADAPTATION À UN USAGE PARTICULIER. + + + + Grbl Controller Visualizer + Grbl Controleur Visualisateur + + + + LETARTARE + LETARTARE + + + Grbl Controller + Controleur Grbl + + + Grbl Controller 4 + Controleur Grbl 4 + + + + GCode + + + Can't open COM port + Impossible d'ouvrir le port série + + + + -Is hardware connected to USB? + - le périphérique est-il bien connecté sur un port USB ? + + + + -Is correct port chosen? + - le port choisi est-il correct ? + + + + -Does current user have sufficient permissions? + - l'utilisateur a-t-il les droits d'utilisation suffisants ? + + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + Emis : 0x%02X (CTRL-X) pour verifier la presence de Grbl + + + + + Sending to port failed + L'émission vers le port a échouée + + + Got Grbl Version (Parsed:) %d.%d%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + Port not available yet + Le port n'est plus disponible + + + + Buffer size too small + Le tampon est trop petit + + + + SENDING[%d]: 0x%02X (CTRL-X) + + EMIS[%d]: 0x%02X (CTRL-X)\n + + + + SENDING[%d]: %s + + EMIS[%d]: %s\n + + + + WAITFOROK FAILED + + Echec lors de l'attente de Ok + + + + Wait for ok failed + L'attente d'un bon déroulement a échouée + + + + + Error reading data from COM port + + Erreur de lecture des données sur le port série + + + + Unexpected: list is empty (o)! + Liste attendue vide (o) + + + GOT[%d]:%s for %s + + Obtenu [%d]:%s pour %s\n + + + + Error? + Erreur non répertoriée + + + + Unexpected: list is empty (e)! + Liste attendue vide (e) + + + + + GOT:%s + + Obtenu : %s\n + + + + Wait interrupted by user + Attente d'interuption par l'utilisateur + + + + Expecting Grbl version string. Unable to parse response. + Attente de la version Grbl, impossible d'analyser la réponse + + + + No data from COM port after connect. Expecting Grbl version string. + Aucune données depuis le port série après la connexion, en attente de la version Grbl + + + + Wait interrupted by user (startup) + Attente d'interuption par l'utilisateur (démarrage) + + + XYUV-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XYUV : [%1]=>[%2] + + + ([a-zA-Z]+),MPos: + ([a-zA-Z]+),PosM : + + + ([a-zA-Z]+), MPos: + ([a-zA-Z]+) ,PosM : + + + MPos: + PosM : + + + WPos: + PosT : + + + Decoded: State:%s MPos: %f,%f,%f WPos: %f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f WPos: %f,%f,%f + + + + Decoded: State:%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Décodage : Etat :%s MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + Error decoding position data! + + Erreur de décodage des données de position\n + + + + Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d) + + Vous avez la version Grbl (analyse) %d.%d%c ($$=%d)\n + + + + + GOT[%d]: '%s' for '%s' (aggressive) + + Obtenu :[%d]: '%s' pour '%s' (offensif) + + + + GOT: '%s' (aggressive) + + Obtenu : '%s' (offensif) + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + L'axe supplémentaire existe matériellement. Veuillez corriger les options en cochant 4 ème axe. + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + L'axe supplémentaire n'existe pas matériellement. Veuillez corriger les options en décochant 4 ème axe. + + + + Decoded: State:%s + Decodage : Etat :%s + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + Decodage : MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + GOT-TE:%s + + Obtenu evenement temporel :%s\n + + + + Sending file '%1' + Emission du fichier '%1' + + + + Pause program Grbl ... + Pause du programme 'Grbl' ... + + + Pause for sending 'Gcode' lines to 'Grbl' ... + Pause dans l'envoi des lignes de' Gcode' vers 'Grbl' + + + + Resume program Grbl ... + Reprise du programme 'Grbl' + + + + Resume sending 'Gcode' lines to 'Grbl' + Reprise de l'envoi des lignes de' Gcode' vers 'Grbl' + + + + Gave up waiting for OK + + Fin d'attente Ok\n + + + + Code sent successfully with %1 error(s): + Code émis correctement avec %1 erreur(s) + + + + Code sent successfully with no errors. + Code émis correctement sans erreur + + + + Filtered %1 commands: + Commande filtrée %1 + + + + Process interrupted. + Processus interrompu + + + + Pause for sending 'Gcode' lines to 'Grbl' + Pause dans l'envoi des lignes de' Gcode' vers 'Grbl' + + + + Removed unsupported command '%1' part of '%2' + Suppression de la commande '%1' portion de '%2 ( non supportée) + + + + Removed unsupported G command '%1' + Suppression de la commande G '%1' non supportée + + + + Removed unsupported M command '%1' + Suppression de la commande M '%1' non supportée + + + + Removed unsupported command '%1' + Suppression de la commande '%1' non supportée + + + + Unable to remove enough decimal places for command (will be truncated): %s + Impossible de supprimer assez de decimales pour la commande (sera tronquee) %s + + + + Error, insufficent reduction '%1' + Erreur : réduction insuffisante '%1' + + + + Precision reduced '%1' + Précision réduite '%1' + + + + Z-Rate Limit: [%1]=>[%2] + Limite de vitesse Z [%1]=>[%2] + + + + Z-Rate Limit: [%1]=>[%2,%3] + Limite de vitesse Z : [%1]=>[%2,%3] + + + + XY-Rate Limit FIX: [%1]=>[%2] + Correction de la limite de vitesse XY : [%1]=>[%2] + + + + GCV use 'inches' but Grbl parser set for 'mm' + GCV utilise les 'pouces' alors que Grbl indique des 'mm'. + + + + + Correction Grbl ended. + Fin de la modification de 'Grbl' + + + + GCV use 'mm' but Grbl parser set for 'inches' + GCV utilise les 'mm' alors que Grbl indique des 'pouces'. + + + + + Bad command: %1 + Commande erronee : %1 + + + Options specify use mm but Grbl parser set for inches. Fixing. + Vous utiliser des 'mm' alors que l'analyse indique des 'pouces'. Corriger dans la configuration + + + Options specify use inches but Grbl parser set for mm. Fixing. + Vous utiliser les 'pouces' alors que l'analyse indique des 'mm'. Corriger dans la configuration + + + Options specify use mm but Grbl reporting set for inches. Fixing. + Vous utiliser les mm alors que Grbl donne des pouces. Corriger dans la configuration + + + Options specify use inches but Grbl reporting set for mm. Fixing. + Vous utiliser les 'pouce's alors que Grbl donne des 'mm'. Corriger dans la configuration + + + (mm) + (mm) + + + (in) + (pouce) + + + + GrblDialog + + + Grbl Settings + Configuration GRBL + + + + Apply + Appliquer + + + + Close + Fermer + + + + Rank + Rang + + + + Value + Valeur + + + + Description + Description + + + Item + Elément + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + Activation de 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Use of non activated appender '%1' + Utilisation de 'Appender' '%1' non activé + + + + Use of closed appender '%1' + Utilisation de 'Appender' '%1' fermé + + + + Use of appender '%1' that requires layout and has no layout set + Utiliser 'Appender' '%1' lequel nécessite une mise en page non réalisée ! + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + Utiliation de 'Appender' '%1' sans un modèle valide initialisé + + + + The pattern '%1' does not specify a frequency for appender '%2' + Le modème '%1' ne spécifie aucune fréquence pour 4Appender' '%2' + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + La conversion de type '%1' de la propriété '%2' de l'objet de classe '%3' est impossible. + + + + Unable to set property value on object + Impossible d'inialiser la valeur de la propriété de l'objet. + + + + Invalid null object pointer + Pointeur d'objet 'null' invalide + + + + Invalid empty property name + Nom de propriété invalide (vide) + + + + Property '%1' does not exist in class '%2' + La propriété '%1' n'existe pas dans la classe '%2' + + + + Property '%1' is not writable in class '%2' + La propriété '%1' ne peut être modifiée dans la classe '%2' + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + L'activation de 'Appender' '%1' nécessite un fichier associé + + + + Use of appender '%1' without open file + Utilisation de 'Appender' '%1' sans fichier ouvert + + + + Unable to write to file '%1' for appender '%2' + Impossible d'écrire dans le fichier '%1' pour 'Appender' '%2' + + + + Unable to open file '%1' for appender '%2' + Impossible d'ouvrir le fichier '%1' pour 'Appender' '%2' + + + + Unable to remove file '%1' for appender '%2' + Impossible de supprimer le fichier '%1' pour 'Appender' '%2' + + + + Unable to rename file '%1' to '%2' for appender '%3' + Impossible de renommer le fichier '%1' en '%2' pour 'Appender' '%3' + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + Parenthèse fermante manquante pour la parenthèse ouvrante '%1'. Valeur de substitution '%2' invalide + + + + Invalid option string '%1' for a boolean + Option chaîne '%1' invalide pour un booléen + + + + Invalid option string '%1' for a file size + Option chaîne '%1' invalide pour la taille d'un fichier + + + + Invalid option string '%1' for an integer + Option chaîne '%1' invalide pour un entier + + + + Invalid option string '%1' for a level + Option chaîne '%1' invalide pour un niveau + + + + Invalid option string '%1' for a target + Option chaîne '%1' invalide pour une cible + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + On trouve un caractère'%1', alors qu'un chiffre est attendu. + + + + Option '%1' cannot be converted into an integer + L'option '%1' ne peut-être convertie vers un entier + + + + Option %1 isn't a positive integer + L'option '%1' n'est pas un entier positif + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + Impossible d'ouvrir le fichier de propriétés '%1' + + + + Unable to read property file '%1' + Impossible de lire le fichier de propriétés '%1' + + + + Missing appender definition for appender named '%1' + La définition de 'appender' est manquente pour 'Appender' nommé '%1' + + + + Unable to create appender of class '%1' named '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Unable to create layout of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + Unable to create appender of class '%1' namd '%2' + La création de la classe 'Appender''%1' nommée '%2' est impossible + + + + Missing layout definition for appender '%1' + La définition de la structure est manquante pour 'Appender' '%1' + + + Unable to create layoput of class '%1' requested by appender '%2' + Impossible de créer la structure de classe '%1' attendu par '%2' + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + Activation de 'Appender' '%1' lequel nécessite un éditeur non configuré ! + + + + Use of appender '%1' without a writer set + Utiliser 'Appender' '%1' sans éditeur configuré + + + + MainWindow + + Grbl Controller + Contrôleur Grbl + + + + attempts to connect to the card containing 'Grbl' or terminates the connection + Essai de connexion à la carte contenant 'Grbl' ou arréter la connexion + + + + Port selection in those detected by the system + Sélection du port détecté par le système + + + + connection speed to card (bauds) + Vitesse de connexion à la carte (bauds) + + + + stops sending the contents of the file 'Gcode' + Arréter l'émission du contenu du fichier 'Gcode' + + + load a file for animation or send to Grbl + Chager un fichier 'Gcode' pour animation ou émission vers 'Grbl' + + + + sending line by line the contents of the file 'Gcode' + Emet ligne par ligne le cotenu du fichier (Gcode' + + + + shows the full name of the loaded file + Montre le nom complet du fichier chargé + + + + commands are sent to 'Grbl' simply control without executing + Les commandes sontsimplement transmise à 'Grbl'pour vérification sans exécution + + + + + Check + Vérifier + + + + time to send a file to 'Grbl' + Durée pour envoyer un fichier vers 'Grbl' + + + + 00:00:00 + 00:00:00 + + + + indicates the last release state Grbl + Indique le dernier état de Grbl + + + + no state + aucun + + + + Lines: + Lignes + + + + Console + Console + + + Gcode + Gcode + + + Simulate + Simulation + + + + + + Pause + Pause + + + + Line : + Ligne + + + Speed rate + Avance axes + + + + Speed rate gcode (mm or inches per minute) + Vitesse de travail gcode (mm ou pouces par minute) + + + + Spindle control: running -> yellow + Commande de broche : fonctionne -> jaune + + + + Pass in absolute coordinates after moving it occurs in relative displacement + Passe en coordonnées absolues après les commandes manuelles qui sont en déplacement relatif + + + Starter blocks + Blocs départ + + + + G90 after adjust + G90 après l'ajustement + + + + X + X + + + + Unit X axis + Unité de l'axe X + + + + Y + Y + + + + Unit Y axis + Unité de l'axe Y + + + + Z + Z + + + + Send File + Envoi d'un fichier + + + + Begin + Démarrer + + + + Stop + Arrêter + + + + Choose file + Choisir un fichier + + + + Runtime: + Exécution + + + Manual GCode + Commande directe en GCode + + + + Command + Commande + + + + + Open + Ouvrir + + + C + C + + + GRBL +settings + Configuratiion +GRBL + + + + Port name + Nom du port + + + + Visual + Visuel + + + animation of the scene + Animation de la scène 3D + + + + + Animate + Animation + + + + Starting and stopping the animation + Démarre et arrête l'animation 3D + + + + + interpolation tolerance for viewer 3D + Tolérance d'interpolation du visualisateur 3D + + + + + + + + + mm + mm + + + + interpolation number of segments for 3D + Nombre de segment d'interpolation pour la 3D + + + + Up one line in the gcode + Remonte d'une ligne dans le Gcode + + + + Current line gcode + Ligne courante du Gcode + + + + Down one line in the gcode + Descend d'une ligne dans le Gcode + + + + Animation period mS + Période de l'animation en mS + + + + Period mS + Période mS + + + + Value of the period + Valeur de la période + + + + Monitoring the progress of the animation gcode + Montre l'avancement de l'animation du Gcode + + + + animation of the scene 3D + Animation de la scène en 3D + + + + Unit Z axis + Unité de l'axe Z + + + + Unit of the fourth axis + Unité du quatrième axe + + + + deg + deg + + + + T + T + + + + + mm/mn + mm/mn + + + Speed gcode mm per minute + Vitesse de travail du Gcode 'mm' par minute + + + Segments + Segments + + + Speed gcode (mm or inches per minute) + Vitesse d'avance du gcode (mm ou pouces par minutes) + + + Step Size + Valeur du pas + + + T Jog + Commande T + + + Reset Control + Commande RAZ + + + + Soft Reset Grbl + RAZ logiciel de Grbl + + + + Unlock Grbl + Débloquer Grbl + + + + Machine Coordinates + Coordonnées machine + + + + Work Coordinates + Coordonnées de travail + + + + Last State: + Dernier état + + + interpolation number of segments + Nombre de segments d'interpolation + + + + Tolerance + Tolérance + + + interpolation tolerance + Tolérance d'interpolation + + + + tool selection + Choix de l'outil + + + + With or without bounding box + Visualisation ou non de l'enveloppe + + + + Bbox + Eboite + + + + with or without rapid movements + Visualise ou non les mouvements rapides + + + Zero Position + = Position zéro + + + Go Home + Aller position repos + + + Axis Control + Commandes d'axes + + + + Step size, accept cursors keyboard commands + Valeur du pas, accepte les commandes des curseurs clavier + + + + Small movements of the Z axis + Petits déplcements de l'axe Z + + + + Step value for the relative movements (G91) + Valeur du pas pour les déplacements relatifs + + + + Z Jog + pilote Z + + + Step Size + Valeur du pas + + + Absolute coordinates after adjust + Coordonnées absolues après ajustement + + + + + Spindle On + Départ broche + + + + + + + 0 + + + + + C Jog + pilote C + + + + Visualizer + Visualisateur + + + + Baud Rate + Vitesse du port + + + + %v + + + + + File progress + Avancement + + + + Queued Commands + Ordres en attente + + + Lines + Lignes + + + Advanced + Avancé + + + + GRBL Settings + Configuratiion +GRBL + + + + Grbl commands + Commandes Grbl + + + + + Help + Aide + + + + Build info + Information + + + + Parameters + Paramètres + + + + Grbl Controller Visualizer + Grbl Controleur Visualisateur + + + + load a file for animation + or send to Grbl + Charge un fichier pour animation ou pour envoyer à 'Grbl' + + + Not yet implemented !! + pas encore implémenté + + + + Shows the commands available in Grbl + Liste les commandes disponibles de 'Grbl' + + + + Parser state + Etat analyseur + + + + Startup blocks + Blocs départ + + + + Homing Cycle + + + + Cycle start + Départ + + + Feed hold + Maintien + + + Status + Etat + + + + Item segments + Segments élement + + + + Removes the selected text lines + Supprime les lignes de texte sélectionnées + + + + Clear selection + Enlève le choix + + + + + Prints lines of text selected +otherwise all text + Imprime les lignes de texte sélectionnées +sinon tout le texte + + + + Print selection + Imprimer le choix + + + + Print visual + Imprimer + + + + Feed rate + Avance + + + + Speed spindle + Broche + + + + Last spindle speed read in the Gcode + La dernière vitesse de broche lue dans le Gcode + + + + rpm + tours/mn + + + + + + + Moves the axis at zero + Déplace l'axe en position zéro + + + + + + Move the axis to negative values + Déplace l'axe vers les valeurs négatives + + + + + + Move the axis to the positive values + Déplace l'axe vers les valeurs positives + + + + Axis moves clockwise +Move the axis to negative values + Déplace l'axe en sens horaire +Déplace l'axe vers les valeurs négatives + + + + Moves the axis in the counterclockwise +Move the axis to the positive values + Déplace l'axe en sens anti-horaire +Déplace l'axe vers les valeurs positives + + + + Go Home :first moves the Z axis + then all axes synchronously at zero + Déplace d'abord l'axe Z +puis en synchronisme déplace tous les axes vers zéro + + + + The current position will be the new zero position :G92 x0 y0 z0 + La position actuelle devient la nouvelle position zéro :G92 x0 y0 z0 + + + + Viewer3D + Visu 3D + + + + Perspective view + Vue en perspective + + + + Front view + Vue de face + + + + Back view + Vue arrière + + + + Left view + Vue de gauche + + + + Right view + Vue de droite + + + + Bottom view + Vue de dessous + + + + Top view + Vue de dessus + + + + Vector up along Y axis + Veceur d'alignement vertical selon l'axe Y + + + + Queue clear + Vidage de la file + + + + The current position will be the new zero position :G92 x0 y0 z0 + La position actuelle devient la nouvelle position zéro :G92 x0 y0 z0 + + + + = Zero Position + = Position zéro + + + With or not tool + Avec ou sans outil + + + + Tool + Outil + + + With or not boubing box + Avec ous sans la boite enveloppante + + + + G0 + G0 + + + + + Help 3D + Aide 3D + + + + Refresh Pos + Actualiser position + + + + Firmware : + Micrologiciel : + + + + Suspend the issuance of the file 'Gcode to the end of the current line + Suspend l'émission du fichier 'Gcode' à la fin de la ligne courante + + + + Grbl version + Version de 'Grbl' + + + + + none + aucun + + + The current position will be the new zero position + La position actuelle devient la nouvelle position zéro + + + First moves the Z axis + then all axes synchronously at zero + Déplce d'abord l'axe Z +puis en synchronisme déplce tous les axes vers zéro + + + Asks 'Grbl' provide current positions + Demande à 'Grbl' de fournir la position actuelle + + + + &Help + &Aide + + + + &Tools + &Outils + + + + &File + &Fichiers + + + + &About + &A propos + + + + &Options + &Options + + + + E&xit + &Quitter + + + + Close / Reset + Fermer / Raz + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + Vous semblez avoir la dernière version du contrôleur Grbl. Soyez conscient que depuis la version 3.4 le comportement par défaut de l'envoi de commandes à Grbl a été modifié pour les envoyer aussi vite que possible (mode de précharge agressif). + +Vos paramètres ont été modifiés pour permettre ce mode. Pourquoi? Parce qu'il permet une utilisation la plus optimale de Grbl et réduit considérablement le temps de terminer un travail typique. Qu'est-ce que cela signifie pour vous ? Maintenant les commandes d'arc vont être plus continues et plus rapides qu'auparavant, ce qui peut amener votre broche à travailler un peu plus vite, s'il vous plaît donc faire quelques tests en premier. Sinon, passez à la boîte de dialogue Options et désactiver manuellement la précharge agressive + + + Wish to "zero position" before beginning? + Voulez-vous allez en postion zéro avant de démarrer ? + + + + User clicked Port Open/Close + L'utilisateur a clique Ouverture/Fermeture du port + + + + Resetting port to restart controller + L'initialisation du port initialise le contrôleur + + + + Do you want to zero the displayed position before proceeding? + Voulez-vous afficher la postion zéro avant de démarrer ? + + + + %s has started + Lancement de %s + + + + No tool + Sans outil + + + + Mini 1 mm + Mini 1mm + + + + Hemi 3 mm + Hémi 3mm + + + + Right 3 mm + Droit 3mm + + + + Sharp 3 mm + Pointu 3mm + + + + Short 3 mm + Court 3 mm + + + + %s has stopped + Fin de %s + + + + Resume + Reprise + + + + Open File + Charger un fichier + + + + NC (*.nc);;All Files (*.*) + NC (*.nc);;Tous fichiers (*.*) + + + + A Jog + pilote A + + + + B Jog + pilote B + + + + U Jog + pilote U + + + + V Jog + pilote V + + + + W Jog + pilote W + + + + Spindle Off + Arrêt broche + + + Spindle On. + Marche de la broche + + + Spindle Off. + Arrêt de la broche + + + + Usr chg: pos=%d new=%d + + Changement de position : %d -> =%d + + + + Usr chg: pos=%.1f new=%.1f + + Changement de position : %.1f -> =%.1f + + + + Usr chg no slider: %d + + Utilisation du coulisseau : %d + + + + Usr chg no slider: %.1f + + Utilisation du coulisseau : %.1f + + + + Pressed and stopped + + Actionne et stoppe + + + + Pressed not stopped + + Actionne sans stop + + + + Released + + Relache + + + + During the mode 'Check 'does not use the command '$C' please + Pendant la durée du mode 'Vérification' ne pas utiliser la commande '$C' ! + + + + No check + Fin vérifier + + + + With 'Grbl Settings' you must validate the homing cycle + Avec 'Grbl Settings' vous devez valider le cycle de mise en référence + + + + Unexpected type %c + Type attendu %c + + + + No animate + Fin animation + + + + in + pou + + + + mn + mm + + + + deg. + deg + + + + + Run + Marche + + + + Options + + + Options + Options + + + + Axis + Axes + + + + Invert Axis + Inverser les axes + + + + Z Axis + Axe Z + + + + Y Axis + Axe Y + + + + X Axis + Axe X + + + C Axis + Axe C + + + + Seconds to Wait for Response + Secondes d'attente lors d'une réponse + + + Z-Jog Rate (inches or mm/min) + Vitesse manuelle Z (pouces ou mmm/min) + + + Main + Général + + + + Use millimeters when sending manual commands (v0.8c+ only) + Emission des commandes manuelles en millimètre (v0.8c+ seulement) + + + + Filtering + Filtre + + + + Z Rate Limiting + Limitation de vitesse + + + + Limit Z Rate + Vitesse max Z + + + + Z-Rate Limit (inches or mm/min) + Vitesse limite Z (pouces ou mmm/min) + + + + XY Rate (inches or mm/min) + Vitesse XY (pouces ou mmm/min) + + + + Use aggressive preload strategy for Grbl + Utiliser une stratégie offensive de pré-chargement pour Grbl + + + + General + Général + + + + Z-Jog Rate (mm/min) + Vitesse manuelle Z (mm/min) + + + + Max Log Lines ( 0 : unlimited ) + Max Lignes Jornal (0: illimité) + + + + Wait for each jog/manual command to complete (future feature) + Attendre à chaque commande manuelle pour terminer (option future) + + + + Write debugging log to home folder (requires restart) + Mise au point sauvée dans le répertoire d'accueil (+ redémarrage) + + + + Fourth Axis + 4 ème axe + + + + Selecting the Fourth axis + Choix du quatrième axe + + + + A + A + + + + B + B + + + + C + C + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + Valider le mode 4 axes + + + + Display + Affichage + + + + Display the position + Affiche la position + + + + Enable position request and report + Demander la position puis l'afficher + + + + Synchronous simulation (! EXPERIMENTAL !) + Simulation synchrone (!! EXPERIMENTAL !! + + + + No display + Sans affichage + + + + Position Request + Demande de position + + + + Always Request (most reliable/slightly slower jogging) + permanente (plus fiable, mais les commandes manuelles sont ralenties) + + + + Always Request but without Idle Check (fast jog/manual operations) + permanente mais sans controler l'inactivité (commandes manuelles rapides) + + + + Not during manual control (no position update during jog/manual) + sauf les commandes manuelles où l'actualisation de la position est inactive. + + + Always Request + Demande permanente + + + Not during manual control + Exclure des commandes manuelles + + + + Request frequency (seconds) + Période des demandes (secondes) + + + + Command Filtering + Filtrage des commandes + + + + Filter file commands before sending + Filtrage des commandes du fichier GCode avant l'émission + + + + Selectively reduce precision for excessively long lines + Réduire sélectivement la précision, lors de longues lignes de code + + + + Character send delay ms + Délai d'émission des caractères en mS + + + + Grbl Line Buffer Size + Taille du tampon d'entrée de Grbl + + + + QObject + + + Unexpected: Told to send %d bytes + + Inattendu : impossible d'envoyer%d octets + + + Unable to write bytes to port probably due to outgoing queue full. Write data lost! + Impossible d'ecrire sur le port, probablement la file d'attente de sortie est pleine.Perte de donnees en ecriture ! + + + Error writing to port. Write data lost! + Erreu d'ecriture sur le port. Les donnees a ecrire sont perdues + + + + mm + mm + + + + inches + pouces + + + + (Width-X: + (Larg-X: + + + + Height-Y: + Haut-Y: + + + Unexpected type %c + Type attendu %c + + + + Initialising Log4Qt %1 + Initialisation de LOg4Qt %1 + + + + QextSerialPort + + + No Error has occurred + Aucune erreur + + + + Invalid file descriptor (port was not opened correctly) + Descripteur de périphérique invalide (port mal ouvert) + + + + Unable to allocate memory tables (POSIX) + Impossible d'allouer les tables en mémoire (POSIX) + + + + Caught a non-blocked signal (POSIX) + Capture d'un signal non-bloqué (POSIX) + + + + Operation timed out (POSIX) + Dépassement temporel (POSIX) + + + + The file opened by the port is not a valid device + Le fichier ouvert pour le port n'est pas un périphérique valide + + + + The port detected a break condition + Le port a détecté une condition d'arrêt + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + Le port a détecté une erreur de trame (probablement due à une vitesse erronée) + + + + There was an I/O error while communicating with the port + Erreur d'entrée/sortie lors d'une communication sur le port + + + + Character buffer overrun + Dépassementt du tampon de caractères + + + + Receive buffer overflow + Débordement du tampon de réception + + + + The port detected a parity error in the received data + Le port a détecté une erreur de parité lors de la réception de données + + + + Transmit buffer overflow + Débordement du tampon d'émission + + + + General read operation failure + Echec d'une opération de lecture + + + + General write operation failure + Echec d'une opération d'écriture + + + + The %1 file doesn't exists + Le fichier %1 n'existe pas + + + + Permission denied + Non autorisé + + + + Device is already locked + Périphérique déjà bloqué + + + + Unknown error: %1 + Erreur non répertoriée : %1 + + + + Viewer + + + <h3>Version %1</h3> + <h3>Version %1</h3> + + + + <code>by LETARTARE %1</code> + <code>par LETARTARE %1</code> + + + + <br><br> for <h2> %1</h2> + <br><br> pour <h2> %1</h2> + + + + <br>Displays the <b>Path</b> GCode using 'OpenGL'. + <br>Montre les <b>Chemins</b> GCodeen utilisant 'OpenGL'. + + + + <br><br><i>Move the camera using the mouse.</i> + <br><br><i>Déplacer la caméra grace à la souris.</i> + + + diff --git a/GCV-3.6.1-T4/src/trlocale/GrblController_xx.qm b/GCV-3.6.1-T4/src/trlocale/GrblController_xx.qm new file mode 100644 index 0000000..be651ee --- /dev/null +++ b/GCV-3.6.1-T4/src/trlocale/GrblController_xx.qm @@ -0,0 +1 @@ +<¸dÊÍ!¿`¡½Ý \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/trlocale/GrblController_xx.ts b/GCV-3.6.1-T4/src/trlocale/GrblController_xx.ts new file mode 100644 index 0000000..fde7788 --- /dev/null +++ b/GCV-3.6.1-T4/src/trlocale/GrblController_xx.ts @@ -0,0 +1,1804 @@ + + + + + About + + + About... + + + + + The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + + + + Grbl Controller Visualizer + + + + + LETARTARE + + + + + GCode + + + Can't open COM port + + + + + -Is hardware connected to USB? + + + + + -Is correct port chosen? + + + + + -Does current user have sufficient permissions? + + + + + Got Grbl Version (Parsed:) %d.%d%c%c ($$=%d) + + + + + + + Sending to port failed + + + + + SENDING: 0x%02X (CTRL-X) to check presence of Grbl + + + + + + Port not available yet + + + + + Buffer size too small + + + + + SENDING[%d]: 0x%02X (CTRL-X) + + + + + + SENDING[%d]: %s + + + + + + WAITFOROK FAILED + + + + + + Wait for ok failed + + + + + + Error reading data from COM port + + + + + + Unexpected: list is empty (o)! + + + + + + GOT[%d]: '%s' for '%s' (aggressive) + + + + + + Error? + + + + + Unexpected: list is empty (e)! + + + + + GOT: '%s' (aggressive) + + + + + + + GOT:%s + + + + + + Wait interrupted by user + + + + + Expecting Grbl version string. Unable to parse response. + + + + + No data from COM port after connect. Expecting Grbl version string. + + + + + Wait interrupted by user (startup) + + + + + Incorrect - extra axis present in hardware but options set for only 3 axes. Please fix options. + + + + + Incorrect - extra axis not present in hardware but options set for > 3 axes. Please fix options. + + + + + Decoded: State:%s + + + + + Decoded: MPos: %f,%f,%f WPos: %f,%f,%f + + + + + + Decoded: MPos: %f,%f,%f,%f WPos: %f,%f,%f,%f + + + + + + GOT-TE:%s + + + + + + Sending file '%1' + + + + + Pause program Grbl ... + + + + + Resume program Grbl ... + + + + + Resume sending 'Gcode' lines to 'Grbl' + + + + + Gave up waiting for OK + + + + + + Code sent successfully with %1 error(s): + + + + + Code sent successfully with no errors. + + + + + Filtered %1 commands: + + + + + Process interrupted. + + + + + Pause for sending 'Gcode' lines to 'Grbl' + + + + + Removed unsupported command '%1' part of '%2' + + + + + Removed unsupported G command '%1' + + + + + Removed unsupported M command '%1' + + + + + Removed unsupported command '%1' + + + + + Unable to remove enough decimal places for command (will be truncated): %s + + + + + Error, insufficent reduction '%1' + + + + + Precision reduced '%1' + + + + + Z-Rate Limit: [%1]=>[%2] + + + + + Z-Rate Limit: [%1]=>[%2,%3] + + + + + XY-Rate Limit FIX: [%1]=>[%2] + + + + + GCV use 'inches' but Grbl parser set for 'mm' + + + + + + Correction Grbl ended. + + + + + GCV use 'mm' but Grbl parser set for 'inches' + + + + + + Bad command: %1 + + + + + GrblDialog + + + Grbl Settings + + + + + Apply + + + + + Close + + + + + Rank + + + + + Value + + + + + Description + + + + + Log4Qt::AppenderSkeleton + + + Activation of appender '%1' that requires layout and has no layout set + + + + + Use of non activated appender '%1' + + + + + Use of closed appender '%1' + + + + + Use of appender '%1' that requires layout and has no layout set + + + + + Log4Qt::DailyRollingFileAppender + + + Use of appender '%1' without having a valid date pattern set + + + + + The pattern '%1' does not specify a frequency for appender '%2' + + + + + Log4Qt::Factory + + + Cannot convert to type '%1' for property '%2' on object of class '%3' + + + + + Unable to set property value on object + + + + + Invalid null object pointer + + + + + Invalid empty property name + + + + + Property '%1' does not exist in class '%2' + + + + + Property '%1' is not writable in class '%2' + + + + + Log4Qt::FileAppender + + + Activation of Appender '%1' that requires file and has no file set + + + + + Use of appender '%1' without open file + + + + + Unable to write to file '%1' for appender '%2' + + + + + Unable to open file '%1' for appender '%2' + + + + + Unable to remove file '%1' for appender '%2' + + + + + Unable to rename file '%1' to '%2' for appender '%3' + + + + + Log4Qt::OptionConverter + + + Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2. + + + + + Invalid option string '%1' for a boolean + + + + + Invalid option string '%1' for a file size + + + + + Invalid option string '%1' for an integer + + + + + Invalid option string '%1' for a level + + + + + Invalid option string '%1' for a target + + + + + Log4Qt::PatternFormatter + + + Found character '%1' where digit was expected. + + + + + Option '%1' cannot be converted into an integer + + + + + Option %1 isn't a positive integer + + + + + Log4Qt::PropertyConfigurator + + + Unable to open property file '%1' + + + + + Unable to read property file '%1' + + + + + Missing appender definition for appender named '%1' + + + + + Unable to create appender of class '%1' named '%2' + + + + + Unable to create layout of class '%1' requested by appender '%2' + + + + + Missing layout definition for appender '%1' + + + + + Log4Qt::WriterAppender + + + Activation of Appender '%1' that requires writer and has no writer set + + + + + Use of appender '%1' without a writer set + + + + + MainWindow + + + + Check + + + + + Lines: + + + + + Visual + + + + + + Animate + + + + + Starting and stopping the animation + + + + + Up one line in the gcode + + + + + Current line gcode + + + + + Down one line in the gcode + + + + + Animation period mS + + + + + Value of the period + + + + + Monitoring the progress of the animation gcode + + + + + X + + + + + Y + + + + + Z + + + + + Send File + + + + + Begin + + + + + Stop + + + + + Choose file + + + + + Runtime: + + + + + + Open + + + + + Port name + + + + + Tolerance + + + + + Step size, accept cursors keyboard commands + + + + + Small movements of the Z axis + + + + + Step value for the relative movements (G91) + + + + + Soft Reset Grbl + + + + + Unlock Grbl + + + + + Machine Coordinates + + + + + Work Coordinates + + + + + Last State: + + + + + With or without bounding box + + + + + Bbox + + + + + with or without rapid movements + + + + + Z Jog + + + + + + Spindle On + + + + + + + + 0 + + + + + C Jog + + + + + Visualizer + + + + + Baud Rate + + + + + %v + + + + + File progress + + + + + Queued Commands + + + + + Command + + + + + Console + + + + + + + Pause + + + + + Line : + + + + + Period mS + + + + + T + + + + + mm/mn + + + + + attempts to connect to the card containing 'Grbl' or terminates the connection + + + + + Port selection in those detected by the system + + + + + connection speed to card (bauds) + + + + + stops sending the contents of the file 'Gcode' + + + + + sending line by line the contents of the file 'Gcode' + + + + + shows the full name of the loaded file + + + + + commands are sent to 'Grbl' simply control without executing + + + + + time to send a file to 'Grbl' + + + + + Suspend the issuance of the file 'Gcode to the end of the current line + + + + + 00:00:00 + + + + + indicates the last release state Grbl + + + + + no state + + + + + animation of the scene 3D + + + + + + interpolation tolerance for viewer 3D + + + + + + + + + + mm + + + + + interpolation number of segments for 3D + + + + + Speed rate gcode (mm or inches per minute) + + + + + Spindle control: running -> yellow + + + + + Pass in absolute coordinates after moving it occurs in relative displacement + + + + + G90 after adjust + + + + + Unit X axis + + + + + Unit Y axis + + + + + Unit Z axis + + + + + Unit of the fourth axis + + + + + deg + + + + + GRBL Settings + + + + + Grbl commands + + + + + Help + + + + + Build info + + + + + Parameters + + + + + Grbl Controller Visualizer + + + + + load a file for animation + or send to Grbl + + + + + Shows the commands available in Grbl + + + + + Parser state + + + + + Startup blocks + + + + + Homing Cycle + + + + + Item segments + + + + + Removes the selected text lines + + + + + Clear selection + + + + + + Prints lines of text selected +otherwise all text + + + + + Print selection + + + + + Print visual + + + + + Feed rate + + + + + Speed spindle + + + + + Last spindle speed read in the Gcode + + + + + rpm + + + + + + + + Moves the axis at zero + + + + + + + Move the axis to negative values + + + + + + + Move the axis to the positive values + + + + + Axis moves clockwise +Move the axis to negative values + + + + + Moves the axis in the counterclockwise +Move the axis to the positive values + + + + + Go Home :first moves the Z axis + then all axes synchronously at zero + + + + + The current position will be the new zero position :G92 x0 y0 z0 + + + + + Viewer3D + + + + + Perspective view + + + + + Front view + + + + + Back view + + + + + Left view + + + + + Right view + + + + + Bottom view + + + + + Top view + + + + + Vector up along Y axis + + + + + tool selection + + + + + Tool + + + + + G0 + + + + + + Help 3D + + + + + Grbl version + + + + + Refresh Pos + + + + + Firmware : + + + + + + none + + + + + Queue clear + + + + + The current position will be the new zero position :G92 x0 y0 z0 + + + + + = Zero Position + + + + + &Help + + + + + &Tools + + + + + &File + + + + + &About + + + + + &Options + + + + + E&xit + + + + + You appear to have upgraded to the latest version of Grbl Controller. Please be aware that as of version 3.4 the default behavior of sending commands to Grbl has been changed to send them as fast as possible (Aggressive preload mode). + +Your settings have been changed to enable this mode. Why? Because it provides the most optimal use of Grbl and greatly reduces the time to finish a typical job. + +What does this mean to you? Arc commands will now run smoother and faster than before, which may cause your spindle to work slightly harder, so please run some tests first. Alternately, go to the Options dialog and manually disable Aggressive Preload + + + + + User clicked Port Open/Close + + + + + Do you want to zero the displayed position before proceeding? + + + + + Close / Reset + + + + + %s has started + + + + + No tool + + + + + Mini 1 mm + + + + + Hemi 3 mm + + + + + Right 3 mm + + + + + Sharp 3 mm + + + + + Short 3 mm + + + + + %s has stopped + + + + + Resume + + + + + Resetting port to restart controller + + + + + Open File + + + + + NC (*.nc);;All Files (*.*) + + + + + A Jog + + + + + B Jog + + + + + U Jog + + + + + V Jog + + + + + W Jog + + + + + Spindle Off + + + + + Unexpected type %c + + + + + Usr chg: pos=%d new=%d + + + + + + Usr chg: pos=%.1f new=%.1f + + + + + + Usr chg no slider: %d + + + + + + Usr chg no slider: %.1f + + + + + + Pressed and stopped + + + + + + Pressed not stopped + + + + + + Released + + + + + + During the mode 'Check 'does not use the command '$C' please + + + + + No check + + + + + With 'Grbl Settings' you must validate the homing cycle + + + + + No animate + + + + + in + + + + + mn + + + + + deg. + + + + + + Run + + + + + Options + + + Options + + + + + Axis + + + + + Invert Axis + + + + + Z Axis + + + + + Y Axis + + + + + X Axis + + + + + Seconds to Wait for Response + + + + + General + + + + + Use millimeters when sending manual commands (v0.8c+ only) + + + + + Wait for each jog/manual command to complete (future feature) + + + + + Filtering + + + + + Z Rate Limiting + + + + + Limit Z Rate + + + + + Z-Rate Limit (inches or mm/min) + + + + + XY Rate (inches or mm/min) + + + + + Use aggressive preload strategy for Grbl + + + + + Z-Jog Rate (mm/min) + + + + + Max Log Lines ( 0 : unlimited ) + + + + + Write debugging log to home folder (requires restart) + + + + + Fourth Axis + + + + + Selecting the Fourth axis + + + + + A + + + + + B + + + + + C + + + + + U + + + + + V + + + + + W + + + + + Enable 4-axis mode + + + + + Display + + + + + Display the position + + + + + Enable position request and report + + + + + Synchronous simulation (! EXPERIMENTAL !) + + + + + No display + + + + + Position Request + + + + + Always Request (most reliable/slightly slower jogging) + + + + + Always Request but without Idle Check (fast jog/manual operations) + + + + + Not during manual control (no position update during jog/manual) + + + + + Request frequency (seconds) + + + + + Command Filtering + + + + + Filter file commands before sending + + + + + Selectively reduce precision for excessively long lines + + + + + Character send delay ms + + + + + Grbl Line Buffer Size + + + + + QObject + + + mm + + + + + inches + + + + + (Width-X: + + + + + Height-Y: + + + + + Unexpected: Told to send %d bytes + + + + + + Initialising Log4Qt %1 + + + + + QextSerialPort + + + No Error has occurred + + + + + Invalid file descriptor (port was not opened correctly) + + + + + Unable to allocate memory tables (POSIX) + + + + + Caught a non-blocked signal (POSIX) + + + + + Operation timed out (POSIX) + + + + + The file opened by the port is not a valid device + + + + + The port detected a break condition + + + + + The port detected a framing error (usually caused by incorrect baud rate settings) + + + + + There was an I/O error while communicating with the port + + + + + Character buffer overrun + + + + + Receive buffer overflow + + + + + The port detected a parity error in the received data + + + + + Transmit buffer overflow + + + + + General read operation failure + + + + + General write operation failure + + + + + The %1 file doesn't exists + + + + + Permission denied + + + + + Device is already locked + + + + + Unknown error: %1 + + + + + Viewer + + + <h3>Version %1</h3> + + + + + <code>by LETARTARE %1</code> + + + + + <br><br> for <h2> %1</h2> + + + + + <br>Displays the <b>Path</b> GCode using 'OpenGL'. + + + + + <br><br><i>Move the camera using the mouse.</i> + + + + diff --git a/GCV-3.6.1-T4/src/version.h b/GCV-3.6.1-T4/src/version.h new file mode 100644 index 0000000..e2d6e36 --- /dev/null +++ b/GCV-3.6.1-T4/src/version.h @@ -0,0 +1,13 @@ +/**************************************************************** + * version.h + * GrblHoming - zapmaker fork on github + * + * 14 July 2013 + * GPL License (see LICENSE file) + * Software is provided AS-IS + ****************************************************************/ +#ifndef VERSION_H +#define VERSION_H +#define GRBL_CONTROLLER_NAME_AND_VERSION "Grbl Controller Visualizer 3.6.1-T4" +#define VERSION_BUILD " 20140822" +#endif // VERSION_H diff --git a/GCV-3.6.1-T4/src/visu3D/Arc3D.cpp b/GCV-3.6.1-T4/src/visu3D/Arc3D.cpp new file mode 100644 index 0000000..487ad1c --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Arc3D.cpp @@ -0,0 +1,415 @@ +/*************************************************************** + * Name: Arc3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ +#include "Arc3D.h" +#include +#include "definitions.h" /// PLANE_XY_G17,... + +Arc3D::Arc3D(): + plane(NO_PLANE), + cw(true), + pstart(), pend(), poffset(), + nrevol(0) +{ + pcenter = pstart + poffset; + radius = 0.0; + astart = aend = 0.0; + color = Qt::black; /// noir + linewidth = 1; + feedrate = SPEED_DEFAULT; + // no paths + interpolated = false; + path.clear(); +} + +// arc for plane circle +Arc3D::Arc3D(float dia) +{ + radius = dia/2.0; +} + +// arc for GCode G2, G3 +Arc3D::Arc3D(uint8_t p, bool dir, QVector3D s, QVector3D e, QVector3D o, uint8_t r, bool h) : + plane(p), + cw(dir), + pstart(s), pend(e), poffset(o), + nrevol(r), // not used !! + helix(h), + pcenter(pstart + poffset), + color(Qt::darkGreen), /// green + linewidth(1), feedrate(SPEED_DEFAULT) +{ + // no paths + interpolated = false; + path.clear(); +//diag("GArc start ==> sx, sy, sz = %f, %f, %f", pstart.x(), pstart.y(), pstart.z()); +//diag("GArc end ==> ex, ey, ez = %f, %f, %f", pend.x(), pend.y(), pend.z()); +//diag("GArc offset ==> lx, ly, lz = %f, %f, %f", poffset.x(), poffset.y(), poffset.z()); +//diag("GArc center ==> cx, cy, cz = %f, %f, %f", pcenter.x(), pcenter.y(), pcenter.z()); + /// plane selection + double t2(0) , u2(0); /// axes ? +//diag("Arc plane = %d", plane); + switch (plane) { + case PLANE_XY_G17 : /// XY G17 + pcenter.setZ(pstart.z()) ; + t2 = qPow(pstart.x() - pcenter.x(), 2.0) ; + //diag("sx , cx = %f, %f", pstart.x(), pcenter.x()); + u2 = qPow(pstart.y() - pcenter.y() , 2.0) ; + // diag("sy , cy = %f, %f", pstart.y(), pcenter.y()); + // diag("XY : t2 , u2 = %f, %f" , t2, u2); + // angles + astart = qAtan2(pstart.y()- pcenter.y(), pstart.x()- pcenter.x() ); + aend = qAtan2(pend.y()- pcenter.y(), pend.x()- pcenter.x() ); + // diag("as , ae = %f, %f", astart, aend); + break; + case PLANE_ZX_G19 : /// ZX G18 + pcenter.setY(pstart.y()) ; + t2 = qPow(pstart.x() - pcenter.x(), 2.0) ; + u2 = qPow(pstart.z() - pcenter.z(), 2.0) ; + // diag("XZ : t2 , u2 = %f, %f" , t2, u2); + // + astart = qAtan2(pstart.z()- pcenter.z(), pstart.x()- pcenter.x() ); + aend = qAtan2(pend.z()- pcenter.z(), pend.x()- pcenter.x() ); + break; + case PLANE_YZ_G18: /// YZ G19 + pcenter.setX(pstart.x()); + t2 = qPow(pstart.y() - pcenter.y(), 2.0) ; + u2 = qPow(pstart.z() - pcenter.z(), 2.0) ; + // diag("YZ : t2 , u2 = %f, %f" , t2, u2); + // + astart = qAtan2(pstart.z()- pcenter.z(), pstart.y()- pcenter.y() ); + aend = qAtan2(pend.z()- pcenter.z(), pend.y()- pcenter.y() ); + break; + default : + ; + } + /// radius into plane + radius = qSqrt( t2 + u2 ); +//diag("radius = %f", radius); +//diag("astart , aend = %f, %f", astart, aend); +} + +Arc3D::~Arc3D() +{ + //dtor +} + +void Arc3D::setColor(QColor c) +{ + color = c ; +} + +void Arc3D::setLineWidth(int lw) +{ + if (lw > 0 && lw <= 10) + linewidth = lw; + else + linewidth = 1; +} + +void Arc3D::setSpeed (double f) +{ + if (f > SPEED_MIN && f <= SPEED_MAX) + feedrate = f; +} + + +/// FOR TESTING ... it's correct +uint32_t Arc3D::interpolateAng(const double tol, QList& path1) +{ + if (interpolated) + return path.size()-1; + // no paths + path.clear(); +//diag("pstart = %f/%f/%f", pstart.x(), pstart.y(), pstart.z() ); +//diag("pend = %f/%f/%f", pend.x(), pend.y(), pend.z() ); + // number of sectors + uint32_t nsec ; + if (radius) { + double as = astart + ,ae = aend + ,da; + /// TO REWRITE !! + // radians + if (cw) + da = -positive(as - ae); + else + da = positive(ae - as); + /// <-- +//diag("as , ae , cw = %f, %f, %s ", astart, aend, cw==0 ? "horaire" : "anti"); + // interpolation segments + /// -> an another way to ... + /// radians + double dda = 2*qAcos(1- (tol/radius)); + nsec = qRound(qAbs(da/dda)+ 0.5); +//diag("tol, radius, dda, seg : %.3f, %.2f, %.2f, %d", tol, radius, dda, seg); + /// <-- + // new increment dda + dda = da / double(nsec); +//diag("dda : %f", dda); + // generate segments + if (nsec > 0 ) { + // with helix ? + double dx(0), dy(0), dz(0); + QVector3D pdh(0, 0, 0); + if (helix) { + switch (plane) { + case PLANE_XY_G17: + dz = (pend.z()-pstart.z())/(1.0*nsec); + pdh.setZ(dz); + break; + case PLANE_ZX_G19: + dy = (pend.y()-pstart.y())/(1.0*nsec); + pdh.setY(dy); + break; + case PLANE_YZ_G18: + dx = (pend.x()-pstart.x())/(1.0*nsec); + pdh.setX(dx); + break; + } + } + + // generate sectors interpolation from 'astart' + double teta = astart; + QVector3D p ; + uint32_t npi = 0; + do { + p = pointArc(teta); + if (helix) { + p += npi*pdh; + } + path.append(p); + teta += dda; + npi++; + } while (npi <= nsec) ; + // 'path' contains the end points of the vectors + interpolated = true; + } + else { /// one sectort + nsec = 1; + path.append(pstart); + path.append(pend); + } + } + else { + nsec = 0; + path.append(pcenter); + } + + path1 = path; + + return nsec ; +} + +uint32_t Arc3D::interpolateSeg(const double tol) +{ + if (interpolated) + return path.size()-1; + // no paths + path.clear(); + + + // number of sectors + uint32_t seg ; + if (radius) { + double as = astart + ,ae = aend + ,da; + /// TO REWRITE !! + //da = ae - as; /// radians + if (cw) + da = -positive(as - ae); + else + da = positive(ae - as); + /// <-- + // interpolation segments + // calculating the start deflection in radians + double defle = radius*(1-qCos(da/=2)); + // accumulates the number of divisions + seg = 1; + // calculate the deflection for fle <= tol + if (defle > tol) { + do { + defle = radius*(1-qCos(da/=2)); + seg++; + } while (defle > tol); + + seg = 1 << seg ; + // with helix + double dx(0), dy(0), dz(0); + QVector3D pdh(0, 0, 0); + if (helix) { + switch (plane) { + case PLANE_XY_G17: + dz = (pend.z()-pstart.z())/(1.0*seg); + pdh.setZ(dz); + break; + case PLANE_ZX_G19: + dy = (pend.y()-pstart.y())/(1.0*seg); + pdh.setY(dy); + break; + case PLANE_YZ_G18: + dx = (pend.x()-pstart.x())/(1.0*seg); + pdh.setX(dx); + break; + } + } + // generate segments interpolation from 'astart' + double teta = astart; + QVector3D p ; + uint32_t npi = 0; + // 'path' contains the end points of the vectors + do { + p = pointArc(teta); + if (helix) { + p += npi* pdh; + } + path.append(p); + teta += da; + npi++; + } while (npi <= seg) ; + + interpolated = true; + } + else { + seg = 1; + path.append(pstart); + path.append(pend); + } + } + else { + seg = 0; + path.append(pcenter); + } +//diag("seg : %d", seg); + return seg ; +} + +// arc point from 'a' radian +QVector3D Arc3D::pointArc ( const double a ) +{ + double teta = normal(a); + double dx(0), dy(0), dz(0); + switch (plane) { + case PLANE_XY_G17 : /// XY + dx = radius*qCos(teta) ; + dy = radius*qSin(teta) ; + dz = 0; + break; + case PLANE_ZX_G19 : /// ZX + dx = radius*qCos(teta) ; + dy = 0; + dz = radius*qSin(teta) ; + break; + case PLANE_YZ_G18 : /// YZ + dx = 0; + dy = radius*qSin(teta) ; + dz = radius*qCos(teta) ; + break; + } + + QVector3D P(pcenter.x() + dx, pcenter.y() + dy, pcenter.z() + dz ); + return P; +} + +void Arc3D::gdraw3D() const +{ + if (path.size() == 0) + return; + + double psx = path.at(0).x() + ,psy = path.at(0).y() + ,psz = path.at(0).z() ; + double pex , pey, pez; + + glLineWidth(linewidth); + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glBegin(GL_LINE_STRIP); + foreach (QVector3D p, path) { + pex = p.x(); pey = p.y(); pez = p.z(); + glVertex3d(psx, psy, psz); + glVertex3d(pex, pey, pez); + psx = pex; psy = pey; psz = pez; + } + glEnd(); +} + +void Arc3D::MinMax(QVector3D& pmin, QVector3D& pmax) +{ + if (path.size() == 0) + return; + if (!interpolated) + return; + + double x , y, z; + foreach (QVector3D p, path) { + x = p.x(); y = p.y(); z = p.z(); + if (x > pmax.x()) pmax.setX(x); + if (y > pmax.y()) pmax.setY(y); + if (z > pmax.z()) pmax.setZ(z); + + if (x < pmin.x()) pmin.setX(x); + if (y < pmin.y()) pmin.setY(y); + if (z < pmin.z()) pmin.setZ(z); + } +} + +///----------------------------------------------------------------------------- +/// To VERIFY !! +///----------------------------------------------------------------------------- +// normalizes the value of the angle in [0..2*PI[ +double Arc3D::positive (const double VA) +{ + double V = VA; +// if < 0.0 + while (V <= 0.0) // 0 -> 2*PI, (..2*PI] ) -2*k*PI -> 0 ( [0.. ) + V += 2*M_PI; +// if > 2*PI + while (V > 2*M_PI) // 2*PI -> 2*PI ( ..2*PI] ) + V -= 2*M_PI; + return V; +} +///----------------------------------------------------------------------------- +/// To VERIFY !! +///----------------------------------------------------------------------------- +// normalizes the value of the angle in [-PI..PI] +double Arc3D::normal ( const double VA ) +{ + double V = VA; +// if < -PI + while (V < - M_PI) // [-PI.. + V += 2*M_PI; +// if >= +PI + while (V > M_PI) // and -> ..PI] + V -= 2*M_PI; + return V; +} + +// radians => degrees +double Arc3D::deg (double a, emode m) +{ + if (m == _NORM ) + a = normal(a); + else + a = positive(a); + + return a *= (180.0/M_PI); +} + +// degrees => radians +double Arc3D::rad(double a /*, emode m*/) +{ + a /= (180.0/M_PI); + /* + if (m == _NORM ) + a = normal(a); + else + a = positive(a); + */ + return a ; +} diff --git a/GCV-3.6.1-T4/src/visu3D/Arc3D.h b/GCV-3.6.1-T4/src/visu3D/Arc3D.h new file mode 100644 index 0000000..0dffe42 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Arc3D.h @@ -0,0 +1,83 @@ +/*************************************************************** + * Name: Arc3D.h + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#ifndef ARC3D_H +#define ARC3D_H + +#include +#include /// uint8_t, ... + +class Arc3D +{ + + // mode = NORM -> all angles are in [-PI..+PI[ + // mode = POSI -> all angles are in [0..2*PI] + enum emode { _NORM, _POSI }; + + public: + Arc3D(); + // arc for plane circle + Arc3D(float diameter); + // arc for GCode G2, G3 + Arc3D(uint8_t plane, bool dir, QVector3D pstart, QVector3D pend, + QVector3D poffset, uint8_t revolutions, bool helix=false); + + virtual ~Arc3D(); + + void gdraw3D() const; + + void setColor (QColor); + + void setLineWidth(int) ; + + void setSpeed (double); + + uint32_t interpolateSeg(const double tol ); + + uint32_t interpolateAng(const double tol, QList& path1 ); + + void MinMax(QVector3D&, QVector3D&); + + private: + ///fonctions + QVector3D pointArc ( const double angle); + // normalizes the value of the angle in [0..2*PI[ + double positive (const double VA); + // normalizes the value of the angle in [-PI..PI] + double normal ( const double VA ); + // radians -> degrees + double deg (double a, emode m = _POSI); + // degrees -> radians + double rad(double a /*, emode m = _POSI*/); + + /// attributs + + /// plane selection XY (G17) = 0, ZX (G18) = 1, YZ (G19) = 2 + uint8_t plane; + bool cw; // direction + QVector3D pstart, pend; // x, y, z + QVector3D poffset; // i, j, k + uint8_t nrevol; // revolutions + bool helix; // helix + /// calculated + QVector3D pcenter; // center + double radius; // radius + double astart, aend; // angles (radians) + // buffer path + QList path; + bool interpolated; + + // The color with which this item should be displayed + QColor color; + int linewidth; + double feedrate; +}; + + +#endif // ARC_H diff --git a/GCV-3.6.1-T4/src/visu3D/Line3D.cpp b/GCV-3.6.1-T4/src/visu3D/Line3D.cpp new file mode 100644 index 0000000..8b4e6b3 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Line3D.cpp @@ -0,0 +1,85 @@ +/*************************************************************** + * Name: Line3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#include "Line3D.h" + +#include +#include "definitions.h" + +Line3D::Line3D() : + pstart(), pend(), + color (Qt::black), + feedrate(SPEED_DEFAULT) + +{ +} + +Line3D::Line3D( const QVector3D s, const QVector3D e) : + pstart(s), + pend(e), + color(Qt::blue), linewidth(1), + feedrate(SPEED_DEFAULT) +{ +} + +Line3D::~Line3D() +{ + //dtor +} + +void Line3D::gdraw3D() const +{ + glLineWidth(linewidth); + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glBegin(GL_LINES); + glVertex3d(pstart.x(), pstart.y(), pstart.z()); + glVertex3d(pend.x(), pend.y(), pend.z()); + glEnd(); +} + +void Line3D::setColor(QColor c) +{ + color = c ; +} + +void Line3D::setLineWidth(int lw) +{ + if (lw > 0 && lw <= 10) + linewidth = lw; + else + linewidth = 1; +} + +void Line3D::setSpeed (double f) +{ + if (f > SPEED_MIN && f <= SPEED_MAX) + feedrate = f; +} + +void Line3D::MinMax(QVector3D& pmin, QVector3D& pmax) +{ + /// start point + double x = pstart.x(), y = pstart.y(), z = pstart.z(); + if (x > pmax.x()) pmax.setX(x); + if (y > pmax.y()) pmax.setY(y); + if (z > pmax.z()) pmax.setZ(z); + + if (x < pmin.x()) pmin.setX(x); + if (y < pmin.y()) pmin.setY(y); + if (z < pmin.z()) pmin.setZ(z); + /// end point + x = pend.x(), y = pend.y(), z = pend.z(); + if (x > pmax.x()) pmax.setX(x); + if (y > pmax.y()) pmax.setY(y); + if (z > pmax.z()) pmax.setZ(z); + + if (x < pmin.x()) pmin.setX(x); + if (y < pmin.y()) pmin.setY(y); + if (z < pmin.z()) pmin.setZ(z); +} diff --git a/GCV-3.6.1-T4/src/visu3D/Line3D.h b/GCV-3.6.1-T4/src/visu3D/Line3D.h new file mode 100644 index 0000000..38ed237 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Line3D.h @@ -0,0 +1,49 @@ +/*************************************************************** + * Name: Line3D.h + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#ifndef LINE3D_H +#define LINE3D_H + +#include + +/*! + A simple line 3D. + */ +class Line3D +{ +public: + Line3D(); + + Line3D(const QVector3D s, const QVector3D e) ; + + virtual ~Line3D(); + + void gdraw3D() const; + + void setColor (QColor); + + void setLineWidth(int); + + void setSpeed (double); + + void MinMax(QVector3D&, QVector3D&); + +private: + + QVector3D pstart, pend; + QColor color; + int linewidth; + double feedrate; + bool mm; + +}; + +#endif // LINE3D_H + + diff --git a/GCV-3.6.1-T4/src/visu3D/Point3D.cpp b/GCV-3.6.1-T4/src/visu3D/Point3D.cpp new file mode 100644 index 0000000..e87089b --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Point3D.cpp @@ -0,0 +1,54 @@ +/*************************************************************** + * Name: Point3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#include "Point3D.h" +#include + +Point3D::Point3D() : + p(), + color (Qt::black) +{ +} + +Point3D::Point3D(const QColor c, const QVector3D s) : + p(s), + color(c) +{ +} + +Point3D::~Point3D() +{ //dtor +} + +void Point3D::setColor(QColor c) +{ + color = c ; +} + +void Point3D::gdraw3D() const +{ + glLineWidth(1); + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glBegin(GL_POINTS); + glVertex3d(p.x(), p.y(), p.z()); + glEnd(); +} + +void Point3D::MinMax(QVector3D& pmin, QVector3D& pmax) +{ + /// start point + double x = p.x(), y = p.y(), z = p.z(); + if (x > pmax.x()) pmax.setX(x); + if (y > pmax.y()) pmax.setY(y); + if (z > pmax.z()) pmax.setZ(z); + + if (x < pmin.x()) pmin.setX(x); + if (y < pmin.y()) pmin.setY(y); + if (z < pmin.z()) pmin.setZ(z); +} diff --git a/GCV-3.6.1-T4/src/visu3D/Point3D.h b/GCV-3.6.1-T4/src/visu3D/Point3D.h new file mode 100644 index 0000000..7dc13b2 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Point3D.h @@ -0,0 +1,38 @@ +/*************************************************************** + * Name: Point3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-16-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#ifndef POINT3D_H +#define POINT3D_H + +#include + + +class Point3D +{ + public: + Point3D(); + + Point3D(const QColor c, const QVector3D s) ; + + virtual ~Point3D(); + + void gdraw3D() const; + + void setColor (QColor); + + void MinMax(QVector3D&, QVector3D&); + + private: + + const QVector3D p ; + QColor color; + bool mm; +}; + +#endif // POINT3D_H diff --git a/GCV-3.6.1-T4/src/visu3D/Tools3D.cpp b/GCV-3.6.1-T4/src/visu3D/Tools3D.cpp new file mode 100644 index 0000000..d5d62a6 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Tools3D.cpp @@ -0,0 +1,184 @@ +/*************************************************************** + * Name: Tools3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#include "Tools3D.h" + +#include +#include "definitions.h" + + +Tools3D::Tools3D() : + color (Qt::black) +{ +} + +Tools3D::Tools3D(uint8_t pl, QVector3D s, typeTool t) : + plane(pl), + start(s), + type(t), + color (Qt::black), + mm(true) +{ +} + +Tools3D::~Tools3D() +{ +} + +void Tools3D::setColor(QColor c) +{ + color = c ; +} + +void Tools3D::setPlane(uint8_t pl) +{ + plane = pl; +} + +void Tools3D::setPos(QVector3D pos) +{ + start = pos; +} + +void Tools3D::setPos(qglviewer::Vec vpos) +{ + start = QVector3D(vpos.x, vpos.y, vpos.z) ; +} + +void Tools3D::setPos(double x, double y, double z) +{ + start = QVector3D(x, y, z);; +} + +/// just a red point +void Tools3D::setTool(typeTool t) +{ + type = t; +} +void Tools3D::setUnit(bool mm1) +{ + mm = mm1; +} + +// +void Tools3D::gdraw3D() const +{ + float X = start.x(); + float Y = start.y(); + float Z = start.z(); + /// mm + float D = 3.0; + float L = 10.0; + if (!mm) { + D /= MM_IN_AN_INCH; + L /= MM_IN_AN_INCH; + } + float R = D/2.0; + float H = 3*D; + + QColor color(Qt::red); color.setRgb(255, 90, 40, 255); + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + // a quadratic object in the heap for caps + GLUquadricObj * temp = gluNewQuadric (); + glPushMatrix(); + { + // placing the axis of the tool to the position 'X, Y, Z' + glTranslated (X, Y, Z ); + if (plane == PLANE_XY_G17) { + // align the tool perpendicular to the work plan + glRotated (180, 1, 0, 0); + } + else + if (plane == PLANE_ZX_G19) { + glRotated (90, 1, 0, 0); + } + else + if (plane == PLANE_YZ_G18) { + glRotated (-90, 0, 1, 0); + } + + // the type of tool + if (type == _RIGHT) { // diameter = 3 mm + //1- right milling cutter + // disc bottom: internal and external radius, number of sides, concentric zone + gluDisk (temp, 0.0, R, 64, 1); + // vertical cylinder axis Z on + glTranslated (0, 0, -L); + // cylinder + gluCylinder(temp, R, R, L, 64, 1); + // the top disc + gluDisk (temp, 0.0, R, 64, 1); + } + else + if (type == _HEMI) { // diameter = 3 mm + //2- milling cutter hemispherical + // vertical cylinder axis Z on + glTranslated (0, 0, -R); + // lower sphere: radius, number of sides around Z, number of section along Z + gluSphere (temp, R, 24, 12 ); + // vertical cylinder axis Z on + glTranslated (0, 0, -L); + // cylinder + gluCylinder(temp, R, R, L, 64, 1); + // the top disc + gluDisk (temp, 0.0, R, 64, 1); + } + else + if (type == _SHARP) { + //3- sharp milling cutter + glTranslated (0, 0, -H); + // lower cone , radius base, radius top, length, number of sides, number of section + gluCylinder (temp, R, 0, H, 64, 1); + // vertical cylinder axis Z on + glTranslated (0, 0, -L); + // cylinder + gluCylinder(temp, R, R, L, 64, 1); + // the top disc + gluDisk (temp, 0.0, R, 64, 1); + + /* reversing the direction of the tool + //3- sharp milling cutter + glTranslated (0, 0, H); + // lower cone , radius base, radius top, length, number of sides, number of section + gluCylinder (temp, 0, R, H, 64, 1); + // vertical cylinder axis Z on + glTranslated (0, 0, H); + // cylinder + gluCylinder(temp, R, R, L, 64, 1); + // the top disc + gluDisk (temp, 0.0, R, 64, 1); + */ + } + else + if (type == _SHARP_SHORT) { + //3- sharp milling cutter + H /= 2.0; R /= 2.0; + glTranslated (0, 0, -H); + // lower cone , radius base, radius top, length, number of sides, number of section + gluCylinder (temp, R, 0, H, 64, 1); + // vertical cylinder axis Z on + glTranslated (0, 0, -L); + // cylinder + //gluCylinder(temp, R, R, L, 64, 1); + // the top disc + //gluDisk (temp, 0.0, R, 64, 1); + } + else + if (type == _MINI) { // diameter = 1 mm + // lower sphere: radius, number of sides around Z, number of section along Z + gluSphere (temp, R/3, 24, 12 ); + } + // for the light reflection + gluQuadricOrientation(temp, GLU_OUTSIDE); + } + + glPopMatrix(); + gluDeleteQuadric(temp); +} +//------------------------------------------------------------------------------ diff --git a/GCV-3.6.1-T4/src/visu3D/Tools3D.h b/GCV-3.6.1-T4/src/visu3D/Tools3D.h new file mode 100644 index 0000000..e360c34 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/Tools3D.h @@ -0,0 +1,49 @@ +/*************************************************************** + * Name: Tools3D.h + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#ifndef TOOLS3D_H +#define TOOLS3D_H + +#include +#include +#include // uint8_t ... + +class Tools3D +{ + public: + enum typeTool {_MINI=0, _RIGHT, _HEMI, _SHARP, _SHARP_SHORT}; + + Tools3D(); + + Tools3D(uint8_t plane, QVector3D s, typeTool type=_SHARP_SHORT); + + virtual ~Tools3D(); + + void gdraw3D() const; + + void setColor (QColor); + + void setPlane(uint8_t); + + void setPos(QVector3D); + void setPos(qglviewer::Vec); + void setPos(double x, double y, double z); + void setTool(typeTool); + void setUnit(bool mm); + + private: + + uint8_t plane ; + QVector3D start; + typeTool type; + QColor color; + bool mm; +}; + +#endif // POINT3D_H diff --git a/GCV-3.6.1-T4/src/visu3D/box3D.cpp b/GCV-3.6.1-T4/src/visu3D/box3D.cpp new file mode 100644 index 0000000..3edc867 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/box3D.cpp @@ -0,0 +1,70 @@ +/*************************************************************** + * Name: Box3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#include "box3D.h" +#include + +Box3D::Box3D(const QVector3D p1, const QVector3D p2, bool mm1, QColor c) + : pmin(p1), pmax(p2), + mm(mm1), color(c) + +{ +} + +void Box3D::setColor(QColor c) +{ + color = c ; +} + +void Box3D::setMm (bool bm) +{ + mm = bm; +} + +void Box3D::setDim (QVector3D p1, QVector3D p2) +{ + pmin = p1; pmax = p2; +} + + +void Box3D::gdraw3D() const +{ + glLineWidth(1); + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + + double p1x = pmin.x() , p1y = pmin.y() , p1z = pmin.z() , + p2x = pmax.x() , p2y = pmax.y(), p2z = pmax.z() ; + /// establishes the pattern that the lines will use for drawing + glLineStipple(1, 0x48FF); + glEnable(GL_LINE_STIPPLE); + + glBegin(GL_LINE_STRIP); + glVertex3d(p1x, p1y, p1z); + glVertex3d(p1x, p2y, p1z); + glVertex3d(p2x, p2y, p1z); + glVertex3d(p2x, p1y, p1z); + glVertex3d(p1x, p1y, p1z); + glVertex3d(p1x, p1y, p2z); + glVertex3d(p1x, p2y, p2z); + glVertex3d(p2x, p2y, p2z); + glVertex3d(p2x, p1y, p2z); + glVertex3d(p1x, p1y, p2z); + glEnd(); + + glBegin(GL_LINES); + glVertex3d(p1x, p2y, p1z); + glVertex3d(p1x, p2y, p2z); + glVertex3d(p2x, p2y, p1z); + glVertex3d(p2x, p2y, p2z); + glVertex3d(p2x, p1y, p1z); + glVertex3d(p2x, p1y, p2z); + glEnd(); + glDisable(GL_LINE_STIPPLE); +} + diff --git a/GCV-3.6.1-T4/src/visu3D/box3D.h b/GCV-3.6.1-T4/src/visu3D/box3D.h new file mode 100644 index 0000000..50f32d6 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/box3D.h @@ -0,0 +1,37 @@ +/*************************************************************** + * Name: Box3D.h + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#ifndef BOX3D_H +#define BOX3D_H + +#include + + +// An Axis Aligned Bounding Box. +class Box3D +{ +public: + Box3D(const QVector3D p1, const QVector3D p2, bool mm1 = true, QColor c = Qt::red); + + void gdraw3D() const; + + void setColor (QColor); + + void setDim (QVector3D p1, QVector3D p2); + + void setMm (bool); + +private: + + QVector3D pmin, pmax; + bool mm; + QColor color; +}; + +#endif diff --git a/GCV-3.6.1-T4/src/visu3D/viewer3D.cpp b/GCV-3.6.1-T4/src/visu3D/viewer3D.cpp new file mode 100644 index 0000000..bd3fa27 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/viewer3D.cpp @@ -0,0 +1,888 @@ +/*************************************************************** + * Name: viewer3D.cpp + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ + +#include "viewer3D.h" +#include +#include "point3D.h" +#include "line3D.h" +#include "arc3d.h" +#include "box3D.h" +#include "version.h" + +// Constructor must call the base class constructor. +Viewer::Viewer(QWidget *parent1) + : QGLViewer(parent1), parent(parent1), + radius(MAX_X), tol(TOL_MM_STEP), // mm + mm(true), + plane(PLANE_XY_G17), + withtool(true), withbbox(true), withg0(true), created(false), first(true), + vmax(MAX_X), // mm + vecBanned(MAX_X, MAX_Y, MAX_Z), phome(MIN_X, MIN_Y, MAX_Z), + pvcenter(25, 25, 50 ) /// oups ? +{ + restoreStateFromFile(); +} + +void Viewer::init() +{ + /// clear yellow + setBackgroundColor(QColor(244, 237, 187)); + setForegroundColor(Qt::black); + setSceneRadius(radius); + setSceneCenter(pvcenter); + setAxisIsDrawn(true); + /// front view + setFrontView() ; + /// create one tool + Tool = Tools3D( 0, phome ); + /// + visu = false; + pause = true; + firstauto = true; + runcode = false; + npoint = -1; + linecodeText = linecodeTextmax = 0; + posPath = 0; + pmin = QVector3D( MIN_X, MIN_Y, MIN_Z); + pmin = QVector3D( MAX_X, MAX_Y, MAX_Z); + pcurr = pprev = phome; + + // timer animator + repeatVisu = new QTimer(this); + //setPeriod(250); + connect(repeatVisu, SIGNAL(timeout()), this, SLOT(setVisualAuto())); + // timer for points + repeatPoint = new QTimer(this); + connect(repeatPoint, SIGNAL(timeout()), this, SLOT(drawItem())); + //itemrec = true; +} + +/// called by 'MainWindow::preProcessFile(...)' with 'emit setItems(posList)' +void Viewer::setItems(QList itemsRcvd) +{ + // all items + items = itemsRcvd ; + foreach(PosItem item, items) { + mm = item.mm ; + } + if (!mm) { + vmax /= MM_IN_AN_INCH; + radius /= MM_IN_AN_INCH; + setSceneRadius(radius); + vecBanned /= MM_IN_AN_INCH; + } + // create all + gcreateScene(); + gcreateBbox(); + /// z + 10 mm + float dz = 10; + if (!mm) + dz /= MM_IN_AN_INCH; + pprev = pcurr = QVector3D(0, 0, pmax.z()+ dz); + Tool.setUnit(mm); + Tool.setPos(pcurr); + gcreateTool(); + // + setTextIsEnabled(true); + first = true; + itemrec = true; +} + +/// main routine +void Viewer::draw() +{ + if (itemrec) { + // Scene + glCallList(_LSCENE); + // Bounding box + if (withbbox) { + glCallList(_LBBOX); + } + // dimensions text bounding box + drawDimBbox(); + // Tool + if (withtool) { + glCallList(_LTOOL); + } + // define max and min + setSceneBoundingBox (pvmin, pvmax); + if (first) { + set3DView(); + first = false; + } + } +} + +void Viewer::drawDimBbox() +{ + glDisable(GL_LIGHTING); + color= Qt::blue; + glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + QString unit; + QVector3D bpmin(pmin), bpmax(pmax); + uint8_t n; + if (mm) { + unit = " mm"; n = 3; + } + else { + unit = " in"; n = 4; + } + drawText(10, height()-10 , "BoxMin : " + QString().setNum(bpmin.x(), 'f', n) + "/" + + QString().setNum(bpmin.y(), 'f', n) + "/" + + QString().setNum(bpmin.z(), 'f', n) + unit + ); + drawText(10, height()-25, "BoxMax : " + QString().setNum(bpmax.x(), 'f', n) + "/" + + QString().setNum(bpmax.y(), 'f', n) + "/" + + QString().setNum(bpmax.z(), 'f', n) + unit + ); +} + +void Viewer::gcreateScene(int nl) +{ + glNewList(_LSCENE, GL_COMPILE) ; + Scene(nl); + glEndList(); +} + +void Viewer::gcreateBbox() +{ + glNewList(_LBBOX, GL_COMPILE) ; + /// bounding box of items + Box3D box(pmin, pmax, mm, Qt::blue); + box.gdraw3D(); + glEndList(); +} + +void Viewer::gcreateTool() +{ + glNewList(_LTOOL, GL_COMPILE) ; + Tool.setPlane(plane); + Tool.gdraw3D(); + glEndList(); +} + +// slot called by 'ui->doubleSpinBoxTol::valueChanged(double)' +void Viewer::setTolerance(double t) +{ + if (t != tol) { + tol = t; + if (created) { + gcreateScene(); + update(); + } + } +} + +// slot called by 'MainWindow::::setSpeedRateToLine(QList)' +void Viewer::setFeedRateToLine(QList stl) +{ + feedRateToLine = stl ; +} + +// slot called by 'MainWindow::::setSpeedSpindleToLine(QList)' +void Viewer::setSpeedSpindleToLine(QList stl) +{ + speedSpindleToLine = stl ; +} + +// called for Gcode line valid +void Viewer::Scene(int nlColor){ + // + if (items.size() == 0) + return; + // point last + QVector3D plast(items.at(0).x, items.at(0).y, items.at(0).z); + // min and max values + pmin = QVector3D(vmax, vmax, vmax); + pmax = QVector3D(-vmax,-vmax, -vmax); + uint8_t plane(NO_PLANE); + Arc3D arc; + Line3D line; + QVector3D pend, poffset; + /// no path interpolated + posPath = 0; + pathDrawing.clear(); + pointToLine.clear(); + feedRateByLineValid.clear(); + segToLineValid.clear(); + // feedrate + feedrate = prevfeedrate = 0.0; // SPEED_DEFAUL ? + // speed spindle + speedspindle = prevspeedspindle = 0.0; + bool motion; + uint32_t seg = 0; + + /// all items + foreach (PosItem item, items) { + pathItem.clear(); + // unit + mm = item.mm; +//diag("Scene::mm = %s", mm==true?"true":"false"); + pend = QVector3D(item.x, item.y, item.z); + motion = item.g == 0 || item.g == 1 || item.g == 2 || item.g == 3 ; + /// Fxxxx + if (!motion) { + //1- spindle speed + if (item.speedspindle > 0 ) { + speedspindle = item.speedspindle; + /// QMap + speedSpindleByLineValid.insert(item.index, speedspindle); +//diag(" item.index %d -> speedspindle %0.2f", item.index, speedspindle); + } + else + if (item.speedspindle == 0) { + if (prevspeedspindle == 0) + speedspindle = 0; + else + speedspindle = prevspeedspindle; + } + //2- feedrate + if (item.feedrate > 0) { + feedrate = item.feedrate; + /// QMap + feedRateByLineValid.insert(item.index, feedrate); +//diag(" item.index %d -> feedtate %0.2f", item.index, feedrate); + } + else + if (item.feedrate == 0) { + if (prevfeedrate == 0) + feedrate = 0; + else + feedrate = prevfeedrate; + } + + seg = 0; + } + /// Element + else { + if (item.feedrate > 0) + feedrate = item.feedrate; + else + feedrate = prevfeedrate; + /// line G0 fast + if (item.g == 0) { + seg = 1; + if (withg0) { + /// one line + line = Line3D(plast, pend); + if (item.index == nlColor) { + line.setColor(Qt::red); + line.setLineWidth(4); + } + else { + line.setColor(Qt::magenta); + line.setLineWidth(1); + } + /// point min and max + line.MinMax(pmin, pmax); + // feedrate max ?? + line.setSpeed(feedrate); + /// fill list + line.gdraw3D() ; + } + } + else + /// line G1 work + if (item.g == 1) { + seg = 1; + /// one line + line = Line3D(plast, pend) ; + if (item.index == nlColor) { + line.setColor(Qt::red); + line.setLineWidth(4); + } + else { + line.setColor(Qt::darkBlue); + line.setLineWidth(1); + } + /// point min and max + line.MinMax(pmin, pmax); + // feedrate + line.setSpeed(feedrate); + /// fill list + line.gdraw3D() ; + } + else + /// arcs, helix : G2, G3 work + if (item.g == 2 || item.g == 3) // G2, G3 + { + poffset = QVector3D(item.i, item.j, item.k); + /// one arc + plane = item.plane; + arc = Arc3D(plane, item.cw, plast, pend, poffset, 2, item.helix); + /// interpolateSeg with tolerance + seg = arc.interpolateAng(tol, pathItem); + /// point min and max gcodeText.append(line); + arc.MinMax(pmin, pmax) ; + arc.setLineWidth(1); + if (item.index == nlColor) { + arc.setColor(Qt::red); + arc.setLineWidth(4); + } + /// feedrate + arc.setSpeed(feedrate); + /// fill list + arc.gdraw3D(); + } + /// another ... + else { + // spline G5, G5.1, G5.2 ... + } + /// path item + //if (motion) + pathItem.append(pend); + plast = pend; + /// fill list points + foreach(QVector3D p, pathItem) { + /// QList + pointToLine.append(item.index); + /// QList + pathDrawing.append(p); + } + } +//diag(" item.index %d -> seg = %d", item.index, seg); + /// QMap + feedRateByLineValid.insert(item.index, feedrate); + /// QMap + speedSpindleByLineValid.insert(item.index, speedspindle); + /// QMap + segToLineValid.insert(item.index, seg); + prevfeedrate = feedrate ; + prevspeedspindle = speedspindle; + } + /// last number point [0..npointmax] + npointmax = pathDrawing.size()-1; + /// for bounding box + pvmin = qglviewer::Vec (pmin.x(), pmin.y(), pmin.z()); + pvmax = qglviewer::Vec (pmax.x(), pmax.y(), pmax.z()); + pvcenter = (pvmax - pvmin )/2.0; + + /// created scene + created = true; +/* +int u = 0; +foreach (int seg , segToLineValid) +diag("%d -> seg : %d", u++, seg); +*/ +} + +void Viewer::Help3D() +{ + help(); +} + +QString Viewer::helpString() const +{ + QString text("
"); + // text += "
" ; + text += "

V i e w e r 3 D

"; + text += tr("

Version %1

").arg("T4"); + text += tr("by LETARTARE %1").arg("https://github.com/LETARTARE"); + text += tr("

for

%1

").arg(GRBL_CONTROLLER_NAME_AND_VERSION ); + text += QString("ZAPMAKER %1").arg("https://github.com/zapmaker/GrblHoming
"); + + text += tr("
Displays the Path GCode using 'OpenGL'.") ; + text += tr("

Move the camera using the mouse."); + + text += "

"; + return text; +} + +void Viewer::setFrontView() +{ + /// front view (-Z) + camera()->setViewDirection(qglviewer::Vec(0, 0, -1)); + /// directs the scene vertically upwards + camera()->setUpVector (qglviewer::Vec(0, 1, 0)); + // all items + showEntireScene(); +} +void Viewer::setBackView() +{ + /// front view (Z) + camera()->setViewDirection(qglviewer::Vec(0, 0, 1)); + /// directs the scene vertically upwards + camera()->setUpVector (qglviewer::Vec(0, 1, 0)); + // all items + showEntireScene(); +} + +void Viewer::setLeftView() +{ + /// left view (X) + camera()->setViewDirection(qglviewer::Vec(1, 0, 0)); + /// directs the scene vertically upwards + camera()->setUpVector (qglviewer::Vec(0, 1, 0)); + // all items + showEntireScene(); +} +void Viewer::setRightView() +{ + /// right view (-X) + camera()->setViewDirection(qglviewer::Vec(-1, 0, 0)); + /// directs the scene vertically upwards + camera()->setUpVector (qglviewer::Vec(0, 1, 0)); + // all items + showEntireScene(); +} +void Viewer::setTopView() +{ + /// top view (-Y) + camera()->setViewDirection(qglviewer::Vec(0, -1, 0)); + /// sets the scene following the Z axis down + camera()->setUpVector (qglviewer::Vec(0, 0, -1)); + // all items + showEntireScene(); +} +void Viewer::setBottomView() +{ + /// top view (Y) + camera()->setViewDirection(qglviewer::Vec(0, 1, 0)); + /// sets the scene following the Z axis up + camera()->setUpVector (qglviewer::Vec(0, 0, 1)); + // all items + showEntireScene(); +} +void Viewer::set3DView() +{ + /// 3D view (-x, -Y, -Z) + camera()->setViewDirection(qglviewer::Vec(-1, -1, -1)); + /// directs the scene vertically upwards + //camera()->setUpVector (qglviewer::Vec(0, 1, 0 )); + camera()->setUpVector (qglviewer::Vec(-2, 4, -3)); + // all items + showEntireScene(); +} +void Viewer::setVectorUp() +{ + /// directs the scene vertically upwards + camera()->setUpVector (qglviewer::Vec(0, 1, 0)); + // all items + showEntireScene(); +} + +/// T4 +/// display a point mm +void Viewer::setLivePoint(QVector3D xyz, bool /*useMm*/, int nl) /// + bool mm , bool isLiveCP ? +{ + /// tool + if (xyz != vecBanned) { + pprev = pcurr; +//diag("===========> setLivePoint::pprev = %0.2f/%.02f/%0.2f", pprev.x(), pprev.y(), pprev.z() ); + pcurr = xyz; +//diag("===========> setLivePoint::pcurr = %0.2f/%0.2f/%0.2f", pcurr.x(), pcurr.y(), pcurr.z() ); + //Tool.setUnit(useMm); + Tool.setPos(pcurr); + gcreateTool(); + /// scene + if (nl) { + gcreateScene(nl); + } + else { + gcreateScene() ; + } + update(); + } + // display colored line to 'visuGcode' + emit setActiveLineVisuGcode(nl, true); + // display xyz + if (visu || posReqKind == POS_SYNC) + emit updateLCD(pcurr); +} + +void Viewer::setTotalNumLine(QString str) +{ + linecodeTextmax = str.toUInt(); +} + +/// +double Viewer::getFeedRate(int nl) +{ + double s(SPEED_FAST); + if (!mm) + s /= MM_IN_AN_INCH; + if (nl >= 0 && nl <= linecodeTextmax ) { + s = feedRateToLine.value(nl); + } + return s; +} + +/// rpm +double Viewer::getSpeedSpindle(int nl) +{ + double s(0); + if (nl >= 0 && nl <= linecodeTextmax ) { + s = speedSpindleToLine.value(nl); + } + + return s; +} + +/// MainWindow::setActiveLineVisuGcode(int, bool)' -> emit setNumLine(strline); +// receive a line number into 1..linecodeTextmax +void Viewer::setNumLine(QString strline) +{ + int nl = strline.toUInt(); + if (nl != linecodeText) { + feedrate = getFeedRate(nl); + emit setFeedRateGcode(feedrate); + speedspindle = getSpeedSpindle(nl); + emit setSpeedSpindleGcode(speedspindle); + linecodeText = nl; + if (!runcode) { + if (repeatPoint->isActive()) { + repeatPoint->stop(); + } + ptemp = getLastPoint(nl) ; + if (ptemp != vecBanned) { + setLivePoint(ptemp, mm, nl); // item colored in red + } + else { + setLivePoint(pcurr, mm); // item colored normally + } + emit setSegments(getSeg(linecodeText)); + } + /// execute Gcode + else { +//diag("\n"); + if (pointToLine.contains(nl)) { + // stop timer + if (repeatPoint->isActive()) + repeatPoint->stop(); + npmax = pointToLine.count(nl) ; +//diag("nl : %d -> npmax = %d", nl, npmax); + nfirstpoint = pointToLine.indexOf(nl); + pointsItem = pathDrawing.mid( nfirstpoint, npmax); + np = 0; +//diag("nl %d -> speed %0.2f", nl, feedrate); + /// first item point + ptemp = pointsItem.value(np); + QVector3D pc; + float length; + int msec; + // line + if (npmax == 1) { + pc = pcurr; + // total length mm + length = (ptemp - pc).length(); + // mm/S + feedrate /= 60; + // total duration + msec = 1000*(length /feedrate); +//diag("line->nl %d -> length : %5.2f / feedrate %5.2f -> msec %d", nl, length, feedrate, msec); + /// time mini for one segment = 200 mS + float tmini = 200.0; + npmax = msec/tmini; +//diag("==>npmax = %d", npmax); + if (npmax > 1) { + /// remplir poinstItem ; firstp = pcur + dp, lastp = ptemp + pointsItem.clear(); + QVector3D dp = (ptemp - pc)/npmax; + for (int u = 1; u <= npmax; u++) { + ptemp = pc + u*dp ; + pointsItem.append(ptemp); +//diag("==> line->ptemp = %0.2f/%0.2f/%0.2f", ptemp.x(), ptemp.y(), ptemp.z() ); + } + // !! coefficient !! + msec = tmini/5.0; + } + else + npmax = 1; + + emit setSegments(npmax); + /// repeat all msec + repeatPoint->start(msec); + } + // arc + else { + pc = ptemp; + ptemp = pointsItem.value(np+1); +//diag("===> pc = %0.2f/%0.2f/%0.2f", pc.x(), pc.y(), pc.z() ); +//diag("===> ptemp = %0.2f/%0.2f/%0.2f", ptemp.x(), ptemp.y(), ptemp.z() ); + /// a segment length mm + length = (ptemp - pc).length(); + /// mm/S + feedrate /= 60; + msec = 1000*(length /feedrate); + /// coefficient !!! + msec *= 1.5; + //int msec = timeItem(npmax, speed); +//diag("arc->nl %d -> length : %5.2f / feedrate %5.2f -> msec %d", nl, length, feedrate msec); + emit setSegments(npmax); + /// repeat all msec + repeatPoint->start(msec); + } + } + } + } +} + +void Viewer::drawItem() +{ + if (!runcode && repeatPoint->isActive() ) { + repeatPoint->stop(); + } + else + if (np < npmax) { + pp = pointsItem.value(np); + setLivePoint(pp, mm, linecodeText); +//diag("---> pp = %0.2f/%0.2f/%0.2f", pp.x(), pp.y(), pp.z() ); + np++ ; + if (np >= npmax) { + repeatPoint->stop(); + } + } +} +/// TODO ... +float Viewer::timeItem(int np, float speed) +{ + /// path length between two points + float length = np*(pcurr -pprev).length(); + // steps per mm -> 1 step = 0.01 mm + //int stepsPerMm = 100; + //int steps = length * stepsPerMm; + // 1200 mm per mn -> 20 mm per second -> 0.02 mm per mS + float msec = length /speed; + + return msec; +} + +// get last point from line number +QVector3D Viewer::getLastPoint(int nl) +{ + /// verify nl + if (pointToLine.contains(nl)) { + npoint = pointToLine.lastIndexOf(nl); + ptemp = pathDrawing.at(npoint); + } + else { + ptemp = vecBanned; + } + + return ptemp; +} + +// called by 'MainWindow::toVisual(valid)' +// works with line number +void Viewer::setVisual(bool valid) +{ + visu = valid; + if (visu && !linecodeText) { + npoint = -1 ; + linecodeText = 1; + ptemp = getLastPoint(linecodeText); + setLivePoint(ptemp, mm, linecodeText) ; + } +} + +// called by 'MainWindow::toPause(valid)' +void Viewer::setPause(bool valid) +{ + pause = valid; +//diag("Viewer::setPause(%s)", valid==true ?"true":"false" ); + if (visu) { + if (pause) { + repeatVisu->stop(); + } + else { + repeatVisu->start(250); + } + } +} +// works with line number +void Viewer::setPrev() +{ + if (visu && pause) { + if (linecodeText > 1) { + linecodeText--; + /// read one vector + ptemp = getLastPoint(linecodeText) ; + emit setFeedRateGcode(getFeedRate(linecodeText)) ; + emit setSpeedSpindleGcode(getSpeedSpindle(linecodeText)) ; + emit setLineNum(QString::number(linecodeText)); + emit setSegments(getSeg(linecodeText)); + setLivePoint(ptemp, mm, linecodeText); + } + else + if (repeatVisu->isActive()) { + repeatVisu->stop(); + first = true; + } + } +} +// works with line number +void Viewer::setNext() +{ + if (visu && pause) { + if (linecodeText < linecodeTextmax) { + linecodeText++; + /// read one vector + ptemp = getLastPoint(linecodeText) ; + emit setFeedRateGcode(getFeedRate(linecodeText)) ; + emit setSpeedSpindleGcode(getSpeedSpindle(linecodeText)) ; + emit setLineNum(QString::number(linecodeText)) ; + emit setSegments(getSeg(linecodeText)); + setLivePoint(ptemp, mm, linecodeText); + } + else + if (repeatVisu->isActive()) { + repeatVisu->stop(); + first = true; + } + } +} + +uint32_t Viewer::getSeg(int nl) +{ + uint32_t seg(0); + if (segToLineValid.contains(nl) ) + seg= segToLineValid.value(nl); + + return seg; +} + +// called by Timer 'Viewer::repeat' all '250' mS +// works with point number and line number +void Viewer::setVisualAuto() +{ + if (visu && !pause) { + if (firstauto) { + npoint = -1; + firstauto = false; + } + if (npoint < npointmax) { + npoint++; + /// read one vector + ptemp = pathDrawing.at(npoint) ; + linecodeText = pointToLine.at(npoint); + emit setFeedRateGcode(getFeedRate(linecodeText)) ; + emit setSpeedSpindleGcode(getSpeedSpindle(linecodeText)) ; + emit setLineNum(QString::number(linecodeText)) ; + emit setSegments(getSeg(linecodeText)); + setLivePoint(ptemp, mm, linecodeText); + } + else + if (repeatVisu->isActive()) { + repeatVisu->stop(); + first = true; + firstauto = true; + /// run visu -> pause visu + emit setPauseVisual(true); + } + } +} + +// called by 'MainWindow::begin()' : emit runCode(true); +// called by 'MainWindow::stop()' : emit runCode(false); +void Viewer::runCode(bool run, int posreqkind) +{ +//diag("runCode : %s", run==true ? "true" : "false"); + runcode = run; + posReqKind = posreqkind ; + if (runcode && repeatVisu->isActive()) { + repeatVisu->stop(); + firstauto = true; + } +} + +void Viewer::setPeriod(int p) +{ + if (p > 100 && p <= 1000) + repeatVisu->setInterval(p) ; +} + +void Viewer::noTool() +{ + withtool = false; +} + +void Viewer::miniTool() +{ + Tool.setTool(Tools3D::_MINI); + withtool = true; + gcreateTool(); +} + +void Viewer::hemiTool() +{ + Tool.setTool(Tools3D::_HEMI); + withtool = true; + gcreateTool(); +} + +void Viewer::rightTool() +{ + Tool.setTool(Tools3D::_RIGHT); + withtool = true; + gcreateTool(); +} + +void Viewer::sharpTool() +{ + Tool.setTool(Tools3D::_SHARP); + withtool = true; + gcreateTool(); +} + +void Viewer::shortTool() +{ + Tool.setTool(Tools3D::_SHARP_SHORT); + withtool = true; + gcreateTool(); +} + +void Viewer::setTool(bool with) +{ + withtool = with; + update(); +} + +void Viewer::setBbox(bool with) +{ + withbbox = with; + update(); +} + +void Viewer::setG0(bool with) +{ + withg0 = with; + if (created) { + gcreateScene(); + update(); + } +} +/// T4 +/// display a point, relative mode +void Viewer::setLiveRelPoint(QVector3D dxyz, int nl) /// + bool mm , bool isLiveCP ? +{ + /// tool + if (dxyz != vecBanned) { + pprev = pcurr; +//diag("setLiveRelPoint::pprev = %0.2f/%.02f/%0.2f", pprev.x(), pprev.y(), pprev.z() ); + pcurr += dxyz; +//diag("==============> setLiveRelPoint::pcurr = %0.2f/%0.2f/%0.2f", pcurr.x(), pcurr.y(), pcurr.z() ); + Tool.setPos(pcurr); + gcreateTool(); + /// scene + if (nl) { + gcreateScene(nl); + } + else { + gcreateScene() ; + } + update(); + } + // display colored line to 'visuGcode' + emit setActiveLineVisuGcode(nl, true); + // display xyz + if (visu || posReqKind == POS_SYNC) + emit updateLCD(pcurr); +} + +///----------------------------------------------------------------------------- diff --git a/GCV-3.6.1-T4/src/visu3D/viewer3D.h b/GCV-3.6.1-T4/src/visu3D/viewer3D.h new file mode 100644 index 0000000..a9573f4 --- /dev/null +++ b/GCV-3.6.1-T4/src/visu3D/viewer3D.h @@ -0,0 +1,161 @@ +/*************************************************************** + * Name: viewer3D.h + * Purpose: + * Author: LETARTARE + * Created: 2014-20-06 + * Copyright: LETARTARE + * License: GPL + **************************************************************/ +#ifndef VIEWER3D_H +#define VIEWER3D_H + +#include +/// T4 +#include +#include +#include "Tools3D.h" + +#include "positem.h" + +class Viewer : public QGLViewer +{ + Q_OBJECT +public : + enum glist {_LSCENE=1000, _LBBOX, _LTOOL}; + + Viewer(QWidget *parent); + virtual void init(); + +protected : + + virtual void draw(); + + double getFeedRate(int nl); + double getSpeedSpindle(int nl); + uint32_t getSeg(int nl); + +signals: + void updateLCD(QVector3D); + void setActiveLineVisuGcode(int, bool); + void setPauseVisual(bool); + void setLineNum(QString); + void setFeedRateGcode(double); + void setSpeedSpindleGcode(double); + void setSegments(int); + +public Q_SLOTS: + + void set3DView(); + void setFrontView(); + void setBackView(); + void setLeftView(); + void setRightView(); + void setTopView(); + void setBottomView(); + void setVectorUp(); + + void Help3D(); + + void setItems(QList); + +/// T4 + void setLivePoint(QVector3D xyz, bool useMm=true, int nl=0); + void setLiveRelPoint(QVector3D dxyz, int nl=0); +///<- + void setTool(bool=false); + void setBbox(bool=false); + void setG0(bool=false); +/// animator + void setVisual(bool); + void setPause(bool); + void setPrev() ; + void setNext() ; + void setVisualAuto(); + void setNumLine(QString); + void setTotalNumLine(QString); + void setFeedRateToLine(QList); + void setSpeedSpindleToLine(QList); + void runCode(bool, int) ; + + void drawItem() ; + float timeItem(int nl, float f) ; + /// + void noTool() ; + void miniTool(); + void hemiTool(); + void rightTool(); + void sharpTool(); + void shortTool(); + + void setPeriod(int); + void setTolerance(double); + +private: + +/// fonctions + virtual QString helpString() const; + /// create Gl list + void gcreateScene(int=0); + void gcreateTool() ; + void gcreateBbox() ; + // objets draw + void Scene(int nlColor=0); + /// bounding box + void drawDimBbox(); + void MinMax(QVector3D); + + QVector3D getLastPoint(int) ; + void getPoints(int nl) ; + +/// attributs + QWidget * parent; + float radius ; + // tolerance + double tol; + bool mm; + uint8_t plane; + bool itemrec, withtool, withbbox, withg0, created, first; + + // scene size max + uint16_t vmax ; + // vectors + QVector3D vecBanned, phome; + QVector3D pmax, pmin, pcurr, pprev, ptemp, pp; + qglviewer::Vec pvmax, pvmin, pvcenter; + Tools3D Tool; + // positions + PosItem livePoint; + QList items; + + int linecodeText, linecodeTextmax; + + // paths + QList pathItem, pointsItem; + QList pathDrawing; + QList pointToLine; + QList feedRateToLine; + QList speedSpindleToLine; + QMap segToLineValid; + QMap feedRateByLineValid; + QMap speedSpindleByLineValid; + + /// line -> pathDrawing + int posPath ; + // motor steps + QList stepsItem; + QList stepsComplete; + + QColor color; + + // animator + bool visu, pause, runcode, firstauto; + int npoint, npointmax, np, npmax,nfirstpoint, nlastpoint ; + QTimer * repeatVisu; + QTimer * repeatPoint; + // from PosItem + float feedrate, prevfeedrate ; // mm per mn + float speedspindle, prevspeedspindle; // turn per minute + // mode request display + int posReqKind ; +}; +#endif diff --git a/GCV-3.6.1-T4/src/wininfoafter.txt b/GCV-3.6.1-T4/src/wininfoafter.txt new file mode 100644 index 0000000..ab64a5b --- /dev/null +++ b/GCV-3.6.1-T4/src/wininfoafter.txt @@ -0,0 +1 @@ +Thanks! Please visit www.zapmaker.org to give feedback. \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/wininfobefore.txt b/GCV-3.6.1-T4/src/wininfobefore.txt new file mode 100644 index 0000000..a28c537 --- /dev/null +++ b/GCV-3.6.1-T4/src/wininfobefore.txt @@ -0,0 +1,7 @@ +GrblController 3 - Control your Grbl Arduino and other basic CNC 3-axis systems. + +Installs a EXE file and support DLLs that communicate via COM port to Grbl Arduino using GCode. + +by Zapmaker + +Released under GPL 3.0 \ No newline at end of file diff --git a/GCV-3.6.1-T4/src/winlicense.txt b/GCV-3.6.1-T4/src/winlicense.txt new file mode 100644 index 0000000..720cb46 --- /dev/null +++ b/GCV-3.6.1-T4/src/winlicense.txt @@ -0,0 +1,3 @@ +GrblController + +The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. \ No newline at end of file diff --git a/GCV-3.6.1-T4/translate.bat b/GCV-3.6.1-T4/translate.bat new file mode 100644 index 0000000..e19fc59 --- /dev/null +++ b/GCV-3.6.1-T4/translate.bat @@ -0,0 +1,8 @@ +rem translate.bat +rem by LETARTARE + +cd src + +translate.bat + + diff --git a/GCV-3.6.1-T4/winexe/GCV-3.6.1-T4-cb.jtgcv b/GCV-3.6.1-T4/winexe/GCV-3.6.1-T4-cb.jtgcv new file mode 100644 index 0000000..2a87f9f Binary files /dev/null and b/GCV-3.6.1-T4/winexe/GCV-3.6.1-T4-cb.jtgcv differ diff --git a/QextSerialPort/qextserialport.pri b/QextSerialPort/qextserialport.pri deleted file mode 100644 index 007fa3a..0000000 --- a/QextSerialPort/qextserialport.pri +++ /dev/null @@ -1,60 +0,0 @@ -exists(../common.pri) { - #For case: - # someone want to copy all file in the src/ directory - # to their project src/ directory and they does not like - # the common.pri file. - #In this case: - # they can just include this file (qextserialport.pri) too. - include(../common.pri) -} -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - -qextserialport-library:!qextserialport-buildlib { - # Using QextSerialPort as shared or static library. - LIBS += -L$$QEXTSERIALPORT_LIBDIR -l$$QEXTSERIALPORT_LIBNAME - !qextserialport-static: DEFINES += QEXTSERIALPORT_USING_SHARED -} else { - # Building library(shared or static) - # or including source files - HEADERS += $$PWD/qextserialport.h \ - $$PWD/qextserialport_p.h \ - $$PWD/qextserialenumerator.h \ - $$PWD/qextserialenumerator_p.h \ - $$PWD/qextserialport_global.h - SOURCES += $$PWD/qextserialport.cpp \ - $$PWD/qextserialenumerator.cpp - unix { - SOURCES += $$PWD/qextserialport_unix.cpp - linux*:!qextserialport-no-udev { - SOURCES += $$PWD/qextserialenumerator_linux.cpp - } else:macx { - SOURCES += $$PWD/qextserialenumerator_osx.cpp - } else { - SOURCES += $$PWD/qextserialenumerator_unix.cpp - } - } - win32:SOURCES += $$PWD/qextserialport_win.cpp \ - $$PWD/qextserialenumerator_win.cpp - - # For Windows user who doesn't have Qt4's Private files - win32:contains(QT_VERSION, ^4\\..*\\..*):!exists($$[QT_INSTALL_HEADERS]/QtCore/private/qwineventnotifier_p.h){ - DEFINES += QESP_NO_QT4_PRIVATE - HEADERS += $$PWD/qextwineventnotifier_p.h - SOURCES += $$PWD/qextwineventnotifier_p.cpp - } - - # For building shared library only - qextserialport-buildlib:contains(TEMPLATE, .*lib):contains(CONFIG, shared){ - DEFINES += QEXTSERIALPORT_BUILD_SHARED - } - - linux*:qextserialport-no-udev:DEFINES += QESP_NO_UDEV -} - -macx:LIBS += -framework IOKit -framework CoreFoundation -win32:LIBS += -lsetupapi -ladvapi32 -luser32 -linux*:!qextserialport-no-udev: LIBS += -ludev - -# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work -linux*:DEFINES += __linux__ diff --git a/README b/README index 854c482..38ef1ee 100644 --- a/README +++ b/README @@ -1,367 +1,124 @@ - ---- GrblController ---- - -GrblController is a gcode sender, monitor and homing tool for GRBL for -Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. - -Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this -project. - -Version 3.0 is a near-complete rewrite of the C++ code fixing all known bugs. -The other major enhancement is native Mac OSX support (including older 32 bit Intel 10.5). - -The code was tested with real milling projects using the Shapeoko and works -pretty well. For a list of possible future enhancements, see file TODO. - -Prebuilt binaries/installers can be found on github's download section for this -project (GrblHoming). Alternately, if you download the (a) Qt SDK from Nokia or -(b) the Qt source from Qt Project along with the standalone Qt Creator, you can -build from source. - -Details on how to do this can be found here: -http://zapmaker.org/ - -V3.4.3 -Bug fix -- Unsupported G43/G44 commands include following Z command which causes problems when - left standalone. The entire line must be removed. -- Now treat M2 and M30 as unsupported as they cause grbl lockup when using aggressive - preloading. -- Moved program version define into its own header file so fewer files need recompiling - with a version change. - -V3.4.2 -Bug fix -- If a gcode command line is an arc with X,Y,Z and z-rate limiting enabled, fixed to - properly split the z rate to not use the G2 command and use G1 instead as grbl - was generating an error with the G2. - -V3.4.1 -Code sync -- Fixes to code now allows code to compile under Qt5 without error and also resolves - some localization issues. Continues to properly compile under Qt4 also. No normally - noticable functional differences. - -V3.4 -Enhancements -- Z-axis slider now allows rapid control of Z-axis positioning. This feature is still - being evaluated for proper behavior due to some user-interface issues. - If you run into trouble, please report a bug. -- All axis control buttons have been permanently enabled regardless of whether or not an - axis command is in progress - this allows more rapid updating. Note - there is no error - checking for the case of entering too many commands for the Grbl buffer. This is unlikely - but possible. -- Now supports setting of baud rates from 9600 to 115200 -- Aggressive preload enabled is now the default. If the user upgraded from an older - Grbl Controller and had it disabled, a popup will warn them that it is being enabled. - They still have the option to disable, if desired -- Logging is turned on by default (only for new installs) -- All detected errors are collected and displayed after a file is run in the status view -- If filtering unsupported commands, all commands filtered out are listed after the file - is run. -- Logging now gives the line number of each command sent from the file and the corresponding - ok or error also contains the line number. -- An option has been provided to reduce the precision of lines that exceed Grbl's line buffer, - which by default is 50 characters. The code removes the arguments with the greatest precision - first and ending with at least one decimal place of precision. Errors are generated if it - cannot remove sufficient precision for the available buffer space. The buffer size on Grbl - is configurable in the options, as older Grbls have 50 characters and newer have 70. - -Bug Fixes -- If Grbl stops responding (waiting for an ok), Soft Reset Grbl now functions correctly - (so you can soft reset without having to restart Grbl Controller). This affects aggressive - preload mode only. -- Commands to start/stop coolant coupled with dwell commands and aggressive preload cause - Grbl's modal logic to stop sending OK responses (on purpose). This was solved by waiting - for the OK of the coolant off before sending additional commands. It is not clear whether - this fixes all possible such modal problems, so use carefully and report any anomalies. - -V3.3.9 -Enhancement -- We now are able to remember and restore ports that are not visible to QextSerialEnumerator - so that user doesn't have to retype the ghost port every time they start Grbl Controller. - -V3.3.8 -Enhancement/Fix -- Modified code that detects presence of Grbl upon serial port opening, the original - assumption was that we would get the version string upon serial port open, but some - Arduino-compatible boards like the AlaMode did not behave this way. Fixed the code - so that if there is no response upon serial port open, we send a soft reset (Ctrl-X) - and wait for the version string. Tested to work with AlaMode and with traditional - Ardiuno Uno. - -V3.3.7 -Enhancement -- Made COM port field editable - -V3.3.6 -Bug Fixes -- Fixed decimal on the LCD display to always show three decimal points so that - it is easier to read the display (it doesn't jump around anymore). Tested to - hold up to 9999.999 and -9999.999, which should handle 20 x 20 meter Shapeokos. - -V3.3.5 -Bug Fixes -- Changed how we detect Grbl upon opening on COM port. - ** NOTE ** This change will probably break older V0.51 capability - Previously we sent out a linefeed to trigger a response, however, this caused problems - on some arduino variants and would not result in correct sync with the controller. - Fixed by no longer sending the linefeed and instead just watch the port for Grbl response. -- Changed the default "short" wait timeout to 2 seconds from 1 second in case of slow responses. - -V3.3.4 -Enhancements -- Added option checkbox to choose to filter gcode or send it as-is to the controller. The - filtering removes gcode that is not supported in v0.8 of Grbl, which reduces the error - reports from Grbl. Some files generate unexpected codes like G91.1 which can actually - affect the motion in unexpected ways- filtering helps prevent this from happening. - - IMPORTANT: The default is to not filter, which is different than previous versions! This - may result in unexpected command processing. If using advanced gcodes, perform an air run - first. - -Bug Fixes -- Mach3 files have no whitespace in the gcode. Fixed code to handle such files. Affects - the Visualizer only. -- The filtering logic was fixed to properly filter gcode when sending a file - previous - versions would filter out gcode that Grbl supported. -- Changed validator for double (i.e. float) values so that code compiles under older Qt - versions. -- Changed Visualizer display to say Width-X and Height-Y instead of Width and Depth to make - it less confusing. - -V3.3.3 -Bug Fix -- Modal G arc (where G2 or G3 is specified once followed by X/Y/I/J) was failing for certain - arc combinations in the visualizer due to resetting the cw to false with each line. Fixed - to not reset the cw variable and retain from previous lines. - -V3.3.2 -Bug Fix -- G-command can now be set once and multiple X/Y commands then issued on lines following - (Allows "ShapeOko_Calibration_Pattern_01b.ngc to be rendered) - -V3.3.1 -Bug Fixes -- Hardened the visualizer's file parser so that it supports spaces between positional - arguments and values -- No longer skips last line in file if that line contains a valid command -- No longer crashes if line contains one or more stray whilespace characters -- Also accepts semi-colon as a comment line (in addition to existing open paren and percent) - -V3.3 -Enhancemetns -- Added "Visualizer" feature. It is now possible to see top-down view of the - file to be milled. - * Shows actual file units (inches or millimeters) independent of coordinate display - * Auto-scaling - * Supports limited subset of commands (G0/G1/G2/G3) - * Visualizer on tab panel shared with Axis control - * Actual last spindle cutter position is shown; auto-scales to include both cutter - and file - * When file is being run, overlay of all commands sent to Grbl is shown in green - * Displays dimensions of design, along with design's width and depth in file's units - -V3.2 -Enhancements -- Support for "Aggressive Preload" of commands when sending file to Grbl - * File's lines are sent to Grbl as fast as Grbl can take it, allowing - Grbl to optimize acceleration. Some files have been observed to take - 1/3 the time to complete! - * Modeled after Grbl's own python script (computes/predicts how much - space is available in Grbl's input buffer) - * Due to the additional processing, CPU usage is greater than normal mode - and it has been optimized to run fine on a Raspberry Pi - * Normal (non-preload) mode is the default - * Response processing code now waits until a line has been received rather - than collect a long stream to behave like the python script - * LCD updates have been set to be roughly once every second independent - of rate of line sends/preloads -- Z-rate limit feature now includes default xy rate setting - * Z rate limiting only occurs during file sends. If z is included with x&y - then they are split into two commands automatically and the xy rate setting - is used for the xy portion - * Since feed rate is modal, code will fix any subsequent xy items that are - missing feed rate specifiers (cambam correctly adds them, but others may not) -- Replaced basic logging with Log4Qt logging capabilities. - * Support for error, warning, info, debug message types. All messages are timestamped. - * More diagnostic messages added, mainly around sending and receiving from com ports - * Only error and warning are displayed in release build, all are displayed in debug. - * If the user enables file logging, all messages are stored regardless of build type - * File is output to user's home folder - * If you enable or disable logging to file, you must restart Grbl Controller - * You can split out diagnostic from status messages by grepping for (DIAG) or (STATUS) -- Changed menus so that the first menu is File > Exit. Menus now use accelerators - -Bug Fixes -- Fixed problems with z-rate limit feature, previous version was not implemented correctly. -- Fixed subtle issues with sending bytes to COM port - * On really fast Windows PCs, the default timeout values would occasionally result in - a line not being sent. This was fixed by changing the write timeout from 10 to - 500 ms by hardcoding it into the QextSerialPort library. This was only observed in - aggressive preload mode, never in normal mode. - -Known issues -- New reponse line detect mode requires more processing because mainly of the faster - stream of status messages. To get around this, certain features have been disabled - in the status view so that CPU usage is manageable on the Raspberry Pi, specifically - the horizontal scroll bar is not available. Turn on file logging if you wish to see - the entire line. -- When using aggressive preload, any error messages returned by Grbl are not synced - to sent messages (they come back randomly). This can be confusing. -- If running preload, it can take longer for steppers to stop after a Stop command - due to the number of items in Grbl's queue. The only way to stop sooner is to - press Close / Reset button -- Under exteme CPU loads (unlikely to occur with recent optimizations), the "runtime" - display does not display accurate times, oddly, it displays the same time that would - occur if not under load - -Tested on cardboard using file provided by user: -- Windows 7 64bit, 0.8c, aggressive mode (~4 minute run) -- Windows 7 64bit, 0.8c, normal mode (~10 minute run) -- Windows 7 64bit, 0.8a, aggressive mode(~4 minute run) -- Raspberry Pi, 0.8c, aggressive mode (~4 minute run) -- Raspberry Pi, 0.8c, aggressive mode and z-limit (~6 minute run) - -V3.1.2 (unofficial release, optimizations for Raspberry Pi) -Enhancements -- Optimized multiline write to status window to use faster list-based approach -- Removed unnecessary main window repaint after every line added to status window -- Fixed options window text positioning so that it appears proper on the pi - -V3.1.1 (unofficial release, adjustments for Raspberry Pi) -Enhancements -- Changed measurement units in LCD from "inches" to "in" (cosmetic) -- Shortened text and adjusted main window layout for the text size on the pi - -V3.1 -Enhancements -- Supports Grbl 0.8c. Still supports 0.8a. 0.51 is supported but without LCDs. -- Grbl settings dialog is now a table of dynamic length depending on # of params. -- LCD position data is now obtained from Grbl and is *not* computed -- Added LCD displays for both machine and work coordinates -- Cycling of Grbl via COM port toggling has been completely removed, except - that Close button has now been renamed Close / Reset. -- Position data on Grbl is persisted as long as possible to allow for repositioning, etc. -- Zero work coordinates has been added (G92) -- Go-to-home feature added (lifts tool 5 mm and traverses to x=0, y=0) -- Option to put manual command (back) into absolute mode after jog button command -- Grbl Soft reset (Ctrl-X) button added -- Z-axis rate limiting capability added. Only affects file, not jog or manual commands. -- User is required to specify which measurement mode they are using, mm or inches: - * Default is millimeters - * Grbl is configured to operate in either mm or inches - * If a file is sent in inches and user is in mm, it will auto-restore to mm - after the file has been sent (and vice-versa, mm->inches) -- 0.8c enhancements: - * Displays current Grbl state (i.e. Run, Idle, etc.) - * LCDs display whether values are in inches or millimeters - * Unlock Grbl button added ($X) - * Determines and sets parser state for current mm/inch command mode ($G) - * Determines and sets coordinate units via $13 -- Removed annoying "No movement expected for command" message -- Flags that cross threads have been changed to use QAtomicInt -- Version is now shown in title bar -- A basic log file feature has been added -- Runs on the Raspberry Pi! - -Known Issues -- The registry key product name has been changed from GCodeSender to GrblController - *** WARNING: Old settings are not migrated **** -- Switching between millimeters and inches works, but has not been fully tested -- Go to home has not been fully tested with inches mode -- Manually issuing $13 or G20/G21 can confuse the program - -V3.0 -Enhancements -- Nearly a full code rewrite to ensure ease-of-use and robustness -- Percentage complete progress bar for files; also shows time elapsed sending file. -- Reset button now cycles COM port which causes Arduino to stop steppers and - reinitialize position to 0,0,0 (No more manual Auduino resets!) -- Settings configurations are now stored using QSettings class for platform independence. -- Only available COM ports are now shown. Uses third-party QextSerialPort library. -- App remembers last COM port used, last folder, last file extension used after restart -- Ability to configure wait-for-response time -- Status list window now shows both sent and received data -- Error responses are ignored during file send (nearly 100% of the time they are not important) -- Z-jog speed using buttons is configurable -- Radio buttons to select mode have been removed in favor of enabling/disabling widgets based - on current context. This simplifies usage. -- Popups have been removed in favor of writing errors to status list window - -Bug fixes -- Overall code hardening -- Properly implementing Qt signals and slots across the board - -Build verification -- Windows 7 64 bit using MinGW -- Inno Setup for Windows, installs successfully on Windows 7 -- Mac OSX Mountain Lion, target 64 bit and 32 bit executables -- Qt Mac installer successfully installs and runs on Mountain Lion and 10.5 32 bit Intel -- Linux: Builds successfully on Debian 6, Ubuntu 12.10 - -V2.1x1 - -NOTE: Changes were only focused on Arduino GRBL capabilities with the Shapeoko, so -things like Tool Change were not tested. - -Enhancements -- Improved handling of response code - this is the most significant change as it -ensures reliable send/response handling when sending a file to the Grbl processor. -- Manual command now allows hitting return and command is sent. No need to press Go. -- Default job step size changed from 0.01 to 1 mm -- Compiles and runs under Linux now (tested with Debian and latest Qt) -- Works with old 168 Arduino processor (except that old code is buggy and not recommended) -- Disabled "go to home at end of job". The arduino code doesn't handle it correctly -and mills straight back into and through your work. Checkbox in settings has no effect. - -Bug fixes -- Fixed crash when options file is not present the first time run -- Fixed crash when trying to get GRBL settings from device -- Settings work with 168 (8 settings) and 328 processors (10 settings) -- Fixed Stop to call proper routine stopsig - now Stop button works correctly - -------------------------------------------------------------- -Fork by Zapmaker at this rev -------------------------------------------------------------- -v2.1a - -Bug fixes - -- Corrected an issue that caused the program to crash if the g-code had blank lines. - -V2.1 - -New Features - -- Gcode that is valid but is not recognized by GRBL gets filtered and it is not sent. - -Bug fixes - -- Corrected an issue that prevented manually sent Gcode for being displayed correctly. -- Corrected an issue with the images not displaying. - -V2.0 Major release - -- Improved the port handling reducing opening and closing frecuency. -- Added the ability to type and send commands directly. -- Support for tool change instructions. If enabled it pauses execution, raises the spindle, goes to a fixed location for toolchange, waits for tool change, and continues excecution. -- Added About window. - -V1.0c Minor - -Bug fixes - -- Corrected a problem when adjusting axis that caused all axis to move at the same time. Caused by grbl starting in incremental programming. - -V1.0b Minor - -Bug fixes - -- Corrected a bug in the adjusting script. - -V1.0a Minor - -Bug fixes - -- Fixed a bug reading some file formats that avoided the dials from updating. - + ---- GrblController ---- + +GrblController is a gcode sender, monitor and homing tool for GRBL for +Mac, Windows and Linux systems written using the Qt Desktop Framework in C++. + +Enhanced by Zapmaker. Kosme did a great deal of excellent foundation work on this +project. + +Details on how to do this can be found here: +http://zapmaker.org/ + +-------------------------------------------------------------------------------- +GCV : Grbl Controller Visualizer is a 3D extension of GrblController-3.6.1 +-------------------------------------------------------------------------------- + +GCV-3.6.1-T4 Grbl Controller Visualizer (LETARTARE proposals August 22, 2014) + +An executable 'Win32' into 'winexe/GCV-3.6.1-T4-cb.jtgcv'. +This is a file Win32 compressed, change the extension 'jtgcv -> 7z' to decompress. + +* 3.6.1-T3 + + +1- Analyzes the gcode with 4 axes X, Y, Z, T ( fourth axis ), +2- New display console ('Console') commands, with the ability to copy, delete + text part, delete the selected (or all) text, print the selected (or all) text +3- Display speed rate XYZ with 'Lcd', display last spindle speed, +4- Visualizes the 'Gcode' XYZ 3D with motion mouse : + - A help button to explain the multiple possible actions on the drawing, + by utilsation keyboard and mouse, + - You can see it or not the box limits the drawing, + - Choosing a particuler tool, + - Different views are available by buttons, + - Display axes oriented, + - Display a grid in the XY plane, + - Choice of deleting lines G0. + +5- Animation 3D XYZ axes, regardless of the connection : + - When loading a file, you can read its contents in the console 'Visual', + which will launch the manual or automatic animation, + - In manual mode you can use the mouse to select a line of code or the + navigation buttons or sliders keyboard arrows, + - In automatic mode has a period setting reading 'Gcode', + +6- In addition to the periodic polling of 'Grbl', a new method is proposed + EXPERIMENTAL display named 'Synchronous simulation' based on motion prediction, + - This mode is for use rather large arcs or helical path, + - It does not work with manual controls, + - It is accessed via 'Tools->Options->Display->Synchronous simulation', + +7- The visual presentation of 'GCV' has been modified : + - a flip button to pause and resume sending gcode file at the end of the current + line, will send to 'Grbl', + - buttons for Grbl commands grouped with console, + - manual controls axes (jog) are grouped next to the display positions : + - the incremental value step manual controls is defined by a slide + and a display, and can be adjusted finely by keyboard keys, + - homing new buttons for each axis, + - homing new button for all axes, + - the feed rate movement is displayed during, + - the last spindle speed is displayed, + +8- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, 0.9f, the last 0.9g + 2- Four axes 0845, 0.8c1, 0.8c2 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c2Mega2560 + +- KNOWN BUGS + - In the mode 'Check', it does not use the command line to send '$C' + - The mode 'Simulation synchronous' does not work in manual controls + - If no file is loaded, the manual controls do not support the visualization tool + - ... + + +-------------------------------------------------------------------------------- +Fix old bug to T1, T2, T3 (July 7, 2014) + +V3.6.1-T3 (LETARTARE proposals June 06, 2014) + +* 3.6.1-T2 + + +1- complete analysis of the Grbl version for 0.8cx versions +2- use 'Check' Grbl mode "$C" +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + +-------------------------------------------------------------------------------- + +V3.6.1-T2 (LETARTARE proposals June 03, 2014) + +* 3.6.1-T1 + + +1- Display Grbl version bottom right of the window (Firmware : Grbl 0.8c) +2- displays the total number of lines of loaded file, on the line runtime (Lines : 1245) +3- Displays the current line of the file read, on the line runtime (Lines : 150/1245) +4- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, 0.8c1 (0.8c to 4 axes) with MEGA2560 + https://github.com/LETARTARE/Grbl-xx_with_Arduino/tree/master/Grbl8c1Mega2560 + +-------------------------------------------------------------------------------- + +V3.6.1-T1 (LETARTARE proposals June 01, 2014) + +- 3.6.1 + +1- Improved to the same card 3 and 4 axis detection +2- Displays the line numbers of the file if no number exists +3- Updating of the French translation + +- Works with versions Grbl : + 1- Three axes 0.8c, 0.9d, 0.9e, + 2- Four axes 0845, future 0.8c1 (0.8c to 4 axes) + +-------------------------------------------------------------------------------- + + + diff --git a/coord3d.cpp b/coord3d.cpp deleted file mode 100644 index 6198f0d..0000000 --- a/coord3d.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "coord3d.h" - -Coord3D::Coord3D() - : x(0.0), y(0.0), z(0.0), stoppedZ(true), sliderZIndex(0) -{ -} - -bool Coord3D::operator==(const Coord3D& rhs) -{ - return (x == rhs.x && y == rhs.y && z == rhs.z); -} diff --git a/grbldialog.ui b/grbldialog.ui deleted file mode 100644 index 900ad7b..0000000 --- a/grbldialog.ui +++ /dev/null @@ -1,60 +0,0 @@ - - - GrblDialog - - - - 0 - 0 - 489 - 378 - - - - Grbl Settings - - - - - 400 - 20 - 75 - 23 - - - - Apply - - - - - - 400 - 60 - 75 - 23 - - - - Close - - - - - - 10 - 20 - 371 - 341 - - - - 2 - - - - - - - - diff --git a/mainwindow.ui b/mainwindow.ui deleted file mode 100644 index 55c2413..0000000 --- a/mainwindow.ui +++ /dev/null @@ -1,1316 +0,0 @@ - - - MainWindow - - - true - - - - 0 - 0 - 838 - 651 - - - - - 7 - 0 - - - - - 10000000 - 10000000 - - - - Grbl Controller - - - - - - - - - 418 - 30 - 191 - 131 - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - 390 - 30 - 20 - 131 - - - - - - - - 18 - - - - X - - - Qt::AlignCenter - - - - - - - - 18 - - - - Y - - - Qt::AlignCenter - - - - - - - - 18 - - - - Z - - - Qt::AlignCenter - - - - - - - - false - - - - 20 - 360 - 341 - 231 - - - - - - false - - - - 20 - 120 - 341 - 161 - - - - Send File - - - - - 10 - 20 - 321 - 62 - - - - - - - - - - Begin - - - - - - - Stop - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Choose file - - - - - - - - - 10 - 90 - 321 - 23 - - - - 0 - - - - - false - - - - 20 - 130 - 61 - 16 - - - - Runtime: - - - - - false - - - - 90 - 130 - 61 - 16 - - - - - - - - - - false - - - - 700 - 490 - 121 - 61 - - - - GRBL settings - - - - - false - - - - 20 - 290 - 341 - 61 - - - - Manual GCode - - - - - 10 - 20 - 321 - 31 - - - - - - - Command - - - Qt::AlignCenter - - - - - - - - - - - - - - - - - 20 - 50 - 101 - 21 - - - - Open - - - - - - 20 - 10 - 341 - 31 - - - - - 0 - - - - - - 0 - 0 - - - - - 80 - 16777215 - - - - Port name - - - - - - - - 0 - 0 - - - - - 220 - 0 - - - - true - - - - - - - - - 620 - 30 - 191 - 131 - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 50 - false - true - - - - true - - - 7 - - - QLCDNumber::Filled - - - - - - - - - 380 - 470 - 161 - 91 - - - - Reset Control - - - - - 10 - 20 - 141 - 66 - - - - - - - Soft Reset Grbl - - - - - - - Unlock Grbl - - - - - - - - - - 420 - 0 - 191 - 31 - - - - - - - Machine Coordinates - - - - - - - - - - - - - - - - 620 - 0 - 201 - 31 - - - - - - - Work Coordinates - - - - - - - - - - - - - - - - 160 - 90 - 201 - 31 - - - - - - - Last State: - - - - - - - - - - - - - - - - 550 - 490 - 141 - 71 - - - - - - - - 11 - - - - false - - - Zero Position - - - - - - - Go Home - - - - - - - - - 380 - 180 - 441 - 281 - - - - 0 - - - - Axis Control - - - - - 20 - 20 - 214 - 120 - - - - - - - - - - - :/img/up.PNG:/img/up.PNG - - - - 24 - 24 - - - - - - - - Qt::Vertical - - - - 18 - 17 - - - - - - - - - - - - :/img/left.PNG:/img/left.PNG - - - - 24 - 24 - - - - - - - - - - - - :/img/down.PNG:/img/down.PNG - - - - 24 - 24 - - - - - - - - - - - - :/img/right.PNG:/img/right.PNG - - - - 24 - 24 - - - - - - - - - - 330 - 10 - 70 - 132 - - - - - - - - - - - :/img/up.PNG:/img/up.PNG - - - - 24 - 24 - - - - - - - - - 10 - 75 - true - - - - Z Jog - - - Qt::AlignCenter - - - - - - - - - - - :/img/down.PNG:/img/down.PNG - - - - 24 - 24 - - - - - - - - - - 320 - 170 - 101 - 52 - - - - - - - Step Size - - - - - - - - - - - - 20 - 170 - 281 - 61 - - - - - - - Absolute coordinates after adjust - - - - - - - Spindle On - - - false - - - - - - - - - 270 - 10 - 19 - 101 - - - - 80 - - - 40 - - - 40 - - - Qt::Vertical - - - false - - - false - - - QSlider::TicksBelow - - - - - - 260 - 130 - 46 - 13 - - - - 0 - - - Qt::AlignCenter - - - - - - 260 - 150 - 46 - 13 - - - - 0 - - - Qt::AlignCenter - - - - - - Visualizer - - - - - -1 - -1 - 437 - 259 - - - - - - - - - 255 - 255 - 255 - - - - - - - 244 - 237 - 187 - - - - - - - - - 255 - 255 - 255 - - - - - - - 244 - 237 - 187 - - - - - - - - - 244 - 237 - 187 - - - - - - - 244 - 237 - 187 - - - - - - - - true - - - - - - - - 160 - 50 - 171 - 22 - - - - - - - QFrame::NoFrame - - - Baud Rate - - - - - - - - - - - - - 0 - 0 - 838 - 25 - - - - - &Help - - - - - - &Tools - - - - - - &File - - - - - - - - - - - &About - - - - - &Options - - - - - E&xit - - - - - - - RenderArea - QWidget -
renderarea.h
- 1 -
-
- - - - -
diff --git a/options.ui b/options.ui deleted file mode 100644 index cae7d5d..0000000 --- a/options.ui +++ /dev/null @@ -1,417 +0,0 @@ - - - Options - - - - 0 - 0 - 529 - 564 - - - - Options - - - - - 240 - 510 - 281 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 40 - 10 - 151 - 101 - - - - Invert Axis - - - - - 10 - 19 - 131 - 71 - - - - - - - Z Axis - - - - - - - Y Axis - - - - - - - X Axis - - - - - - - - - - 210 - 20 - 261 - 16 - - - - Seconds to Wait for Response - - - - - - 210 - 40 - 71 - 22 - - - - 1 - - - 1000 - - - 60 - - - - - - 210 - 70 - 261 - 16 - - - - Z-Jog Rate (inches or mm/min) - - - - - - 40 - 130 - 431 - 17 - - - - Use millimeters when sending manual commands (v0.8c+ only) - - - - - - 30 - 170 - 471 - 91 - - - - Z Rate Limiting - - - - - 10 - 20 - 451 - 51 - - - - - - - Limit Z Rate - - - - - - - true - - - QAbstractSpinBox::CorrectToNearestValue - - - 3 - - - 0.100000000000000 - - - 9999.989999999999782 - - - 1.000000000000000 - - - 100.000000000000000 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Z-Rate Limit (inches or mm/min) - - - - - - - XY Rate (inches or mm/min) - - - - - - - 2 - - - 0.100000000000000 - - - 999999.989999999990687 - - - 2000.000000000000000 - - - - - - - - - - 210 - 90 - 91 - 22 - - - - true - - - QAbstractSpinBox::CorrectToNearestValue - - - 3 - - - 0.100000000000000 - - - 9999.989999999999782 - - - 1.000000000000000 - - - 260.000000000000000 - - - - - - 40 - 270 - 461 - 81 - - - - - - - Use aggressive preload strategy for Grbl - - - - - - - Write debugging log to home folder (requires restart) - - - - - - - - - 40 - 360 - 461 - 111 - - - - Command Filtering - - - - - 20 - 20 - 431 - 17 - - - - Filter file commands before sending - - - - - - 20 - 50 - 431 - 17 - - - - Selectively reduce precision for excessively long lines - - - - - - 20 - 80 - 261 - 22 - - - - - - - Grbl Line Buffer Size - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 50 - - - - - - - groupZRateLimit - buttonBox - groupBoxAxis - labelWaitForResp - spinResponseWaitSec - labelZJogRate - checkBoxUseMmManualCmds - doubleSpinZJogRate - verticalLayoutWidget_2 - groupBox - - - - - buttonBox - accepted() - Options - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Options - reject() - - - 316 - 260 - - - 286 - 274 - - - - -