summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/collapser.cc14
-rw-r--r--client/macrowindow.cc41
-rw-r--r--client/macrowindow.h1
-rw-r--r--client/mainwindow.cc3
-rw-r--r--client/pcpviewer/pcpviewer.cc3
-rw-r--r--client/pracro_dk.ts83
-rw-r--r--client/widgets/altcombobox.cc6
-rw-r--r--client/widgets/altcombobox.h2
-rw-r--r--client/widgets/combobox.cc13
-rw-r--r--client/widgets/widget.cc34
-rw-r--r--client/widgets/widget.h1
-rw-r--r--client/widgets/window.cc16
-rw-r--r--server/src/admin_connection.cc21
-rw-r--r--server/src/admin_export.cc48
-rw-r--r--server/src/admin_export.h4
-rw-r--r--server/src/client_connection.cc15
-rw-r--r--server/src/client_connection.h7
-rw-r--r--server/src/fieldnamescanner.cc6
-rw-r--r--server/src/fieldnamescanner.h4
-rw-r--r--server/src/httpd.cc9
-rw-r--r--server/src/session.cc23
-rw-r--r--server/src/session.h12
-rw-r--r--server/xml/courses/test.xml1
23 files changed, 263 insertions, 104 deletions
diff --git a/client/collapser.cc b/client/collapser.cc
index 599397f..abbe295 100644
--- a/client/collapser.cc
+++ b/client/collapser.cc
@@ -32,8 +32,8 @@
#include "debug.h"
-#define ANIM_TIME 300 // ms
-#define ANIM_INTERVAL 5 // ms
+#define ANIM_TIME 200 // ms
+#define ANIM_INTERVAL 50 // ms
Collapser::Collapser(QWidget *current, QScrollArea *scroll)
{
@@ -110,8 +110,14 @@ void Collapser::anim()
placeholder.setWeight(x);
- int height = (int)((1 - y) * placeholder.fromHeight() +
- y * placeholder.toHeight());
+ // Make sure we don't 'bounce' around when animating to the same height.
+ int height;
+ if(placeholder.fromHeight() == placeholder.toHeight()) {
+ height = placeholder.toHeight();
+ } else {
+ height = (int)((1 - y) * placeholder.fromHeight() +
+ y * placeholder.toHeight());
+ }
setFixedHeight(height);
diff --git a/client/macrowindow.cc b/client/macrowindow.cc
index 44f2797..f924d8c 100644
--- a/client/macrowindow.cc
+++ b/client/macrowindow.cc
@@ -52,6 +52,7 @@ MacroWindow::MacroWindow(NetCom &n, QString course, QString templ,
MacroDrawer *d)
: Collapser(NULL, is_static?NULL:scrollarea), netcom(n)
{
+ this->scrollarea = scrollarea;
drawer = d;
this->is_static = is_static;
@@ -189,11 +190,13 @@ bool MacroWindow::doCommit()
void MacroWindow::commit()
{
doCommit();
+ drawer->setFocus();
}
void MacroWindow::cancel()
{
collapseWrapper();
+ drawer->setFocus();
}
void MacroWindow::expandWrapper()
@@ -271,9 +274,39 @@ void MacroWindow::clear()
lua->clear();
if(mainwidget) {
- delete mainwidget;
- mainwidget = NULL;
drawer->setFocus();
+ mainwidget->deleteLater();
+ mainwidget = NULL;
+ }
+}
+
+QWidgetList getRecursiveWidgetList(QWidget *w)
+{
+ QWidgetList list;
+
+ list.append(w);
+
+ QObjectList objs = w->children();
+ for(int i = 0; i < objs.size(); i++) {
+ if(objs[i]->isWidgetType()) {
+ QWidget *cw = (QWidget*)objs[i];
+ list.append(getRecursiveWidgetList(cw));
+ }
+ }
+
+ return list;
+}
+
+void setTabOrderRecursive(QWidget *w)
+{
+ QWidgetList list = getRecursiveWidgetList(w);
+ QWidget *last = NULL;
+ for(int i = 0; i < list.size(); i++) {
+ QWidget *w = list[i];
+ if((w->focusPolicy() & Qt::TabFocus) != 0) {
+ if(last) QWidget::setTabOrder(last, w);
+ last = w;
+ }
}
}
@@ -292,7 +325,9 @@ void MacroWindow::animated(QWidget *w)
if(is_static) return;
+ setTabOrderRecursive(scrollarea);
+
// Set keyboard focus on the first focusable widget in the macro.
- mainwidget->setKeyboardFocus();
+ mainwidget->setKeyboardFocusRecursive();
}
}
diff --git a/client/macrowindow.h b/client/macrowindow.h
index afc144d..65a0d87 100644
--- a/client/macrowindow.h
+++ b/client/macrowindow.h
@@ -94,6 +94,7 @@ private:
bool is_static;
MacroDrawer *drawer;
+ QWidget *scrollarea;
};
#endif/*__PRACRO_MACROWINDOW_H__*/
diff --git a/client/mainwindow.cc b/client/mainwindow.cc
index 121412e..4cb721f 100644
--- a/client/mainwindow.cc
+++ b/client/mainwindow.cc
@@ -337,6 +337,9 @@ void MainWindow::updateMacros(QDomNodeList &nodes)
break;
}
}
+
+ QVBoxLayout *l = (QVBoxLayout*)central->layout();
+ l->addStretch(1);
}
}
diff --git a/client/pcpviewer/pcpviewer.cc b/client/pcpviewer/pcpviewer.cc
index 5853e0a..ea59edb 100644
--- a/client/pcpviewer/pcpviewer.cc
+++ b/client/pcpviewer/pcpviewer.cc
@@ -42,6 +42,9 @@
PCPViewer::PCPViewer(QString patientid) : praxisd("sarge", 10000)
{
+ setWindowTitle(tr("Pracro Patient View"));
+ setWindowIcon(QIcon(":/icons/icon.png"));
+
this->patientid = patientid;
setLayout(new QVBoxLayout());
diff --git a/client/pracro_dk.ts b/client/pracro_dk.ts
index 9c7fd40..72cda12 100644
--- a/client/pracro_dk.ts
+++ b/client/pracro_dk.ts
@@ -2,6 +2,19 @@
<!DOCTYPE TS>
<TS version="2.0" language="da_DK">
<context>
+ <name>AboutBox</name>
+ <message>
+ <location filename="aboutbox.cc" line="40"/>
+ <source>About Pracro</source>
+ <translation>Om Pracro</translation>
+ </message>
+ <message>
+ <location filename="aboutbox.cc" line="72"/>
+ <source>&lt;h1&gt;Pracro Client&lt;/h1&gt;&lt;h2&gt;v.</source>
+ <translation>&lt;h1&gt;Pracro Klient&lt;/h1&gt;&lt;h2&gt;v.</translation>
+ </message>
+</context>
+<context>
<name>DBWidget</name>
<message>
<source>Write something in the searchfield</source>
@@ -53,43 +66,43 @@ et CPR nummer på 10 cifre.</translation>
<context>
<name>MacroWindow</name>
<message>
- <location filename="macrowindow.cc" line="177"/>
+ <location filename="macrowindow.cc" line="181"/>
<source>Error</source>
<translation>Der er sket en fejl</translation>
</message>
<message>
- <location filename="macrowindow.cc" line="178"/>
+ <location filename="macrowindow.cc" line="182"/>
<source>The macro </source>
<translation>Makroen </translation>
</message>
<message>
- <location filename="macrowindow.cc" line="179"/>
+ <location filename="macrowindow.cc" line="183"/>
<source> was not filled out correctly, please try again.
</source>
<translation> er ikke.udfyldt korrekt. Prøv igen.</translation>
</message>
<message>
- <location filename="macrowindow.cc" line="213"/>
+ <location filename="macrowindow.cc" line="219"/>
<source>Save the macro changes?</source>
<translation>Gem makro ændringer?</translation>
</message>
<message>
- <location filename="macrowindow.cc" line="214"/>
+ <location filename="macrowindow.cc" line="220"/>
<source>you have choosen to close the macro </source>
<translation>Du har valgt at lukke makroen </translation>
</message>
<message>
- <location filename="macrowindow.cc" line="216"/>
+ <location filename="macrowindow.cc" line="222"/>
<source>do you want to save before closing?</source>
<translation>ønsker du at gemme dine ændringer først?</translation>
</message>
<message>
- <location filename="macrowindow.cc" line="241"/>
+ <location filename="macrowindow.cc" line="247"/>
<source>Close first</source>
<translation>Luk først</translation>
</message>
<message>
- <location filename="macrowindow.cc" line="242"/>
+ <location filename="macrowindow.cc" line="248"/>
<source>Close other one first.</source>
<translation>Luk den åbne makro først.</translation>
</message>
@@ -97,26 +110,26 @@ et CPR nummer på 10 cifre.</translation>
<context>
<name>MainWindow</name>
<message>
- <location filename="mainwindow.cc" line="112"/>
+ <location filename="mainwindow.cc" line="124"/>
<source>Close and commit</source>
<translation>Gem i journal</translation>
</message>
<message>
- <location filename="mainwindow.cc" line="115"/>
+ <location filename="mainwindow.cc" line="127"/>
<source>Close no commit</source>
<translation>Gem som kladde</translation>
</message>
<message>
- <location filename="mainwindow.cc" line="150"/>
- <location filename="mainwindow.cc" line="162"/>
- <location filename="mainwindow.cc" line="174"/>
+ <location filename="mainwindow.cc" line="168"/>
+ <location filename="mainwindow.cc" line="180"/>
+ <location filename="mainwindow.cc" line="192"/>
<source>Close first.</source>
<translation>Luk først.</translation>
</message>
<message>
- <location filename="mainwindow.cc" line="151"/>
- <location filename="mainwindow.cc" line="163"/>
- <location filename="mainwindow.cc" line="175"/>
+ <location filename="mainwindow.cc" line="169"/>
+ <location filename="mainwindow.cc" line="181"/>
+ <location filename="mainwindow.cc" line="193"/>
<source>Close open macros first.</source>
<translation>Luk åbne makroer først.</translation>
</message>
@@ -133,14 +146,14 @@ et CPR nummer på 10 cifre.</translation>
<translation type="obsolete">Denne session bliver husket på denne specifikke maskine. For at genåbne på et senere tidspunkt, skal du blot genåbne på samme patient.</translation>
</message>
<message>
- <location filename="mainwindow.cc" line="181"/>
- <location filename="mainwindow.cc" line="203"/>
+ <location filename="mainwindow.cc" line="199"/>
+ <location filename="mainwindow.cc" line="221"/>
<source>Discard</source>
<translation>Kassér</translation>
</message>
<message>
- <location filename="mainwindow.cc" line="182"/>
- <location filename="mainwindow.cc" line="204"/>
+ <location filename="mainwindow.cc" line="200"/>
+ <location filename="mainwindow.cc" line="222"/>
<source>This session will &lt;strong&gt;NOT&lt;/strong&gt; be stored in the journal.&lt;br/&gt;Are you sure you want to continue?</source>
<translation>Dette vil slette alle indtastede data. Denne session vil &lt;strong&gt;IKKE&lt;/strong&gt; blive gemt i journalen hvis du fortsætter. Fortsætter du kan dataene &lt;strong&gt;IKKE&lt;/strong&gt; gendannes.&lt;br/&gt;Er du sikker på du vil fortsætte?</translation>
</message>
@@ -158,6 +171,26 @@ et CPR nummer på 10 cifre.</translation>
<oldsource>Remove form list</oldsource>
<translation>Fjern fra listen</translation>
</message>
+ <message>
+ <location filename="widgets/multilist.cc" line="133"/>
+ <source>Inner widget changed.</source>
+ <translation>Indre widget er ændret.</translation>
+ </message>
+ <message>
+ <location filename="widgets/multilist.cc" line="134"/>
+ <source>The inner widget changed, and you didn&apos;t add it to the list.
+Do you want to continue and discard the change?</source>
+ <translation>Den indre widget har ændret sig men er ikke tilføjet til listen.
+Vil du fortsætte og smide ændringerne væk?</translation>
+ </message>
+</context>
+<context>
+ <name>PCPViewer</name>
+ <message>
+ <location filename="pcpviewer/pcpviewer.cc" line="45"/>
+ <source>Pracro Patient View</source>
+ <translation>Pracro Patient Visning</translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -252,9 +285,17 @@ et CPR nummer på 10 cifre.</translation>
<translation>Ignorér</translation>
</message>
<message>
- <location filename="macro.cc" line="121"/>
+ <location filename="macro.cc" line="122"/>
<source>Depends on: </source>
<translation>Afhænger af: </translation>
</message>
</context>
+<context>
+ <name>Template</name>
+ <message>
+ <location filename="template.cc" line="54"/>
+ <source>Open</source>
+ <translation>Åbn</translation>
+ </message>
+</context>
</TS>
diff --git a/client/widgets/altcombobox.cc b/client/widgets/altcombobox.cc
index 9956fff..082601a 100644
--- a/client/widgets/altcombobox.cc
+++ b/client/widgets/altcombobox.cc
@@ -107,6 +107,12 @@ AltComboBox::~AltComboBox()
{
}
+bool AltComboBox::setKeyboardFocus()
+{
+ combobox->setFocus();
+ return true;
+}
+
QComboBox *AltComboBox::qcombobox()
{
return combobox;
diff --git a/client/widgets/altcombobox.h b/client/widgets/altcombobox.h
index e6a21d7..b0fb61c 100644
--- a/client/widgets/altcombobox.h
+++ b/client/widgets/altcombobox.h
@@ -94,6 +94,8 @@ public:
QComboBox *qcombobox();
+ bool setKeyboardFocus();
+
public slots:
void comboChanged();
void onChildChange();
diff --git a/client/widgets/combobox.cc b/client/widgets/combobox.cc
index eed2d10..935f620 100644
--- a/client/widgets/combobox.cc
+++ b/client/widgets/combobox.cc
@@ -93,6 +93,8 @@ ComboBox::ComboBox(QDomNode &node, MacroWindow *macrowindow)
// Make empty default selection.
combobox->setCurrentIndex(-1);
+ combobox->installEventFilter(this);
+
QDomElement elem = node.toElement();
combotype = SELECT;
@@ -213,15 +215,26 @@ void ComboBox::changed()
emit eventOnChange();
}
+#include <QKeyEvent>
bool ComboBox::eventFilter(QObject *obj, QEvent *event)
{
if(ignoreChangeEvents == true) return false;
+
if(combotype == SELECT) {
if(event->type() == QEvent::MouseButtonRelease) {
if(enabled()) combobox->showPopup();
}
}
+ if(event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = (QKeyEvent*)event;
+ // printf("KEY: %d\n", ke->key());
+ // if(ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down) {
+ if(ke->key() == Qt::Key_Space) {
+ if(enabled()) combobox->showPopup();
+ }
+ }
+
return QObject::eventFilter(obj, event);
}
diff --git a/client/widgets/widget.cc b/client/widgets/widget.cc
index ac90ef2..a57eb78 100644
--- a/client/widgets/widget.cc
+++ b/client/widgets/widget.cc
@@ -313,8 +313,26 @@ bool Widget::hidden()
bool Widget::setKeyboardFocus()
{
- widget->setFocus();
- return true;
+ if((widget->focusPolicy() & Qt::TabFocus) != 0) {
+ widget->setFocus();
+ return true;
+ }
+
+ return false;
+}
+
+bool Widget::setKeyboardFocusRecursive()
+{
+ if(setKeyboardFocus()) return true;
+
+ QVector< Widget* >::iterator i = children.begin();
+ while(i != children.end()) {
+ Widget *w = *i;
+ if(w && w->setKeyboardFocusRecursive()) return true;
+ i++;
+ }
+
+ return false;
}
Widget *Widget::findWidget(QString n, bool deep)
@@ -514,11 +532,13 @@ void Widget::createWidget(QDomNode &xml_node, QLayout *layout)
}
- addChild(widget);
-
- if(layout) layout->addWidget(widget->qwidget());
-
- if(widget && widget->qwidget()) widget->qwidget()->show();
+ if(widget) {
+ addChild(widget);
+ if(widget->qwidget()) {
+ if(layout) layout->addWidget(widget->qwidget());
+ widget->qwidget()->show();
+ }
+ }
}
int wdg_name(lua_State *L)
diff --git a/client/widgets/widget.h b/client/widgets/widget.h
index 4f23790..6199aa4 100644
--- a/client/widgets/widget.h
+++ b/client/widgets/widget.h
@@ -111,6 +111,7 @@ public:
virtual bool hidden();
virtual bool setKeyboardFocus();
+ bool setKeyboardFocusRecursive();
virtual void setForegroundColour(unsigned char red,
unsigned char green,
diff --git a/client/widgets/window.cc b/client/widgets/window.cc
index a305171..7aa6374 100644
--- a/client/widgets/window.cc
+++ b/client/widgets/window.cc
@@ -30,14 +30,9 @@
#include <QWidget>
#include <QIcon>
-//#define DEBUG(fmt...) printf(fmt)
-#define DEBUG(ftm...)
-
Window::Window(QDomNode &node, MacroWindow *macrowindow)
: Widget(node, macrowindow)
{
- DEBUG("window\n");
-
widget = new QWidget(NULL);
widget->setWindowFlags(Qt::WindowContextHelpButtonHint |
@@ -65,21 +60,10 @@ Window::Window(QDomNode &node, MacroWindow *macrowindow)
Window::~Window()
{
- DEBUG("~window\n");
-
//delete widget;
}
bool Window::setKeyboardFocus()
{
- QVector< Widget* >::iterator i = children.begin();
- while(i != children.end()) {
- Widget *w = *i;
- if(w) {
- if(w->setKeyboardFocus()) return true;
- }
- i++;
- }
-
return false;
}
diff --git a/server/src/admin_connection.cc b/server/src/admin_connection.cc
index 0fe5380..fac52a1 100644
--- a/server/src/admin_connection.cc
+++ b/server/src/admin_connection.cc
@@ -27,6 +27,8 @@
*/
#include "admin_connection.h"
+#include <stdlib.h>
+
#include "admin_rc.h"
#include "admin_export.h"
@@ -36,7 +38,11 @@
static std::string admin_sessionunlock(Environment &env, std::string id)
{
- Session *session = env.sessions.session(id);
+ // NOTE: Returned session is returned in locked state!
+ Session *session = NULL;
+ SessionAutounlock l(&session);
+
+ session = env.sessions.lockedSession(id);
if(session) {
if(session->isReadonly()) {
env.sessions.deleteSession(id);
@@ -56,8 +62,10 @@ static std::string admin_listactivesessions(Environment &env)
std::vector<std::string> act = env.sessions.activeSessions();
std::vector<std::string>::iterator i = act.begin();
while(i != act.end()) {
- Session *s = env.sessions.session(*i);
- SessionAutolock lock(*s);
+ // NOTE: Returned session is returned in locked state!
+ Session *s = NULL;
+ SessionAutounlock l(&s);
+ s = env.sessions.lockedSession(*i);
str += "Session " + *i + ": "+s->templ+" on "+s->patientid+" "+
std::string(s->idle()?"[idle]":"[active]")+"\n";
i++;
@@ -118,8 +126,13 @@ bool AdminConnection::handle(const char *data, size_t size)
}
if(uri == "/export" && args.find("template") != args.end()) {
+ time_t from = 0;
+ if(args.find("from") != args.end()) from = atoi(args["from"].c_str());
+
+ time_t to = time(NULL);
+ if(args.find("to") != args.end()) to = atoi(args["to"].c_str());
bool ok;
- std::string res = admin_export(env, args["template"], &ok);
+ std::string res = admin_export(env, args["template"], &ok, from, to);
if(!ok) reply = admin_header(uri) + res + admin_rc("footer");
else {
reply = res;
diff --git a/server/src/admin_export.cc b/server/src/admin_export.cc
index 3ec77d1..0aa290c 100644
--- a/server/src/admin_export.cc
+++ b/server/src/admin_export.cc
@@ -47,8 +47,10 @@ static std::string escape(std::string &str)
std::string::iterator i = str.begin();
while(i != str.end()) {
if(*i == '\"') out += "''";
+ else if(*i == '\n') out += "\342\220\244"; // N/L controlcharacter pictogram
+ else if(*i == '\r') { }
else out += *i;
- i++;
+ i++;
}
out += "\"";
return out;
@@ -59,34 +61,22 @@ public:
File(fieldnames_t &f, pqxx::work &w)
: work(w), fieldnames(f)
{
- // name += ".csf";
- // fp = fopen(name.c_str(), "w");
-
pos["id"] = 0;
pos["patientid"] = 1;
pos["time"] = 2;
pos["template"] = 3;
- //printf("%s\n", n.c_str());
-
size_t idx = 4;
fieldnames_t::iterator i = f.begin();
while(i != f.end()) {
- //printf("%s ", i->c_str());
pos[*i] = idx;
idx++;
i++;
}
- // printf("\n");
output_header();
}
- ~File()
- {
- // if(fp) fclose(fp);
- }
-
void output_header()
{
beginrow();
@@ -144,7 +134,8 @@ private:
};
-static std::string do_export(std::string templ, bool *ok)
+static std::string do_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to)
{
if(Conf::database_backend != "pgsql") {
*ok = false;
@@ -182,7 +173,7 @@ static std::string do_export(std::string templ, bool *ok)
}
}
- templates_t t = scanfieldnames(filter);
+ templates_t t = scanfieldnames(env, filter);
/*
templates_t::iterator ti = t.begin();
while(ti != t.end()) {
@@ -198,10 +189,24 @@ static std::string do_export(std::string templ, bool *ok)
File file(t[templ], work);
+ std::string tostr;
+ std::string fromstr;
{
- pqxx::result result =
- work.exec("SELECT * FROM commits WHERE template='"+templ+"'"
- " AND status='committed' ORDER BY patientid, timestamp;");
+ char buf[32];
+ sprintf(buf, "%d", (int)from);
+ fromstr = buf;
+ sprintf(buf, "%d", (int)to);
+ tostr = buf;
+ }
+
+ {
+ std::string q = "SELECT * FROM commits WHERE template='"+templ+"'"
+ " AND status='committed' AND timestamp>=" +fromstr+
+ " AND timestamp<="+tostr+" ORDER BY patientid, timestamp;";
+
+ DEBUG(export, "QUERY: %s\n", q.c_str());
+
+ pqxx::result result = work.exec(q);
pqxx::result::const_iterator ri = result.begin();
for(unsigned int r = 0; r < result.size(); r++) {
pqxx::result::tuple tuple = result.at(r);
@@ -210,7 +215,7 @@ static std::string do_export(std::string templ, bool *ok)
std::string version = tuple.at(2).c_str();
std::string timestamp = tuple.at(3).c_str();
std::string uid = tuple.at(4).c_str();
- std::string status = tuple.at(5).c_str();
+ // std::string status = tuple.at(5).c_str();
file.beginrow();
file.addcell("id", uid);
@@ -253,10 +258,11 @@ static std::string do_export(std::string templ, bool *ok)
#endif/* WITHOUT_DB */
-std::string admin_export(Environment &env, std::string templ, bool *ok)
+std::string admin_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to)
{
#ifndef WITHOUT_DB
- return do_export(templ, ok);
+ return do_export(env, templ, ok, from, to);
#else
return "No database available";
#endif/* WITHOUT_DB */
diff --git a/server/src/admin_export.h b/server/src/admin_export.h
index 69c7a36..804d373 100644
--- a/server/src/admin_export.h
+++ b/server/src/admin_export.h
@@ -29,9 +29,11 @@
#define __PRACRO_ADMIN_EXPORT_H__
#include <string>
+#include <time.h>
#include "environment.h"
-std::string admin_export(Environment &env, std::string templ, bool *ok);
+std::string admin_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to);
#endif/*__PRACRO_ADMIN_EXPORT_H__*/
diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc
index fe55efc..075dc46 100644
--- a/server/src/client_connection.cc
+++ b/server/src/client_connection.cc
@@ -44,7 +44,7 @@ static std::string error_box(std::string message)
static bool did_commit = false;
#endif
-ClientConnection::ClientConnection(Environment &e, headers_t &headers,
+ClientConnection::ClientConnection(Environment &e, headers_t headers,
headers_t args, std::string uri)
: env(e), parser(&transaction)
{
@@ -154,17 +154,22 @@ bool ClientConnection::handle(const char *data, size_t size)
}
Session *session = NULL;
+ SessionAutounlock l(&session);
+
try {
if(sessionid == "") {
// Create new session
- session = env.sessions.newSession(patientid, templ);
+ // NOTE: New session is returned in locked state!
+ session = env.sessions.newLockedSession(patientid, templ);
} else {
// Attach to old session
- session = env.sessions.session(sessionid);
+ // NOTE: Returned session is returned in locked state!
+ session = env.sessions.lockedSession(sessionid);
// Session didn't exist - create a new one anyway.
if(session == NULL) {
- session = env.sessions.newSession(patientid, templ);
+ // NOTE: New session is returned in locked state!
+ session = env.sessions.newLockedSession(patientid, templ);
}
}
} catch(Sessions::SessionAlreadyActive &e) {
@@ -201,7 +206,7 @@ bool ClientConnection::handle(const char *data, size_t size)
parser_complete = true;
{
- SessionAutolock lock(*session);
+ //SessionAutolock lock(session);
response = handleTransaction(request, transaction, env, *session);
}
diff --git a/server/src/client_connection.h b/server/src/client_connection.h
index b811b7f..e64dcad 100644
--- a/server/src/client_connection.h
+++ b/server/src/client_connection.h
@@ -40,7 +40,12 @@ class Session;
class ClientConnection : public Connection {
public:
- ClientConnection(Environment &e, headers_t &headers,
+ /**
+ * URI: course/template/macro
+ * Params: petientid, sessionid and statechange (commit, nocommit or discard)
+ * Headers are currently not used.
+ */
+ ClientConnection(Environment &e, headers_t headers,
headers_t args, std::string uri);
~ClientConnection();
diff --git a/server/src/fieldnamescanner.cc b/server/src/fieldnamescanner.cc
index 5418bb4..ba3b61f 100644
--- a/server/src/fieldnamescanner.cc
+++ b/server/src/fieldnamescanner.cc
@@ -58,12 +58,12 @@ fieldnames_t getFields(Widget &widget)
return fieldnames;
}
-templates_t scanfieldnames(std::set<std::string> &filter)
+templates_t scanfieldnames(Environment &env, std::set<std::string> &filter)
{
templates_t templates;
// TemplateList templatelist(Conf::xml_basedir + "/templates");
- MacroList macrolist(Conf::xml_basedir + "/macros");
+ // MacroList macrolist(Conf::xml_basedir + "/macros");
// Iterate templates:
std::vector<std::string> templatefiles = getTemplates();
@@ -83,7 +83,7 @@ templates_t scanfieldnames(std::set<std::string> &filter)
if(ms->isHeader == false) {
std::string macro = ms->name;
DEBUG(scanner, "Name '%s'\n", macro.c_str());
- std::string macrofile = macrolist.getLatestVersion(macro);
+ std::string macrofile = env.macrolist.getLatestVersion(macro);
DEBUG(scanner, "File '%s'\n", macrofile.c_str());
// Iterate fields:
diff --git a/server/src/fieldnamescanner.h b/server/src/fieldnamescanner.h
index c766ba1..6201db7 100644
--- a/server/src/fieldnamescanner.h
+++ b/server/src/fieldnamescanner.h
@@ -33,12 +33,14 @@
#include <string>
#include <set>
+#include "environment.h"
+
typedef std::string fieldname_t;
typedef std::vector< fieldname_t > fieldnames_t;
typedef std::string template_name_t;
typedef std::map< template_name_t, fieldnames_t > templates_t;
-templates_t scanfieldnames(std::set<std::string> &filter);
+templates_t scanfieldnames(Environment &env, std::set<std::string> &filter);
#endif/*__PRACRO_FIELDNAMESCANNER_H__*/
diff --git a/server/src/httpd.cc b/server/src/httpd.cc
index f7ad7f4..1c0575a 100644
--- a/server/src/httpd.cc
+++ b/server/src/httpd.cc
@@ -68,6 +68,11 @@ static int request_handler(void *cls,
unsigned int *data_size,
void **con_cls)
{
+ DEBUG(httpd, "request_handler: cls(%p) con(%p) url(%s) method(%s)"
+ " version(%s) *con_cls(%p)\n",
+ cls, con, url, method, version, *con_cls);
+ DEBUG(httpd, "request_handler: *data_size(%u) data:[%s]\n", *data_size, data);
+
int ret = MHD_YES;
Httpd *httpd = (Httpd*)cls;
@@ -176,7 +181,7 @@ Httpd::~Httpd()
void Httpd::listen(unsigned short int port,
unsigned int cn_limit, unsigned int cn_timeout)
{
- int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY;
+ int flags = MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION;
d = MHD_start_daemon(flags, port, NULL, NULL,
request_handler, this,
@@ -196,7 +201,7 @@ void Httpd::listen_ssl(unsigned short int port,
std::string key, std::string cert,
unsigned int cn_limit, unsigned int cn_timeout)
{
- int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL;
+ int flags = MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL;
d_ssl = MHD_start_daemon(flags, port, NULL, NULL,
request_handler, this,
diff --git a/server/src/session.cc b/server/src/session.cc
index 8071d45..fcd138a 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -195,7 +195,7 @@ static bool fexists(const std::string &f)
return ret;
}
-Session *Sessions::newSession(std::string patientid, std::string templ)
+Session *Sessions::newLockedSession(std::string patientid, std::string templ)
throw(SessionAlreadyActive)
{
MutexAutolock lock(mutex);
@@ -209,6 +209,7 @@ Session *Sessions::newSession(std::string patientid, std::string templ)
DEBUG(session, "Patient/template matched session is already active.");
throw SessionAlreadyActive(session->id());
}
+ session->lock();
return session;
}
@@ -224,27 +225,33 @@ Session *Sessions::newSession(std::string patientid, std::string templ)
DEBUG(session, "Looked up session by id is already active.");
throw SessionAlreadyActive(session->id());
}
+ session->lock();
return session;
}
}
Session *session = new Session(env, "", patientid, templ);
sessions[session->id()] = session;
+ session->lock();
return session;
}
-Session *Sessions::session(std::string sessionid)
+Session *Sessions::lockedSession(std::string sessionid)
{
MutexAutolock lock(mutex);
- if(sessions.find(sessionid) != sessions.end())
- return sessions[sessionid];
+ if(sessions.find(sessionid) != sessions.end()) {
+ Session *s = sessions[sessionid];
+ s->lock();
+ return s;
+ }
std::string filename = getSessionFilename(Conf::session_path, sessionid);
if(fexists(filename)) {
SessionSerialiser ser(env, Conf::session_path);
Session *s = ser.load(sessionid);
sessions[s->id()] = s;
+ s->lock();
return s;
}
@@ -311,15 +318,15 @@ std::vector<std::string> Sessions::activeSessions()
return act;
}
-SessionAutolock::SessionAutolock(Session &s)
+SessionAutounlock::SessionAutounlock(Session **s)
: session(s)
{
- session.lock();
+ // session->lock();
}
-SessionAutolock::~SessionAutolock()
+SessionAutounlock::~SessionAutounlock()
{
- session.unlock();
+ if(*session) (*session)->unlock();
}
#ifdef TEST_SESSION
diff --git a/server/src/session.h b/server/src/session.h
index b5c31d7..4d1ed12 100644
--- a/server/src/session.h
+++ b/server/src/session.h
@@ -95,14 +95,14 @@ public:
* Create a new session, with a unique id. Insert it into the session list,
* and return its pointer.
*/
- Session *newSession(std::string patientid, std::string templ)
+ Session *newLockedSession(std::string patientid, std::string templ)
throw(SessionAlreadyActive);
/**
* Lookup session in session list. Returns the session or NULL if no session
* exists with that sessionid.
*/
- Session *session(std::string sessionid);
+ Session *lockedSession(std::string sessionid);
/**
* Remove session from the session list and return its pointer. It is up to
@@ -136,13 +136,13 @@ private:
Mutex mutex;
};
-class SessionAutolock {
+class SessionAutounlock {
public:
- SessionAutolock(Session &session);
- ~SessionAutolock();
+ SessionAutounlock(Session **session);
+ ~SessionAutounlock();
private:
- Session &session;
+ Session **session;
};
#endif/*__PRACRO_SESSION_H__*/
diff --git a/server/xml/courses/test.xml b/server/xml/courses/test.xml
index 4594409..9dabdb9 100644
--- a/server/xml/courses/test.xml
+++ b/server/xml/courses/test.xml
@@ -1,5 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<course name="test" title="Test Course" version="1.0">
<template name="test"/>
- <template name="test2"/>
</course>