mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-09 00:04:30 -05:00
feat(ICCProfile): Add an action to save an ICC profile file
This commit is contained in:
parent
b1181118a7
commit
76a4202f7e
@ -95,6 +95,16 @@ message
|
|||||||
.. versionadded:: 3.40
|
.. versionadded:: 3.40
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
static QString saveIccProfile( const QColorSpace &colorSpace, const QString &iccProfileFilePath );
|
||||||
|
%Docstring
|
||||||
|
Save color space ``colorSpace`` to an ICC profile file ``iccProfileFilePath``.
|
||||||
|
|
||||||
|
:return: error message if an error occurred else empty string.
|
||||||
|
|
||||||
|
.. versionadded:: 3.40
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -95,6 +95,16 @@ message
|
|||||||
.. versionadded:: 3.40
|
.. versionadded:: 3.40
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
static QString saveIccProfile( const QColorSpace &colorSpace, const QString &iccProfileFilePath );
|
||||||
|
%Docstring
|
||||||
|
Save color space ``colorSpace`` to an ICC profile file ``iccProfileFilePath``.
|
||||||
|
|
||||||
|
:return: error message if an error occurred else empty string.
|
||||||
|
|
||||||
|
.. versionadded:: 3.40
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -138,6 +138,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa
|
|||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
connect( mAddIccProfile, &QToolButton::clicked, this, static_cast<void ( QgsProjectProperties::* )()>( &QgsProjectProperties::addIccProfile ) );
|
connect( mAddIccProfile, &QToolButton::clicked, this, static_cast<void ( QgsProjectProperties::* )()>( &QgsProjectProperties::addIccProfile ) );
|
||||||
connect( mRemoveIccProfile, &QToolButton::clicked, this, &QgsProjectProperties::removeIccProfile );
|
connect( mRemoveIccProfile, &QToolButton::clicked, this, &QgsProjectProperties::removeIccProfile );
|
||||||
|
connect( mSaveIccProfile, &QToolButton::clicked, this, &QgsProjectProperties::saveIccProfile );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
|
// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
|
||||||
@ -1042,6 +1043,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa
|
|||||||
mColorSpaceName->setVisible( false );
|
mColorSpaceName->setVisible( false );
|
||||||
mAddIccProfile->setVisible( false );
|
mAddIccProfile->setVisible( false );
|
||||||
mRemoveIccProfile->setVisible( false );
|
mRemoveIccProfile->setVisible( false );
|
||||||
|
mSaveIccProfile->setVisible( false );
|
||||||
#endif
|
#endif
|
||||||
// Default alpha transparency
|
// Default alpha transparency
|
||||||
mDefaultOpacityWidget->setOpacity( QgsProject::instance()->styleSettings()->defaultSymbolOpacity() );
|
mDefaultOpacityWidget->setOpacity( QgsProject::instance()->styleSettings()->defaultSymbolOpacity() );
|
||||||
@ -2736,10 +2738,27 @@ void QgsProjectProperties::removeIccProfile()
|
|||||||
updateColorSpaceWidgets();
|
updateColorSpaceWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsProjectProperties::saveIccProfile()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save ICC profile" ), QDir::homePath(),
|
||||||
|
tr( "ICC profile files (*.icc *.ICC)" ) );
|
||||||
|
|
||||||
|
if ( fileName.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString error = QgsColorUtils::saveIccProfile( mColorSpace, fileName );
|
||||||
|
if ( !error.isEmpty() )
|
||||||
|
{
|
||||||
|
QMessageBox::warning( this, tr( "Save ICC profile" ), error );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsProjectProperties::updateColorSpaceWidgets()
|
void QgsProjectProperties::updateColorSpaceWidgets()
|
||||||
{
|
{
|
||||||
mColorSpaceName->setText( mColorSpace.isValid() ? mColorSpace.description() : tr( "<i>None</i>" ) );
|
mColorSpaceName->setText( mColorSpace.isValid() ? mColorSpace.description() : tr( "<i>None</i>" ) );
|
||||||
mRemoveIccProfile->setEnabled( mColorSpace.isValid() );
|
mRemoveIccProfile->setEnabled( mColorSpace.isValid() );
|
||||||
|
mSaveIccProfile->setEnabled( mColorSpace.isValid() );
|
||||||
|
|
||||||
// force color model index according to color space one
|
// force color model index according to color space one
|
||||||
if ( mColorSpace.isValid() )
|
if ( mColorSpace.isValid() )
|
||||||
|
|||||||
@ -222,6 +222,11 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui:
|
|||||||
*/
|
*/
|
||||||
void removeIccProfile();
|
void removeIccProfile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever user select the save ICC profile button
|
||||||
|
*/
|
||||||
|
void saveIccProfile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update color space widget according to current project color space
|
* Update color space widget according to current project color space
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -377,6 +377,22 @@ QColorSpace QgsColorUtils::iccProfile( const QString &iccProfileFilePath, QStrin
|
|||||||
return colorSpace;
|
return colorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString QgsColorUtils::saveIccProfile( const QColorSpace &colorSpace, const QString &iccProfileFilePath )
|
||||||
|
{
|
||||||
|
if ( !colorSpace.isValid() )
|
||||||
|
return QObject::tr( "Invalid ICC profile" );
|
||||||
|
|
||||||
|
QFile iccProfile( iccProfileFilePath );
|
||||||
|
if ( !iccProfile.open( QIODevice::WriteOnly ) )
|
||||||
|
return QObject::tr( "File access error '%1'" ).arg( iccProfileFilePath );
|
||||||
|
|
||||||
|
if ( iccProfile.write( colorSpace.iccProfile() ) < 0 )
|
||||||
|
return QObject::tr( "Error while writing to file '%1'" ).arg( iccProfileFilePath );
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
|
|
||||||
Qgis::ColorModel QgsColorUtils::toColorModel( QColorSpace::ColorModel colorModel, bool *ok )
|
Qgis::ColorModel QgsColorUtils::toColorModel( QColorSpace::ColorModel colorModel, bool *ok )
|
||||||
|
|||||||
@ -108,6 +108,15 @@ class CORE_EXPORT QgsColorUtils
|
|||||||
*/
|
*/
|
||||||
static QColorSpace iccProfile( const QString &iccProfileFilePath, QString &errorMsg SIP_OUT );
|
static QColorSpace iccProfile( const QString &iccProfileFilePath, QString &errorMsg SIP_OUT );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save color space \a colorSpace to an ICC profile file \a iccProfileFilePath.
|
||||||
|
* \returns error message if an error occurred else empty string.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.40
|
||||||
|
*/
|
||||||
|
static QString saveIccProfile( const QColorSpace &colorSpace, const QString &iccProfileFilePath );
|
||||||
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1500,17 +1500,45 @@
|
|||||||
<string notr="true">projstyles</string>
|
<string notr="true">projstyles</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<item row="6" column="0" colspan="3">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="cbxStyleRandomColors">
|
<widget class="QLabel" name="mIccProfileLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Assign random colors to symbols</string>
|
<string>ICC Profile</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="label_27">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Color model</string>
|
<string>Opacity</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" colspan="4">
|
||||||
|
<widget class="QgsOpacityWidget" name="mDefaultOpacityWidget" native="true">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QToolButton" name="mAddIccProfile">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Load an ICC profile file and attach it to the project.</p><p>Color model will be updated accordingly.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../images/images.qrc">
|
||||||
|
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="4">
|
||||||
|
<widget class="QComboBox" name="mColorModel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Color model used as default when selecting a color in the whole application.</p><p>Any color defined in a different color model than the one specified here will be converted to this color model when exporting a layout.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1535,45 +1563,31 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_27">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Opacity</string>
|
<string>Color model</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="6" column="0" colspan="3">
|
||||||
<widget class="QLabel" name="mIccProfileLabel">
|
<widget class="QCheckBox" name="cbxStyleRandomColors">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ICC Profile</string>
|
<string>Assign random colors to symbols</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="3">
|
<item row="1" column="3">
|
||||||
<widget class="QToolButton" name="mAddIccProfile">
|
<widget class="QToolButton" name="mSaveIccProfile">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Load an ICC profile file and attach it to the project.</p><p>Color model will be updated accordingly.</p></body></html></string>
|
<string><html><head/><body><p>Save ICC profile</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../images/images.qrc">
|
<iconset resource="../../images/images.qrc">
|
||||||
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
|
<normaloff>:/images/themes/default/mActionFileSave.svg</normaloff>:/images/themes/default/mActionFileSave.svg</iconset>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="3">
|
|
||||||
<widget class="QComboBox" name="mColorModel">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Color model used as default when selecting a color in the whole application.</p><p>Any color defined in a different color model than the one specified here will be converted to this color model when exporting a layout.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1" colspan="3">
|
|
||||||
<widget class="QgsOpacityWidget" name="mDefaultOpacityWidget" native="true">
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::StrongFocus</enum>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@ -272,6 +272,7 @@ void TestQgsProjectProperties::testColorSettings()
|
|||||||
#else
|
#else
|
||||||
QVERIFY( !pp->mRemoveIccProfile->isVisible() );
|
QVERIFY( !pp->mRemoveIccProfile->isVisible() );
|
||||||
QVERIFY( !pp->mAddIccProfile->isVisible() );
|
QVERIFY( !pp->mAddIccProfile->isVisible() );
|
||||||
|
QVERIFY( !pp->mSaveIccProfile->isVisible() );
|
||||||
QVERIFY( !pp->mColorSpaceName->isVisible() );
|
QVERIFY( !pp->mColorSpaceName->isVisible() );
|
||||||
QVERIFY( !pp->mIccProfileLabel->isVisible() );
|
QVERIFY( !pp->mIccProfileLabel->isVisible() );
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -9,11 +9,18 @@ __author__ = 'Nyall Dawson'
|
|||||||
__date__ = '06/07/2022'
|
__date__ = '06/07/2022'
|
||||||
__copyright__ = 'Copyright 2022, The QGIS Project'
|
__copyright__ = 'Copyright 2022, The QGIS Project'
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from qgis.PyQt.QtCore import QTemporaryDir
|
||||||
from qgis.PyQt.QtGui import QColor
|
from qgis.PyQt.QtGui import QColor
|
||||||
from qgis.PyQt.QtXml import QDomDocument
|
from qgis.PyQt.QtXml import QDomDocument
|
||||||
from qgis.core import QgsColorUtils, QgsReadWriteContext, QgsSymbolLayerUtils
|
from qgis.core import QgsColorUtils, QgsReadWriteContext, QgsSymbolLayerUtils
|
||||||
from qgis.testing import unittest
|
from qgis.testing import unittest
|
||||||
|
|
||||||
|
from utilities import unitTestDataPath
|
||||||
|
|
||||||
|
TEST_DATA_DIR = unitTestDataPath()
|
||||||
|
|
||||||
|
|
||||||
class TestQgsColorUtils(unittest.TestCase):
|
class TestQgsColorUtils(unittest.TestCase):
|
||||||
|
|
||||||
@ -288,6 +295,21 @@ class TestQgsColorUtils(unittest.TestCase):
|
|||||||
self.assertAlmostEqual(res.blue(), 23, delta=1)
|
self.assertAlmostEqual(res.blue(), 23, delta=1)
|
||||||
self.assertEqual(res.alpha(), 220)
|
self.assertEqual(res.alpha(), 220)
|
||||||
|
|
||||||
|
def test_icc_profile(self):
|
||||||
|
"""
|
||||||
|
Test ICC profile load and save method
|
||||||
|
"""
|
||||||
|
|
||||||
|
iccProfileFilePath = os.path.join(TEST_DATA_DIR, "sRGB2014.icc")
|
||||||
|
colorSpace, errorMsg = QgsColorUtils.iccProfile(iccProfileFilePath)
|
||||||
|
self.assertTrue(colorSpace.isValid())
|
||||||
|
|
||||||
|
tmpDir = QTemporaryDir()
|
||||||
|
tmpFile = f"{tmpDir.path()}/test.icc"
|
||||||
|
|
||||||
|
error = QgsColorUtils.saveIccProfile(colorSpace, tmpFile)
|
||||||
|
self.assertTrue(not error)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user