├── LICENSE ├── README.md ├── lib └── qrencode │ ├── include │ └── qrencode.h │ └── libqrencode.a ├── qqrencode ├── libqtqrencode_global.h ├── qqrencode.cpp ├── qqrencode.h ├── qqrencode.pro └── qqrencode_p.h ├── qtqrencode.pro └── test ├── main.cpp ├── qqrencodetestsuite.cpp ├── qqrencodetestsuite.h ├── test.pro ├── testrunner.cpp └── testrunner.h /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014 Neal Sebastian, https://github.com/yoneal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## qtqrencode 2 | 3 | Qt 5 wrapper and renderer for [qrencode](https://github.com/fukuchi/libqrencode) (QR Code encoding) library. 4 | 5 | ## Build 6 | 7 | You will need [Qt 5+](http://qt-project.org/downloads) and [qrencode 3.4+](http://fukuchi.org/works/qrencode). Clone this repo and build it with Qt's qmake: 8 | ```bash 9 | sudo apt-get install libqrencode-dev 10 | git clone https://github.com/yoneal/qtqrencode 11 | cd qtqrencode 12 | mkdir build && cd build 13 | qmake -Wall ../qtqrencode.pro 14 | make 15 | # You can install it, if you want.. 16 | sudo make install 17 | ``` 18 | Or, you can just open the project using Qt Creator. 19 | 20 | ## Usage 21 | 22 | Just grab the library, along with the following header files: 23 | 24 | * qqrencode.h 25 | * libqtqrencode_global.h 26 | 27 | Then include it in your project like so, 28 | ``` 29 | LIBS += -lqtqrencode 30 | ``` 31 | 32 | No need to manually copy the files if you installed it in the system directories.. 33 | 34 | ## Profit 35 | ``` 36 | #include 37 | 38 | ... 39 | 40 | QQREncode encoder; 41 | encoder.encode(QString("abcdefghijklmnopqrstuvwxyz 1234567890$%*+-./:"); 42 | QImage qrcode = encoder.toQImage(); 43 | qrcode.scaled(150,150).save("qrcode.jpg","JPG"); 44 | ``` 45 | 46 | See [test](test) folder for more examples. 47 | 48 | ## Thanks 49 | 50 | Thanks to [Kentaro Fukuchi](http://fukuchi.org) for sharing qrencode. 51 | -------------------------------------------------------------------------------- /lib/qrencode/include/qrencode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * qrencode - QR Code encoder 3 | * 4 | * Copyright (C) 2006-2012 Kentaro Fukuchi 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /** \mainpage 22 | * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D 23 | * symbology. 24 | * 25 | * \section encoding Encoding 26 | * 27 | * There are two methods to encode data: encoding a string/data or 28 | * encoding a structured data. 29 | * 30 | * \subsection encoding-string Encoding a string/data 31 | * You can encode a string by calling QRcode_encodeString(). 32 | * The given string is parsed automatically and encoded. If you want to encode 33 | * data that can be represented as a C string style (NUL terminated), you can 34 | * simply use this way. 35 | * 36 | * If the input data contains Kanji (Shift-JIS) characters and you want to 37 | * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint. 38 | * Otherwise, all of non-alphanumeric characters are encoded as 8 bit data. 39 | * If you want to encode a whole string in 8 bit mode, you can use 40 | * QRcode_encodeString8bit() instead. 41 | * 42 | * Please note that a C string can not contain NUL characters. If your data 43 | * contains NUL, you must use QRcode_encodeData(). 44 | * 45 | * \subsection encoding-input Encoding a structured data 46 | * You can construct a structured input data manually. If the structure of the 47 | * input data is known, you can use this way. 48 | * At first, create a ::QRinput object by QRinput_new(). Then add input data 49 | * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput() 50 | * to encode the QRinput data. 51 | * You can reuse the QRinput data again to encode it in other symbols with 52 | * different parameters. 53 | * 54 | * \section result Result 55 | * The encoded symbol is resulted as a ::QRcode object. It will contain 56 | * its version number, width of the symbol and an array represents the symbol. 57 | * See ::QRcode for the details. You can free the object by QRcode_free(). 58 | * 59 | * Please note that the version of the result may be larger than specified. 60 | * In such cases, the input data would be too large to be encoded in a 61 | * symbol of the specified version. 62 | * 63 | * \section structured Structured append 64 | * Libqrencode can generate "Structured-appended" symbols that enables to split 65 | * a large data set into mulitple QR codes. A QR code reader concatenates 66 | * multiple QR code symbols into a string. 67 | * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured() 68 | * to generate structured-appended symbols. This functions returns an instance 69 | * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you 70 | * can retrieve each QR code in this way: 71 | * 72 | * \code 73 | * QRcode_List *qrcodes; 74 | * QRcode_List *entry; 75 | * QRcode *qrcode; 76 | * 77 | * qrcodes = QRcode_encodeStringStructured(...); 78 | * entry = qrcodes; 79 | * while(entry != NULL) { 80 | * qrcode = entry->code; 81 | * // do something 82 | * entry = entry->next; 83 | * } 84 | * QRcode_List_free(entry); 85 | * \endcode 86 | * 87 | * Instead of using auto-parsing functions, you can construct your own 88 | * structured input. At first, instantiate an object of ::QRinput_Struct 89 | * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput, 90 | * and one QR code is generated for a ::QRinput. 91 | * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct 92 | * object. In order to generate structured-appended symbols, it is required to 93 | * embed headers to each symbol. You can use 94 | * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate 95 | * headers to each symbol. You should call this function just once before 96 | * encoding symbols. 97 | */ 98 | 99 | #ifndef __QRENCODE_H__ 100 | #define __QRENCODE_H__ 101 | 102 | #if defined(__cplusplus) 103 | extern "C" { 104 | #endif 105 | 106 | /** 107 | * Encoding mode. 108 | */ 109 | typedef enum { 110 | QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only 111 | QR_MODE_NUM = 0, ///< Numeric mode 112 | QR_MODE_AN, ///< Alphabet-numeric mode 113 | QR_MODE_8, ///< 8-bit data mode 114 | QR_MODE_KANJI, ///< Kanji (shift-jis) mode 115 | QR_MODE_STRUCTURE, ///< Internal use only 116 | QR_MODE_ECI, ///< ECI mode 117 | QR_MODE_FNC1FIRST, ///< FNC1, first position 118 | QR_MODE_FNC1SECOND, ///< FNC1, second position 119 | } QRencodeMode; 120 | 121 | /** 122 | * Level of error correction. 123 | */ 124 | typedef enum { 125 | QR_ECLEVEL_L = 0, ///< lowest 126 | QR_ECLEVEL_M, 127 | QR_ECLEVEL_Q, 128 | QR_ECLEVEL_H ///< highest 129 | } QRecLevel; 130 | 131 | /** 132 | * Maximum version (size) of QR-code symbol. 133 | */ 134 | #define QRSPEC_VERSION_MAX 40 135 | 136 | /** 137 | * Maximum version (size) of QR-code symbol. 138 | */ 139 | #define MQRSPEC_VERSION_MAX 4 140 | 141 | 142 | /****************************************************************************** 143 | * Input data (qrinput.c) 144 | *****************************************************************************/ 145 | 146 | /** 147 | * Singly linked list to contain input strings. An instance of this class 148 | * contains its version and error correction level too. It is required to 149 | * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(), 150 | * or use QRinput_new2() to instantiate an object. 151 | */ 152 | typedef struct _QRinput QRinput; 153 | 154 | /** 155 | * Instantiate an input data object. The version is set to 0 (auto-select) 156 | * and the error correction level is set to QR_ECLEVEL_L. 157 | * @return an input object (initialized). On error, NULL is returned and errno 158 | * is set to indicate the error. 159 | * @throw ENOMEM unable to allocate memory. 160 | */ 161 | extern QRinput *QRinput_new(void); 162 | 163 | /** 164 | * Instantiate an input data object. 165 | * @param version version number. 166 | * @param level Error correction level. 167 | * @return an input object (initialized). On error, NULL is returned and errno 168 | * is set to indicate the error. 169 | * @throw ENOMEM unable to allocate memory for input objects. 170 | * @throw EINVAL invalid arguments. 171 | */ 172 | extern QRinput *QRinput_new2(int version, QRecLevel level); 173 | 174 | /** 175 | * Instantiate an input data object. Object's Micro QR Code flag is set. 176 | * Unlike with full-sized QR Code, version number must be specified (>0). 177 | * @param version version number (1--4). 178 | * @param level Error correction level. 179 | * @return an input object (initialized). On error, NULL is returned and errno 180 | * is set to indicate the error. 181 | * @throw ENOMEM unable to allocate memory for input objects. 182 | * @throw EINVAL invalid arguments. 183 | */ 184 | extern QRinput *QRinput_newMQR(int version, QRecLevel level); 185 | 186 | /** 187 | * Append data to an input object. 188 | * The data is copied and appended to the input object. 189 | * @param input input object. 190 | * @param mode encoding mode. 191 | * @param size size of data (byte). 192 | * @param data a pointer to the memory area of the input data. 193 | * @retval 0 success. 194 | * @retval -1 an error occurred and errno is set to indeicate the error. 195 | * See Execptions for the details. 196 | * @throw ENOMEM unable to allocate memory. 197 | * @throw EINVAL input data is invalid. 198 | * 199 | */ 200 | extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data); 201 | 202 | /** 203 | * Append ECI header. 204 | * @param input input object. 205 | * @param ecinum ECI indicator number (0 - 999999) 206 | * @retval 0 success. 207 | * @retval -1 an error occurred and errno is set to indeicate the error. 208 | * See Execptions for the details. 209 | * @throw ENOMEM unable to allocate memory. 210 | * @throw EINVAL input data is invalid. 211 | * 212 | */ 213 | extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum); 214 | 215 | /** 216 | * Get current version. 217 | * @param input input object. 218 | * @return current version. 219 | */ 220 | extern int QRinput_getVersion(QRinput *input); 221 | 222 | /** 223 | * Set version of the QR code that is to be encoded. 224 | * This function cannot be applied to Micro QR Code. 225 | * @param input input object. 226 | * @param version version number (0 = auto) 227 | * @retval 0 success. 228 | * @retval -1 invalid argument. 229 | */ 230 | extern int QRinput_setVersion(QRinput *input, int version); 231 | 232 | /** 233 | * Get current error correction level. 234 | * @param input input object. 235 | * @return Current error correcntion level. 236 | */ 237 | extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input); 238 | 239 | /** 240 | * Set error correction level of the QR code that is to be encoded. 241 | * This function cannot be applied to Micro QR Code. 242 | * @param input input object. 243 | * @param level Error correction level. 244 | * @retval 0 success. 245 | * @retval -1 invalid argument. 246 | */ 247 | extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level); 248 | 249 | /** 250 | * Set version and error correction level of the QR code at once. 251 | * This function is recommened for Micro QR Code. 252 | * @param input input object. 253 | * @param version version number (0 = auto) 254 | * @param level Error correction level. 255 | * @retval 0 success. 256 | * @retval -1 invalid argument. 257 | */ 258 | extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level); 259 | 260 | /** 261 | * Free the input object. 262 | * All of data chunks in the input object are freed too. 263 | * @param input input object. 264 | */ 265 | extern void QRinput_free(QRinput *input); 266 | 267 | /** 268 | * Validate the input data. 269 | * @param mode encoding mode. 270 | * @param size size of data (byte). 271 | * @param data a pointer to the memory area of the input data. 272 | * @retval 0 success. 273 | * @retval -1 invalid arguments. 274 | */ 275 | extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data); 276 | 277 | /** 278 | * Set of QRinput for structured symbols. 279 | */ 280 | typedef struct _QRinput_Struct QRinput_Struct; 281 | 282 | /** 283 | * Instantiate a set of input data object. 284 | * @return an instance of QRinput_Struct. On error, NULL is returned and errno 285 | * is set to indicate the error. 286 | * @throw ENOMEM unable to allocate memory. 287 | */ 288 | extern QRinput_Struct *QRinput_Struct_new(void); 289 | 290 | /** 291 | * Set parity of structured symbols. 292 | * @param s structured input object. 293 | * @param parity parity of s. 294 | */ 295 | extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity); 296 | 297 | /** 298 | * Append a QRinput object to the set. QRinput created by QRinput_newMQR() 299 | * will be rejected. 300 | * @warning never append the same QRinput object twice or more. 301 | * @param s structured input object. 302 | * @param input an input object. 303 | * @retval >0 number of input objects in the structure. 304 | * @retval -1 an error occurred. See Exceptions for the details. 305 | * @throw ENOMEM unable to allocate memory. 306 | * @throw EINVAL invalid arguments. 307 | */ 308 | extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input); 309 | 310 | /** 311 | * Free all of QRinput in the set. 312 | * @param s a structured input object. 313 | */ 314 | extern void QRinput_Struct_free(QRinput_Struct *s); 315 | 316 | /** 317 | * Split a QRinput to QRinput_Struct. It calculates a parity, set it, then 318 | * insert structured-append headers. QRinput created by QRinput_newMQR() will 319 | * be rejected. 320 | * @param input input object. Version number and error correction level must be 321 | * set. 322 | * @return a set of input data. On error, NULL is returned, and errno is set 323 | * to indicate the error. See Exceptions for the details. 324 | * @throw ERANGE input data is too large. 325 | * @throw EINVAL invalid input data. 326 | * @throw ENOMEM unable to allocate memory. 327 | */ 328 | extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input); 329 | 330 | /** 331 | * Insert structured-append headers to the input structure. It calculates 332 | * a parity and set it if the parity is not set yet. 333 | * @param s input structure 334 | * @retval 0 success. 335 | * @retval -1 an error occurred and errno is set to indeicate the error. 336 | * See Execptions for the details. 337 | * @throw EINVAL invalid input object. 338 | * @throw ENOMEM unable to allocate memory. 339 | */ 340 | extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s); 341 | 342 | /** 343 | * Set FNC1-1st position flag. 344 | */ 345 | extern int QRinput_setFNC1First(QRinput *input); 346 | 347 | /** 348 | * Set FNC1-2nd position flag and application identifier. 349 | */ 350 | extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid); 351 | 352 | /****************************************************************************** 353 | * QRcode output (qrencode.c) 354 | *****************************************************************************/ 355 | 356 | /** 357 | * QRcode class. 358 | * Symbol data is represented as an array contains width*width uchars. 359 | * Each uchar represents a module (dot). If the less significant bit of 360 | * the uchar is 1, the corresponding module is black. The other bits are 361 | * meaningless for usual applications, but here its specification is described. 362 | * 363 | *
364 |  * MSB 76543210 LSB
365 |  *     |||||||`- 1=black/0=white
366 |  *     ||||||`-- data and ecc code area
367 |  *     |||||`--- format information
368 |  *     ||||`---- version information
369 |  *     |||`----- timing pattern
370 |  *     ||`------ alignment pattern
371 |  *     |`------- finder pattern and separator
372 |  *     `-------- non-data modules (format, timing, etc.)
373 |  * 
374 | */ 375 | typedef struct { 376 | int version; ///< version of the symbol 377 | int width; ///< width of the symbol 378 | unsigned char *data; ///< symbol data 379 | } QRcode; 380 | 381 | /** 382 | * Singly-linked list of QRcode. Used to represent a structured symbols. 383 | * A list is terminated with NULL. 384 | */ 385 | typedef struct _QRcode_List { 386 | QRcode *code; 387 | struct _QRcode_List *next; 388 | } QRcode_List; 389 | 390 | /** 391 | * Create a symbol from the input data. 392 | * @warning This function is THREAD UNSAFE when pthread is disabled. 393 | * @param input input data. 394 | * @return an instance of QRcode class. The version of the result QRcode may 395 | * be larger than the designated version. On error, NULL is returned, 396 | * and errno is set to indicate the error. See Exceptions for the 397 | * details. 398 | * @throw EINVAL invalid input object. 399 | * @throw ENOMEM unable to allocate memory for input objects. 400 | */ 401 | extern QRcode *QRcode_encodeInput(QRinput *input); 402 | 403 | /** 404 | * Create a symbol from the string. The library automatically parses the input 405 | * string and encodes in a QR Code symbol. 406 | * @warning This function is THREAD UNSAFE when pthread is disabled. 407 | * @param string input string. It must be NUL terminated. 408 | * @param version version of the symbol. If 0, the library chooses the minimum 409 | * version for the given input data. 410 | * @param level error correction level. 411 | * @param hint tell the library how Japanese Kanji characters should be 412 | * encoded. If QR_MODE_KANJI is given, the library assumes that the 413 | * given string contains Shift-JIS characters and encodes them in 414 | * Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical 415 | * characters will be encoded as is. If you want to embed UTF-8 416 | * string, choose this. Other mode will cause EINVAL error. 417 | * @param casesensitive case-sensitive(1) or not(0). 418 | * @return an instance of QRcode class. The version of the result QRcode may 419 | * be larger than the designated version. On error, NULL is returned, 420 | * and errno is set to indicate the error. See Exceptions for the 421 | * details. 422 | * @throw EINVAL invalid input object. 423 | * @throw ENOMEM unable to allocate memory for input objects. 424 | * @throw ERANGE input data is too large. 425 | */ 426 | extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); 427 | 428 | /** 429 | * Same to QRcode_encodeString(), but encode whole data in 8-bit mode. 430 | * @warning This function is THREAD UNSAFE when pthread is disabled. 431 | */ 432 | extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level); 433 | 434 | /** 435 | * Micro QR Code version of QRcode_encodeString(). 436 | * @warning This function is THREAD UNSAFE when pthread is disabled. 437 | */ 438 | extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); 439 | 440 | /** 441 | * Micro QR Code version of QRcode_encodeString8bit(). 442 | * @warning This function is THREAD UNSAFE when pthread is disabled. 443 | */ 444 | extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level); 445 | 446 | /** 447 | * Encode byte stream (may include '\0') in 8-bit mode. 448 | * @warning This function is THREAD UNSAFE when pthread is disabled. 449 | * @param size size of the input data. 450 | * @param data input data. 451 | * @param version version of the symbol. If 0, the library chooses the minimum 452 | * version for the given input data. 453 | * @param level error correction level. 454 | * @throw EINVAL invalid input object. 455 | * @throw ENOMEM unable to allocate memory for input objects. 456 | * @throw ERANGE input data is too large. 457 | */ 458 | extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level); 459 | 460 | /** 461 | * Micro QR Code version of QRcode_encodeData(). 462 | * @warning This function is THREAD UNSAFE when pthread is disabled. 463 | */ 464 | extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level); 465 | 466 | /** 467 | * Free the instance of QRcode class. 468 | * @param qrcode an instance of QRcode class. 469 | */ 470 | extern void QRcode_free(QRcode *qrcode); 471 | 472 | /** 473 | * Create structured symbols from the input data. 474 | * @warning This function is THREAD UNSAFE when pthread is disabled. 475 | * @param s 476 | * @return a singly-linked list of QRcode. 477 | */ 478 | extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s); 479 | 480 | /** 481 | * Create structured symbols from the string. The library automatically parses 482 | * the input string and encodes in a QR Code symbol. 483 | * @warning This function is THREAD UNSAFE when pthread is disabled. 484 | * @param string input string. It must be NUL terminated. 485 | * @param version version of the symbol. 486 | * @param level error correction level. 487 | * @param hint tell the library how Japanese Kanji characters should be 488 | * encoded. If QR_MODE_KANJI is given, the library assumes that the 489 | * given string contains Shift-JIS characters and encodes them in 490 | * Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical 491 | * characters will be encoded as is. If you want to embed UTF-8 492 | * string, choose this. Other mode will cause EINVAL error. 493 | * @param casesensitive case-sensitive(1) or not(0). 494 | * @return a singly-linked list of QRcode. On error, NULL is returned, and 495 | * errno is set to indicate the error. See Exceptions for the details. 496 | * @throw EINVAL invalid input object. 497 | * @throw ENOMEM unable to allocate memory for input objects. 498 | */ 499 | extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); 500 | 501 | /** 502 | * Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode. 503 | * @warning This function is THREAD UNSAFE when pthread is disabled. 504 | */ 505 | extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level); 506 | 507 | /** 508 | * Create structured symbols from byte stream (may include '\0'). Wholde data 509 | * are encoded in 8-bit mode. 510 | * @warning This function is THREAD UNSAFE when pthread is disabled. 511 | * @param size size of the input data. 512 | * @param data input dat. 513 | * @param version version of the symbol. 514 | * @param level error correction level. 515 | * @return a singly-linked list of QRcode. On error, NULL is returned, and 516 | * errno is set to indicate the error. See Exceptions for the details. 517 | * @throw EINVAL invalid input object. 518 | * @throw ENOMEM unable to allocate memory for input objects. 519 | */ 520 | extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level); 521 | 522 | /** 523 | * Return the number of symbols included in a QRcode_List. 524 | * @param qrlist a head entry of a QRcode_List. 525 | * @return number of symbols in the list. 526 | */ 527 | extern int QRcode_List_size(QRcode_List *qrlist); 528 | 529 | /** 530 | * Free the QRcode_List. 531 | * @param qrlist a head entry of a QRcode_List. 532 | */ 533 | extern void QRcode_List_free(QRcode_List *qrlist); 534 | 535 | 536 | /****************************************************************************** 537 | * System utilities 538 | *****************************************************************************/ 539 | 540 | /** 541 | * Return a string that identifies the library version. 542 | * @param major_version 543 | * @param minor_version 544 | * @param micro_version 545 | */ 546 | extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version); 547 | 548 | /** 549 | * Return a string that identifies the library version. 550 | * @return a string identifies the library version. The string is held by the 551 | * library. Do NOT free it. 552 | */ 553 | extern char *QRcode_APIVersionString(void); 554 | 555 | /** 556 | * Clear all caches. This is only for debug purpose. If you are attacking a 557 | * complicated memory leak bug, try this to reduce the reachable blocks record. 558 | * @warning This function is THREAD UNSAFE when pthread is disabled. 559 | */ 560 | extern void QRcode_clearCache(void); 561 | 562 | #if defined(__cplusplus) 563 | } 564 | #endif 565 | 566 | #endif /* __QRENCODE_H__ */ 567 | -------------------------------------------------------------------------------- /lib/qrencode/libqrencode.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoneal/qtqrencode/30f4384befdeb355d564cd269e7bfc0608341a4b/lib/qrencode/libqrencode.a -------------------------------------------------------------------------------- /qqrencode/libqtqrencode_global.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBQTQRENCODE_GLOBAL_H 2 | #define LIBQTQRENCODE_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(LIBQTQRENCODE_LIBRARY) 7 | # define LIBQTQRENCODESHARED_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define LIBQTQRENCODESHARED_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // LIBQTQRENCODE_GLOBAL_H 13 | -------------------------------------------------------------------------------- /qqrencode/qqrencode.cpp: -------------------------------------------------------------------------------- 1 | #include "qqrencode.h" 2 | #include "qqrencode_p.h" 3 | 4 | #include 5 | #include 6 | 7 | #define INCHES_PER_METER (100.0/2.54) 8 | 9 | QQREncodePrivate::~QQREncodePrivate() 10 | { 11 | QRcode_free(m_code); 12 | } 13 | 14 | void QQREncodePrivate::paint(QPainter &painter) 15 | { 16 | unsigned char *row, *p; 17 | int x, y; 18 | 19 | int symwidth = m_code->width + m_margin * 2; 20 | painter.setClipRect(QRect(0,0,symwidth, symwidth)); 21 | painter.setPen(m_pen); 22 | painter.setBrush(m_fg); 23 | 24 | /* Make solid background */ 25 | painter.fillRect(QRect(0, 0, symwidth, symwidth), m_bg); 26 | 27 | /* Write data */ 28 | p = m_code->data; 29 | for(y=0; ywidth; y++) { 30 | row = (p+(y*m_code->width)); 31 | /* no RLE */ 32 | for(x=0; xwidth; x++) { 33 | if(*(row+x)&0x1) { 34 | painter.drawRect(m_margin + x, m_margin + y, 1, 1); 35 | } 36 | } 37 | 38 | } 39 | } 40 | 41 | QQREncode::QQREncode() 42 | : d_ptr(new QQREncodePrivate(this)) 43 | { 44 | } 45 | 46 | QQREncode::~QQREncode() 47 | { 48 | } 49 | 50 | void QQREncode::setLevel(QQREncode::ErrorCorrectionLevel value) 51 | { 52 | Q_D(QQREncode); 53 | switch (value) { 54 | case LOW: 55 | d->m_level = QR_ECLEVEL_L; 56 | break; 57 | case MEDIUM: 58 | d->m_level = QR_ECLEVEL_M; 59 | break; 60 | case QUARTILE: 61 | d->m_level = QR_ECLEVEL_Q; 62 | break; 63 | case HIGH: 64 | d->m_level = QR_ECLEVEL_H; 65 | break; 66 | } 67 | } 68 | 69 | QQREncode::ErrorCorrectionLevel QQREncode::getLevel() const 70 | { 71 | Q_D(const QQREncode); 72 | switch (d->m_level) { 73 | case QR_ECLEVEL_L: 74 | return LOW; 75 | case QR_ECLEVEL_M: 76 | return MEDIUM; 77 | case QR_ECLEVEL_Q: 78 | return QUARTILE; 79 | case QR_ECLEVEL_H: 80 | return HIGH; 81 | } 82 | return LOW; 83 | } 84 | 85 | //bool QQREncode::encode(QString code, QString output) 86 | //{ 87 | // if (code.isEmpty() || output.isEmpty()) { 88 | // return false; 89 | // } 90 | // QString program = "./qrencode.exe"; 91 | // QStringList arguments; 92 | // arguments << "-t" << "PNG"; 93 | // arguments << "-o" << output; 94 | // arguments << code; 95 | 96 | // QProcess *myProcess = new QProcess(this); 97 | // myProcess->start(program, arguments); 98 | // return myProcess->waitForFinished(); 99 | //} 100 | 101 | 102 | void QQREncode::setVersion(int version) 103 | { 104 | Q_D(QQREncode); 105 | // 1 - 40 106 | if (version > 0 && version <= 40) 107 | d->m_version = version; 108 | } 109 | 110 | int QQREncode::version() const 111 | { 112 | Q_D(const QQREncode); 113 | return d->m_version; 114 | } 115 | 116 | void QQREncode::setMargin(int value) 117 | { 118 | Q_D(QQREncode); 119 | if (value > -1) 120 | d->m_margin = value; 121 | } 122 | 123 | int QQREncode::margin() const 124 | { 125 | Q_D(const QQREncode); 126 | return d->m_margin; 127 | } 128 | 129 | void QQREncode::setMicro(bool value) 130 | { 131 | Q_D(QQREncode); 132 | d->m_micro = (value) ? 1 : 0; 133 | } 134 | 135 | bool QQREncode::isMicro() const 136 | { 137 | Q_D(const QQREncode); 138 | return (d->m_micro == 1) ? true : false; 139 | } 140 | 141 | void QQREncode::setBackground(QColor color) 142 | { 143 | Q_D(QQREncode); 144 | d->m_bg.setColor(color); 145 | } 146 | 147 | void QQREncode::setForeground(QColor color) 148 | { 149 | Q_D(QQREncode); 150 | d->m_fg.setColor(color); 151 | d->m_pen.setColor(color); 152 | } 153 | 154 | bool QQREncode::encode(QByteArray input) 155 | { 156 | Q_D(QQREncode); 157 | QRcode *c = NULL; 158 | if (input.isEmpty()) return false; 159 | if (d->m_micro) { 160 | c = QRcode_encodeDataMQR(input.size(), (const unsigned char*)input.constData(), 161 | d->m_version, d->m_level); 162 | } else { 163 | c = QRcode_encodeData(input.size(), (const unsigned char*)input.constData(), 164 | d->m_version, d->m_level); 165 | } 166 | if (c == NULL) { 167 | return false; 168 | } 169 | if (d->m_code) QRcode_free(d->m_code); 170 | d->m_code = c; 171 | return true; 172 | } 173 | 174 | bool QQREncode::encode(QString input, bool caseSensitive) 175 | { 176 | Q_D(QQREncode); 177 | if (input.isEmpty()) return false; 178 | QRcode *c = NULL; 179 | if (d->m_micro) { 180 | c = QRcode_encodeStringMQR(input.toStdString().c_str(), 181 | d->m_version, 182 | d->m_level, 183 | QR_MODE_8, 184 | (caseSensitive) ? 1 : 0); 185 | } else { 186 | c = QRcode_encodeString(input.toStdString().c_str(), 187 | d->m_version, 188 | d->m_level, 189 | QR_MODE_8, 190 | (caseSensitive) ? 1 : 0); 191 | } 192 | if (c == NULL) { 193 | return false; 194 | } 195 | if (d->m_code) QRcode_free(d->m_code); 196 | d->m_code = c; 197 | return true; 198 | } 199 | 200 | bool QQREncode::encodeKanji(QByteArray input, bool caseSensitive) 201 | { 202 | Q_D(QQREncode); 203 | if (input.isEmpty()) return false; 204 | QRcode *c = NULL; 205 | if (d->m_micro) { 206 | c = QRcode_encodeStringMQR(input.constData(), 207 | d->m_version, 208 | d->m_level, 209 | QR_MODE_KANJI, 210 | (caseSensitive) ? 1 : 0); 211 | } else { 212 | c = QRcode_encodeString(input.constData(), 213 | d->m_version, 214 | d->m_level, 215 | QR_MODE_KANJI, 216 | (caseSensitive) ? 1 : 0); 217 | } 218 | if (c == NULL) { 219 | return false; 220 | } 221 | if (d->m_code) QRcode_free(d->m_code); 222 | d->m_code = c; 223 | return true; 224 | } 225 | 226 | bool QQREncode::toSVG(QString output, int size) 227 | { 228 | Q_D(QQREncode); 229 | if (output.isEmpty() || d->m_code == NULL) { 230 | return false; 231 | } 232 | 233 | QSvgGenerator generator; 234 | generator.setFileName(output); 235 | generator.setSize(QSize(size, size)); 236 | int symwidth = d->m_code->width + d->m_margin * 2; 237 | generator.setViewBox(QRect(0, 0, symwidth, symwidth)); 238 | 239 | QPainter painter; 240 | painter.begin(&generator); 241 | d->paint(painter); 242 | painter.end(); 243 | 244 | return true; 245 | } 246 | 247 | QImage QQREncode::toQImage(int size) 248 | { 249 | Q_D(QQREncode); 250 | if (size < 0) throw std::invalid_argument("Invalid size"); 251 | 252 | if (d->m_code == NULL) { 253 | std::logic_error("No qr code to convert"); 254 | } 255 | 256 | int symwidth = d->m_code->width + d->m_margin * 2; 257 | QImage result(QSize(symwidth, symwidth), QImage::Format_Mono); 258 | result.fill(Qt::white); 259 | 260 | QPainter painter; 261 | painter.begin(&result); 262 | d->paint(painter); 263 | painter.end(); 264 | 265 | if (size > 0) 266 | return result.scaled(size, size); 267 | return result; 268 | } 269 | -------------------------------------------------------------------------------- /qqrencode/qqrencode.h: -------------------------------------------------------------------------------- 1 | #ifndef QQRENCODE_H 2 | #define QQRENCODE_H 3 | 4 | #include 5 | 6 | #include "libqtqrencode_global.h" 7 | 8 | class QQREncodePrivate; 9 | 10 | class LIBQTQRENCODESHARED_EXPORT QQREncode 11 | { 12 | Q_GADGET 13 | Q_ENUMS(ErrorCorrectionLevel) 14 | 15 | public: 16 | enum ErrorCorrectionLevel { 17 | LOW, 18 | MEDIUM, 19 | QUARTILE, 20 | HIGH 21 | }; 22 | 23 | QQREncode(); 24 | ~QQREncode(); 25 | 26 | void setLevel(ErrorCorrectionLevel value); 27 | ErrorCorrectionLevel getLevel() const; 28 | void setVersion(int version); 29 | int version() const; 30 | void setMargin(int value); 31 | int margin() const; 32 | void setMicro(bool value); 33 | bool isMicro() const; 34 | void setBackground(QColor color); 35 | void setForeground(QColor color); 36 | 37 | bool encode(QByteArray input); 38 | bool encode(QString input, bool caseSensitive=true); 39 | bool encodeKanji(QByteArray input, bool caseSensitive=true); 40 | 41 | bool toSVG(QString output, int size); 42 | QImage toQImage(int size=0); 43 | 44 | // ToDo: encode structured, rle 45 | 46 | private: 47 | Q_DISABLE_COPY(QQREncode) 48 | QScopedPointer d_ptr; 49 | Q_DECLARE_PRIVATE(QQREncode) 50 | }; 51 | 52 | #endif // QQRENCODE_H 53 | -------------------------------------------------------------------------------- /qqrencode/qqrencode.pro: -------------------------------------------------------------------------------- 1 | QT += core gui svg 2 | 3 | !win32-msvc2010 { 4 | QMAKE_CXXFLAGS_DEBUG += -std=c++11 -Wno-write-strings 5 | QMAKE_CXXFLAGS_RELEASE += -std=c++11 -Wno-write-strings 6 | } 7 | 8 | TARGET = qtqrencode 9 | TEMPLATE = lib 10 | 11 | DEFINES += LIBQTQRENCODE_LIBRARY 12 | 13 | SOURCES += qqrencode.cpp 14 | 15 | HEADERS += qqrencode.h \ 16 | libqtqrencode_global.h \ 17 | qqrencode_p.h 18 | 19 | header_files.files = qqrencode.h \ 20 | libqtqrencode_global.h 21 | header_files.path = /usr/include 22 | INSTALLS += header_files 23 | 24 | win32 { 25 | LIBS += -L$$PWD/../lib/qrencode -lqrencode 26 | } else { 27 | target.path = /usr/lib 28 | INSTALLS += target 29 | macx { 30 | LIBS += -L/usr/local/lib -lqrencode 31 | } else { 32 | LIBS += -lqrencode 33 | } 34 | } 35 | 36 | INCLUDEPATH += $$PWD/../lib/qrencode/include 37 | DEPENDPATH += $$PWD/../lib/qrencode/include 38 | -------------------------------------------------------------------------------- /qqrencode/qqrencode_p.h: -------------------------------------------------------------------------------- 1 | #ifndef QQRENCODE_P_H 2 | #define QQRENCODE_P_H 3 | 4 | #include "qqrencode.h" 5 | 6 | #include 7 | #include 8 | 9 | class QQREncodePrivate 10 | { 11 | Q_DECLARE_PUBLIC(QQREncode) 12 | 13 | public: 14 | QQREncodePrivate(QQREncode *qqrencode) 15 | : q_ptr(qqrencode), m_code(NULL), m_level(QR_ECLEVEL_L),m_version(1), m_margin(4), m_micro(0), 16 | m_pen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin), m_bg(Qt::white), 17 | m_fg(Qt::black) 18 | { 19 | } 20 | 21 | ~QQREncodePrivate(); 22 | 23 | void paint(QPainter &painter); 24 | 25 | QQREncode *q_ptr; 26 | QRcode *m_code; 27 | QRecLevel m_level; 28 | int m_version; 29 | int m_margin; 30 | int m_micro; 31 | QPen m_pen; 32 | QBrush m_bg; 33 | QBrush m_fg; 34 | 35 | // ToDo: Corrupted SVG when setting the resolution 36 | // int m_dpi = 72; 37 | // ToDo: structured and rle features 38 | // int m_structured = 0; 39 | // int m_rle = 0; 40 | }; 41 | 42 | #endif // QQRENCODE_P_H 43 | -------------------------------------------------------------------------------- /qtqrencode.pro: -------------------------------------------------------------------------------- 1 | lessThan(QT_MAJOR_VERSION, 5) { 2 | error("Cannot build with Qt version $${QT_VERSION}, this project requires at least Qt 5") 3 | } 4 | 5 | TEMPLATE = subdirs 6 | SUBDIRS += \ 7 | qqrencode \ 8 | test 9 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "qqrencodetestsuite.h" 2 | #include "testrunner.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | QCoreApplication app(argc, argv); 12 | 13 | #if QT_VERSION < QT_VERSION_CHECK(5,0,0) 14 | QTextCodec *codec = QTextCodec::codecForName("UTF-8"); 15 | QTextCodec::setCodecForCStrings(codec); 16 | #endif 17 | 18 | // Perform tests 19 | TestRunner runner(QStringList(), &app); 20 | /** 21 | * Add tests here 22 | */ 23 | runner.addTest(new QQREncodeTestSuite(&app)); 24 | QObject::connect(&runner, &TestRunner::finished, [&] (int result) 25 | { 26 | qDebug() << "Overall Result: " << (result == 0 ? "PASS" : "FAIL"); 27 | app.quit(); 28 | }); 29 | QTimer::singleShot(0, &runner, SLOT(run())); 30 | 31 | return app.exec(); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /test/qqrencodetestsuite.cpp: -------------------------------------------------------------------------------- 1 | #include "qqrencodetestsuite.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | const QString RESULTS_PATH = "./results/"; 8 | 9 | QQREncodeTestSuite::QQREncodeTestSuite(QObject *parent) : 10 | QObject(parent) 11 | { 12 | } 13 | 14 | void QQREncodeTestSuite::initTestCase() 15 | { 16 | QDir().rmpath(RESULTS_PATH); 17 | QDir().mkpath(RESULTS_PATH); 18 | } 19 | 20 | void QQREncodeTestSuite::accessors() 21 | { 22 | QQREncode encoder; 23 | encoder.setLevel(QQREncode::ErrorCorrectionLevel::HIGH); 24 | QCOMPARE(encoder.getLevel(),QQREncode::ErrorCorrectionLevel::HIGH); 25 | encoder.setVersion(40); 26 | QCOMPARE(encoder.version(), 40); 27 | encoder.setMargin(8); 28 | QCOMPARE(encoder.margin(),8); 29 | encoder.setMicro(true); 30 | QCOMPARE(encoder.isMicro(),true); 31 | } 32 | 33 | void QQREncodeTestSuite::encodeAlphaNumeric() 34 | { 35 | QQREncode encoder; 36 | QVERIFY(encoder.encode(QString("abcdefghijklmnopqrstuvwxyz 1234567890$%*+-./:"))); 37 | encoder.toSVG(RESULTS_PATH + "alphanumeric.svg",200); 38 | QImage code = encoder.toQImage(); 39 | code.scaled(200,200).save(RESULTS_PATH + "alphanumeric.png","PNG"); 40 | } 41 | 42 | void QQREncodeTestSuite::encodeByteArray() 43 | { 44 | QQREncode encoder; 45 | unsigned char testdata[] = {0xF3, 0xFF, 0xFE, 0xF1}; 46 | QVERIFY(encoder.encode(QByteArray((const char*)testdata, 4))); 47 | encoder.toSVG(RESULTS_PATH + "bytearray.svg",200); 48 | QImage code = encoder.toQImage(); 49 | code.scaled(200,200).save(RESULTS_PATH + "bytearray.png","PNG"); 50 | } 51 | 52 | void QQREncodeTestSuite::encodeKanji() 53 | { 54 | QQREncode encoder; 55 | QTextCodec *codec = QTextCodec::codecForName("Shift-JIS"); 56 | QVERIFY(encoder.encodeKanji(codec->fromUnicode(QString("お疲れ様テスト。")))); 57 | // delete codec; 58 | encoder.toSVG(RESULTS_PATH + "kanji.svg",200); 59 | QImage code = encoder.toQImage(); 60 | code.scaled(200,200).save(RESULTS_PATH + "kanji.png","PNG"); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /test/qqrencodetestsuite.h: -------------------------------------------------------------------------------- 1 | #ifndef QQRENCODETESTSUITE_H 2 | #define QQRENCODETESTSUITE_H 3 | 4 | #include 5 | 6 | /** 7 | * For now, manual inspection of images is needed to verify the resulting QR is correct. 8 | * @brief The QQREncodeTestSuite class 9 | */ 10 | class QQREncodeTestSuite : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit QQREncodeTestSuite(QObject *parent = 0); 15 | 16 | private slots: 17 | void initTestCase(); 18 | void accessors(); 19 | void encodeAlphaNumeric(); 20 | void encodeByteArray(); 21 | void encodeKanji(); 22 | }; 23 | 24 | #endif // QQRENCODETESTSUITE_H 25 | -------------------------------------------------------------------------------- /test/test.pro: -------------------------------------------------------------------------------- 1 | QT += core testlib 2 | 3 | !win32-msvc2010 { 4 | QMAKE_CXXFLAGS_DEBUG += -std=c++11 5 | QMAKE_CXXFLAGS_RELEASE += -std=c++11 6 | } 7 | 8 | TARGET = tester 9 | CONFIG += console 10 | 11 | TEMPLATE = app 12 | 13 | SOURCES += \ 14 | main.cpp \ 15 | testrunner.cpp \ 16 | qqrencodetestsuite.cpp 17 | 18 | HEADERS += \ 19 | testrunner.h \ 20 | qqrencodetestsuite.h 21 | 22 | win32:CONFIG(release, debug|release) { 23 | # WINDOWS RELEASE 24 | PRE_TARGETDEPS += $$OUT_PWD/../qqrencode/release/qtqrencode.dll 25 | LIBS += -L$$OUT_PWD/../qqrencode/release/ -lqtqrencode 26 | 27 | } else:win32:CONFIG(debug, debug|release) { 28 | # WINDOWS DEBUG 29 | PRE_TARGETDEPS += $$OUT_PWD/../qqrencode/debug/qtqrencode.dll 30 | LIBS += -L$$OUT_PWD/../qqrencode/debug/ -lqtqrencode 31 | } else:CONFIG(release, debug|release) { 32 | PRE_TARGETDEPS += $$OUT_PWD/../qqrencode/libqtqrencode.so 33 | LIBS += -L$$OUT_PWD/../qqrencode/ -lqtqrencode 34 | } else:CONFIG(debug, debug|release) { 35 | PRE_TARGETDEPS += $$OUT_PWD/../qqrencode/libqtqrencode.so 36 | LIBS += -L$$OUT_PWD/../qqrencode/ -lqtqrencode 37 | } 38 | 39 | INCLUDEPATH += $$PWD/../qqrencode 40 | DEPENDPATH += $$PWD/../qqrencode 41 | -------------------------------------------------------------------------------- /test/testrunner.cpp: -------------------------------------------------------------------------------- 1 | #include "testrunner.h" 2 | 3 | TestRunner::TestRunner(QStringList args, QObject *parent) : 4 | QObject(parent), 5 | m_arguments(args) 6 | { 7 | } 8 | 9 | void TestRunner::addTest(QObject *test) 10 | { 11 | test->setParent(this); 12 | m_tests.append(test); 13 | } 14 | 15 | 16 | void TestRunner::run() 17 | { 18 | foreach (QObject *test, m_tests) 19 | { 20 | m_overallResult = QTest::qExec(test, m_arguments); 21 | if (m_overallResult != 0) 22 | { 23 | break; 24 | } 25 | } 26 | emit finished(m_overallResult); 27 | } 28 | -------------------------------------------------------------------------------- /test/testrunner.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTRUNNER_H 2 | #define TESTRUNNER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief The TestRunner class 11 | * Inspired from mlvljr's TestRunner here: 12 | * http://stackoverflow.com/questions/1524390/what-unit-testing-framework-should-i-use-for-qt 13 | */ 14 | class TestRunner : public QObject 15 | { 16 | Q_OBJECT 17 | public: 18 | explicit TestRunner(QStringList args, QObject *parent = 0); 19 | 20 | void addTest(QObject *test); 21 | 22 | signals: 23 | void finished(int result); 24 | 25 | public slots: 26 | void run(); 27 | 28 | private: 29 | QStringList m_arguments; 30 | QList m_tests; 31 | int m_overallResult; 32 | }; 33 | 34 | #endif // TESTRUNNER_H 35 | --------------------------------------------------------------------------------