GCC Code Coverage Report


./
File: src/XpertMass/ChemicalGroup.cpp
Date: 2024-08-24 11:26:06
Lines:
0/213
0.0%
Functions:
0/26
0.0%
Branches:
0/346
0.0%

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 "ChemicalGroup.hpp"
36
37
38 namespace MsXpS
39 {
40
41 namespace libXpertMass
42 {
43
44
45 /*!
46 \class MsXpS::libXpertMass::ChemicalGroup
47 \inmodule libXpertMass
48 \ingroup PolChemDefBuildingdBlocks
49 \inheaderfile ChemicalGroup.hpp
50
51 \brief The ChemicalGroup class provides a model for specifying the
52 acido-basic behaviour of a chemical group of either a \l Monomer object or of a
53 \l Modif object.
54
55 If the ChemicalGroup does not prove sufficient to characterize precisely the
56 acido-basic properties of an entity, \l ChemicalGroupRule instances can be
57 added to that effect.
58
59 In an pkaphpidata definition file, the following xml structure
60 is encountered:
61
62 \code
63 <pkaphpidata>
64 <monomers>
65 <monomer>
66 <code>A</code>
67 <mnmchemgroup>
68 <name>N-term NH2</name>
69 <pka>9.6</pka>
70 <acidcharged>TRUE</acidcharged>
71 <polrule>left_trapped</polrule>
72 <chemgrouprule>
73 <entity>LE_PLM_MODIF</entity>
74 <name>Acetylation</name>
75 <outcome>LOST</outcome>
76 </chemgrouprule>
77 </mnmchemgroup>
78 <mnmchemgroup>
79 <name>C-term COOH</name>
80 <pka>2.35</pka>
81 <acidcharged>FALSE</acidcharged>
82 <polrule>right_trapped</polrule>
83 </mnmchemgroup>
84 </monomer>
85 <monomer>
86 <code>C</code>
87 <mnmchemgroup>
88 <name>N-term NH2</name>
89 <pka>9.6</pka>
90 <acidcharged>TRUE</acidcharged>
91 <polrule>left_trapped</polrule>
92 <chemgrouprule>
93 <entity>LE_PLM_MODIF</entity>
94 <name>Acetylation</name>
95 <outcome>LOST</outcome>
96 </chemgrouprule>
97 </mnmchemgroup>
98 <mnmchemgroup>
99 <name>C-term COOH</name>
100 <pka>2.35</pka>
101 <acidcharged>FALSE</acidcharged>
102 <polrule>right_trapped</polrule>
103 </mnmchemgroup>
104 <mnmchemgroup>
105 <name>Lateral SH2</name>
106 <pka>8.3</pka>
107 <acidcharged>FALSE</acidcharged>
108 <polrule>never_trapped</polrule>
109 </mnmchemgroup>
110 </monomer>
111 .....
112 <modifs>
113 <modif>
114 <name>Phosphorylation</name>
115 <mdfchemgroup>
116 <name>none_set</name>
117 <pka>1.2</pka>
118 <acidcharged>FALSE</acidcharged>
119 </mdfchemgroup>
120 <mdfchemgroup>
121 <name>none_set</name>
122 <pka>6.5</pka>
123 <acidcharged>FALSE</acidcharged>
124 </mdfchemgroup>
125 </modif>
126 </modifs>
127 </pkaphpidata>
128 \endcode
129
130 \sa ChemicalGroupRule,
131 */
132
133 /*!
134 \enum MsXpS::libXpertMass::ChemicalGroupTrapping
135
136 This enum specifies how the chemical group behaves when the chemical entity
137 that it holds polymerizes into a \l Polymer.
138
139 One example will clear things out:
140
141 An amino acid has a amino group and a carboxylic acid group. The amino group
142 gets entrapped in the monomer-to-monomer bond (the peptide bond) if the
143 polymerization occurs at the left of the monomer. That means that if the
144 Monomer holding this ChemicalGroup is N-terminal, then the amino group should
145 be accounted for because it is intact. Conversely, the carboxylic acid group
146 gets entrapped in the peptide bond if the polymerization occurs at the right of
147 the monomer. That means that if the Monomer holding this ChemicalGroup is
148 C-terminal, then the carboxylic acid group should be accounted for because it is
149 intact.
150
151 \value NEVER_TRAPPED
152 The chemical group is not lost upon polymerization, it should thus
153 always be accounted for.
154
155 \value LEFT_TRAPPED
156 The chemical group gets trapped in the inter-monomer bond if
157 polymerization occurs at left of the \l Monomer.
158
159 \value RIGHT_TRAPPED
160 The chemical group gets trapped in the inter-monomer bond if
161 polymerization occurs at right of the \l Monomer.
162
163 \omitvalue NOT_SET.
164 */
165
166 /*!
167 \variable MsXpS::libXpertMass::ChemicalGroup::m_name
168
169 \brief The name of the ChemicalGroup instance.
170 */
171
172 /*!
173 \variable MsXpS::libXpertMass::ChemicalGroup::m_pka
174
175 \brief The pKa of the ChemicalGroup instance.
176 */
177
178 /*!
179 \variable MsXpS::libXpertMass::ChemicalGroup::m_acidCharged
180
181 \brief Tells if the group is charged when in acid conditions (that is, the pH
182 is less than the pKa).
183 */
184
185 /*!
186 \variable MsXpS::libXpertMass::ChemicalGroup::m_polymerizationRule
187
188 \brief The way this ChemicalGroup behaves upon polymerization of the chemical
189 entity into a \l Polymer.
190 */
191
192 /*!
193 \variable MsXpS::libXpertMass::ChemicalGroup::m_ruleList
194
195 \brief The list of \l ChemicalGroupRule instances.
196 */
197
198 /*!
199 \brief Constructs a ChemicalGroup instance.
200
201 \a name The name of this ChemicalGroup.
202 \a pka The pKa value of this ChemicalGroup.
203 \a is_acid_charged Tells if the ChemicalGroup bears a charge when in acidic
204 conditions.
205 \a polymerization_rule Specifies the polymerization rule.
206 */
207 ChemicalGroup::ChemicalGroup(QString name,
208 float pka,
209 bool is_acid_charged,
210 ChemicalGroupTrapping polymerization_rule)
211 : m_name(name),
212 m_pka(pka),
213 m_acidCharged(is_acid_charged),
214 m_polymerizationRule(polymerization_rule)
215 {
216 Q_ASSERT(m_pka > 0 && m_pka < 14);
217 }
218
219 /*!
220 \brief Construct a ChemicalGroup instance as a copy of \a other.
221 */
222 ChemicalGroup::ChemicalGroup(const ChemicalGroup &other)
223 : m_name(other.m_name),
224 m_pka(other.m_pka),
225 m_acidCharged(other.m_acidCharged),
226 m_polymerizationRule(other.m_polymerizationRule)
227 {
228 }
229
230 /*!
231 \brief Destructs this ChemicalGroup instance.
232 */
233 ChemicalGroup::~ChemicalGroup()
234 {
235 while(!m_ruleList.isEmpty())
236 delete m_ruleList.takeFirst();
237 }
238
239 /*!
240 \brief Assigns \a other to this ChemicalGroup instance.
241
242 Returns a reference to this ChemicalGroup instance.
243 */
244 ChemicalGroup &
245 ChemicalGroup::operator=(const ChemicalGroup &other)
246 {
247 if(&other == this)
248 return *this;
249
250 m_name = other.m_name;
251 m_pka = other.m_pka;
252 m_acidCharged = other.m_acidCharged;
253 m_polymerizationRule = other.m_polymerizationRule;
254
255 qDeleteAll(m_ruleList);
256
257 for(int iter = 0; iter < other.m_ruleList.size(); ++iter)
258 m_ruleList.append(new ChemicalGroupRule(*other.m_ruleList.at(iter)));
259
260 return *this;
261 }
262
263 /*!
264 \brief Sets the \a name.
265 */
266 void
267 ChemicalGroup::setName(QString name)
268 {
269 m_name = name;
270 }
271
272 /*!
273 \brief Returns the name.
274 */
275 QString
276 ChemicalGroup::name() const
277 {
278 return m_name;
279 }
280
281 /*!
282 \brief Sets the pKa to \a pka.
283 */
284 void
285 ChemicalGroup::setPka(float pka)
286 {
287 Q_ASSERT(pka > 0 && pka < 14);
288
289 m_pka = pka;
290 }
291
292 /*!
293 \brief Returns the pKa.
294 */
295 float
296 ChemicalGroup::pka() const
297 {
298 return m_pka;
299 }
300
301 /*!
302 \brief Sets the charge condition in acidic conditions to \a acid_charged.
303
304 If true, the group bears a charge when the pH is less than the pKa.
305 */
306 void
307 ChemicalGroup::setAcidCharged(bool acid_charged)
308 {
309 m_acidCharged = acid_charged;
310 }
311
312 /*!
313 \brief Returns the charge condition in acidic conditions.
314
315 If true, the group bears a charge when the pH is less than the pKa.
316 */
317 bool
318 ChemicalGroup::isAcidCharged() const
319 {
320 return m_acidCharged;
321 }
322
323 /*!
324 \brief Sets the polymerization rule to \a pol_rule.
325
326 The polymerization rule determines if the chemical group is trapped upon
327 formation of a Monomer-to-Monomer bond.
328 */
329 void
330 ChemicalGroup::setPolRule(ChemicalGroupTrapping pol_rule)
331 {
332 m_polymerizationRule = pol_rule;
333 }
334
335 /*!
336 \brief Returns the polymerization rule.
337 */
338 ChemicalGroupTrapping
339 ChemicalGroup::polRule() const
340 {
341 return m_polymerizationRule;
342 }
343
344 /*!
345 \brief Returns the list of ChemicalGroupRule instances.
346 */
347 QList<ChemicalGroupRule *> &
348 ChemicalGroup::ruleList()
349 {
350 return m_ruleList;
351 }
352
353 /*!
354 \brief Searches by \a entity for a ChemicalGroupRule instance.
355
356 Returns the \a index of the ChemicalGroupRule instance in the member list of
357 ChemicalGroupRule instances or -1 if not found.
358 */
359 ChemicalGroupRule *
360 ChemicalGroup::findRuleEntity(QString entity, int *index) const
361 {
362 int ruleIndex = 0;
363
364 if(!index)
365 ruleIndex = 0;
366 else
367 {
368 if(*index < 0)
369 return 0;
370 else if(*index > m_ruleList.size())
371 return 0;
372 ruleIndex = *index;
373 }
374
375 if(entity.isEmpty())
376 return 0;
377
378 for(int iter = ruleIndex; iter < m_ruleList.size(); ++iter)
379 {
380 ChemicalGroupRule *rule = m_ruleList.at(iter);
381
382 if(rule->entity() == entity)
383 {
384 if(index)
385 *index = iter;
386
387 return rule;
388 }
389 }
390
391 return 0;
392 }
393
394 /*!
395 \brief Searches by \a name for a ChemicalGroupRule instance.
396
397 Returns the \a index of the ChemicalGroupRule instance in the member list of
398 ChemicalGroupRule instances or -1 if not found.
399 */
400 ChemicalGroupRule *
401 ChemicalGroup::findRuleName(QString name, int *index) const
402 {
403 int ruleIndex = 0;
404
405 if(!index)
406 ruleIndex = 0;
407 else
408 {
409 if(*index < 0)
410 return 0;
411 else if(*index > m_ruleList.size())
412 return 0;
413 ruleIndex = *index;
414 }
415
416 if(name.isEmpty())
417 return 0;
418
419 for(int iter = ruleIndex; iter < m_ruleList.size(); ++iter)
420 {
421 ChemicalGroupRule *rule = m_ruleList.at(iter);
422
423 if(rule->name() == name)
424 {
425 if(index)
426 *index = iter;
427
428 return rule;
429 }
430 }
431
432 return 0;
433 }
434
435
436 /*!
437 \brief Searches by \a entity and \a name for a ChemicalGroupRule instance.
438
439 Returns the \a index of the ChemicalGroupRule instance in the member list of
440 ChemicalGroupRule instances or -1 if not found.
441 */
442 ChemicalGroupRule *
443 ChemicalGroup::findRule(QString entity, QString name, int *index) const
444 {
445 int ruleIndex = 0;
446
447 if(!index)
448 ruleIndex = 0;
449 else
450 {
451 if(*index < 0)
452 return 0;
453 else if(*index > m_ruleList.size())
454 return 0;
455 ruleIndex = *index;
456 }
457
458 if(entity.isEmpty() || name.isEmpty())
459 return 0;
460
461 for(int iter = ruleIndex; iter < m_ruleList.size(); ++iter)
462 {
463 ChemicalGroupRule *rule = m_ruleList.at(iter);
464
465 if(rule->entity() == entity && rule->name() == name)
466 {
467 if(index)
468 *index = iter;
469
470 return rule;
471 }
472 }
473
474 return 0;
475 }
476
477
478 /*!
479 \brief Parses the ChemicalGroup XML \a element \e{related to a \l Monomer}.
480
481 Upon parsing of the \a element (tag \code{<mnmchemgroup>}), its data
482 are validated and set to this ChemicalGroup instance, thus essentially
483 initializing it.
484
485 In an pkaphpidata definition file, the following xml structure
486 is encountered:
487
488 \code
489 <pkaphpidata>
490 <monomers>
491 <monomer>
492 <code>A</code>
493 <mnmchemgroup>
494 <name>N-term NH2</name>
495 <pka>9.6</pka>
496 <acidcharged>TRUE</acidcharged>
497 <polrule>left_trapped</polrule>
498 <chemgrouprule>
499 <entity>LE_PLM_MODIF</entity>
500 <name>Acetylation</name>
501 <outcome>LOST</outcome>
502 </chemgrouprule>
503 </mnmchemgroup>
504 <mnmchemgroup>
505 <name>C-term COOH</name>
506 <pka>2.35</pka>
507 <acidcharged>FALSE</acidcharged>
508 <polrule>right_trapped</polrule>
509 </mnmchemgroup>
510 </monomer>
511 <monomer>
512 <code>C</code>
513 <mnmchemgroup>
514 <name>N-term NH2</name>
515 <pka>9.6</pka>
516 <acidcharged>TRUE</acidcharged>
517 <polrule>left_trapped</polrule>
518 <chemgrouprule>
519 <entity>LE_PLM_MODIF</entity>
520 <name>Acetylation</name>
521 <outcome>LOST</outcome>
522 </chemgrouprule>
523 </mnmchemgroup>
524 <mnmchemgroup>
525 <name>C-term COOH</name>
526 <pka>2.35</pka>
527 <acidcharged>FALSE</acidcharged>
528 <polrule>right_trapped</polrule>
529 </mnmchemgroup>
530 <mnmchemgroup>
531 <name>Lateral SH2</name>
532 <pka>8.3</pka>
533 <acidcharged>FALSE</acidcharged>
534 <polrule>never_trapped</polrule>
535 </mnmchemgroup>
536 </monomer>
537 \endcode
538
539 Upon parsing of the \a element, all the data are validated and set to this
540 ChemicalGroup instance, thus essentially initializing it. If there are
541 \l{ChemicalGroupRule}s associated to the ChemicalGroup element, these are
542 rendered also.
543
544 Returns true if parsing and validation were successful, false otherwise.
545 */
546 bool
547 ChemicalGroup::renderXmlMnmElement(const QDomElement &element)
548 {
549 // The element the parameter points to is:
550 //
551 // <mnmchemgroup>
552 //
553 // Which means that element.tagName() == "mnmchemgroup" and that we'll
554 // have to go one step down to the first child of the current node
555 // in order to get to the \code<name>\endcode element.
556
557
558 QDomElement child;
559
560 if(element.tagName() != "mnmchemgroup")
561 return false;
562
563 child = element.firstChildElement("name");
564
565 if(child.isNull())
566 return false;
567
568 m_name = child.text();
569
570 child = child.nextSiblingElement();
571
572 if(child.isNull() || child.tagName() != "pka")
573 return false;
574
575 bool ok = false;
576 m_pka = child.text().toFloat(&ok);
577
578 if(!m_pka && !ok)
579 return false;
580
581 if(m_pka <= 0 || m_pka >= 14)
582 return false;
583
584 child = child.nextSiblingElement();
585
586 if(child.isNull() || child.tagName() != "acidcharged")
587 return false;
588
589 if(child.text() != "FALSE" && child.text() != "TRUE")
590 return false;
591
592 m_acidCharged = (child.text() == "FALSE" ? false : true);
593
594 // And now the polrule element. There should be one, here, in fact,
595 // because we are dealing with a monomer, and not a modification.
596
597 child = child.nextSiblingElement();
598
599 if(child.isNull() || child.tagName() != "polrule")
600 return false;
601
602 if(child.text() == "never_trapped")
603 m_polymerizationRule = ChemicalGroupTrapping::NEVER_TRAPPED;
604 else if(child.text() == "left_trapped")
605 m_polymerizationRule = ChemicalGroupTrapping::LEFT_TRAPPED;
606 else if(child.text() == "right_trapped")
607 m_polymerizationRule = ChemicalGroupTrapping::RIGHT_TRAPPED;
608 else
609 return false;
610
611 // And finally the chemical group rules... There might be zero, one
612 // or more.
613
614 QDomElement childChemGroupRule = child.nextSiblingElement("chemgrouprule");
615
616 while(!childChemGroupRule.isNull())
617 {
618 ChemicalGroupRule *rule = new ChemicalGroupRule();
619
620 if(!rule->renderXmlElement(childChemGroupRule))
621 {
622 delete rule;
623 return false;
624 }
625
626 m_ruleList.append(rule);
627
628 childChemGroupRule = childChemGroupRule.nextSiblingElement();
629 }
630
631 return true;
632 }
633
634
635 /*!
636 \brief Parses the ChemicalGroup XML \a element \e{related to a \l Modif}.
637
638 Upon parsing of the \a element (tag <mnmchemgroup>), its data are validated and
639 set to this ChemicalGroup instance, thus essentially initializing it.
640
641 In an pkaphpidata definition file, the following xml structure
642 is encountered:
643
644 \code
645 <pkaphpidata>
646 <monomers>
647 <monomer>
648 <code>A</code>
649 <mnmchemgroup>
650 <name>N-term NH2</name>
651 <pka>9.6</pka>
652 <acidcharged>TRUE</acidcharged>
653 <polrule>left_trapped</polrule>
654 <chemgrouprule>
655 <entity>LE_PLM_MODIF</entity>
656 <name>Acetylation</name>
657 <outcome>LOST</outcome>
658 </chemgrouprule>
659 </mnmchemgroup>
660 <mnmchemgroup>
661 <name>C-term COOH</name>
662 <pka>2.35</pka>
663 <acidcharged>FALSE</acidcharged>
664 <polrule>right_trapped</polrule>
665 </mnmchemgroup>
666 </monomer>
667 .......
668 </monomers>
669 <modifs>
670 <modif>
671 <name>Phosphorylation</name>
672 <mdfchemgroup>
673 <name>none_set</name>
674 <pka>1.2</pka>
675 <acidcharged>FALSE</acidcharged>
676 </mdfchemgroup>
677 <mdfchemgroup>
678 <name>none_set</name>
679 <pka>6.5</pka>
680 <acidcharged>FALSE</acidcharged>
681 </mdfchemgroup>
682 </modif>
683 </modifs>
684 </pkaphpidata>
685 \endcode
686
687 Upon parsing of the \a element, all the data are validated and set to this
688 ChemicalGroup instance, thus essentially initializing it. If there are
689 \l{ChemicalGroupRule}s associated to the ChemicalGroup element, these are
690 rendered also.
691
692 Returns true if parsing and validation were successful, false otherwise.
693 */
694 bool
695 ChemicalGroup::renderXmlMdfElement(const QDomElement &element)
696 {
697 QDomElement child;
698
699 if(element.tagName() != "mdfchemgroup")
700 return false;
701
702 child = element.firstChildElement("name");
703
704 if(child.isNull())
705 return false;
706
707 m_name = child.text();
708
709 child = child.nextSiblingElement();
710
711 if(child.isNull() || child.tagName() != "pka")
712 return false;
713
714 bool ok = false;
715 m_pka = child.text().toFloat(&ok);
716
717 if(!m_pka && !ok)
718 return false;
719
720 if(m_pka <= 0 || m_pka >= 14)
721 return false;
722
723 child = child.nextSiblingElement();
724
725 if(child.isNull() || child.tagName() != "acidcharged")
726 return false;
727
728 if(child.text() != "FALSE" && child.text() != "TRUE")
729 return false;
730
731 m_acidCharged = (child.text() == "FALSE" ? false : true);
732
733 return true;
734 }
735
736
737 //////////////////////// ChemicalGroupProp ////////////////////////
738 //////////////////////// ChemicalGroupProp ////////////////////////
739
740
741 /*!
742 \class MsXpS::libXpertMass::ChemicalGroupProp
743 \inmodule libXpertMass
744 \ingroup ThePropSystem
745
746 \brief The ChemicalGroupProp class provides a Prop instance of which the member
747 data points to a dynamically allocated \l ChemicalGroup instance.
748 */
749
750
751 /*!
752 \brief Constructs a ChemicalGroupProp instance using \a data and \a name.
753
754 The \a data pointer is set to the \l mpa_data member.
755 */
756 ChemicalGroupProp::ChemicalGroupProp(const QString &name, ChemicalGroup *data)
757 {
758 if(!name.isEmpty())
759 m_name = name;
760 else
761 m_name = QString();
762
763 mpa_data = static_cast<void *>(data);
764 }
765
766
767 /*!
768 \brief Constructs a ChemicalGroupProp instance as a copy of \a other.
769
770 The data in \a other are duplicated and set to this ChemicalGroupProp instance.
771 */
772 ChemicalGroupProp::ChemicalGroupProp(const ChemicalGroupProp &other)
773 : Prop(other)
774 {
775 if(other.mpa_data != nullptr)
776 {
777 ChemicalGroup *chemicalGroup =
778 static_cast<ChemicalGroup *>(other.mpa_data);
779
780 mpa_data = static_cast<void *>(new ChemicalGroup(*chemicalGroup));
781 }
782 else
783 mpa_data = nullptr;
784 }
785
786 /*!
787 \brief Destructs this ChemicalGroupProp instance.
788
789 The deletion of the data are delegated to \l deleteData().
790 */
791 ChemicalGroupProp::~ChemicalGroupProp()
792 {
793 deleteData();
794 }
795
796 /*!
797 \brief Deletes the member data.
798 */
799 void
800 ChemicalGroupProp::deleteData()
801 {
802 if(mpa_data != nullptr)
803 {
804 delete static_cast<ChemicalGroup *>(mpa_data);
805 mpa_data = nullptr;
806 }
807 }
808
809 /*!
810 \brief Assigns \a other to this ChemicalGroupProp instance.
811
812 The member data are first deleted and then set to a copy of those in \a other.
813 */
814 ChemicalGroupProp &
815 ChemicalGroupProp::operator=(const ChemicalGroupProp &other)
816 {
817 if(&other == this)
818 return *this;
819
820 Prop::operator=(other);
821
822 if(mpa_data != nullptr)
823 deleteData();
824
825 if(other.mpa_data != nullptr)
826 {
827 ChemicalGroup *chemicalGroup =
828 static_cast<ChemicalGroup *>(other.mpa_data);
829
830 mpa_data = static_cast<void *>(new ChemicalGroup(*chemicalGroup));
831 }
832 else
833 mpa_data = nullptr;
834
835 return *this;
836 }
837
838
839 /*!
840 \brief Duplicates this ChemicalGroupProp instance and returns its pointer.
841 */
842 ChemicalGroupProp *
843 ChemicalGroupProp::cloneOut() const
844 {
845 ChemicalGroupProp *new_p = new ChemicalGroupProp(*this);
846
847 return new_p;
848 }
849
850 bool
851 ChemicalGroupProp::renderXmlElement([[maybe_unused]] const QDomElement &element,
852 [[maybe_unused]] int version)
853 {
854 return false;
855 }
856
857 QString *
858 ChemicalGroupProp::formatXmlElement([[maybe_unused]] int offset,
859 [[maybe_unused]] const QString &indent)
860 {
861 return nullptr;
862 }
863
864 } // namespace libXpertMass
865
866 } // namespace MsXpS
867