浏览代码

Add ctkScreenshotDialogTest1 + rename ctkScreenshotDialog methods

Expose to the API the option of taking screenshots instantanely.
Julien Finet 14 年之前
父节点
当前提交
9796920565

+ 2 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -40,6 +40,7 @@ CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cxx
   ctkRangeWidgetTest1.cpp
   ctkRangeWidgetTest2.cpp
   ctkDateRangeWidgetTest1.cpp
+  ctkScreenshotDialogTest1.cpp
   ctkSettingsPanelTest1.cpp
   ctkSettingsTest1.cpp
   ctkSettingsDialogTest1.cpp
@@ -127,6 +128,7 @@ SIMPLE_TEST( ctkPathLineEditTest1 )
 SIMPLE_TEST( ctkRangeSliderTest1 )
 SIMPLE_TEST( ctkRangeWidgetTest1 )
 SIMPLE_TEST( ctkRangeWidgetTest2 )
+SIMPLE_TEST( ctkScreenshotDialogTest1 )
 SIMPLE_TEST( ctkSettingsDialogTest1 )
 SIMPLE_TEST( ctkSettingsPanelTest1 )
 SIMPLE_TEST( ctkSettingsTest1 )

+ 100 - 0
Libs/Widgets/Testing/Cpp/ctkScreenshotDialogTest1.cpp

@@ -0,0 +1,100 @@
+/*=========================================================================
+
+  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 <QApplication>
+#include <QDir>
+#include <QTimer>
+
+// CTK includes
+#include "ctkScreenshotDialog.h"
+
+// STD includes
+#include <cstdlib>
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkScreenshotDialogTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+
+  QWidget topLevel;
+
+  ctkScreenshotDialog screenshotDialog;
+
+  // Check default values
+  if (screenshotDialog.widgetToGrab() != 0 ||
+      screenshotDialog.baseFileName() != "Untitled" ||
+      screenshotDialog.directory() != "." ||
+      screenshotDialog.delay() != 0)
+    {
+    std::cerr << "ctkScreenshotDialog, bad default values: "
+                << screenshotDialog.widgetToGrab() << " "
+                << qPrintable(screenshotDialog.baseFileName()) << " "
+                << qPrintable(screenshotDialog.directory()) << " "
+                <<  screenshotDialog.delay() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  screenshotDialog.setWidgetToGrab(&topLevel);
+  if (screenshotDialog.widgetToGrab() != &topLevel)
+    {
+    std::cerr << "ctkScreenshotDialog::setWidgetToGrab failed: "
+              << screenshotDialog.widgetToGrab() << " instead of  "
+              << &topLevel << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  screenshotDialog.setBaseFileName("screenshot");
+  if (screenshotDialog.baseFileName() != "screenshot")
+    {
+    std::cerr << "ctkScreenshotDialog::setBaseFileName failed: "
+              << qPrintable(screenshotDialog.baseFileName()) << " instead of "
+              << "\"screenshot\"." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  screenshotDialog.setDirectory("..");
+  if (screenshotDialog.directory() != "..")
+    {
+    std::cerr << "ctkScreenshotDialog::setDirectory failed: "
+              << qPrintable(screenshotDialog.directory()) << " instead of "
+              << ".." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  screenshotDialog.setDelay(1);
+  if (screenshotDialog.delay() != 1)
+    {
+    std::cerr << "ctkScreenshotDialog::setDelay failed: "
+              << screenshotDialog.delay() << " instead of 2." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  topLevel.show();
+
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(1400, &app, SLOT(quit()));
+    }
+
+  screenshotDialog.saveScreenshot(); // 1000msecs should be enough
+  return screenshotDialog.exec();
+}

+ 3 - 1
Libs/Widgets/ctkDirectoryButton.h

@@ -84,7 +84,9 @@ public:
   virtual ~ctkDirectoryButton();
 
   /// Set/get the current directory
-  void setDirectory(const QString& directory);
+  /// If path is empty, the program's working directory, ("."), is used.
+  /// By default, \a directory is the current working directory. 
+  void setDirectory(const QString& path);
   QString directory()const;
 
   ///

+ 64 - 24
Libs/Widgets/ctkScreenshotDialog.cpp

@@ -63,7 +63,7 @@ void ctkScreenshotDialogPrivate::setupUi(QDialog * widget)
   // Update OK button text
   okButton->setText("Capture");
 
-  connect(okButton, SIGNAL(clicked()), SLOT(onCaptureButtonClicked()));
+  connect(okButton, SIGNAL(clicked()), q, SLOT(saveScreenshot()));
   connect(this->ImageNameLineEdit, SIGNAL(textChanged(QString)), SLOT(updateFullNameLabel()));
   connect(this->ImageVersionNumberSpinBox, SIGNAL(valueChanged(int)), SLOT(updateFullNameLabel()));
   connect(this->DelaySpinBox, SIGNAL(valueChanged(int)), SLOT(resetCountDownValue()));
@@ -71,6 +71,7 @@ void ctkScreenshotDialogPrivate::setupUi(QDialog * widget)
 
   this->CaptureButton = okButton;
 
+  // Called to enable/disable buttons
   q->setWidgetToGrab(0);
 }
 
@@ -82,10 +83,14 @@ void ctkScreenshotDialogPrivate::setWaitingForScreenshot(bool waiting)
 }
 
 //-----------------------------------------------------------------------------
-void ctkScreenshotDialogPrivate::onCaptureButtonClicked()
+bool ctkScreenshotDialogPrivate::isWaitingForScreenshot()const
 {
-  Q_Q(ctkScreenshotDialog);
-  q->saveScreenshot(this->DelaySpinBox->value());
+  Q_Q(const ctkScreenshotDialog);
+  // Bad Qt const correctness, need to hack.
+  ctkScreenshotDialog* parent = const_cast<ctkScreenshotDialog*>(q);
+  Q_ASSERT(this->DelaySpinBox->isEnabledTo(parent) ==
+           this->ButtonBox->isEnabledTo(parent));
+  return this->ButtonBox->isEnabledTo(parent);
 }
 
 //-----------------------------------------------------------------------------
@@ -93,7 +98,8 @@ void ctkScreenshotDialogPrivate::updateFullNameLabel()
 {
   QString text("%1_%2.png");
   this->ImageFullNameLabel->setText(
-      text.arg(this->ImageNameLineEdit->text()).arg(this->ImageVersionNumberSpinBox->value()));
+      text.arg(this->ImageNameLineEdit->text())
+          .arg(this->ImageVersionNumberSpinBox->value()));
 }
 
 //-----------------------------------------------------------------------------
@@ -113,8 +119,29 @@ void ctkScreenshotDialogPrivate::resetCountDownValue()
 //-----------------------------------------------------------------------------
 void ctkScreenshotDialogPrivate::updateCountDown()
 {
-  this->CountDownValue--;
-  this->setCountDownLabel(this->CountDownValue);
+  this->setCountDownLabel(--this->CountDownValue);
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialogPrivate::saveScreenshot(int delayInSeconds)
+{
+  Q_Q(ctkScreenshotDialog);
+
+  if (this->WidgetToGrab.isNull())
+    {
+    return;
+    }
+
+  if (delayInSeconds <= 0)
+    {
+    q->instantScreenshot();
+    return;
+    }
+  this->setWaitingForScreenshot(true);
+  this->CountDownValue = delayInSeconds;
+  this->CountDownTimer.start(1000);
+  // Add 1ms to give time to set the countdown at 0. 
+  QTimer::singleShot(delayInSeconds * 1000 + 1, q, SLOT(instantScreenshot()));
 }
 
 //-----------------------------------------------------------------------------
@@ -153,59 +180,72 @@ QWidget* ctkScreenshotDialog::widgetToGrab() const
 }
 
 //-----------------------------------------------------------------------------
-void ctkScreenshotDialog::setImageName(const QString& newImageName)
+void ctkScreenshotDialog::setBaseFileName(const QString& newBaseName)
 {
   Q_D(ctkScreenshotDialog);
-  d->ImageNameLineEdit->setText(newImageName);
+  d->ImageNameLineEdit->setText(newBaseName);
 }
   
 //-----------------------------------------------------------------------------
-QString ctkScreenshotDialog::imageName() const
+QString ctkScreenshotDialog::baseFileName() const
 {
   Q_D(const ctkScreenshotDialog);
   return d->ImageNameLineEdit->text();
 }
 
 //-----------------------------------------------------------------------------
-void ctkScreenshotDialog::setImageDirectory(const QString& newDirectory)
+void ctkScreenshotDialog::setDirectory(const QString& newDirectory)
 {
   Q_D(ctkScreenshotDialog);
   d->DirectoryButton->setDirectory(newDirectory);
 }
 
 //-----------------------------------------------------------------------------
-QString ctkScreenshotDialog::imageDirectory()const
+QString ctkScreenshotDialog::directory()const
 {
   Q_D(const ctkScreenshotDialog);
   return d->DirectoryButton->directory();
 }
 
 //-----------------------------------------------------------------------------
-void ctkScreenshotDialog::saveScreenshot(int delayInSeconds)
+void ctkScreenshotDialog::setDelay(int seconds)
 {
   Q_D(ctkScreenshotDialog);
+  d->DelaySpinBox->setValue(seconds);
+}
 
-  if (d->WidgetToGrab.isNull())
-    {
-    return;
-    }
+//-----------------------------------------------------------------------------
+int ctkScreenshotDialog::delay()const
+{
+  Q_D(const ctkScreenshotDialog);
+  return d->DelaySpinBox->value();
+}
 
-  if (delayInSeconds > 0)
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::saveScreenshot()
+{
+  Q_D(ctkScreenshotDialog);
+  d->saveScreenshot(this->delay());
+}
+
+//-----------------------------------------------------------------------------
+void ctkScreenshotDialog::instantScreenshot()
+{
+  Q_D(ctkScreenshotDialog);
+
+  if (d->WidgetToGrab.isNull())
     {
-    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)
+  if (d->isWaitingForScreenshot() && d->DelaySpinBox->value() != 0)
     {
-    d->setWaitingForScreenshot(false);
-    d->resetCountDownValue();
     qApp->beep();
     }
+  d->setWaitingForScreenshot(false);
+  d->resetCountDownValue();
 
   // Rescale
   QPixmap rescaledViewportPixmap = viewportPixmap.scaled(

+ 44 - 23
Libs/Widgets/ctkScreenshotDialog.h

@@ -29,41 +29,62 @@
 
 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
+/** ctkScreenshotDialog is simple dialog allowing to grab the content 
+    of any widget and save it into a PNG file.
+    It can be used as a tool and can take screenshots without being opened nor
+    executed.
+    \code
+    ctkScreenshotDialog screenshot;
+    screenshot.setWidgetToGrab(myWidget);
+    screenshot.instantScreenshot();
+    \endcode
+ \sa ctkScreenshotDialog::setWidgetToGrab, QDialog
+*/
 class CTK_WIDGETS_EXPORT ctkScreenshotDialog : public QDialog
 {
   Q_OBJECT
+  Q_PROPERTY(QString baseFileName READ baseFileName WRITE setBaseFileName)
+  Q_PROPERTY(QString directory READ directory WRITE setDirectory)
+  Q_PROPERTY(int delay READ delay WRITE setDelay)
+
 public:
   typedef QDialog Superclass;
-  ctkScreenshotDialog(QWidget* newParent = 0);
+  ctkScreenshotDialog(QWidget* parent = 0);
   virtual ~ctkScreenshotDialog();
 
-  /// Get widget to grab content from
-  QWidget* widgetToGrab()const;
-
-  /// Set widget to grab content from
+  /// Get widget to grab content from. If no widget is set, no screenshot will
+  /// be taken.
+  /// 0 by default.
+  /// TODO: if widgetToGrab -> screenshot the entire application
   void setWidgetToGrab(QWidget* newWidgetToGrab);
+  QWidget* widgetToGrab()const;
   
-  /// 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;
+  /// Set screenshot base name used to generate unique file names to save the
+  /// screenshot images. The base name doesn't contain the file extension
+  /// (automatically set to ".png")
+  /// "Untitled" by default
+  void setBaseFileName(const QString& newImageName);
+  QString baseFileName() const;
+
+  /// Set directory where screenshot files are saved. If path is empty, the
+  /// program's working directory, ("."), is used.
+  /// Current working directory by default.
+  void setDirectory(const QString& path);
+  QString directory()const;
+
+  /// Set the delay in seconds before the screenshot is taken.
+  /// 0 seconds by default.
+  void setDelay(int seconds);
+  int delay()const;
 
 public slots:
+  /// Instantanely grabs the content of \a widgetToGrag. Generates a
+  /// png file into \a directory. It automatically increments the image name
+  /// index suffix.
+  void instantScreenshot();
 
-  /// Grab the content of specified widget after \a delayInSeconds
-  /// \sa setWidgetToGrab
-  void saveScreenshot(int delayInSeconds = 0);
+  /// Calls instantScreenshot() after a countdown of \a delay seconds
+  void saveScreenshot();
 
 protected:
   QScopedPointer<ctkScreenshotDialogPrivate> d_ptr;

+ 2 - 1
Libs/Widgets/ctkScreenshotDialog_p.h

@@ -44,10 +44,11 @@ public:
   void setupUi(QDialog * widget);
 
   void setWaitingForScreenshot(bool waiting);
+  bool isWaitingForScreenshot()const;
 
 public slots:
 
-  void onCaptureButtonClicked();
+  void saveScreenshot(int delayInSeconds);
 
   void updateFullNameLabel();