Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project image decoration support #5200

Merged
merged 3 commits into from Apr 26, 2024
Merged

Project image decoration support #5200

merged 3 commits into from Apr 26, 2024

Conversation

nirvn
Copy link
Member

@nirvn nirvn commented Apr 21, 2024

This PR implements support for projects' image decoration (joining the title and copyright decorations implement in QField 3.2).

To support fill and outline settings, a new ParametizedImage item was added, which relies on SVG and image cache to configure the fill and stroke color of the image. It will probably come in handy in other scenarios too.

As per the two other decorations we have, QField will enforce an harmonious position for the decoration.

In action:

image

The decoration gives users a simple way to further "brand" their projects.

Relevant QGIS documentation: https://docs.qgis.org/3.34/en/docs/user_manual/map_views/map_view.html#image-decoration

Sponsored by Deutsches Archäologisches Institut (DAI)

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 35. Check the log or trigger a new build to see more.

void ParametizedImage::setSource( const QString &source )
{
if ( mSource == source )
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
return;
if ( mSource == source ) {
return;
}

mSource = source;
emit sourceChanged();

QFileInfo fi( mSource );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'fi' of type 'QFileInfo' can be declared 'const' [misc-const-correctness]

Suggested change
QFileInfo fi( mSource );
QFileInfo const fi( mSource );

mSource = source;
emit sourceChanged();

QFileInfo fi( mSource );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable name 'fi' is too short, expected at least 3 characters [readability-identifier-length]

  QFileInfo fi( mSource );
            ^

{
if ( mIsRaster )
{
mSourceSize = QgsApplication::instance()->imageCache()->originalSize( mSource, true );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: static member accessed through instance [readability-static-accessed-through-instance]

      mSourceSize = QgsApplication::instance()->imageCache()->originalSize( mSource, true );
                    ^

}
else
{
mSourceSize = QgsApplication::instance()->svgCache()->svgViewboxSize( mSource, size().width(), QColor( 0, 0, 0 ), QColor( 255, 0, 0 ), 10, 1, 0, true );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers]

      mSourceSize = QgsApplication::instance()->svgCache()->svgViewboxSize( mSource, size().width(), QColor( 0, 0, 0 ), QColor( 255, 0, 0 ), 10, 1, 0, true );
                                                                                                                                             ^

const double devicePixelRatio = window()->screen()->devicePixelRatio();
QImage sourceImage = QgsApplication::instance()->imageCache()->pathAsImage( mSource, QSize( drawnWidth * devicePixelRatio, drawnHeight * devicePixelRatio ), true, 1, fitsInCache, true );
painter->drawImage( ( size().width() - drawnWidth ) / 2, ( size().height() - drawnHeight ) / 2, sourceImage );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions]

    painter->drawImage( ( size().width() - drawnWidth ) / 2, ( size().height() - drawnHeight ) / 2, sourceImage );
                        ^

{
const double drawnWidth = sourceRatio >= itemRatio ? size().width() : size().height() * sourceRatio;
QPicture sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );
painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: static member accessed through instance [readability-static-accessed-through-instance]

    QPicture sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );
                             ^

{
const double drawnWidth = sourceRatio >= itemRatio ? size().width() : size().height() * sourceRatio;
QPicture sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );
painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'sourcePicture' of type 'QPicture' can be declared 'const' [misc-const-correctness]

Suggested change
painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
QPicture const sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );

const double drawnWidth = sourceRatio >= itemRatio ? size().width() : size().height() * sourceRatio;
QPicture sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );
painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'qreal' (aka 'double') to 'int' [bugprone-narrowing-conversions]

    painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
                                              ^

const double drawnWidth = sourceRatio >= itemRatio ? size().width() : size().height() * sourceRatio;
QPicture sourcePicture = QgsApplication::instance()->svgCache()->svgAsPicture( mSource, drawnWidth, mFillColor, mStrokeColor, mStrokeWidth, 1, fitsInCache, 0, true );
painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'qreal' (aka 'double') to 'int' [bugprone-narrowing-conversions]

    painter->drawPicture( size().width() / 2, size().height() / 2, sourcePicture );
                          ^

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 26. Check the log or trigger a new build to see more.

void ParametizedImage::setFillColor( const QColor &color )
{
if ( mFillColor == color )
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
return;
if ( mFillColor == color ) {
return;
}

emit fillColorChanged();

if ( mIsValid && !mIsRaster )
update();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
update();
if ( mIsValid && !mIsRaster ) {
update();
}

void ParametizedImage::setStrokeColor( const QColor &color )
{
if ( mStrokeColor == color )
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
return;
if ( mStrokeColor == color ) {
return;
}

emit strokeColorChanged();

if ( mIsValid && !mIsRaster )
update();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
update();
if ( mIsValid && !mIsRaster ) {
update();
}

void ParametizedImage::setStrokeWidth( double width )
{
if ( mStrokeWidth == width )
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: statement should be inside braces [readability-braces-around-statements]

Suggested change
return;
if ( mStrokeWidth == width ) {
return;
}

QSizeF mSourceSize;

QColor mFillColor = QColor( 0, 0, 0 );
QColor mStrokeColor = QColor( 255, 255, 255 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 255 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers]

    QColor mStrokeColor = QColor( 255, 255, 255 );
                                            ^

QSizeF mSourceSize;

QColor mFillColor = QColor( 0, 0, 0 );
QColor mStrokeColor = QColor( 255, 255, 255 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 255 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers]

    QColor mStrokeColor = QColor( 255, 255, 255 );
                                       ^

QSizeF mSourceSize;

QColor mFillColor = QColor( 0, 0, 0 );
QColor mStrokeColor = QColor( 255, 255, 255 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 255 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers]

    QColor mStrokeColor = QColor( 255, 255, 255 );
                                  ^

@@ -743,3 +744,39 @@ QVariantMap ProjectInfo::getCopyrightDecorationConfiguration()

return configuration;
}

QVariantMap ProjectInfo::getImageDecorationConfiguration()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'getImageDecorationConfiguration' can be made static [readability-convert-member-functions-to-static]

src/core/projectinfo.h:187:

-     Q_INVOKABLE QVariantMap getImageDecorationConfiguration();
+     Q_INVOKABLE static QVariantMap getImageDecorationConfiguration();

imagePath = QStringLiteral( ":/images/qfield_logo.svg" );
}

QColor fillColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/Color" ), QStringLiteral( "#000000" ) ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'fillColor' of type 'QColor' can be declared 'const' [misc-const-correctness]

Suggested change
QColor fillColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/Color" ), QStringLiteral( "#000000" ) ) );
QColor const fillColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/Color" ), QStringLiteral( "#000000" ) ) );

@qfield-fairy
Copy link
Collaborator

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

}

QColor fillColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/Color" ), QStringLiteral( "#000000" ) ) );
QColor strokeColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/OutlineColor" ), QStringLiteral( "#FFFFFF" ) ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'strokeColor' of type 'QColor' can be declared 'const' [misc-const-correctness]

Suggested change
QColor strokeColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/OutlineColor" ), QStringLiteral( "#FFFFFF" ) ) );
QColor const strokeColor = QgsColorUtils::colorFromString( QgsProject::instance()->readEntry( configurationName, QStringLiteral( "/OutlineColor" ), QStringLiteral( "#FFFFFF" ) ) );

parametizedimage.cpp - ParametizedImage

---------------------
begin : 21.05.2024
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool where did you purchased a time machine? I need one as well!

}
else
{
imagePath = QStringLiteral( ":/images/qfield_logo.svg" );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean that if the path is misconfigured or the file did not get to the phone we just show a qfield logo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domi4484 , yep, same logic as in QGIS, where there it shows a QGIS logo.

QVariantMap ProjectInfo::getImageDecorationConfiguration()
{
QVariantMap configuration;
const QString configurationName = QStringLiteral( "Image" );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All those literals are defined the same way in QGIS as well? I think ideally they should be some const or are they by purpose not made part of the interface in QGIS?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domi4484 , correct, they are.

That's in big part because decorations have been living in src/app for as long as they've existed.

@nirvn nirvn merged commit ebbc737 into master Apr 26, 2024
21 of 23 checks passed
@nirvn nirvn deleted the image_decoration branch April 26, 2024 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants