From 5a7b3f4806cb28e49045ccc322bbc1faeb0ed75d Mon Sep 17 00:00:00 2001
From: Martyn Gigg <martyn.gigg@gmail.com>
Date: Wed, 22 Nov 2017 22:18:06 +0000
Subject: [PATCH] Remove usage of QString::fromStdWString

To compile with Qt5 the option /Z:wchar_t- needs to be removed
on Visual C++ but is still required for Qt4. Instead we define the
functionality internally to allow consistent definition within the
project.
Refs #20381
---
 MantidPlot/src/Mantid/MantidMatrixModel.cpp   |  7 +++-
 buildconfig/CMake/MSVCSetup.cmake             |  4 +-
 qt/widgets/common/CMakeLists.txt              |  1 +
 .../inc/MantidQtWidgets/Common/QStringUtils.h | 41 +++++++++++++++++++
 qt/widgets/common/src/PlotAxis.cpp            |  7 ++--
 qt/widgets/common/test/PlotAxisTest.h         | 10 +++--
 .../src/MantidQwtIMDWorkspaceData.cpp         |  6 ++-
 .../sliceviewer/src/DimensionSliceWidget.cpp  |  4 +-
 qt/widgets/sliceviewer/src/XYLimitsDialog.cpp |  7 +++-
 9 files changed, 71 insertions(+), 16 deletions(-)
 create mode 100644 qt/widgets/common/inc/MantidQtWidgets/Common/QStringUtils.h

diff --git a/MantidPlot/src/Mantid/MantidMatrixModel.cpp b/MantidPlot/src/Mantid/MantidMatrixModel.cpp
index d7177336947..c202b776202 100644
--- a/MantidPlot/src/Mantid/MantidMatrixModel.cpp
+++ b/MantidPlot/src/Mantid/MantidMatrixModel.cpp
@@ -8,10 +8,15 @@
 #include "MantidAPI/TextAxis.h"
 #include "MantidKernel/ReadLock.h"
 
+#include "MantidQtWidgets/Common/QStringUtils.h"
+
 #include <QApplication>
 #include <QObject>
 #include <QPalette>
 #include <QVariant>
+
+using MantidQt::API::toQStringInternal;
+
 // ----------   MantidMatrixModel   ------------------ //
 
 /**   MantidMatrixModel constructor.
@@ -132,7 +137,7 @@ QVariant MantidMatrixModel::headerData(int section, Qt::Orientation orientation,
       }
     }
 
-    QString unit = QString::fromStdWString(axis->unit()->label().utf8());
+    QString unit = toQStringInternal(axis->unit()->label().utf8());
 
     // Handle RefAxis for X axis
     Mantid::API::RefAxis *refAxis = dynamic_cast<Mantid::API::RefAxis *>(axis);
diff --git a/buildconfig/CMake/MSVCSetup.cmake b/buildconfig/CMake/MSVCSetup.cmake
index c64593fe0f7..e43004a65ad 100644
--- a/buildconfig/CMake/MSVCSetup.cmake
+++ b/buildconfig/CMake/MSVCSetup.cmake
@@ -19,9 +19,7 @@ add_definitions ( -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS )
 ##########################################################################
 # /MP     - Compile .cpp files in parallel
 # /W3     - Warning Level 3 (This is also the default)
-# /Zc:wchar_t- - Do not treat wchar_t as a builtin type. Required for Qt to
-#           work with wstring
-set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W3 /Zc:wchar_t-" )
+set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W3" )
 
 # Set PCH heap limit, the default does not work when running msbuild from the commandline for some reason
 # Any other value lower or higher seems to work but not the default. It it is fine without this when compiling
diff --git a/qt/widgets/common/CMakeLists.txt b/qt/widgets/common/CMakeLists.txt
index 32ec0b86f51..da0c5c53983 100644
--- a/qt/widgets/common/CMakeLists.txt
+++ b/qt/widgets/common/CMakeLists.txt
@@ -266,6 +266,7 @@ set ( INC_FILES
 	inc/MantidQtWidgets/Common/PythonSystemHeader.h
 	inc/MantidQtWidgets/Common/PythonThreading.h
 	inc/MantidQtWidgets/Common/QScienceSpinBox.h
+	inc/MantidQtWidgets/Common/QStringUtils.h
 	inc/MantidQtWidgets/Common/ScriptRepositoryView.h
 	inc/MantidQtWidgets/Common/SelectionNotificationService.h
 	inc/MantidQtWidgets/Common/SignalBlocker.h
diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/QStringUtils.h b/qt/widgets/common/inc/MantidQtWidgets/Common/QStringUtils.h
new file mode 100644
index 00000000000..173627c4326
--- /dev/null
+++ b/qt/widgets/common/inc/MantidQtWidgets/Common/QStringUtils.h
@@ -0,0 +1,41 @@
+#ifndef MANTIDQT_API_QSTRINGUTILS_H
+#define MANTIDQT_API_QSTRINGUTILS_H
+
+#include <QString>
+#include <string>
+
+namespace MantidQt {
+namespace API {
+/**
+* Internal version of QString::fromStdWString. On MSVC Qt4 rquired
+* /Z:wchar_t- but Qt5 does not. For simplicity we
+* remove the /Z:wchar_t- compiler option and
+* define the functionality interally.
+* @param str A pointer to the raw wchar_t string
+*/
+inline QString toQStringInternal(const wchar_t *str) {
+  return sizeof(wchar_t) == sizeof(QChar)
+             ? QString::fromUtf16(reinterpret_cast<const ushort *>(str),
+                                  static_cast<int>(wcslen(str)))
+             : QString::fromUcs4(reinterpret_cast<const uint *>(str),
+                                 static_cast<int>(wcslen(str)));
+}
+
+/**
+* Internal version of QString::fromStdWString. On MSVC Qt4 rquired
+* /Z:wchar_t- but Qt5 does not. For simplicity we
+* remove the /Z:wchar_t- compiler option and
+* define the functionality interally.
+* @param str A std::wstring object
+*/
+inline QString toQStringInternal(const std::wstring &str) {
+  return sizeof(wchar_t) == sizeof(QChar)
+             ? QString::fromUtf16(reinterpret_cast<const ushort *>(str.data()),
+                                  static_cast<int>(str.size()))
+             : QString::fromUcs4(reinterpret_cast<const uint *>(str.data()),
+                                 static_cast<int>(str.size()));
+}
+}
+}
+
+#endif // MANTIDQT_API_QSTRINGUTILS_H
\ No newline at end of file
diff --git a/qt/widgets/common/src/PlotAxis.cpp b/qt/widgets/common/src/PlotAxis.cpp
index b8ab39cc480..6dc892f4fb0 100644
--- a/qt/widgets/common/src/PlotAxis.cpp
+++ b/qt/widgets/common/src/PlotAxis.cpp
@@ -1,4 +1,5 @@
 #include "MantidQtWidgets/Common/PlotAxis.h"
+#include "MantidQtWidgets/Common/QStringUtils.h"
 
 #include "MantidAPI/Axis.h"
 #include "MantidAPI/MatrixWorkspace.h"
@@ -72,7 +73,7 @@ void PlotAxis::titleFromDimension(const Mantid::Geometry::IMDDimension &dim) {
   if (!m_title.isEmpty()) {
     auto unitLbl = dim.getUnits();
     if (!unitLbl.utf8().empty()) {
-      m_title += " (" + QString::fromStdWString(unitLbl.utf8()) + ")";
+      m_title += " (" + toQStringInternal(unitLbl.utf8()) + ")";
     } else if (!unitLbl.ascii().empty()) {
       m_title += " (" + QString::fromStdString(unitLbl.ascii()) + ")";
     }
@@ -103,8 +104,8 @@ void PlotAxis::titleFromYData(const Mantid::API::MatrixWorkspace &workspace,
       const auto xunit = workspace.getAxis(0)->unit();
       const auto lbl = xunit->label();
       if (!lbl.utf8().empty()) {
-        m_title += " (" + QString::fromStdWString(lbl.utf8()) + ")" +
-                   QString::fromWCharArray(L"\u207b\u00b9");
+        m_title += " (" + toQStringInternal(lbl.utf8()) + ")" +
+                   toQStringInternal(L"\u207b\u00b9");
       }
     }
   } else {
diff --git a/qt/widgets/common/test/PlotAxisTest.h b/qt/widgets/common/test/PlotAxisTest.h
index aad6ec1684a..1c34e83e3a7 100644
--- a/qt/widgets/common/test/PlotAxisTest.h
+++ b/qt/widgets/common/test/PlotAxisTest.h
@@ -4,6 +4,7 @@
 #include <cxxtest/TestSuite.h>
 
 #include "MantidQtWidgets/Common/PlotAxis.h"
+#include "MantidQtWidgets/Common/QStringUtils.h"
 #include "MantidAPI/NumericAxis.h"
 #include "MantidAPI/SpectraAxis.h"
 #include "MantidGeometry/MDGeometry/MDHistoDimension.h"
@@ -80,7 +81,8 @@ public:
     ws->getAxis(0)->setUnit("TOF");
     ws->replaceAxis(1, new Mantid::API::NumericAxis(1));
     ws->getAxis(1)->setUnit("TOF");
-    QString expected = QString::fromWCharArray(L"Time-of-flight (\u03bcs)");
+    QString expected =
+        MantidQt::API::toQStringInternal(L"Time-of-flight (\u03bcs)");
     TS_ASSERT_EQUALS(expected, PlotAxis(*ws, 0).title());
     TS_ASSERT_EQUALS(expected, PlotAxis(*ws, 1).title());
   }
@@ -94,8 +96,8 @@ public:
     const auto lbl = xunit->label();
     // the Y unit should be (<x_unit_label>)^-1 when plotting as distribution
     // instead of (<x_unit_label>^-1).
-    TS_ASSERT_EQUALS(" (" + QString::fromStdWString(lbl.utf8()) + ")" +
-                         QString::fromWCharArray(L"\u207b\u00b9"),
+    TS_ASSERT_EQUALS(" (" + MantidQt::API::toQStringInternal(lbl.utf8()) + ")" +
+                         MantidQt::API::toQStringInternal(L"\u207b\u00b9"),
                      PlotAxis(true, *ws).title());
   }
 
@@ -139,7 +141,7 @@ public:
         Mantid::Geometry::GeneralFrame::GeneralFrameTOF,
         UnitLabel("us", L"\u03bcs", "\\mu s"));
     MDHistoDimension dim("tof", "dimx", frame, 0.0f, 1.0f, 10);
-    QString expected = QString::fromWCharArray(L"tof (\u03bcs)");
+    QString expected = MantidQt::API::toQStringInternal(L"tof (\u03bcs)");
     TS_ASSERT_EQUALS(expected, PlotAxis(dim).title());
   }
 
diff --git a/qt/widgets/legacyqwt/src/MantidQwtIMDWorkspaceData.cpp b/qt/widgets/legacyqwt/src/MantidQwtIMDWorkspaceData.cpp
index 0fa0b651f41..e6a3d3abaa0 100644
--- a/qt/widgets/legacyqwt/src/MantidQwtIMDWorkspaceData.cpp
+++ b/qt/widgets/legacyqwt/src/MantidQwtIMDWorkspaceData.cpp
@@ -1,3 +1,5 @@
+#include "MantidQtWidgets/LegacyQwt/MantidQwtIMDWorkspaceData.h"
+#include "MantidQtWidgets/Common/QStringUtils.h"
 #include "MantidAPI/CoordTransform.h"
 #include "MantidAPI/IMDEventWorkspace.h"
 #include "MantidAPI/IMDHistoWorkspace.h"
@@ -6,9 +8,9 @@
 #include "MantidAPI/NullCoordTransform.h"
 #include "MantidGeometry/MDGeometry/IMDDimension.h"
 #include "MantidGeometry/MDGeometry/MDTypes.h"
-#include "MantidQtWidgets/LegacyQwt/MantidQwtIMDWorkspaceData.h"
 #include <QStringBuilder>
 
+using MantidQt::API::toQStringInternal;
 using namespace Mantid::Kernel;
 using namespace Mantid::Geometry;
 using Mantid::API::NullCoordTransform;
@@ -365,7 +367,7 @@ QString MantidQwtIMDWorkspaceData::getXAxisLabel() const {
     IMDDimension_const_sptr dim =
         m_originalWorkspace.lock()->getDimension(m_currentPlotAxis);
     xLabel = QString::fromStdString(dim->getName()) + " (" +
-             QString::fromStdWString(dim->getUnits().utf8()) + ")";
+             toQStringInternal(dim->getUnits().utf8()) + ")";
   } else {
     // Distance
     // Distance, or not set.
diff --git a/qt/widgets/sliceviewer/src/DimensionSliceWidget.cpp b/qt/widgets/sliceviewer/src/DimensionSliceWidget.cpp
index 646f93bc2d2..3a2f263b058 100644
--- a/qt/widgets/sliceviewer/src/DimensionSliceWidget.cpp
+++ b/qt/widgets/sliceviewer/src/DimensionSliceWidget.cpp
@@ -1,9 +1,11 @@
 #include "MantidQtWidgets/SliceViewer/DimensionSliceWidget.h"
+#include "MantidQtWidgets/Common/QStringUtils.h"
 #include "MantidKernel/UnitLabel.h"
 #include <iosfwd>
 #include <QLayout>
 
 namespace MantidQt {
+using API::toQStringInternal;
 namespace SliceViewer {
 
 DimensionSliceWidget::DimensionSliceWidget(QWidget *parent)
@@ -151,7 +153,7 @@ void DimensionSliceWidget::setMinMax(double min, double max) {
   if (!m_dim)
     return;
   ui.lblName->setText(QString::fromStdString(m_dim->getName()));
-  ui.lblUnits->setText(QString::fromStdWString(m_dim->getUnits().utf8()));
+  ui.lblUnits->setText(toQStringInternal(m_dim->getUnits().utf8()));
 
   ui.horizontalSlider->setRange(min, max, m_dim->getBinWidth());
 
diff --git a/qt/widgets/sliceviewer/src/XYLimitsDialog.cpp b/qt/widgets/sliceviewer/src/XYLimitsDialog.cpp
index de7232992fe..b2c875a3627 100644
--- a/qt/widgets/sliceviewer/src/XYLimitsDialog.cpp
+++ b/qt/widgets/sliceviewer/src/XYLimitsDialog.cpp
@@ -1,7 +1,10 @@
 #include "MantidQtWidgets/SliceViewer/XYLimitsDialog.h"
+#include "MantidQtWidgets/Common/QStringUtils.h"
 #include "MantidKernel/UnitLabel.h"
 #include <QIntValidator>
 
+using MantidQt::API::toQStringInternal;
+
 XYLimitsDialog::XYLimitsDialog(QWidget *parent) : QDialog(parent) {
   ui.setupUi(this);
   ui.textXMax->setValidator(new QDoubleValidator(ui.textXMax));
@@ -20,14 +23,14 @@ XYLimitsDialog::~XYLimitsDialog() {}
  * @param dim : IMDDimension */
 void XYLimitsDialog::setXDim(Mantid::Geometry::IMDDimension_const_sptr dim) {
   ui.lblXName->setText(QString::fromStdString(dim->getName()));
-  ui.lblXUnits->setText(QString::fromStdWString(dim->getUnits().utf8()));
+  ui.lblXUnits->setText(toQStringInternal(dim->getUnits().utf8()));
 }
 
 /** Set the labels for the Y dimensions
  * @param dim : IMDDimension */
 void XYLimitsDialog::setYDim(Mantid::Geometry::IMDDimension_const_sptr dim) {
   ui.lblYName->setText(QString::fromStdString(dim->getName()));
-  ui.lblYUnits->setText(QString::fromStdWString(dim->getUnits().utf8()));
+  ui.lblYUnits->setText(toQStringInternal(dim->getUnits().utf8()));
 }
 
 //------------------------------------------------------------------------------------------
-- 
GitLab