Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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