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