Selaa lähdekoodia

Add screenshot dialog

Screenshot dialog provide an easy to grab the content of widgets
and save it into a file.
Jean-Christophe Fillion-Robin 14 vuotta sitten
vanhempi
commit
4e3979c230

+ 6 - 0
Libs/Widgets/CMakeLists.txt

@@ -58,6 +58,9 @@ SET(KIT_SRCS
   ctkRangeSlider.h
   ctkRangeWidget.cpp
   ctkRangeWidget.h
+  ctkScreenshotDialog.cpp
+  ctkScreenshotDialog.h
+  ctkScreenshotDialog_p.h
   ctkSettings.cpp
   ctkSettings.h
   ctkSliderWidget.cpp
@@ -121,6 +124,8 @@ SET(KIT_MOC_SRCS
   ctkMenuButton.h
   ctkRangeSlider.h
   ctkRangeWidget.h
+  ctkScreenshotDialog.h
+  ctkScreenshotDialog_p.h
   ctkSettings.h
   ctkSliderWidget.h
   ctkTestApplication.h
@@ -146,6 +151,7 @@ SET(KIT_UI_FORMS
   Resources/UI/ctkAddRemoveComboBox.ui
   Resources/UI/ctkRangeWidget.ui
   Resources/UI/ctkDateRangeWidget.ui
+  Resources/UI/ctkScreenshotDialog.ui
   Resources/UI/ctkSliderWidget.ui
   Resources/UI/ctkWorkflowGroupBox.ui
   )

+ 222 - 0
Libs/Widgets/Resources/UI/ctkScreenshotDialog.ui

@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ctkScreenshotDialog</class>
+ <widget class="QDialog" name="ctkScreenshotDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>725</width>
+    <height>304</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Screen Capture Options</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="OptionGroupBox">
+     <property name="enabled">
+      <bool>false</bool>
+     </property>
+     <property name="title">
+      <string>Options</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <item row="0" column="0">
+       <widget class="QLabel" name="DirectoryLabel">
+        <property name="text">
+         <string>Folder:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="ctkDirectoryButton" name="DirectoryButton">
+        <property name="toolTip">
+         <string>Select a directory in which screen captures will be saved.</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="ImageNameLabel">
+        <property name="text">
+         <string>Image name:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLineEdit" name="ImageNameLineEdit">
+        <property name="toolTip">
+         <string>Type in a base-name for the image file, or use the default provided.</string>
+        </property>
+        <property name="text">
+         <string>Untitled</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="ImageVersionNumberLabel">
+        <property name="text">
+         <string>Image version number:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QSpinBox" name="ImageVersionNumberSpinBox"/>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="ScaleFactorLabel">
+        <property name="text">
+         <string>Scale factor:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QDoubleSpinBox" name="ScaleFactorSpinBox">
+        <property name="toolTip">
+         <string>Select an integer scale factor (between 0.5 and 5) for the image file, e.g. a value of &quot;2&quot; will save an image twice the size.</string>
+        </property>
+        <property name="decimals">
+         <number>1</number>
+        </property>
+        <property name="minimum">
+         <double>0.500000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>5.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.500000000000000</double>
+        </property>
+        <property name="value">
+         <double>1.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="OverwriteLabel">
+        <property name="text">
+         <string>Overwrite:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QCheckBox" name="OverwriteCheckBox">
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="0">
+       <widget class="QLabel" name="DelayLabel">
+        <property name="text">
+         <string>Screenshot delay:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QSpinBox" name="DelaySpinBox">
+        <property name="suffix">
+         <string> s</string>
+        </property>
+        <property name="maximum">
+         <number>60</number>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>5</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="CountDownLabel">
+       <property name="text">
+        <string>0 s</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="ImageFullNameLabel">
+       <property name="text">
+        <string>Untitled_0.png</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QDialogButtonBox" name="ButtonBox">
+       <property name="standardButtons">
+        <set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ctkDirectoryButton</class>
+   <extends>QWidget</extends>
+   <header>ctkDirectoryButton.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>ButtonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ctkScreenshotDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>651</x>
+     <y>221</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>674</x>
+     <y>188</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

+ 244 - 0
Libs/Widgets/ctkScreenshotDialog.cpp

@@ -0,0 +1,244 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QPushButton>
+#include <QMessageBox>
+
+// CTK includes
+#include "ctkScreenshotDialog.h"
+#include "ctkScreenshotDialog_p.h"
+
+//-----------------------------------------------------------------------------
+// ctkScreenshotDialogPrivate methods
+
+//-----------------------------------------------------------------------------
+ctkScreenshotDialogPrivate::ctkScreenshotDialogPrivate(ctkScreenshotDialog& object)
+  : QObject(&object), q_ptr(&object)
+{
+  this->CaptureButton = 0;
+  this->CountDownValue = 0;
+}
+
+//-----------------------------------------------------------------------------
+ctkScreenshotDialogPrivate::~ctkScreenshotDialogPrivate()
+{
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::init()
+{
+  Q_Q(ctkScreenshotDialog);
+  this->setupUi(q);
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::setupUi(QDialog * widget)
+{
+  Q_Q(ctkScreenshotDialog);
+
+  this->Ui_ctkScreenshotDialog::setupUi(widget);
+
+  QPushButton * okButton = this->ButtonBox->button(QDialogButtonBox::Ok);
+  Q_ASSERT(okButton);
+
+  // Update OK button text
+  okButton->setText("Capture");
+
+  connect(okButton, SIGNAL(clicked()), SLOT(onCaptureButtonClicked()));
+  connect(this->ImageNameLineEdit, SIGNAL(textChanged(QString)), SLOT(updateFullNameLabel()));
+  connect(this->ImageVersionNumberSpinBox, SIGNAL(valueChanged(int)), SLOT(updateFullNameLabel()));
+  connect(this->DelaySpinBox, SIGNAL(valueChanged(int)), SLOT(resetCountDownValue()));
+  connect(&this->CountDownTimer, SIGNAL(timeout()), SLOT(updateCountDown()));
+
+  this->CaptureButton = okButton;
+
+  q->setWidgetToGrab(0);
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::setWaitingForScreenshot(bool waiting)
+{
+  this->DelaySpinBox->setDisabled(waiting);
+  this->ButtonBox->setDisabled(waiting);
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::onCaptureButtonClicked()
+{
+  Q_Q(ctkScreenshotDialog);
+  q->saveScreenshot(this->DelaySpinBox->value());
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::updateFullNameLabel()
+{
+  QString text("%1_%2.png");
+  this->ImageFullNameLabel->setText(
+      text.arg(this->ImageNameLineEdit->text()).arg(this->ImageVersionNumberSpinBox->value()));
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::setCountDownLabel(int newValue)
+{
+  this->CountDownLabel->setText(QString("%1").arg(newValue));
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::resetCountDownValue()
+{
+  this->CountDownTimer.stop();
+  this->CountDownValue = this->DelaySpinBox->value();
+  this->setCountDownLabel(this->CountDownValue);
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::updateCountDown()
+{
+  this->CountDownValue--;
+  this->setCountDownLabel(this->CountDownValue);
+}
+
+//-----------------------------------------------------------------------------
+// ctkScreenshotDialog methods
+
+//-----------------------------------------------------------------------------
+ctkScreenshotDialog::ctkScreenshotDialog(QWidget* newParent)
+  : Superclass(newParent)
+  , d_ptr(new ctkScreenshotDialogPrivate(*this))
+{
+  Q_D(ctkScreenshotDialog);
+  d->init();
+}
+
+//-----------------------------------------------------------------------------
+ctkScreenshotDialog::~ctkScreenshotDialog()
+{
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::setWidgetToGrab(QWidget* newWidgetToGrab)
+{
+  Q_D(ctkScreenshotDialog);
+
+  d->OptionGroupBox->setEnabled(newWidgetToGrab != 0);
+  d->CaptureButton->setEnabled(newWidgetToGrab != 0);
+
+  d->WidgetToGrab = newWidgetToGrab;
+}
+
+//-----------------------------------------------------------------------------
+QWidget* ctkScreenshotDialog::widgetToGrab() const
+{
+  Q_D(const ctkScreenshotDialog);
+  return d->WidgetToGrab.data();
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::setImageName(const QString& newImageName)
+{
+  Q_D(ctkScreenshotDialog);
+  d->ImageNameLineEdit->setText(newImageName);
+}
+  
+//-----------------------------------------------------------------------------
+QString ctkScreenshotDialog::imageName() const
+{
+  Q_D(const ctkScreenshotDialog);
+  return d->ImageNameLineEdit->text();
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::setImageDirectory(const QString& newDirectory)
+{
+  Q_D(ctkScreenshotDialog);
+  d->DirectoryButton->setDirectory(newDirectory);
+}
+
+//-----------------------------------------------------------------------------
+QString ctkScreenshotDialog::imageDirectory()const
+{
+  Q_D(const ctkScreenshotDialog);
+  return d->DirectoryButton->directory();
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::saveScreenshot(int delayInSeconds)
+{
+  Q_D(ctkScreenshotDialog);
+
+  if (d->WidgetToGrab.isNull())
+    {
+    return;
+    }
+
+  if (delayInSeconds > 0)
+    {
+    d->setWaitingForScreenshot(true);
+    d->CountDownTimer.start(1000);
+    QTimer::singleShot(delayInSeconds * 1000, this, SLOT(saveScreenshot()));
+    return;
+    }
+
+  QPixmap viewportPixmap = QPixmap::grabWidget(d->WidgetToGrab.data());
+
+  if (d->DelaySpinBox->value() != 0)
+    {
+    d->setWaitingForScreenshot(false);
+    d->resetCountDownValue();
+    qApp->beep();
+    }
+
+  // Rescale
+  QPixmap rescaledViewportPixmap = viewportPixmap.scaled(
+      viewportPixmap.size().width() * d->ScaleFactorSpinBox->value(),
+      viewportPixmap.size().height() * d->ScaleFactorSpinBox->value());
+
+  QString filename = QString("%1/%2_%3.png").arg(d->DirectoryButton->directory())
+                     .arg(d->ImageNameLineEdit->text())
+                     .arg(d->ImageVersionNumberSpinBox->value());
+
+  // Check if file exists
+  bool overwrite = d->OverwriteCheckBox->isChecked();
+  if (QFile::exists(filename) && !overwrite)
+    {
+    int answer = QMessageBox::question(this, "Screen Capture",
+                                       tr("File already exists. Overwrite ?"),
+                                       QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No);
+    if (answer == QMessageBox::YesToAll)
+      {
+      overwrite = true;
+      d->OverwriteCheckBox->setChecked(true);
+      }
+    else if(answer == QMessageBox::Yes)
+      {
+      overwrite = true;
+      }
+    else
+      {
+      return;
+      }
+    }
+
+  rescaledViewportPixmap.save(filename);
+
+  d->ImageVersionNumberSpinBox->setValue(d->ImageVersionNumberSpinBox->value() + 1);
+}

+ 76 - 0
Libs/Widgets/ctkScreenshotDialog.h

@@ -0,0 +1,76 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkScreenshotDialog_h
+#define __ctkScreenshotDialog_h
+
+// Qt includes
+#include <QDialog>
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+
+class ctkScreenshotDialogPrivate;
+
+///
+/// ctkScreenshotDialog is simple dialog allowing to grab the content 
+/// of any widget and save it into a PNG file.
+/// \sa ctkScreenshotDialog::setWidgetToGrab, QDialog
+class CTK_WIDGETS_EXPORT ctkScreenshotDialog : public QDialog
+{
+  Q_OBJECT
+public:
+  typedef QDialog Superclass;
+  ctkScreenshotDialog(QWidget* newParent = 0);
+  virtual ~ctkScreenshotDialog();
+
+  /// Get widget to grab content from
+  QWidget* widgetToGrab()const;
+
+  /// Set widget to grab content from
+  void setWidgetToGrab(QWidget* newWidgetToGrab);
+  
+  /// Set image name 
+  void setImageName(const QString& newImageName);
+  
+  /// Get image name
+  QString imageName() const;
+
+  /// Set directory where image should be saved
+  void setImageDirectory(const QString& newDirectory);
+
+  /// Get directory were images are saved
+  QString imageDirectory()const;
+
+public slots:
+
+  /// Grab the content of specified widget after \a delayInSeconds
+  /// \sa setWidgetToGrab
+  void saveScreenshot(int delayInSeconds = 0);
+
+protected:
+  QScopedPointer<ctkScreenshotDialogPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkScreenshotDialog);
+  Q_DISABLE_COPY(ctkScreenshotDialog);
+};
+
+#endif

+ 67 - 0
Libs/Widgets/ctkScreenshotDialog_p.h

@@ -0,0 +1,67 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkScreenshotDialog_p_h
+#define __ctkScreenshotDialog_p_h
+
+// Qt includes
+#include <QTimer>
+
+// CTK includes
+#include "ctkScreenshotDialog.h"
+#include "ui_ctkScreenshotDialog.h"
+
+//-----------------------------------------------------------------------------
+class ctkScreenshotDialogPrivate : public QObject, public Ui_ctkScreenshotDialog
+{
+  Q_OBJECT
+  Q_DECLARE_PUBLIC(ctkScreenshotDialog);
+protected:
+  ctkScreenshotDialog* const q_ptr;
+public:
+  explicit ctkScreenshotDialogPrivate(ctkScreenshotDialog& object);
+  virtual ~ctkScreenshotDialogPrivate();
+
+  void init();
+
+  void setupUi(QDialog * widget);
+
+  void setWaitingForScreenshot(bool waiting);
+
+public slots:
+
+  void onCaptureButtonClicked();
+
+  void updateFullNameLabel();
+
+  void setCountDownLabel(int newValue);
+
+  void resetCountDownValue();
+
+  void updateCountDown();
+
+public:
+  QWeakPointer<QWidget> WidgetToGrab;
+  QPushButton*          CaptureButton;
+  int                   CountDownValue;
+  QTimer                CountDownTimer;
+};
+
+#endif