Переглянути джерело

Added a timer which keeps count of the session timeout.
This timer emits two signals: sessionTimedOut and sessionAboutToBeTimedOut.

Daniel Knorr 10 роки тому
батько
коміт
5769564693

+ 38 - 0
Applications/ctkXnatTreeBrowser/ctkXnatTreeBrowserMainWindow.cpp

@@ -36,6 +36,10 @@
 #include "ctkXnatReconstruction.h"
 #include "ctkXnatReconstruction.h"
 #include "ctkXnatReconstructionFolder.h"
 #include "ctkXnatReconstructionFolder.h"
 
 
+#include <QMessageBox>
+#include <QDateTime>
+#include <QTimer>
+
 ctkXnatTreeBrowserMainWindow::ctkXnatTreeBrowserMainWindow(QWidget *parent) :
 ctkXnatTreeBrowserMainWindow::ctkXnatTreeBrowserMainWindow(QWidget *parent) :
   QMainWindow(parent),
   QMainWindow(parent),
   ui(new Ui::ctkXnatTreeBrowserMainWindow),
   ui(new Ui::ctkXnatTreeBrowserMainWindow),
@@ -46,6 +50,7 @@ ctkXnatTreeBrowserMainWindow::ctkXnatTreeBrowserMainWindow(QWidget *parent) :
 
 
   ui->treeView->setModel(m_TreeModel);
   ui->treeView->setModel(m_TreeModel);
   ui->downloadLabel->hide();
   ui->downloadLabel->hide();
+  ui->treeView->setHeaderHidden(true);
 
 
   this->connect(ui->loginButton, SIGNAL(clicked()), SLOT(loginButtonPushed()));
   this->connect(ui->loginButton, SIGNAL(clicked()), SLOT(loginButtonPushed()));
   this->connect(ui->treeView, SIGNAL(clicked(const QModelIndex&)), SLOT(itemSelected(const QModelIndex&)));
   this->connect(ui->treeView, SIGNAL(clicked(const QModelIndex&)), SLOT(itemSelected(const QModelIndex&)));
@@ -86,6 +91,8 @@ void ctkXnatTreeBrowserMainWindow::loginButtonPushed()
       {
       {
         ui->loginButton->setText("Logout");
         ui->loginButton->setText("Logout");
         ui->loginLabel->setText(QString("Connected: %1").arg(m_Session->url().toString()));
         ui->loginLabel->setText(QString("Connected: %1").arg(m_Session->url().toString()));
+        this->connect(m_Session, SIGNAL(sessionTimedOut()), this, SLOT(sessionTimedOutMsg()));
+        this->connect(m_Session, SIGNAL(sessionAboutToBeTimedOut()), this, SLOT(sessionTimesOutSoonMsg()));
 
 
         ctkXnatDataModel* dataModel = m_Session->dataModel();
         ctkXnatDataModel* dataModel = m_Session->dataModel();
         m_TreeModel->addDataModel(dataModel);
         m_TreeModel->addDataModel(dataModel);
@@ -122,3 +129,34 @@ void ctkXnatTreeBrowserMainWindow::downloadButtonClicked()
     m_TreeModel->downloadFile(index, fileName);
     m_TreeModel->downloadFile(index, fileName);
   }
   }
 }
 }
+
+void ctkXnatTreeBrowserMainWindow::sessionTimedOutMsg()
+{
+  ctkXnatDataModel* dataModel = m_Session->dataModel();
+  m_TreeModel->removeDataModel(dataModel);
+  ui->treeView->reset();
+  delete m_Session;
+  m_Session = 0;
+  ui->loginButton->setText("Login");
+  ui->loginLabel->setText("Disconnected");
+  ui->downloadLabel->hide();
+  QMessageBox::warning(this, "Session Timeout", "The session timed out.");
+}
+
+void ctkXnatTreeBrowserMainWindow::sessionTimesOutSoonMsg()
+{
+  QMessageBox msgBox;
+  msgBox.setIcon(QMessageBox::Warning);
+  msgBox.setWindowTitle("Session Timeout Soon");
+  msgBox.setText("The session will time out in 1 minute.\nDo you want to renew the session?");
+  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+  msgBox.setDefaultButton(QMessageBox::No);
+  msgBox.show();
+  QTimer* timer = new QTimer(this);
+  timer->start(60000);
+  this->connect(timer, SIGNAL(timeout()), &msgBox, SLOT(reject()));
+  if (msgBox.exec() == QMessageBox::Yes){
+    m_Session->renew();
+  }
+  timer->stop();
+}

+ 2 - 0
Applications/ctkXnatTreeBrowser/ctkXnatTreeBrowserMainWindow.h

@@ -46,6 +46,8 @@ private Q_SLOTS:
   void loginButtonPushed();
   void loginButtonPushed();
   void itemSelected(const QModelIndex&);
   void itemSelected(const QModelIndex&);
   void downloadButtonClicked();
   void downloadButtonClicked();
+  void sessionTimedOutMsg();
+  void sessionTimesOutSoonMsg();
 
 
 private:
 private:
   Ui::ctkXnatTreeBrowserMainWindow* ui;
   Ui::ctkXnatTreeBrowserMainWindow* ui;

+ 38 - 1
Libs/XNAT/Core/ctkXnatSession.cpp

@@ -36,6 +36,7 @@
 #include "ctkXnatSubject.h"
 #include "ctkXnatSubject.h"
 
 
 #include <QDateTime>
 #include <QDateTime>
+#include <QTimer>
 #include <QDebug>
 #include <QDebug>
 #include <QScopedPointer>
 #include <QScopedPointer>
 #include <QStringBuilder>
 #include <QStringBuilder>
@@ -66,6 +67,14 @@ public:
 
 
   ctkXnatSession* q;
   ctkXnatSession* q;
 
 
+  QTimer* timer;
+
+  // The time in milliseconds untill the signal sessionAboutToBeTimedOut gets emitted
+  int timeToSessionTimesOutSoon = 840000;
+
+  // The time in milliseconds untill the signal sessionTimedOut gets emitted
+  int timeToSessionTimedOut = 60000;
+
   ctkXnatSessionPrivate(const ctkXnatLoginProfile& loginProfile, ctkXnatSession* q);
   ctkXnatSessionPrivate(const ctkXnatLoginProfile& loginProfile, ctkXnatSession* q);
   ~ctkXnatSessionPrivate();
   ~ctkXnatSessionPrivate();
 
 
@@ -88,6 +97,7 @@ ctkXnatSessionPrivate::ctkXnatSessionPrivate(const ctkXnatLoginProfile& loginPro
   : loginProfile(loginProfile)
   : loginProfile(loginProfile)
   , xnat(new ctkXnatAPI())
   , xnat(new ctkXnatAPI())
   , q(q)
   , q(q)
+  , timer(new QTimer(q))
 {
 {
   // TODO This is a workaround for connecting to sites with self-signed
   // TODO This is a workaround for connecting to sites with self-signed
   // certificate. Should be replaced with something more clever.
   // certificate. Should be replaced with something more clever.
@@ -210,6 +220,7 @@ QDateTime ctkXnatSessionPrivate::updateExpirationDate(qRestResult* restResult)
           timeSpan.chop(1);
           timeSpan.chop(1);
           expirationDate = expirationDate.addMSecs(timeSpan.toLong());
           expirationDate = expirationDate.addMSecs(timeSpan.toLong());
           sessionProperties[SESSION_EXPIRATION_DATE] = expirationDate.toString(Qt::ISODate);
           sessionProperties[SESSION_EXPIRATION_DATE] = expirationDate.toString(Qt::ISODate);
+          this->timer->start(this->timeToSessionTimesOutSoon);
           emit q->sessionRenewed(expirationDate);
           emit q->sessionRenewed(expirationDate);
         }
         }
       }
       }
@@ -353,6 +364,8 @@ void ctkXnatSession::open()
   QScopedPointer<qRestResult> restResult(d->xnat->takeResult(uuid));
   QScopedPointer<qRestResult> restResult(d->xnat->takeResult(uuid));
   if (restResult)
   if (restResult)
   {
   {
+    QObject::connect(d->timer, SIGNAL(timeout()), this, SLOT(emitSessionTimeOut()));
+
     QString sessionId = restResult->result()["content"].toString();
     QString sessionId = restResult->result()["content"].toString();
     d->sessionId = sessionId;
     d->sessionId = sessionId;
     d->setDefaultHttpHeaders();
     d->setDefaultHttpHeaders();
@@ -480,6 +493,7 @@ QUuid ctkXnatSession::httpGet(const QString& resource, const ctkXnatSession::Url
 {
 {
   Q_D(ctkXnatSession);
   Q_D(ctkXnatSession);
   d->checkSession();
   d->checkSession();
+  d->timer->start(d->timeToSessionTimesOutSoon);
   return d->xnat->get(resource, parameters, rawHeaders);
   return d->xnat->get(resource, parameters, rawHeaders);
 }
 }
 
 
@@ -494,6 +508,7 @@ QList<ctkXnatObject*> ctkXnatSession::httpResults(const QUuid& uuid, const QStri
   {
   {
     d->throwXnatException("Http request failed.");
     d->throwXnatException("Http request failed.");
   }
   }
+  d->timer->start(d->timeToSessionTimesOutSoon);
   return d->results(restResult.data(), schemaType);
   return d->results(restResult.data(), schemaType);
 }
 }
 
 
@@ -524,7 +539,7 @@ bool ctkXnatSession::exists(const ctkXnatObject* object)
 
 
   QString query = object->resourceUri();
   QString query = object->resourceUri();
   bool success = d->xnat->sync(d->xnat->get(query));
   bool success = d->xnat->sync(d->xnat->get(query));
-
+  d->timer->start(d->timeToSessionTimesOutSoon);
   return success;
   return success;
 }
 }
 
 
@@ -533,6 +548,7 @@ const QMap<QByteArray, QByteArray> ctkXnatSession::httpHeadSync(const QUuid &uui
 {
 {
   Q_D(ctkXnatSession);
   Q_D(ctkXnatSession);
   QScopedPointer<qRestResult> result (d->xnat->takeResult(uuid));
   QScopedPointer<qRestResult> result (d->xnat->takeResult(uuid));
+  d->timer->start(d->timeToSessionTimesOutSoon);
   if (result == NULL)
   if (result == NULL)
   {
   {
     d->throwXnatException("Sending HEAD request failed.");
     d->throwXnatException("Sending HEAD request failed.");
@@ -545,6 +561,7 @@ QUuid ctkXnatSession::httpHead(const QString& resourceUri)
 {
 {
   Q_D(ctkXnatSession);
   Q_D(ctkXnatSession);
   QUuid queryId = d->xnat->head(resourceUri);
   QUuid queryId = d->xnat->head(resourceUri);
+  d->timer->start(d->timeToSessionTimesOutSoon);
   return queryId;
   return queryId;
 }
 }
 
 
@@ -566,6 +583,7 @@ void ctkXnatSession::save(ctkXnatObject* object)
   qDebug() << "ctkXnatSession::save() query:" << query;
   qDebug() << "ctkXnatSession::save() query:" << query;
   QUuid queryId = d->xnat->put(query);
   QUuid queryId = d->xnat->put(query);
   qRestResult* result = d->xnat->takeResult(queryId);
   qRestResult* result = d->xnat->takeResult(queryId);
+  d->timer->start(d->timeToSessionTimesOutSoon);
 
 
   if (!result || !result->error().isNull())
   if (!result || !result->error().isNull())
   {
   {
@@ -590,6 +608,7 @@ void ctkXnatSession::remove(ctkXnatObject* object)
 
 
   QString query = object->resourceUri();
   QString query = object->resourceUri();
   bool success = d->xnat->sync(d->xnat->del(query));
   bool success = d->xnat->sync(d->xnat->del(query));
+  d->timer->start(d->timeToSessionTimesOutSoon);
 
 
   if (!success)
   if (!success)
   {
   {
@@ -607,6 +626,7 @@ void ctkXnatSession::download(const QString& fileName,
 
 
   QUuid queryId = d->xnat->download(fileName, resource, parameters, rawHeaders);
   QUuid queryId = d->xnat->download(fileName, resource, parameters, rawHeaders);
   d->xnat->sync(queryId);
   d->xnat->sync(queryId);
+  d->timer->start(d->timeToSessionTimesOutSoon);
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
@@ -615,3 +635,20 @@ void ctkXnatSession::processResult(QUuid queryId, QList<QVariantMap> parameters)
   Q_UNUSED(queryId)
   Q_UNUSED(queryId)
   Q_UNUSED(parameters)
   Q_UNUSED(parameters)
 }
 }
+
+//----------------------------------------------------------------------------
+void ctkXnatSession::emitSessionTimeOut()
+{
+  Q_D(ctkXnatSession);
+
+  if (d->timer->interval() == d->timeToSessionTimesOutSoon)
+  {
+    d->timer->start(d->timeToSessionTimedOut);
+    emit sessionAboutToBeTimedOut();
+  }
+  else if (d->timer->interval() == d->timeToSessionTimedOut)
+  {
+    d->timer->stop();
+    emit sessionTimedOut();
+  }
+}

+ 11 - 0
Libs/XNAT/Core/ctkXnatSession.h

@@ -229,6 +229,16 @@ public:
    */
    */
   Q_SIGNAL void sessionAboutToBeClosed();
   Q_SIGNAL void sessionAboutToBeClosed();
 
 
+  /**
+   * @brief Signals that the session is timed out.
+   */
+  Q_SIGNAL void sessionTimedOut();
+
+  /**
+   * @brief Signals that the session will time out in one minute.
+   */
+  Q_SIGNAL void sessionAboutToBeTimedOut();
+
 public slots:
 public slots:
   void processResult(QUuid queryId, QList<QVariantMap> parameters);
   void processResult(QUuid queryId, QList<QVariantMap> parameters);
   void progress(QUuid queryId, double progress);
   void progress(QUuid queryId, double progress);
@@ -239,6 +249,7 @@ protected:
 private:
 private:
   Q_DECLARE_PRIVATE(ctkXnatSession)
   Q_DECLARE_PRIVATE(ctkXnatSession)
   Q_DISABLE_COPY(ctkXnatSession)
   Q_DISABLE_COPY(ctkXnatSession)
+  Q_SLOT void emitSessionTimeOut();
 };
 };
 
 
 #endif
 #endif