Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
QmitkGnuplotWidget.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "QmitkGnuplotWidget.h"
18 #include <QClipboard>
19 #include <QContextMenuEvent>
20 #include <QMenu>
21 #include <ui_QmitkGnuplotWidget.h>
22 
24  : QWidget(parent),
25  m_Ui(new Ui::QmitkGnuplotWidget),
26  m_ContextMenu(nullptr),
27  m_CopyPlotAction(nullptr),
28  m_CopyScriptAction(nullptr),
29  m_Process(new QProcess(this))
30 {
31  m_Ui->setupUi(this);
32 
33  connect(
34  m_Process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(OnProcessStateChanged(QProcess::ProcessState)));
35  connect(m_Process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(OnProcessError(QProcess::ProcessError)));
36  connect(
37  m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(OnProcessFinished(int, QProcess::ExitStatus)));
38 
39  this->CreateContextMenu();
40 }
41 
43 {
44 }
45 
46 void QmitkGnuplotWidget::CreateContextMenu()
47 {
48  m_CopyPlotAction = new QAction("Copy &Plot", this);
49  connect(m_CopyPlotAction, SIGNAL(triggered()), this, SLOT(OnCopyPlot()));
50 
51  m_CopyScriptAction = new QAction("Copy &Script", this);
52  connect(m_CopyScriptAction, SIGNAL(triggered()), this, SLOT(OnCopyScript()));
53 
54  m_ContextMenu = new QMenu(this);
55 
56  m_ContextMenu->addActions(QList<QAction *>() << m_CopyPlotAction << m_CopyScriptAction);
57 }
58 
59 void QmitkGnuplotWidget::contextMenuEvent(QContextMenuEvent *event)
60 {
61  const QPixmap *plot = m_Ui->label->pixmap();
62 
63  m_CopyPlotAction->setEnabled(plot != nullptr && !plot->isNull());
64  m_CopyScriptAction->setEnabled(!m_Commands.empty());
65 
66  m_ContextMenu->popup(event->globalPos());
67 
68  event->accept();
69 }
70 
71 void QmitkGnuplotWidget::OnCopyPlot()
72 {
73  const QPixmap *plot = m_Ui->label->pixmap();
74 
75  if (plot != nullptr && !plot->isNull())
76  QApplication::clipboard()->setPixmap(*plot);
77 }
78 
79 void QmitkGnuplotWidget::OnCopyScript()
80 {
81  if (m_Commands.empty())
82  return;
83 
84  QString script = this->CreateSetTermCommand();
85 
86  Q_FOREACH (const QString &command, m_Commands)
87  {
88  script += command + "\n";
89  }
90 
91  QApplication::clipboard()->setText(script);
92 }
93 
94 void QmitkGnuplotWidget::resizeEvent(QResizeEvent *)
95 {
96  m_ModifiedTime.Modified();
97 
98  if (m_Process->isOpen() || m_Commands.isEmpty() || m_GnuplotPath.isEmpty())
99  return;
100 
101  this->Update();
102 }
103 
105 {
106  return m_GnuplotPath;
107 }
108 
109 void QmitkGnuplotWidget::SetGnuplotPath(const QString &path)
110 {
111  m_GnuplotPath = path;
112  m_ModifiedTime.Modified();
113 }
114 
116 {
117  return m_Commands;
118 }
119 
120 void QmitkGnuplotWidget::SetCommands(const QStringList &commands)
121 {
122  m_Commands = commands;
123  m_ModifiedTime.Modified();
124 }
125 
127 {
128  if (m_UpdateTime < m_ModifiedTime)
129  m_Process->start(m_GnuplotPath, QStringList() << "-");
130 }
131 
133 {
134  return QSize(400, 300);
135 }
136 
137 QString QmitkGnuplotWidget::CreateSetTermCommand() const
138 {
139  return QString("set term pngcairo size %1,%2 enhanced font '%3,%4'\n")
140  .arg(this->width())
141  .arg(this->height())
142  .arg(this->font().family())
143  .arg(this->font().pointSize());
144 }
145 
146 void QmitkGnuplotWidget::OnProcessStateChanged(QProcess::ProcessState state)
147 {
148  if (state == QProcess::Running)
149  {
150  m_UpdateTime = m_ModifiedTime;
151 
152  m_Process->write(this->CreateSetTermCommand().toLatin1());
153 
154  Q_FOREACH (const QString &command, m_Commands)
155  {
156  m_Process->write(QString("%1\n").arg(command).toLatin1());
157  }
158 
159  m_Process->write("exit\n");
160  m_Process->closeWriteChannel();
161  }
162 }
163 
164 void QmitkGnuplotWidget::OnProcessError(QProcess::ProcessError error)
165 {
166  switch (error)
167  {
168  case QProcess::FailedToStart:
169  m_Ui->label->setText("Gnuplot failed to start!");
170  break;
171 
172  case QProcess::Crashed:
173  m_Ui->label->setText("Gnuplot crashed!");
174  break;
175 
176  case QProcess::Timedout:
177  m_Ui->label->setText("Gnuplot timed out!");
178  break;
179 
180  case QProcess::WriteError:
181  m_Ui->label->setText("Could not write to gnuplot!");
182  break;
183 
184  case QProcess::ReadError:
185  m_Ui->label->setText("Could not read from gnuplot!");
186  break;
187 
188  default:
189  m_Ui->label->setText("An unknown error occurred!");
190  break;
191  }
192 }
193 
194 void QmitkGnuplotWidget::OnProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
195 {
196  bool needUpdate = false;
197 
198  if (exitStatus != QProcess::CrashExit)
199  {
200  if (exitCode == 0)
201  {
202  if (m_UpdateTime < m_ModifiedTime)
203  {
204  needUpdate = true;
205  }
206  else
207  {
208  m_Ui->label->setPixmap(QPixmap::fromImage(QImage::fromData(m_Process->readAllStandardOutput(), "PNG")));
209  }
210  }
211  else
212  {
213  m_Ui->label->setText(QString("Gnuplot exit code: %1!").arg(exitCode));
214  }
215  }
216 
217  m_Process->close();
218 
219  if (needUpdate)
220  this->Update();
221 }
QString GetGnuplotPath() const
void SetCommands(const QStringList &commands)
void contextMenuEvent(QContextMenuEvent *event) override
QmitkGnuplotWidget(QWidget *parent=nullptr)
void SetGnuplotPath(const QString &path)
void resizeEvent(QResizeEvent *event) override
QSize sizeHint() const override
QStringList GetCommands() const