GCC Code Coverage Report


./
File: src/XpertMass/CrossLinker.cpp
Date: 2024-08-24 11:26:06
Lines:
84/203
41.4%
Functions:
7/21
33.3%
Branches:
92/286
32.2%

Line Branch Exec Source
1 /* BEGIN software license
2 *
3 * MsXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright(C) 2009,...,2018 Filippo Rusconi
6 *
7 * http://www.msxpertsuite.org
8 *
9 * This file is part of the MsXpertSuite project.
10 *
11 * The MsXpertSuite project is the successor of the massXpert project. This
12 * project now includes various independent modules:
13 *
14 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
15 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * END software license
31 */
32
33
34 /////////////////////// Local includes
35 #include "CrossLinker.hpp"
36 #include "PolChemDef.hpp"
37
38
39 namespace MsXpS
40 {
41
42 namespace libXpertMass
43 {
44
45
46 /*!
47 \class MsXpS::libXpertMass::CrossLinker
48 \inmodule libXpertMass
49 \ingroup PolChemDefAqueousChemicalReactions
50 \inheaderfile CrossLinker.hpp
51
52 \brief The CrossLinker class provides abstractions to define the chemical basis
53 of a cross-linking reaction.
54
55 The notion of a cross-linker is that it is the description of the chemical
56 reaction that is carried out by \l{Monomer}s in a \l Polymer or in an \l
57 Oligomer sequence to form a \l CrossLink.
58
59 There are two different kinds of chemical entities potentially involved in the
60 description of a CrossLinker:
61
62 \list
63 \a Modif instances that are applied to \l Monomer instances.
64 \a the \l Formula base class that completes the chemical reactions described by
65 the \l Modif instances.
66 \endlist
67 */
68
69 /*!
70 \variable MsXpS::libXpertMass::CrossLinker::m_modifList
71
72 \brief The list of \l Modif instances that describe the reaction (or the
73 reactions) involved in the formation of a CrossLink between \l{Monomer}s of a
74 \l Polymer (or of an \l Oligomer) sequence.
75 */
76
77 /*!
78 \brief Constructs a CrossLinker instance.
79
80 \list
81 \li \a pol_chem_def_csp: the polymer chemistry definition (\l PolChemDef).
82 \li \a name: the name of this CrossLinker.
83 \li \a formula: the \l Formula that potentially complements the description of
84 the reaction that is the basis of this CrossLinker (used to initialize the
85 Formula base class).
86 \endlist
87 */
88 784 CrossLinker::CrossLinker(PolChemDefCstSPtr pol_chem_def_csp,
89 const QString &name,
90 784 const QString &formula)
91
3/6
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 784 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 784 times.
✗ Branch 10 not taken.
784 : PolChemDefEntity(pol_chem_def_csp, name), Formula(formula)
92 {
93 784 }
94
95 /*!
96 \brief Constructs a CrossLinker instance as a copy of \a other.
97 */
98 CrossLinker::CrossLinker(const CrossLinker &other)
99 : PolChemDefEntity(other), Formula(other), Ponderable(other)
100 {
101 for(int iter = 0; iter < other.m_modifList.size(); ++iter)
102 m_modifList.append(other.m_modifList.at(iter));
103 }
104
105
106 /*!
107 \brief Destructs this CrossLinker instance
108 */
109 CrossLinker::~CrossLinker()
110 {
111 // We do not own the modifications in m_modifList!
112 }
113
114 /*!
115 \brief Sets the Modif at index \a index to \a modif.
116
117 \a index cannot be out-of-bounds.
118
119 Returns true.
120 */
121 bool
122 CrossLinker::setModifAt(Modif *modif, int index)
123 {
124 Q_ASSERT(modif);
125 Q_ASSERT(index >= 0 && index < m_modifList.size());
126
127 m_modifList.replace(index, modif);
128
129 return true;
130 }
131
132
133 /*!
134 \brief Adds \a modif to this CrossLinker instance.
135
136 Returns true.
137 */
138 bool
139 CrossLinker::appendModif(Modif *modif)
140 {
141 Q_ASSERT(modif);
142 m_modifList.append(modif);
143
144 return true;
145 }
146
147
148 /*!
149 \brief Returns the \l Modif instance at \a index.
150
151 \a index cannot be out-of-bounds.
152 */
153 const Modif *
154 CrossLinker::modifAt(int index) const
155 {
156 Q_ASSERT(index >= 0 && index < m_modifList.size());
157
158 return m_modifList.at(index);
159 }
160
161
162 /*!
163 \brief Removes the \l Modif instance at \a index.
164
165 \a index cannot be out-of-bounds.
166
167 Returns true.
168 */
169 bool
170 CrossLinker::removeModifAt(int index)
171 {
172 Q_ASSERT(index < m_modifList.size());
173
174 m_modifList.removeAt(index);
175
176 return true;
177 }
178
179
180 /*!
181 \brief Returns the \l Formula.
182 */
183 QString
184 8 CrossLinker::formula() const
185 {
186 8 return Formula::toString();
187 }
188
189
190 /*!
191 \brief Returns the list of \l Modif instances.
192 */
193 QList<Modif *> &
194 8 CrossLinker::modifList()
195 {
196 8 return m_modifList;
197 }
198
199
200 /*!
201 \brief Returns true if a \l Modif instance by \a modif_name is in the list of
202 Modif instances, false otherwise.
203 */
204 int
205 CrossLinker::hasModif(const QString &modif_name)
206 {
207 // Iterate in the list of modifications, and check if one of these
208 // has the name passed as argument. If so return the index of the
209 // found item in the list, otherwise return -1.
210
211 for(int iter = 0; iter < m_modifList.size(); ++iter)
212 {
213 Modif *modif = m_modifList.at(iter);
214
215 if(modif->name() == modif_name)
216 return iter;
217 }
218
219 return -1;
220 }
221
222 /*!
223 \brief Assigns \a other to this CrossLinker instance.
224
225 Returns a reference to this CrossLinker instance.
226 */
227 CrossLinker &
228 CrossLinker::operator=(const CrossLinker &other)
229 {
230 if(&other == this)
231 return *this;
232
233 PolChemDefEntity::operator=(other);
234 Formula::operator=(other);
235 Ponderable::operator=(other);
236
237 while(!m_modifList.isEmpty())
238 m_modifList.removeFirst();
239
240 for(int iter = 0; iter < other.m_modifList.size(); ++iter)
241 m_modifList.append(other.m_modifList.at(iter));
242
243 return *this;
244 }
245
246 /*!
247 \brief Returns true if this CrossLinker and \a other are identical.
248 */
249 bool
250 CrossLinker::operator==(const CrossLinker &other) const
251 {
252 if(&other == this)
253 return true;
254
255 if(PolChemDefEntity::operator!=(other))
256 return false;
257 if(Formula::operator!=(other))
258 return false;
259 if(Ponderable::operator!=(other))
260 return false;
261
262 if(m_modifList.size() != other.m_modifList.size())
263 return false;
264
265 for(int iter = 0; iter < m_modifList.size(); ++iter)
266 {
267 if(*m_modifList.at(iter) != *other.m_modifList.at(iter))
268 return false;
269 }
270
271 return true;
272 }
273
274
275 /*!
276 \brief Returns true if this CrossLinker and \a other are different.
277
278 Returns the negated result of operator==().
279 */
280 bool
281 CrossLinker::operator!=(const CrossLinker &other) const
282 {
283 if(&other == this)
284 return false;
285
286 return !operator==(other);
287 }
288
289 /*!
290 \brief Returns true if this CrossLinker instance is found in the member polymer
291 chemistry definition, false otherwise.
292 */
293 int
294 CrossLinker::isNameKnown()
295 {
296 const QList<CrossLinker *> &refList = mcsp_polChemDef->crossLinkerList();
297
298 if(m_name.isEmpty())
299 return -1;
300
301 for(int iter = 0; iter < refList.size(); ++iter)
302 {
303 if(refList.at(iter)->m_name == m_name)
304 return iter;
305 }
306
307 return -1;
308 }
309
310 /*!
311 \brief Returns the index of a CrossLinker found in the \a cross_linker_list
312 list of CrossLinker instances by name \a name, -1 otherwise.
313
314 If \a other is non-nullptr, the found CrossLinker instance is copied into it.
315 */
316 int
317 CrossLinker::isNameInList(const QString &name,
318 const QList<CrossLinker *> &cross_linker_list,
319 CrossLinker *other)
320 {
321 CrossLinker *crossLinker = 0;
322
323 if(name.isEmpty())
324 return -1;
325
326 for(int iter = 0; iter < cross_linker_list.size(); ++iter)
327 {
328 crossLinker = cross_linker_list.at(iter);
329 Q_ASSERT(crossLinker);
330
331 if(crossLinker->m_name == name)
332 {
333 if(other != nullptr)
334 *other = *crossLinker;
335
336 return iter;
337 }
338 }
339
340 return -1;
341 }
342
343 /*!
344 \brief Returns true if this CrossLinker instance validates successfully,
345 false otherwise.
346
347 The validation involves the following:
348
349 \list
350 \li The member polymer chemistry definition must exist.
351 \li The name cannot be empty.
352 \li The formula (if not empty) must validate successfully agains the member
353 polymer chemistry definition.
354 \li The list of \l Modif instances must contain either no or more than two
355 Modif instances. In the latter case, the Modif instances must be found in the
356 member polymer chemistry definition and must validate successfully.
357 \endlist
358 */
359 bool
360 784 CrossLinker::validate()
361 {
362
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(!mcsp_polChemDef)
363 return false;
364
365
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(m_name.isEmpty())
366 return false;
367
368 // Remember that the formula of the crosslinker might be empty because the
369 // crosslinker might be fully accounted for by the modifications (below).
370
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(!m_formula.isEmpty())
371 {
372 Formula formula(m_formula);
373
374 IsotopicDataCstSPtr isotopic_data_csp =
375 mcsp_polChemDef->getIsotopicDataCstSPtr();
376
377 if(!formula.validate(isotopic_data_csp))
378 return false;
379 }
380
381 // This is mainly a sanity check, as the pointers to Modif in the
382 // list all point to modification objects in the polymer chemistry
383 // definition, which have been validated already...
384
385 // The validation actually is simple, it might be that there are NO
386 // modifs, or if this is not the case there must be at least
387 // 2. Indeed, either none of the monomers in the crosslink get
388 // modified, or each one has to be(otherwise we cannot know which
389 // modif goes to which monomer).
390
391 784 int size = m_modifList.size();
392
393
2/4
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 784 times.
784 if(size > 0 && size < 2)
394 return false;
395
396
2/2
✓ Branch 0 taken 1960 times.
✓ Branch 1 taken 784 times.
2744 for(int iter = 0; iter < size; ++iter)
397 {
398 // Make sure the modification is known to the polymer chemistry
399 // definition. This check is not performed by the modif's
400 // validation function.
401
402
3/6
✓ Branch 3 taken 1960 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1960 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1960 times.
1960 if(!mcsp_polChemDef->referenceModifByName(m_modifList.at(iter)->name()))
403 return false;
404
405
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1960 times.
1960 if(!m_modifList.at(iter)->validate())
406 return false;
407 }
408
409 784 return true;
410 }
411
412 /*!
413 \brief Returns true if the mass calculations for this CrossLinker instance are
414 performed without error, false otherwise.
415
416 The calculation involved accounting masses for the Modifs (if any) and for the
417 Formula (if non-empty). The member masses (\l Ponderable base class) are
418 updated.
419 */
420 bool
421 784 CrossLinker::calculateMasses()
422 {
423 // qDebug() << "Calculating masses for the cross-link";
424
425 784 m_mono = 0;
426 784 m_avg = 0;
427
428 // Account the masses of the formula parent class.
429 IsotopicDataCstSPtr isotopic_data_csp =
430
1/2
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
784 mcsp_polChemDef->getIsotopicDataCstSPtr();
431
432 // Here is a special case because the formula for the crosslinker might be
433 // empty because the crosslinker might be accounted for only but the
434 // modifications below.
435
436
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(!m_formula.isEmpty())
437 {
438 // qDebug() << "The formula of the crosslinker is:" << m_formula
439 //<< "accounting for its masses.";
440
441 if(!Formula::accountMasses(isotopic_data_csp, &m_mono, &m_avg))
442 return false;
443 }
444 else
445 {
446 // qDebug() << "The formula of the crosslinker is empty.";
447 }
448 // Now, for each modif in the crossLinker, have to account their
449 // mass.
450
451
2/2
✓ Branch 1 taken 1960 times.
✓ Branch 2 taken 784 times.
2744 for(int iter = 0; iter < m_modifList.size(); iter++)
452 {
453 1960 Modif *modif = m_modifList.at(iter);
454
455 // qDebug() << "Accounting for crosslinker modif's" << modif->name()
456 //<< "masses";
457
458
2/4
✓ Branch 1 taken 1960 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1960 times.
1960 if(!modif->accountMasses(&m_mono, &m_avg))
459 {
460 qDebug()
461 << "Failed to account for masses of the cross-linker's modif.";
462 return false;
463 }
464 }
465
466 // qDebug() << "At this point, the masses of the CrossLinker are:" << m_mono
467 //<< "/" << m_avg;
468
469 784 return true;
470 784 }
471
472 /*!
473 \brief Copies the member masses (\l Ponderable base class) to \a mono and \a
474 avg if these are non-nullptr.
475
476 Upon copying, the masses are multiplied by the compounding factor \a
477 times.
478
479 Returns true.
480 */
481 bool
482 CrossLinker::accountMasses(double *mono, double *avg, int times)
483 {
484 // qDebug() << "Accounting masses for crossliker -- mono:" << m_mono
485 //<< "avg:" << m_avg;
486
487 if(mono)
488 *mono += m_mono * times;
489
490 if(avg)
491 *avg += m_avg * times;
492
493 return true;
494 }
495
496 /*!
497 \brief Copies the member masses (\l Ponderable base class) to \a ponderable.
498
499 \a ponderable cannot be nullptr.
500
501 Upon copying, the masses are multiplied by the compounding factor \a
502 times.
503
504 Returns true.
505 */
506 bool
507 CrossLinker::accountMasses(Ponderable *ponderable, int times)
508 {
509 Q_ASSERT(ponderable);
510
511 ponderable->rmono() += m_mono * times;
512 ponderable->ravg() += m_avg * times;
513
514 return true;
515 }
516
517 /*!
518 \brief Returns true if parsing of XML \a element, using a \a{version}ed
519 function was successful, false otherwise.
520
521 The data in \a element are set to this CrossLinker instance if they validated
522 successfully, thus essentially initializing this CrossLinker instance.
523 */
524 bool
525 784 CrossLinker::renderXmlClkElement(const QDomElement &element, int version)
526 {
527
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 784 times.
784 if(element.tagName() != "clk")
528 return false;
529
530
1/2
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
784 if(version == 1)
531 {
532 // no-op
533
534 784 version = 1;
535 }
536
537
1/2
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
784 QDomElement child;
538
539
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 784 times.
784 if(element.tagName() != "clk")
540 return false;
541
542
3/6
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 784 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 784 times.
✗ Branch 9 not taken.
784 child = element.firstChildElement("name");
543
544
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 784 times.
784 if(child.isNull())
545 return false;
546
547
1/2
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
784 m_name = child.text();
548
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(m_name.isEmpty())
549 return false;
550
551 // qDebug() << "The crosslinker name:" << m_name;
552
553
3/6
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 784 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 784 times.
✗ Branch 9 not taken.
784 child = child.nextSiblingElement("formula");
554
555 // Here, it is possible that the formula element be empty because the
556 // crosslinker might be accounted for by using the modifications in it.
557
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 784 times.
✗ Branch 4 not taken.
784 if(!child.isNull())
558 {
559
1/2
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
784 QString formula = child.text();
560
561
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 784 times.
784 if(!formula.isEmpty())
562 {
563 if(!Formula::renderXmlFormulaElement(child))
564 return false;
565 }
566 // else
567 // qDebug() << "The formula element of crosslinker is empty.";
568
1/2
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
784 }
569 else
570 qDebug() << "The formula element of crosslinker is null.";
571
572
1/2
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
784 const QList<Modif *> &refList = mcsp_polChemDef->modifList();
573
574 // At this point there might be 0, 1 or more "modifname" elements.
575
3/6
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 784 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 784 times.
✗ Branch 9 not taken.
784 child = child.nextSiblingElement("modifname");
576
577
3/4
✓ Branch 1 taken 2744 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1960 times.
✓ Branch 4 taken 784 times.
2744 while(!child.isNull())
578 {
579 // qDebug() << "Now handling CrossLinker modif:" << child.text();
580
581
2/4
✓ Branch 1 taken 1960 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1960 times.
✗ Branch 5 not taken.
1960 int index = Modif::isNameInList(child.text(), refList);
582
583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1960 times.
1960 if(index == -1)
584 {
585 qDebug() << "Failed to parse one modification of the crosslink:"
586 << m_name;
587
588 return false;
589 }
590 else
591 {
592 // qDebug()
593 //<< "Found the CrossLinker modification in the reference list:"
594 //<< m_name;
595 }
596
597 // Modif *modif = mcsp_polChemDef->modifList().at(index);
598 // qDebug() << "The found modif has name:" << modif->name()
599 //<< "and masses:" << modif->mono() << "/" << modif->avg();
600
601
2/4
✓ Branch 2 taken 1960 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1960 times.
✗ Branch 7 not taken.
1960 m_modifList.append(mcsp_polChemDef->modifList().at(index));
602
603
3/6
✓ Branch 2 taken 1960 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1960 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1960 times.
✗ Branch 9 not taken.
1960 child = child.nextSiblingElement("modifname");
604 }
605
606
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 784 times.
784 if(!calculateMasses())
607 {
608 qDebug() << __FILE__ << __LINE__
609 << "Failed to calculate masses for crossLinker" << m_name;
610
611 return false;
612 }
613
614
2/4
✓ Branch 1 taken 784 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 784 times.
784 if(!validate())
615 return false;
616
617 784 return true;
618 784 }
619
620 /*!
621 \brief Formats this CrossLinker instance in a heap-allocated string to be used
622 as an XML element in the polymer chemistry definition.
623
624 The formatting of the XML element takes into account \a offset and \a
625 indent by prepending the string with \a offset * \a indent character substring.
626
627 \a indent defaults to two spaces.
628
629 Returns a dynamically allocated string that needs to be freed after use.
630 */
631 QString *
632 8 CrossLinker::formatXmlClkElement(int offset, const QString &indent)
633 {
634 int newOffset;
635 8 int iter = 0;
636
637
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 QString lead("");
638
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 QString *string = new QString();
639
640 // Prepare the lead.
641 8 newOffset = offset;
642
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 while(iter < newOffset)
643 {
644
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 lead += indent;
645 24 ++iter;
646 }
647
648 /* We are willing to create an <modif> node that should look like this:
649 *
650 <clk>
651 <name>Phosphorylation</name>
652 <formula>-H+H2PO3</formula>
653 <modifname>Phosphorylation</modifname>
654 <modifname>Acetylation</modifname>
655 </clk>
656 *
657 */
658
659
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
16 *string += QString("%1<clk>\n").arg(lead);
660
661 // Prepare the lead.
662 8 ++newOffset;
663 8 lead.clear();
664 8 iter = 0;
665
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
40 while(iter < newOffset)
666 {
667
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 lead += indent;
668 32 ++iter;
669 }
670
671 // Continue with indented elements.
672
673
4/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
24 *string += QString("%1<name>%2</name>\n").arg(lead).arg(m_name);
674
675
4/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
24 *string += QString("%1<formula>%2</formula>\n").arg(lead).arg(m_formula);
676
677
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 8 times.
28 for(int iter = 0; iter < m_modifList.size(); ++iter)
678 {
679
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 *string += QString("%1<modifname>%2</modifname>\n")
680
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 .arg(lead)
681
3/6
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
40 .arg(m_modifList.at(iter)->name());
682 }
683
684 // Prepare the lead for the closing element.
685 8 --newOffset;
686 8 lead.clear();
687 8 iter = 0;
688
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 while(iter < newOffset)
689 {
690
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 lead += indent;
691 24 ++iter;
692 }
693
694
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
16 *string += QString("%1</clk>\n").arg(lead);
695
696 8 return string;
697 8 }
698
699 } // namespace libXpertMass
700
701 } // namespace MsXpS
702