diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f45d8c16ac91137b442bac6dc12c7c97762791b..1a104fc10c81b14bf2a13499d47309e2474f3bc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,8 +127,14 @@ if(ENABLE_MANTIDPLOT) message(FATAL_ERROR "Qwt version 5 is required, found: ${QWT5_VERSION}") endif() - find_package(PyQt4 REQUIRED) - find_package(SIP REQUIRED) + if(PYTHON_VERSION_MAJOR EQUAL 3 AND + UNIX_DIST MATCHES "RedHatEnterprise" AND UNIX_RELEASE MATCHES "7\..*") + set(USE_PRIVATE_SIPPYQT4 ON) + include(ExternalSipPyQt4) + else() + find_package(PyQt4 REQUIRED) + find_package(SIP REQUIRED) + endif() separate_arguments(PYQT4_SIP_FLAGS) endif() @@ -382,58 +388,64 @@ if(ENABLE_CPACK) # rhel requirements - only used if package requested is rpm set( CPACK_RPM_PACKAGE_REQUIRES - "nexus >= 4.3.1,gsl,glibc,muParser,numpy,h5py >= 2.3.1,PyCifRW >= 4.2.1,tbb,librdkafka," - "${CPACK_RPM_PACKAGE_REQUIRES},OCE-draw,OCE-foundation,OCE-modeling,OCE-ocaf,OCE-visualization," + "boost169-date-time," + "boost169-regex," + "boost169-serialization," + "boost169-filesystem," + "boost169-system," + "nexus >= 4.3.1,gsl,glibc,muParser,tbb,librdkafka," + "OCE-draw,OCE-foundation,OCE-modeling,OCE-ocaf,OCE-visualization," "poco-crypto,poco-data,poco-mysql,poco-sqlite,poco-odbc,poco-util,poco-xml,poco-zip,poco-net,poco-netssl,poco-foundation," - "sip >= 4.18,python-enum34," - "python-six,python-ipython >= 1.1.0,python-ipython-notebook,PyYAML," - "python-requests," - "scipy," "hdf,hdf5,jsoncpp >= 0.7.0") if(ENABLE_MANTIDPLOT) set(CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qt4 >= 4.2,PyQt4,qwtplot3d-qt4") + "${CPACK_RPM_PACKAGE_REQUIRES},qt4 >= 4.2,qscintilla,qwt5-qt4,qwtplot3d-qt4") endif() if(ENABLE_WORKBENCH) set(CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qt5-qtbase,python2-qt5") + "${CPACK_RPM_PACKAGE_REQUIRES},qt5-qtbase,qscintilla-qt5") endif() - if("${UNIX_CODENAME}" MATCHES "Santiago") # RHEL6 - if(ENABLE_WORKBENCH) - message(FATAL_ERROR "mantidworkbench is not supported on RHEL6") - endif() - # On RHEL6 we have to use an updated qscintilla to fix an auto complete - # bug + if(PYTHON_VERSION_MAJOR EQUAL 3) set( CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qscintilla >= 2.4.6,boost157,python-matplotlib," - # On RHEL6 we are using SCL packages for Qt - "scl-utils,mantidlibs34,mantidlibs34-runtime,mantidlibs34-qt,mantidlibs34-qt-x11,mantidlibs34-qt-webkit,mantidlibs34-qwt5-qt4" - ) - else() # assumes RHEL7 Require matplotlib >= 1.5 to fix bug in latex - # rendering - oddly matplotlib-qt4 contains qt5 backend as well + "${CPACK_RPM_PACKAGE_REQUIRES}," + "boost169-python3," + "python36-numpy,python36-scipy,python36-h5py,python36-PyCifRW," + "python36-six,python36-PyYAML,python36-requests," + "python36-ipython,python36-ipython-notebook" + ) + if(ENABLE_MANTIDPLOT) + set(CPACK_RPM_PACKAGE_REQUIRES + "${CPACK_RPM_PACKAGE_REQUIRES},python36-QtPy," + "python36-matplotlib-qt4,python36-ipython-gui") + endif() + if(ENABLE_WORKBENCH) + set(CPACK_RPM_PACKAGE_REQUIRES + "${CPACK_RPM_PACKAGE_REQUIRES},python36-qt5,python36-QtPy," + "python36-matplotlib-qt5,python36-psutil,python36-ipython-gui") + endif() + else() set( CPACK_RPM_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}," - "boost169-date-time," - "boost169-regex," - "boost169-serialization," - "boost169-filesystem," - "boost169-system," "boost169-python2," - "python2-QtPy," - "python2-matplotlib-qt4 >= 1.5.2" - ) + "numpy,scipy,h5py >= 2.3.1,PyCifRW >= 4.2.1," + "python-enum34,python-six,PyYAML,python-requests," + "python-ipython >= 1.1.0,python-ipython-notebook" + ) if(ENABLE_MANTIDPLOT) set(CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qscintilla,qwt5-qt4") + "${CPACK_RPM_PACKAGE_REQUIRES},sip >= 4.18,PyQt4,python2-QtPy," + "python2-matplotlib-qt4 >= 1.5.2,python-ipython-gui") endif() if(ENABLE_WORKBENCH) set(CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qscintilla-qt5,python-psutil") + "${CPACK_RPM_PACKAGE_REQUIRES},python2-qt5,python2-QtPy," + "python2-matplotlib-qt4 >= 1.5.2,python-psutil,python-ipython-gui") endif() endif() + string(REPLACE ";" "," CPACK_RPM_PACKAGE_REQUIRES diff --git a/Framework/PostInstall/CMakeLists.txt b/Framework/PostInstall/CMakeLists.txt index 5e996f052745df4fd8011fc0a2cef5adb6e50d97..7f94a7725d63df9f635117c13c3e0fa89f59c910 100644 --- a/Framework/PostInstall/CMakeLists.txt +++ b/Framework/PostInstall/CMakeLists.txt @@ -12,7 +12,7 @@ # ${DESTDIR}${CMAKE_INSTALL_PREFIX} but this should be evaluated at CPack time # so escape the $ to its written literally. set(PACKAGE_ROOT \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}) -set(EXCLUDE_REGEX ".*_template|.*port_v3") +set(EXCLUDE_REGEX ".*_template") set(COMPILE_SCRIPT "message ( \"Byte-compiling Python in ${PACKAGE_ROOT}\")") set( diff --git a/Framework/PythonInterface/mantid/plots/__init__.py b/Framework/PythonInterface/mantid/plots/__init__.py index 7ce38b4fc87b82bc384a9b413339977fb768d34b..8031d9567800cf57ebe109b57404da199b6ba535 100644 --- a/Framework/PythonInterface/mantid/plots/__init__.py +++ b/Framework/PythonInterface/mantid/plots/__init__.py @@ -19,7 +19,7 @@ try: from collections.abc import Iterable except ImportError: # check Python 2 location - from collections import Iterable + from collections import Iterable from matplotlib.axes import Axes from matplotlib.collections import Collection from matplotlib.colors import Colormap @@ -35,11 +35,11 @@ from mpl_toolkits.mplot3d.axes3d import Axes3D from mantid.api import AnalysisDataService as ads from mantid.kernel import logger from mantid.plots import helperfunctions, plotfunctions, plotfunctions3D -from mantid.plots.utility import autoscale_on_update +from mantid.plots.legend import LegendProperties from mantid.plots.helperfunctions import get_normalize_by_bin_width from mantid.plots.scales import PowerScale, SquareScale -from mantid.plots.utility import artists_hidden, MantidAxType, legend_set_draggable -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties +from mantid.plots.utility import (artists_hidden, autoscale_on_update, + legend_set_draggable, MantidAxType) def plot_decorator(func): diff --git a/Framework/PythonInterface/mantid/plots/legend.py b/Framework/PythonInterface/mantid/plots/legend.py new file mode 100644 index 0000000000000000000000000000000000000000..5cf25f89661cb7ddd62b5054bbab13c4b6bb12d8 --- /dev/null +++ b/Framework/PythonInterface/mantid/plots/legend.py @@ -0,0 +1,174 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2020 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +# This file is part of the mantid package +# +# +""" +Functionality for dealing with legends on plots +""" +from __future__ import (absolute_import, division, print_function) + +import sys + +import matplotlib +from matplotlib import colors +from matplotlib.patches import BoxStyle + +from mantid.plots.utility import legend_set_draggable + + +def convert_color_to_hex(color): + """Convert a matplotlib color to its hex form""" + try: + return colors.cnames[color] + except (KeyError, TypeError): + rgb = colors.colorConverter.to_rgb(color) + return colors.rgb2hex(rgb) + + +class LegendProperties(dict): + def __getattr__(self, item): + return self[item] + + @classmethod + def from_legend(cls, legend): + props = dict() + + props['visible'] = legend.get_visible() + + title = legend.get_title() + if sys.version_info[0] >= 3: + if isinstance(title.get_text(), str): + props['title'] = title.get_text() + else: + props['title'] = None + else: + if isinstance(title.get_text(), unicode): + props['title'] = title.get_text() + else: + props['title'] = None + + props['title_font'] = title.get_fontname() + props['title_size'] = title.get_fontsize() + props['title_color'] = convert_color_to_hex(title.get_color()) + + props['box_visible'] = legend.get_frame_on() + + box = legend.get_frame() + props['background_color'] = convert_color_to_hex(box.get_facecolor()) + props['edge_color'] = convert_color_to_hex(box.get_edgecolor()) + props['transparency'] = box.get_alpha() + + text = legend.get_texts()[0] + props['entries_font'] = text.get_fontname() + props['entries_size'] = text.get_fontsize() + props['entries_color'] = convert_color_to_hex(text.get_color()) + + props['marker_size'] = legend.handlelength + props['shadow'] = legend.shadow + + boxstyle = legend.legendPatch.get_boxstyle() + if isinstance(boxstyle, BoxStyle.Round): + props['round_edges'] = True + else: + props['round_edges'] = False + + props['columns'] = legend._ncol + props['column_spacing'] = legend.columnspacing + props['label_spacing'] = legend.labelspacing + + position = legend._legend_handle_box.get_children()[0].align + if position == "baseline": + props['marker_position'] = "Left of Entries" + else: + props['marker_position'] = "Right of Entries" + + props['markers'] = legend.numpoints + props['border_padding'] = legend.borderpad + props['marker_label_padding'] = legend.handletextpad + + return cls(props) + + @classmethod + def from_view(cls, view): + props = dict() + props['visible'] = not view.hide_legend_check_box.isChecked() + props['title'] = view.get_title() + props['background_color'] = view.get_background_color() + props['edge_color'] = view.get_edge_color() + props['transparency'] = (100-float(view.get_transparency_spin_box_value()))/100 + props['entries_font'] = view.get_entries_font() + props['entries_size'] = view.get_entries_size() + props['entries_color'] = view.get_entries_color() + props['title_font'] = view.get_title_font() + props['title_size'] = view.get_title_size() + props['title_color'] = view.get_title_color() + props['marker_size'] = view.get_marker_size() + props['box_visible'] = not view.get_hide_box() + return cls(props) + + @classmethod + def from_view_advanced(cls, view): + props = dict() + props['shadow'] = view.get_shadow() + props['round_edges'] = view.get_round_edges() + props['columns'] = view.get_number_of_columns() + props['column_spacing'] = view.get_column_spacing() + props['label_spacing'] = view.get_label_spacing() + props['marker_position'] = view.get_marker_position() + props['markers'] = view.get_number_of_markers() + props['border_padding'] = view.get_border_padding() + props['marker_label_padding'] = view.get_marker_label_padding() + return cls(props) + + @classmethod + def create_legend(cls, props, ax): + if int(matplotlib.__version__[0]) >= 2: + legend = ax.legend(ncol=props['columns'], + prop={'size': props['entries_size']}, + numpoints=props['markers'], + markerfirst=props['marker_position'] == "Left of Entries", + frameon=props['box_visible'], + fancybox=props['round_edges'], + shadow=props['shadow'], + framealpha=props['transparency'], + facecolor=props['background_color'], + edgecolor=props['edge_color'], + title=props['title'], + borderpad=props['border_padding'], + labelspacing=props['label_spacing'], + handlelength=props['marker_size'], + handletextpad=props['marker_label_padding'], + columnspacing=props['column_spacing']) + else: + legend = ax.legend(ncol=props['columns'], + prop={'size': props['entries_size']}, + numpoints=props['markers'], + markerfirst=props['marker_position'] == "Left of Entries", + frameon=props['box_visible'], + fancybox=props['round_edges'], + shadow=props['shadow'], + framealpha=props['transparency'], + title=props['title'], + borderpad=props['border_padding'], + labelspacing=props['label_spacing'], + handlelength=props['marker_size'], + handletextpad=props['marker_label_padding'], + columnspacing=props['column_spacing']) + + title = legend.get_title() + title.set_fontname(props['title_font']) + title.set_fontsize(props['title_size']) + title.set_color(props['title_color']) + + for text in legend.get_texts(): + text.set_fontname(props['entries_font']) + text.set_fontsize(props['entries_size']) + text.set_color(props['entries_color']) + + legend.set_visible(props['visible']) + legend_set_draggable(legend, True) diff --git a/MantidPlot/CMakeLists.txt b/MantidPlot/CMakeLists.txt index 394f3d0978aa7a4a17082783172f362e8021efc7..1a778bbf120bb48a9ba8aa87ae7e7da71efa3957 100644 --- a/MantidPlot/CMakeLists.txt +++ b/MantidPlot/CMakeLists.txt @@ -420,7 +420,6 @@ include(UseQt4) # Do the sip generation. # -include_directories(${PYTHON_INCLUDE_PATH}) # We need to manually add all the headers that are in qti.sip so that the # dependencies are known to CMake @@ -459,21 +458,23 @@ set(MANTIDQTPYTHON_SIP_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/../qt/python/mantidqtpython -I ${CMAKE_CURRENT_SOURCE_DIR}/../qt/python/mantidqtpython) +if ( USE_PRIVATE_SIPPYQT4 ) + set ( _sip_include_dir ${PYQT4_SIP_INCLUDE_DIR} ) + set ( _sip_executable ${PYQT4_SIP_EXECUTABLE} ) +else () + set ( _sip_include_dir ${SIP_INCLUDE_DIR} ) + set ( _sip_executable ${SIP_EXECUTABLE} ) +endif () + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SIP_SRC_AUTO} - COMMAND ${SIP_EXECUTABLE} -I ${PYQT4_SIP_DIR} + COMMAND ${_sip_executable} -I ${PYQT4_SIP_DIR} ${MANTIDQTPYTHON_SIP_INCLUDES} ${PYQT4_SIP_FLAGS} -c ${CMAKE_CURRENT_BINARY_DIR} -j1 -w -o ${SIP_SPEC} - DEPENDS ${SIP_INCLUDE_DIR}/sip.h - src/qti.sip + DEPENDS src/qti.sip ${QTI_SIP_HDRS} ../qt/python/mantidqtpython/mantidqtpython_def.sip COMMENT "Generating python bindings using sip") -# Needed for sip.h header that can end up in a different place to to the main -# Python include directory -include_directories(SYSTEM ${SIP_INCLUDE_DIR}) -# Needed for sip generated files to find includes in src -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # # Specify the files that we need to pass to Qt macros @@ -671,9 +672,6 @@ enable_precompiled_headers(src/PrecompiledHeader.h ALL_SRC) qt4_wrap_ui(UI_HDRS ${UI_FILES}) -# The generated ui headers will go here: -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - # # Internal icon links # @@ -687,19 +685,16 @@ qt4_add_resources(RES_FILES # # Add the dependencies # - +# This must come before ParaView so Python gets picked up from our third-party on Windows +# and not the one Paraview is built with. Warnings from our external repo are all ignored +# but the ones built by ParaView are not. +include_directories(SYSTEM ${_sip_include_dir} ${PYTHON_INCLUDE_PATH}) if(MAKE_VATES) include(${PARAVIEW_USE_FILE}) endif() -include_directories(SYSTEM ${MUPARSER_INCLUDE_DIR}) -include_directories(${ZLIB_INCLUDE_DIRS}) - -include_directories(SYSTEM ${QWT5_INCLUDE_DIR}) find_package(QwtPlot3d REQUIRED) -include_directories(SYSTEM ${QWTPLOT3D_INCLUDE_DIR}) - find_package(QScintillaQt4 REQUIRED) # @@ -801,20 +796,31 @@ add_executable(MantidPlot ${CONFIG_RESET_SCRIPT_FILE} ${IPYTHON_INSTALL_FILES}) -target_include_directories(MantidPlot - PRIVATE ${SIP_INCLUDE_DIR} - src - src/lib/include - src/lib/3rdparty/qtcolorpicker/src - ../qt/widgets/common/inc - ../qt/widgets/instrumentview/inc - ../qt/widgets/sliceviewer/inc - ../qt/widgets/spectrumviewer/inc - ../qt/widgets/factory/inc - ../Framework/PythonInterface/inc) + +# Sip must be before Python for the case of our private sip module for RHEL +# so that it gets picked up before the system one if it exists +target_include_directories(MantidPlot SYSTEM PRIVATE + ${MUPARSER_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIRS} + ${QWT5_INCLUDE_DIR} + ${QWTPLOT3D_INCLUDE_DIR} +) +target_include_directories(MantidPlot PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + src + src/lib/include + src/lib/3rdparty/qtcolorpicker/src + ../qt/widgets/common/inc + ../qt/widgets/instrumentview/inc + ../qt/widgets/sliceviewer/inc + ../qt/widgets/spectrumviewer/inc + ../qt/widgets/factory/inc + ../Framework/PythonInterface/inc +) # GCC 8 onwards needs to disable functional casting at the Python interface -target_compile_options( MantidPlot PRIVATE +target_compile_options( MantidPlot PRIVATE $<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,8.0>>:-Wno-cast-function-type> ) # Library dependencies diff --git a/buildconfig/CMake/DetermineLinuxDistro.cmake b/buildconfig/CMake/DetermineLinuxDistro.cmake index 52936753319450a50bf2bcc123eaa81f99f1fa6a..5aad0c9e9cc0ee5f23f2ecc0529545e3f9699d31 100644 --- a/buildconfig/CMake/DetermineLinuxDistro.cmake +++ b/buildconfig/CMake/DetermineLinuxDistro.cmake @@ -9,7 +9,7 @@ if ( LSB_CMD ) string ( STRIP ${UNIX_DIST} UNIX_DIST ) string ( REGEX REPLACE "RedHatEnterpriseClient" "RedHatEnterprise" UNIX_DIST ${UNIX_DIST} ) string ( REGEX REPLACE "RedHatEnterpriseWorkstation" "RedHatEnterprise" UNIX_DIST ${UNIX_DIST} ) - # Make Scientific Linux and CentOS look like RHEL6 + # Make Scientific Linux and CentOS look like RHEL string ( REGEX REPLACE "Scientific" "RedHatEnterprise" UNIX_DIST ${UNIX_DIST} ) string ( REGEX REPLACE "CentOS" "RedHatEnterprise" UNIX_DIST ${UNIX_DIST} ) # get the codename diff --git a/buildconfig/CMake/ExternalSipPyQt4.cmake b/buildconfig/CMake/ExternalSipPyQt4.cmake new file mode 100644 index 0000000000000000000000000000000000000000..2aece3fb4f755a129f00183c2d892e7fc098263c --- /dev/null +++ b/buildconfig/CMake/ExternalSipPyQt4.cmake @@ -0,0 +1,82 @@ +include(ExternalProject) +include(ProcessorCount) + +set(_SIP_PYQT_DIR extern-pyt4-sip) +set(_SIP_PYQT_INSTALL_DIR ${_SIP_PYQT_DIR}/install) + +# sipdir - use different variables to standard sip installation to be able to distingish it +set(PYQT4_SIP_INCLUDE_DIR "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/include" CACHE STRING "sip include directory" FORCE) +set(PYQT4_SIP_EXECUTABLE "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/bin/sip" CACHE STRING "sip executable" FORCE) +set(PYQT4_SIP_VERSION "041307" CACHE STRING "sip hexadecimal string" FORCE) +set(PYQT4_SIP_VERSION_STR "4.19.7" CACHE STRING "sip version string" FORCE) +ExternalProject_Add(extern-pyqt4-sip + PREFIX ${_SIP_PYQT_DIR}/sip + INSTALL_DIR ${_SIP_PYQT_INSTALL_DIR} + URL https://www.riverbankcomputing.com/static/Downloads/sip/4.19.7/sip-4.19.7.tar.gz + URL_HASH MD5=ae4f2db79713046d61b2a44e5ee1e3ab + CONFIGURE_COMMAND "${PYTHON_EXECUTABLE}" "<SOURCE_DIR>/configure.py" + --sip-module=PyQt4.sip + --bindir=<INSTALL_DIR>/bin + --destdir=<INSTALL_DIR>/lib/site-packages + --incdir=<INSTALL_DIR>/include + --sipdir=<INSTALL_DIR>/share/sip + BUILD_COMMAND make 2> build.log +) + +# PyQt4 +set(PYQT4_VERSION "040c01" CACHE STRING "PyQt4's version as a 6-digit hexadecimal number" FORCE) +set(PYQT4_VERSION_STR "4.12.1" CACHE STRING "PyQt4's version as a human-readable string" FORCE) +set(PYQT4_VERSION_TAG "Qt_4_8_6" CACHE STRING "The Qt version tag used by PyQt4's .sip files" FORCE) +set(PYQT4_SIP_DIR "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/share/sip" CACHE PATH "The base directory where PyQt4's .sip files are installed" FORCE) +set(PYQT4_SIP_FLAGS "-x VendorID -t WS_X11 -x PyQt_NoPrintRangeBug -t Qt_4_8_6" CACHE STRING "The SIP flags used to build PyQt4" FORCE) +set(PRIVATE_PYQT_SITE_PACKAGES ${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/lib/site-packages) +set(_pyqt4_lib_site_packages ${PRIVATE_PYQT_SITE_PACKAGES}/PyQt4) + +# Write a wrapper pyuic script so it can find out internal copy of PyQt4 +set(PYQT4_PYUIC "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/internal-pyuic.py" CACHE STRING "Location of the pyuic script" FORCE) +configure_file(${CMAKE_MODULE_PATH}/internal-pyuic.py.in ${PYQT4_PYUIC} @ONLY) + +# Determine core count for make step +ProcessorCount(NPROCESSORS) +if(NPROCESSORS EQUAL 0) + set(NPROCESSORS 1) +endif() + +ExternalProject_Add(extern-pyqt4 + PREFIX ${_SIP_PYQT_DIR}/pyqt4 + INSTALL_DIR ${_SIP_PYQT_INSTALL_DIR} + URL https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.12.1/PyQt4_gpl_x11-4.12.1.tar.gz/download + URL_HASH MD5=0112e15858cd7d318a09e7366922f874 + PATCH_COMMAND patch -p1 --input ${CMAKE_SOURCE_DIR}/buildconfig/CMake/pyqt4_qreal_float_support.patch + COMMAND patch -p0 --input ${CMAKE_SOURCE_DIR}/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch + # patch configure to pick up sipconfig built above + COMMAND sed -i -e "/^import sipconfig/i sys.path.insert(0, \"${_pyqt4_lib_site_packages}\")" "<SOURCE_DIR>/configure.py" + CONFIGURE_COMMAND "${PYTHON_EXECUTABLE}" "<SOURCE_DIR>/configure.py" + --assume-shared + --confirm-license + --bindir=<INSTALL_DIR>/bin + --destdir=<INSTALL_DIR>/lib/site-packages + --sipdir=<INSTALL_DIR>/share/sip + --no-designer-plugin + --no-timestamp + --no-deprecated + --qmake=/usr/bin/qmake-qt4 + --no-qsci-api + BUILD_COMMAND make -j${NPROCESSORS} 2> build.log + DEPENDS extern-pyqt4-sip +) + +# Write out .pth file to find this. We ensure to insert our path ahead of others so it takes precendence over the system +# We assume we only have to support a single-configuration build type on Linux +file(WRITE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/private-pyqt4.pth +"import sys; sys.__plen = len(sys.path) +${PRIVATE_PYQT_SITE_PACKAGES} +${_pyqt4_lib_site_packages} +import sys; new = sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p = getattr(sys, '__egginsert', 0); sys.path[p:p] = new; sys.__egginsert = p + len(new) +") + +# Package PyQt. We assume this is for Python 3 +install(DIRECTORY ${PRIVATE_PYQT_SITE_PACKAGES}/PyQt4 + DESTINATION ${LIB_DIR} + PATTERN "__pycache__" EXCLUDE + PATTERN "port_v2" EXCLUDE) diff --git a/buildconfig/CMake/FindPyQt.py b/buildconfig/CMake/FindPyQt.py index 0da4e37568ef76f4df076577ef45164f8ff502e1..b25705f7c35b731171dd2c48885f807338bed77c 100644 --- a/buildconfig/CMake/FindPyQt.py +++ b/buildconfig/CMake/FindPyQt.py @@ -45,15 +45,18 @@ class PyQtConfig(object): raise RuntimeError("Unknown Qt version ({}) found. Unable to determine location of PyQt sip files." "Please update FindPyQt accordingly.".format(self.version_str[0])) else: - # RHEL has a separate python2-sip and python3-sip directory + # RH/Fedora have separate pythonX-sip or pythonXY-sip directories prefix_share = os.path.join(sys.prefix, 'share') - possible_sip_dirs = (os.path.join(prefix_share, 'sip', name), - os.path.join(prefix_share, - 'python{}-sip'.format(sys.version_info.major), - name)) + possible_sip_dirs = ( + 'python{}{}-sip'.format(sys.version_info.major, sys.version_info.minor), + 'python{}-sip'.format(sys.version_info.major), + 'sip' + ) for sip_dir in possible_sip_dirs: - if os.path.exists(sip_dir): - self.sip_dir = sip_dir + pyqt_sip_dir = os.path.join(prefix_share, sip_dir, name) + if os.path.exists(pyqt_sip_dir): + self.sip_dir = pyqt_sip_dir + break # Assume uic script is in uic submodule uic = __import__(name + '.uic', globals(), locals(), ['uic'], 0) diff --git a/buildconfig/CMake/LinuxPackageScripts.cmake b/buildconfig/CMake/LinuxPackageScripts.cmake index 5ea3e8c70b0a38fd87e02ed1e08e3365bc40f577..212664bbc679c1f778022f93b5d2a453852a398b 100644 --- a/buildconfig/CMake/LinuxPackageScripts.cmake +++ b/buildconfig/CMake/LinuxPackageScripts.cmake @@ -30,6 +30,9 @@ if ( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT ) set ( CMAKE_INSTALL_PREFIX /opt/mantid${CPACK_PACKAGE_SUFFIX} CACHE PATH "Install path" FORCE ) endif() +# Tell rpm to use the appropriate python executable +set(CPACK_RPM_SPEC_MORE_DEFINE "%define __python ${PYTHON_EXECUTABLE}") + # Tell rpm that this package does not own /opt /usr/share/{applications,pixmaps} # Required for Fedora >= 18 and RHEL >= 7 set ( CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /opt /usr/share/applications /usr/share/pixmaps ) @@ -69,6 +72,7 @@ print(sc.get_python_lib(plat_specific=True))" file ( WRITE ${CMAKE_CURRENT_BINARY_DIR}/mantid.pth.install "${CMAKE_INSTALL_PREFIX}/${BIN_DIR}\n" + "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}\n" ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/mantid.pth.install diff --git a/buildconfig/CMake/Packaging/launch_mantidplot.sh.in b/buildconfig/CMake/Packaging/launch_mantidplot.sh.in index 8f9a573c6bc3679f30059feaa4da16dd217d8e4f..ea5054cd8d3f5faab24db9c8619e25cf052f551d 100644 --- a/buildconfig/CMake/Packaging/launch_mantidplot.sh.in +++ b/buildconfig/CMake/Packaging/launch_mantidplot.sh.in @@ -19,6 +19,11 @@ if [ -n "${PYTHONPATH}" ]; then LOCAL_PYTHONPATH=${LOCAL_PYTHONPATH}:${PYTHONPATH} fi +# Find private sip module if it exists. Required by qtpy & IPython/external/qt_loader.py +if [ -f "${INSTALLDIR}/lib/PyQt4/sip.so" ]; then + LOCAL_PYTHONPATH=$LOCAL_PYTHONPATH:${INSTALLDIR}/lib/PyQt4 +fi + @GDB_DEFINITIONS@ # Launch diff --git a/buildconfig/CMake/Packaging/mantidpython.in b/buildconfig/CMake/Packaging/mantidpython.in index 1d4346bb3a8cc6987d6fcad7eb09f52e9faf74f5..fcda7c7e0e008ddef2c8da4f11380be7ef3e2458 100755 --- a/buildconfig/CMake/Packaging/mantidpython.in +++ b/buildconfig/CMake/Packaging/mantidpython.in @@ -20,7 +20,7 @@ fi PV_PLUGIN_PATH="${INSTALLDIR}/plugins/paraview/qt4" # Define where python libraries are -LOCAL_PYTHONPATH=${INSTALLDIR}/bin:@LOCAL_PYPATH@@PARAVIEW_PYTHON_PATHS@ +LOCAL_PYTHONPATH=@LOCAL_PYPATH@@PARAVIEW_PYTHON_PATHS@ if [ -n "${PYTHONPATH}" ]; then LOCAL_PYTHONPATH=${LOCAL_PYTHONPATH}:${PYTHONPATH} fi @@ -32,6 +32,13 @@ else LOCAL_QT_API="pyqt" # force to use qt4 fi +# Find private sip module if it exists. Required by qtpy +if [ -f "${INSTALLDIR}/lib/PyQt4/sip.so" ]; then + if [ "$LOCAL_QT_API" = "pyqt" ] || [ "$LOCAL_QT_API" = "pyqt4" ]; then + LOCAL_PYTHONPATH=$LOCAL_PYTHONPATH:${INSTALLDIR}/lib/PyQt4 + fi +fi + if [ -n "$1" ] && [ "$1" = "--classic" ]; then shift set -- @WRAPPER_PREFIX@@PYTHON_EXECUTABLE@ @PYTHON_ARGS@ "$@"@WRAPPER_POSTFIX@ diff --git a/buildconfig/CMake/PyQtFindImpl.cmake b/buildconfig/CMake/PyQtFindImpl.cmake index 3bfcf7a66f6bd20e4afc438f5f0641c21d347bcd..f75cce7b16b56b70cd3967fd5ebb1bd170ccda2b 100644 --- a/buildconfig/CMake/PyQtFindImpl.cmake +++ b/buildconfig/CMake/PyQtFindImpl.cmake @@ -27,6 +27,7 @@ function (find_pyqt major_version) if (NOT EXISTS ${_find_pyqt_py}) message(FATAL_ERROR "Failed to find FindPyQt.py in \"${CMAKE_MODULE_PATH}\"") endif() + execute_process (COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt_py} ${major_version} OUTPUT_VARIABLE _pyqt_config ERROR_VARIABLE _pyqt_config_err) if(CMAKE_HOST_WIN32 AND major_version EQUAL 4 AND _pyqt_config_err MATCHES "Qt: Untested Windows version 10.0 detected!") diff --git a/buildconfig/CMake/SipQtTargetFunctions.cmake b/buildconfig/CMake/SipQtTargetFunctions.cmake index 610c776bc56f7b820ca1c57341ec42b83cae5803..e3f73b4bbb112d190709d2e4b18994fe838d31e9 100644 --- a/buildconfig/CMake/SipQtTargetFunctions.cmake +++ b/buildconfig/CMake/SipQtTargetFunctions.cmake @@ -65,6 +65,14 @@ function ( mtd_add_sip_module ) endforeach () # Run sip code generator + if ( PARSED_PYQT_VERSION EQUAL 4 AND USE_PRIVATE_SIPPYQT4 ) + set ( _sip_include_dir ${PYQT4_SIP_INCLUDE_DIR} ) + set ( _sip_executable ${PYQT4_SIP_EXECUTABLE} ) + else () + set ( _sip_include_dir ${SIP_INCLUDE_DIR} ) + set ( _sip_executable ${SIP_EXECUTABLE} ) + endif () + set ( _module_spec ${CMAKE_CURRENT_BINARY_DIR}/${PARSED_MODULE_NAME}.sip ) configure_file ( ${_sipmodule_template_path} ${_module_spec} ) set ( _pyqt_sip_dir ${PYQT${PARSED_PYQT_VERSION}_SIP_DIR} ) @@ -73,10 +81,10 @@ function ( mtd_add_sip_module ) set ( _pyqt_sip_flags ${PYQT${PARSED_PYQT_VERSION}_SIP_FLAGS} ) set ( _sip_generated_cpp ${CMAKE_CURRENT_BINARY_DIR}/sip${PARSED_MODULE_NAME}part0.cpp ) add_custom_command ( OUTPUT ${_sip_generated_cpp} - COMMAND ${PYTHON_EXECUTABLE} ${_sip_wrapper} ${SIP_EXECUTABLE} + COMMAND ${PYTHON_EXECUTABLE} ${_sip_wrapper} ${_sip_executable} ${_sip_include_flags} ${_pyqt_sip_flags} -c ${CMAKE_CURRENT_BINARY_DIR} -j1 -w -e ${_module_spec} - DEPENDS ${_module_spec} ${_sip_include_deps} ${SIP_INCLUDE_DIR}/sip.h + DEPENDS ${_module_spec} ${_sip_include_deps} COMMENT "Generating ${PARSED_MODULE_NAME} python bindings with sip" ) @@ -84,13 +92,16 @@ function ( mtd_add_sip_module ) # Suppress Warnings about sip bindings have PyObject -> PyFunc casts which # is a valid pattern GCC8 onwards detects # GCC 8 onwards needs to disable functional casting at the Python interface - target_compile_options( ${PARSED_TARGET_NAME} PRIVATE + target_compile_options( ${PARSED_TARGET_NAME} PRIVATE $<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,8.0>>:-Wno-cast-function-type> ) - target_include_directories ( ${PARSED_TARGET_NAME} SYSTEM PRIVATE ${SIP_INCLUDE_DIR} ) + target_include_directories ( ${PARSED_TARGET_NAME} SYSTEM PRIVATE ${_sip_include_dir} ${PYTHON_INCLUDE_PATH}) target_include_directories ( ${PARSED_TARGET_NAME} PRIVATE ${PARSED_INCLUDE_DIRS} ) target_include_directories ( ${PARSED_TARGET_NAME} SYSTEM PRIVATE ${PARSED_SYSTEM_INCLUDE_DIRS} ) target_link_libraries ( ${PARSED_TARGET_NAME} PRIVATE ${PARSED_LINK_LIBS} ) + if ( PARSED_PYQT_VERSION EQUAL 4 AND USE_PRIVATE_SIPPYQT4 ) + add_dependencies( ${PARSED_TARGET_NAME} extern-pyqt4 ) + endif () # Set all required properties on the target set_target_properties ( ${PARSED_TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_NAME ${PARSED_MODULE_NAME} ) diff --git a/buildconfig/CMake/UiToPy.cmake b/buildconfig/CMake/UiToPy.cmake index 5793bcad87d73117007e96469fb0d6f187914f6d..e350af0904a99a59eab271dff9e3612596c5850e 100644 --- a/buildconfig/CMake/UiToPy.cmake +++ b/buildconfig/CMake/UiToPy.cmake @@ -4,7 +4,6 @@ function(UiToPy ui_files target_name) - set(py_exec ${PYTHON_EXECUTABLE}) set(py_uic_py ${PYQT4_PYUIC} ) # From FindPyQt4 set(ui_dir ${CMAKE_CURRENT_SOURCE_DIR}) @@ -17,13 +16,14 @@ function(UiToPy ui_files target_name) # Source file to generate from set( source_file ${ui_dir}/${ui_name}.ui ) # Command to run the translation - add_custom_command(OUTPUT ${generated_file} COMMAND ${py_exec} ${py_uic_py} ${source_file} -o ${generated_file} COMMAND ${py_exec} ${CMAKE_SOURCE_DIR}/buildconfig/wrap_pyui.py ${generated_file} DEPENDS ${source_file}) + add_custom_command(OUTPUT ${generated_file} COMMAND ${py_exec} ${py_uic_py} ${source_file} -o ${generated_file} COMMAND ${py_exec} ${CMAKE_SOURCE_DIR}/buildconfig/wrap_pyui.py ${generated_file} DEPENDS ${source_file}) # Record all generated files list(APPEND _outputs ${generated_file}) endforeach(ui_file) # Create a custom target add_custom_target(${target_name} DEPENDS ${_outputs}) - + if(USE_PRIVATE_SIPPYQT4) + add_dependencies(${target_name} extern-pyqt4) + endif() endfunction(UiToPy) - diff --git a/buildconfig/CMake/internal-pyuic.py.in b/buildconfig/CMake/internal-pyuic.py.in new file mode 100644 index 0000000000000000000000000000000000000000..6cd825792ca9ea5004688ad29c9ddf97d907e6a1 --- /dev/null +++ b/buildconfig/CMake/internal-pyuic.py.in @@ -0,0 +1,3 @@ +import sys +sys.path.insert(0, "@PRIVATE_PYQT_SITE_PACKAGES@") +import PyQt4.uic.pyuic diff --git a/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch b/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b524720bf727afdb8d7326e883e241ccbb14f00 --- /dev/null +++ b/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch @@ -0,0 +1,94 @@ +--- configure.py.orig 2020-01-09 15:07:19.231636923 +0000 ++++ configure.py 2020-01-09 15:10:28.159688544 +0000 +@@ -1,19 +1,19 @@ + # This script generates the PyQt configuration and generates the Makefiles. + # + # Copyright (c) 2016 Riverbank Computing Limited <info@riverbankcomputing.com> +-# ++# + # This file is part of PyQt4. +-# ++# + # This file may be used under the terms of the GNU General Public License + # version 3.0 as published by the Free Software Foundation and appearing in + # the file LICENSE included in the packaging of this file. Please review the + # following information to ensure the GNU General Public License version 3.0 + # requirements will be met: http://www.gnu.org/copyleft/gpl.html. +-# ++# + # If you do not wish to use this file under the terms of the GPL version 3.0 + # then you may purchase a commercial license. For more information contact + # info@riverbankcomputing.com. +-# ++# + # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +@@ -90,7 +90,7 @@ def find_default_qmake(): + + for d in path.split(os.pathsep): + qmake = os.path.join(d, base_qmake) +- ++ + if os.access(qmake, os.X_OK): + return qmake + +@@ -109,7 +109,7 @@ def create_optparser(): + if not os.path.isdir(value): + raise optparse.OptionValueError("'%s' is not a directory" % value) + setattr(parser.values, option.dest, os.path.abspath(value)) +- ++ + def store_abspath_file(option, opt_str, value, parser): + if not os.path.isfile(value): + raise optparse.OptionValueError("'%s' is not a file" % value) +@@ -342,8 +342,8 @@ class ConfigurePyQt4: + + check_module("QtGui", "qwidget.h", "new QWidget()") + check_module("QtHelp", "qhelpengine.h", "new QHelpEngine(\"foo\")") +- check_module("QtMultimedia", "QAudioDeviceInfo", +- "new QAudioDeviceInfo()") ++ # check_module("QtMultimedia", "QAudioDeviceInfo", ++ # "new QAudioDeviceInfo()") + check_module("QtNetwork", "qhostaddress.h", "new QHostAddress()") + + # Qt v4.7 was current when we added support for QtDBus and we didn't +@@ -364,14 +364,14 @@ class ConfigurePyQt4: + extra_libs=sql_libs) + check_module("QtSvg", "qsvgwidget.h", "new QSvgWidget()") + check_module("QtTest", "QtTest", "QTest::qSleep(0)") +- check_module("QtWebKit", "qwebpage.h", "new QWebPage()") ++ # check_module("QtWebKit", "qwebpage.h", "new QWebPage()") + check_module("QtXml", "qdom.h", "new QDomDocument()") + check_module("QtXmlPatterns", "qxmlname.h", "new QXmlName()") + check_module("phonon", "phonon/videowidget.h", + "new Phonon::VideoWidget()") +- check_module("QtAssistant", "qassistantclient.h", +- "new QAssistantClient(\"foo\")", extra_lib_dirs=ass_lib_dirs, +- extra_libs=ass_libs) ++ # check_module("QtAssistant", "qassistantclient.h", ++ # "new QAssistantClient(\"foo\")", extra_lib_dirs=ass_lib_dirs, ++ # extra_libs=ass_libs) + + if qt_shared == '': + sipconfig.inform("QtDesigner module disabled with static Qt libraries.") +@@ -503,8 +503,8 @@ class ConfigurePyQt4: + if "QtTest" in pyqt_modules: + generate_code("QtTest") + +- if "QtWebKit" in pyqt_modules: +- generate_code("QtWebKit") ++ # if "QtWebKit" in pyqt_modules: ++ # generate_code("QtWebKit") + + if "QtXml" in pyqt_modules: + generate_code("QtXml") +@@ -1511,7 +1511,7 @@ def needed_qt_libs(mname, qt_libs): + "QtSql": ["QtGui"], + "QtSvg": ["QtGui"], + "QtTest": ["QtGui"], +- "QtWebKit": ["QtNetwork", "QtGui"], ++ # "QtWebKit": ["QtNetwork", "QtGui"], + "QtXml": ["QtCore"], + "QtXmlPatterns": ["QtNetwork", "QtCore"], + "phonon": ["QtGui"], diff --git a/buildconfig/CMake/pyqt4_qreal_float_support.patch b/buildconfig/CMake/pyqt4_qreal_float_support.patch new file mode 100644 index 0000000000000000000000000000000000000000..d8c3ef74723e77f9ee28ca8303ebf7d669dc6708 --- /dev/null +++ b/buildconfig/CMake/pyqt4_qreal_float_support.patch @@ -0,0 +1,240 @@ +From: Michael Casadevall <mcasadevall@debian.org> +Date: Thu, 8 Oct 2015 12:56:35 -0700 +Subject: Add QList<double> support explicitly when qreal is not double + +--- + sip/QtCore/qlist.sip | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 224 insertions(+) + +diff --git a/sip/QtCore/qlist.sip b/sip/QtCore/qlist.sip +index 978e576..63002d2 100644 +--- a/sip/QtCore/qlist.sip ++++ b/sip/QtCore/qlist.sip +@@ -814,3 +814,227 @@ template<qreal, TYPE> + return sipGetState(sipTransferObj); + %End + }; ++ ++// If we're on an architecture where qreal != double, then we need to also ++// explicately handle doubles. On architectures where qreal == double, they ++// will automaticially be cast upwards ++ ++%If (!PyQt_qreal_double) ++ ++%If (Qt_4_3_0 -) ++// QList<QPair<double, double> > is implemented as a Python list of 2-element tuples. ++%MappedType QList<QPair<double, double> > ++{ ++%TypeHeaderCode ++#include <qlist.h> ++#include <qpair.h> ++%End ++ ++%ConvertFromTypeCode ++ // Create the list. ++ PyObject *l; ++ ++ if ((l = PyList_New(sipCpp->size())) == NULL) ++ return NULL; ++ ++ // Set the list elements. ++ for (int i = 0; i < sipCpp->size(); ++i) ++ { ++ const QPair<double, double> &p = sipCpp->at(i); ++ PyObject *pobj; ++ ++ if ((pobj = Py_BuildValue((char *)"dd", p.first, p.second)) == NULL) ++ { ++ Py_DECREF(l); ++ ++ return NULL; ++ } ++ ++ PyList_SET_ITEM(l, i, pobj); ++ } ++ ++ return l; ++%End ++ ++%ConvertToTypeCode ++ SIP_SSIZE_T len; ++ ++ // Check the type if that is all that is required. ++ if (sipIsErr == NULL) ++ { ++ if (!PySequence_Check(sipPy) || (len = PySequence_Size(sipPy)) < 0) ++ return 0; ++ ++ for (SIP_SSIZE_T i = 0; i < len; ++i) ++ { ++ PyObject *tup = PySequence_ITEM(sipPy, i); ++ ++ if (!PySequence_Check(tup) || PySequence_Size(tup) != 2) ++ return 0; ++ } ++ ++ return 1; ++ } ++ ++ QList<QPair<double, double> > *ql = new QList<QPair<double, double> >; ++ len = PySequence_Size(sipPy); ++ ++ for (SIP_SSIZE_T i = 0; i < len; ++i) ++ { ++ PyObject *tup = PySequence_ITEM(sipPy, i); ++ ++ double first = PyFloat_AsDouble(PySequence_ITEM(tup, 0)); ++ double second = PyFloat_AsDouble(PySequence_ITEM(tup, 1)); ++ ++ ql->append(QPair<double, double>(first, second)); ++ } ++ ++ *sipCppPtr = ql; ++ ++ return sipGetState(sipTransferObj); ++%End ++}; ++%End ++%If (Qt_4_3_0 -) ++// QList<QPair<double, TYPE> > is implemented as a Python list of 2-element tuples. ++template<double, TYPE> ++%MappedType QList<QPair<double, TYPE> > ++{ ++%TypeHeaderCode ++#include <qlist.h> ++#include <qpair.h> ++%End ++ ++%ConvertFromTypeCode ++ // Create the list. ++ PyObject *l; ++ ++ if ((l = PyList_New(sipCpp->size())) == NULL) ++ return NULL; ++ ++ // Set the list elements. ++ for (int i = 0; i < sipCpp->size(); ++i) ++ { ++ const QPair<double, TYPE> &p = sipCpp->at(i); ++ TYPE *t = new TYPE(p.second); ++ PyObject *pobj; ++ ++ if ((pobj = sipBuildResult(NULL, "(dB)", p.first, t, sipClass_TYPE, sipTransferObj)) == NULL) ++ { ++ Py_DECREF(l); ++ delete t; ++ ++ return NULL; ++ } ++ ++ PyList_SET_ITEM(l, i, pobj); ++ } ++ ++ return l; ++%End ++ ++%ConvertToTypeCode ++ SIP_SSIZE_T len; ++ ++ // Check the type if that is all that is required. ++ if (sipIsErr == NULL) ++ { ++ if (!PySequence_Check(sipPy) || (len = PySequence_Size(sipPy)) < 0) ++ return 0; ++ ++ for (SIP_SSIZE_T i = 0; i < len; ++i) ++ { ++ PyObject *tup = PySequence_ITEM(sipPy, i); ++ ++ if (!PySequence_Check(tup) || PySequence_Size(tup) != 2) ++ return 0; ++ ++ if (!sipCanConvertToInstance(PySequence_ITEM(tup, 1), sipClass_TYPE, SIP_NOT_NONE)) ++ return 0; ++ } ++ ++ return 1; ++ } ++ ++ QList<QPair<double, TYPE> > *ql = new QList<QPair<double, TYPE> >; ++ len = PySequence_Size(sipPy); ++ ++ for (SIP_SSIZE_T i = 0; i < len; ++i) ++ { ++ PyObject *tup = PySequence_ITEM(sipPy, i); ++ double d; ++ int state; ++ ++ d = PyFloat_AsDouble(PySequence_ITEM(tup, 0)); ++ TYPE *t = reinterpret_cast<TYPE *>(sipConvertToInstance(PySequence_ITEM(tup, 1), sipClass_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr)); ++ ++ if (*sipIsErr) ++ { ++ sipReleaseInstance(t, sipClass_TYPE, state); ++ ++ delete ql; ++ return 0; ++ } ++ ++ ql->append(QPair<double, TYPE>(d, *t)); ++ ++ sipReleaseInstance(t, sipClass_TYPE, state); ++ } ++ ++ *sipCppPtr = ql; ++ ++ return sipGetState(sipTransferObj); ++%End ++}; ++%End ++ ++// QList<double> is implemented as a Python list of doubles. ++%MappedType QList<double> ++{ ++%TypeHeaderCode ++#include <qlist.h> ++%End ++ ++%ConvertFromTypeCode ++ // Create the list. ++ PyObject *l; ++ ++ if ((l = PyList_New(sipCpp->size())) == NULL) ++ return NULL; ++ ++ // Set the list elements. ++ for (int i = 0; i < sipCpp->size(); ++i) ++ { ++ PyObject *pobj; ++ ++ if ((pobj = PyFloat_FromDouble(sipCpp->value(i))) == NULL) ++ { ++ Py_DECREF(l); ++ ++ return NULL; ++ } ++ ++ PyList_SET_ITEM(l, i, pobj); ++ } ++ ++ return l; ++%End ++ ++%ConvertToTypeCode ++ // Check the type if that is all that is required. ++ if (sipIsErr == NULL) ++ return (PySequence_Check(sipPy) && PySequence_Size(sipPy) >= 0); ++ ++ QList<double> *ql = new QList<double>; ++ SIP_SSIZE_T len = PySequence_Size(sipPy); ++ ++ for (SIP_SSIZE_T i = 0; i < len; ++i) ++ ql->append(PyFloat_AsDouble(PySequence_ITEM(sipPy, i))); ++ ++ *sipCppPtr = ql; ++ ++ return sipGetState(sipTransferObj); ++%End ++}; ++ ++%End diff --git a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec index 1dea7f388369cdfc1711a3fa6d85137fa25b273b..611aa020b90a1b9222b6a30682a4da72d0d7c5a6 100644 --- a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec +++ b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec @@ -1,11 +1,11 @@ -%if 0%{?fedora} || 0%{?rhel} >= 8 +%if 0%{?fedora} || 0%{?rhel} >= 7 %global with_python3 1 %else %global with_python3 0 %endif Name: mantid-developer -Version: 1.35 +Version: 1.37 Release: 1%{?dist} Summary: Meta Package to install dependencies for Mantid Development @@ -16,20 +16,23 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %{?fedora:Requires: rpmfusion-nonfree-release} %{?rhel:Requires: epel-release} -Requires: clang %{?fedora:Requires: cmake-gui} %{?rhel:Requires: cmake3-gui} +%{?fedora:Requires: python2-qtconsole} Requires: boost169-devel Requires: boost169-python2-devel +Requires: clang Requires: doxygen -Requires: gperftools-devel -Requires: gperftools-libs +Requires: dvipng Requires: gcc-c++ +Requires: git Requires: git-all +Requires: gperftools-devel +Requires: gperftools-libs +Requires: graphviz Requires: gsl-devel -Requires: hdf-devel Requires: hdf5-devel -Requires: h5py >= 2.3.1 +Requires: hdf-devel Requires: jsoncpp-devel >= 0.7.0 Requires: librdkafka-devel Requires: muParser-devel @@ -39,27 +42,40 @@ Requires: nexus-devel >= 4.2 Requires: ninja-build Requires: numpy Requires: OCE-devel +Requires: openssl-devel Requires: poco-devel >= 1.4.6 Requires: PyQt4-devel -Requires: python2-qt5-devel -Requires: python-QtPy -Requires: python-requests -Requires: python-devel -Requires: python-setuptools -Requires: python-ipython >= 1.1 +Requires: python2-h5py >= 2.3.1 Requires: python2-matplotlib Requires: python2-matplotlib-qt4 Requires: python2-matplotlib-qt4 -Requires: python-pip -%{?fedora:Requires: python2-qtconsole} -Requires: python-sphinx -Requires: python2-sphinx-bootstrap-theme -Requires: PyYAML Requires: python2-mock Requires: python2-psutil +Requires: python2-qt5-devel +%{?fedora:Requires: python2-qtconsole} +Requires: python2-sphinx-bootstrap-theme +Requires: python-devel Requires: python-enum34 +Requires: python-ipython >= 1.1 +Requires: python-pip +Requires: python-QtPy +Requires: python-requests +Requires: python-setuptools +Requires: python-sphinx +Requires: PyYAML Requires: qscintilla-devel +Requires: qscintilla-qt5-devel +Requires: qt5-qtbase-devel +Requires: qt5-qtbase-gui +Requires: qt5-qtimageformats +Requires: qt5-qtsvg +Requires: qt5-qttools-devel +Requires: qt5-qttools-libs-designer +Requires: qt5-qtwebkit-devel +Requires: qt5-qtx11extras +Requires: qt5-qtx11extras-devel Requires: qt-devel >= 4.6 +Requires: qtwebkit-devel Requires: qwt5-qt4-devel Requires: qwtplot3d-qt4-devel Requires: redhat-lsb @@ -68,61 +84,32 @@ Requires: scipy Requires: sip-devel Requires: tbb Requires: tbb-devel -Requires: git -Requires: openssl-devel Requires: texlive-latex Requires: texlive-latex-bin Requires: texlive-was Requires: tex-preview -Requires: dvipng -Requires: qt-devel -Requires: qtwebkit-devel -Requires: qt5-qtbase-devel -Requires: qt5-qtbase-gui -Requires: qt5-qtimageformats -Requires: qt5-qtsvg -Requires: qt5-qttools-devel -Requires: qt5-qttools-libs-designer -Requires: qt5-qtwebkit-devel -Requires: qt5-qtx11extras -Requires: qt5-qtx11extras-devel -Requires: qscintilla-qt5-devel -Requires: graphviz -%if %{with_python3} -Requires: python3-setuptools -Requires: python3-sip-devel -Requires: python3-PyQt4-devel -Requires: python3-qt5-devel -Requires: python3-QtPy -Requires: python3-numpy -Requires: python3-scipy -Requires: python3-scikit-image -Requires: python3-sphinx -Requires: python3-sphinx-bootstrap-theme -Requires: python3-dateutil -Requires: python3-h5py -Requires: python3-ipython-gui -Requires: python3-matplotlib -%{?fedora:Requires: python3-qtconsole} -Requires: python3-PyYAML -Requires: python3-mock -%{?fedora:Requires: python3-psutil} -%{?fedora:Requires: python3-requests} -Requires: boost-python3-devel -%endif +Requires: zeromq -%if 0%{?el7} -Requires: python36-setuptools -Requires: python36-qt5-devel -Requires: python36-numpy -Requires: python36-scipy -Requires: python36-sphinx -Requires: python36-dateutil -Requires: python36-PyYAML -Requires: python36-mock -Requires: python36-psutil -Requires: python36-requests +%if %{with_python3} Requires: boost169-python3-devel +Requires: python%{python3_pkgversion}-dateutil +Requires: python%{python3_pkgversion}-h5py +Requires: python%{python3_pkgversion}-ipython +Requires: python%{python3_pkgversion}-ipython-gui +Requires: python%{python3_pkgversion}-matplotlib-qt5 +Requires: python%{python3_pkgversion}-numpy +Requires: python%{python3_pkgversion}-psutil +%{?fedora:Requires: python%{python3_pkgversion}-PyQt4-devel} +Requires: python%{python3_pkgversion}-PyYAML +Requires: python%{python3_pkgversion}-qt5-devel +%{?fedora:Requires: python%{python3_pkgversion}-qtconsole} +Requires: python%{python3_pkgversion}-QtPy +Requires: python%{python3_pkgversion}-requests +Requires: python%{python3_pkgversion}-scipy +Requires: python%{python3_pkgversion}-setuptools +Requires: python%{python3_pkgversion}-sphinx +Requires: python%{python3_pkgversion}-sphinx-bootstrap-theme +Requires: python%{python3_pkgversion}-PyYAML %endif BuildArch: noarch @@ -146,6 +133,11 @@ required for Mantid development. %files %changelog +* Thu Jan 16 2020 Martyn Gigg <martyn.gigg@stfc.ac.uk> +- Merge fedora and rhel python 3 packages using python3_pkgversion + +* Tue Jan 07 2020 Martyn Gigg <martyn.gigg@stfc.ac.uk> +- Add remaining python36 packages required for mantid. * Tue Dec 03 2019 David Fairbrother <david.fairbrother@stfc.ac.uk> - Added Python Enum34 back-port to the required Python dependencies diff --git a/qt/applications/workbench/workbench/plotting/figureerrorsmanager.py b/qt/applications/workbench/workbench/plotting/figureerrorsmanager.py index f77488c193feb767a6c6a1aa1747c750a001b2d8..ac8d16650e1b1d1cb826c9601b41b6c73f3e8b80 100644 --- a/qt/applications/workbench/workbench/plotting/figureerrorsmanager.py +++ b/qt/applications/workbench/workbench/plotting/figureerrorsmanager.py @@ -12,8 +12,8 @@ from matplotlib.container import ErrorbarContainer from matplotlib.lines import Line2D from mantid.plots import MantidAxes from mantid.plots.helperfunctions import get_data_from_errorbar_container, set_errorbars_hidden +from mantid.plots.legend import LegendProperties from mantidqt.widgets.plotconfigdialog.curvestabwidget import curve_has_errors, CurveProperties, remove_curve_from_ax -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties class FigureErrorsManager(object): diff --git a/qt/python/mantidqt/CMakeLists.txt b/qt/python/mantidqt/CMakeLists.txt index 9b9f0c6aa1d0b80c3285a06b3c8ca743695b9e6e..9d3c39a7bfb43073dda0e5d9aa51e831634fbcc8 100644 --- a/qt/python/mantidqt/CMakeLists.txt +++ b/qt/python/mantidqt/CMakeLists.txt @@ -38,9 +38,6 @@ if(ENABLE_MANTIDPLOT) ${CMAKE_CURRENT_LIST_DIR} ${COMMON_SIP_DIR} ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/core/inc - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} LINK_LIBS ${common_link_libs} MantidQtWidgetsCommonQt4 @@ -72,9 +69,6 @@ if(ENABLE_WORKBENCH) ${CMAKE_CURRENT_LIST_DIR} ${COMMON_SIP_DIR} ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/core/inc - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} LINK_LIBS MantidQtWidgetsCommonQt5 ${common_link_libs} diff --git a/qt/python/mantidqt/icons/CMakeLists.txt b/qt/python/mantidqt/icons/CMakeLists.txt index c4f3820ee5865c74bb63c93ce1975a7167c8c193..b669302bedc108ad9dc66a6c32385fcebbf5628f 100644 --- a/qt/python/mantidqt/icons/CMakeLists.txt +++ b/qt/python/mantidqt/icons/CMakeLists.txt @@ -15,9 +15,6 @@ if(ENABLE_MANTIDPLOT) ${COMMON_SIP_DIR} ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/core/inc ${ICONS_INC_DIR} - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} LINK_LIBS MantidQtIconsQt4 Qt4::QtCore @@ -44,9 +41,6 @@ if(ENABLE_WORKBENCH) ${COMMON_SIP_DIR} ${ICONS_INC_DIR} ${CMAKE_SOURCE_DIR}/Framework/PythonInterface/core/inc - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} LINK_LIBS MantidQtIconsQt5 Qt5::Core diff --git a/qt/python/mantidqt/project/plotsloader.py b/qt/python/mantidqt/project/plotsloader.py index 309998423ad26e10d528cf38546021858f0e1b0e..30505f16ee118ad6e51fc158c92b527df0f2765e 100644 --- a/qt/python/mantidqt/project/plotsloader.py +++ b/qt/python/mantidqt/project/plotsloader.py @@ -16,9 +16,10 @@ from matplotlib import axis, ticker # noqa from mantid import logger from mantid.api import AnalysisDataService as ADS +from mantid.plots.legend import LegendProperties # Constants set in workbench.plotting.functions but would cause backwards reliability from mantidqt.plotting.functions import pcolormesh -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties + SUBPLOT_WSPACE = 0.5 SUBPLOT_HSPACE = 0.5 diff --git a/qt/python/mantidqt/project/plotssaver.py b/qt/python/mantidqt/project/plotssaver.py index 615fd2dab26a51ab5dddd8f0e123f66aad1f1fcd..2622abeac9ea197d8b944400e44533dcd4b73cd4 100644 --- a/qt/python/mantidqt/project/plotssaver.py +++ b/qt/python/mantidqt/project/plotssaver.py @@ -13,7 +13,7 @@ from matplotlib import ticker from matplotlib.image import AxesImage from mantid import logger -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties +from mantid.plots.legend import LegendProperties try: from matplotlib.colors import to_hex diff --git a/qt/python/mantidqt/project/test/test_plotssaver.py b/qt/python/mantidqt/project/test/test_plotssaver.py index c2d6dc985d86846a5b5755fd06d0b9d42b3e4476..5c6672e6ee0894ead41ab068e5b187425c25ac4b 100644 --- a/qt/python/mantidqt/project/test/test_plotssaver.py +++ b/qt/python/mantidqt/project/test/test_plotssaver.py @@ -9,7 +9,6 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) import matplotlib -import platform import unittest from mantid.api import AnalysisDataService as ADS @@ -33,11 +32,11 @@ class PlotsSaverTest(unittest.TestCase): u'background_color': u'#ffffff', u'edge_color': u'#000000', u'transparency': 0.5, - u'entries_font': u'Bitstream Vera Sans', - u'entries_size': 10, + u'entries_font': u'DejaVu Sans', + u'entries_size': 10.0, u'entries_color': u'#000000', - u'title_font': u'Bitstream Vera Sans', - u'title_size': 12, + u'title_font': u'DejaVu Sans', + u'title_size': 12.0, u'title_color': u'#000000', u'marker_size': 2.0, u'box_visible': True, @@ -128,11 +127,6 @@ class PlotsSaverTest(unittest.TestCase): self.loader_plot_dict[u'creationArguments'] = [[{u"specNum": 2, "function": "plot"}]] - # The original font isn't available on Windows so it has to be changed. - if platform.system() == "Windows": - self.loader_plot_dict[u'axes'][0][u'legend'][u'entries_font'] = 'DejaVu Sans' - self.loader_plot_dict[u'axes'][0][u'legend'][u'title_font'] = 'DejaVu Sans' - self.maxDiff = None self.assertDictEqual(return_value, self.loader_plot_dict) @@ -142,11 +136,6 @@ class PlotsSaverTest(unittest.TestCase): expected_value = self.loader_plot_dict["axes"][0] - # The original font isn't available on Windows so it has to be changed. - if platform.system() == "Windows": - self.loader_plot_dict[u'axes'][0][u'legend'][u'entries_font'] = 'DejaVu Sans' - self.loader_plot_dict[u'axes'][0][u'legend'][u'title_font'] = 'DejaVu Sans' - self.maxDiff = None self.assertDictEqual(return_value, expected_value) diff --git a/qt/python/mantidqt/widgets/codeeditor/completion.py b/qt/python/mantidqt/widgets/codeeditor/completion.py index d5290d19f1ff06ca625b9dd5248965869e04d27c..6019a7394bcc801ffbd558f18a2935e2553c4fcd 100644 --- a/qt/python/mantidqt/widgets/codeeditor/completion.py +++ b/qt/python/mantidqt/widgets/codeeditor/completion.py @@ -71,7 +71,7 @@ def get_builtin_argspec(builtin): if not doc_string: return None func_descriptor = doc_string.split('\n')[0].strip() - if re.search(builtin.__name__ + "\([\[\*a-zA-Z_].*\)", func_descriptor): + if re.search(builtin.__name__ + r"\([\[\*a-zA-Z_].*\)", func_descriptor): args_string = func_descriptor[func_descriptor.find('(') + 1:func_descriptor.rfind(')')] all_args_list = args_string.split(', ') args = [] diff --git a/qt/python/mantidqt/widgets/instrumentview/CMakeLists.txt b/qt/python/mantidqt/widgets/instrumentview/CMakeLists.txt index a2603e5a518875bfe3bba7570ededfb8d270a870..4b171ed2a4f77167de990a7d87b54df26d08f4f1 100644 --- a/qt/python/mantidqt/widgets/instrumentview/CMakeLists.txt +++ b/qt/python/mantidqt/widgets/instrumentview/CMakeLists.txt @@ -10,9 +10,6 @@ mtd_add_sip_module(MODULE_NAME _instrumentviewqt5 TARGET_NAME mantidqt_instrumentviewqt5 SIP_SRCS _instrumentview.sip PYQT_VERSION 5 - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} LINK_LIBS ${common_link_libs} MantidQtWidgetsInstrumentViewQt5 diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/colorselector.py b/qt/python/mantidqt/widgets/plotconfigdialog/colorselector.py index 28cd82e7ed12864867d3ea55e8b11ca229c2772c..5e72ce5576633d10b0cca9f18b1f70f45cdf2b8a 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/colorselector.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/colorselector.py @@ -8,22 +8,14 @@ from __future__ import (absolute_import, unicode_literals) -from matplotlib import colors, rcParams +from mantid.plots.legend import convert_color_to_hex +from matplotlib import rcParams from qtpy.QtCore import QRegExp from qtpy.QtGui import QColor, QPalette, QRegExpValidator from qtpy.QtWidgets import (QWidget, QLineEdit, QPushButton, QHBoxLayout, QColorDialog) -def convert_color_to_hex(color): - """Convert a matplotlib color to its hex form""" - try: - return colors.cnames[color] - except (KeyError, TypeError): - rgb = colors.colorConverter.to_rgb(color) - return colors.rgb2hex(rgb) - - MPL_DEFAULT = convert_color_to_hex(rcParams['lines.color']) diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/curvestabwidget/presenter.py b/qt/python/mantidqt/widgets/plotconfigdialog/curvestabwidget/presenter.py index a634b85b517b1ddb427f862dd76a11f5f081a908..613c8c8d1c582e3d5dc0402344b722e08e604695 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/curvestabwidget/presenter.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/curvestabwidget/presenter.py @@ -8,12 +8,12 @@ from __future__ import (absolute_import, unicode_literals) +from mantid.plots.legend import LegendProperties from mantidqt.utils.qt import block_signals from mantidqt.widgets.plotconfigdialog import get_axes_names_dict, curve_in_ax from mantidqt.widgets.plotconfigdialog.curvestabwidget import ( CurveProperties, curve_has_errors, remove_curve_from_ax) from mantidqt.widgets.plotconfigdialog.curvestabwidget.view import CurvesTabWidgetView -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties from workbench.plotting.figureerrorsmanager import FigureErrorsManager diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/__init__.py b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/__init__.py index 5e5ffb2aea1f1e66d05ccd6c287e3fe352bb7dba..db65bfdd56145fdd2d6d2eccf8d7684e66930c50 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/__init__.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/__init__.py @@ -7,155 +7,3 @@ # This file is part of the mantid workbench. from __future__ import (absolute_import, unicode_literals) - -from mantid.plots.utility import legend_set_draggable -from mantidqt.widgets.plotconfigdialog.colorselector import convert_color_to_hex -import matplotlib -from matplotlib.patches import BoxStyle - -import sys - - -class LegendProperties(dict): - def __getattr__(self, item): - return self[item] - - @classmethod - def from_legend(cls, legend): - props = dict() - - props['visible'] = legend.get_visible() - - title = legend.get_title() - if sys.version_info[0] >= 3: - if isinstance(title.get_text(), str): - props['title'] = title.get_text() - else: - props['title'] = None - else: - if isinstance(title.get_text(), unicode): - props['title'] = title.get_text() - else: - props['title'] = None - - props['title_font'] = title.get_fontname() - props['title_size'] = title.get_fontsize() - props['title_color'] = convert_color_to_hex(title.get_color()) - - props['box_visible'] = legend.get_frame_on() - - box = legend.get_frame() - props['background_color'] = convert_color_to_hex(box.get_facecolor()) - props['edge_color'] = convert_color_to_hex(box.get_edgecolor()) - props['transparency'] = box.get_alpha() - - text = legend.get_texts()[0] - props['entries_font'] = text.get_fontname() - props['entries_size'] = text.get_fontsize() - props['entries_color'] = convert_color_to_hex(text.get_color()) - - props['marker_size'] = legend.handlelength - props['shadow'] = legend.shadow - - boxstyle = legend.legendPatch.get_boxstyle() - if isinstance(boxstyle, BoxStyle.Round): - props['round_edges'] = True - else: - props['round_edges'] = False - - props['columns'] = legend._ncol - props['column_spacing'] = legend.columnspacing - props['label_spacing'] = legend.labelspacing - - position = legend._legend_handle_box.get_children()[0].align - if position == "baseline": - props['marker_position'] = "Left of Entries" - else: - props['marker_position'] = "Right of Entries" - - props['markers'] = legend.numpoints - props['border_padding'] = legend.borderpad - props['marker_label_padding'] = legend.handletextpad - - return cls(props) - - @classmethod - def from_view(cls, view): - props = dict() - props['visible'] = not view.hide_legend_check_box.isChecked() - props['title'] = view.get_title() - props['background_color'] = view.get_background_color() - props['edge_color'] = view.get_edge_color() - props['transparency'] = (100-float(view.get_transparency_spin_box_value()))/100 - props['entries_font'] = view.get_entries_font() - props['entries_size'] = view.get_entries_size() - props['entries_color'] = view.get_entries_color() - props['title_font'] = view.get_title_font() - props['title_size'] = view.get_title_size() - props['title_color'] = view.get_title_color() - props['marker_size'] = view.get_marker_size() - props['box_visible'] = not view.get_hide_box() - return cls(props) - - @classmethod - def from_view_advanced(cls, view): - props = dict() - props['shadow'] = view.get_shadow() - props['round_edges'] = view.get_round_edges() - props['columns'] = view.get_number_of_columns() - props['column_spacing'] = view.get_column_spacing() - props['label_spacing'] = view.get_label_spacing() - props['marker_position'] = view.get_marker_position() - props['markers'] = view.get_number_of_markers() - props['border_padding'] = view.get_border_padding() - props['marker_label_padding'] = view.get_marker_label_padding() - return cls(props) - - @classmethod - def create_legend(cls, props, ax): - if int(matplotlib.__version__[0]) >= 2: - legend = ax.legend(ncol=props['columns'], - prop={'size': props['entries_size']}, - numpoints=props['markers'], - markerfirst=props['marker_position'] == "Left of Entries", - frameon=props['box_visible'], - fancybox=props['round_edges'], - shadow=props['shadow'], - framealpha=props['transparency'], - facecolor=props['background_color'], - edgecolor=props['edge_color'], - title=props['title'], - borderpad=props['border_padding'], - labelspacing=props['label_spacing'], - handlelength=props['marker_size'], - handletextpad=props['marker_label_padding'], - columnspacing=props['column_spacing']) - else: - legend = ax.legend(ncol=props['columns'], - prop={'size': props['entries_size']}, - numpoints=props['markers'], - markerfirst=props['marker_position'] == "Left of Entries", - frameon=props['box_visible'], - fancybox=props['round_edges'], - shadow=props['shadow'], - framealpha=props['transparency'], - title=props['title'], - borderpad=props['border_padding'], - labelspacing=props['label_spacing'], - handlelength=props['marker_size'], - handletextpad=props['marker_label_padding'], - columnspacing=props['column_spacing']) - - title = legend.get_title() - title.set_fontname(props['title_font']) - title.set_fontsize(props['title_size']) - title.set_color(props['title_color']) - - for text in legend.get_texts(): - text.set_fontname(props['entries_font']) - text.set_fontsize(props['entries_size']) - text.set_color(props['entries_color']) - - legend.set_visible(props['visible']) - - legend_set_draggable(legend, True) diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/advancedlegendoptionsdialog/view.py b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/advancedlegendoptionsdialog/view.py index f8d52ef6f10b9e257f3b67b4582658727505e068..aeb8953684ace67c7cd50df244fcf0398b704450 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/advancedlegendoptionsdialog/view.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/advancedlegendoptionsdialog/view.py @@ -12,8 +12,8 @@ from qtpy.QtCore import Qt, QSize from qtpy.QtGui import QIcon from qtpy.QtWidgets import QDialog +from mantid.plots.legend import LegendProperties from mantidqt.utils.qt import load_ui -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties class AdvancedLegendOptionsView(QDialog): diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/presenter.py b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/presenter.py index d93aac576de27500dffe04ff5d8d227dafe7c4ee..7e46f40b31d7dbaca54981b25802b0e151dfec3d 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/presenter.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/presenter.py @@ -8,8 +8,8 @@ from __future__ import (absolute_import, unicode_literals) +from mantid.plots.legend import LegendProperties from mantidqt.widgets.plotconfigdialog.legendtabwidget.view import LegendTabWidgetView -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties import matplotlib import matplotlib.font_manager diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/view.py b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/view.py index 44e930baad4cf1f5700e100d3abdcde0d3b250cf..03688639f8b6562fc1a4f83d731b438ac8a818da 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/view.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/legendtabwidget/view.py @@ -11,9 +11,9 @@ from __future__ import (absolute_import, unicode_literals) from qtpy.QtCore import Qt from qtpy.QtWidgets import QWidget +from mantid.plots.legend import LegendProperties from mantidqt.utils.qt import load_ui from mantidqt.widgets.plotconfigdialog.colorselector import ColorSelector -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties from mantidqt.widgets.plotconfigdialog.legendtabwidget.advancedlegendoptionsdialog.view import AdvancedLegendOptionsView diff --git a/qt/python/mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py b/qt/python/mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py index 142baa29fbdb5d94be52dbe0d96270873ac130f7..a018b5bb42f9a4a521dc69324804a95daad59ead 100644 --- a/qt/python/mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py +++ b/qt/python/mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py @@ -16,12 +16,12 @@ from matplotlib.colors import LogNorm from matplotlib.patches import BoxStyle from matplotlib.pyplot import figure +from mantid.plots.legend import LegendProperties from mantid.py3compat.mock import Mock, patch from mantidqt.widgets.plotconfigdialog.colorselector import convert_color_to_hex from mantidqt.widgets.plotconfigdialog.axestabwidget import AxProperties from mantidqt.widgets.plotconfigdialog.imagestabwidget import ImageProperties from mantidqt.widgets.plotconfigdialog.curvestabwidget import CurveProperties -from mantidqt.widgets.plotconfigdialog.legendtabwidget import LegendProperties from mantidqt.widgets.plotconfigdialog.presenter import PlotConfigDialogPresenter AX_VIEW = 'mantidqt.widgets.plotconfigdialog.axestabwidget.presenter.AxesTabWidgetView' diff --git a/qt/python/mantidqtpython/CMakeLists.txt b/qt/python/mantidqtpython/CMakeLists.txt index 12e643447252a9f92fe42edf8012e8601803e112..ed8af025ecd28e357f95a292cbb99c8732a78882 100644 --- a/qt/python/mantidqtpython/CMakeLists.txt +++ b/qt/python/mantidqtpython/CMakeLists.txt @@ -89,9 +89,6 @@ mtd_add_sip_module(MODULE_NAME mantidqtpython ${CMAKE_CURRENT_LIST_DIR} ${COMMON_SIP_DIR} ../../../Framework/PythonInterface/core/inc - SYSTEM_INCLUDE_DIRS - ${PYTHON_INCLUDE_PATH} - ${SIP_INCLUDE_DIR} PYQT_VERSION 4 LINK_LIBS ${TCMALLOC_LIBRARIES_LINKTIME} diff --git a/scripts/HFIR_4Circle_Reduction/process_mask.py b/scripts/HFIR_4Circle_Reduction/process_mask.py index 39be7b70ce638cda69c055ea43eb3f7d0d00e092..700e82e2db96fa4d3f6ad7e0df2437e87c8b3974 100644 --- a/scripts/HFIR_4Circle_Reduction/process_mask.py +++ b/scripts/HFIR_4Circle_Reduction/process_mask.py @@ -4,6 +4,8 @@ # NScD Oak Ridge National Laboratory, European Spallation Source # & Institut Laue - Langevin # SPDX - License - Identifier: GPL - 3.0 + +from __future__ import print_function + import math import numpy import re @@ -35,7 +37,7 @@ def parse_mask(xml_name): det_range_list = re.split(',', det_list_str) for det_range in det_range_list: - print det_range + print(det_range) # int_count = 0