• 机器人地面站-[QGroundControl源码解析]-[2]


    目录

    前言

    一.QGC

    二.QGCComboBox

    三.QGCFileDownload

    四.QGCLoggingCategory

    五.QGCMapPalette

    六.QGCPalette

    七.QGCQGeoCoordinate

    八.QGCTemporaryFile

    九.QGCToolbox

    十.RunGuard

    十一.TerrainTile

    总结


    前言

    上一节我们对一些工具类进行了注释和阅读,他们包括cmd用户输入的解析,json文件的读取加载和解析,kml文件的加载读取和解析,以及shape文件的读取和解析。今天我们来看一下qgc开头的几个文件。

    一.QGC

    这个类主要就是几个方法,可以看头文件中的注释,cc文件主要实现了这些方法,比较简单,cc文件这里就不再贴出了,一下是头文件内容。

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. #include
    12. #include
    13. #include "QGCConfig.h"
    14. namespace QGC
    15. {
    16. /**
    17. * @brief Get the current ground time in microseconds. 获取当前地面时时间(以微秒为单位)。
    18. * @note This does not have microsecond precision, it is limited to millisecond precision. 这没有微秒精度,它被限制在毫秒精度。
    19. */
    20. quint64 groundTimeUsecs();
    21. /**
    22. * @brief Get the current ground time in milliseconds 获取当前地面时间(以毫秒为单位)
    23. */
    24. quint64 groundTimeMilliseconds();
    25. /**
    26. * @brief Get the current ground time in fractional seconds 以小数秒为单位获取当前地面时间
    27. * @note Precision is limited to milliseconds.
    28. */
    29. qreal groundTimeSeconds();
    30. /**
    31. * @brief Returns the angle limited to -pi - pi 返回-pi 到-pi这个范围的的角度
    32. */
    33. float limitAngleToPMPIf(double angle);
    34. /**
    35. * @brief Returns the angle limited to -pi - pi
    36. */
    37. double limitAngleToPMPId(double angle);
    38. /**
    39. * @brief Records boot time (called from main)记录启动时间(从main调用)
    40. */
    41. void initTimer();
    42. /**
    43. * @brief Get the ground time since boot in milliseconds 获取自启动后的地面时间(以毫秒为单位)
    44. */
    45. quint64 bootTimeMilliseconds();
    46. /**
    47. * @brief Returns true if the two values are equal or close. Correctly handles 0 and NaN values. 如果两个值相等或接近,则返回true。 正确处理0和NaN值。
    48. */
    49. bool fuzzyCompare(double value1, double value2);
    50. class SLEEP : public QThread
    51. {
    52. Q_OBJECT
    53. public:
    54. using QThread::sleep;
    55. using QThread::msleep;
    56. using QThread::usleep;
    57. };
    58. ///CRC的全称是循环冗余校验。
    59. quint32 crc32(const quint8 *src, unsigned len, unsigned state);
    60. }

    二.QGCComboBox

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. /// @file
    12. /// @brief Subclass of QComboBox. Mainly used for unit test so you can simulate a user selection
    13. /// with correct signalling. 主要用于单元测试,可以用正确的信号模拟用户选择。
    14. ///
    15. /// @author Don Gagne
    16. class QGCComboBox : public QComboBox {
    17. Q_OBJECT
    18. public:
    19. QGCComboBox(QWidget* parent = nullptr);
    20. /// @brief Sets the current index on the combo. Signals activated, as well as currentIndexChanged.
    21. /// 设置组combo当前索引。 当信号被激活,currentIndexChanged也会被触发。
    22. void simulateUserSetCurrentIndex(int index);
    23. };
    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "QGCComboBox.h"
    10. QGCComboBox::QGCComboBox(QWidget* parent) :
    11. QComboBox(parent)
    12. {
    13. }
    14. void QGCComboBox::simulateUserSetCurrentIndex(int index)
    15. {
    16. Q_ASSERT(index >=0 && index < count());
    17. // This will signal currentIndexChanged
    18. setCurrentIndex(index);
    19. // We have to manually signal activated
    20. //手动触发信号activated textActivated信号
    21. emit activated(index);
    22. emit textActivated(itemText(index));
    23. }

    三.QGCFileDownload

    此类利用QNetworkAccessManager进行文件的下载和存储。头文件注释如下

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. /**
    12. * @brief Get the current ground time in microseconds. 获取当前地面时时间(以微秒为单位)。
    13. * @note NetworkAccess API是围绕一个QNetworkAccessManager对象构造的,
    14. * 该对象包含它发送的请求的公共配置和设置。它包含代理和缓存配置,以及与此类问题相关的信号,以及可用于监视网络运行进度的应答信号。
    15. * 一个QNetworkAccessManager对于整个Qt应用程序应该已经足够了。
    16. * QNetworkAccessManager https://blog.csdn.net/jolin678/article/details/122984515
    17. */
    18. class QGCFileDownload : public QNetworkAccessManager
    19. {
    20. Q_OBJECT
    21. public:
    22. QGCFileDownload(QObject* parent = nullptr);
    23. /// Download the specified remote file. 下载指定的远程文件。
    24. /// @param remoteFile File to download. Can be http address or file system path. 可以是http地址或文件系统路径。
    25. /// @param redirect true: call is internal due to redirect 用于重定向
    26. /// @return true: Asynchronous download has started, false: Download initialization failed
    27. /// true:异步下载已经启动,false:下载初始化失败
    28. bool download(const QString& remoteFile, bool redirect = false);
    29. signals:
    30. //下载进度信号
    31. void downloadProgress(qint64 curr, qint64 total);
    32. //下载完成信号
    33. void downloadComplete(QString remoteFile, QString localFile, QString errorMsg);
    34. private:
    35. //下载完成
    36. void _downloadFinished(void);
    37. //下载出现错误
    38. void _downloadError(QNetworkReply::NetworkError code);
    39. QString _originalRemoteFile;
    40. };

    cc文件如下

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "QGCFileDownload.h"
    10. #include
    11. #include
    12. #include
    13. QGCFileDownload::QGCFileDownload(QObject* parent)
    14. : QNetworkAccessManager(parent)
    15. {
    16. }
    17. bool QGCFileDownload::download(const QString& remoteFile, bool redirect)
    18. {
    19. //如果不重定向
    20. if (!redirect) {
    21. _originalRemoteFile = remoteFile;
    22. }
    23. if (remoteFile.isEmpty()) {
    24. qWarning() << "downloadFile empty";
    25. return false;
    26. }
    27. QUrl remoteUrl;
    28. //如果含有http则是网路路径否则是本地路径
    29. if (remoteFile.startsWith("http:") || remoteFile.startsWith("https:"))
    30. {
    31. remoteUrl.setUrl(remoteFile);
    32. }else
    33. {
    34. remoteUrl = QUrl::fromLocalFile(remoteFile);
    35. }
    36. if (!remoteUrl.isValid()) {
    37. qWarning() << "Remote URL is invalid" << remoteFile;
    38. return false;
    39. }
    40. QNetworkRequest networkRequest(remoteUrl);
    41. //代理设置
    42. QNetworkProxy tProxy;
    43. tProxy.setType(QNetworkProxy::DefaultProxy);
    44. setProxy(tProxy);
    45. QNetworkReply* networkReply = get(networkRequest);
    46. if (!networkReply) {
    47. qWarning() << "QNetworkAccessManager::get failed";
    48. return false;
    49. }
    50. //绑定槽函数
    51. connect(networkReply, &QNetworkReply::downloadProgress, this, &QGCFileDownload::downloadProgress);
    52. connect(networkReply, &QNetworkReply::finished, this, &QGCFileDownload::_downloadFinished);
    53. connect(networkReply, &QNetworkReply::errorOccurred, this, &QGCFileDownload::_downloadError);
    54. return true;
    55. }
    56. void QGCFileDownload::_downloadFinished(void)
    57. {
    58. //当某一个Object emit一个signal的时候,它就是一个sender,系统会记录下当前是谁emit出这个signal的,所以你在对应的slot里就可以通过 sender()得到当前是那个对象调用了你的slot
    59. QNetworkReply* reply = qobject_cast(QObject::sender());
    60. // When an error occurs or the user cancels the download, we still end up here. So bail out in
    61. // those cases.
    62. //当出现错误或用户取消下载时,我们仍然会在这里结束。 所以,在这些情况下,你可以在这里释放对象。
    63. if (reply->error() != QNetworkReply::NoError) {
    64. reply->deleteLater();
    65. return;
    66. }
    67. // Check for redirection
    68. QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    69. if (!redirectionTarget.isNull()) {
    70. //如果重定向目标不为空
    71. QUrl redirectUrl = reply->url().resolved(redirectionTarget.toUrl());
    72. download(redirectUrl.toString(), true /* redirect */);
    73. reply->deleteLater();
    74. return;
    75. }
    76. // Split out filename from path
    77. //获取文件名
    78. QString remoteFileName = QFileInfo(reply->url().toString()).fileName();
    79. if (remoteFileName.isEmpty()) {
    80. qWarning() << "Unabled to parse filename from remote url" << reply->url().toString();
    81. //给个默认文件名
    82. remoteFileName = "DownloadedFile";
    83. }
    84. // Strip out http parameters from remote filename 从远程文件名中删除http的参数
    85. int parameterIndex = remoteFileName.indexOf("?");
    86. if (parameterIndex != -1) {
    87. remoteFileName = remoteFileName.left(parameterIndex);
    88. }
    89. // Determine location to download file to 确定要下载文件的位置
    90. // TempLocation 临时文件路径
    91. QString downloadFilename = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
    92. if (downloadFilename.isEmpty()) {
    93. downloadFilename = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
    94. if (downloadFilename.isEmpty()) {
    95. emit downloadComplete(_originalRemoteFile, QString(), tr("Unabled to find writable download location. Tried downloads and temp directory."));
    96. return;
    97. }
    98. }
    99. downloadFilename += "/" + remoteFileName;
    100. if (!downloadFilename.isEmpty()) {
    101. // Store downloaded file in download location
    102. QFile file(downloadFilename);
    103. if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
    104. emit downloadComplete(_originalRemoteFile, downloadFilename, tr("Could not save downloaded file to %1. Error: %2").arg(downloadFilename).arg(file.errorString()));
    105. return;
    106. }
    107. //写入
    108. file.write(reply->readAll());
    109. file.close();
    110. emit downloadComplete(_originalRemoteFile, downloadFilename, QString());
    111. } else {
    112. QString errorMsg = "Internal error";
    113. qWarning() << errorMsg;
    114. emit downloadComplete(_originalRemoteFile, downloadFilename, errorMsg);
    115. }
    116. //释放
    117. reply->deleteLater();
    118. }
    119. /// @brief Called when an error occurs during download
    120. void QGCFileDownload::_downloadError(QNetworkReply::NetworkError code)
    121. {
    122. //处理下载过程中的各种错误
    123. QString errorMsg;
    124. if (code == QNetworkReply::OperationCanceledError) {
    125. errorMsg = tr("Download cancelled");
    126. } else if (code == QNetworkReply::ContentNotFoundError) {
    127. errorMsg = tr("Error: File Not Found");
    128. } else {
    129. errorMsg = tr("Error during download. Error: %1").arg(code);
    130. }
    131. emit downloadComplete(_originalRemoteFile, QString(), errorMsg);
    132. }

    四.QGCLoggingCategory

    这个类中干货很多,不仅有宏定义的一些使用技巧,还有宏定义中一些符号的使用方式。但是目前看代码还没了解这个类后边是如何被使用的,到后面看到的时候再提。头文件如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. #include
    12. // Add Global logging categories (not class specific) here using Q_DECLARE_LOGGING_CATEGORY
    13. // 在这里使用Q_DECLARE_LOGGING_CATEGORY添加全局日志分类(不是特定于类的)
    14. Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeLog) //固件升级日志
    15. Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog) //固件升级长日志
    16. Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog) //任务命令日志
    17. Q_DECLARE_LOGGING_CATEGORY(MissionItemLog) //任务项目日志
    18. Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog) //参数管理日志
    19. Q_DECLARE_LOGGING_CATEGORY(GeotaggingLog) //地理标签日志
    20. Q_DECLARE_LOGGING_CATEGORY(RTKGPSLog) //RTKGPS日志
    21. Q_DECLARE_LOGGING_CATEGORY(GuidedActionsControllerLog) //指导行动控制日志
    22. Q_DECLARE_LOGGING_CATEGORY(ADSBVehicleManagerLog) //ADS-B[1]是广播式自动相关监视的英文缩写,它主要实施空对空监视
    23. Q_DECLARE_LOGGING_CATEGORY(LocalizationLog) //定位日志
    24. Q_DECLARE_LOGGING_CATEGORY(VideoAllLog) // turns on all individual QGC video logs 打开所有单独的QGC视频日志
    25. /// @def QGC_LOGGING_CATEGORY
    26. /// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a
    27. /// global list. It's usage is the same as Q_LOGGING_CATEOGRY.
    28. /// 这是Q_LOGGING_CATEGORY的一个特定于QGC的替换
    29. /// 它将把类别名注册到一个全局列表中。 它的用法与q_logging_categorogry相同。
    30. /// 关于define中 #和##的使用 https://blog.csdn.net/Damon_X/article/details/113343979 https://blog.csdn.net/auccy/article/details/88833659
    31. /// 相当于:例如FirmwareUpgradeLog 等价于 static QGCLoggingCategory qgcCategoryFirmwareUpgradeLog (__VA_ARGS__); __VA_ARGS__ 指代可变参数列表
    32. #define QGC_LOGGING_CATEGORY(name, ...) \
    33. static QGCLoggingCategory qgcCategory ## name (__VA_ARGS__); \
    34. Q_LOGGING_CATEGORY(name, __VA_ARGS__)
    35. class QGCLoggingCategoryRegister : public QObject
    36. {
    37. Q_OBJECT
    38. public:
    39. //单例模式
    40. static QGCLoggingCategoryRegister* instance(void);
    41. /// Registers the specified logging category to the system.
    42. void registerCategory(const char* category) { _registeredCategories << category; }
    43. /// Returns the list of available logging category names.
    44. /// 将指定的日志记录类别注册到系统 注意Q_INVOKABLE
    45. Q_INVOKABLE QStringList registeredCategories(void);
    46. /// Turns on/off logging for the specified category. State is saved in app settings.
    47. /// 为指定的类别打开/关闭日志记录。 状态保存在应用程序设置中
    48. Q_INVOKABLE void setCategoryLoggingOn(const QString& category, bool enable);
    49. /// Returns true if logging is turned on for the specified category.
    50. /// 如果为指定类别打开了日志记录,则返回true。
    51. Q_INVOKABLE bool categoryLoggingOn(const QString& category);
    52. /// Sets the logging filters rules from saved settings.
    53. /// 从保存的设置设置日志过滤规则。
    54. /// @param commandLineLogggingOptions Logging options which were specified on the command line
    55. /// commandLineLogggingOptions在命令行上指定的日志选项
    56. void setFilterRulesFromSettings(const QString& commandLineLoggingOptions);
    57. private:
    58. QGCLoggingCategoryRegister(void) { }
    59. QStringList _registeredCategories;
    60. QString _commandLineLoggingOptions;
    61. static const char* _filterRulesSettingsGroup;
    62. };
    63. class QGCLoggingCategory
    64. {
    65. public:
    66. QGCLoggingCategory(const char* category) { QGCLoggingCategoryRegister::instance()->registerCategory(category); }
    67. };

    cc文件如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. /// @file
    10. /// @author Don Gagne
    11. #include "QGCLoggingCategory.h"
    12. #include
    13. static const char* kVideoAllLogCategory = "VideoAllLog";
    14. // Add Global logging categories (not class specific) here using QGC_LOGGING_CATEGORY
    15. //在这里使用QGC_LOGGING_CATEGORY添加全局日志分类(不是特定于类的)
    16. //例如第一行相当于生成了两个静态对象 qgcCategoryFirmwareUpgradeLog 和
    17. //然后定义了一个方法
    18. // static QGCLoggingCategory qgcCategoryFirmwareUpgradeLog("FirmwareUpgradeLog");
    19. // const QLoggingCategory &FirmwareUpgradeLog()
    20. // {
    21. // static const QLoggingCategory category("FirmwareUpgradeLog");
    22. // return category;
    23. // }
    24. QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog")
    25. QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog")
    26. QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog")
    27. QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
    28. QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog")
    29. QGC_LOGGING_CATEGORY(GeotaggingLog, "GeotaggingLog")
    30. QGC_LOGGING_CATEGORY(RTKGPSLog, "RTKGPSLog")
    31. QGC_LOGGING_CATEGORY(GuidedActionsControllerLog, "GuidedActionsControllerLog")
    32. QGC_LOGGING_CATEGORY(ADSBVehicleManagerLog, "ADSBVehicleManagerLog")
    33. QGC_LOGGING_CATEGORY(LocalizationLog, "LocalizationLog")
    34. QGC_LOGGING_CATEGORY(VideoAllLog, kVideoAllLogCategory)
    35. QGCLoggingCategoryRegister* _instance = nullptr;
    36. const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters";
    37. QGCLoggingCategoryRegister* QGCLoggingCategoryRegister::instance(void)
    38. {
    39. if (!_instance) {
    40. _instance = new QGCLoggingCategoryRegister();
    41. Q_CHECK_PTR(_instance);//检查指针是否为空
    42. }
    43. return _instance;
    44. }
    45. QStringList QGCLoggingCategoryRegister::registeredCategories(void)
    46. {
    47. //排序后返回
    48. _registeredCategories.sort();
    49. return _registeredCategories;
    50. }
    51. void QGCLoggingCategoryRegister::setCategoryLoggingOn(const QString& category, bool enable)
    52. {
    53. QSettings settings;
    54. settings.beginGroup(_filterRulesSettingsGroup);
    55. settings.setValue(category, enable);
    56. }
    57. bool QGCLoggingCategoryRegister::categoryLoggingOn(const QString& category)
    58. {
    59. QSettings settings;
    60. settings.beginGroup(_filterRulesSettingsGroup);
    61. return settings.value(category, false).toBool();
    62. }
    63. void QGCLoggingCategoryRegister::setFilterRulesFromSettings(const QString& commandLineLoggingOptions)
    64. {
    65. QString filterRules;
    66. QString filterRuleFormat("%1.debug=true\n");
    67. bool videoAllLogSet = false;
    68. if (!commandLineLoggingOptions.isEmpty()) {
    69. _commandLineLoggingOptions = commandLineLoggingOptions;
    70. }
    71. filterRules += "*Log.debug=false\n";
    72. // Set up filters defined in settings 设置设置中定义的过滤器
    73. foreach (QString category, _registeredCategories) {
    74. if (categoryLoggingOn(category)) {
    75. filterRules += filterRuleFormat.arg(category);
    76. if (category == kVideoAllLogCategory) {
    77. videoAllLogSet = true;
    78. }
    79. }
    80. }
    81. // Command line rules take precedence, so they go last in the list 命令行规则优先,因此它们在列表中位于最后
    82. if (!_commandLineLoggingOptions.isEmpty()) {
    83. QStringList logList = _commandLineLoggingOptions.split(",");
    84. if (logList[0] == "full") {
    85. filterRules += "*Log.debug=true\n";
    86. for(int i=1; icount(); i++) {
    87. filterRules += filterRuleFormat.arg(logList[i]);
    88. }
    89. } else {
    90. for (auto& category: logList) {
    91. filterRules += filterRuleFormat.arg(category);
    92. if (category == kVideoAllLogCategory) {
    93. videoAllLogSet = true;
    94. }
    95. }
    96. }
    97. }
    98. if (videoAllLogSet) {
    99. filterRules += filterRuleFormat.arg("VideoManagerLog");
    100. filterRules += filterRuleFormat.arg("VideoReceiverLog");
    101. filterRules += filterRuleFormat.arg("GStreamerLog");
    102. }
    103. // Logging from GStreamer library itself controlled by gstreamer debug levels is always turned on
    104. // 由GStreamer调试级别控制的GStreamer库本身的日志记录总是打开的
    105. filterRules += filterRuleFormat.arg("GStreamerAPILog");
    106. filterRules += "qt.qml.connections=false";
    107. qDebug() << "Filter rules" << filterRules;
    108. QLoggingCategory::setFilterRules(filterRules);
    109. }

    五.QGCMapPalette

    这个类主要是用于存储了两种颜色,然后针对地图是亮色还是暗色, 能够切换这个调色板使得地图上的绘制能够区别于地图背景。

    头文件如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #ifndef QGCMapPalette_h
    10. #define QGCMapPalette_h
    11. #include
    12. #include
    13. /*!
    14. QGCMapPalette is a variant of QGCPalette which is used to hold colors used for display over
    15. the map control. Since the coloring of a satellite map differs greatly from the coloring of
    16. a street map you need to be able to switch between sets of color based on map type.
    17. QGCMapPalette是QGCPalette的一个变体,用来保存用于显示的颜色
    18. 地图上的控制。 由于卫星地图的着色与街道地图的着色有很大的不同,你需要能够基于地图类型的颜色集切换。
    19. Usage:
    20. import QGroundControl.Palette 1.0
    21. FlightMap {
    22. id: map
    23. anchors.fill: parent
    24. QGCMapPalette {
    25. id: mapPal
    26. lightColors: map.isSatelliteMap 根据这个值来构造调色板
    27. }
    28. QGCLabel {
    29. text: "Text over map"
    30. color: mapPal.text
    31. }
    32. }
    33. **/
    34. class QGCMapPalette : public QObject
    35. {
    36. Q_OBJECT
    37. //定义三个属性 这三个属性的改变都会触发paletteChanged信号
    38. Q_PROPERTY(bool lightColors READ lightColors WRITE setLightColors NOTIFY paletteChanged)
    39. Q_PROPERTY(QColor text READ text NOTIFY paletteChanged)
    40. Q_PROPERTY(QColor textOutline READ textOutline NOTIFY paletteChanged)
    41. public:
    42. QGCMapPalette(QObject* parent = nullptr);
    43. /// Text color
    44. /// 属性对应的读取函数 返回数组中对下标对应的颜色值 静态数组_text
    45. QColor text(void) const { return _text[_lightColors ? 0 : 1]; }
    46. QColor textOutline(void) const { return _textOutline[_lightColors ? 0 : 1]; }
    47. bool lightColors(void) const { return _lightColors; }
    48. void setLightColors(bool lightColors);
    49. signals:
    50. void paletteChanged(void);
    51. void lightColorsChanged(bool lightColors);
    52. private:
    53. //是否是亮色
    54. bool _lightColors = false;
    55. //数组大小为2
    56. static const int _cColorGroups = 2;
    57. //静态数组_text
    58. static QColor _text[_cColorGroups];
    59. //静态数组_textOutline
    60. static QColor _textOutline[_cColorGroups];
    61. };
    62. #endif

    cc文件如下:

    1. #include "QGCMapPalette.h"
    2. #include
    3. #include
    4. //定义两个静态数组
    5. QColor QGCMapPalette::_text [QGCMapPalette::_cColorGroups] = { QColor(255,255,255), QColor(0,0,0) };
    6. QColor QGCMapPalette::_textOutline [QGCMapPalette::_cColorGroups] = { QColor(0,0,0,192), QColor(255,255,255,192) };
    7. QGCMapPalette::QGCMapPalette(QObject* parent) :
    8. QObject(parent)
    9. {
    10. }
    11. void QGCMapPalette::setLightColors(bool lightColors)
    12. {
    13. if ( _lightColors != lightColors) {
    14. _lightColors = lightColors;
    15. //前后设置的值不同触发信号
    16. emit paletteChanged();
    17. }
    18. }

    六.QGCPalette

    这个类主要作用是,定义了全局调色板的功能,包括初始化所有主题对应的启用和停用和不同功能空间的颜色设置,对应的设置方法,获取方法,以及当主题发生更改后的消息通知给所有应用调色板的控件,基本上负责了整个应用主题更换,颜色更换的功能。这里文件注释也更加详尽。以下是头文件内用:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #ifndef QGCPalette_h
    10. #define QGCPalette_h
    11. #include
    12. #include
    13. #include
    14. //宏定义 定义一段函数
    15. // 1.声明一个二维数组 第一维存储 light设置 和 dark设置 第二位存储这些设置对应的两个值
    16. // 2.调用paletteOverride
    17. // 3.设置_colorInfoMap 是一个三维数组 第一维两个元素分别是 Light和Dark 第二维ColorGroupEnabled和ColorGroupDisabled 第三维是#name的字符串内容
    18. // 4.将#name存入_colors
    19. #define DECLARE_QGC_COLOR(name, lightDisabled, lightEnabled, darkDisabled, darkEnabled) \
    20. { \
    21. PaletteColorInfo_t colorInfo = { \
    22. { QColor(lightDisabled), QColor(lightEnabled) }, \
    23. { QColor(darkDisabled), QColor(darkEnabled) } \
    24. }; \
    25. qgcApp()->toolbox()->corePlugin()->paletteOverride(#name, colorInfo); \
    26. _colorInfoMap[Light][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupEnabled]; \
    27. _colorInfoMap[Light][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupDisabled]; \
    28. _colorInfoMap[Dark][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupEnabled]; \
    29. _colorInfoMap[Dark][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupDisabled]; \
    30. _colors << #name; \
    31. }
    32. //二维数组 第一维的两个元素相同 第二维分别是disabledColor和enabledColor
    33. #define DECLARE_QGC_NONTHEMED_COLOR(name, disabledColor, enabledColor) \
    34. { \
    35. PaletteColorInfo_t colorInfo = { \
    36. { QColor(disabledColor), QColor(enabledColor) }, \
    37. { QColor(disabledColor), QColor(enabledColor) } \
    38. }; \
    39. qgcApp()->toolbox()->corePlugin()->paletteOverride(#name, colorInfo); \
    40. _colorInfoMap[Light][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupEnabled]; \
    41. _colorInfoMap[Light][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupDisabled]; \
    42. _colorInfoMap[Dark][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupEnabled]; \
    43. _colorInfoMap[Dark][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupDisabled]; \
    44. _colors << #name; \
    45. }
    46. //colorInfo 所有元素相同
    47. #define DECLARE_QGC_SINGLE_COLOR(name, color) \
    48. { \
    49. PaletteColorInfo_t colorInfo = { \
    50. { QColor(color), QColor(color) }, \
    51. { QColor(color), QColor(color) } \
    52. }; \
    53. qgcApp()->toolbox()->corePlugin()->paletteOverride(#name, colorInfo); \
    54. _colorInfoMap[Light][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupEnabled]; \
    55. _colorInfoMap[Light][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Light][ColorGroupDisabled]; \
    56. _colorInfoMap[Dark][ColorGroupEnabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupEnabled]; \
    57. _colorInfoMap[Dark][ColorGroupDisabled][QStringLiteral(#name)] = colorInfo[Dark][ColorGroupDisabled]; \
    58. _colors << #name; \
    59. }
    60. // 参数 name和setname
    61. // 先定义两个变量 第一个变量是 QColor类型的 #name变量 第二个变量QStringList类型的 NAME ## Colors变量
    62. // 定义 #name方法 (方法内容是返回_colorInfoMap对应下标的元素[风格][GroupEnabled / ColorGroupDisabled][#NAME])
    63. // 定义 NAME ## Colors 方法 (方法内容是 向list添加 [亮][GroupEnabled][#NAME],[亮][GroupDisabled][#NAME],[暗][GroupEnabled][#NAME],[暗][GroupDisabled][#NAME])
    64. // 定义 SETNAME方法 (方法内容是设置_colorInfoMap[风格][_colorGroupEnabled/ColorGroupDisabled][#NAME] = color 然后调用_signalPaletteChangeToAll())
    65. #define DEFINE_QGC_COLOR(NAME, SETNAME) \
    66. Q_PROPERTY(QColor NAME READ NAME WRITE SETNAME NOTIFY paletteChanged) \
    67. Q_PROPERTY(QStringList NAME ## Colors READ NAME ## Colors NOTIFY paletteChanged) \
    68. QColor NAME() const { return _colorInfoMap[_theme][_colorGroupEnabled ? ColorGroupEnabled : ColorGroupDisabled][QStringLiteral(#NAME)]; } \
    69. QStringList NAME ## Colors() const { \
    70. QStringList c; \
    71. c << _colorInfoMap[Light][ColorGroupEnabled][QStringLiteral(#NAME)].name(QColor::HexRgb); \
    72. c << _colorInfoMap[Light][ColorGroupDisabled][QStringLiteral(#NAME)].name(QColor::HexRgb); \
    73. c << _colorInfoMap[Dark][ColorGroupEnabled][QStringLiteral(#NAME)].name(QColor::HexRgb); \
    74. c << _colorInfoMap[Dark][ColorGroupDisabled][QStringLiteral(#NAME)].name(QColor::HexRgb); \
    75. return c; \
    76. } \
    77. void SETNAME(const QColor& color) { _colorInfoMap[_theme][_colorGroupEnabled ? ColorGroupEnabled : ColorGroupDisabled][QStringLiteral(#NAME)] = color; _signalPaletteChangeToAll(); }
    78. /*!
    79. QGCPalette is used in QML ui to expose color properties for the QGC palette. There are two
    80. separate palettes in QGC, light and dark. The light palette is for outdoor use and the dark
    81. palette is for indoor use. Each palette also has a set of different colors for enabled and
    82. disabled states.
    83. QGCPalette在QML ui中用于为QGC调色板暴露颜色属性。
    84. 有两个QGC中单独的调色板,亮和暗。
    85. 浅色调色板适用于户外,深色调色板适用于室内。
    86. 每个调色板也有一组用于启用和停用的不同颜色
    87. 禁用状态。
    88. Usage:
    89. import QGroundControl.Palette 1.0
    90. Rectangle {
    91. anchors.fill: parent
    92. color: qgcPal.window
    93. QGCPalette {
    94. id: qgcPal
    95. colorGroupEnabled: enabled
    96. }
    97. }
    98. */
    99. class QGCPalette : public QObject
    100. {
    101. Q_OBJECT
    102. public:
    103. enum ColorGroup {
    104. ColorGroupDisabled = 0,
    105. ColorGroupEnabled,
    106. cMaxColorGroup
    107. };
    108. enum Theme {
    109. Light = 0,
    110. Dark,
    111. cMaxTheme
    112. };
    113. Q_ENUM(Theme)
    114. typedef QColor PaletteColorInfo_t[cMaxTheme][cMaxColorGroup];
    115. //定义三个属性globalTheme colorGroupEnabled colors
    116. Q_PROPERTY(Theme globalTheme READ globalTheme WRITE setGlobalTheme NOTIFY paletteChanged)
    117. Q_PROPERTY(bool colorGroupEnabled READ colorGroupEnabled WRITE setColorGroupEnabled NOTIFY paletteChanged)
    118. Q_PROPERTY(QStringList colors READ colors CONSTANT)
    119. //按照前面对DEFINE_QGC_COLOR的分析,第一行代码相当于
    120. //1.定义了两个属性 分别是window 和 windowColors
    121. //2.定义window方法 方法内容是返回_colorInfoMap对应下标的元素[当前风格][GroupEnabled / ColorGroupDisabled][window] 对应的color类
    122. //3.定义windowColors方法,(方法内容是 向list添加 [亮][GroupEnabled][window],[亮][GroupDisabled][window],[暗][GroupEnabled][window],[暗][GroupDisabled][window])
    123. //4.定义SETwindow方法 (方法内容是设置_colorInfoMap[风格][_colorGroupEnabled/ColorGroupDisabled][#NAME] = color 然后调用_signalPaletteChangeToAll())
    124. DEFINE_QGC_COLOR(window, setWindow)
    125. DEFINE_QGC_COLOR(windowShadeLight, setWindowShadeLight)
    126. DEFINE_QGC_COLOR(windowShade, setWindowShade)
    127. DEFINE_QGC_COLOR(windowShadeDark, setWindowShadeDark)
    128. DEFINE_QGC_COLOR(text, setText)
    129. DEFINE_QGC_COLOR(warningText, setWarningText)
    130. DEFINE_QGC_COLOR(button, setButton)
    131. DEFINE_QGC_COLOR(buttonText, setButtonText)
    132. DEFINE_QGC_COLOR(buttonHighlight, setButtonHighlight)
    133. DEFINE_QGC_COLOR(buttonHighlightText, setButtonHighlightText)
    134. DEFINE_QGC_COLOR(primaryButton, setPrimaryButton)
    135. DEFINE_QGC_COLOR(primaryButtonText, setPrimaryButtonText)
    136. DEFINE_QGC_COLOR(textField, setTextField)
    137. DEFINE_QGC_COLOR(textFieldText, setTextFieldText)
    138. DEFINE_QGC_COLOR(mapButton, setMapButton)
    139. DEFINE_QGC_COLOR(mapButtonHighlight, setMapButtonHighlight)
    140. DEFINE_QGC_COLOR(mapIndicator, setMapIndicator)
    141. DEFINE_QGC_COLOR(mapIndicatorChild, setMapIndicatorChild)
    142. DEFINE_QGC_COLOR(mapWidgetBorderLight, setMapWidgetBorderLight)
    143. DEFINE_QGC_COLOR(mapWidgetBorderDark, setMapWidgetBorderDark)
    144. DEFINE_QGC_COLOR(mapMissionTrajectory, setMapMissionTrajectory)
    145. DEFINE_QGC_COLOR(brandingPurple, setBrandingPurple)
    146. DEFINE_QGC_COLOR(brandingBlue, setBrandingBlue)
    147. DEFINE_QGC_COLOR(colorGreen, setColorGreen)
    148. DEFINE_QGC_COLOR(colorOrange, setColorOrange)
    149. DEFINE_QGC_COLOR(colorRed, setColorRed)
    150. DEFINE_QGC_COLOR(colorGrey, setColorGrey)
    151. DEFINE_QGC_COLOR(colorBlue, setColorBlue)
    152. DEFINE_QGC_COLOR(alertBackground, setAlertBackground)
    153. DEFINE_QGC_COLOR(alertBorder, setAlertBorder)
    154. DEFINE_QGC_COLOR(alertText, setAlertText)
    155. DEFINE_QGC_COLOR(missionItemEditor, setMissionItemEditor)
    156. DEFINE_QGC_COLOR(statusFailedText, setstatusFailedText)
    157. DEFINE_QGC_COLOR(statusPassedText, setstatusPassedText)
    158. DEFINE_QGC_COLOR(statusPendingText, setstatusPendingText)
    159. DEFINE_QGC_COLOR(surveyPolygonInterior, setSurveyPolygonInterior)
    160. DEFINE_QGC_COLOR(surveyPolygonTerrainCollision, setSurveyPolygonTerrainCollision)
    161. DEFINE_QGC_COLOR(toolbarBackground, setToolbarBackground)
    162. DEFINE_QGC_COLOR(toolStripFGColor, setToolStripFGColor)
    163. DEFINE_QGC_COLOR(toolStripHoverColor, setToolStripHoverColor)
    164. QGCPalette(QObject* parent = nullptr);
    165. ~QGCPalette();
    166. QStringList colors () const { return _colors; }
    167. bool colorGroupEnabled () const { return _colorGroupEnabled; }
    168. void setColorGroupEnabled (bool enabled);
    169. static Theme globalTheme () { return _theme; }
    170. static void setGlobalTheme (Theme newTheme);
    171. signals:
    172. void paletteChanged ();
    173. private:
    174. //创建map
    175. static void _buildMap ();
    176. static void _signalPaletteChangeToAll ();
    177. void _signalPaletteChanged ();
    178. void _themeChanged ();
    179. static Theme _theme; ///< There is a single theme for all palettes 所有调色板都有一个单一的主题
    180. bool _colorGroupEnabled; ///< Currently selected ColorGroup. true: enabled, false: disabled 当前选中ColorGroup。 True:启用,false:禁用
    181. static QStringList _colors;
    182. static QMap<int, QMap<int, QMap>> _colorInfoMap; // theme -> colorGroup -> color name -> color
    183. static QList _paletteObjects; ///< List of all active QGCPalette objects 所有活动QGCPalette对象的列表
    184. };
    185. #endif

    cc文件如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. /// @file
    10. /// @author Don Gagne
    11. #include "QGCPalette.h"
    12. #include "QGCApplication.h"
    13. #include "QGCCorePlugin.h"
    14. #include
    15. #include
    16. //变脸赋值
    17. QList QGCPalette::_paletteObjects;
    18. //默认dark
    19. QGCPalette::Theme QGCPalette::_theme = QGCPalette::Dark;
    20. QMap<int, QMap<int, QMap>> QGCPalette::_colorInfoMap;
    21. QStringList QGCPalette::_colors;
    22. QGCPalette::QGCPalette(QObject* parent) :
    23. QObject(parent),
    24. _colorGroupEnabled(true)
    25. {
    26. if (_colorInfoMap.isEmpty()) {
    27. _buildMap();
    28. }
    29. // We have to keep track of all QGCPalette objects in the system so we can signal theme change to all of them
    30. // 我们必须跟踪系统中的所有QGCPalette对象,以便向所有对象发出主题更改的信号
    31. _paletteObjects += this;
    32. }
    33. QGCPalette::~QGCPalette()
    34. {
    35. // 清除QGCPalette对象 这样当主题更改的时,信号将不会发送到这里
    36. bool fSuccess = _paletteObjects.removeOne(this);
    37. if (!fSuccess) {
    38. qWarning() << "Internal error";
    39. }
    40. }
    41. void QGCPalette::_buildMap()
    42. {
    43. // 构建_colorInfoMap和_colors
    44. // Light Dark
    45. // Disabled Enabled Disabled Enabled
    46. DECLARE_QGC_COLOR(window, "#ffffff", "#ffffff", "#222222", "#222222")
    47. DECLARE_QGC_COLOR(windowShadeLight, "#909090", "#828282", "#707070", "#626262")
    48. DECLARE_QGC_COLOR(windowShade, "#d9d9d9", "#d9d9d9", "#333333", "#333333")
    49. DECLARE_QGC_COLOR(windowShadeDark, "#bdbdbd", "#bdbdbd", "#282828", "#282828")
    50. DECLARE_QGC_COLOR(text, "#9d9d9d", "#000000", "#707070", "#ffffff")
    51. DECLARE_QGC_COLOR(warningText, "#cc0808", "#cc0808", "#f85761", "#f85761")
    52. DECLARE_QGC_COLOR(button, "#ffffff", "#ffffff", "#707070", "#626270")
    53. DECLARE_QGC_COLOR(buttonText, "#9d9d9d", "#000000", "#A6A6A6", "#ffffff")
    54. DECLARE_QGC_COLOR(buttonHighlight, "#e4e4e4", "#946120", "#3a3a3a", "#fff291")
    55. DECLARE_QGC_COLOR(buttonHighlightText, "#2c2c2c", "#ffffff", "#2c2c2c", "#000000")
    56. DECLARE_QGC_COLOR(primaryButton, "#585858", "#8cb3be", "#585858", "#8cb3be")
    57. DECLARE_QGC_COLOR(primaryButtonText, "#2c2c2c", "#000000", "#2c2c2c", "#000000")
    58. DECLARE_QGC_COLOR(textField, "#ffffff", "#ffffff", "#707070", "#ffffff")
    59. DECLARE_QGC_COLOR(textFieldText, "#808080", "#000000", "#000000", "#000000")
    60. DECLARE_QGC_COLOR(mapButton, "#585858", "#000000", "#585858", "#000000")
    61. DECLARE_QGC_COLOR(mapButtonHighlight, "#585858", "#be781c", "#585858", "#be781c")
    62. DECLARE_QGC_COLOR(mapIndicator, "#585858", "#be781c", "#585858", "#be781c")
    63. DECLARE_QGC_COLOR(mapIndicatorChild, "#585858", "#766043", "#585858", "#766043")
    64. DECLARE_QGC_COLOR(colorGreen, "#009431", "#009431", "#00e04b", "#00e04b")
    65. DECLARE_QGC_COLOR(colorOrange, "#b95604", "#b95604", "#de8500", "#de8500")
    66. DECLARE_QGC_COLOR(colorRed, "#ed3939", "#ed3939", "#f32836", "#f32836")
    67. DECLARE_QGC_COLOR(colorGrey, "#808080", "#808080", "#bfbfbf", "#bfbfbf")
    68. DECLARE_QGC_COLOR(colorBlue, "#1a72ff", "#1a72ff", "#536dff", "#536dff")
    69. DECLARE_QGC_COLOR(alertBackground, "#eecc44", "#eecc44", "#eecc44", "#eecc44")
    70. DECLARE_QGC_COLOR(alertBorder, "#808080", "#808080", "#808080", "#808080")
    71. DECLARE_QGC_COLOR(alertText, "#000000", "#000000", "#000000", "#000000")
    72. DECLARE_QGC_COLOR(missionItemEditor, "#585858", "#dbfef8", "#585858", "#585d83")
    73. DECLARE_QGC_COLOR(toolStripHoverColor, "#585858", "#9D9D9D", "#585858", "#585d83")
    74. DECLARE_QGC_COLOR(statusFailedText, "#9d9d9d", "#000000", "#707070", "#ffffff")
    75. DECLARE_QGC_COLOR(statusPassedText, "#9d9d9d", "#000000", "#707070", "#ffffff")
    76. DECLARE_QGC_COLOR(statusPendingText, "#9d9d9d", "#000000", "#707070", "#ffffff")
    77. DECLARE_QGC_COLOR(toolbarBackground, "#ffffff", "#ffffff", "#222222", "#222222")
    78. // Colors not affecting by theming 不受主题影响的颜色
    79. // Disabled Enabled
    80. DECLARE_QGC_NONTHEMED_COLOR(brandingPurple, "#4A2C6D", "#4A2C6D")
    81. DECLARE_QGC_NONTHEMED_COLOR(brandingBlue, "#48D6FF", "#6045c5")
    82. DECLARE_QGC_NONTHEMED_COLOR(toolStripFGColor, "#707070", "#ffffff")
    83. // Colors not affecting by theming or enable/disable 不受主题或启用/禁用影响的颜色
    84. DECLARE_QGC_SINGLE_COLOR(mapWidgetBorderLight, "#ffffff")
    85. DECLARE_QGC_SINGLE_COLOR(mapWidgetBorderDark, "#000000")
    86. DECLARE_QGC_SINGLE_COLOR(mapMissionTrajectory, "#be781c")
    87. DECLARE_QGC_SINGLE_COLOR(surveyPolygonInterior, "green")
    88. DECLARE_QGC_SINGLE_COLOR(surveyPolygonTerrainCollision, "red")
    89. }
    90. //对外接口 设置ColorGroupEnabled
    91. void QGCPalette::setColorGroupEnabled(bool enabled)
    92. {
    93. _colorGroupEnabled = enabled;
    94. emit paletteChanged();
    95. }
    96. //对外接口 设置GlobalTheme
    97. void QGCPalette::setGlobalTheme(Theme newTheme)
    98. {
    99. // Mobile build does not have themes
    100. if (_theme != newTheme) {
    101. _theme = newTheme;
    102. _signalPaletteChangeToAll();
    103. }
    104. }
    105. //将主题发生变化的信号发送给所有注册的对象
    106. void QGCPalette::_signalPaletteChangeToAll()
    107. {
    108. // Notify all objects of the new theme 通知新主题的所有对象
    109. foreach (QGCPalette* palette, _paletteObjects) {
    110. palette->_signalPaletteChanged();
    111. }
    112. }
    113. void QGCPalette::_signalPaletteChanged()
    114. {
    115. emit paletteChanged();
    116. }

    七.QGCQGeoCoordinate

    此类主要定义了一个继承自QObject的QGeoCoordinate,它可以在QmlObjectListModel上使用。

    代码如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. #include
    12. /// This is a QGeoCoordinate within a QObject such that it can be used on a QmlObjectListModel
    13. /// 这是一个继承自QObject的QGeoCoordinate,它可以在QmlObjectListModel上使用
    14. class QGCQGeoCoordinate : public QObject
    15. {
    16. Q_OBJECT
    17. public:
    18. QGCQGeoCoordinate(const QGeoCoordinate& coord, QObject* parent = nullptr);
    19. //定义coordinate属性 和set get 和信号 函数
    20. Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
    21. //脏数据
    22. Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
    23. QGeoCoordinate coordinate (void) const { return _coordinate; }
    24. void setCoordinate (const QGeoCoordinate& coordinate);
    25. bool dirty (void) const { return _dirty; }
    26. void setDirty (bool dirty);
    27. signals:
    28. void coordinateChanged (QGeoCoordinate coordinate);
    29. void dirtyChanged (bool dirty);
    30. private:
    31. QGeoCoordinate _coordinate;
    32. bool _dirty;
    33. };
    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "QGCQGeoCoordinate.h"
    10. #include
    11. QGCQGeoCoordinate::QGCQGeoCoordinate(const QGeoCoordinate& coord, QObject* parent)
    12. : QObject (parent)
    13. , _coordinate (coord)
    14. , _dirty (false)
    15. {
    16. //设置该对象的从属关系是cpp而不是qml https://blog.csdn.net/baidu_41388533/article/details/116973961
    17. QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
    18. }
    19. void QGCQGeoCoordinate::setCoordinate(const QGeoCoordinate& coordinate)
    20. {
    21. //不相等则修改
    22. if (_coordinate != coordinate) {
    23. _coordinate = coordinate;
    24. emit coordinateChanged(coordinate);
    25. setDirty(true);
    26. }
    27. }
    28. void QGCQGeoCoordinate::setDirty(bool dirty)
    29. {
    30. if (_dirty != dirty) {
    31. _dirty = dirty;
    32. emit dirtyChanged(dirty);
    33. }
    34. }

    八.QGCTemporaryFile

    该类主要模仿QTemporaryFile,主要用于创建临时文件,打开临时文件,删除临时文件。代码如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #pragma once
    10. #include
    11. /// @file
    12. /// @brief This class mimics QTemporaryFile. We have our own implementation due to the fact that
    13. /// QTemporaryFile implemenation differs cross platform making it unusable for our use-case.
    14. /// Look for bug reports on QTemporaryFile keeping the file locked for details.
    15. /// 这个类模仿QTemporaryFile。 我们有自己的实现,因为 QTemporaryFile在跨平台上的实现是不同的,这使得它在我们的用例中不可用。 详细信息请查看QTemporaryFile上的bug报告。
    16. /// @author Don Gagne
    17. class QGCTemporaryFile : public QFile {
    18. Q_OBJECT
    19. public:
    20. /// @brief Creates a new temp file object. QGC temp files are always created in the
    21. /// QStandardPaths::TempLocation directory.
    22. /// 创建一个新的临时文件对象。 QGC临时文件总是创建在QStandardPaths::TempLocation目录中。
    23. /// @param template Template for file name following QTemporaryFile rules. Template should NOT include
    24. /// directory path, only file name.
    25. /// QTemporaryFile规则下的文件名模板。 模板不应包含 目录路径,只有文件名。
    26. QGCTemporaryFile(const QString& fileTemplate, QObject* parent = nullptr);
    27. ~QGCTemporaryFile();
    28. bool open(OpenMode openMode = ReadWrite);
    29. void setAutoRemove(bool autoRemove) { _autoRemove = autoRemove; }
    30. private:
    31. static QString _newTempFileFullyQualifiedName(const QString& fileTemplate);
    32. QString _template;
    33. bool _autoRemove = false;
    34. };
    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. /// @file
    10. /// @brief This class mimics QTemporaryFile. We have our own implementation due to the fact that
    11. /// QTemporaryFile implemenation differs cross platform making it unusable for our use-case.
    12. /// Look for bug reports on QTemporaryFile keeping the file locked for details.
    13. ///
    14. /// @author Don Gagne
    15. #include "QGCTemporaryFile.h"
    16. #include
    17. #include
    18. #include
    19. QGCTemporaryFile::QGCTemporaryFile(const QString& fileTemplate, QObject* parent) :
    20. QFile(parent),
    21. _template(fileTemplate)
    22. {
    23. }
    24. QGCTemporaryFile::~QGCTemporaryFile()
    25. {
    26. //在析构函数中,判断属性_autoRemove 如果是这自动删除文件
    27. if (_autoRemove) {
    28. remove();
    29. }
    30. }
    31. bool QGCTemporaryFile::open(QFile::OpenMode openMode)
    32. {
    33. //设置名称
    34. setFileName(_newTempFileFullyQualifiedName(_template));
    35. return QFile::open(openMode);
    36. }
    37. QString QGCTemporaryFile::_newTempFileFullyQualifiedName(const QString& fileTemplate)
    38. {
    39. QString nameTemplate = fileTemplate;
    40. //创建文件夹 QStandardPaths::TempLocation
    41. QDir tempDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
    42. // Generate unique, non-existing filename 生成惟一的、不存在的文件名
    43. static const char rgDigits[] = "0123456789";
    44. QString tempFilename;
    45. do {
    46. QString uniqueStr;
    47. for (int i=0; i<6; i++) {
    48. uniqueStr += rgDigits[QRandomGenerator::global()->generate() % 10];
    49. }
    50. if (fileTemplate.contains("XXXXXX")) {
    51. tempFilename = nameTemplate.replace("XXXXXX", uniqueStr, Qt::CaseSensitive);
    52. } else {
    53. tempFilename = nameTemplate + uniqueStr;
    54. }
    55. } while (tempDir.exists(tempFilename));
    56. return tempDir.filePath(tempFilename);
    57. }

    九.QGCToolbox

    此类管理所有的上层服务和插件,提供了QGCToolbox和QGCTool,所有的插件和服务都继承自QGCTool,QGCTool又继承自QObject,但在构造时构造父类的时候传入了QGCToolbox。QGCToolbox在构造时创建了所有插件和服务。

    我的理解是,首先QGCToolbox被构建,在构造函数中,

    例如,当我执行第一个 SettingsManager的创建时,SettingsManager的构造函数被执行。

     构造函数中调用了QGCTool,和一些初始化操作。QGCTool的构造函数具体做了什么。

     主要看初始化父类这里,将toolbox设置为了QGCTool的父类。于是这里我的理解是:QGCToolBox首先拥有所有的插件和服务,然后这些插件和服务的父类又指向QGCToolBox,第二步骤在QGCToolBox完成初始后,再调用setToolbox函数设置toolbox,从而实现每个插件和服务是可以获取其他插件和服务的。下面放出代码:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #ifndef QGCToolbox_h
    10. #define QGCToolbox_h
    11. #include
    12. class FactSystem; //自动校准系统
    13. class FirmwarePluginManager; //固件插件管理
    14. class AudioOutput; //音频输出
    15. class GPSManager; //gps管理
    16. class JoystickManager; //手柄管理
    17. class FollowMe; //跟随我
    18. class LinkManager; //连接管理
    19. class MAVLinkProtocol; //mavlink协议
    20. class MissionCommandTree; //任务命令管理
    21. class MultiVehicleManager; //多设备管理
    22. class QGCMapEngineManager; //地图引擎管理
    23. class QGCApplication; //qgc应用
    24. class QGCImageProvider; //图像提供者
    25. class UASMessageHandler; //网络无人机系操作类
    26. class QGCPositionManager; //位置管理
    27. class VideoManager; //视频管理
    28. class MAVLinkLogManager; //mavlink协议管理
    29. class QGCCorePlugin; //核心插件
    30. class SettingsManager; //设置管理
    31. class AirspaceManager; //空域管理
    32. class ADSBVehicleManager; //空对空监视设备管理
    33. #if defined(QGC_ENABLE_PAIRING)
    34. class PairingManager;
    35. #endif
    36. #if defined(QGC_GST_TAISYNC_ENABLED)
    37. class TaisyncManager;
    38. #endif
    39. #if defined(QGC_GST_MICROHARD_ENABLED)
    40. class MicrohardManager;
    41. #endif
    42. /// This is used to manage all of our top level services/tools
    43. /// 这用于管理我们所有的上层服务/工具
    44. class QGCToolbox : public QObject {
    45. Q_OBJECT
    46. public:
    47. QGCToolbox(QGCApplication* app);
    48. //定义公有接口
    49. FirmwarePluginManager* firmwarePluginManager () { return _firmwarePluginManager; }
    50. AudioOutput* audioOutput () { return _audioOutput; }
    51. JoystickManager* joystickManager () { return _joystickManager; }
    52. LinkManager* linkManager () { return _linkManager; }
    53. MAVLinkProtocol* mavlinkProtocol () { return _mavlinkProtocol; }
    54. MissionCommandTree* missionCommandTree () { return _missionCommandTree; }
    55. MultiVehicleManager* multiVehicleManager () { return _multiVehicleManager; }
    56. QGCMapEngineManager* mapEngineManager () { return _mapEngineManager; }
    57. QGCImageProvider* imageProvider () { return _imageProvider; }
    58. UASMessageHandler* uasMessageHandler () { return _uasMessageHandler; }
    59. FollowMe* followMe () { return _followMe; }
    60. QGCPositionManager* qgcPositionManager () { return _qgcPositionManager; }
    61. VideoManager* videoManager () { return _videoManager; }
    62. MAVLinkLogManager* mavlinkLogManager () { return _mavlinkLogManager; }
    63. QGCCorePlugin* corePlugin () { return _corePlugin; }
    64. SettingsManager* settingsManager () { return _settingsManager; }
    65. AirspaceManager* airspaceManager () { return _airspaceManager; }
    66. ADSBVehicleManager* adsbVehicleManager () { return _adsbVehicleManager; }
    67. #if defined(QGC_ENABLE_PAIRING)
    68. PairingManager* pairingManager () { return _pairingManager; }
    69. #endif
    70. #ifndef __mobile__
    71. GPSManager* gpsManager () { return _gpsManager; }
    72. #endif
    73. #if defined(QGC_GST_TAISYNC_ENABLED)
    74. TaisyncManager* taisyncManager () { return _taisyncManager; }
    75. #endif
    76. #if defined(QGC_GST_MICROHARD_ENABLED)
    77. MicrohardManager* microhardManager () { return _microhardManager; }
    78. #endif
    79. private:
    80. //设置子toolbox
    81. void setChildToolboxes(void);
    82. //扫描和加载插件
    83. void _scanAndLoadPlugins(QGCApplication *app);
    84. //定义私有变量
    85. AudioOutput* _audioOutput = nullptr;
    86. FactSystem* _factSystem = nullptr;
    87. FirmwarePluginManager* _firmwarePluginManager = nullptr;
    88. #ifndef __mobile__
    89. GPSManager* _gpsManager = nullptr;
    90. #endif
    91. QGCImageProvider* _imageProvider = nullptr;
    92. JoystickManager* _joystickManager = nullptr;
    93. LinkManager* _linkManager = nullptr;
    94. MAVLinkProtocol* _mavlinkProtocol = nullptr;
    95. MissionCommandTree* _missionCommandTree = nullptr;
    96. MultiVehicleManager* _multiVehicleManager = nullptr;
    97. QGCMapEngineManager* _mapEngineManager = nullptr;
    98. UASMessageHandler* _uasMessageHandler = nullptr;
    99. FollowMe* _followMe = nullptr;
    100. QGCPositionManager* _qgcPositionManager = nullptr;
    101. VideoManager* _videoManager = nullptr;
    102. MAVLinkLogManager* _mavlinkLogManager = nullptr;
    103. QGCCorePlugin* _corePlugin = nullptr;
    104. SettingsManager* _settingsManager = nullptr;
    105. AirspaceManager* _airspaceManager = nullptr;
    106. ADSBVehicleManager* _adsbVehicleManager = nullptr;
    107. #if defined(QGC_ENABLE_PAIRING)
    108. PairingManager* _pairingManager = nullptr;
    109. #endif
    110. #if defined(QGC_GST_TAISYNC_ENABLED)
    111. TaisyncManager* _taisyncManager = nullptr;
    112. #endif
    113. #if defined(QGC_GST_MICROHARD_ENABLED)
    114. MicrohardManager* _microhardManager = nullptr;
    115. #endif
    116. //定义友元类
    117. friend class QGCApplication;
    118. };
    119. /// This is the base class for all tools
    120. /// 这是所有工具类的基类
    121. class QGCTool : public QObject {
    122. Q_OBJECT
    123. public:
    124. // All tools must be parented to the QGCToolbox and go through a two phase creation. In the constructor the toolbox
    125. // should only be passed to QGCTool constructor for correct parenting. It should not be referenced or set in the
    126. // protected member. Then in the second phase of setToolbox calls is where you can reference the toolbox.、
    127. //所有的工具都必须被父级导入到QGCToolbox中,并经过两个阶段的创建。
    128. //在构造函数中,工具箱应该只传递给QGCTool构造函数,以便进行正确的加载。
    129. //不应该在受保护的成员中引用或设置它。 然后,在setToolbox调用的第二阶段是可以引用工具箱的地方。
    130. QGCTool(QGCApplication* app, QGCToolbox* toolbox);
    131. // If you override this method, you must call the base class.
    132. // 如果重写这个方法你必须调用这个基类方法
    133. virtual void setToolbox(QGCToolbox* toolbox);
    134. protected:
    135. QGCApplication* _app;
    136. QGCToolbox* _toolbox;
    137. };
    138. #endif
    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "FactSystem.h"
    10. #include "FirmwarePluginManager.h"
    11. #include "AudioOutput.h"
    12. #ifndef __mobile__
    13. #include "GPSManager.h"
    14. #endif
    15. #include "JoystickManager.h"
    16. #include "LinkManager.h"
    17. #include "MAVLinkProtocol.h"
    18. #include "MissionCommandTree.h"
    19. #include "MultiVehicleManager.h"
    20. #include "QGCImageProvider.h"
    21. #include "UASMessageHandler.h"
    22. #include "QGCMapEngineManager.h"
    23. #include "FollowMe.h"
    24. #include "PositionManager.h"
    25. #include "VideoManager.h"
    26. #include "MAVLinkLogManager.h"
    27. #include "QGCCorePlugin.h"
    28. #include "QGCOptions.h"
    29. #include "SettingsManager.h"
    30. #include "QGCApplication.h"
    31. #include "ADSBVehicleManager.h"
    32. #if defined(QGC_ENABLE_PAIRING)
    33. #include "PairingManager.h"
    34. #endif
    35. #if defined(QGC_AIRMAP_ENABLED)
    36. #include "AirMapManager.h"
    37. #else
    38. #include "AirspaceManager.h"
    39. #endif
    40. #if defined(QGC_GST_TAISYNC_ENABLED)
    41. #include "TaisyncManager.h"
    42. #endif
    43. #if defined(QGC_GST_MICROHARD_ENABLED)
    44. #include "MicrohardManager.h"
    45. #endif
    46. #if defined(QGC_CUSTOM_BUILD)
    47. #include CUSTOMHEADER
    48. #endif
    49. QGCToolbox::QGCToolbox(QGCApplication* app)
    50. {
    51. // SettingsManager must be first so settings are available to any subsequent tools
    52. // SettingsManager必须是第一个,这样之后的任何工具都可以使用设置
    53. // 以下这些类都继承自QGCTool
    54. _settingsManager = new SettingsManager (app, this);
    55. //-- Scan and load plugins
    56. _scanAndLoadPlugins(app);
    57. _audioOutput = new AudioOutput (app, this);
    58. _factSystem = new FactSystem (app, this);
    59. _firmwarePluginManager = new FirmwarePluginManager (app, this);
    60. #ifndef __mobile__
    61. _gpsManager = new GPSManager (app, this);
    62. #endif
    63. _imageProvider = new QGCImageProvider (app, this);
    64. _joystickManager = new JoystickManager (app, this);
    65. _linkManager = new LinkManager (app, this);
    66. _mavlinkProtocol = new MAVLinkProtocol (app, this);
    67. _missionCommandTree = new MissionCommandTree (app, this);
    68. _multiVehicleManager = new MultiVehicleManager (app, this);
    69. _mapEngineManager = new QGCMapEngineManager (app, this);
    70. _uasMessageHandler = new UASMessageHandler (app, this);
    71. _qgcPositionManager = new QGCPositionManager (app, this);
    72. _followMe = new FollowMe (app, this);
    73. _videoManager = new VideoManager (app, this);
    74. _mavlinkLogManager = new MAVLinkLogManager (app, this);
    75. _adsbVehicleManager = new ADSBVehicleManager (app, this);
    76. #if defined(QGC_ENABLE_PAIRING)
    77. _pairingManager = new PairingManager (app, this);
    78. #endif
    79. //-- Airmap Manager
    80. //-- This should be "pluggable" so an arbitrary AirSpace manager can be used 他应该是“可插拔的”,这样就可以使用任意的空域管理器
    81. //-- For now, we instantiate the one and only AirMap provider 现在,我们实例化唯一的AirMap提供程序
    82. #if defined(QGC_AIRMAP_ENABLED)
    83. _airspaceManager = new AirMapManager (app, this);
    84. #else
    85. _airspaceManager = new AirspaceManager (app, this);
    86. #endif
    87. #if defined(QGC_GST_TAISYNC_ENABLED)
    88. _taisyncManager = new TaisyncManager (app, this);
    89. #endif
    90. #if defined(QGC_GST_MICROHARD_ENABLED)
    91. _microhardManager = new MicrohardManager (app, this);
    92. #endif
    93. }
    94. void QGCToolbox::setChildToolboxes(void)
    95. {
    96. // SettingsManager must be first so settings are available to any subsequent tools
    97. _settingsManager->setToolbox(this);
    98. _corePlugin->setToolbox(this);
    99. _audioOutput->setToolbox(this);
    100. _factSystem->setToolbox(this);
    101. _firmwarePluginManager->setToolbox(this);
    102. #ifndef __mobile__
    103. _gpsManager->setToolbox(this);
    104. #endif
    105. _imageProvider->setToolbox(this);
    106. _joystickManager->setToolbox(this);
    107. _linkManager->setToolbox(this);
    108. _mavlinkProtocol->setToolbox(this);
    109. _missionCommandTree->setToolbox(this);
    110. _multiVehicleManager->setToolbox(this);
    111. _mapEngineManager->setToolbox(this);
    112. _uasMessageHandler->setToolbox(this);
    113. _followMe->setToolbox(this);
    114. _qgcPositionManager->setToolbox(this);
    115. _videoManager->setToolbox(this);
    116. _mavlinkLogManager->setToolbox(this);
    117. _airspaceManager->setToolbox(this);
    118. _adsbVehicleManager->setToolbox(this);
    119. #if defined(QGC_GST_TAISYNC_ENABLED)
    120. _taisyncManager->setToolbox(this);
    121. #endif
    122. #if defined(QGC_GST_MICROHARD_ENABLED)
    123. _microhardManager->setToolbox(this);
    124. #endif
    125. #if defined(QGC_ENABLE_PAIRING)
    126. _pairingManager->setToolbox(this);
    127. #endif
    128. }
    129. void QGCToolbox::_scanAndLoadPlugins(QGCApplication* app)
    130. {
    131. //利用宏定义加载插件
    132. #if defined (QGC_CUSTOM_BUILD)
    133. //-- Create custom plugin (Static)
    134. _corePlugin = (QGCCorePlugin*) new CUSTOMCLASS(app, this);
    135. if(_corePlugin) {
    136. return;
    137. }
    138. #endif
    139. //-- No plugins found, use default instance
    140. _corePlugin = new QGCCorePlugin(app, this);
    141. }
    142. QGCTool::QGCTool(QGCApplication* app, QGCToolbox* toolbox)
    143. : QObject(toolbox)
    144. , _app(app)
    145. , _toolbox(nullptr)
    146. {
    147. }
    148. void QGCTool::setToolbox(QGCToolbox* toolbox)
    149. {
    150. _toolbox = toolbox;
    151. }

    十.RunGuard

    这个类主要是对共享内存的操作,感觉和guard守卫的意思没多大关系,整个代码都是在介绍对共享内存的申请,绑定,释放还有锁和随机key的生成这些操作,具体代码的注释已经放在代码中。

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #ifndef RunGuard_H
    10. #define RunGuard_H
    11. #include
    12. #include
    13. #include
    14. //顾名思义 运行守卫
    15. class RunGuard
    16. {
    17. public:
    18. //构造函数用key创建
    19. RunGuard( const QString& key );
    20. ~RunGuard();
    21. //是否是另外的运行程序
    22. bool isAnotherRunning();
    23. //尝试运行
    24. bool tryToRun();
    25. //释放
    26. void release();
    27. private:
    28. //键
    29. const QString key;
    30. //内存锁键
    31. const QString memLockKey;
    32. //共享内存键
    33. const QString sharedmemKey;
    34. //共享内存
    35. QSharedMemory sharedMem;
    36. //内存锁
    37. QSystemSemaphore memLock;
    38. //Q_DISABLE_COPY宏作用是禁止对给定的类使用复制构造函数和赋值运算符。
    39. Q_DISABLE_COPY( RunGuard )
    40. };
    41. #endif
    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "RunGuard.h"
    10. #include
    11. namespace
    12. {
    13. //key生成函数
    14. QString generateKeyHash( const QString& key, const QString& salt )
    15. {
    16. QByteArray data;
    17. data.append( key.toUtf8() );
    18. data.append( salt.toUtf8() );
    19. data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();
    20. return data;
    21. }
    22. }
    23. //构造函数 构造时使用锁
    24. RunGuard::RunGuard( const QString& key )
    25. : key( key )
    26. , memLockKey( generateKeyHash( key, "_memLockKey" ) )
    27. , sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
    28. , sharedMem( sharedmemKey )
    29. , memLock( memLockKey, 1 )
    30. {
    31. memLock.acquire();
    32. {
    33. //QSharedMemory 类提供了对一段共享内存的访问。既提供了被多进程和多线程共享的一段内存的访问。也为单线程或单进程锁定内存以实现互斥访问提供了方法。
    34. // 详见 https://blog.csdn.net/ddllrrbb/article/details/82729671
    35. QSharedMemory fix( sharedmemKey ); // Fix for *nix: http://habrahabr.ru/post/173281/
    36. //试图将进程附着在通过key所标识的共享内存段上
    37. fix.attach();
    38. }
    39. memLock.release();
    40. }
    41. RunGuard::~RunGuard()
    42. {
    43. release();
    44. }
    45. bool RunGuard::isAnotherRunning()
    46. {
    47. //如果当前内存已经被附着返回false
    48. if ( sharedMem.isAttached() )
    49. return false;
    50. //锁
    51. memLock.acquire();
    52. //进行附着,如果附着成功返回true
    53. const bool isRunning = sharedMem.attach();
    54. //如果附着不成功则进行将进程和共享内存段分离
    55. if ( isRunning )
    56. sharedMem.detach();
    57. memLock.release();
    58. return isRunning;
    59. }
    60. bool RunGuard::tryToRun()
    61. {
    62. //isRunning返回true 则这里返回false
    63. if ( isAnotherRunning() ) // Extra check
    64. return false;
    65. //否则isRunning返回false则进行锁操作
    66. memLock.acquire();
    67. //创建一段大小为8byte共享内存
    68. const bool result = sharedMem.create( sizeof( quint64 ) );
    69. memLock.release();
    70. if ( !result )
    71. {
    72. release();
    73. return false;
    74. }
    75. return true;
    76. }
    77. void RunGuard::release()
    78. {
    79. memLock.acquire();
    80. if ( sharedMem.isAttached() )
    81. sharedMem.detach();
    82. memLock.release();
    83. }

    十一.TerrainTile

    这个类主要是用于地形数据的读取,计算,加载,解析。主要注释都加载代码中。

    头文件如下:

    1. #ifndef TERRAINTILE_H
    2. #define TERRAINTILE_H
    3. #include "QGCLoggingCategory.h"
    4. #include
    5. //相当于 extern const QLoggingCategory &TerrainTileLog();
    6. //具体声明在cc文件中解释
    7. Q_DECLARE_LOGGING_CATEGORY(TerrainTileLog)
    8. /**
    9. * @brief The TerrainTile class
    10. * 实现https://developers.airmap.com/v2.0/docs/elevation-api的接口
    11. * Implements an interface for https://developers.airmap.com/v2.0/docs/elevation-api
    12. */
    13. class TerrainTile
    14. {
    15. public:
    16. TerrainTile();
    17. ~TerrainTile();
    18. /**
    19. * Constructor from serialized elevation data (either from file or web)
    20. * 构造函数从序列化的海拔数据(从文件或web)
    21. * @param document
    22. */
    23. TerrainTile(QByteArray byteArray);
    24. /**
    25. * Check whether valid data is loaded
    26. * 检查是否加载了有效数据
    27. * @return true if data is valid
    28. */
    29. bool isValid(void) const { return _isValid; }
    30. /**
    31. * Evaluates the elevation at the given coordinate
    32. * 计算给定坐标上的海拔高度
    33. * @param coordinate
    34. * @return elevation
    35. */
    36. double elevation(const QGeoCoordinate& coordinate) const;
    37. /**
    38. * Accessor for the minimum elevation of the tile
    39. * 获取瓦片的最小高度
    40. * @return minimum elevation
    41. */
    42. double minElevation(void) const { return _minElevation; }
    43. /**
    44. * Accessor for the maximum elevation of the tile
    45. * 获取瓦片的最大高度
    46. * @return maximum elevation
    47. */
    48. double maxElevation(void) const { return _maxElevation; }
    49. /**
    50. * Accessor for the average elevation of the tile
    51. * 获取瓦片的平均高度
    52. * @return average elevation
    53. */
    54. double avgElevation(void) const { return _avgElevation; }
    55. /**
    56. * Accessor for the center coordinate
    57. * 中心坐标的访问器
    58. * @return center coordinate
    59. */
    60. QGeoCoordinate centerCoordinate(void) const;
    61. //序列化数据从map的json数据中
    62. static QByteArray serializeFromAirMapJson(QByteArray input);
    63. ///< Each terrain tile represents a square area .01 degrees in lat/lon
    64. /// 每个地形贴图代表一个纬度/经度0.01度的正方形区域
    65. static constexpr double tileSizeDegrees = 0.01;
    66. ///< 1 Arc-Second spacing of elevation values
    67. /// 1arc秒间距的高度值
    68. static constexpr double tileValueSpacingDegrees = 1.0 / 3600;
    69. static constexpr double tileValueSpacingMeters = 30.0;
    70. private:
    71. typedef struct {
    72. double swLat,swLon, neLat, neLon;
    73. int16_t minElevation;
    74. int16_t maxElevation;
    75. double avgElevation;
    76. int16_t gridSizeLat;
    77. int16_t gridSizeLon;
    78. } TileInfo_t;
    79. QGeoCoordinate _southWest; /// South west corner of the tile 西南角的瓦片
    80. QGeoCoordinate _northEast; /// North east corner of the tile 东北角的瓦片
    81. int16_t _minElevation; /// Minimum elevation in tile 瓦片上的最小海拔高度
    82. int16_t _maxElevation; /// Maximum elevation in tile 瓦片上的最大海拔高度
    83. double _avgElevation; /// Average elevation of the tile 瓦片上的平均海拔高度
    84. int16_t** _data; /// 2D elevation data array 2维海拔高度数组
    85. int16_t _gridSizeLat; /// data grid size in latitude direction 纬度方向的数据网格大小
    86. int16_t _gridSizeLon; /// data grid size in longitude direction 经度方向的数据网格大小
    87. bool _isValid; /// data loaded is valid 加载的数据是否可用
    88. // Json keys
    89. static const char* _jsonStatusKey;
    90. static const char* _jsonDataKey;
    91. static const char* _jsonBoundsKey;
    92. static const char* _jsonSouthWestKey;
    93. static const char* _jsonNorthEastKey;
    94. static const char* _jsonStatsKey;
    95. static const char* _jsonMaxElevationKey;
    96. static const char* _jsonMinElevationKey;
    97. static const char* _jsonAvgElevationKey;
    98. static const char* _jsonCarpetKey;
    99. };
    100. #endif // TERRAINTILE_H

    cc文件如下:

    1. /****************************************************************************
    2. *
    3. * (c) 2009-2020 QGROUNDCONTROL PROJECT
    4. *
    5. * QGroundControl is licensed according to the terms in the file
    6. * COPYING.md in the root of the source code directory.
    7. *
    8. ****************************************************************************/
    9. #include "TerrainTile.h"
    10. #include "JsonHelper.h"
    11. #include "QGCMapEngine.h"
    12. #include "QGC.h"
    13. #include
    14. #include
    15. #include
    16. #include
    17. #include
    18. // 等价于
    19. // static QGCLoggingCategory qgcCategoryTerrainTileLog("TerrainTileLog");
    20. // const QLoggingCategory &TerrainTileLog()
    21. // {
    22. // static const QLoggingCategory category("TerrainTileLog");
    23. // return category;
    24. // }
    25. QGC_LOGGING_CATEGORY(TerrainTileLog, "TerrainTileLog");
    26. const char* TerrainTile::_jsonStatusKey = "status";
    27. const char* TerrainTile::_jsonDataKey = "data";
    28. const char* TerrainTile::_jsonBoundsKey = "bounds";
    29. const char* TerrainTile::_jsonSouthWestKey = "sw";
    30. const char* TerrainTile::_jsonNorthEastKey = "ne";
    31. const char* TerrainTile::_jsonStatsKey = "stats";
    32. const char* TerrainTile::_jsonMaxElevationKey = "max";
    33. const char* TerrainTile::_jsonMinElevationKey = "min";
    34. const char* TerrainTile::_jsonAvgElevationKey = "avg";
    35. const char* TerrainTile::_jsonCarpetKey = "carpet";
    36. TerrainTile::TerrainTile()
    37. : _minElevation(-1.0)
    38. , _maxElevation(-1.0)
    39. , _avgElevation(-1.0)
    40. , _data(nullptr)
    41. , _gridSizeLat(-1)
    42. , _gridSizeLon(-1)
    43. , _isValid(false)
    44. {
    45. }
    46. TerrainTile::~TerrainTile()
    47. {
    48. if (_data) {
    49. for (int i = 0; i < _gridSizeLat; i++) {
    50. delete[] _data[i];
    51. }
    52. delete[] _data;
    53. _data = nullptr;
    54. }
    55. }
    56. TerrainTile::TerrainTile(QByteArray byteArray)
    57. : _minElevation(-1.0)
    58. , _maxElevation(-1.0)
    59. , _avgElevation(-1.0)
    60. , _data(nullptr)
    61. , _gridSizeLat(-1)
    62. , _gridSizeLon(-1)
    63. , _isValid(false)
    64. {
    65. //计算结构体TileInfo_t的大小作为 header
    66. int cTileHeaderBytes = static_cast<int>(sizeof(TileInfo_t));
    67. //计算byteArray的大小作为TileBytes
    68. int cTileBytesAvailable = byteArray.size();
    69. //大小不能比头还小
    70. if (cTileBytesAvailable < cTileHeaderBytes) {
    71. qWarning() << "Terrain tile binary data too small for TileInfo_s header";
    72. return;
    73. }
    74. //byteArray转为TileInfo_t
    75. // reinterpret_cast可以允许任何指针类型(引用)之间的转换,整型与指针类型间的转换以及指针与足够大的整型之间的转换。
    76. // reinterpret_cast转换的实质是让编译器重新给出对象的比例模型而不进行二值转换。也就是让编译器按照目标转换类型在内存中所占的比特位重新编译原始数据类型。转换前后对象的地址值是不变的,只是对象的读取内存的比例变了而已。
    77. // reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。
    78. // 与static_cast
    79. // 通常这个运算符用来进行数值类型间的转化,比如int到float,也可以是自定义的某些数据类型的转化。这个操作符通常也可以用于类指针之间的转化,但是这个运算符在父类到子类的转化中,没有做检查并不安全。
    80. const TileInfo_t* tileInfo = reinterpret_cast<const TileInfo_t*>(byteArray.constData());
    81. //读取完成后设置值
    82. _southWest.setLatitude(tileInfo->swLat);
    83. _southWest.setLongitude(tileInfo->swLon);
    84. _northEast.setLatitude(tileInfo->neLat);
    85. _northEast.setLongitude(tileInfo->neLon);
    86. _minElevation = tileInfo->minElevation;
    87. _maxElevation = tileInfo->maxElevation;
    88. _avgElevation = tileInfo->avgElevation;
    89. _gridSizeLat = tileInfo->gridSizeLat;
    90. _gridSizeLon = tileInfo->gridSizeLon;
    91. //QLoggingCategory可以控制打印输出类别和模块。方便在调试时,过滤掉不关心的打印信息
    92. qCDebug(TerrainTileLog) << "Loading terrain tile: " << _southWest << " - " << _northEast;
    93. qCDebug(TerrainTileLog) << "min:max:avg:sizeLat:sizeLon" << _minElevation << _maxElevation << _avgElevation << _gridSizeLat << _gridSizeLon;
    94. int cTileDataBytes = static_cast<int>(sizeof(int16_t)) * _gridSizeLat * _gridSizeLon;
    95. if (cTileBytesAvailable < cTileHeaderBytes + cTileDataBytes) {
    96. qWarning() << "Terrain tile binary data too small for tile data";
    97. return;
    98. }
    99. //创建二维数组
    100. _data = new int16_t*[_gridSizeLat];
    101. for (int k = 0; k < _gridSizeLat; k++) {
    102. _data[k] = new int16_t[_gridSizeLon];
    103. }
    104. int valueIndex = 0;
    105. //首先将输入的bytearray转为8bit的数组然后将下标行进到header的尾部
    106. //然后将head后的数据转为16bit的数组,头后边的数据正是要放入二维数组的数据
    107. const int16_t* pTileData = reinterpret_cast<const int16_t*>(&reinterpret_cast<const uint8_t*>(byteArray.constData())[cTileHeaderBytes]);
    108. //设置二维网格数据的值
    109. for (int i = 0; i < _gridSizeLat; i++) {
    110. for (int j = 0; j < _gridSizeLon; j++) {
    111. _data[i][j] = pTileData[valueIndex++];
    112. }
    113. }
    114. _isValid = true;
    115. return;
    116. }
    117. double TerrainTile::elevation(const QGeoCoordinate& coordinate) const
    118. {
    119. if (_isValid && _southWest.isValid() && _northEast.isValid()) {
    120. qCDebug(TerrainTileLog) << "elevation: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast;
    121. // The lat/lon values in _northEast and _southWest coordinates can have rounding errors such that the coordinate
    122. // request may be slightly outside the tile box specified by these values. So we clamp the incoming values to the
    123. // edges of the tile if needed.
    124. //在_northEast和_southWest坐标中的lat/lon值可能有误差,从而使坐标要求可能略超出这些值指定的瓦片框。 所以如果需要我们对传入值进行差值在贴图的边缘。
    125. //求当前坐标和西南角的最大经度
    126. double clampedLon = qMax(coordinate.longitude(), _southWest.longitude());
    127. //求当前坐标和西南角的最大维度
    128. double clampedLat = qMax(coordinate.latitude(), _southWest.latitude());
    129. // Calc the index of the southernmost and westernmost index data value
    130. // 求最南和最西索引数据值的索引
    131. int lonIndex = qFloor((clampedLon - _southWest.longitude()) / tileValueSpacingDegrees);
    132. int latIndex = qFloor((clampedLat - _southWest.latitude()) / tileValueSpacingDegrees);
    133. // Calc how far along in between the known values the requested lat/lon is fractionally
    134. //计算在已知值和请求的lat/lon之间有多远
    135. double lonIndexLongitude = _southWest.longitude() + (static_cast<double>(lonIndex) * tileValueSpacingDegrees);
    136. double lonFraction = (clampedLon - lonIndexLongitude) / tileValueSpacingDegrees;
    137. double latIndexLatitude = _southWest.latitude() + (static_cast<double>(latIndex) * tileValueSpacingDegrees);
    138. double latFraction = (clampedLat - latIndexLatitude) / tileValueSpacingDegrees;
    139. // Calc the elevation as the average across the four known points
    140. // 用四个已知点的平均值来计算海拔高度
    141. double known00 = _data[latIndex][lonIndex];
    142. double known01 = _data[latIndex][lonIndex+1];
    143. double known10 = _data[latIndex+1][lonIndex];
    144. double known11 = _data[latIndex+1][lonIndex+1];
    145. double lonValue1 = known00 + ((known01 - known00) * lonFraction);
    146. double lonValue2 = known10 + ((known11 - known10) * lonFraction);
    147. double latValue = lonValue1 + ((lonValue2 - lonValue1) * latFraction);
    148. return latValue;
    149. } else {
    150. qCWarning(TerrainTileLog) << "elevation: Internal error - invalid tile";
    151. return qQNaN();
    152. }
    153. }
    154. QGeoCoordinate TerrainTile::centerCoordinate(void) const
    155. {
    156. return _southWest.atDistanceAndAzimuth(_southWest.distanceTo(_northEast) / 2.0, _southWest.azimuthTo(_northEast));
    157. }
    158. QByteArray TerrainTile::serializeFromAirMapJson(QByteArray input)
    159. {
    160. QJsonParseError parseError;
    161. QJsonDocument document = QJsonDocument::fromJson(input, &parseError);
    162. if (parseError.error != QJsonParseError::NoError) {
    163. QByteArray emptyArray;
    164. return emptyArray;
    165. }
    166. if (!document.isObject()) {
    167. qCDebug(TerrainTileLog) << "Terrain tile json doc is no object";
    168. QByteArray emptyArray;
    169. return emptyArray;
    170. }
    171. //json解析完成
    172. QJsonObject rootObject = document.object();
    173. QString errorString;
    174. // typedef struct {
    175. // const char* key; ///< json key name
    176. // QJsonValue::Type type; ///< required type for key, QJsonValue::Null specifies double with possible NaN
    177. // bool required; ///< true: key must be present
    178. // } KeyValidateInfo;
    179. QList rootVersionKeyInfoList = {
    180. { _jsonStatusKey, QJsonValue::String, true },
    181. { _jsonDataKey, QJsonValue::Object, true },
    182. };
    183. if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) {
    184. qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
    185. QByteArray emptyArray;
    186. return emptyArray;
    187. }
    188. if (rootObject[_jsonStatusKey].toString() != "success") {
    189. qCDebug(TerrainTileLog) << "Invalid terrain tile.";
    190. QByteArray emptyArray;
    191. return emptyArray;
    192. }
    193. const QJsonObject& dataObject = rootObject[_jsonDataKey].toObject();
    194. QList dataVersionKeyInfoList = {
    195. { _jsonBoundsKey, QJsonValue::Object, true },
    196. { _jsonStatsKey, QJsonValue::Object, true },
    197. { _jsonCarpetKey, QJsonValue::Array, true },
    198. };
    199. if (!JsonHelper::validateKeys(dataObject, dataVersionKeyInfoList, errorString)) {
    200. qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
    201. QByteArray emptyArray;
    202. return emptyArray;
    203. }
    204. // Bounds
    205. const QJsonObject& boundsObject = dataObject[_jsonBoundsKey].toObject();
    206. QList boundsVersionKeyInfoList = {
    207. { _jsonSouthWestKey, QJsonValue::Array, true },
    208. { _jsonNorthEastKey, QJsonValue::Array, true },
    209. };
    210. if (!JsonHelper::validateKeys(boundsObject, boundsVersionKeyInfoList, errorString)) {
    211. qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
    212. QByteArray emptyArray;
    213. return emptyArray;
    214. }
    215. const QJsonArray& swArray = boundsObject[_jsonSouthWestKey].toArray();
    216. const QJsonArray& neArray = boundsObject[_jsonNorthEastKey].toArray();
    217. if (swArray.count() < 2 || neArray.count() < 2 ) {
    218. qCDebug(TerrainTileLog) << "Incomplete bounding location";
    219. QByteArray emptyArray;
    220. return emptyArray;
    221. }
    222. // Stats
    223. const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
    224. QList statsVersionKeyInfoList = {
    225. { _jsonMinElevationKey, QJsonValue::Double, true },
    226. { _jsonMaxElevationKey, QJsonValue::Double, true },
    227. { _jsonAvgElevationKey, QJsonValue::Double, true },
    228. };
    229. if (!JsonHelper::validateKeys(statsObject, statsVersionKeyInfoList, errorString)) {
    230. qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
    231. QByteArray emptyArray;
    232. return emptyArray;
    233. }
    234. // Carpet
    235. const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
    236. int gridSizeLat = carpetArray.count();
    237. int gridSizeLon = carpetArray[0].toArray().count();
    238. TileInfo_t tileInfo;
    239. tileInfo.swLat = swArray[0].toDouble();
    240. tileInfo.swLon = swArray[1].toDouble();
    241. tileInfo.neLat = neArray[0].toDouble();
    242. tileInfo.neLon = neArray[1].toDouble();
    243. tileInfo.minElevation = static_cast<int16_t>(statsObject[_jsonMinElevationKey].toInt());
    244. tileInfo.maxElevation = static_cast<int16_t>(statsObject[_jsonMaxElevationKey].toInt());
    245. tileInfo.avgElevation = statsObject[_jsonAvgElevationKey].toDouble();
    246. tileInfo.gridSizeLat = static_cast<int16_t>(gridSizeLat);
    247. tileInfo.gridSizeLon = static_cast<int16_t>(gridSizeLon);
    248. // We require 1-arc second value spacing
    249. double neCornerLatExpected = tileInfo.swLat + ((tileInfo.gridSizeLat - 1) * tileValueSpacingDegrees);
    250. double neCornerLonExpected = tileInfo.swLon + ((tileInfo.gridSizeLon - 1) * tileValueSpacingDegrees);
    251. if (!QGC::fuzzyCompare(tileInfo.neLat, neCornerLatExpected) || !QGC::fuzzyCompare(tileInfo.neLon, neCornerLonExpected)) {
    252. qCWarning(TerrainTileLog) << QStringLiteral("serialize: Internal error - distance between values incorrect neExpected(%1, %2) neActual(%3, %4) sw(%5, %6) gridSize(%7, %8)")
    253. .arg(neCornerLatExpected).arg(neCornerLonExpected).arg(tileInfo.neLat).arg(tileInfo.neLon).arg(tileInfo.swLat).arg(tileInfo.swLon).arg(tileInfo.gridSizeLat).arg(tileInfo.gridSizeLon);
    254. QByteArray emptyArray;
    255. return emptyArray;
    256. }
    257. int cTileHeaderBytes = static_cast<int>(sizeof(TileInfo_t));
    258. int cTileDataBytes = static_cast<int>(sizeof(int16_t)) * gridSizeLat * gridSizeLon;
    259. QByteArray byteArray(cTileHeaderBytes + cTileDataBytes, 0);
    260. //这里和读取的方法对应
    261. TileInfo_t* pTileInfo = reinterpret_cast(byteArray.data());
    262. int16_t* pTileData = reinterpret_cast<int16_t*>(&reinterpret_cast<uint8_t*>(byteArray.data())[cTileHeaderBytes]);
    263. *pTileInfo = tileInfo;
    264. int valueIndex = 0;
    265. for (int i = 0; i < gridSizeLat; i++) {
    266. const QJsonArray& row = carpetArray[i].toArray();
    267. if (row.count() < gridSizeLon) {
    268. qCDebug(TerrainTileLog) << "Expected row array of " << gridSizeLon << ", instead got " << row.count();
    269. QByteArray emptyArray;
    270. return emptyArray;
    271. }
    272. for (int j = 0; j < gridSizeLon; j++) {
    273. pTileData[valueIndex++] = static_cast<int16_t>(row[j].toDouble());
    274. }
    275. }
    276. return byteArray;
    277. }

    总结

    这篇文章主要介绍了QGC开头的几个文件,大多还是一些工具类,如日志,toolbox工具箱,调色板,共享内存守卫,地形数据,文件下载,临时文件管理等,细心的朋友可能发现,其中QGCApplicaion和main没有介绍,是因为这两个文件里含有大量的还没接触到的文件和类,所以这里我准备先搁置一下。下篇我将按照文件夹的顺序进行代码的解读首先是ADSB文件夹下的代码,并尽量了解工作原理。

  • 相关阅读:
    【vue3】匿名插槽,具名插槽,作用域插槽,动态插槽
    android 动画
    HTTP 1.0 和 HTTP 1.1的主要区别
    基于优先级的时间片轮转调度算法(C语言实现)
    【Linux】文本编辑器Vim(Vim的操作方法、命令集,Vim插件安装配置)
    解决npm install报错: No module named gyp
    AI Agent涌向移动终端,手机智能体开启跨端跨应用业务连接新场景
    02 Redis的基本数据结构和常用命令
    【5G MAC】随机接入流程中的 Msg3 —— Scheduled UL (PUSCH) Transmission
    Windows11下安装k8s
  • 原文地址:https://blog.csdn.net/weixin_43409627/article/details/126905093