diff options
Diffstat (limited to 'client/cprquerydialog.cc')
-rw-r--r-- | client/cprquerydialog.cc | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/client/cprquerydialog.cc b/client/cprquerydialog.cc new file mode 100644 index 0000000..19337a4 --- /dev/null +++ b/client/cprquerydialog.cc @@ -0,0 +1,486 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * cprquerydialog.cc + * + * Sat Feb 19 17:05:43 CET 2005 + * Copyright 2005 Bent Bisballe + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of MIaV. + * + * MIaV is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MIaV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MIaV; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include <qframe.h> + +#include "messagebox.h" +#include "cprquerydialog.h" +#include "miav_config.h" + +CPRQueryDialog::CPRQueryDialog(Info *info, + QLabel *lcpr, + QLabel *lname, + QWidget *parent, + const char *name, + QStatusBar *status) + : QDialog(parent, name, TRUE) +{ + this->info = info; + setCaption(name); + + // Load image + QPixmap pix_backspace; + pix_backspace.load( PIXMAP_BACKSPACE ); + + lbl_name = lname; + lbl_cpr = lcpr; + statusbar = status; + + //Read configuration + CPR_HOST = config->readString("cpr_host"); + CPR_PORT = config->readInt("cpr_port"); + CPR_TIMEOUT = config->readInt("cpr_timeout"); + + cpr[0] = '\0'; + internalCpr[0] = '\0'; + + cprSocket = new QSocket(this); + connect(cprSocket, SIGNAL(readyRead()), SLOT(cprSocket_readyRead())); + connect(cprSocket, SIGNAL(connected()), SLOT(cprSocket_connected())); + connect(cprSocket, SIGNAL(error(int)), SLOT(cprSocket_error(int))); + + lbl_cpr->setText("Indtast CPR"); + + // Setup connection timer + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(cprSocket_timeout())); + + // Generate input buttons + QGridLayout *gl = new QGridLayout(this, 4, 3, 10, 2); + + QButton *b1 = createButton(this, "1", 1); + QButton *b2 = createButton(this, "2", 2); + QButton *b3 = createButton(this, "3", 3); + QButton *b4 = createButton(this, "4", 4); + QButton *b5 = createButton(this, "5", 5); + QButton *b6 = createButton(this, "6", 6); + QButton *b7 = createButton(this, "7", 7); + QButton *b8 = createButton(this, "8", 8); + QButton *b9 = createButton(this, "9", 9); + QButton *b0 = createButton(this, "0", 0); + QButton *bbs = createButton(this, "", 10); + bbs->setPixmap(pix_backspace); + QButton *bca = createButton(this, "CA", 11); + + gl->addWidget(b1, 0,0); + gl->addWidget(b2, 0,1); + gl->addWidget(b3, 0,2); + gl->addWidget(b4, 1,0); + gl->addWidget(b5, 1,1); + gl->addWidget(b6, 1,2); + gl->addWidget(b7, 2,0); + gl->addWidget(b8, 2,1); + gl->addWidget(b9, 2,2); + gl->addWidget(b0, 3,1); + gl->addWidget(bbs, 3,2); + gl->addWidget(bca, 3,0); + + // Setup signals + connect(b1, SIGNAL(clicked()), SLOT(b_1_clicked())); + connect(b2, SIGNAL(clicked()), SLOT(b_2_clicked())); + connect(b3, SIGNAL(clicked()), SLOT(b_3_clicked())); + connect(b4, SIGNAL(clicked()), SLOT(b_4_clicked())); + connect(b5, SIGNAL(clicked()), SLOT(b_5_clicked())); + connect(b6, SIGNAL(clicked()), SLOT(b_6_clicked())); + connect(b7, SIGNAL(clicked()), SLOT(b_7_clicked())); + connect(b8, SIGNAL(clicked()), SLOT(b_8_clicked())); + connect(b9, SIGNAL(clicked()), SLOT(b_9_clicked())); + connect(b0, SIGNAL(clicked()), SLOT(b_0_clicked())); + connect(bbs,SIGNAL(clicked()), SLOT(b_b_clicked())); + connect(bca,SIGNAL(clicked()), SLOT(b_c_clicked())); + + this->move(175,150); + + listen = new CPRListen(info, config->readInt("cprlisten_port")); + listen_timer = new QTimer(this); + connect(listen_timer, SIGNAL(timeout()), SLOT(listen_timeout())); + listen->run(); + listen_timer->start(500); // Check every 500 ms + + show(); +} + +CPRQueryDialog::~CPRQueryDialog() +{ + // Cleanup + // delete timer; + // delete cprSocket + + // Cleanup after cpr listen + listen->stop(); + // listen->wait_stop(); + delete listen; + // delete listen_timer; +} + +void CPRQueryDialog::listen_timeout() +{ + string newcpr; + if(listen->cprChanged()) { + char newcpr_buf[32]; + newcpr = listen->getCpr(); + sprintf(newcpr_buf, "%s-%s", newcpr.substr(0,6).c_str(), newcpr.substr(6,4).c_str()); + // printf("cprbuf[%s]\n", newcpr_buf); + lbl_cpr->setText(newcpr_buf); + verifycpr(newcpr_buf); + } +} + +/** + * createButton: + * A genric button-creater + */ +QPushButton *CPRQueryDialog::createButton(QWidget *parent, const char *text, int value) +{ + char buf[32]; + sprintf(buf, "%d", value); + QPushButton *q = new QPushButton(this, buf); + + QFont f("Lucida", 48); + q->setFixedSize(150, 100); + q->setText(text); + q->setFont(f); + return q; +} + +/** + * Event functions for handling buttonclicks. + * For button 0-9 the values is sent back. + * Backspace and clear are handled via special + * signals. + * When 10 digits has been input we close the form + */ +void CPRQueryDialog::b_1_clicked() { insert_digit(1); } +void CPRQueryDialog::b_2_clicked() { insert_digit(2); } +void CPRQueryDialog::b_3_clicked() { insert_digit(3); } +void CPRQueryDialog::b_4_clicked() { insert_digit(4); } +void CPRQueryDialog::b_5_clicked() { insert_digit(5); } +void CPRQueryDialog::b_6_clicked() { insert_digit(6); } +void CPRQueryDialog::b_7_clicked() { insert_digit(7); } +void CPRQueryDialog::b_8_clicked() { insert_digit(8); } +void CPRQueryDialog::b_9_clicked() { insert_digit(9); } +void CPRQueryDialog::b_0_clicked() { insert_digit(0);} +void CPRQueryDialog::b_b_clicked() { remove_digit();} +void CPRQueryDialog::b_c_clicked() { remove_all();} + +void CPRQueryDialog::b_clicked(int value) +{ + printf("%d\n", value); + switch(value) { + case 10: + if (digits>0) digits--; + emit bbs_clicked(); + break; + case 11: + digits = 0; + emit bca_clicked(); + break; + default: + digits++; + emit number_clicked(value); + } + if (digits == 10){ + digits = 0; + accept(); + } +} + +/** + * remove_digit: + * Remove one digit from the selected cpr + * Used when the user pushes backspace in + * the inputwindow + */ +void CPRQueryDialog::remove_digit() +{ + int temp; + temp = strlen(cpr); + if (temp == 7) /* Remove two characters due to the hyphen */ + strcpy(cpr+temp-2, "\0"); + else if ((temp >0) && (temp <=11)) + strcpy(cpr+temp-1, "\0"); + lbl_cpr->setText(cpr); +} + +/** + * remove_all: + * Clear the selected cpr + */ +void CPRQueryDialog::remove_all() +{ + strcpy(cpr, ""); + lbl_cpr->setText(cpr); +} + +/** + * insert_digit: + * Respond to what the user types in the inputWindow + */ +void CPRQueryDialog::insert_digit(int value) +{ + char temp[2]; + switch(strlen(cpr)) { + case 5: // Automaticaly add a hyphen after the sixth digit + sprintf(temp, "%d-", value); + strcat(cpr, temp); + lbl_cpr->setText(cpr); + break; + case 10: + sprintf(temp, "%d", value); + strcat(cpr, temp); + lbl_cpr->setText(cpr); + verifycpr(cpr); + break; + default: + sprintf(temp, "%d", value); + strcat(cpr, temp); + lbl_cpr->setText(cpr); + break; + } +} + +/** + * verifycpr: + * Test a cpr via test_cpr(). + * If cpr is invalid, then ask user what + * to do via MessageBox + */ +void CPRQueryDialog::verifycpr(char *cpr) +{ + strncpy(internalCpr, cpr, 6); + strncpy(internalCpr+6, cpr+7, 4); + internalCpr[10] = 0; + + if (!(test_cpr(internalCpr))) { + MessageBox ccw(this, CONFIRM_INVALID_CPR_TITLE, CONFIRM_INVALID_CPR, TYPE_YES_NO_CANCEL); + switch(ccw.exec()) { + case MSG_CANCEL: + bedit_clicked(); + break; + case MSG_NO: + bcancel_clicked(); + break; + case MSG_YES: + // Overwrite name from previous cpr. + lbl_name->setText(NAME_NOT_AVAILABLE); + accept(); + break; + } + } else { + cprSocket->connectToHost(CPR_HOST->c_str(), CPR_PORT); + timer->start(CPR_TIMEOUT); + // accept(); + } +} + + +/* Clears all data - alerts user if measurements are not stored */ +void CPRQueryDialog::bcancel_clicked() +{ + cpr[0]= '\0'; + lbl_cpr->setText("Indtast CPR"); + lbl_name->setText(""); +} + +/* This is used when the user enters a cpr that is not valid and wishes to edit + * the cpr. + */ +void CPRQueryDialog::bedit_clicked() +{ + cpr[10]= '\0'; + lbl_cpr->setText(cpr); + lbl_name->setText(""); +} + + +/** + * test_cpr: + * Checks that a cpr i valid via a modulo 11 test + */ +int CPRQueryDialog::test_cpr(const char *s) +{ + int sum = 0; + int ctl; + const char *cptr; + + // Is the string to short to be a cpr? + if(strlen(s) != 10) return 0; + + // Are all characters digits? + for(cptr = s; *cptr; cptr++) if(!isdigit(*cptr)) return 0; + + // Calculate modulo 11 checksum + sum += (s[0] - '0') * 4; + sum += (s[1] - '0') * 3; + sum += (s[2] - '0') * 2; + sum += (s[3] - '0') * 7; + sum += (s[4] - '0') * 6; + sum += (s[5] - '0') * 5; + sum += (s[6] - '0') * 4; + sum += (s[7] - '0') * 3; + sum += (s[8] - '0') * 2; + ctl = 11 - (sum % 11); + + // Is the checksum correct? + if(ctl == 11) ctl = 0; + return s[9] - '0' == ctl; +} + +/** + * cprSocket_error + * Called if an error occurres in the corsocket connection. + * Writes out the appropriate error message. + */ +void CPRQueryDialog::cprSocket_error(int errnum) +{ + QString msg = QString("cprSocket encountered an error: "); + timer->stop(); + + lbl_name->setText(NAME_NOT_AVAILABLE); + + // Print error message + switch(errnum) { + case QSocket::ErrConnectionRefused: // if the connection was refused + msg.append("ErrConnectionRefused"); + break; + case QSocket::ErrHostNotFound: // if the host was not found + msg.append("ErrHostNotFound"); + break; + case QSocket::ErrSocketRead: // if a read from the socket failed + msg.append("ErrSocketRead"); + break; + } + + if(statusbar) statusbar->message(msg, 5000); + MessageBox(this, "Fejl", msg, TYPE_OK, ICON_ERROR).exec(); + //info->error(msg.c_str()); + accept(); +} + +/** + * cprSocket_readyRead: + * Uses a patients cpr to look up his or hers name + * via the departments cpr-server. + * This is called by the cprSocket when the socket is ready + */ +void CPRQueryDialog::cprSocket_readyRead() +{ + QString name; + QString firstname; + QString lastname; + int timeout = 0; + + if (!cprSocket->canReadLine()) return; + + QString msg = QString("Recieving name from cpr database..."); + if(statusbar) statusbar->message(msg, 5000); + timer->stop(); + + while(cprSocket->canReadLine()) { + QString s = cprSocket->readLine(); + if (s.startsWith("0001")) { + name.append(s.right(s.length()-4)); + lastname.append(s.right(s.length()-4)); + name.setLength(name.length()-1); + if (name.length()) name += QString(", "); + } + if (s.startsWith("0002")) { + name.append(s.right(s.length()-4)); + firstname.append(s.right(s.length()-4)); + name.setLength(name.length()-1); + cprSocket->close(); + lbl_name->setText(name); + accept(); + return; + } + if (timeout>1000) { + lbl_name->setText(NAME_NOT_AVAILABLE); + MessageBox(this, NAME_NOT_AVAILABLE_TITLE, NAME_NOT_AVAILABLE, TYPE_OK, ICON_ERROR).exec(); + accept(); + return; + } + timeout++; + } + + accept(); +} + + +/** + * cprSocket_connected: + * Writes the selected cpr to the cpr-server + * when the cprSocket is connected. + */ +void CPRQueryDialog::cprSocket_connected() +{ + QString msg = QString("Connected to cpr database, sending cpr number..."); + if(statusbar) statusbar->message(msg, 5000); + timer->stop(); + + cprSocket->writeBlock(internalCpr, 10); + cprSocket->writeBlock("\n", 1); +} + +/** + * cprSocket_timeout: + * Called when the connection has not emitted a signal in CPR_TIMEOUT miliseconds. + */ +void CPRQueryDialog::cprSocket_timeout() +{ + QString msg = QString("cprSocket timed out doing: "); + timer->stop(); + + lbl_name->setText(NAME_NOT_AVAILABLE); + + + // Print connection status + switch(cprSocket->state()) { + case QSocket::Idle: // if there is no connection + msg.append("Idle"); + break; + case QSocket::HostLookup: // during a DNS lookup + msg.append("HostLookup"); + break; + case QSocket::Connecting: // during TCP connection establishment + msg.append("Connecting"); + break; + case QSocket::Connected: // when there is an operational connection + msg.append("Conected"); + break; + case QSocket::Closing: // if the socket is closing down, but is not yet closed. + msg.append("Closing"); + break; + } + + if(statusbar) statusbar->message(msg, 5000); + MessageBox(this, "Fejl", msg, TYPE_OK, ICON_ERROR).exec(); + accept(); +} + +#endif /* USE_GUI */ |