From e756b86da8d6abb14e914879bf34aa56caf1da76 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Wed, 15 Dec 2021 16:56:05 -0700 Subject: [PATCH] use streams for garmin_fit debug messages. (#795) * use streams for garmin_fit debug messages. This eliminates the Qt 6 warnings related to the change in types for container sizes and the format specifier. * retire debug_print() * make logging debug single arg ctors explicit --- CMakeLists.txt | 1 + GPSBabel.pro | 1 + defs.h | 1 - fatal.cc | 13 ----- garmin_fit.cc | 134 +++++++++++++++++++++++--------------------- src/core/logging.cc | 31 ++++++++++ src/core/logging.h | 19 +++++++ 7 files changed, 122 insertions(+), 78 deletions(-) create mode 100644 src/core/logging.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index cee6224d9..f562b5ec8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,7 @@ set(SUPPORT rgbcolors.cc route.cc session.cc + src/core/logging.cc src/core/nvector.cc src/core/textstream.cc src/core/usasciicodec.cc diff --git a/GPSBabel.pro b/GPSBabel.pro index 2926027d7..2d1ebccdc 100644 --- a/GPSBabel.pro +++ b/GPSBabel.pro @@ -207,6 +207,7 @@ SUPPORT = \ rgbcolors.cc \ route.cc \ session.cc \ + src/core/logging.cc \ src/core/nvector.cc \ src/core/textstream.cc \ src/core/usasciicodec.cc \ diff --git a/defs.h b/defs.h index 820232e0d..b57b1ed95 100644 --- a/defs.h +++ b/defs.h @@ -1060,7 +1060,6 @@ extern const QVector style_list; [[noreturn]] void fatal(const char*, ...) PRINTFLIKE(1, 2); void is_fatal(int condition, const char*, ...) PRINTFLIKE(2, 3); void warning(const char*, ...) PRINTFLIKE(1, 2); -void debug_print(int level, const char* fmt, ...) PRINTFLIKE(2,3); void printposn(double c, int is_lat); diff --git a/fatal.cc b/fatal.cc index a28667d36..7ddff28a0 100644 --- a/fatal.cc +++ b/fatal.cc @@ -56,16 +56,3 @@ warning(const char* fmt, ...) vfprintf(stderr, fmt, ap); va_end(ap); } - -void -debug_print(int level, const char* fmt, ...) -{ - va_list ap; - for (int i = 1; i= 1) { - debug_print(1,"%s: header len=%d\n", MYNAME, len); + Debug(1) << MYNAME ": header len=" << len; } int ver = gbfgetc(fin); @@ -99,7 +99,7 @@ GarminFitFormat::fit_parse_header() fatal(MYNAME ": Unsupported protocol version %d.%d\n", ver >> 4, ver & 0xf); if (global_opts.debug_level >= 1) { - debug_print(1,"%s: protocol version=%d\n", MYNAME, ver); + Debug(1) << MYNAME ": protocol version=" << ver; } // profile version @@ -114,8 +114,8 @@ GarminFitFormat::fit_parse_header() } if (global_opts.debug_level >= 1) { - debug_print(1,"%s: profile version=%d\n", MYNAME, ver); - debug_print(1,"%s: fit_data.len=%d\n", MYNAME, fit_data.len); + Debug(1) << MYNAME ": profile version=" << ver; + Debug(1) << MYNAME ": fit_data.len=" << fit_data.len; } // Header CRC may be omitted entirely @@ -139,7 +139,7 @@ GarminFitFormat::fit_parse_header() fatal(FatalMsg().nospace() << MYNAME ": File " << fin->name << " is corrupt. Use recoverymode option at your risk."); } } else if (global_opts.debug_level >= 1) { - debug_print(1, MYNAME ": Header CRC verified.\n"); + Debug(1) << MYNAME ": Header CRC verified."; } } } @@ -147,9 +147,9 @@ GarminFitFormat::fit_parse_header() QFileInfo fi(fin->name); qint64 size = fi.size(); if ((len + fit_data.len + 2) != size) { - Warning() << MYNAME ": File size" << size << "is not expected given header len" << len << ", data length" << fit_data.len << "and a 2 byte file CRC."; + Warning().nospace() << MYNAME ": File size " << size << " is not expected given header len " << len << ", data length " << fit_data.len << " and a 2 byte file CRC."; } else if (global_opts.debug_level >= 1) { - debug_print(1, MYNAME ": File size matches expectations from information in the header.\n"); + Debug(1) << MYNAME ": File size matches expectations from information in the header."; } gbfseek(fin, len, SEEK_SET); @@ -249,7 +249,7 @@ GarminFitFormat::fit_parse_definition_message(uint8_t header) // byte 5 has the number of records in the remainder of the definition message int num_fields = fit_getuint8(); if (global_opts.debug_level >= 8) { - debug_print(8,"%s: definition message contains %d records\n",MYNAME, num_fields); + Debug(8) << MYNAME ": definition message contains " << num_fields << " records"; } // remainder of the definition message is data at one byte per field * 3 fields @@ -259,8 +259,9 @@ GarminFitFormat::fit_parse_definition_message(uint8_t header) int type = fit_getuint8(); fit_field_t field = {id, size, type}; if (global_opts.debug_level >= 8) { - debug_print(8,"%s: record %d ID: %d SIZE: %d TYPE: %d fit_data.len=%d\n", - MYNAME, i, field.id, field.size, field.type, fit_data.len); + Debug(8) << MYNAME ": record " << i << " ID: " << field.id << " SIZE: " + << field.size << " TYPE: " << field.type << " fit_data.len=" + << fit_data.len; } def.fields.append(field); } @@ -290,7 +291,7 @@ GarminFitFormat::fit_parse_definition_message(uint8_t header) if (hasDevFields) { int numOfDevFields = fit_getuint8(); if (global_opts.debug_level >= 8) { - debug_print(8,"%s: definition message contains %d developer records\n",MYNAME, numOfDevFields); + Debug(8) << MYNAME ": definition message contains " << numOfDevFields << " developer records"; } if (numOfDevFields > 0) { int numOfFields = num_fields + numOfDevFields; @@ -300,8 +301,9 @@ GarminFitFormat::fit_parse_definition_message(uint8_t header) int type = fit_getuint8(); fit_field_t field = {id, size, type}; if (global_opts.debug_level >= 8) { - debug_print(8,"%s: developer record %d ID: %d SIZE: %d TYPE: %d fit_data.len=%d\n", - MYNAME, i - num_fields, field.id, field.size, field.type, fit_data.len); + Debug(8) << MYNAME ": developer record " << i - num_fields << + " ID: " << field.id << " SIZE: " << field.size << + " TYPE: " << field.type << " fit_data.len=" << fit_data.len; } // Because we parse developer fields like normal fields and we do not want // that the field id interfere which valid id's from the normal fields @@ -328,8 +330,9 @@ GarminFitFormat::fit_read_field(const fit_field_t& f) // otherwise we just skip over the data. if (global_opts.debug_level >= 8) { - debug_print(8,"%s: fit_read_field: read data field with f.type=0x%X and f.size=%d fit_data.len=%d\n", - MYNAME, f.type, f.size, fit_data.len); + Debug(8) << MYNAME ": fit_read_field: read data field with f.type=0x" << + Qt::hex << f.type << " and f.size=" << + Qt::dec << f.size << " fit_data.len=" << fit_data.len; } switch (f.type) { case 0: // enum @@ -342,7 +345,7 @@ GarminFitFormat::fit_read_field(const fit_field_t& f) fit_getuint8(); } if (global_opts.debug_level >= 8) { - debug_print(8, "%s: fit_read_field: skipping 1-byte array data\n", MYNAME); + Debug(8) << MYNAME ": fit_read_field: skipping 1-byte array data"; } return -1; } @@ -358,7 +361,7 @@ GarminFitFormat::fit_read_field(const fit_field_t& f) fit_getuint8(); } if (global_opts.debug_level >= 8) { - debug_print(8, "%s: fit_read_field: skipping 2-byte array data\n", MYNAME); + Debug(8) << MYNAME ": fit_read_field: skipping 2-byte array data"; } return -1; } @@ -371,7 +374,7 @@ GarminFitFormat::fit_read_field(const fit_field_t& f) fit_getuint8(); } if (global_opts.debug_level >= 8) { - debug_print(8, "%s: fit_read_field: skipping 4-byte array data\n", MYNAME); + Debug(8) << MYNAME ": fit_read_field: skipping 4-byte array data"; } return -1; } @@ -380,7 +383,7 @@ GarminFitFormat::fit_read_field(const fit_field_t& f) fit_getuint8(); } if (global_opts.debug_level >= 8) { - debug_print(8, "%s: fit_read_field: skipping unrecognized data type\n", MYNAME); + Debug(8) << MYNAME ": fit_read_field: skipping unrecognized data type"; } return -1; } @@ -409,11 +412,11 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) QString description; if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data ID %d with num_fields=%d\n", MYNAME, def.global_id, def.fields.size()); + Debug(7) << MYNAME ": parsing fit data ID " << def.global_id << " with num_fields=" << def.fields.size(); } for (int i = 0; i < def.fields.size(); ++i) { if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing field %d\n", MYNAME, i); + Debug(7) << MYNAME ": parsing field " << i; } const fit_field_t& f = def.fields.at(i); QVariant field = fit_read_field(f); @@ -423,7 +426,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) } if (f.id == kFieldTimestamp) { if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: timestamp=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: timestamp=" << static_cast(val); } timestamp = val; // if the timestamp is < 0x10000000, this value represents @@ -438,13 +441,13 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) switch (f.id) { case kFieldGlobalUtcOffset: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: global utc_offset=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: global utc_offset=" << static_cast(val); } fit_data.global_utc_offset = val; break; default: if (global_opts.debug_level >= 1) { - debug_print(1, "%s: unrecognized data type in GARMIN FIT device settings: f.id=%d\n", MYNAME, f.id); + Debug(1) << MYNAME ": unrecognized data type in GARMIN FIT device settings: f.id=" << f.id; } break; } // switch (f.id) @@ -455,19 +458,19 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) switch (f.id) { case kFieldLatitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: lat=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: lat=" << static_cast(val); } lat = val; break; case kFieldLongitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: lon=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: lon=" << static_cast(val); } lon = val; break; case kFieldAltitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: alt=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: alt=" << static_cast(val); } if (val != 0xffff) { alt = val; @@ -475,25 +478,25 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; case kFieldHeartRate: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: heartrate=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: heartrate=" << static_cast(val); } heartrate = val; break; case kFieldCadence: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: cadence=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: cadence=" << static_cast(val); } cadence = val; break; case kFieldDistance: // NOTE: 5 is DISTANCE in cm ... unused. if (global_opts.debug_level >= 7) { - debug_print(7, "%s: unrecognized data type in GARMIN FIT record: f.id=%d\n", MYNAME, f.id); + Debug(7) << MYNAME ": unrecognized data type in GARMIN FIT record: f.id=" << f.id; } break; case kFieldSpeed: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: speed=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: speed=" << static_cast(val); } if (val != 0xffff) { speed = val; @@ -501,19 +504,19 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; case kFieldPower: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: power=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: power=" << static_cast(val); } power = val; break; case kFieldTemperature: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: temperature=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: temperature=" << static_cast(val); } temperature = val; break; case kFieldEnhancedSpeed: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: enhanced_speed=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: enhanced_speed=" << static_cast(val); } if (val != 0xffff) { speed = val; @@ -521,7 +524,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; case kFieldEnhancedAltitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: enhanced_altitude=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: enhanced_altitude=" << static_cast(val); } if (val != 0xffff) { alt = val; @@ -529,7 +532,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; default: if (global_opts.debug_level >= 1) { - debug_print(1, "%s: unrecognized data type in GARMIN FIT record: f.id=%d\n", MYNAME, f.id); + Debug(1) << MYNAME ": unrecognized data type in GARMIN FIT record: f.id=" << f.id; } break; } // switch (f.id) @@ -540,49 +543,49 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) switch (f.id) { case kFieldStartTime: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: starttime=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: starttime=" << static_cast(val); } //starttime = val; break; case kFieldStartLatitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: startlat=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: startlat=" << static_cast(val); } //startlat = val; break; case kFieldStartLongitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: startlon=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: startlon=" << static_cast(val); } //startlon = val; break; case kFieldEndLatitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: endlat=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: endlat=" << static_cast(val); } endlat = val; break; case kFieldEndLongitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: endlon=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: endlon=" << static_cast(val); } endlon = val; break; case kFieldElapsedTime: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: elapsedtime=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: elapsedtime=" << static_cast(val); } //elapsedtime = val; break; case kFieldTotalDistance: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: totaldistance=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: totaldistance=" << static_cast(val); } //totaldistance = val; break; default: if (global_opts.debug_level >= 1) { - debug_print(1, "%s: unrecognized data type in GARMIN FIT lap: f.id=%d\n", MYNAME, f.id); + Debug(1) << MYNAME ": unrecognized data type in GARMIN FIT lap: f.id=" << f.id; } break; } // switch (f.id) @@ -593,13 +596,13 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) switch (f.id) { case kFieldEvent: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: event=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: event=" << static_cast(val); } event = val; break; case kFieldEventType: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: eventtype=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: eventtype=" << static_cast(val); } eventtype = val; break; @@ -611,19 +614,19 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) switch (f.id) { case kFieldLocLatitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: lat=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: lat=" << static_cast(val); } lat = val; break; case kFieldLocLongitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: lon=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: lon=" << static_cast(val); } lon = val; break; case kFieldLocAltitude: if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: alt=%d\n", MYNAME, val); + Debug(7) << MYNAME ": parsing fit data: alt=" << static_cast(val); } if (val != 0xffff) { alt = val; @@ -632,18 +635,18 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) case kFieldLocationName: name = field.toString(); if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: location name=%s\n", MYNAME, qPrintable(name)); + Debug(7) << MYNAME ": parsing fit data: location name=" << name; } break; case kFieldLocationDescription: description = field.toString(); if (global_opts.debug_level >= 7) { - debug_print(7,"%s: parsing fit data: location description=%s\n", MYNAME, qPrintable(description)); + Debug(7) << MYNAME ": parsing fit data: location description=" << description; } break; default: if (global_opts.debug_level >= 1) { - debug_print(1, "%s: unrecognized data type in GARMIN FIT locations: f.id=%d\n", MYNAME, f.id); + Debug(1) << MYNAME ": unrecognized data type in GARMIN FIT locations: f.id=" << f.id; } break; } // switch (f.id) @@ -651,7 +654,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; default: if (global_opts.debug_level >= 1) { - debug_print(1, "%s: unrecognized/unhandled global ID for GARMIN FIT: %d\n", MYNAME, def.global_id); + Debug(1) << MYNAME ": unrecognized/unhandled global ID for GARMIN FIT: " << def.global_id; } break; } // switch (def.global_id) @@ -659,7 +662,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) } if (global_opts.debug_level >= 7) { - debug_print(7,"%s: storing fit data with num_fields=%d\n", MYNAME, def.fields.size()); + Debug(7) << MYNAME ": storing fit data with num_fields=" << def.fields.size(); } switch (def.global_id) { case kIdLap: { // lap message @@ -667,7 +670,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; } if (global_opts.debug_level >= 7) { - debug_print(7,"%s: storing fit data LAP %d\n", MYNAME, def.global_id); + Debug(7) << MYNAME ": storing fit data LAP " << def.global_id; } auto* lappt = new Waypoint; lappt->latitude = GPS_Math_Semi_To_Deg(endlat); @@ -728,7 +731,7 @@ GarminFitFormat::fit_parse_data(const fit_message_def& def, int time_offset) break; } if (global_opts.debug_level >= 7) { - debug_print(7,"%s: storing fit data location %d\n", MYNAME, def.global_id); + Debug(7) << MYNAME ": storing fit data location " << def.global_id; } auto* locpt = new Waypoint; locpt->latitude = GPS_Math_Semi_To_Deg(lat); @@ -788,20 +791,23 @@ GarminFitFormat::fit_parse_record() // bits 3..0 -> local message type if (header & 0x80) { if (global_opts.debug_level >= 6) { - debug_print(6,"%s: got compressed message at file position 0x%x, fit_data.len=%d", MYNAME, position, fit_data.len); - debug_print(0," ...local message type 0x%X\n", header&0x0f); + Debug(6) << MYNAME ": got compressed message at file position 0x" << + Qt::hex << position << ", fit_data.len=" << Qt::dec << fit_data.len + << " ...local message type 0x" << Qt::hex << (header & 0x0f); } fit_parse_compressed_message(header); } else if (header & 0x40) { if (global_opts.debug_level >= 6) { - debug_print(6,"%s: got definition message at file position 0x%x, fit_data.len=%d", MYNAME, position, fit_data.len); - debug_print(0," ...local message type 0x%X\n", header&0x0f); + Debug(6) << MYNAME ": got definition message at file position 0x" << + Qt::hex << position << ", fit_data.len=" << Qt::dec << fit_data.len + << " ...local message type 0x" << Qt::hex << (header & 0x0f); } fit_parse_definition_message(header); } else { if (global_opts.debug_level >= 6) { - debug_print(6,"%s: got data message at file position 0x%x, fit_data.len=%d", MYNAME, position, fit_data.len); - debug_print(0," ...local message type 0x%X\n", header&0x0f); + Debug(6) << MYNAME ": got data message at file position 0x" << + Qt::hex << position << ", fit_data.len=" << Qt::dec << fit_data.len + << " ...local message type 0x" << Qt::hex << (header & 0x0f); } fit_parse_data_message(header); } @@ -829,7 +835,7 @@ GarminFitFormat::fit_check_file_crc() const fatal(FatalMsg().nospace() << MYNAME ": File " << fin->name << " is corrupt. Use recoverymode option at your risk."); } } else if (global_opts.debug_level >= 1) { - debug_print(1, MYNAME ": File CRC verified.\n"); + Debug(1) << MYNAME ": File CRC verified."; } gbfseek(fin, position, SEEK_SET); @@ -850,7 +856,7 @@ GarminFitFormat::read() fit_data.track = new route_head; track_add_head(fit_data.track); if (global_opts.debug_level >= 1) { - debug_print(1,"%s: starting to read data with fit_data.len=%d\n", MYNAME, fit_data.len); + Debug(1) << MYNAME ": starting to read data with fit_data.len=" << fit_data.len; } try { while (fit_data.len) { diff --git a/src/core/logging.cc b/src/core/logging.cc new file mode 100644 index 000000000..f6e1a31d6 --- /dev/null +++ b/src/core/logging.cc @@ -0,0 +1,31 @@ +/* + Copyright (C) 2021 Robert Lipe, robertlipe+source@gpsbabel.org + + 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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#include // for QDebug + +#include "src/core/logging.h" + + +QDebug operator<< (QDebug debug, const DebugIndent& indent) +{ + for (int i = 1; i