1 /*
2 ----------------------------------------------------------------------------
3 "THE BEER-WARE LICENSE" (Revision 42):
4 <dkratzert@gmx.de> wrote this file. As long as you retain
5 this notice you can do whatever you want with this stuff. If we meet some day,
6 and you think this stuff is worth it, you can buy me a beer in return.
7 Daniel Kratzert
8 ----------------------------------------------------------------------------
9 */
10
11 #include <QtGui>
12 #include "dsreditwindow.h"
13 #include "dsrglwindow.h"
14 #include "deprecation.h"
15
16 /*
17 TODO:
18 - create a database handler class.
19 */
20
DSREditWindow(Molecule * mol,DSRMol * header,QString dsr_db_path,QString nametag,QVector<QStringList> fragmentsList,DSRGui * parent)21 DSREditWindow::DSREditWindow(Molecule *mol, DSRMol *header,
22 QString dsr_db_path, QString nametag,
23 QVector<QStringList> fragmentsList, DSRGui *parent)
24 : QWidget(parent)
25 {
26 RESTRAINT_CARDS << "SIMU" << "RIGU" << "DELU" << "SAME" << "FREE" << "DFIX" << "BUMP"
27 << "HFIX" << "BIND" << "SADI" << "CHIV" << "FLAT" << "DEFS" << "ISOR"
28 << "NCSY" << "DANG" << "EADP" << "EXYZ";
29 this->setParent(parent);
30 m_gui = parent;
31 m_mol = mol;
32 m_header = header;
33 mydsrdbpath = dsr_db_path;
34 m_frags = fragmentsList;
35 userdb = false;
36 m_nametag = nametag;
37 a = 0;
38 b = 0;
39 c = 0;
40 alpha = 0;
41 beta = 0;
42 gamma = 0;
43 oldatoms = new QString;
44 oldrestraints = new QString;
45 previous_atoms = new QStringList;
46 first_atnames = new QStringList;
47 setWindowFlags(Qt::Window);
48 setWindowTitle(QString("Edit Fragment"));
49 mainVLayout = new QVBoxLayout(this);
50 maingrid = new QGridLayout;
51 mainVLayout->addLayout(maingrid);
52 makeUnitCellEdit();
53 QLabel *cellabel = new QLabel("Unit Cell");
54 QLabel *namelabel = new QLabel("Name:");
55 nameEdit = new QLineEdit;
56 QLabel *restrlabel = new QLabel("Restraints:");
57 restrEdit = new QTextEdit();
58 QLabel *atomslabel = new QLabel("Atoms:");
59 atomsEdit = new QTextEdit;
60 atomsEdit->setAcceptRichText(false);
61 QLabel *resiclabel = new QLabel("Residue Class:");
62 resicledit = new QLineEdit;
63 resicledit->setMaximumWidth(getCharWidth(6));
64 resicledit->setMinimumWidth(getCharWidth(6));
65 use_selected = new QPushButton("Use selected Atoms");
66 use_selected->setMaximumWidth(getCharWidth(30));
67 myedgl = new DSRGlWindow(this, mol, *header, nametag);
68 updateButton = new QPushButton("Update Fragment");
69 addButton = new QPushButton("Add as New");
70 deleteButton = new QPushButton("Delete Fragment");
71 mailButton = new QPushButton("Mail Fragment home");
72 clearButton = new QPushButton("Clear All");
73 renameButton = new QPushButton("Enter Rename Mode");
74 accept_renameButton = new QPushButton("OK");
75 //accept_renameButton->setStyleSheet("QPushButton{background: rgb(124, 255, 117);}");
76 abort_renameButton = new QPushButton("Abort");
77 //abort_renameButton->setStyleSheet("QPushButton{background: rgb(255, 180, 180);}");
78 buttonlayout = new QGridLayout;
79 infoLabel = new QLabel;
80 // buttongrid row column spanrow spancolumn:
81 buttonlayout->addWidget(addButton, 0, 0);
82 buttonlayout->addWidget(updateButton, 0, 1);
83 buttonlayout->addWidget(deleteButton, 0, 2);
84 buttonlayout->addWidget(mailButton, 1, 0);
85 buttonlayout->addWidget(clearButton, 1, 1);
86 buttonlayout->addWidget(renameButton, 1, 2);
87 buttonlayout->addWidget(infoLabel, 2, 0, 2, 3);
88 //infoLabel->setStyleSheet("border: 1px solid lightgrey");
89 addButton->setDisabled(true);
90
91 // maingrid row column spanrow spancolumn:
92 maingrid->setRowStretch(1, 2);
93 maingrid->setRowStretch(3, 2);
94 maingrid->setRowStretch(4, 2);
95 maingrid->setColumnStretch(0, 0);
96 maingrid->setColumnStretch(1, 2);
97 maingrid->setColumnStretch(2, 0);
98 maingrid->setColumnStretch(3, 0);
99 maingrid->setColumnStretch(4, 2);
100 maingrid->addWidget(myedgl, 0, 4, 4, 3);
101 maingrid->addWidget(cellabel, 0, 0, 1, 1);
102 maingrid->addLayout(cellLayout, 0, 1, 1, 3);
103 maingrid->addWidget(namelabel, 1, 0, 1, 1);
104 maingrid->addWidget(nameEdit, 1, 1, 1, 1);
105 maingrid->addWidget(resiclabel, 1, 2, 1, 1);
106 maingrid->addWidget(resicledit, 1, 3, 1, 1);
107 maingrid->addWidget(use_selected,2, 1, 1, 2);
108 maingrid->addWidget(atomslabel, 3, 0, 1, 1);
109 maingrid->addWidget(atomsEdit, 3, 1, 1, 3);
110 maingrid->addWidget(restrlabel, 4, 0, 2, 1);
111 maingrid->addWidget(restrEdit, 4, 1, 2, 3);
112 maingrid->addLayout(buttonlayout,4, 4, 2, 3, Qt::AlignTop);
113
114 addButton->setToolTip("Add this fragment to the database.\n"
115 "Fragments from the database supplied by DSR will\n"
116 "always be stored as a new fragment in the user database.");
117 deleteButton->setToolTip("Deletes the currently opened fragment. \n"
118 "It can only delete fragments from the user database in dsr_usr_db.txt");
119 nameEdit->setToolTip("Insert any chemical name or sum formula here.");
120 resicledit->setToolTip("A residue class has to start with a letter \n"
121 "and can be up to four characters including numbers.");
122 use_selected->setToolTip("Uses the selected atoms in ShlelXle as new atoms\n"
123 "for the atom list below.");
124 atomsEdit->setToolTip("Insert atoms with following syntax:\n"
125 "Name Atomic Number x y z\n"
126 "C6 6 0.00460 2.39814 1.55732");
127 updateButton->setToolTip("Updates the fragment with the current changes.");
128 deleteButton->setToolTip("Erases the current fragment from the database.\n"
129 "(Only user-made fragments can be deleted)");
130 mailButton->setToolTip("Sends the current fragment to the author of DSR.\n"
131 "By sending the fragment to Daniel Kratzert, you\n"
132 "allow him to distribute it with the DSR program.");
133 renameButton->setToolTip("Enter rename mode to rename atoms.\n"
134 "Restraints will be updated according to the new atom names.\n"
135 "You can not add/delete atoms in rename mode.\n"
136 "Renaming is only available if no previous changes were made.");
137 clearButton->setToolTip("Clear all settings to define a new fragment.");
138 accept_renameButton->setToolTip("Accept the changes and return to fragment editor.");
139 abort_renameButton->setToolTip("Revert all changes and return to fragment editor.");
140 restrEdit->setToolTip("Insert any valid SHELXL restraint.");
141 use_selected->setStyleSheet("QPushButton {"
142 "font-weight: bold; "
143 "}");
144 infoLabel->setText("");
145 QFont labelfont("Arial bold", 12);
146 infoLabel->setFont(labelfont);
147 infoLabel->setWordWrap(true); // otherwise the widget gets elongated by long text.
148 myedgl->updateGL();
149 // Only do this if we selected a fragment in the list!
150 // Before, we have no information from the db header.
151 if (!nametag.isEmpty() && !header->cell.isEmpty()) {
152 setCellFromDB(header);
153 }
154 if (!nametag.isEmpty() && !header->comment.isEmpty()) {
155 setNamefromDB(header);
156 }
157 if (!nametag.isEmpty() && !header->residue.isEmpty()) {
158 setResidueFromDB(header);
159 }
160 if (!nametag.isEmpty() && !header->atoms.isEmpty()) {
161 setAtomsFromDB(header);
162 }
163 if (!nametag.isEmpty() && !header->restr.isEmpty()) {
164 setRestraintsFromDB(header);
165 }
166 if (!nametag.isEmpty() && !header->dbtype.isEmpty()) {
167 setDBTypeFromDB(header);
168 }
169 if (!userdb) {
170 deleteButton->setEnabled(false);
171 }
172 if (m_nametag.isEmpty()) {
173 updateButton->setDisabled(true);
174 }
175 connectSignalsAndSlots();
176 connect(deleteButton, SIGNAL(clicked()),
177 parent->mygl, SLOT(clear_molecule()));
178 }
179
~DSREditWindow()180 DSREditWindow::~DSREditWindow(){
181 }
182
connectSignalsAndSlots()183 void DSREditWindow::connectSignalsAndSlots()
184 //! handles all signals and slots
185 {
186 // check and set residue class from edit field:
187 connect(resicledit, SIGNAL(textChanged(QString)),
188 this, SLOT(checkResiClassInput(QString)));
189 // set fragname variable from edit field:
190 connect(nameEdit, SIGNAL(textChanged(QString)),
191 this, SLOT(setFragmentName(QString)));
192 // set cell from edit fields:
193 connect(cell_a, SIGNAL(textChanged(QString)),
194 this, SLOT(set_a_value(QString)));
195 connect(cell_b, SIGNAL(textChanged(QString)),
196 this, SLOT(set_b_value(QString)));
197 connect(cell_c, SIGNAL(textChanged(QString)),
198 this, SLOT(set_c_value(QString)));
199 connect(cell_alpha, SIGNAL(textChanged(QString)),
200 this, SLOT(set_alpha_value(QString)));
201 connect(cell_beta, SIGNAL(textChanged(QString)),
202 this, SLOT(set_beta_value(QString)));
203 connect(cell_gamma, SIGNAL(textChanged(QString)),
204 this, SLOT(set_gamma_value(QString)));
205 // set MyAtoms from atomsEdit field:
206 connect(atomsEdit, SIGNAL(textChanged()),
207 this, SLOT(setAtoms()));
208 connect(restrEdit, SIGNAL(textChanged()),
209 this, SLOT(setRestraints()));
210 // display an error message if there is any error in the
211 // format of atoms or restraints:
212 connect(this, SIGNAL(line_error(QString)),
213 this, SLOT(setInfoLabel(QString)));
214 connect(addButton, SIGNAL(clicked()),
215 this, SLOT(addFragment()));
216 connect(deleteButton, SIGNAL(clicked()),
217 this, SLOT(deleteCurrentFragment()));
218 connect(deleteButton, SIGNAL(clicked()),
219 this, SLOT(updateFraglist()));
220 connect(deleteButton, SIGNAL(clicked()), // the information in this window gets useless,
221 this, SLOT(close())); // thus it is closed.
222 connect(updateButton, SIGNAL(clicked()),
223 this, SLOT(updateFragment()));
224 connect(use_selected, SIGNAL(clicked()),
225 this, SLOT(setSelectedAtoms()));
226 connect(mailButton, SIGNAL(clicked()),
227 this, SLOT(mailHome()));
228 connect(renameButton, SIGNAL(clicked()),
229 this, SLOT(enterRenameMode()));
230 connect(accept_renameButton, SIGNAL(clicked()),
231 this, SLOT(leaveRenameMode()));
232 connect(clearButton, SIGNAL(clicked()),
233 this, SLOT(clearAll()));
234 }
235
236
minimumSizeHint() const237 QSize DSREditWindow::minimumSizeHint() const
238 {
239 return QSize(700, 700);
240 }
241
sizeHint() const242 QSize DSREditWindow::sizeHint() const
243 {
244 return QSize(900, 700);
245 }
246
247
clearAll()248 void DSREditWindow::clearAll(){
249 cell_a->clear();
250 cell_b->clear();
251 cell_c->clear();
252 cell_alpha->clear();
253 cell_beta->clear();
254 cell_gamma->clear();
255 nameEdit->clear();
256 resicledit->clear();
257 atomsEdit->clear();
258 restrEdit->clear();
259 restrEdit->append("Add at least one restraint here. (And delete this text)");
260 addButton->setDisabled(true); // Otherwise, it is possible to create a damaged fragment.
261 updateButton->setDisabled(true);
262 myedgl->clear_molecule();
263 }
264
enterRenameMode()265 void DSREditWindow::enterRenameMode(){
266 //! prepare window to rename atoms
267 first_atnames->clear();
268 foreach (QString line, atomsEdit->toPlainText().split(QRegExp("\n|\r\n|\r"))) {
269 first_atnames->append(line.split(' ').at(0));
270 }
271 addButton->hide();
272 updateButton->hide();
273 mailButton->hide();
274 restrEdit->setDisabled(true);
275 nameEdit->setDisabled(true);
276 resicledit->setDisabled(true);
277 cell_a->setDisabled(true);
278 cell_b->setDisabled(true);
279 cell_c->setDisabled(true);
280 cell_alpha->setDisabled(true);
281 cell_beta->setDisabled(true);
282 cell_gamma->setDisabled(true);
283 renameButton->hide();
284 deleteButton->hide();
285 use_selected->setDisabled(true);
286 buttonlayout->addWidget(accept_renameButton, 0, 0, 1, 2);
287 buttonlayout->addWidget(abort_renameButton, 1, 0, 1, 2);
288 accept_renameButton->show();
289 abort_renameButton->show();
290 atomsEdit->disconnect();
291 oldatoms->clear();
292 oldatoms->append(atomsEdit->toPlainText());
293 oldrestraints->clear();
294 oldrestraints->append(restrEdit->toPlainText());
295 connect(atomsEdit, SIGNAL(textChanged()),
296 this, SLOT(renameAtoms()));
297 connect(abort_renameButton, SIGNAL(clicked()),
298 this, SLOT(abortRenameMode()));
299 restrEdit->disconnect();
300 new_header = new DSRMol;
301 new_header->atoms.clear();
302 }
303
leaveRenameMode()304 void DSREditWindow::leaveRenameMode(){
305 //! go out of rename mode and rename the restraints
306 //rename_restraints()
307 renameButton->show();
308 deleteButton->show();
309 restrEdit->setEnabled(true);
310 nameEdit->setEnabled(true);
311 resicledit->setEnabled(true);
312 cell_a->setEnabled(true);
313 cell_b->setEnabled(true);
314 cell_c->setEnabled(true);
315 cell_alpha->setEnabled(true);
316 cell_beta->setEnabled(true);
317 cell_gamma->setEnabled(true);
318 use_selected->setEnabled(true);
319 mailButton->show();
320 updateButton->show();
321 addButton->show();
322 accept_renameButton->hide();
323 abort_renameButton->hide();
324 atomsEdit->disconnect();
325 restrEdit->disconnect();
326 // re-attach signal after rename mode
327 connect(atomsEdit, SIGNAL(textChanged()),
328 this, SLOT(setAtoms()));
329 connect(restrEdit, SIGNAL(textChanged()),
330 this, SLOT(setRestraints()));
331 setAtoms();
332 setRestraints();
333 }
334
abortRenameMode()335 void DSREditWindow::abortRenameMode(){
336 //! go out of rename mode and do nothing
337 //rename_restraints()
338 renameButton->show();
339 deleteButton->show();
340 restrEdit->setEnabled(true);
341 nameEdit->setEnabled(true);
342 resicledit->setEnabled(true);
343 cell_a->setEnabled(true);
344 cell_b->setEnabled(true);
345 cell_c->setEnabled(true);
346 cell_alpha->setEnabled(true);
347 cell_beta->setEnabled(true);
348 cell_gamma->setEnabled(true);
349 use_selected->setEnabled(true);
350 mailButton->show();
351 updateButton->show();
352 addButton->show();
353 accept_renameButton->hide();
354 abort_renameButton->hide();
355 atomsEdit->disconnect();
356 restrEdit->disconnect();
357 // re-attach signal after rename mode
358 connect(atomsEdit, SIGNAL(textChanged()),
359 this, SLOT(setAtoms()));
360 connect(restrEdit, SIGNAL(textChanged()),
361 this, SLOT(setRestraints()));
362 atomsEdit->setText(oldatoms->toLatin1());
363 restrEdit->setText(oldrestraints->toLatin1());
364 myedgl->display_fragment(*m_header);
365 }
366
updateFraglist()367 void DSREditWindow::updateFraglist(){
368 emit updated(m_nametag);
369 }
370
mailHome()371 void DSREditWindow::mailHome() {
372 //! mail the current fragment to dkratzert@gmx.de
373 //! Formating according to RFC 6068
374 //! Mac and Windows like to have different mailstrings
375 QString mailstring;
376 #if defined Q_WS_WIN32 || defined Q_OS_WIN
377 mailstring = "mailto:dkratzert@gmx.de?"
378 "subject=New%20fragment%20for%20DSR"
379 "&body=Dear%20Daniel,%0D%0A"
380 "please%20add%20this%20fragment%20to%20the%20DSR%20database:%0D%0A%0D%0A"
381 +QString("%1").arg(combineDataToNewFragment().join("%0D%0A"))
382 +"%0D%0A";
383 #else
384 mailstring = "mailto:dkratzert@gmx.de?"
385 "subject=New fragment for DSR"
386 "&body=Dear Daniel,\n"
387 "please add this fragment to the DSR database:\n\n"
388 +QString("%1").arg(combineDataToNewFragment().join("\n"))
389 +"\n";
390 #endif
391 QDesktopServices::openUrl(QUrl(mailstring, QUrl::TolerantMode));
392 }
393
addFragment()394 void DSREditWindow::addFragment() {
395 //! combines new fragment and write db to the harddisk
396 QStringList origdb;
397 QStringList newdb;
398 if (!validateCell()) {
399 emit line_error(QString(tr("<font color=red><b>No valid unit cell!</font>")));
400 return;
401 }
402 if (nameEdit->text().isEmpty()) {
403 emit line_error(QString(tr("<font color=red><b>Please give the fragment a name.</font>")));
404 return;
405 }
406 origdb = readFragmentDB();
407 newdb = combineDataToNewFragment();
408 origdb.append(newdb);
409 userdb = true;
410 writeFragmentDB(origdb);
411 this->updateFraglist();
412 this->close();
413 }
414
updateFragment()415 void DSREditWindow::updateFragment() {
416 //! this method deletes the old and writes the new fragment
417 QStringList origdb;
418 QStringList newFragment;
419 QString delfrag; // I will delete this later
420 delfrag = m_nametag;
421 if (!validateCell()) {
422 emit line_error(QString(tr("<font color=red><b>No valid unit cell!</font>")));
423 return;
424 }
425 if (nameEdit->text().isEmpty()) {
426 emit line_error(QString(tr("<font color=red><b>Please give the fragment a name.</font>")));
427 return;
428 }
429 origdb = readFragmentDB();
430 newFragment = combineDataToNewFragment();
431 origdb.append(newFragment);
432 userdb = true;
433 writeFragmentDB(origdb);
434 deleteFragment(delfrag);
435 this->updateFraglist();
436 this->close();
437 }
438
combineDataToNewFragment()439 QStringList DSREditWindow::combineDataToNewFragment(){
440 //! combines all collected data to a fragment string for the database
441 QStringList fragStringList;
442 m_nametag = inventNameTag(5);
443 if (resiclass.isEmpty()) {
444 resiclass = inventNameTag(4);
445 }
446 fragStringList.append("\n<"+m_nametag+">");
447 fragStringList.append("rem Name: "+fragname+"");
448 fragStringList.append("rem Src: ShelXle DSR GUI");
449 fragStringList.append("RESI "+resiclass);
450 foreach (QStringList line, myRestraints) {
451 fragStringList.append(line.join(" "));
452 }
453 fragStringList.append("FRAG 17 "+QString("%1 %2 %3 %4 %5 %6")
454 .arg(a).arg(b).arg(c)
455 .arg(alpha).arg(beta).arg(gamma));
456 QString atline;
457 foreach (QStringList line, myAtoms) {
458 if (line.length() < 5 ) continue;
459 atline.clear();
460 atline = QString("%1 %2 %3 %4 %5")
461 .arg(line.at(0), -5, ' ')
462 .arg(line.at(1), -3, ' ')
463 .arg(line.at(2).toDouble(), 10, 'f', 5)
464 .arg(line.at(3).toDouble(), 10, 'f', 5)
465 .arg(line.at(4).toDouble(), 10, 'f', 5);
466 fragStringList.append(atline);
467 }
468 fragStringList.append("</"+m_nametag+">");
469 return fragStringList;
470 }
471
validateCell()472 bool DSREditWindow::validateCell() {
473 //! validates if the cell parameter make sense
474 if (a > 0 && b > 0 && c > 0) {
475 if ((alpha > 0 && beta > 0 && gamma > 0) && (alpha+beta+gamma <= 360)) {
476 return true;
477 }
478 }
479 return false;
480 }
481
setDBTypeFromDB(DSRMol * header)482 void DSREditWindow::setDBTypeFromDB(DSRMol *header) {
483 //! set userdb false or true if "dsr_db" or "dsr_user_db"
484 if (header->dbtype == QString("dsr_user_db")) {
485 userdb = true;
486 }
487 }
488
setInfoLabel(QString myerror)489 void DSREditWindow::setInfoLabel(QString myerror) {
490 //! display the error of the error signa in infoLabel
491 infoLabel->setText(myerror);
492 }
493
setNamefromDB(DSRMol * header)494 void DSREditWindow::setNamefromDB(DSRMol *header) {
495 //! Set the name of the linedit field nameEdit to the fragment name from the database
496 //! This method runs if you select a fragment and then click on the edit button.
497 QString name;
498 name = header->comment;
499 nameEdit->setText(name);
500 fragname = name;
501 }
502
setResidueFromDB(DSRMol * header)503 void DSREditWindow::setResidueFromDB(DSRMol *header) {
504 //! get residue from header and populate resiclass variable and edit field
505 QString residueClass;
506 residueClass = header->residue;
507 resicledit->setText(residueClass);
508 resiclass = residueClass;
509 }
510
setAtomsFromDB(DSRMol * header)511 void DSREditWindow::setAtomsFromDB(DSRMol *header) {
512 //! Fills the atoms edit field with atom data.
513 QFont font("Courier");
514 atomsEdit->setLineWrapMode(QTextEdit::NoWrap);
515 font.setStyleHint(QFont::TypeWriter);
516 atomsEdit->setMinimumHeight(200);
517 atomsEdit->setFont(font);
518 QTextCursor cursor = atomsEdit->textCursor();
519 QString atomEditorLine;
520 foreach (QStringList atom, header->atoms) {
521 myAtoms.append(atom);
522 atomEditorLine.clear();
523 int num = 0;
524 // This relies on the .format() by DSR!:
525 foreach (QString column, atom) { // format each column:
526 switch (num) {
527 case 0: // name
528 column = column.leftJustified(6, ' ');
529 break;
530 case 1: // sfac
531 column = column.leftJustified(4, ' ');
532 break;
533 case 2: // x
534 column = column.rightJustified(9, ' ')+" ";
535 break;
536 case 3: // y
537 column = column.rightJustified(9, ' ')+" ";
538 break;
539 case 4: // z
540 column = column.rightJustified(9, ' ');
541 break;
542 default: // anything else, just in case...
543 column = column.leftJustified(9, ' ');
544 break;
545 }
546 atomEditorLine = atomEditorLine+column;
547 num++;
548 }
549 atomsEdit->append(atomEditorLine);
550 }
551 cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
552 atomsEdit->setTextCursor(cursor);
553 }
554
setRestraintsFromDB(DSRMol * header)555 void DSREditWindow::setRestraintsFromDB(DSRMol *header) {
556 //! Fils the restraints edit field with restraints from the db
557 QFont font("Courier");
558 restrEdit->setLineWrapMode(QTextEdit::NoWrap);
559 font.setStyleHint(QFont::TypeWriter);
560 restrEdit->setMinimumHeight(200);
561 restrEdit->setFont(font);
562 QTextCursor cursor = restrEdit->textCursor();
563 QStringList restr;
564 restr = header->restr;
565 myRestraints.clear();
566 for (int i=0; i<restr.size(); i++) {
567 restrEdit->append(restr.at(i));
568 myRestraints.append(restr.at(i).split(" ", skipEmptyParts));
569 }
570 cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
571 restrEdit->setTextCursor(cursor);
572 }
573
setCellFromDB(DSRMol * header)574 void DSREditWindow::setCellFromDB(DSRMol *header) {
575 // 2
576 //! Sets the cell information from the dsr db.
577 //! Usually a 1 1 1 90 90 90 cell should come from DSR
578 //! because it exports cartesian coordinates for this GUI
579 a = header->cell.at(0);
580 b = header->cell.at(1);
581 c = header->cell.at(2);
582 alpha = header->cell.at(3);
583 beta = header->cell.at(4);
584 gamma = header->cell.at(5);
585 cell_a->setText(QString("%1").arg(a));
586 cell_b->setText(QString("%1").arg(b));
587 cell_c->setText(QString("%1").arg(c));
588 cell_alpha->setText(QString("%1").arg(alpha));
589 cell_beta->setText(QString("%1").arg(beta));
590 cell_gamma->setText(QString("%1").arg(gamma));
591 cell_a->setMaximumWidth(getCharWidth(10));
592 cell_a->setMinimumWidth(getCharWidth(6));
593 cell_b->setMaximumWidth(getCharWidth(10));
594 cell_b->setMinimumWidth(getCharWidth(6));
595 cell_c->setMaximumWidth(getCharWidth(10));
596 cell_c->setMinimumWidth(getCharWidth(6));
597 cell_alpha->setMaximumWidth(getCharWidth(10));
598 cell_alpha->setMinimumWidth(getCharWidth(6));
599 cell_beta->setMaximumWidth(getCharWidth(10));
600 cell_beta->setMinimumWidth(getCharWidth(6));
601 cell_gamma->setMaximumWidth(getCharWidth(10));
602 cell_gamma->setMinimumWidth(getCharWidth(6));
603 }
604
checkResiClassInput(QString text)605 void DSREditWindow::checkResiClassInput(QString text) {
606 //! check wether the input text to residue class field is valid.
607 if (!text[0].isLetter()) {
608 resicledit->clear(); // first character has to be a letter!
609 resiclass.clear();
610 return;
611 }
612 resiclass.clear();
613 resiclass = text.toUpper();
614 resicledit->setText(text.left(4).toUpper()); // resi class allows up to 4 characters!
615 }
616
setFragmentName(QString name)617 void DSREditWindow::setFragmentName(QString name) {
618 //! runs if fragment name is changed
619 fragname = name;
620 }
621
622
renameRestraints(QStringList new_atnames,int cursopos)623 void DSREditWindow::renameRestraints(QStringList new_atnames, int cursopos){
624 //! renames the restraints in rename mode
625 QTextCursor cursor = atomsEdit->textCursor();
626 cursor.setPosition(cursopos, QTextCursor::MoveAnchor);
627 QStringList origrestr;
628 origrestr = restrEdit->toPlainText().split(QRegExp("\n|\r\n|\r"));
629 atomsEdit->setTextCursor(cursor);
630 // the previous atoms are the names before I typed a new one and renaming starts
631 // I want to rename previous names with new names
632 if (new_atnames.length() == previous_atoms->length()) {
633 restrEdit->clear();
634 foreach (QString rline, origrestr) {
635 QStringList rline_list;
636 rline_list = rline.split(' ');
637 // go through all new atoms and replace previous names with new names in restraints list:
638 int num = 0;
639 foreach (QString newatom, new_atnames) {
640 for(int i = 0; i < rline_list.length(); i++) {
641 if (rline_list.at(i).toUpper() == previous_atoms->at(num).toUpper()) {
642 rline_list[i] = newatom.toUpper().toLatin1();
643 }
644 }
645 num++;
646 }
647 restrEdit->append(rline_list.join(" "));
648 }
649 }
650 }
651
renameAtoms()652 void DSREditWindow::renameAtoms(){
653 //! Takes the text from atomEdit and fills myAtoms Qvector<QStringlist>
654 //! The special thing in this method is that only the Names can be changed
655 //! The text after the fourth character will constantly be overwritten by
656 //! the previous coordinates.
657 //! It should be impossble to delete an atom.
658 int cursopos = atomsEdit->textCursor().position();
659 myAtoms.clear();
660 atomsEdit->disconnect();
661 badLine = false;
662 QString error;
663 QStringList line_split;
664 QStringList new_atnames; // <- the new atom names
665 int num = 0;
666 error = QString(tr(""));
667 emit line_error(error);
668 int length = atomsEdit->toPlainText().split(QRegExp("\n|\r\n|\r")).length();
669 if (previous_atoms->length() == 0) {
670 previous_atoms->append(*first_atnames);
671 }
672 foreach (QString line, atomsEdit->toPlainText().split(QRegExp("\n|\r\n|\r"))) {
673 if (length != previous_atoms->length()) { // make sure not to delete an atom!
674 atomsEdit->undo(); // In this case, undo last action
675 connect(atomsEdit, SIGNAL(textChanged()),
676 this, SLOT(renameAtoms()));
677 return;
678 }
679 line_split = line.split(" ", skipEmptyParts);
680 if (line_split.length() > 0){
681 line_split[0] = line_split.at(0).left(4);
682 new_atnames.append(line_split.at(0).toUpper()); // collect new atom names after after a character was changed
683 } else { // This is to make sure there is no empty line. An empty line will cause the rename mode to abort.
684 this->atomsEdit->undo();
685 this->abortRenameMode();
686 error = QString(tr("<font color=red><b>Do not delete atoms in rename mode!</font>"));
687 emit line_error(error);
688 return;
689 }
690 num++;
691 if (new_atnames.count(line_split.at(0)) >= 2) {
692 // warn user about duplicates and do not rename atom:
693 error = QString(tr("<font color=red><b>Attempt to create duplicate atom \"%1\" detected. "
694 "<br>Please make them unique.</font>").arg(line_split.at(0)));
695 emit line_error(error);
696 atomsEdit->undo(); // In this case, undo last action. Makes duplicates impossible
697 connect(atomsEdit, SIGNAL(textChanged()),
698 this, SLOT(renameAtoms()));
699 return;
700 }
701 if (!line_split.at(0).contains(QRegExp("^([A-Za-z]{1,3})\\d{0,3}[A-Za-z\\'\\\"\\#]{0,2}\\d{0,1}"))) {
702 error = QString(tr("<font color=red><b>Invalid atom name found.</font>"));
703 emit line_error(error);
704 connect(atomsEdit, SIGNAL(textChanged()),
705 this, SLOT(renameAtoms()));
706 return;
707 }
708 }
709 atomsEdit->clear();
710 int onum = 0;
711 foreach (QString line, oldatoms->split(QRegExp("\n|\r\n|\r"))) {
712 // use the new names + the previous atoms
713 line = new_atnames.at(onum).leftJustified(4, ' ').left(4)+line.remove(0, 4);
714 atomsEdit->append(line);
715 myAtoms.append(line.split(' ', skipEmptyParts));
716 onum++;
717 }
718 renameRestraints(new_atnames, cursopos);
719 previous_atoms->clear();
720 previous_atoms->append(new_atnames);
721 new_header->atoms.clear();
722 foreach(QStringList line, myAtoms) {
723 new_header->atoms.append(line);
724 }
725 connect(atomsEdit, SIGNAL(textChanged()),
726 this, SLOT(renameAtoms()));
727 myedgl->display_fragment(*new_header);
728 }
729
730
setAtoms()731 void DSREditWindow::setAtoms(){
732 //! takes the text from atomEdit and fills myAtoms Qvector<QStringlist>
733 renameButton->setDisabled(true);
734 myAtoms.clear();
735 badLine = false;
736 QString error;
737 QStringList line_split;
738 QStringList atnames;
739 int num = 0;
740 foreach (QString line, atomsEdit->toPlainText().split(QRegExp("\n|\r\n|\r"))) {
741 line_split = line.split(" ", skipEmptyParts);
742 line_split = checkAtomLine(line_split, num+1);
743 myAtoms.append(line_split);
744 if (line_split.length() > 0){
745 atnames.append(line_split.at(0).toUpper());
746 if (atnames.count(line_split.at(0).toUpper()) >= 2) {
747 error = QString(tr("<font color=red><b>Duplicate atom \"%1\" found! Please make them unique.</font>").arg(line_split.at(0)));
748 // Can not do undo(), because it would prevent adding duplicate names with "add selected atoms"
749 // and this has to be possible because of residues:
750 //atomsEdit->undo();
751 emit line_error(error);
752 badLine = true;
753 //return;
754 }
755 }
756 num++;
757 }
758 if (myAtoms.size() <= 1 && myAtoms[0].isEmpty()) {
759 addButton->setDisabled(true);
760 updateButton->setDisabled(true);
761 error = QString(tr("<font color=red><b>Please add at least one atom to add/update the fragment.</font>"));
762 emit line_error(error);
763 return;
764 } else {
765 addButton->setEnabled(true);
766 updateButton->setEnabled(true);
767 }
768 if (!badLine) {
769 emit line_error("");
770 addButton->setEnabled(true);
771 updateButton->setEnabled(true);
772 } else {
773 updateButton->setDisabled(true);
774 addButton->setDisabled(true);
775 return;
776 }
777 }
778
setSelectedAtoms()779 void DSREditWindow::setSelectedAtoms() {
780 //! uses selected atoms for atom field and sets cell accordingly
781 atomsEdit->clear();
782 int numselect = m_mol->selectedatoms.size();
783 QString line;
784 QString atname;
785 QString firstatom;
786 QString lastatom;
787 for (int i = 0; i < numselect; i++) {
788 line.clear();
789 atname.clear();
790 // The two split() make sure no illegal suffices remain on the labels:
791 atname = m_mol->selectedatoms.at(i).Label.split('_').at(0).split(QChar(187)).at(0);
792 if (i == 0) {
793 firstatom = atname;
794 }
795 if (i+1 == numselect) {
796 lastatom = atname;
797 }
798 line = QString("%1 %2 %3 %4 %5")
799 .arg(atname, -5) // Atom name
800 .arg(m_mol->selectedatoms.at(i).an+1, -2) // strangely ShelXle stores AN-1 here
801 .arg(m_mol->selectedatoms.at(i).pos.x, 10, 'f', 5) // X
802 .arg(m_mol->selectedatoms.at(i).pos.y, 10, 'f', 5) // Y
803 .arg(m_mol->selectedatoms.at(i).pos.z, 10, 'f', 5); // Z
804 atomsEdit->append(line);
805 }
806 // make sure at least some restraints end up in the database:
807 if ((restrEdit->toPlainText().simplified().size() < 4)
808 && (firstatom.size() > 0) && (lastatom.size() > 0)) {
809 restrEdit->clear();
810 restrEdit->append(QString("RIGU %1 > %2").arg(firstatom, lastatom));
811 restrEdit->append(QString("SIMU %1 > %2").arg(firstatom, lastatom));
812 }
813 cell_a->setText("1");
814 cell_b->setText("1");
815 cell_c->setText("1");
816 cell_alpha->setText("90");
817 cell_beta->setText("90");
818 cell_gamma->setText("90");
819 updateButton->show();
820 addButton->show();
821 }
822
checkAtomLine(QStringList line,int num)823 QStringList DSREditWindow::checkAtomLine(QStringList line, int num) {
824 //! check an atom text line for consistency
825 //! like if there are all xyz parameters or the name makes sense
826 QString error;
827 error.clear();
828 bool isAtFloat = false;
829 if (!line.isEmpty()) {
830 line.at(0).toFloat(&isAtFloat);
831 }
832 bool is_scatt_int = true;
833 if (line.length() >= 2) {
834 line.at(1).toFloat(&is_scatt_int);
835 }
836 if (line.size() > 0 && line.size() < 5) {
837 error = QString(tr("<font color=red><b>Error in atom line %1: Too few parameters.</b></font>")).arg(num);
838 emit line_error(error);
839 badLine = true;
840 } else if (line.size() > 5) {
841 error = QString(tr("<font color=red><b>Error in atom line %1: Too many parameters.</font>")).arg(num);
842 emit line_error(error);
843 badLine = true;
844 } else if (line.join("").contains(",")) {
845 error = QString(tr("<font color=red><b>Error in atom line %1: Numbers should not contain comma.</font>")).arg(num);
846 emit line_error(error);
847 badLine = true;
848 } else if (!line.isEmpty() && line[0][0].isDigit()) {
849 error = QString(tr("<font color=red><b>Error in atom line %1: Atoms can not begin with a number.</font>")).arg(num);
850 emit line_error(error);
851 badLine = true;
852 } else if (!line.isEmpty() && line[0].length() > 4) {
853 error = QString(tr("<font color=red><b>Error in atom line %1: Atom name must not have more than four characters.</font>")).arg(num);
854 emit line_error(error);
855 badLine = true;
856 } else if (!line.isEmpty() && line[0].contains("_")) {
857 error = QString(tr("<font color=red><b>Error in atom line %1: Atom name must not have underscores.</font>")).arg(num);
858 emit line_error(error);
859 badLine = true;
860 } else if (isAtFloat) {
861 error = QString(tr("<font color=red><b>Error in atom line %1: Atoms can not be only numbers.</font>")).arg(num);
862 emit line_error(error);
863 badLine = true;
864 } else if (!myisAscii(line.join(""))) {
865 error = QString(tr("<font color=red><b>Error in atom line %1: Non-ascii characters are not allowed.</font>")).arg(num);
866 emit line_error(error);
867 badLine = true;
868 } else if (!is_scatt_int) {
869 error = QString(tr("<font color=red><b>Error in atom line %1: Scattering factor can be only integer numbers.</font>")).arg(num);
870 emit line_error(error);
871 badLine = true;
872 } else if (!validateCell()) {
873 error = QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>"));
874 emit line_error(error);
875 badLine = true;
876 }else {
877 int num2 = 0;
878 foreach (QString item, line) {
879 bool ok = false;
880 item.toFloat(&ok);
881 if (num2 >= 2 && !ok){
882 error = QString(tr("<font color=red><b>Error in atom line %1: columns 3 to 5 contain non-numerical character(s).</font>")).arg(num);
883 emit line_error(error);
884 badLine = true;
885 }
886 num2++;
887 }
888 }
889 if (badLine == true) {
890 addButton->setDisabled(true);
891 updateButton->setDisabled(true);
892 } else {
893 addButton->setEnabled(true);
894 updateButton->setEnabled(true);
895 }
896 return line;
897 }
898
myisAscii(QString line)899 bool DSREditWindow::myisAscii(QString line) {
900 //! test if line contains non-ascii characters
901 for (int num=0; num<line.length(); num++) {
902 if (line.at(num).unicode() > 127) return false;
903 }
904 return true;
905 }
906
setRestraints()907 void DSREditWindow::setRestraints() {
908 //! takes text from restrEdit and fills myRestraints Qvector<QStringlist>
909 renameButton->setDisabled(true);
910 myRestraints.clear();
911 badLine = false;
912 QString error;
913 QStringList line_split;
914 int num = 0;
915 foreach (QString line, restrEdit->toPlainText().split(QRegExp("\n|\r\n|\r"))) {
916 line_split = line.split(" ", skipEmptyParts);
917 checkRestraintLine(line_split, num+1);
918 myRestraints.append(line_split);
919 num++;
920 }
921 if (!badLine) {
922 emit line_error("");
923 } else {
924 return;
925 }
926 if (myRestraints[0].isEmpty()) {
927 addButton->setDisabled(true);
928 updateButton->setDisabled(true);
929 error = QString(tr("<font color=red><b>Please add at least one restraint to add/update the fragment.</font>"));
930 emit line_error(error);
931 } else {
932 addButton->setEnabled(true);
933 updateButton->setEnabled(true);
934 }
935 }
936
checkRestraintLine(QStringList restrline,int num)937 void DSREditWindow::checkRestraintLine(QStringList restrline, int num) {
938 //! Check each line of the restraints for errors. Especially atoms that
939 //! are not in the atoms list.
940 bool ok;
941 QString error;
942 QStringList atomList;
943 foreach (QStringList atomline, myAtoms) {
944 if (atomline.isEmpty()) continue;
945 atomList.append(atomline.at(0).toUpper());
946 }
947 foreach (QString item, restrline.mid(0, 1)) {
948 if (!RESTRAINT_CARDS.contains(item.toUpper())){
949 error = QString(tr("<font color=red><b>Invalid restraint %1 in line %2.</font>")).arg(item).arg(num);
950 updateButton->setDisabled(true);
951 addButton->setDisabled(true);
952 emit line_error(error);
953 badLine = true;
954 }
955 if (badLine == true) {
956 return;
957 }
958 }
959 foreach (QString item, restrline.mid(1, -1)) {
960 item.toFloat(&ok);
961 if (ok) {continue;}
962 if (item == ">") {continue;}
963 if (item == "<") {continue;}
964 if (item == "_") {continue;}
965 if (item == "$") {continue;}
966 if (!atomList.contains(item.toUpper())) {
967 error = QString(tr("<font color=red><b>Atom %1 in restraints line %2 not in atom list!</font>")).arg(item).arg(num);
968 updateButton->setDisabled(true);
969 addButton->setDisabled(true);
970 emit line_error(error);
971 badLine = true;
972 }
973 if (badLine == true) {
974 return;
975 }
976 error = "";
977 emit line_error(error);
978 }
979 num++;
980 }
981
makeUnitCellEdit()982 void DSREditWindow::makeUnitCellEdit(){
983 //! The unit cell input field
984 cellLayout = new QHBoxLayout;
985 cell_a = new QLineEdit;
986 cell_b = new QLineEdit;
987 cell_c = new QLineEdit;
988 cell_alpha = new QLineEdit;
989 cell_beta = new QLineEdit;
990 cell_gamma = new QLineEdit;
991 QLabel *alabel = new QLabel("a:");
992 QLabel *blabel = new QLabel("b:");
993 QLabel *clabel = new QLabel("c:");
994 QLabel *alphalabel = new QLabel(QChar(0xb1, 0x03)+QString(":"));
995 QLabel *betalabel = new QLabel(QChar(0xb2, 0x03)+QString(":"));
996 QLabel *gammalabel = new QLabel(QChar(0xb3, 0x03)+QString(":"));
997 cellLayout->addWidget(alabel);
998 cellLayout->addWidget(cell_a);
999 cellLayout->addWidget(blabel);
1000 cellLayout->addWidget(cell_b);
1001 cellLayout->addWidget(clabel);
1002 cellLayout->addWidget(cell_c);
1003 cellLayout->addWidget(alphalabel);
1004 cellLayout->addWidget(cell_alpha);
1005 cellLayout->addWidget(betalabel);
1006 cellLayout->addWidget(cell_beta);
1007 cellLayout->addWidget(gammalabel);
1008 cellLayout->addWidget(cell_gamma);
1009 // TODO: better validator needed:
1010 QDoubleValidator *cellaValidator = new QDoubleValidator(0, 999, 6, cell_a);
1011 cellaValidator->setNotation(QDoubleValidator::StandardNotation);
1012 QDoubleValidator *cellbValidator = new QDoubleValidator(0, 999, 6, cell_b);
1013 cellbValidator->setNotation(QDoubleValidator::StandardNotation);
1014 QDoubleValidator *cellcValidator = new QDoubleValidator(0, 999, 6, cell_c);
1015 cellcValidator->setNotation(QDoubleValidator::StandardNotation);
1016 QDoubleValidator *cellalValidator = new QDoubleValidator(0, 360, 6, cell_alpha);
1017 cellalValidator->setNotation(QDoubleValidator::StandardNotation);
1018 QDoubleValidator *cellbeValidator = new QDoubleValidator(0, 360, 6, cell_beta);
1019 cellbeValidator->setNotation(QDoubleValidator::StandardNotation);
1020 QDoubleValidator *cellgaValidator = new QDoubleValidator(0, 360, 6, cell_gamma);
1021 cellgaValidator->setNotation(QDoubleValidator::StandardNotation);
1022 //connect(cell_a, SIGNAL(textChanged(QString)),cell_a, SLOT(validate_cellinput()));
1023 cell_a->setValidator(cellaValidator);
1024 cell_b->setValidator(cellbValidator);
1025 cell_c->setValidator(cellcValidator);
1026 cell_alpha->setValidator(cellalValidator);
1027 cell_beta->setValidator(cellbeValidator);
1028 cell_gamma->setValidator(cellgaValidator);
1029 cell_a->setMaximumWidth(getCharWidth(7));
1030 cell_b->setMaximumWidth(getCharWidth(7));
1031 cell_c->setMaximumWidth(getCharWidth(7));
1032 cell_alpha->setMaximumWidth(getCharWidth(7));
1033 cell_beta->setMaximumWidth(getCharWidth(7));
1034 cell_gamma->setMaximumWidth(getCharWidth(7));
1035 }
1036
set_a_value(QString a)1037 void DSREditWindow::set_a_value(QString a) {
1038 cell_a->setStyleSheet("QLineEdit");
1039 if (a.contains(",")){
1040 a.replace(",", ".");
1041 cell_a->setText(a);
1042 }
1043 bool ok;
1044 this->a = a.toDouble(&ok);
1045 if (!ok) {
1046 cell_a->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1047 }
1048 if (validateCell()) {
1049 emit line_error("");
1050 } else {
1051 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1052 }
1053 }
1054
set_b_value(QString b)1055 void DSREditWindow::set_b_value(QString b) {
1056 cell_b->setStyleSheet("QLineEdit");
1057 if (b.contains(",")){
1058 b.replace(",", ".");
1059 cell_b->setText(b);
1060 }
1061 bool ok;
1062 this->b = b.toDouble(&ok);
1063 if (!ok) {
1064 cell_b->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1065 }
1066 if (validateCell()) {
1067 emit line_error("");
1068 } else {
1069 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1070 }
1071 }
set_c_value(QString c)1072 void DSREditWindow::set_c_value(QString c) {
1073 cell_c->setStyleSheet("QLineEdit");
1074 if (c.contains(",")){
1075 c.replace(",", ".");
1076 cell_c->setText(c);
1077 }
1078 bool ok;
1079 this->c = c.toDouble(&ok);
1080 if (!ok) {
1081 cell_c->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1082 }
1083 if (validateCell()) {
1084 emit line_error("");
1085 } else {
1086 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1087 }
1088 }
1089
set_alpha_value(QString alpha)1090 void DSREditWindow::set_alpha_value(QString alpha) {
1091 cell_alpha->setStyleSheet("QLineEdit");
1092 if (alpha.contains(",")){
1093 alpha.replace(",", ".");
1094 cell_alpha->setText(alpha);
1095 }
1096 bool ok;
1097 this->alpha = alpha.toDouble(&ok);
1098 if (!ok) {
1099 cell_alpha->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1100 }
1101 if (validateCell()) {
1102 emit line_error("");
1103 } else {
1104 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1105 }
1106 }
1107
set_beta_value(QString beta)1108 void DSREditWindow::set_beta_value(QString beta) {
1109 cell_beta->setStyleSheet("QLineEdit");
1110 if (beta.contains(",")){
1111 beta.replace(",", ".");
1112 cell_beta->setText(beta);
1113 }
1114 bool ok;
1115 this->beta = beta.toDouble(&ok);
1116 if (!ok) {
1117 cell_beta->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1118 }
1119 if (validateCell()) {
1120 emit line_error("");
1121 } else {
1122 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1123 }
1124 }
1125
set_gamma_value(QString gamma)1126 void DSREditWindow::set_gamma_value(QString gamma) {
1127 cell_gamma->setStyleSheet("QLineEdit");
1128 if (gamma.contains(",")){
1129 gamma.replace(",", ".");
1130 cell_gamma->setText(gamma);
1131 }
1132 bool ok;
1133 this->gamma = gamma.toDouble(&ok);
1134 if (!ok) {
1135 cell_gamma->setStyleSheet("QLineEdit{background: rgb(255, 180, 180);}");
1136 }
1137 if (validateCell()) {
1138 emit line_error("");
1139 } else {
1140 emit line_error(QString(tr("<font color=red><b>Please define proper unit cell parameters!</font>")));
1141 }
1142 }
1143
getCharWidth(int numchars)1144 int DSREditWindow::getCharWidth(int numchars) {
1145 //! returns the width of a numchar amount of characters
1146 QString buchstaben;
1147 buchstaben.clear();
1148 for (int i=1; i<=numchars; i++) {
1149 buchstaben += "#";
1150 }
1151
1152 #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
1153 return QFontMetrics(this->font()).horizontalAdvance(buchstaben);
1154 }
1155 #else
1156 return QFontMetrics(this->font()).width(buchstaben);
1157 }
1158 #endif
1159
deleteCurrentFragment()1160 void DSREditWindow::deleteCurrentFragment(){
1161 //! delete the currently open fragment
1162 deleteFragment(m_nametag);
1163 }
1164
deleteFragment(QString nametag)1165 void DSREditWindow::deleteFragment(QString nametag){
1166 //! deletes the fragment with tag "nametag" from and only
1167 //! from the dsr_user_db.txt.
1168 QStringList udb = readFragmentDB();
1169 QStringList udb2;
1170 udb2.clear();
1171 int startlineNumber, endlineNumber;
1172 startlineNumber = -1;
1173 endlineNumber = -1;
1174 for (int i=0; i<udb.size(); i++) {
1175 if (udb[i].toUpper().startsWith("<"+nametag.toUpper()+">")){
1176 if (startlineNumber > 0) {
1177 setInfoLabel(QString(tr("Duplicate entry for %1 found in the users database")).arg(nametag));
1178 return;} // in this case we have a dublicate entry
1179 startlineNumber = i;
1180 }
1181 if (udb[i].toUpper().startsWith("</"+nametag.toUpper()+">")){
1182 if (endlineNumber > 0) {
1183 setInfoLabel(QString(tr("Duplicate entry for %1 found in the users database")).arg(nametag));
1184 return;} // in this case we have a dublicate entry
1185 endlineNumber = i;
1186 }
1187 }
1188 if ((startlineNumber < 0) || (endlineNumber < 0)) {
1189 setInfoLabel(QString(tr("Start or end tag %1 missing in the users database")).arg(nametag));
1190 return; // in this case any of the db tags was not found
1191 }
1192 if (startlineNumber > 0) {
1193 udb2 = udb.mid(0, startlineNumber);
1194 }
1195 udb2 = udb2+udb.mid(endlineNumber+1, -1);
1196 writeFragmentDB(udb2);
1197 }
1198
readFragmentDB()1199 QStringList DSREditWindow::readFragmentDB() {
1200 //! read the entire user databse into a stringlist
1201 QFile file(mydsrdbpath+"/dsr_user_db.txt");
1202 QStringList stringList;
1203 if (file.open(QFile::ReadOnly | QFile::Text)) {
1204 QTextStream textStream(&file);
1205 while (true) {
1206 QString line = textStream.readLine();
1207 if (line.isNull()) {
1208 break;
1209 }
1210 if (line.isEmpty()) {
1211 continue;
1212 } else {
1213 stringList.append(line);
1214 }
1215 }
1216 }
1217 file.close();
1218 return stringList;
1219 }
1220
writeFragmentDB(QStringList database)1221 void DSREditWindow::writeFragmentDB(QStringList database) {
1222 //! write the entire user databse into a text file
1223 if (userdb == false) {
1224 return;
1225 } // never delete from main DB
1226 QFile file(mydsrdbpath+"/dsr_user_db.txt");
1227 if (file.open(QFile::ReadWrite | QFile::Text)) {
1228 QTextStream out(&file);
1229 file.resize(0); // delete original
1230 out << database.join("\n");
1231 }
1232 file.close();
1233 }
1234
doesFragExist(QString name,bool fullname=false)1235 bool DSREditWindow::doesFragExist(QString name, bool fullname=false) {
1236 //! checks if a fragment nametag is already in the database
1237 //! setting fullname to true checks for the full name instead of the tag
1238 int column = 0;
1239 if (fullname) {
1240 column = 1;
1241 }
1242 foreach (QStringList line, m_frags) {
1243 if (line.at(column).toLower() == name.toLower()) {
1244 return true;
1245 }
1246 }
1247 return false;
1248 }
1249
randString(int len)1250 QString DSREditWindow::randString(int len) {
1251 //! returns a random string of size len
1252 //! from http://stackoverflow.com/questions/3244999/create-a-random-string-or-number-in-qt4
1253 QString str;
1254 str.resize(len);
1255 for (int s = 0; s < len ; ++s) {
1256 str[s] = QChar('A' + char(qrand() % ('Z' - 'A')));
1257 }
1258 return str;
1259 }
1260
inventNameTag(int length=5)1261 QString DSREditWindow::inventNameTag(int length=5){
1262 //! invents a random name tag for a new fragment
1263 QString name;
1264 bool there = true;
1265 while (there) {
1266 name = randString(length);
1267 there = doesFragExist(name, false);
1268 }
1269 return name;
1270 }
1271
1272