UltraScan III
us_analyte_gui.cpp
Go to the documentation of this file.
1 #include "us_analyte_gui.h"
3 #include "us_passwd.h"
4 #include "us_settings.h"
5 #include "us_gui_settings.h"
6 #include "us_investigator.h"
7 #include "us_editor_gui.h"
8 #include "us_table.h"
9 #include "us_util.h"
10 
12  const QString& GUID,
13  int access,
14  double temp )
15  : US_WidgetsDialog( 0, 0 ),
16  signal_wanted( signal ),
17  guid ( GUID ),
18  temperature ( temp )
19 {
20  setWindowTitle( tr( "Analyte Management" ) );
21  setPalette( US_GuiSettings::frameColor() );
22  setAttribute( Qt::WA_DeleteOnClose );
23 
25  analyte = US_Analyte();
27 
28  QPalette normal = US_GuiSettings::editColor();
29 
30  QGridLayout* main = new QGridLayout( this );
31  main->setSpacing ( 2 );
32  main->setContentsMargins ( 2, 2, 2, 2 );
33 
34  int row = 0;
35 
36  QStringList DB = US_Settings::defaultDB();
37  QString db_name;
38 
39  if ( DB.size() < 5 )
40  db_name = "No Default Set";
41  else
42  db_name = DB.at( 0 );
43 
44  QLabel* lb_DB = us_banner( tr( "Database: " ) + db_name, -1 );
45  lb_DB->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
46  main->addWidget( lb_DB, row++, 0, 1, 3 );
47 
48  QGridLayout* protein = us_radiobutton( tr( "Protein" ),
49  rb_protein, true );
50  QGridLayout* dna = us_radiobutton( tr( "DNA" ), rb_dna );
51  QGridLayout* rna = us_radiobutton( tr( "RNA" ), rb_rna );
52  QGridLayout* carb = us_radiobutton( tr( "Carbohydrate/Other" ), rb_carb );
53 
54  QHBoxLayout* radios = new QHBoxLayout;
55  radios->addLayout( protein );
56  radios->addLayout( dna );
57  radios->addLayout( rna );
58  radios->addLayout( carb );
59 
60  main->addLayout( radios, row++, 0, 1, 3 );
61 
62  QButtonGroup* typeButtons = new QButtonGroup( this );
63  typeButtons->addButton( rb_protein, US_Analyte::PROTEIN );
64  typeButtons->addButton( rb_dna , US_Analyte::DNA );
65  typeButtons->addButton( rb_rna , US_Analyte::RNA );
66  typeButtons->addButton( rb_carb , US_Analyte::CARBOHYDRATE );
67  connect( typeButtons, SIGNAL( buttonClicked ( int ) ),
68  SLOT ( set_analyte_type ( int ) ) );
69 
70  QPushButton* pb_investigator = us_pushbutton( tr( "Select Investigator" ) );
71  connect( pb_investigator, SIGNAL( clicked() ), SLOT( sel_investigator() ) );
72  main->addWidget( pb_investigator, row, 0 );
73 
74  QString investigator = QString::number( US_Settings::us_inv_ID() ) + ": " +
76 
77  if ( US_Settings::us_inv_level() < 1 )
78  pb_investigator->setEnabled( false );
79 
80  le_investigator = us_lineedit( investigator, 0, true );
81  main->addWidget( le_investigator, row++, 1, 1, 2 );
82 
83  QBoxLayout* search = new QHBoxLayout;
84 
85  // Search
86  QLabel* lb_search = us_label( tr( "Search:" ) );
87  search->addWidget( lb_search );
88 
90  le_search->setReadOnly( true );
91  connect( le_search, SIGNAL( textChanged( const QString& ) ),
92  SLOT ( search ( const QString& ) ) );
93  search->addWidget( le_search );
94  main->addLayout( search, row++, 0 );
95 
96  // Analyte descriptions from DB
97  QLabel* lb_banner1 = us_banner( tr( "Doubleclick on analyte data to select" ), -1 );
98  lb_banner1->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
99  main->addWidget( lb_banner1, row++, 0 );
100 
102  connect( lw_analytes, SIGNAL( itemDoubleClicked( QListWidgetItem* ) ),
103  SLOT ( select_analyte ( QListWidgetItem* ) ) );
104 
105  main->addWidget( lw_analytes, row, 0, 6, 1 );
106  row += 6;
107 
108  // Labels
109  QGridLayout* description = new QGridLayout;
110  QLabel* lb_description = us_label( tr( "Analyte Description:" ) );
111  description->addWidget( lb_description, 0, 0 );
112 
113  le_description = us_lineedit( "" );
114  connect( le_description, SIGNAL( editingFinished () ),
115  SLOT ( change_description() ) );
116  description->addWidget( le_description, 0, 1 );
117 
118  QLabel* lb_guid = us_label( tr( "Global Identifier:" ) );
119  description->addWidget( lb_guid, 1, 0 );
120 
121  le_guid = us_lineedit( "", 0, true );
122  description->addWidget( le_guid, 1, 1 );
123  main->addLayout( description, row, 0, 2, 3 );
124 
125  if ( US_Settings::us_debug() == 0 )
126  {
127  lb_guid->setVisible( false );
128  le_guid->setVisible( false );
129  }
130 
131  // Go back to top of 2nd column
132  row = 3;
133  disk_controls = new US_Disk_DB_Controls( access );
134  connect( disk_controls, SIGNAL( changed ( bool ) ),
135  SLOT ( source_changed( bool ) ) );
136  main->addLayout( disk_controls, row++, 1, 1, 2 );
137 
138  QLabel* lb_banner3 = us_banner( tr( "Database/Disk Functions" ), -2 );
139  lb_banner3->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
140  main->addWidget( lb_banner3, row++, 1, 1, 2 );
141 
142  QPushButton* pb_list = us_pushbutton(
143  tr( "List Descriptions" ) );
144  connect( pb_list, SIGNAL( clicked() ), SLOT( list() ) );
145  main->addWidget( pb_list, row, 1 );
146 
147  QPushButton* pb_new = us_pushbutton( tr( "New Analyte" ) );
148  connect( pb_new, SIGNAL( clicked() ), SLOT( new_analyte() ) );
149  main->addWidget( pb_new, row++, 2 );
150 
151  pb_save = us_pushbutton( tr( "Save Analyte" ), false );
152  connect( pb_save, SIGNAL( clicked() ), SLOT( save() ) );
153  main->addWidget( pb_save, row, 1 );
154 
155  pb_delete = us_pushbutton( tr( "Delete Analyte" ), false );
156  connect( pb_delete, SIGNAL( clicked() ), SLOT( delete_analyte() ) );
157  main->addWidget( pb_delete, row++, 2 );
158 
159  QLabel* lb_banner4 = us_banner( tr( "Other Functions" ), -2 );
160  lb_banner4->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
161  main->addWidget( lb_banner4, row++, 1, 1, 2 );
162 
163  pb_sequence = us_pushbutton( tr( "Manage Sequence" ) );
164  connect( pb_sequence, SIGNAL( clicked() ), SLOT( manage_sequence() ) );
165  main->addWidget( pb_sequence, row, 1 );
166 
167  pb_spectrum = us_pushbutton( tr( "Manage Spectrum" ) );
168  connect( pb_spectrum, SIGNAL( clicked() ), SLOT( spectrum() ) );
169  main->addWidget( pb_spectrum, row++, 2 );
170 
171  pb_more = us_pushbutton( tr( "More Info" ), false );
172  connect( pb_more, SIGNAL( clicked() ), SLOT( more_info() ) );
173  main->addWidget( pb_more, row, 1 );
174 
176  cmb_optics->addItem( tr( "Absorbance" ) );
177  cmb_optics->addItem( tr( "Interference" ) );
178  cmb_optics->addItem( tr( "Fluorescence" ) );
179  main->addWidget( cmb_optics, row++, 2 );
180  QSpacerItem* spacer0 = new QSpacerItem( 20, 9 );
181  main->addItem ( spacer0, row++, 2 );
182 
183  row +=2;
184 
185  // Lower half -- protein operations and data
186  protein_widget = new QWidget( this );
187 
188  QGridLayout* protein_info = new QGridLayout( protein_widget );
189  protein_info->setSpacing ( 2 );
190  protein_info->setContentsMargins( 2, 2, 2, 2 );
191 
192  int prow = 0;
193 
194  QLabel* lb_protein_mw = us_label( tr( "MW <small>(Daltons)</small>:" ) );
195  protein_info->addWidget( lb_protein_mw, prow, 0 );
196 
197  le_protein_mw = us_lineedit( "", 0, false );
198  protein_info->addWidget( le_protein_mw, prow, 1 );
199 
200  QLabel* lb_protein_vbar20 = us_label(
201  tr( "VBar <small>(cm<sup>3</sup>/g at 20" ) + DEGC + ")</small>:" );
202  protein_info->addWidget( lb_protein_vbar20, prow, 2 );
203 
205  connect( le_protein_vbar20, SIGNAL( textChanged ( const QString& ) ),
206  SLOT ( value_changed( const QString& ) ) );
207  protein_info->addWidget( le_protein_vbar20, prow++, 3 );
208 
209  QLabel* lb_protein_temp = us_label(
210  tr( "Temperature <small>(" ) + DEGC + ")</small>:" );
211  protein_info->addWidget( lb_protein_temp, prow, 0 );
212 
213  le_protein_temp = us_lineedit( QString::number( temperature, 'f', 1 ) );
214 
215  if ( signal )
216  {
218  }
219  else
220  {
221  connect( le_protein_temp, SIGNAL( textChanged ( const QString& ) ),
222  SLOT ( temp_changed( const QString& ) ) );
223  }
224 
225  protein_info->addWidget( le_protein_temp, prow, 1 );
226 
227  QLabel* lb_protein_vbar = us_label(
228  tr( "VBar <small>(cm<sup>3</sup>/g at T " ) + DEGC + ")</small>:" );
229 
230  protein_info->addWidget( lb_protein_vbar, prow, 2 );
231 
232  le_protein_vbar = us_lineedit( "", 0, true );
233  protein_info->addWidget( le_protein_vbar, prow++, 3 );
234 
235  QLabel* lb_protein_residues = us_label( tr( "Residue count:" ) );
236  protein_info->addWidget( lb_protein_residues, prow, 0 );
237 
238  le_protein_residues = us_lineedit( "", 0, true );
239  protein_info->addWidget( le_protein_residues, prow, 1 );
240  main->addWidget( protein_widget, row, 0, 1, 3 );
241 
242  QLabel* lb_protein_e280 = us_label(
243  tr( "E280 <small>(OD/(mol*cm))</small>:" ) );
244  protein_info->addWidget( lb_protein_e280, prow, 2 );
245  le_protein_e280 = us_lineedit( "", 0, true );
246  protein_info->addWidget( le_protein_e280, prow++, 3 );
247  QSpacerItem* spacer1 = new QSpacerItem( 20, 0 );
248  protein_info->addItem( spacer1, prow, 0, 1, 4 );
249  protein_info->setRowStretch( prow, 100 );
250 
251  protein_widget->setVisible( true );
252 
253  // Lower half -- DNA/RNA operations and data
254  dna_widget = new QWidget( this );
255  QGridLayout* dna_layout = new QGridLayout( dna_widget );
256  dna_layout->setSpacing ( 2 );
257  dna_layout->setContentsMargins( 2, 2, 2, 2 );
258 
259  QPalette p = US_GuiSettings::labelColor();
260 
261  QGroupBox* gb_double = new QGroupBox( tr( "Calculate MW" ) );
262  gb_double->setPalette( p );
263  QGridLayout* grid1 = new QGridLayout;
264  grid1->setSpacing ( 2 );
265  grid1->setContentsMargins( 2, 2, 2, 2 );
266 
267  QGridLayout* box1 = us_checkbox( tr( "Double Stranded" ), ck_stranded, true );
268  QGridLayout* box2 = us_checkbox( tr( "Complement Only" ), ck_mw_only );
269  grid1->addLayout( box1, 0, 0 );
270  grid1->addLayout( box2, 1, 0 );
271  connect( ck_stranded, SIGNAL( toggled ( bool ) ),
272  SLOT ( update_stranded( bool ) ) );
273  connect( ck_mw_only , SIGNAL( toggled ( bool ) ),
274  SLOT ( update_mw_only ( bool ) ) );
275 
276  QVBoxLayout* stretch1 = new QVBoxLayout;
277  stretch1->addStretch();
278  grid1->addLayout( stretch1, 2, 0 );
279 
280  gb_double->setLayout( grid1 );
281  dna_layout->addWidget( gb_double, 0, 0 );
282 
283 
284  QGroupBox* gb_three_prime = new QGroupBox( tr( "Three prime" ) );
285  gb_three_prime->setPalette( p );
286  QGridLayout* grid2 = new QGridLayout;
287  grid2->setSpacing ( 2 );
288  grid2->setContentsMargins( 2, 2, 2, 2 );
289 
290  QGridLayout* box3 = us_radiobutton( tr( "Hydroxyl" ), rb_3_hydroxyl, true );
291  QGridLayout* box4 = us_radiobutton( tr( "Phosphate" ), rb_3_phosphate );
292 
293  grid2->addLayout( box3, 0, 0 );
294  grid2->addLayout( box4, 0, 1 );
295  gb_three_prime->setLayout( grid2 );
296  connect( rb_3_hydroxyl, SIGNAL( toggled ( bool ) ),
297  SLOT ( update_nucleotide( bool ) ) );
298 
299  dna_layout->addWidget( gb_three_prime, 1, 0 );
300 
301  QGroupBox* gb_five_prime = new QGroupBox( tr( "Five prime" ) );
302  gb_five_prime->setPalette( p );
303  QGridLayout* grid3 = new QGridLayout;
304  grid3->setSpacing ( 2 );
305  grid3->setContentsMargins( 2, 2, 2, 2 );
306 
307  QGridLayout* box5 = us_radiobutton( tr( "Hydroxyl" ), rb_5_hydroxyl, true );
308  QGridLayout* box6 = us_radiobutton( tr( "Phosphate" ), rb_5_phosphate );
309 
310  grid3->addLayout( box5, 0, 0 );
311  grid3->addLayout( box6, 0, 1 );
312 
313  gb_five_prime->setLayout( grid3 );
314  connect( rb_5_hydroxyl, SIGNAL( toggled ( bool ) ),
315  SLOT ( update_nucleotide( bool ) ) );
316 
317  dna_layout->addWidget( gb_five_prime, 2, 0 );
318 
319  QGridLayout* ratios = new QGridLayout;
320 
321  QLabel* lb_ratios = us_banner( tr( "Counterion molar ratio/nucletide" ) );
322  ratios->addWidget( lb_ratios, 0, 0, 1, 3 );
323 
324  QLabel* lb_sodium = us_label( tr( "Sodium, Na+" ) );
325  ratios->addWidget( lb_sodium, 1, 0 );
326 
327  ct_sodium = us_counter( 2, 0.0, 1.0, 0.0 );
328  ct_sodium->setStep( 0.01 );
329  connect( ct_sodium, SIGNAL( valueChanged ( double ) ),
330  SLOT ( update_nucleotide( double ) ) );
331  ratios->addWidget( ct_sodium, 1, 1, 1, 2 );
332 
333  QLabel* lb_potassium = us_label( tr( "Potassium, K+" ) );
334  ratios->addWidget( lb_potassium, 2, 0 );
335 
336  ct_potassium = us_counter( 2, 0.0, 1.0, 0.0 );
337  ct_potassium->setStep( 0.01 );
338  connect( ct_potassium, SIGNAL( valueChanged ( double ) ),
339  SLOT ( update_nucleotide( double ) ) );
340  ratios->addWidget( ct_potassium, 2, 1, 1, 2 );
341 
342  QLabel* lb_lithium = us_label( tr( "Lithium, Li+" ) );
343  ratios->addWidget( lb_lithium, 3, 0 );
344 
345  ct_lithium = us_counter( 2, 0.0, 1.0, 0.0 );
346  ct_lithium->setStep( 0.01 );
347  connect( ct_lithium, SIGNAL( valueChanged ( double ) ),
348  SLOT ( update_nucleotide( double ) ) );
349  ratios->addWidget( ct_lithium, 3, 1, 1, 2 );
350 
351  QLabel* lb_magnesium = us_label( tr( "Magnesium, Mg+" ) );
352  ratios->addWidget( lb_magnesium, 4, 0 );
353 
354  ct_magnesium = us_counter( 2, 0.0, 1.0, 0.0 );
355  ct_magnesium->setStep( 0.01 );
356  connect( ct_magnesium, SIGNAL( valueChanged ( double ) ),
357  SLOT ( update_nucleotide( double ) ) );
358  ratios->addWidget( ct_magnesium, 4, 1, 1, 2 );
359 
360  QLabel* lb_calcium = us_label( tr( "Calcium, Ca+" ) );
361  ratios->addWidget( lb_calcium, 5, 0 );
362 
363  ct_calcium = us_counter( 2, 0.0, 1.0, 0.0 );
364  ct_calcium->setStep( 0.01 );
365  connect( ct_calcium, SIGNAL( valueChanged ( double ) ),
366  SLOT ( update_nucleotide( double ) ) );
367  ratios->addWidget( ct_calcium, 5, 1 );
368 
369  dna_layout->addLayout( ratios, 0, 1, 4, 2 );
370 
371  QGridLayout* nucle_data = new QGridLayout;
372  QLabel* lb_nucle_mw = us_label( tr( "MW <small>(Daltons)</small>:" ) );
373  nucle_data->addWidget( lb_nucle_mw, 0, 0 );
374 
375  le_nucle_mw = us_lineedit( "", -2, true );
376  nucle_data->addWidget( le_nucle_mw, 0, 1, 1, 3 );
377 
378  QLabel* lb_nucle_vbar = us_label(
379  tr( "VBar<small>(cm<sup>3</sup>/g)</small>:" ) );
380  nucle_data->addWidget( lb_nucle_vbar, 1, 0 );
381 
382  le_nucle_vbar = us_lineedit( "" );
383  connect( le_nucle_vbar, SIGNAL( textChanged ( const QString& ) ),
384  SLOT ( value_changed( const QString& ) ) );
385  nucle_data->addWidget( le_nucle_vbar, 1, 1, 1, 3 );
386 
387  dna_layout->addLayout( nucle_data, 4, 0, 2, 3 );
388  main->addWidget( dna_widget, row, 0, 2, 3 );
389  dna_widget->setVisible( false );
390 
391  // Lower half -- carbohydrate operations and data
392  carbs_widget = new QWidget( this );
393 
394  QGridLayout* carbs_info = new QGridLayout( carbs_widget );
395  carbs_info->setSpacing ( 2 );
396  carbs_info->setContentsMargins( 2, 2, 2, 2 );
397 
398  QLabel* lb_carbs_mw = us_label( tr( "MW <small>(Daltons)</small>:" ) );
399  carbs_info->addWidget( lb_carbs_mw, 0, 0 );
400 
401  le_carbs_mw = us_lineedit( "" );
402  carbs_info->addWidget( le_carbs_mw, 0, 1 );
403 
404  QLabel* lb_carbs_vbar = us_label(
405  tr( "VBar<small>(cm<sup>3</sup>/g)</small>:" ) );
406  carbs_info->addWidget( lb_carbs_vbar, 0, 2 );
407 
408  le_carbs_vbar = us_lineedit( "" );
409  carbs_info->addWidget( le_carbs_vbar, 0, 3 );
410 
411  QGridLayout* box7 = us_checkbox( tr( "Gradient-Forming" ),
412  ck_grad_form, false );
413  carbs_info->addLayout( box7, 1, 0, 1, 2 );
414 
415  main->addWidget( carbs_widget, row, 0, 2, 3 );
416  carbs_widget->setVisible( false );
417 
418  row += 4;
419 
420  // Standard Buttons
421  QBoxLayout* buttons = new QHBoxLayout;
422 
423  QPushButton* pb_reset = us_pushbutton( tr( "Reset" ) );
424  connect( pb_reset, SIGNAL( clicked() ), SLOT( reset() ) );
425  buttons->addWidget( pb_reset );
426 
427  QPushButton* pb_help = us_pushbutton( tr( "Help" ) );
428  connect( pb_help, SIGNAL( clicked() ), SLOT( help() ) );
429  buttons->addWidget( pb_help );
430 
431  QPushButton* pb_accept;
432 
433  if ( signal_wanted )
434  {
435  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
436  connect( pb_cancel, SIGNAL( clicked() ), SLOT( reject() ) );
437  buttons->addWidget( pb_cancel );
438 
439  pb_accept = us_pushbutton( tr( "Accept" ) );
440  }
441  else
442  pb_accept = us_pushbutton( tr( "Close" ) );
443 
444  connect( pb_accept, SIGNAL( clicked() ), SLOT( close() ) );
445  buttons->addWidget( pb_accept );
446 
447  main->addLayout( buttons, row, 0, 1, 3 );
448 
449  if ( guid.size() == 0 )
450  {
451  reset();
452  }
453 
454  else
455  {
456  int result;
458 
459  if ( disk_controls->db() )
460  {
461  US_Passwd pw;
462  US_DB2 db( pw.getPasswd() );
463 
464  if ( db.lastErrno() != US_DB2::OK )
465  {
466  QMessageBox::information( this,
467  tr( "Database Error" ),
468  tr( "The following error was returned:\n" ) + db.lastError() );
469  return;
470  }
471 
472  result = analyte.load( true, guid, &db );
473  }
474  else
475  result = analyte.load( false, guid );
476 
477  if ( result == US_DB2::OK )
478  populate();
479  else
480  {
481  QMessageBox::warning( this,
482  tr( "Analyte Missing" ),
483  tr( "No Analyte was found " )
484  + ( disk_controls->db()
485  ? tr( "in the database" )
486  : tr( "on local disk" ) )
487  + tr( ", with a GUID of\n" ) + guid );
488  }
489 
490  QString strVBar = QString::number( analyte.vbar20, 'f', 4 );
491  le_protein_vbar20->setText( strVBar );
492  le_nucle_vbar ->setText( strVBar );
493  le_carbs_vbar ->setText( strVBar );
494  le_carbs_mw ->setText( QString::number( (int) analyte.mw ) );
495  }
496 
497  list();
498 
499  switch ( analyte.type )
500  {
501  case US_Analyte::PROTEIN:
502  dna_widget ->setVisible( false );
503  carbs_widget ->setVisible( false );
504  protein_widget->setVisible( true );
505  resize( 0, 0 ); // Resize to minimum dimensions
506  break;
507 
508  case US_Analyte::DNA:
509  case US_Analyte::RNA:
511  protein_widget->setVisible( false );
512  carbs_widget ->setVisible( false );
513  dna_widget ->setVisible( true );
514  break;
515 
517  protein_widget->setVisible( false );
518  dna_widget ->setVisible( false );
519  carbs_widget ->setVisible( true );
520  resize( 0, 0 ); // Resize to minimum dimensions
521  break;
522  }
523 }
524 
526 {
527  emit use_db( db );
528  list();
529  qApp->processEvents();
530 }
531 
533 {
534  if ( ! discard_changes() ) return;
535 
536  analyte = US_Analyte(); // Set to default
537 
538  // Protein is default
539  if ( rb_rna ->isChecked() ) analyte.type = US_Analyte::RNA;
540  if ( rb_dna ->isChecked() ) analyte.type = US_Analyte::DNA;
541  if ( rb_carb ->isChecked() ) analyte.type = US_Analyte::CARBOHYDRATE;
542 
543  if ( ! rb_protein->isChecked() ) analyte.vbar20 = 0.55; // Empirical value
544 
546  populate();
547  if ( analyte.type == US_Analyte::RNA ||
549 }
550 
552 {
553  QStringList DB = US_Settings::defaultDB();
554 
555  if ( DB.size() < 5 )
556  {
557  QMessageBox::warning( this,
558  tr( "Attention" ),
559  tr( "There is no default database set." ) );
560  }
561  else
562  {
564 
565  if ( personID > 0 )
567  }
568 }
569 
570 void US_AnalyteGui::value_changed( const QString& )
571 {
572  // This only is activated by changes to vbar20
573  // (either protein or dna/rna) but vbar is not saved.
574  temp_changed( le_protein_temp->text() );
575 }
576 
578 {
580 
581  int row = -1;
582 
583  for ( int ii = 0; ii < descriptions.size(); ii++ )
584  {
585  if ( analyte.description == descriptions.at( ii ) )
586  {
587  row = ii;
588  break;
589  }
590  }
591 
592  pb_save->setEnabled( row < 0 );
593 
594  if ( row < 0 )
595  { // no match to description: clear GUID, de-select any list item
596  le_guid->clear();
597  lw_analytes->setCurrentRow( -1 );
598  }
599 
600  if ( row < 0 ) return;
601 
602  le_search->clear();
603  search( "" );
604 
605  lw_analytes->setCurrentRow( row );
606 }
607 
609 {
610  le_description->setText( analyte.description );
611  le_guid ->setText( analyte.analyteGUID );
612 qDebug() << "AnG: populate desc" << analyte.description;
613 qDebug() << "AnG: populate type" << analyte.type;
614 
616  {
617  rb_protein->setChecked( true );
618 
620  double temperature = le_protein_temp->text().toDouble();
621  US_Math2::calc_vbar( p, analyte.sequence, temperature );
622 
623  analyte.mw = ( analyte.mw == 0 ) ? p.mw : analyte.mw;
624  le_protein_mw ->setText( QString::number( (int) analyte.mw ) );
625  le_protein_vbar20 ->setText( QString::number( p.vbar20, 'f', 4 ) );
626  le_protein_vbar ->setText( QString::number( p.vbar , 'f', 4 ) );
627  le_protein_residues->setText( QString::number( p.residues ) );
628  le_protein_e280 ->setText( QString::number( p.e280 ) );
629 
630  // If spectrum is empty, set to 280.0/e280
631  QString spectrum_type = cmb_optics->currentText();
632 
633  if ( p.e280 != 0.0 )
634  {
635  if ( spectrum_type == tr( "Absorbance" ) )
636  {
637  if ( analyte.extinction.count() == 0 )
638  analyte.extinction [ 280.0 ] = p.e280;
639  }
640  else if ( spectrum_type == tr( "Interference" ) )
641  {
642  if ( analyte.refraction.count() == 0 )
643  analyte.refraction [ 280.0 ] = p.e280;
644  }
645  else
646  {
647  if ( analyte.fluorescence.count() == 0 )
648  analyte.fluorescence[ 280.0 ] = p.e280;
649  }
650  }
651  }
652 
653  else if ( analyte.type == US_Analyte::DNA ||
655  {
657  ? rb_rna->setChecked( true )
658  : rb_dna->setChecked( true );
659 
660  inReset = true;
661  ck_stranded->setChecked( analyte.doubleStranded );
662  ck_mw_only ->setChecked( analyte.complement );
663 
664  ( analyte._3prime ) ? rb_3_hydroxyl ->setChecked( true )
665  : rb_3_phosphate->setChecked( true );
666 
667  ( analyte._5prime ) ? rb_5_hydroxyl ->setChecked( true )
668  : rb_5_phosphate->setChecked( true );
669  ct_sodium ->setValue( analyte.sodium );
670  ct_potassium->setValue( analyte.potassium );
671  ct_lithium ->setValue( analyte.lithium );
672  ct_magnesium->setValue( analyte.magnesium );
673  ct_calcium ->setValue( analyte.calcium );
674 
675  le_nucle_vbar->setText( QString::number( analyte.vbar20, 'f', 4 ) );
676  inReset = false;
678  }
679 
680  else if ( analyte.type == US_Analyte::CARBOHYDRATE )
681  {
682 qDebug() << "AnG: populate grad_form" << analyte.grad_form;
683  rb_carb ->setChecked( true );
684  ck_grad_form->setChecked( analyte.grad_form );
685  }
686 }
687 
688 
690 {
691  if ( inReset ) return;
692 
693  if ( ! discard_changes() )
694  {
695  inReset = true;
696 
697  switch ( analyte.type )
698  {
699  case US_Analyte::PROTEIN:
700  rb_protein->setChecked( true );
701  break;
702  case US_Analyte::DNA:
703  rb_dna ->setChecked( true );
704  break;
705  case US_Analyte::RNA:
706  rb_rna ->setChecked( true );
707  break;
709  rb_carb ->setChecked( true );
710  break;
711  default:
712  rb_protein->setChecked( true );
713  break;
714  }
715 
716  inReset = false;
717  return;
718  }
719 
720  switch ( type )
721  {
722  case US_Analyte::PROTEIN:
723  dna_widget ->setVisible( false );
724  carbs_widget ->setVisible( false );
725  protein_widget->setVisible( true );
726  resize( 0, 0 ); // Resize to minimum dimensions
727  break;
728 
729  case US_Analyte::DNA:
730  case US_Analyte::RNA:
731  protein_widget->setVisible( false );
732  carbs_widget ->setVisible( false );
733  dna_widget ->setVisible( true );
734  break;
735 
737  protein_widget->setVisible( false );
738  dna_widget ->setVisible( false );
739  carbs_widget ->setVisible( true );
740  resize( 0, 0 ); // Resize to minimum dimensions
741  break;
742  }
743 
744  US_Analyte a; // Create a blank analyte
745  analyte = a;
748  reset();
749  list();
750 }
751 
753 {
754  bool changed = ! ( analyte == saved_analyte );
755 
756  if ( analyte.analyteGUID.size() != 36 || changed )
757  {
758  int response = QMessageBox::question( this,
759  tr( "Analyte Changed" ),
760  tr( "Are you sure?\n\n"
761  "The displayed analyte has changed.\n"
762  "You will not be able to easily reproduce this analyte.\n\n"
763  "Do you really want to continue without saving?" ),
764  QMessageBox::Yes | QMessageBox::No );
765 
766  if ( response == QMessageBox::No ) return;
767  }
768 
770  analyte.vbar20 = le_protein_vbar20->text().toDouble();
771 
772  // Give a warning if the vbar implies a negative buoyancy
773  if ( ( 1.0 - analyte.vbar20 * DENS_20W ) <= 0.0 )
774  {
775  QMessageBox::warning( this, tr( "Negative Buoyancy Implied" ),
776  tr( "The current vbar value implies a non-positive buoyancy.\n"
777  "This will have to be changed with any 2DSA operations.\n\n"
778  "Floating data is indicated there by negative sedimentation\n"
779  "coefficient values, rather than negative buoyancy." ) );
780  }
781 
782  // If a signal is not wanted, just close
783  if ( ! signal_wanted )
784  {
785  accept();
786  return;
787  }
788 
789  if ( data_ok() )
790  {
791  emit valueChanged( analyte );
792  accept();
793  }
794 
795  // Just return if data is not OK
796 }
797 
799 {
800  inReset = true;
801  lw_analytes->clear();
802 
803  analyte.analyteID.clear();
804 
805  le_investigator->setText( tr( "Not Selected" ) );
806 
807  if ( US_Settings::us_inv_ID() > 0 )
808  {
809  QString inv = QString::number( US_Settings::us_inv_ID() ) + ": " +
811 
812  le_investigator->setText( inv );
813  }
814 
815  le_search->clear();
816  le_search->setReadOnly( true );
817 
818  US_Analyte a;
819  analyte = a;
820 
821  if ( rb_protein->isChecked() ) analyte.type = US_Analyte::PROTEIN;
822  if ( rb_dna ->isChecked() ) analyte.type = US_Analyte::DNA;
823  if ( rb_rna ->isChecked() ) analyte.type = US_Analyte::RNA;
824  if ( rb_carb ->isChecked() ) analyte.type = US_Analyte::CARBOHYDRATE;
825 
827 
828  filenames .clear();
829  analyteIDs .clear();
830  GUIDs .clear();
831  descriptions.clear();
832 
833  le_guid ->clear();
834  le_description ->clear();
835  le_protein_mw ->clear();
836  le_protein_vbar20 ->clear();
837  le_protein_vbar ->clear();
838  ck_grad_form ->setChecked( false );
839 
840  if ( ! signal_wanted ) le_protein_temp->setText( "20.0" );
841 
842  le_protein_residues->clear();
843 
844  ct_sodium ->setValue( 0.0 );
845  ct_potassium ->setValue( 0.0 );
846  ct_lithium ->setValue( 0.0 );
847  ct_magnesium ->setValue( 0.0 );
848  ct_calcium ->setValue( 0.0 );
849 
850  ck_stranded ->setChecked( true );
851  ck_mw_only ->setChecked( false );
852 
853  rb_3_hydroxyl ->setChecked( true );
854  rb_5_hydroxyl ->setChecked( true );
855 
856  le_nucle_mw ->clear();
857  le_nucle_vbar ->clear();
858  le_carbs_mw ->clear();
859  le_carbs_vbar ->clear();
860 
861  pb_save ->setEnabled( false );
862  pb_more ->setEnabled( false );
863  pb_delete ->setEnabled( false );
864 
865  qApp->processEvents();
866  inReset = false;
867 }
868 
869 void US_AnalyteGui::temp_changed( const QString& text )
870 {
871  double temperature = text.toDouble();
872  double vbar20 = le_protein_vbar20->text().toDouble();
873  double vbar = vbar20 + 4.25e-4 * ( temperature - 20.0 );
874  le_protein_vbar->setText( QString::number( vbar, 'f', 4 ) );
875 }
876 
878 {
879  A = analyte.sequence.count( "a" );
880  C = analyte.sequence.count( "c" );
881  G = analyte.sequence.count( "g" );
882  T = analyte.sequence.count( "t" );
883  U = analyte.sequence.count( "u" );
884 }
885 
887 {
889  connect( edit, SIGNAL( sequenceChanged( QString ) ),
890  SLOT ( update_sequence( QString ) ) );
891  edit->exec();
892 
893 }
894 
896 {
897  seq = seq.toLower().remove( QRegExp( "[\\s0-9]" ) );
898  QString check = seq;
899 
900  if ( seq == analyte.sequence ) return;
901 
902  switch ( analyte.type )
903  {
904  case US_Analyte::PROTEIN:
905  seq.remove( QRegExp( "[^a-z\\+\\?\\@]" ) );
906  break;
907 
908  case US_Analyte::DNA:
909  seq.remove( QRegExp( "[^acgt]" ) );
910  break;
911 
912  case US_Analyte::RNA:
913  seq.remove( QRegExp( "[^acgu]" ) );
914  break;
915 
917  break;
918  }
919 
920  if ( check != seq )
921  {
922  int response = QMessageBox::question( this,
923  tr( "Attention" ),
924  tr( "There are invalid characters in the sequence!\n"
925  "Invalid characters will be removed\n"
926  "Do you want to continue?" ),
927  QMessageBox::Yes, QMessageBox::No );
928 
929  if ( response == QMessageBox::No ) return;
930  }
931 
932  // Reformat the sequence
933  const int gsize = 10;
934  const int lsize = 6;
935 
936  // Groups of gsize nucleotides
937  int segments = ( seq.size() + gsize - 1 ) / gsize;
938  int p = 0;
939  QString s;
940 
941  for ( int i = 0; i < segments; i++ )
942  {
943  QString t;
944 
945  if ( i % lsize == 0 )
946  s += t.sprintf( "%04i ", i * gsize + 1 );
947 
948  s += seq.mid( p, gsize );
949  p += gsize;
950 
951  if ( i % lsize == lsize - 1 )
952  s.append( "\n" );
953  else
954  s.append( " " );
955  }
956 
957  analyte.sequence = s;
958 
959  switch ( analyte.type )
960  {
961  case US_Analyte::PROTEIN:
962  {
964  double temperature = le_protein_temp->text().toDouble();
965  US_Math2::calc_vbar( p, analyte.sequence, temperature );
966 
967  le_protein_mw ->setText( QString::number( (int) p.mw ) );
968  le_protein_vbar20 ->setText( QString::number( p.vbar20, 'f', 4 ) );
969  le_protein_vbar ->setText( QString::number( p.vbar , 'f', 4 ) );
970  le_protein_residues->setText( QString::number( p.residues ) );
971  le_protein_e280 ->setText( QString::number( p.e280 ) );
972 
973  analyte.mw = p.mw;
974  analyte.vbar20 = p.vbar20;
975 
976  // If spectrum is empty, set to 280.0/e280
977  QString spectrum_type = cmb_optics->currentText();
978 
979  if ( spectrum_type == tr( "Absorbance" ) )
980  {
981  if ( analyte.extinction.count() == 0 )
982  analyte.extinction [ 280.0 ] = p.e280;
983  }
984  else if ( spectrum_type == tr( "Interference" ) )
985  {
986  if ( analyte.refraction.count() == 0 )
987  analyte.refraction [ 280.0 ] = p.e280;
988  }
989  else
990  {
991  if ( analyte.fluorescence.count() == 0 )
992  analyte.fluorescence[ 280.0 ] = p.e280;
993  }
994  break;
995  }
996 
997  case US_Analyte::DNA:
998  case US_Analyte::RNA:
1000  break;
1001 
1003  le_carbs_mw ->setText( QString::number( (int) analyte.mw ) );
1004  le_carbs_vbar->setText( QString::number( analyte.vbar20, 'f', 4 ) );
1005  break;
1006  }
1007 
1008  pb_save->setEnabled( true );
1009  pb_more->setEnabled( true );
1010 }
1011 
1013 {
1014  if ( inReset ) return;
1015  if ( checked ) ck_mw_only->setChecked( false );
1017 }
1018 
1019 void US_AnalyteGui::update_mw_only( bool checked )
1020 {
1021  if ( inReset ) return;
1022  if ( checked ) ck_stranded->setChecked( false );
1024 }
1025 
1026 void US_AnalyteGui::update_nucleotide( bool /* value */ )
1027 {
1028  if ( inReset ) return;
1030 }
1031 
1032 void US_AnalyteGui::update_nucleotide( double /* value */ )
1033 {
1034  if ( inReset ) return;
1036 }
1037 
1039 {
1040  if ( inReset ) return;
1041 
1042  parse_dna();
1043 
1044  bool isDNA = rb_dna ->isChecked();
1045  analyte.doubleStranded = ck_stranded ->isChecked();
1046  analyte.complement = ck_mw_only ->isChecked();
1047  analyte._3prime = rb_3_hydroxyl->isChecked();
1048  analyte._5prime = rb_5_hydroxyl->isChecked();
1049 
1050  analyte.sodium = ct_sodium ->value();
1051  analyte.potassium = ct_potassium->value();
1052  analyte.lithium = ct_lithium ->value();
1053  analyte.magnesium = ct_magnesium->value();
1054  analyte.calcium = ct_calcium ->value();
1055 
1056  double MW = 0;
1057  uint total = A + G + C + T + U;
1058 
1059  if ( analyte.doubleStranded ) total *= 2;
1060 
1061  const double mw_A = 313.209;
1062  const double mw_C = 289.184;
1063  const double mw_G = 329.208;
1064  const double mw_T = 304.196;
1065  const double mw_U = 274.170;
1066 
1067  if ( isDNA )
1068  {
1069  if ( analyte.doubleStranded )
1070  {
1071  MW += A * mw_A;
1072  MW += G * mw_G;
1073  MW += C * mw_C;
1074  MW += T * mw_T;
1075  MW += A * mw_T;
1076  MW += G * mw_C;
1077  MW += C * mw_G;
1078  MW += T * mw_A;
1079  }
1080 
1081  if ( analyte.complement )
1082  {
1083  MW += A * mw_T;
1084  MW += G * mw_C;
1085  MW += C * mw_G;
1086  MW += T * mw_A;
1087  }
1088 
1090  {
1091  MW += A * mw_A;
1092  MW += G * mw_G;
1093  MW += C * mw_C;
1094  MW += T * mw_T;
1095  }
1096  }
1097  else /* RNA */
1098  {
1099  if ( analyte.doubleStranded )
1100  {
1101  MW += A * ( mw_A + 15.999 );
1102  MW += G * ( mw_G + 15.999 );
1103  MW += C * ( mw_C + 15.999 );
1104  MW += U * ( mw_U + 15.999 );
1105  MW += A * ( mw_U + 15.999 );
1106  MW += G * ( mw_C + 15.999 );
1107  MW += C * ( mw_G + 15.999 );
1108  MW += U * ( mw_A + 15.999 );
1109  }
1110 
1111  if ( analyte.complement )
1112  {
1113  MW += A * ( mw_U + 15.999 );
1114  MW += G * ( mw_C + 15.999 );
1115  MW += C * ( mw_G + 15.999 );
1116  MW += U * ( mw_A + 15.999 );
1117  }
1118 
1120  {
1121  MW += A * ( mw_A + 15.999 );
1122  MW += G * ( mw_G + 15.999 );
1123  MW += C * ( mw_C + 15.999 );
1124  MW += U * ( mw_U + 15.999 );
1125  }
1126  }
1127 
1128  MW += analyte.sodium * total * 22.99;
1129  MW += analyte.potassium * total * 39.1;
1130  MW += analyte.lithium * total * 6.94;
1131  MW += analyte.magnesium * total * 24.305;
1132  MW += analyte.calcium * total * 40.08;
1133 
1134  if ( analyte._3prime )
1135  {
1136  MW += 17.01;
1137  if ( analyte.doubleStranded ) MW += 17.01;
1138  }
1139  else // we have phosphate
1140  {
1141  MW += 94.87;
1142  if ( analyte.doubleStranded ) MW += 94.87;
1143  }
1144 
1145  if ( analyte._5prime )
1146  {
1147  MW -= 77.96;
1148  if ( analyte.doubleStranded ) MW -= 77.96;
1149  }
1150 
1151  if ( analyte.sequence.isEmpty() ) MW = 0;
1152 
1153  QString s;
1154 
1155  if ( analyte.doubleStranded )
1156  {
1157  s.sprintf(" %2.5e kD (%d A, %d G, %d C, %d U, %d T, %d bp)",
1158  MW / 1000.0, A, G, C, U, T, total / 2);
1159  }
1160  else
1161  {
1162  s.sprintf(" %2.5e kD (%d A, %d G, %d C, %d U, %d T, %d bases)",
1163  MW / 1000.0, A, G, C, U, T, total );
1164  }
1165 
1166  le_nucle_mw->setText( s );
1167 
1168  if ( rb_dna->isChecked() )
1169  {
1170 
1171  if ( MW > 0 && T == 0 && U > 0)
1172  QMessageBox::question( this,
1173  tr( "Attention:" ),
1174  tr( "Are you sure?\n"
1175  "There don't appear to be any thymine residues present,\n"
1176  "instead there are uracil residues in this sequence." ) );
1177  }
1178  else // DNA */
1179  {
1180  if ( MW > 0 && T > 0 && U == 0 )
1181  QMessageBox::question( this,
1182  tr( "Attention:" ),
1183  tr( "Are you sure?\n"
1184  "There don't appear to be any uracil residues present,\n"
1185  "instead there are thymine residues in this sequence." ) );
1186  }
1187 }
1188 
1190 {
1192  double temperature;
1193 
1194  if ( analyte.type == US_Analyte::PROTEIN )
1195  {
1196  temperature = le_protein_temp->text().toDouble();
1197  US_Math2::calc_vbar( p, analyte.sequence, temperature );
1198  }
1199  else
1200  temperature = 20.0;
1201 
1202 
1203  QString s;
1204  QString s1 =
1205  "***************************************************\n" +
1206  tr( "* Analyte Analysis Results *\n" ) +
1207  "***************************************************\n\n\n" +
1208  tr( "Report for: " ) + analyte.description + "\n\n" ;
1209 
1210 
1211  if ( analyte.type == US_Analyte::PROTEIN )
1212  {
1213  s1 += tr( "Number of Residues: " ) + s.sprintf( "%i", p.residues ) + " AA\n";
1214  s1 += tr( "Molecular Weight: " ) + s.sprintf( "%i", (int)p.mw ) +
1215  tr( " Dalton\n" ) +
1216 
1217  tr( "V-bar at 20.0 " ) + DEGC + ": " +
1218  QString::number( p.vbar20, 'f', 4 ) + tr( " cm^3/g\n" );
1219 
1220  // Write overridden value if applicable
1221  bool override = false;
1222  double vbar20 = le_protein_vbar20->text().toDouble();
1223 
1224  if ( fabs( vbar20 - p.vbar20 ) > 1e-4 ) override = true;
1225 
1226  if ( override )
1227  s1 += tr( "V-bar at 20.0 " ) + DEGC + ": " +
1228  QString::number( vbar20, 'f', 4 ) +
1229  tr( " cm^3/g (override)\n" );
1230 
1231  if ( temperature != 20.0 )
1232  {
1233  s1+= tr( "V-bar at " ) + QString::number( temperature, 'f', 1 ) + " " +
1234  DEGC + ": " + QString::number( p.vbar, 'f', 4 ) +
1235  tr( " cm^3/g\n" );
1236 
1237  if ( override )
1238  s1+= tr( "V-bar at " ) + QString::number( temperature, 'f', 1 ) + " " +
1239  DEGC + ": " + le_protein_vbar->text() +
1240  tr( " cm^3/g (override)\n" );
1241  }
1242  }
1243  else
1244  {
1245  s1 += tr( "Molecular Weight: " ) + le_nucle_mw->text() + "\n" +
1246 
1247  tr( "V-bar: " ) + le_nucle_vbar->text() + tr( " cm^3/g\n" );
1248 
1249  }
1250 
1251  s1 += tr( "\nExtinction coefficients for the denatured analyte:\n"
1252  " Wavelength (nm) OD/(mol cm)\n" );
1253 
1254  QList< double > keys = analyte.extinction.keys();
1255  qSort( keys );
1256 
1257  for ( int i = 0; i < keys.size(); i++ )
1258  {
1259  QString s;
1260  s.sprintf( " %4.1f %9.4f\n",
1261  keys[ i ], analyte.extinction[ keys[ i ] ] );
1262  s1 += s;
1263  }
1264 
1265  s1 += tr( "\nRefraction coefficients for the analyte:\n"
1266  " Wavelength (nm) OD/(mol cm)\n" );
1267 
1268  keys = analyte.refraction.keys();
1269  qSort( keys );
1270 
1271  for ( int i = 0; i < keys.size(); i++ )
1272  {
1273  QString s;
1274  s.sprintf( " %4.1f %9.4f\n",
1275  keys[ i ], analyte.refraction[ keys[ i ] ] );
1276  s1 += s;
1277  }
1278 
1279  s1 += tr( "\nFluorescence coefficients for the analyte:\n"
1280  " Wavelength (nm) OD/(mol cm)\n" );
1281 
1282  keys = analyte.fluorescence.keys();
1283  qSort( keys );
1284 
1285  for ( int i = 0; i < keys.size(); i++ )
1286  {
1287  QString s;
1288  s.sprintf( " %4.1f %9.4f\n",
1289  keys[ i ], analyte.fluorescence[ keys[ i ] ] );
1290  s1 += s;
1291  }
1292 
1293  s1 += tr( "\nComposition: \n\n" );
1294 
1295  if ( analyte.type == US_Analyte::PROTEIN )
1296  {
1297 
1298  s1 += tr( "Alanine: " ) + s.sprintf( "%3i", p.a ) + " ";
1299  s1 += tr( "Arginine: " ) + s.sprintf( "%3i", p.r ) + "\n";
1300 
1301  s1 += tr( "Asparagine: " ) + s.sprintf( "%3i", p.n ) + " ";
1302  s1 += tr( "Aspartate: " ) + s.sprintf( "%3i", p.d ) + "\n";
1303 
1304  s1 += tr( "Asparagine or \n" ) +
1305  tr( "Aspartate: " ) + s.sprintf( "%3i", p.b ) + "\n";
1306 
1307  s1 += tr( "Cysteine: " ) + s.sprintf( "%3i", p.c ) + " ";
1308  s1 += tr( "Glutamate: " ) + s.sprintf( "%3i", p.e ) + "\n";
1309 
1310  s1 += tr( "Glutamine: " ) + s.sprintf( "%3i", p.q ) + " ";
1311  s1 += tr( "Glycine: " ) + s.sprintf( "%3i", p.g ) + "\n";
1312 
1313  s1 += tr( "Glutamine or \n" ) +
1314  tr( "Glutamate: " ) + s.sprintf( "%3i", p.z ) + "\n";
1315 
1316  s1 += tr( "Histidine: " ) + s.sprintf( "%3i", p.h ) + " ";
1317  s1 += tr( "Isoleucine: " ) + s.sprintf( "%3i", p.i ) + "\n";
1318 
1319  s1 += tr( "Leucine: " ) + s.sprintf( "%3i", p.l ) + " ";
1320  s1 += tr( "Lysine: " ) + s.sprintf( "%3i", p.k ) + "\n";
1321 
1322  s1 += tr( "Methionine: " ) + s.sprintf( "%3i", p.m ) + " ";
1323  s1 += tr( "Phenylalanine: " ) + s.sprintf( "%3i", p.f ) + "\n";
1324 
1325  s1 += tr( "Proline: " ) + s.sprintf( "%3i", p.p ) + " ";
1326  s1 += tr( "Serine: " ) + s.sprintf( "%3i", p.s ) + "\n";
1327 
1328  s1 += tr( "Threonine: " ) + s.sprintf( "%3i", p.t ) + " ";
1329  s1 += tr( "Tryptophan: " ) + s.sprintf( "%3i", p.w ) + "\n";
1330 
1331  s1 += tr( "Tyrosine: " ) + s.sprintf( "%3i", p.y ) + " ";
1332  s1 += tr( "Valine: " ) + s.sprintf( "%3i", p.v ) + "\n";
1333 
1334  s1 += tr( "Unknown: " ) + s.sprintf( "%3i", p.x ) + " ";
1335  s1 += tr( "Hao: " ) + s.sprintf( "%3i", p.j ) + "\n";
1336 
1337  s1 += tr( "Delta-linked Ornithine: " ) + QString::number( p.o ) + "\n";
1338  }
1339  else
1340  {
1341  int a = analyte.sequence.count( "a" );
1342  int c = analyte.sequence.count( "c" );
1343  int g = analyte.sequence.count( "g" );
1344  int t = analyte.sequence.count( "t" );
1345  int u = analyte.sequence.count( "u" );
1346 
1347  s1 += tr( "Adenine: " ) + s.sprintf( "%3i", a ) + " ";
1348  s1 += tr( "Cytosine: " ) + s.sprintf( "%3i", c ) + "\n";
1349 
1350  s1 += tr( "Guanine: " ) + s.sprintf( "%3i", g ) + " ";
1351 
1352  if ( analyte.type == US_Analyte::DNA )
1353  s1 += tr( "Thymine: " ) + s.sprintf( "%3i", t ) + "\n";
1354 
1355  else if ( analyte.type == US_Analyte::RNA )
1356  s1 += tr( "Uracil: " ) + s.sprintf( "%3i", u ) + "\n";
1357  }
1358 
1359  US_EditorGui* dialog = new US_EditorGui();
1360  QFont font = QFont( "monospace", US_GuiSettings::fontSize() );
1361  dialog->editor->e->setFont( font );
1362  dialog->editor->e->setText( s1 );
1363 
1364  QFontMetrics fm( font );
1365 
1366  dialog->resize( fm.width( 'W' ) * 80, fm.height() * 20 );
1367 
1368  dialog->exec();
1369 }
1370 
1371 void US_AnalyteGui::search( const QString& text )
1372 {
1373  lw_analytes->clear();
1374  info.clear();
1375  int crow = -1;
1376 
1377  for ( int i = 0; i < descriptions.size(); i++ )
1378  {
1379  if ( descriptions[ i ].contains(
1380  QRegExp( ".*" + text + ".*", Qt::CaseInsensitive ) ) )
1381  {
1382  AnalyteInfo ai;
1383  ai.description = descriptions[ i ];
1384  ai.guid = GUIDs [ i ];
1385  ai.filename = filenames [ i ];
1386  ai.index = i;
1387  info << ai;
1388 
1389  lw_analytes->addItem(
1390  new QListWidgetItem( descriptions[ i ], lw_analytes ) );
1391 
1392  if ( ai.description == analyte.description )
1393  crow = i;
1394  }
1395  }
1396 
1397  if ( crow >= 0 )
1398  lw_analytes->setCurrentRow( crow );
1399 }
1400 
1402 {
1403  reset();
1404 
1405  US_Investigator* inv_dialog = new US_Investigator( true );
1406 
1407  connect( inv_dialog,
1408  SIGNAL( investigator_accepted( int ) ),
1409  SLOT ( assign_investigator ( int ) ) );
1410 
1411  inv_dialog->exec();
1412 }
1413 
1415 {
1416  personID = invID;
1417 
1418  QString number = ( personID > 0 )
1419  ? QString::number( invID ) + ": "
1420  : "";
1421 
1422  le_investigator->setText( number + US_Settings::us_inv_name() );
1423 
1424  lw_analytes->clear();
1425  le_search ->clear();
1426  le_search ->setEnabled( false );
1427  pb_save ->setEnabled ( false );
1428  pb_delete ->setEnabled ( false );
1429 }
1430 
1432 {
1433  QString spectrum_type = cmb_optics->currentText();
1434  QString strExtinc = tr( "Extinction:" );
1435  bool changed = false;
1436  bool is_prot = rb_protein->isChecked();
1437  double e280val = le_protein_e280->text().toDouble();
1438  US_Table* dialog;
1439 
1440  if ( spectrum_type == tr( "Absorbance" ) )
1441  {
1442  if ( is_prot && analyte.extinction.count() == 0 )
1443  analyte.extinction[ 280.0 ] = e280val;
1444 
1445  dialog = new US_Table( analyte.extinction, strExtinc, changed );
1446  }
1447  else if ( spectrum_type == tr( "Interference" ) )
1448  {
1449  if ( is_prot && analyte.refraction.count() == 0 )
1450  analyte.refraction[ 280.0 ] = e280val;
1451 
1452  dialog = new US_Table( analyte.refraction, strExtinc, changed );
1453  }
1454  else
1455  {
1456  if ( is_prot && analyte.fluorescence.count() == 0 )
1457  analyte.fluorescence[ 280.0 ] = e280val;
1458 
1459  dialog = new US_Table( analyte.fluorescence, strExtinc, changed );
1460  }
1461 
1462  dialog->setWindowTitle( tr( "Manage %1 Values" ).arg( spectrum_type ) );
1463 
1464  dialog->exec();
1465 }
1466 
1467 void US_AnalyteGui::connect_error( const QString& error )
1468 {
1469  QMessageBox::warning( this, tr( "Connection Problem" ),
1470  tr( "Could not connect to database\n" ) + error );
1471 }
1472 
1474 {
1475  if ( disk_controls->db() )
1476  list_from_db();
1477  else
1478  list_from_disk();
1479 
1480  le_search->setEnabled( true );
1481  le_search->setReadOnly( false );
1482 }
1483 
1485 {
1486  if ( personID < 0 )
1487  {
1488  QMessageBox::information( this,
1489  tr( "Investigator not set" ),
1490  tr( "Please select an investigator first." ) );
1491  return;
1492  }
1493 
1494  US_Passwd pw;
1495  US_DB2 db( pw.getPasswd() );
1496 
1497  if ( db.lastErrno() != US_DB2::OK )
1498  {
1499  connect_error( db.lastError() );
1500  return;
1501  }
1502 
1503  QStringList q( "get_analyte_desc" );
1504  q << QString::number( personID );
1505 
1506  db.query( q );
1507 
1508  if ( db.lastErrno() != US_DB2::OK )
1509  {
1510  QMessageBox::information( this,
1511  tr( "Database Error" ),
1512  tr( "The following error was returned:\n" ) + db.lastError() );
1513  return;
1514  }
1515 
1516  descriptions.clear();
1517  analyteIDs .clear();
1518  filenames .clear();
1519  GUIDs .clear();
1520 
1521  while ( db.next() )
1522  {
1523  QString a_type = db.value( 2 ).toString();
1525 
1526 
1527  if ( a_type == "Protein" ) current = US_Analyte::PROTEIN;
1528  else if ( a_type == "RNA" ) current = US_Analyte::RNA;
1529  else if ( a_type == "DNA" ) current = US_Analyte::DNA;
1530  else if ( a_type == "Other" ) current = US_Analyte::CARBOHYDRATE;
1531 
1532  if ( current != analyte.type ) continue;
1533 
1534  analyteIDs << db.value( 0 ).toString();
1535  descriptions << db.value( 1 ).toString();
1536  filenames << "";
1537  GUIDs << "";
1538  }
1539 
1540  search();
1541 }
1542 
1544 {
1545  QString path;
1546  if ( ! US_Analyte::analyte_path( path ) ) return;
1547 
1548  filenames .clear();
1549  descriptions.clear();
1550  GUIDs .clear();
1551 
1552  QDir f( path );
1553  QStringList filter( "A*.xml" );
1554  QStringList f_names = f.entryList( filter, QDir::Files, QDir::Name );
1555 
1556  QString type = "*Unknown*";
1557  if ( rb_protein->isChecked() ) type = "PROTEIN";
1558  else if ( rb_dna ->isChecked() ) type = "DNA";
1559  else if ( rb_rna ->isChecked() ) type = "RNA";
1560  else if ( rb_carb ->isChecked() ) type = "CARBOHYDRATE";
1561 
1562  QFile a_file;
1563 
1564  for ( int i = 0; i < f_names.size(); i++ )
1565  {
1566  a_file.setFileName( path + "/" + f_names[ i ] );
1567 
1568  if ( ! a_file.open( QIODevice::ReadOnly | QIODevice::Text) ) continue;
1569 
1570  QXmlStreamReader xml( &a_file );
1571 
1572  while ( ! xml.atEnd() )
1573  {
1574  xml.readNext();
1575 
1576  if ( xml.isStartElement() )
1577  {
1578  if ( xml.name() == "analyte" )
1579  {
1580  QXmlStreamAttributes a = xml.attributes();
1581 
1582  if ( a.value( "type" ).toString() == type )
1583  {
1584  descriptions << a.value( "description" ).toString();
1585  GUIDs << a.value( "analyteGUID" ).toString();
1586  filenames << path + "/" + f_names[ i ];
1587  }
1588  break;
1589  }
1590  }
1591  }
1592 
1593  a_file.close();
1594  }
1595 
1596  search();
1597 }
1598 
1600 {
1601  if ( db.lastErrno() == 0 ) return true;
1602 
1603  QMessageBox::information( this,
1604  tr( "Database Error" ),
1605  tr( "The following error was returned:\n" ) + db.lastError() );
1606 
1607  return false;
1608 }
1609 
1611 {
1612  // Check to see if a sequence is entered
1613  if ( analyte.sequence.isEmpty() )
1614  {
1615  QMessageBox question( QMessageBox::Question,
1616  tr( "Attention" ),
1617  tr( "There is no sequence defined.\n\n"
1618  "Continue?" ),
1619  QMessageBox::No,
1620  this );
1621 
1622  question.addButton( tr( "Continue" ), QMessageBox::YesRole );
1623 
1624  if ( question.exec() == QMessageBox::No )
1625  return false;
1626  }
1627 
1628  analyte.description = le_description->text().remove( '|' );
1629 
1630  if ( analyte.description.isEmpty() )
1631  {
1632  QMessageBox question( QMessageBox::Question,
1633  tr( "Attention" ),
1634  tr( "There is no description for this analyte.\n\n"
1635  "Continue?" ),
1636  QMessageBox::No,
1637  this );
1638 
1639  question.addButton( tr( "Continue" ), QMessageBox::YesRole );
1640 
1641  if ( question.exec() == QMessageBox::No )
1642  return false;
1643 
1644  }
1645 
1646  double vbar = le_protein_vbar->text().toDouble();
1647 
1648  if ( analyte.type == US_Analyte::PROTEIN && ( vbar <= 0.0 || vbar > 2.0 ) )
1649  {
1650  QMessageBox::information( this,
1651  tr( "Attention" ),
1652  tr( "The vbar entry (%1) is not a reasonable value." )
1653  .arg( vbar ) );
1654  return false;
1655  }
1656 
1657  double mwvl = le_protein_mw->text().toDouble();
1658  if ( analyte.type == US_Analyte::DNA ||
1660  mwvl = le_nucle_mw->text().section( " ", 1, 1 ).toDouble();
1661  else if ( analyte.type == US_Analyte::CARBOHYDRATE )
1662  mwvl = le_carbs_mw->text().toDouble();
1663 
1664  if ( mwvl <= 0.0 )
1665  {
1666  QMessageBox::information( this,
1667  tr( "Attention" ),
1668  tr( "The Molecular Weight entry (%1) is not a reasonable value." )
1669  .arg( mwvl ) );
1670  return false;
1671  }
1672 
1673  return true;
1674 }
1675 
1676 int US_AnalyteGui::status_query( const QStringList& q )
1677 {
1678  US_Passwd pw;
1679  US_DB2 db( pw.getPasswd() );
1680 
1681  if ( db.lastErrno() != US_DB2::OK )
1682  {
1683  connect_error( db.lastError() );
1684  return db.lastErrno();
1685  }
1686 
1687  db.statusQuery( q );
1688 
1689  int status = db.lastErrno();
1690 
1691  if ( status == US_DB2::ANALY_IN_USE ) return status;
1692 
1693  if ( database_ok( db ) ) return US_DB2::ERROR;
1694 
1695  if ( status != US_DB2::OK )
1696  {
1697  QMessageBox::information( this,
1698  tr( "Database Error" ),
1699  tr( "The following errro was returned:\n" ) + db.lastError() );
1700  return status;
1701  }
1702 
1703  return US_DB2::OK;
1704 }
1705 
1707 {
1708  // See if there are changes to discard
1709  if ( saved_analyte == analyte ) return true;
1710 
1711  int response = QMessageBox::question( this,
1712  tr( "Analyte Changed" ),
1713  tr( "The analyte has changed.\n"
1714  "Do you want to continue without saving?" ),
1715  QMessageBox::Cancel, QMessageBox::Yes );
1716 
1717  if ( response == QMessageBox::Yes ) return true;
1718 
1719  return false;
1720 }
1721 
1722 void US_AnalyteGui::select_analyte( QListWidgetItem* /* item */ )
1723 {
1724  if ( ! discard_changes() ) return;
1725 
1726  analyte.extinction .clear();
1727  analyte.refraction .clear();
1728  analyte.fluorescence.clear();
1729 
1730  pb_save ->setEnabled( false );
1731  pb_delete->setEnabled( false );
1732  pb_more ->setEnabled( false );
1733 
1734  try
1735  {
1736  if ( disk_controls->db() )
1737  select_from_db();
1738  else
1739  select_from_disk();
1740  }
1741  catch ( int )
1742  {
1743  return;
1744  }
1745 
1746 qDebug() << "AnG: select_analyte desc" << analyte.description;
1747  populate();
1748  le_protein_vbar20->setText( QString::number( analyte.vbar20, 'f', 4 ) );
1749  le_nucle_vbar ->setText( QString::number( analyte.vbar20, 'f', 4 ) );
1750  le_carbs_vbar ->setText( QString::number( analyte.vbar20, 'f', 4 ) );
1753  //le_nucle_mw ->setText( QString::number( (int) analyte.mw ) );
1754  le_carbs_mw ->setText( QString::number( (int) analyte.mw ) );
1756 
1757  pb_delete->setEnabled( true );
1758  pb_save ->setEnabled( true );
1759  pb_more ->setEnabled( true );
1760 }
1761 
1763 {
1764  int index = lw_analytes->currentRow();
1765  if ( index < 0 ) throw -1;
1766  if ( info[ index ].filename.isEmpty() )
1767  {
1768  throw -1;
1769  }
1770 
1771  int result = analyte.load( false, info[ index ].guid );
1772 
1773  if ( result != US_DB2::OK )
1774  {
1775  QMessageBox::warning( this,
1776  tr( "Analyte Load Rrror" ),
1777  tr( "Load error when reading the disk:\n\n" ) + analyte.message );
1778  throw result;
1779  }
1780 
1781  analyte.message = tr( "disk" );
1782 
1783 }
1784 
1786 {
1787  int index = lw_analytes->currentRow();
1788  if ( index < 0 ) throw -1;
1789 
1790  US_Passwd pw;
1791  US_DB2 db( pw.getPasswd() );
1792 
1793  if ( db.lastErrno() != US_DB2::OK )
1794  {
1795  connect_error( db.lastError() );
1796  throw db.lastErrno();
1797  }
1798 
1799  // TODO: Fix analyte to fetch from analyteID
1800  // Here we are getting the guid when we know what the IS is, but
1801  // US_Analyte searches for the guid... Extra work for no benefit.
1802 
1803  QStringList q;
1804  int i = info[ index ].index;
1805  q << "get_analyte_info" << analyteIDs[ i ];
1806  db.query( q );
1807  db.next();
1808 
1809  QString guid = db.value( 0 ).toString();
1810 
1811  int result = analyte.load( true, guid, &db );
1812 
1813  if ( result != US_DB2::OK )
1814  {
1815  QMessageBox::warning( this,
1816  tr( "Analyte Load Error" ),
1817  tr( "Load error when reading the database:\n\n" ) + analyte.message );
1818  throw result;
1819  }
1820 
1821  analyte.message = tr( "database" );
1822 }
1823 
1825 {
1826  if ( analyte.analyteGUID.size() != 36 )
1828 
1829  if ( ! data_ok() ) return;
1830 
1831  le_guid->setText( analyte.analyteGUID );
1832 
1833  if ( analyte.type == US_Analyte::DNA ||
1835  {
1836  // Strip trailing items from the mw text box.
1837  QStringList mw = le_nucle_mw->text().split( " ", QString::SkipEmptyParts );
1838 
1839  if ( mw.empty() )
1840  {
1841  QMessageBox::warning( this,
1842  tr( "Analyte Error" ),
1843  tr( "Molecular weight is empty. Define a sequence." ) );
1844  return;
1845  }
1846 
1847  analyte.mw = mw[ 0 ].toDouble() * 1000.0;
1848  analyte.vbar20 = le_nucle_vbar->text().toDouble();
1849  }
1850 
1851  else if ( analyte.type == US_Analyte::CARBOHYDRATE )
1852  {
1853  analyte.mw = le_carbs_mw ->text().toDouble();
1854  analyte.vbar20 = le_carbs_vbar->text().toDouble();
1855  analyte.grad_form = ck_grad_form ->isChecked();
1856  }
1857 
1858  else
1859  {
1860  analyte.mw = le_protein_mw ->text().toDouble();
1861  analyte.vbar20 = le_protein_vbar20->text().toDouble();
1862  }
1863 
1864  verify_vbar();
1865 
1866  int result;
1867 
1868  if ( disk_controls->db() )
1869  {
1870  US_Passwd pw;
1871  US_DB2 db( pw.getPasswd() );
1872 
1873  if ( db.lastErrno() != US_DB2::OK )
1874  {
1875  QMessageBox::information( this,
1876  tr( "Database Error" ),
1877  tr( "The following error was returned:\n" ) + db.lastError() );
1878  return;
1879  }
1880 
1881  result = analyte.write( true, "", &db );
1882  }
1883  else
1884  {
1885  QString path;
1886  if ( ! US_Analyte::analyte_path( path ) ) return;
1887 
1888  QString filename = US_Analyte::get_filename( path, analyte.analyteGUID );
1889  result = analyte.write( false, filename );
1890  }
1891 
1893 
1894  if ( result == US_DB2::OK )
1895  QMessageBox::information( this,
1896  tr( "Save successful" ),
1897  tr( "The analyte has been successfully saved." ) );
1898  else
1899  QMessageBox::warning( this,
1900  tr( "Save Error" ),
1901  tr( "The analyte could not be saved.\n\n" ) + analyte.message );
1902 
1903  list();
1904 }
1905 
1907 {
1908  //TODO What if we select new and then want to delete that?
1909  if ( analyte.analyteGUID.size() != 36 ) return;
1910 
1911  if ( disk_controls->db() )
1912  delete_from_db();
1913  else
1914  delete_from_disk();
1915 
1916 
1917  list();
1918 }
1919 
1921 {
1922  // Find the file
1923  QString path;
1924  if ( ! US_Analyte::analyte_path( path ) ) return;
1925 
1926  QString fn = US_Analyte::get_filename( path, analyte.analyteGUID );
1927 
1928 
1930  {
1931  QMessageBox::warning( this,
1932  tr( "Not Deleted" ),
1933  tr( "The analyte could not be deleted,\n"
1934  "since it is in use in one or more solutions." ) );
1935  return;
1936  }
1937 
1938  // Delete it
1939  QFile file( fn );
1940  if ( file.exists() )
1941  {
1942  file.remove();
1943  reset();
1944 
1945  QMessageBox::information( this,
1946  tr( "Analyte Deleted" ),
1947  tr( "The analyte has been deleted from the disk." ) );
1948  }
1949 }
1950 
1952 {
1953  QStringList q;
1954  q << "delete_analyte" << analyte.analyteID;
1955 
1956  int status = status_query( q );
1957 
1958  if ( status == US_DB2::ANALY_IN_USE )
1959  {
1960  QMessageBox::warning( this,
1961  tr( "Analyte Not Deleted" ),
1962  tr( "The analyte could not be deleted,\n"
1963  "since it is in use in one or more solutions." ) );
1964  return;
1965  }
1966 
1967  if ( status != US_DB2::OK ) return;
1968 
1969  reset();
1970 
1971  QMessageBox::information( this,
1972  tr( "Analyte Deleted" ),
1973  tr( "The analyte has been deleted from the database." ) );
1974 }
1975 
1977 {
1978  if ( analyte.type == US_Analyte::PROTEIN )
1979  {
1981  double temperature = le_protein_temp->text().toDouble();
1982  US_Math2::calc_vbar( p, analyte.sequence, temperature );
1983 
1984  double mwval = le_protein_mw->text().toDouble();
1985 
1986  if ( p.mw == 0.0 )
1987  p.mw = mwval;
1988 
1989  else if ( mwval != 0.0 && qAbs( mwval - p.mw ) > 1.0 )
1990  {
1991  QString msg = tr(
1992  "There is a difference between<br/>"
1993  "the Molecular Weight value that you specified and<br/>"
1994  "the one calculated from the protein sequence.<br/> <br/>"
1995  "Do you wish to accept the specified value?<ul>"
1996  "<li><b>Yes</b> to use %1 (the specified);</li>"
1997  "<li><b>No </b> to use %2 (the calculated).</li></ul>" )
1998  .arg( mwval ).arg( p.mw );
1999 
2000  QMessageBox msgBox ( this );
2001  msgBox.setWindowTitle ( tr( "Analyte MW Difference" ) );
2002  msgBox.setTextFormat ( Qt::RichText );
2003  msgBox.setText ( msg );
2004  msgBox.addButton ( QMessageBox::No );
2005  msgBox.addButton ( QMessageBox::Yes );
2006  msgBox.setDefaultButton( QMessageBox::Yes );
2007 
2008  if ( msgBox.exec() == QMessageBox::No )
2009  mwval = p.mw;
2010  }
2011 
2012  else if ( mwval == 0.0 )
2013  mwval = p.mw;
2014 
2015  le_protein_mw->setText( QString::number( (int) mwval ) );
2016  analyte.mw = mwval;
2017  double pvbar = p.vbar20;
2018  double vbar20 = le_protein_vbar20->text().toDouble();
2019 
2020  if ( qAbs( vbar20 - pvbar ) > 1e-4 )
2021  {
2022  QString msg = tr(
2023  "There is a difference between<br/>"
2024  "the vbar20 value that you specified and<br/>"
2025  "the one calculated from the protein sequence.<br/> <br/>"
2026  "Do you wish to accept the specified value?<ul>"
2027  "<li><b>Yes</b> to use %1 (the specified);</li>"
2028  "<li><b>No </b> to use %2 (the calculated).</li></ul>" )
2029  .arg( vbar20 ).arg( pvbar );
2030 
2031  QMessageBox msgBox( this );
2032  msgBox.setWindowTitle( tr( "Analyte Vbar Difference" ) );
2033  msgBox.setTextFormat ( Qt::RichText );
2034  msgBox.setText ( msg );
2035  msgBox.addButton ( QMessageBox::No );
2036  msgBox.addButton ( QMessageBox::Yes );
2037  msgBox.setDefaultButton( QMessageBox::Yes );
2038 
2039  if ( msgBox.exec() == QMessageBox::No )
2040  vbar20 = pvbar;
2041 
2042  analyte.vbar20 = vbar20;
2043  le_protein_vbar20->setText( QString::number( vbar20 ) );
2044  }
2045  }
2046 }
2047 
2048 // Determine by GUID whether an analyte is in use in any solution on disk
2049 bool US_AnalyteGui::analyte_in_use( QString& analyteGUID )
2050 {
2051  bool in_use = false;
2052  QString soldir = US_Settings::dataDir() + "/solutions/";
2053  QStringList sfilt( "S*.xml" );
2054  QStringList snames = QDir( soldir )
2055  .entryList( sfilt, QDir::Files, QDir::Name );
2056 
2057  for ( int ii = 0; ii < snames.size(); ii++ )
2058  {
2059  QString sfname = soldir + snames.at( ii );
2060  QFile sfile( sfname );
2061 
2062  if ( ! sfile.open( QIODevice::ReadOnly | QIODevice::Text ) ) continue;
2063 
2064  QXmlStreamReader xml( &sfile );
2065 
2066  while ( ! xml.atEnd() )
2067  {
2068  xml.readNext();
2069 
2070  if ( xml.isStartElement() && xml.name() == "analyte" )
2071  {
2072  QXmlStreamAttributes atts = xml.attributes();
2073 
2074  if ( atts.value( "guid" ).toString() == analyteGUID )
2075  {
2076  in_use = true;
2077  break;
2078  }
2079  }
2080  }
2081 
2082  sfile.close();
2083 
2084  if ( in_use ) break;
2085  }
2086 
2087  return in_use;
2088 }
2089 
2090 
2091 /* Class US_SequenceEditor */
2092 US_SequenceEditor::US_SequenceEditor( const QString& sequence )
2093  : US_WidgetsDialog( 0, 0 )
2094 {
2095  setWindowTitle( tr( "Sequence Management" ) );
2096  setPalette( US_GuiSettings::frameColor() );
2097  setAttribute( Qt::WA_DeleteOnClose );
2098 
2099  QGridLayout* main = new QGridLayout( this );
2100  main->setSpacing ( 2 );
2101  main->setContentsMargins ( 2, 2, 2, 2 );
2102 
2103  edit = new US_Editor( US_Editor::LOAD, false );
2104  edit->e->setAcceptRichText( false );
2105  edit->e->setText( sequence );
2106  main->addWidget( edit, 0, 0, 5, 2 );
2107 
2108  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
2109  connect( pb_cancel, SIGNAL( clicked() ), SLOT( close() ) );
2110  main->addWidget( pb_cancel, 5, 0 );
2111 
2112  QPushButton* pb_accept = us_pushbutton( tr( "Accept" ) );
2113  connect( pb_accept, SIGNAL( clicked() ), SLOT( accept() ) );
2114  main->addWidget( pb_accept, 5, 1 );
2115 
2116  QFont font = QFont( "monospace", US_GuiSettings::fontSize() );
2117  edit->e->setFont( font );
2118 
2119  QFontMetrics fm( font );
2120  resize( fm.width( 'W' ) * 80, fm.height() * 20 );
2121 
2122 }
2123 
2125 {
2126  emit sequenceChanged( edit->e->toPlainText() );
2127  close();
2128 }
2129