summaryrefslogtreecommitdiff
path: root/miav/cprquerydialog.cc
diff options
context:
space:
mode:
Diffstat (limited to 'miav/cprquerydialog.cc')
-rw-r--r--miav/cprquerydialog.cc486
1 files changed, 486 insertions, 0 deletions
diff --git a/miav/cprquerydialog.cc b/miav/cprquerydialog.cc
new file mode 100644
index 0000000..19337a4
--- /dev/null
+++ b/miav/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 */