1 /* massXpert - the true massist's program. 2 -------------------------------------- 3 Copyright(C) 2006,2007 Filippo Rusconi 4 5 http://www.massxpert.org/massXpert 6 7 This file is part of the massXpert project. 8 9 The massxpert project is the successor to the "GNU polyxmass" 10 project that is an official GNU project package(see 11 www.gnu.org). The massXpert project is not endorsed by the GNU 12 project, although it is released ---in its entirety--- under the 13 GNU General Public License. A huge part of the code in massXpert 14 is actually a C++ rewrite of code in GNU polyxmass. As such 15 massXpert was started at the Centre National de la Recherche 16 Scientifique(FRANCE), that granted me the formal authorization to 17 publish it under this Free Software License. 18 19 This software is free software; you can redistribute it and/or 20 modify it under the terms of the GNU General Public 21 License version 3, as published by the Free Software Foundation. 22 23 24 This software is distributed in the hope that it will be useful, 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 General Public License for more details. 28 29 You should have received a copy of the GNU General Public License 30 along with this software; if not, write to the 31 32 Free Software Foundation, Inc., 33 34 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 35 */ 36 37 38 /////////////////////// Qt includes 39 #include<QMessageBox> 40 #include<QFileDialog> 41 42 /////////////////////// Local includes 43 #include "massSearchDlg.hpp" 44 #include "application.hpp" 45 46 47 namespace massXpert 48 { 49 MassSearchDlg(QWidget * parent,Polymer * polymer,const CalcOptions & calcOptions,IonizeRule * ionizeRule)50 MassSearchDlg::MassSearchDlg(QWidget *parent, 51 Polymer *polymer, 52 const CalcOptions &calcOptions, 53 IonizeRule *ionizeRule) 54 : QDialog(parent), 55 mp_polymer(polymer), 56 m_calcOptions(calcOptions), 57 mp_ionizeRule(ionizeRule) 58 { 59 Q_ASSERT(parent); 60 Q_ASSERT(mp_polymer && mp_ionizeRule); 61 62 m_ui.setupUi(this); 63 64 mp_editorWnd = static_cast<SequenceEditorWnd *>(parent); 65 66 m_ui.delimiterLineEdit->setText("$"); 67 68 // Set the current whole/selected sequence data in the 69 // m_calcOptions instance and in the corresponding widgets (true = 70 // read from sequence editor window). 71 updateSelectionData(true); 72 73 m_monoTolerance = 0; 74 m_avgTolerance = 0; 75 76 m_ionizeStart = 0; 77 m_ionizeEnd = 0; 78 79 m_currentMass = 0; 80 m_foundOligosCount = 0; 81 82 m_abort = false; 83 m_sequenceEmbedded = false; 84 85 populateToleranceTypeComboBoxes(); 86 87 setupTableViews(); 88 89 m_ui.ionizationStartSpinBox->setRange(-1000000000, 1000000000); 90 m_ui.ionizationStartSpinBox->setValue(1); 91 92 m_ui.ionizationEndSpinBox->setRange(-1000000000, 1000000000); 93 m_ui.ionizationEndSpinBox->setValue(1); 94 95 m_ui.massSearchProgressBar->setRange(0, 100); 96 m_ui.massSearchProgressBar->setValue(0); 97 98 m_ui.avgToleranceComboBox->setToolTip(tr("AMU: atom mass unit \n" 99 "PCT: percent \n" 100 "PPM: part per million")); 101 m_ui.monoToleranceComboBox->setToolTip(tr("AMU: atom mass unit \n" 102 "PCT: percent \n" 103 "PPM: part per million")); 104 105 m_ui.monoMassLineEdit->setText("1"); 106 m_ui.avgMassLineEdit->setText("1"); 107 108 109 // The tolerance when filtering mono/avg masses... 110 QStringList stringList; 111 112 stringList << tr("AMU") << tr("PCT") << tr("PPM"); 113 114 m_ui.monoFilterToleranceComboBox->insertItems(0, stringList); 115 116 m_ui.monoFilterToleranceComboBox->setToolTip(tr("AMU: atom mass unit \n" 117 "PCT: percent \n" 118 "PPM: part per million")); 119 120 m_ui.avgFilterToleranceComboBox->insertItems(0, stringList); 121 122 m_ui.avgFilterToleranceComboBox->setToolTip(tr("AMU: atom mass unit \n" 123 "PCT: percent \n" 124 "PPM: part per million")); 125 126 m_ui.monoFilterToleranceLineEdit->setText("1"); 127 m_ui.avgFilterToleranceLineEdit->setText("1"); 128 129 monoFilterAct = new QAction(tr("Toggle Mono Filtering"), this); 130 monoFilterAct->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_M, Qt::Key_F)); 131 this->addAction(monoFilterAct); 132 connect(monoFilterAct, 133 SIGNAL(triggered()), 134 this, 135 SLOT(monoFilterOptionsToggled())); 136 137 m_ui.monoFilteringOptionsGroupBox->addAction(monoFilterAct); 138 139 avgFilterAct = new QAction(tr("Toggle Avg Filtering"), this); 140 avgFilterAct->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_A, Qt::Key_F)); 141 this->addAction(avgFilterAct); 142 connect(avgFilterAct, 143 SIGNAL(triggered()), 144 this, 145 SLOT(avgFilterOptionsToggled())); 146 147 m_ui.avgFilteringOptionsGroupBox->addAction(avgFilterAct); 148 149 // When the dialog box is created it is created with the groupbox 150 // unchecked. 151 m_ui.monoFilteringOptionsFrame->setVisible(false); 152 m_ui.avgFilteringOptionsFrame->setVisible(false); 153 154 // When the filtering group box will be opened, the focus will be on 155 // the first widget of the groupbox: 156 mp_monoFocusWidget = m_ui.monoFilterSearchedLineEdit; 157 mp_avgFocusWidget = m_ui.avgFilterSearchedLineEdit; 158 159 160 161 // The results-exporting menus. //////////////////////////////// 162 163 QStringList comboBoxItemList; 164 165 comboBoxItemList 166 << tr("To Clipboard") 167 << tr("To File") 168 << tr("Select File"); 169 170 m_ui.exportResultsComboBox->addItems(comboBoxItemList); 171 172 connect(m_ui.exportResultsComboBox, 173 SIGNAL(activated(int)), 174 this, 175 SLOT(exportResults(int))); 176 177 mpa_resultsString = new QString(); 178 179 //////////////////////////////////// The results-exporting menus. 180 181 182 QSettings settings 183 (static_cast<Application *>(qApp)->configSettingsFilePath(), 184 QSettings::IniFormat); 185 186 settings.beginGroup("mass_search_dlg"); 187 188 restoreGeometry(settings.value("geometry").toByteArray()); 189 190 m_ui.oligomersSplitter-> 191 restoreState(settings.value("oligomersSplitter").toByteArray()); 192 193 m_ui.oligoDetailsSplitter-> 194 restoreState(settings.value("oligoDetailsSplitter").toByteArray()); 195 196 m_ui.tableViewsSplitter-> 197 restoreState(settings.value("tableViewsSplitter").toByteArray()); 198 199 settings.endGroup(); 200 201 202 connect(m_ui.searchPushButton, 203 SIGNAL(clicked()), 204 this, 205 SLOT(search())); 206 207 connect(m_ui.abortPushButton, 208 SIGNAL(clicked()), 209 this, 210 SLOT(abort())); 211 212 connect(m_ui.updateCurrentSelectionDataPushButton, 213 SIGNAL(clicked()), 214 this, 215 SLOT(updateWholeSelectedSequenceData())); 216 217 218 // MONO set of filtering widgets 219 connect(m_ui.monoFilterSearchedLineEdit, 220 SIGNAL(returnPressed()), 221 this, 222 SLOT(monoFilterSearched())); 223 224 connect(m_ui.monoFilterErrorLineEdit, 225 SIGNAL(returnPressed()), 226 this, 227 SLOT(monoFilterError())); 228 229 connect(m_ui.monoFilterMonoMassLineEdit, 230 SIGNAL(returnPressed()), 231 this, 232 SLOT(monoFilterMonoMass())); 233 234 connect(m_ui.monoFilterAvgMassLineEdit, 235 SIGNAL(returnPressed()), 236 this, 237 SLOT(monoFilterAvgMass())); 238 239 connect(m_ui.monoFilteringOptionsGroupBox, 240 SIGNAL(clicked(bool)), 241 this, 242 SLOT(monoFilterOptions(bool))); 243 244 // AVG set of filtering widgets 245 connect(m_ui.avgFilterSearchedLineEdit, 246 SIGNAL(returnPressed()), 247 this, 248 SLOT(avgFilterSearched())); 249 250 connect(m_ui.avgFilterErrorLineEdit, 251 SIGNAL(returnPressed()), 252 this, 253 SLOT(avgFilterError())); 254 255 connect(m_ui.avgFilterMonoMassLineEdit, 256 SIGNAL(returnPressed()), 257 this, 258 SLOT(avgFilterMonoMass())); 259 260 connect(m_ui.avgFilterAvgMassLineEdit, 261 SIGNAL(returnPressed()), 262 this, 263 SLOT(avgFilterAvgMass())); 264 265 connect(m_ui.avgFilteringOptionsGroupBox, 266 SIGNAL(clicked(bool)), 267 this, 268 SLOT(avgFilterOptions(bool))); 269 } 270 271 ~MassSearchDlg()272 MassSearchDlg::~MassSearchDlg() 273 { 274 delete mpa_resultsString; 275 276 delete mpa_monoOligomerTableViewModel; 277 278 delete mpa_monoProxyModel; 279 280 delete mpa_avgOligomerTableViewModel; 281 282 delete mpa_avgProxyModel; 283 284 freeAllOligomerLists(); 285 } 286 287 288 void closeEvent(QCloseEvent * event)289 MassSearchDlg::closeEvent(QCloseEvent *event) 290 { 291 if (event) 292 printf("%s", ""); 293 294 QSettings settings 295 (static_cast<Application *>(qApp)->configSettingsFilePath(), 296 QSettings::IniFormat); 297 298 settings.beginGroup("mass_search_dlg"); 299 300 settings.setValue("geometry", saveGeometry()); 301 302 settings.setValue("oligomersSplitter", 303 m_ui.oligomersSplitter->saveState()); 304 305 settings.setValue("oligoDetailsSplitter", 306 m_ui.oligoDetailsSplitter->saveState()); 307 308 settings.setValue("tableViewsSplitter", 309 m_ui.tableViewsSplitter->saveState()); 310 311 settings.endGroup(); 312 } 313 314 315 SequenceEditorWnd * editorWnd()316 MassSearchDlg::editorWnd() 317 { 318 return mp_editorWnd; 319 } 320 321 322 bool populateToleranceTypeComboBoxes()323 MassSearchDlg::populateToleranceTypeComboBoxes() 324 { 325 QStringList stringList; 326 327 stringList << tr("AMU") << tr("PCT") << tr("PPM"); 328 329 m_ui.monoToleranceComboBox->insertItems(0, stringList); 330 m_ui.avgToleranceComboBox->insertItems(0, stringList); 331 332 return true; 333 } 334 335 void updateWholeSelectedSequenceData()336 MassSearchDlg::updateWholeSelectedSequenceData() 337 { 338 updateSelectionData(true); 339 } 340 341 342 bool updateSelectionData(bool fromSequenceEditor)343 MassSearchDlg::updateSelectionData(bool fromSequenceEditor) 344 { 345 // There are two situations: 346 347 // 1. This function is called from the constructor to setup data 348 // in the whole/selected sequence groupBox widget. It gets the 349 // info directly from the sequence editor window 350 // (fromSequenceEditor = true). By default the param is true, 351 // because this is expected for when this slot is called upon 352 // clicking on the Update button. 353 354 // 2. This function is called only to set the whole/selected 355 // sequence data in the calculation options instance. The data are 356 // read directly from the widgets and the sequence editor window 357 // is not probed. 358 359 if (!fromSequenceEditor) 360 { 361 // Only update that whole/selected sequence data in the 362 // m_calcOptions from the widgettry and not from the 363 // sequence. Because the user cannot modify the selection text 364 // in the line edit widget, all we need to know is: whole or 365 // selected sequence. 366 367 if (m_ui.wholeSequenceRadioButton->isChecked()) 368 { 369 // Set the "selection" to be the whole sequence. 370 371 Coordinates coordinates(0, mp_polymer->size() - 1); 372 m_calcOptions.setCoordinateList(coordinates); 373 374 m_ui.wholeSequenceRadioButton->setChecked(true); 375 376 return true; 377 } 378 // Else, we do not need to do anything. The selection is 379 // updated by clicking onto the Update button. 380 381 return true; 382 } 383 384 // At this point, we are asked to update the whole/selected 385 // sequence data directly from the sequence editor window. So get 386 // all these coordinates ! 387 388 CoordinateList coordList; 389 390 bool res = mp_editorWnd->mpa_editorGraphicsView-> 391 selectionIndices(&coordList); 392 393 if (res) 394 { 395 // If there are more than one region selection or if there is 396 // one region selection but spanning more than one monomer, 397 // then set the target to be "current selected sequence". 398 399 if(coordList.size() > 1) 400 { 401 // Apparently there are multiple regions selected. 402 403 m_ui.currentSelectionLineEdit-> 404 setText(coordList.positionsAsText()); 405 406 m_calcOptions.setCoordinateList(coordList); 407 } 408 else 409 { 410 Coordinates *coordinates = coordList.first(); 411 412 if (coordinates->start() == coordinates->end()) 413 { 414 // Construct a string with both the monomer code and 415 // its position in the sequence. 416 417 Polymer *polymer = mp_editorWnd->polymer(); 418 const Monomer *monomer = 419 polymer->monomerList().at(coordinates->start()); 420 421 QString text = tr("%1 at pos. %2") 422 .arg(monomer->code()) 423 .arg(coordinates->start() + 1); 424 425 m_ui.currentSelectionLineEdit->setText(text); 426 } 427 else 428 { 429 m_ui.currentSelectionLineEdit-> 430 setText(coordList.positionsAsText()); 431 } 432 433 m_calcOptions.setCoordinateList(*coordinates); 434 } 435 436 m_ui.currentSelectionRadioButton->setChecked(true); 437 } 438 else 439 { 440 // There is no selection, set the "selection" to be the 441 // whole sequence. 442 443 Coordinates coordinates(0, mp_polymer->size() - 1); 444 m_calcOptions.setCoordinateList(coordinates); 445 446 m_ui.wholeSequenceRadioButton->setChecked(true); 447 } 448 449 // Return if there was a selection(multiple-region or not) or 450 // not. 451 return res; 452 } 453 454 455 bool checkTolerance(int type)456 MassSearchDlg::checkTolerance(int type) 457 { 458 double nominal = 0; 459 bool ok = false; 460 461 QString text; 462 463 if (type & MXT_MASS_MONO) 464 { 465 text = m_ui.monoMassLineEdit->text(); 466 } 467 else if (type & MXT_MASS_AVG) 468 { 469 text = m_ui.avgMassLineEdit->text(); 470 } 471 else 472 Q_ASSERT(0); 473 474 if (text.isEmpty()) 475 return false; 476 477 nominal = text.toDouble(&ok); 478 479 if (!nominal && !ok) 480 return false; 481 482 return true; 483 } 484 485 bool calculateTolerance(double value,int type)486 MassSearchDlg::calculateTolerance(double value, int type) 487 { 488 int index = 0; 489 double nominal = 0; 490 491 bool ok = false; 492 493 QString text; 494 495 496 if (type & MXT_MASS_MONO) 497 { 498 index = m_ui.monoToleranceComboBox->currentIndex(); 499 text = m_ui.monoMassLineEdit->text(); 500 } 501 else if (type & MXT_MASS_AVG) 502 { 503 index = m_ui.avgToleranceComboBox->currentIndex(); 504 text = m_ui.avgMassLineEdit->text(); 505 } 506 else 507 Q_ASSERT(0); 508 509 510 nominal = text.toDouble(&ok); 511 512 if (!nominal && !ok) 513 return false; 514 515 if (index == 0) 516 { 517 // MXT_MASS_TOLERANCE_AMU 518 519 type & MXT_MASS_MONO ? 520 m_monoTolerance = nominal : 521 m_avgTolerance = nominal; 522 523 return true; 524 } 525 else if (index == 1) 526 { 527 // MXT_MASS_TOLERANCE_PCT 528 529 type & MXT_MASS_MONO ? 530 m_monoTolerance = nominal *(value / 100) : 531 m_avgTolerance = nominal *(value / 100); 532 533 return true; 534 } 535 else if (index == 2) 536 { 537 // MXT_MASS_TOLERANCE_PPM 538 539 type & MXT_MASS_MONO ? 540 m_monoTolerance = nominal *(value / 1000000) : 541 m_avgTolerance = nominal *(value / 1000000); 542 543 return true; 544 } 545 else 546 Q_ASSERT(0); 547 548 return false; 549 } 550 551 552 bool parseMassText(int type)553 MassSearchDlg::parseMassText(int type) 554 { 555 Application *application = static_cast<Application *>(qApp); 556 QLocale locale = application->locale(); 557 558 Q_ASSERT(type & MXT_MASS_MONO || type & MXT_MASS_AVG); 559 560 QString text; 561 562 if (type & MXT_MASS_MONO) 563 text = m_ui.monoMassTextEdit->toPlainText(); 564 else if (type & MXT_MASS_AVG) 565 text = m_ui.avgMassTextEdit->toPlainText(); 566 else 567 Q_ASSERT(0); 568 569 QStringList splitList = text.split(QRegExp("\\s+"), 570 QString::SkipEmptyParts); 571 572 for (int iter = 0; iter < splitList.size(); ++iter) 573 { 574 bool ok = false; 575 576 double value = locale.toDouble(splitList.at(iter), &ok); 577 578 if(!value && !ok) 579 { 580 qDebug() << "Error in mass list"; 581 582 return false; 583 } 584 585 if(type & MXT_MASS_MONO) 586 m_monoMassesList.append(value); 587 else 588 m_avgMassesList.append(value); 589 } 590 591 return true; 592 } 593 594 595 bool searchMass(double value,const Coordinates & coordinates,int type)596 MassSearchDlg::searchMass(double value, 597 const Coordinates &coordinates, 598 int type) 599 { 600 // CalcOptions localCalcOptions(*mp_calcOptions); 601 IonizeRule localIonizeRule(*mp_ionizeRule); 602 603 int count = 0; 604 int cycle = 0; 605 606 Q_ASSERT(type & MXT_MASS_MONO || type & MXT_MASS_AVG); 607 608 int startIndex = coordinates.start(); 609 int endIndex = coordinates.end(); 610 611 double maxValue = type & MXT_MASS_MONO ? 612 value + m_monoTolerance : 613 value + m_avgTolerance; 614 615 double minValue = type & MXT_MASS_MONO ? 616 value - m_monoTolerance : 617 value - m_avgTolerance; 618 619 if (minValue < 0) 620 minValue = 0; 621 622 m_currentMass = value; 623 updateProgressDetails(type); 624 625 for (int iter = startIndex; iter < endIndex + 1; ++iter) 626 { 627 if(m_abort) 628 return true; 629 630 for(int jter = 0; jter < endIndex + 1 - iter; ++jter) 631 { 632 // Note that the ionization starts from a low value and goes 633 // to a higher value, that means that while this loop runs 634 // for a given oligomer, the m/z ratio goes diminishing. 635 636 for (int kter = m_ionizeStart; kter < m_ionizeEnd + 1; 637 ++kter, ++cycle) 638 { 639 ++m_testedOligosCount; 640 641 if(cycle == 200) 642 { 643 cycle = 0; 644 updateProgressDetails(type); 645 } 646 647 localIonizeRule.setLevel(kter); 648 649 Oligomer oligomerTest(mp_polymer, 650 "NOT_SET" /*name*/, 651 QString("") /*description*/, 652 Ponderable(), 653 localIonizeRule, CalcOptions(),false, 654 iter, iter + jter); 655 656 oligomerTest.calculateMasses(&m_calcOptions); 657 658 double mz = type & MXT_MASS_MONO ? 659 oligomerTest.mono() : 660 oligomerTest.avg(); 661 662 if(mz < minValue) 663 // Oligomer's m/z already too small. Break 664 // immediately as this cannot get any better by 665 // continuing to increase the ionization level. 666 break; 667 668 if(mz > maxValue) 669 // Oligomer's m/z is still too big. Continue 670 // incrementing the ionization level, so that its 671 // m/z will decrease... 672 continue; 673 674 675 // At this point the oligomer has correct masses. 676 677 Oligomer *oligomerNew = new Oligomer(oligomerTest); 678 679 ++count; 680 681 int totalCharge = localIonizeRule.charge() * 682 localIonizeRule.level(); 683 684 QString name = QString("%1-z%2#%3") 685 .arg(value) 686 .arg(totalCharge) 687 .arg(count); 688 689 oligomerNew->setName(name); 690 691 // Set the searched mz in a prop. 692 693 DoubleProp *prop = new DoubleProp("SEARCHED_MZ", 694 value); 695 696 oligomerNew->appendProp(prop); 697 698 // Set the error mz in a prop. 699 700 double error = mz - value ; 701 702 prop = new DoubleProp("ERROR_MZ", error); 703 704 oligomerNew->appendProp(prop); 705 706 type & MXT_MASS_MONO ? 707 mpa_monoOligomerTableViewModel->addOligomer(oligomerNew) : 708 mpa_avgOligomerTableViewModel->addOligomer(oligomerNew); 709 710 ++m_foundOligosCount; 711 712 updateProgressDetails(type, false, oligomerNew); 713 } 714 // End of 715 // for (int kter = m_ionizeStart; kter < m_ionizeEnd + 1; ++kter) 716 } 717 // End of 718 // for (int jter = 0; jter < endIndex + 1 - iter; ++jter) 719 } 720 // End of 721 // for (int iter = startIndex; iter < endIndex + 1; ++iter) 722 723 return true; 724 } 725 726 727 bool searchMasses(int type)728 MassSearchDlg::searchMasses(int type) 729 { 730 if (!mp_polymer->size()) 731 return false; 732 733 const CoordinateList &coordinateList = m_calcOptions.coordinateList(); 734 735 if (type & MXT_MASS_MONO) 736 { 737 for(int iter = 0; iter < m_monoMassesList.size(); ++iter) 738 { 739 double value = m_monoMassesList.at(iter); 740 741 if (!calculateTolerance(value, MXT_MASS_MONO)) 742 return false; 743 744 for (int iter = 0; iter < coordinateList.size(); ++iter) 745 { 746 if(!searchMass(value, *(coordinateList.at(iter)), 747 MXT_MASS_MONO)) 748 return false; 749 750 m_ui.massSearchProgressBar->setValue(++m_progressValue); 751 752 if(m_abort) 753 return true; 754 } 755 } 756 } 757 else if (type & MXT_MASS_AVG) 758 { 759 for(int iter = 0; iter < m_avgMassesList.size(); ++iter) 760 { 761 double value = m_avgMassesList.at(iter); 762 763 if (!calculateTolerance(value, MXT_MASS_AVG)) 764 return false; 765 766 for (int iter = 0; iter < coordinateList.size(); ++iter) 767 { 768 if(!searchMass(value, *(coordinateList.at(iter)), 769 MXT_MASS_AVG)) 770 return false; 771 772 m_ui.massSearchProgressBar->setValue(++m_progressValue); 773 774 if(m_abort) 775 return true; 776 } 777 } 778 } 779 else 780 Q_ASSERT(0); 781 782 return true; 783 } 784 785 786 void search()787 MassSearchDlg::search() 788 { 789 // Update the options from the parent window. 790 m_calcOptions = mp_editorWnd->calcOptions(); 791 792 // Set the current whole/selected sequence data in the 793 // m_calcOptions instance (false = no read from sequence editor 794 // window). 795 updateSelectionData(false); 796 797 updateIonizationData(); 798 799 // Empty the treeviews and the lists of oligomers. 800 mpa_monoOligomerTableViewModel->removeOligomers(0, -1); 801 mpa_avgOligomerTableViewModel->removeOligomers(0, -1); 802 803 emptyAllMassLists(); 804 805 m_abort = false; 806 807 if (!parseMassText(MXT_MASS_MONO)) 808 { 809 QMessageBox::warning 810 (this, 811 tr("massXpert - Polymer Mass Search"), 812 tr("%1@%2\n" 813 "Failed to parse the masses to search for MONO.") 814 .arg(__FILE__) 815 .arg(__LINE__), 816 QMessageBox::Ok); 817 818 return; 819 } 820 821 if (!parseMassText(MXT_MASS_AVG)) 822 { 823 QMessageBox::warning 824 (this, 825 tr("massXpert - Polymer Mass Search"), 826 tr("%1@%2\n" 827 "Failed to parse the masses to search for AVG.") 828 .arg(__FILE__) 829 .arg(__LINE__), 830 QMessageBox::Ok); 831 832 return; 833 } 834 835 if (m_monoMassesList.size()) 836 { 837 if(!checkTolerance(MXT_MASS_MONO)) 838 { 839 QMessageBox::information(this, tr("massxpert - Mass Search"), 840 tr("Enter a valid MONO tolerance value"), 841 QMessageBox::Ok); 842 return; 843 } 844 } 845 846 if (m_avgMassesList.size()) 847 { 848 if(!checkTolerance(MXT_MASS_AVG)) 849 { 850 QMessageBox::information(this, tr("massxpert - Mass Search"), 851 tr("Enter a valid AVG tolerance value"), 852 QMessageBox::Ok); 853 return; 854 } 855 } 856 857 setCursor(Qt::WaitCursor); 858 859 m_testedOligosCount = 0; 860 m_foundOligosCount = 0; 861 862 int massNumber = m_monoMassesList.size() + m_avgMassesList.size(); 863 m_progressValue = 0; 864 m_ui.massSearchProgressBar->setRange(0, massNumber); 865 866 updateProgressDetails(MXT_MASS_MONO, true); 867 updateProgressDetails(MXT_MASS_AVG, true); 868 869 Application *application = static_cast<Application *>(qApp); 870 871 if (!searchMasses(MXT_MASS_MONO)) 872 { 873 QMessageBox::warning 874 (this, 875 tr("massXpert - Polymer Mass Search"), 876 tr("%1@%2\n" 877 "Failed to search for the MONO masses.") 878 .arg(__FILE__) 879 .arg(__LINE__), 880 QMessageBox::Ok); 881 882 setCursor(Qt::ArrowCursor); 883 updateMassSearchDetails(m_calcOptions); 884 application->beep(); 885 886 return; 887 } 888 889 if (!searchMasses(MXT_MASS_AVG)) 890 { 891 QMessageBox::warning 892 (this, 893 tr("massXpert - Polymer Mass Search"), 894 tr("%1@%2\n" 895 "Failed to search for the AVG masses.") 896 .arg(__FILE__) 897 .arg(__LINE__), 898 QMessageBox::Ok); 899 900 setCursor(Qt::ArrowCursor); 901 updateMassSearchDetails(m_calcOptions); 902 application->beep(); 903 904 return; 905 } 906 907 setCursor(Qt::ArrowCursor); 908 909 updateMassSearchDetails(m_calcOptions); 910 911 application->beep(); 912 } 913 914 915 void setupTableViews()916 MassSearchDlg::setupTableViews() 917 { 918 // Model stuff all thought for sorting. 919 mpa_monoOligomerTableViewModel = 920 new MassSearchOligomerTableViewModel(&m_monoOligomerList, this); 921 922 mpa_avgOligomerTableViewModel = 923 new MassSearchOligomerTableViewModel(&m_avgOligomerList, this); 924 925 mpa_monoProxyModel = new MassSearchOligomerTableViewSortProxyModel(this); 926 mpa_monoProxyModel->setSourceModel(mpa_monoOligomerTableViewModel); 927 mpa_monoProxyModel->setFilterKeyColumn(-1); 928 929 mpa_avgProxyModel = new MassSearchOligomerTableViewSortProxyModel(this); 930 mpa_avgProxyModel->setSourceModel(mpa_avgOligomerTableViewModel); 931 mpa_avgProxyModel->setFilterKeyColumn(-1); 932 933 m_ui.monoOligomerTableView->setModel(mpa_monoProxyModel); 934 m_ui.monoOligomerTableView->setParentDlg(this); 935 m_ui.monoOligomerTableView->setOligomerList(&m_monoOligomerList); 936 mpa_monoOligomerTableViewModel->setTableView(m_ui.monoOligomerTableView); 937 938 m_ui.avgOligomerTableView->setModel(mpa_avgProxyModel); 939 m_ui.avgOligomerTableView->setParentDlg(this); 940 m_ui.avgOligomerTableView->setOligomerList(&m_avgOligomerList); 941 mpa_avgOligomerTableViewModel->setTableView(m_ui.avgOligomerTableView); 942 } 943 944 945 void updateIonizationData()946 MassSearchDlg::updateIonizationData() 947 { 948 m_ionizeStart = m_ui.ionizationStartSpinBox->value(); 949 m_ionizeEnd = m_ui.ionizationEndSpinBox->value(); 950 951 if (m_ionizeStart > m_ionizeEnd) 952 { 953 int temp = m_ionizeStart; 954 m_ionizeStart = m_ionizeEnd; 955 m_ionizeEnd = temp; 956 } 957 } 958 959 960 void updateProgressDetails(int type,bool reset,Oligomer * oligomer)961 MassSearchDlg::updateProgressDetails(int type, bool reset, 962 Oligomer *oligomer) 963 { 964 Application *application = static_cast<Application *>(qApp); 965 QLocale locale = application->locale(); 966 967 if (reset) 968 { 969 m_ui.lastOligoNameLineEdit->setText(""); 970 m_ui.lastOligoCoordinatesLineEdit->setText(""); 971 m_ui.lastOligoMonoMassLineEdit->setText(""); 972 m_ui.lastOligoAvgMassLineEdit->setText(""); 973 974 m_ui.currentMassLineEdit->setText(""); 975 976 m_ui.lastOligoMassTypeLineEdit->setText(""); 977 978 m_ui.testedCountLabel->setText(QString().setNum(0)); 979 m_ui.foundCountLabel->setText(QString().setNum(0)); 980 981 m_ui.massSearchProgressBar->setValue(0); 982 983 application->processEvents(); 984 985 return; 986 } 987 988 if (oligomer) 989 { 990 m_ui.lastOligoNameLineEdit->setText(oligomer->name()); 991 QString coordinates(tr("[ %1 - %2 ]") 992 .arg(oligomer->startIndex() + 1) 993 .arg(oligomer->endIndex() + 1)); 994 995 m_ui.lastOligoCoordinatesLineEdit->setText(coordinates); 996 997 QString mass = oligomer->mono(locale); 998 m_ui.lastOligoMonoMassLineEdit->setText(mass); 999 1000 mass = oligomer->avg(locale); 1001 m_ui.lastOligoAvgMassLineEdit->setText(mass); 1002 } 1003 1004 m_ui.currentMassLineEdit->setText(QString().setNum(m_currentMass, 1005 'g', 10)); 1006 1007 type & MXT_MASS_MONO ? 1008 m_ui.lastOligoMassTypeLineEdit->setText(tr("MONO")) : 1009 m_ui.lastOligoMassTypeLineEdit->setText(tr("AVG")); 1010 1011 m_ui.testedCountLabel->setText(QString().setNum(m_testedOligosCount)); 1012 m_ui.foundCountLabel->setText(QString().setNum(m_foundOligosCount)); 1013 1014 m_ui.massSearchProgressBar->setValue(m_progressValue); 1015 1016 application->processEvents(); 1017 } 1018 1019 1020 void updateMassSearchDetails(const CalcOptions & calcOptions)1021 MassSearchDlg::updateMassSearchDetails(const CalcOptions &calcOptions) 1022 { 1023 if (calcOptions.monomerEntities() & MXT_MONOMER_CHEMENT_MODIF) 1024 m_ui.modificationsCheckBox->setCheckState(Qt::Checked); 1025 else 1026 m_ui.modificationsCheckBox->setCheckState(Qt::Unchecked); 1027 1028 if (calcOptions.polymerEntities() & MXT_POLYMER_CHEMENT_LEFT_END_MODIF) 1029 m_ui.leftModifCheckBox->setCheckState(Qt::Checked); 1030 else 1031 m_ui.leftModifCheckBox->setCheckState(Qt::Unchecked); 1032 1033 if (calcOptions.polymerEntities() & MXT_POLYMER_CHEMENT_RIGHT_END_MODIF) 1034 m_ui.rightModifCheckBox->setCheckState(Qt::Checked); 1035 else 1036 m_ui.rightModifCheckBox->setCheckState(Qt::Unchecked); 1037 } 1038 1039 1040 void updateOligomerSequence(QString * text)1041 MassSearchDlg::updateOligomerSequence(QString *text) 1042 { 1043 Q_ASSERT(text); 1044 1045 m_ui.oligomerSequenceTextEdit->clear(); 1046 m_ui.oligomerSequenceTextEdit->append(*text); 1047 } 1048 1049 1050 void freeAllOligomerLists()1051 MassSearchDlg::freeAllOligomerLists() 1052 { 1053 while(!m_monoOligomerList.isEmpty()) 1054 delete m_monoOligomerList.takeFirst(); 1055 1056 while(!m_avgOligomerList.isEmpty()) 1057 delete m_avgOligomerList.takeFirst(); 1058 } 1059 1060 1061 void emptyAllMassLists()1062 MassSearchDlg::emptyAllMassLists() 1063 { 1064 while(!m_monoMassesList.isEmpty()) 1065 m_monoMassesList.removeFirst(); 1066 1067 while(!m_avgMassesList.isEmpty()) 1068 m_avgMassesList.removeFirst(); 1069 } 1070 1071 1072 void abort()1073 MassSearchDlg::abort() 1074 { 1075 m_abort = true; 1076 } 1077 1078 1079 1080 bool calculateFilterTolerance(double mass,int massType)1081 MassSearchDlg::calculateFilterTolerance(double mass, int massType) 1082 { 1083 // Get the tolerance that is in its lineEdit. 1084 QString text; 1085 1086 if (massType == MXT_MASS_MONO) 1087 text = m_ui.monoFilterToleranceLineEdit->text(); 1088 else if (massType == MXT_MASS_AVG) 1089 text = m_ui.avgFilterToleranceLineEdit->text(); 1090 else 1091 Q_ASSERT(0); 1092 1093 double tolerance = 0; 1094 bool ok = false; 1095 1096 if (!text.isEmpty()) 1097 { 1098 // Convert the string to a double. 1099 Application *application = static_cast<Application *>(qApp); 1100 QLocale locale = application->locale(); 1101 1102 ok = false; 1103 tolerance = locale.toDouble(text, &ok); 1104 1105 if(!tolerance && !ok) 1106 return false; 1107 } 1108 else 1109 { 1110 m_filterTolerance = 0; 1111 } 1112 1113 // What's the item currently selected in the comboBox? 1114 int index = 0; 1115 1116 if (massType == MXT_MASS_MONO) 1117 index = m_ui.monoFilterToleranceComboBox->currentIndex(); 1118 else if (massType == MXT_MASS_AVG) 1119 index = m_ui.avgFilterToleranceComboBox->currentIndex(); 1120 else 1121 Q_ASSERT(0); 1122 1123 if (index == 0) 1124 { 1125 // MXT_MASS_TOLERANCE_AMU 1126 m_filterTolerance = tolerance; 1127 } 1128 else if (index == 1) 1129 { 1130 // MXT_MASS_TOLERANCE_PCT 1131 m_filterTolerance =(tolerance / 100) * mass; 1132 } 1133 else if (index == 2) 1134 { 1135 // MXT_MASS_TOLERANCE_PPM 1136 m_filterTolerance =(tolerance / 1000000) * mass; 1137 } 1138 else 1139 Q_ASSERT(0); 1140 1141 return true; 1142 } 1143 1144 1145 void monoFilterOptions(bool checked)1146 MassSearchDlg::monoFilterOptions(bool checked) 1147 { 1148 if (!checked) 1149 { 1150 mpa_monoProxyModel->setFilterKeyColumn(-1); 1151 1152 mpa_monoProxyModel->applyNewFilter(); 1153 1154 m_ui.monoFilteringOptionsFrame->setVisible(false); 1155 } 1156 else 1157 { 1158 m_ui.monoFilteringOptionsFrame->setVisible(true); 1159 1160 // In this case, set focus to the last focused widget in the 1161 // groupbox or the first widget in the groubox if this is the 1162 // first time the filtering is used. 1163 mp_monoFocusWidget->setFocus(); 1164 } 1165 } 1166 1167 1168 void monoFilterOptionsToggled()1169 MassSearchDlg::monoFilterOptionsToggled() 1170 { 1171 bool isChecked = m_ui.monoFilteringOptionsGroupBox->isChecked(); 1172 1173 m_ui.monoFilteringOptionsGroupBox->setChecked(!isChecked); 1174 monoFilterOptions(!isChecked); 1175 } 1176 1177 1178 void avgFilterOptions(bool checked)1179 MassSearchDlg::avgFilterOptions(bool checked) 1180 { 1181 if (!checked) 1182 { 1183 mpa_avgProxyModel->setFilterKeyColumn(-1); 1184 1185 mpa_avgProxyModel->applyNewFilter(); 1186 1187 m_ui.avgFilteringOptionsFrame->setVisible(false); 1188 } 1189 else 1190 { 1191 m_ui.avgFilteringOptionsFrame->setVisible(true); 1192 1193 // In this case, set focus to the last focused widget in the 1194 // groupbox or the first widget in the groubox if this is the 1195 // first time the filtering is used. 1196 mp_avgFocusWidget->setFocus(); 1197 } 1198 } 1199 1200 1201 void avgFilterOptionsToggled()1202 MassSearchDlg::avgFilterOptionsToggled() 1203 { 1204 bool isChecked = m_ui.avgFilteringOptionsGroupBox->isChecked(); 1205 1206 m_ui.avgFilteringOptionsGroupBox->setChecked(!isChecked); 1207 avgFilterOptions(!isChecked); 1208 } 1209 1210 1211 void monoFilterSearched()1212 MassSearchDlg::monoFilterSearched() 1213 { 1214 // First off, we have to get the mass that is in the lineEdit. 1215 1216 QString text = m_ui.monoFilterSearchedLineEdit->text(); 1217 1218 if (text.isEmpty()) 1219 return; 1220 1221 // Convert the string to a double. 1222 Application *application = static_cast<Application *>(qApp); 1223 QLocale locale = application->locale(); 1224 1225 bool ok = false; 1226 double mass = locale.toDouble(text, &ok); 1227 1228 if (!mass && !ok) 1229 return; 1230 1231 mpa_monoProxyModel->setSearchedFilter(mass); 1232 1233 mpa_monoProxyModel->setFilterKeyColumn(0); 1234 mpa_monoProxyModel->applyNewFilter(); 1235 1236 mp_monoFocusWidget = m_ui.monoFilterSearchedLineEdit; 1237 } 1238 1239 1240 void avgFilterSearched()1241 MassSearchDlg::avgFilterSearched() 1242 { 1243 // First off, we have to get the mass that is in the lineEdit. 1244 1245 QString text = m_ui.avgFilterSearchedLineEdit->text(); 1246 1247 if (text.isEmpty()) 1248 return; 1249 1250 // Convert the string to a double. 1251 Application *application = static_cast<Application *>(qApp); 1252 QLocale locale = application->locale(); 1253 1254 bool ok = false; 1255 double mass = locale.toDouble(text, &ok); 1256 1257 if (!mass && !ok) 1258 return; 1259 1260 mpa_avgProxyModel->setSearchedFilter(mass); 1261 1262 mpa_avgProxyModel->setFilterKeyColumn(0); 1263 mpa_avgProxyModel->applyNewFilter(); 1264 1265 mp_avgFocusWidget = m_ui.avgFilterSearchedLineEdit; 1266 } 1267 1268 1269 void monoFilterError()1270 MassSearchDlg::monoFilterError() 1271 { 1272 // First off, we have to get the mass error that is in the lineEdit. 1273 1274 QString text = m_ui.monoFilterErrorLineEdit->text(); 1275 1276 if (text.isEmpty()) 1277 return; 1278 1279 // Convert the string to a double. 1280 Application *application = static_cast<Application *>(qApp); 1281 QLocale locale = application->locale(); 1282 1283 bool ok = false; 1284 double mass = locale.toDouble(text, &ok); 1285 1286 if (!mass && !ok) 1287 return; 1288 1289 // At this point, depending on the item that is currently selected 1290 // in the comboBox, we'll have to actually compute the tolerance. 1291 1292 if (!calculateFilterTolerance(mass, MXT_MASS_MONO)) 1293 return ; 1294 1295 mpa_monoProxyModel->setErrorFilter(mass); 1296 mpa_monoProxyModel->setTolerance(m_filterTolerance); 1297 1298 mpa_monoProxyModel->setFilterKeyColumn(3); 1299 mpa_monoProxyModel->applyNewFilter(); 1300 1301 mp_monoFocusWidget = m_ui.monoFilterErrorLineEdit; 1302 } 1303 1304 1305 void avgFilterError()1306 MassSearchDlg::avgFilterError() 1307 { 1308 // First off, we have to get the mass error that is in the lineEdit. 1309 1310 QString text = m_ui.avgFilterErrorLineEdit->text(); 1311 1312 if (text.isEmpty()) 1313 return; 1314 1315 // Convert the string to a double. 1316 Application *application = static_cast<Application *>(qApp); 1317 QLocale locale = application->locale(); 1318 1319 bool ok = false; 1320 double mass = locale.toDouble(text, &ok); 1321 1322 if (!mass && !ok) 1323 return; 1324 1325 // At this point, depending on the item that is currently selected 1326 // in the comboBox, we'll have to actually compute the tolerance. 1327 1328 if (!calculateFilterTolerance(mass, MXT_MASS_AVG)) 1329 return ; 1330 1331 mpa_avgProxyModel->setErrorFilter(mass); 1332 mpa_avgProxyModel->setTolerance(m_filterTolerance); 1333 1334 mpa_avgProxyModel->setFilterKeyColumn(3); 1335 mpa_avgProxyModel->applyNewFilter(); 1336 1337 mp_avgFocusWidget = m_ui.avgFilterErrorLineEdit; 1338 } 1339 1340 1341 void monoFilterMonoMass()1342 MassSearchDlg::monoFilterMonoMass() 1343 { 1344 // First off, we have to get the mass that is in the lineEdit. 1345 1346 QString text = m_ui.monoFilterMonoMassLineEdit->text(); 1347 1348 if (text.isEmpty()) 1349 return; 1350 1351 // Convert the string to a double. 1352 Application *application = static_cast<Application *>(qApp); 1353 QLocale locale = application->locale(); 1354 1355 bool ok = false; 1356 double mass = locale.toDouble(text, &ok); 1357 1358 if (!mass && !ok) 1359 return; 1360 1361 // At this point, depending on the item that is currently selected 1362 // in the comboBox, we'll have to actually compute the tolerance. 1363 1364 if (!calculateFilterTolerance(mass, MXT_MASS_MONO)) 1365 return ; 1366 1367 mpa_monoProxyModel->setMonoFilter(mass); 1368 mpa_monoProxyModel->setTolerance(m_filterTolerance); 1369 1370 mpa_monoProxyModel->setFilterKeyColumn(4); 1371 mpa_monoProxyModel->applyNewFilter(); 1372 1373 mp_monoFocusWidget = m_ui.monoFilterMonoMassLineEdit; 1374 } 1375 1376 1377 void avgFilterMonoMass()1378 MassSearchDlg::avgFilterMonoMass() 1379 { 1380 // First off, we have to get the mass that is in the lineEdit. 1381 1382 QString text = m_ui.avgFilterMonoMassLineEdit->text(); 1383 1384 if (text.isEmpty()) 1385 return; 1386 1387 // Convert the string to a double. 1388 Application *application = static_cast<Application *>(qApp); 1389 QLocale locale = application->locale(); 1390 1391 bool ok = false; 1392 double mass = locale.toDouble(text, &ok); 1393 1394 if (!mass && !ok) 1395 return; 1396 1397 // At this point, depending on the item that is currently selected 1398 // in the comboBox, we'll have to actually compute the tolerance. 1399 1400 if (!calculateFilterTolerance(mass, MXT_MASS_AVG)) 1401 return ; 1402 1403 mpa_avgProxyModel->setMonoFilter(mass); 1404 mpa_avgProxyModel->setTolerance(m_filterTolerance); 1405 1406 mpa_avgProxyModel->setFilterKeyColumn(4); 1407 mpa_avgProxyModel->applyNewFilter(); 1408 1409 mp_avgFocusWidget = m_ui.avgFilterMonoMassLineEdit; 1410 } 1411 1412 1413 void monoFilterAvgMass()1414 MassSearchDlg::monoFilterAvgMass() 1415 { 1416 // First off, we have to get the mass that is in the lineEdit. 1417 1418 QString text = m_ui.monoFilterAvgMassLineEdit->text(); 1419 1420 if (text.isEmpty()) 1421 return; 1422 1423 // Convert the string to a double. 1424 Application *application = static_cast<Application *>(qApp); 1425 QLocale locale = application->locale(); 1426 1427 bool ok = false; 1428 double mass = locale.toDouble(text, &ok); 1429 1430 if (!mass && !ok) 1431 return; 1432 1433 // At this point, depending on the item that is currently selected 1434 // in the comboBox, we'll have to actually compute the tolerance. 1435 1436 if (!calculateFilterTolerance(mass, MXT_MASS_MONO)) 1437 return ; 1438 1439 mpa_monoProxyModel->setAvgFilter(mass); 1440 mpa_monoProxyModel->setTolerance(m_filterTolerance); 1441 1442 mpa_monoProxyModel->setFilterKeyColumn(5); 1443 mpa_monoProxyModel->applyNewFilter(); 1444 1445 mp_monoFocusWidget = m_ui.monoFilterAvgMassLineEdit; 1446 } 1447 1448 1449 void avgFilterAvgMass()1450 MassSearchDlg::avgFilterAvgMass() 1451 { 1452 // First off, we have to get the mass that is in the lineEdit. 1453 1454 QString text = m_ui.avgFilterAvgMassLineEdit->text(); 1455 1456 if (text.isEmpty()) 1457 return; 1458 1459 // Convert the string to a double. 1460 Application *application = static_cast<Application *>(qApp); 1461 QLocale locale = application->locale(); 1462 1463 bool ok = false; 1464 double mass = locale.toDouble(text, &ok); 1465 1466 if (!mass && !ok) 1467 return; 1468 1469 // At this point, depending on the item that is currently selected 1470 // in the comboBox, we'll have to actually compute the tolerance. 1471 1472 if (!calculateFilterTolerance(mass, MXT_MASS_AVG)) 1473 return ; 1474 1475 mpa_avgProxyModel->setAvgFilter(mass); 1476 mpa_avgProxyModel->setTolerance(m_filterTolerance); 1477 1478 mpa_avgProxyModel->setFilterKeyColumn(5); 1479 mpa_avgProxyModel->applyNewFilter(); 1480 1481 mp_avgFocusWidget = m_ui.avgFilterAvgMassLineEdit; 1482 } 1483 1484 1485 1486 // The results-exporting functions. //////////////////////////////// 1487 // The results-exporting functions. //////////////////////////////// 1488 // The results-exporting functions. //////////////////////////////// 1489 void exportResults(int index)1490 MassSearchDlg::exportResults(int index) 1491 { 1492 // Remember that we had set up the combobox with the following strings: 1493 // << tr("To &Clipboard") 1494 // << tr("To &File") 1495 // << tr("&Select File"); 1496 1497 if (index == 0) 1498 { 1499 exportResultsClipboard(); 1500 } 1501 else if (index == 1) 1502 { 1503 exportResultsFile(); 1504 } 1505 else if (index == 2) 1506 { 1507 selectResultsFile(); 1508 } 1509 else 1510 Q_ASSERT(0); 1511 1512 } 1513 1514 1515 void prepareResultsTxtString()1516 MassSearchDlg::prepareResultsTxtString() 1517 { 1518 // Set the delimiter to the char/string that is in the 1519 // corresponding text line edit widget. 1520 1521 QString delimiter = m_ui.delimiterLineEdit->text(); 1522 // If delimiter is empty, the function that will prepare the 1523 // string will put the default character, that is '$'. 1524 1525 mpa_resultsString->clear(); 1526 1527 // We only put the header info if the user does not want to have 1528 // the data formatted for XpertMiner, which only can get the data 1529 // in the format : 1530 // 1531 // mass <delim> charge <delim> name <delim> coords 1532 // 1533 // Note that name and coords are optional. 1534 bool forXpertMiner = false; 1535 MassType massType = MXT_MASS_NONE; 1536 1537 forXpertMiner = m_ui.forXpertMinerCheckBox->isChecked(); 1538 1539 if (!forXpertMiner) 1540 { 1541 *mpa_resultsString += QObject::tr("# \n" 1542 "# ---------------------------\n" 1543 "# Mass Search: \n" 1544 "# ---------------------------\n"); 1545 } 1546 else 1547 { 1548 // Then, we should ask whether the masses to be exported are 1549 // the mono or avg masses. 1550 1551 if(m_ui.monoRadioButton->isChecked()) 1552 massType = MXT_MASS_MONO; 1553 else 1554 massType = MXT_MASS_AVG; 1555 } 1556 1557 1558 // Should the oligomers have their sequence displayed? 1559 bool withSequence = m_ui.withSequenceCheckBox->isChecked(); 1560 1561 QString masses; 1562 1563 // We only show the list of masses if we are exporting not for 1564 // XpertMiner. 1565 1566 if(!forXpertMiner) 1567 { 1568 // Get the mono masses searched: 1569 masses = m_ui.monoMassTextEdit->toPlainText(); 1570 if (!masses.isEmpty()) 1571 { 1572 *mpa_resultsString += QObject::tr("\nSearched mono masses:\n" 1573 "%1\n") 1574 .arg(masses); 1575 } 1576 } 1577 1578 QString *text = 0; 1579 1580 // We export mono data only in two situations: when the data is 1581 // for XpertMiner and the user has selected the Mono radio button 1582 // or when the data is not for XpertMiner. 1583 1584 if((!forXpertMiner) || 1585 (forXpertMiner && m_ui.monoRadioButton->isChecked())) 1586 { 1587 // The mono treeview: 1588 1589 text = m_ui.monoOligomerTableView-> 1590 selectedOligomersAsPlainText(delimiter, 1591 withSequence, 1592 forXpertMiner, 1593 massType); 1594 1595 *mpa_resultsString += *text; 1596 1597 delete text; 1598 } 1599 1600 if(!forXpertMiner) 1601 { 1602 // Get the avg masses searched: 1603 masses = m_ui.avgMassTextEdit->toPlainText(); 1604 if (!masses.isEmpty()) 1605 { 1606 *mpa_resultsString += QObject::tr("\nSearched average masses:\n" 1607 "%1\n") 1608 .arg(masses); 1609 } 1610 } 1611 1612 1613 // We export mono data only in two situations: when the data is 1614 // for XpertMiner and the user has selected the Mono radio button 1615 // or when the data is not for XpertMiner. 1616 1617 if((!forXpertMiner) || 1618 (forXpertMiner && m_ui.avgRadioButton->isChecked())) 1619 { 1620 // The avg treeview: 1621 1622 text = m_ui.avgOligomerTableView-> 1623 selectedOligomersAsPlainText(delimiter, 1624 withSequence, 1625 forXpertMiner, 1626 massType); 1627 1628 *mpa_resultsString += *text; 1629 1630 delete text; 1631 } 1632 1633 } 1634 1635 1636 bool exportResultsClipboard()1637 MassSearchDlg::exportResultsClipboard() 1638 { 1639 prepareResultsTxtString(); 1640 1641 QClipboard *clipboard = QApplication::clipboard(); 1642 1643 clipboard->setText(*mpa_resultsString, QClipboard::Clipboard); 1644 1645 return true; 1646 } 1647 1648 1649 bool exportResultsFile()1650 MassSearchDlg::exportResultsFile() 1651 { 1652 if (m_resultsFilePath.isEmpty()) 1653 { 1654 if(!selectResultsFile()) 1655 return false; 1656 } 1657 1658 QFile file(m_resultsFilePath); 1659 1660 if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) 1661 { 1662 QMessageBox::information(0, 1663 tr("massXpert - Export Data"), 1664 tr("Failed to open file in append mode."), 1665 QMessageBox::Ok); 1666 return false; 1667 } 1668 1669 QTextStream stream(&file); 1670 stream.setCodec("UTF-8"); 1671 1672 prepareResultsTxtString(); 1673 1674 stream << *mpa_resultsString; 1675 1676 file.close(); 1677 1678 return true; 1679 } 1680 1681 1682 bool selectResultsFile()1683 MassSearchDlg::selectResultsFile() 1684 { 1685 m_resultsFilePath = 1686 QFileDialog::getSaveFileName(this, tr("Select File To Export Data To"), 1687 QDir::homePath(), 1688 tr("Data files(*.dat *.DAT)")); 1689 1690 if (m_resultsFilePath.isEmpty()) 1691 return false; 1692 1693 return true; 1694 } 1695 //////////////////////////////////// The results-exporting functions. 1696 //////////////////////////////////// The results-exporting functions. 1697 //////////////////////////////////// The results-exporting functions. 1698 1699 } // namespace massXpert 1700