Skip to content

Commit 5dc9055

Browse files
author
Raphael Dumusc
authored
Merge pull request #46 from rdumusc/cache
Port back image caching for Launcher from Dock [DISCL-368]
2 parents 7efb8a0 + 7b23e1a commit 5dc9055

26 files changed

Lines changed: 302 additions & 280 deletions

apps/Launcher/qml/FileBrowser.qml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ Rectangle {
6060
GradientStop { position: 0.0; color: Style.placeholderTopColor }
6161
GradientStop { position: 1.0; color: Style.placeholderBottomColor }
6262
}
63-
Image {
64-
id: thumbnail
65-
anchors.fill: parent
66-
source: "image://thumbnail/" + filePath
67-
fillMode: Image.PreserveAspectFit
68-
}
63+
visible: thumbnail.status !== Image.Ready
64+
}
65+
Image {
66+
id: thumbnail
67+
anchors.fill: placeholder
68+
fillMode: Image.PreserveAspectFit
69+
cache: false
70+
source: "image://thumbnail/" + filePath
6971
}
7072

7173
Text {

doc/Changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ Changelog {#Changelog}
33

44
# git master (1.1.0)
55

6+
* [46](https://github.com/BlueBrain/Tide/pull/46):
7+
Improved Launcher:
8+
- The creation and caching of file thumbnails is more efficient.
9+
- File thumbnails are displayed with their correct aspect ratio.
10+
Session preview images are of better quality (no longer pixelated).
611
* [38](https://github.com/BlueBrain/Tide/pull/38):
712
Fix a segfault that occured when opening grayscale images.
813
* [36](https://github.com/BlueBrain/Tide/pull/36):

tests/cpp/core/StateSerializationTests.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,17 @@ BOOST_AUTO_TEST_CASE( testStateSerializationToFile )
414414
BOOST_CHECK_LT( previewError, 0.02f );
415415

416416
// 4) Test restoring
417-
DisplayGroupPtr loadedDisplayGroup = boost::make_shared<DisplayGroup>( wallSize );
418-
StateSerializationHelper loader( loadedDisplayGroup );
417+
DisplayGroupPtr loadedGroup = boost::make_shared<DisplayGroup>( wallSize );
418+
StateSerializationHelper loader( loadedGroup );
419419
BOOST_CHECK( loader.load( TEST_DIR + "/test.dcx" ));
420420

421-
BOOST_REQUIRE_EQUAL( loadedDisplayGroup->getContentWindows().size(),
421+
BOOST_REQUIRE_EQUAL( loadedGroup->getContentWindows().size(),
422422
displayGroup->getContentWindows().size( ));
423-
BOOST_REQUIRE_EQUAL( loadedDisplayGroup->getShowWindowTitles(),
423+
BOOST_REQUIRE_EQUAL( loadedGroup->getShowWindowTitles(),
424424
displayGroup->getShowWindowTitles());
425-
BOOST_REQUIRE_EQUAL( loadedDisplayGroup->getCoordinates(), QRectF( QPointF( 0, 0 ), wallSize ));
426-
checkWindow( loadedDisplayGroup->getContentWindows()[0] );
425+
BOOST_REQUIRE_EQUAL( loadedGroup->getCoordinates(),
426+
QRectF( QPointF( 0, 0 ), wallSize ));
427+
checkWindow( loadedGroup->getContentWindows()[0] );
427428

428429
// 4) Cleanup
429430
cleanupTestDir();
13.5 KB
Binary file not shown.

tide/core/StatePreview.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*********************************************************************/
2-
/* Copyright (c) 2013, EPFL/Blue Brain Project */
2+
/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */
33
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
44
/* All rights reserved. */
55
/* */
@@ -55,12 +55,11 @@
5555

5656
namespace
5757
{
58-
static const QSize PREVIEW_IMAGE_SIZE( 512, 512 );
59-
static const QSize THUMBNAIL_SIZE( 128, 128 );
58+
const QSize PREVIEW_IMAGE_SIZE( 512, 512 );
6059
}
6160

6261
StatePreview::StatePreview( const QString &dcxFileName )
63-
: dcxFileName_( dcxFileName )
62+
: _dcxFileName( dcxFileName )
6463
{
6564
}
6665

@@ -71,20 +70,20 @@ QString StatePreview::getFileExtension()
7170

7271
QImage StatePreview::getImage() const
7372
{
74-
return previewImage_;
73+
return _previewImage;
7574
}
7675

7776
QString StatePreview::previewFilename() const
7877
{
79-
QFileInfo fileinfo( dcxFileName_ );
78+
QFileInfo fileinfo( _dcxFileName );
8079

8180
const QString extension = fileinfo.suffix().toLower();
8281
if( extension != "dcx" )
8382
{
8483
put_flog( LOG_WARN, "wrong state file extension: '%s' for session: '%s'"
8584
"(expected: .dcx)",
8685
extension.toLocal8Bit().constData( ),
87-
dcxFileName_.toLocal8Bit().constData( ));
86+
_dcxFileName.toLocal8Bit().constData( ));
8887
return QString();
8988
}
9089
return fileinfo.path() + "/" + fileinfo.completeBaseName() + getFileExtension();
@@ -117,20 +116,21 @@ void StatePreview::generateImage( const QSize& wallDimensions,
117116

118117
const QString& filename = window->getContent()->getURI();
119118
ThumbnailGeneratorPtr generator =
120-
ThumbnailGeneratorFactory::getGenerator( filename, THUMBNAIL_SIZE );
119+
ThumbnailGeneratorFactory::getGenerator( filename,
120+
area.size().toSize( ));
121121
const QImage image = generator->generate( filename );
122122

123123
painter.drawImage( area, image );
124124
}
125125

126126
painter.end();
127127

128-
previewImage_ = preview;
128+
_previewImage = preview;
129129
}
130130

131131
bool StatePreview::saveToFile() const
132132
{
133-
const bool success = previewImage_.save( previewFilename(), "PNG" );
133+
const bool success = _previewImage.save( previewFilename(), "PNG" );
134134

135135
if( !success )
136136
put_flog( LOG_ERROR, "Saving StatePreview image failed: '%s'",
@@ -142,9 +142,5 @@ bool StatePreview::saveToFile() const
142142
bool StatePreview::loadFromFile()
143143
{
144144
QImageReader reader( previewFilename( ));
145-
if ( reader.canRead( ))
146-
{
147-
return reader.read( &previewImage_ );
148-
}
149-
return false;
145+
return reader.canRead() && reader.read( &_previewImage );
150146
}

tide/core/StatePreview.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*********************************************************************/
2-
/* Copyright (c) 2013, EPFL/Blue Brain Project */
2+
/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */
33
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
44
/* All rights reserved. */
55
/* */
@@ -96,8 +96,8 @@ class StatePreview
9696
protected:
9797
QString previewFilename() const;
9898

99-
QString dcxFileName_;
100-
QImage previewImage_;
99+
QString _dcxFileName;
100+
QImage _previewImage;
101101
};
102102

103103
#endif // STATEPREVIEW_H

tide/core/thumbnail/DefaultThumbnailGenerator.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*********************************************************************/
2-
/* Copyright (c) 2013, EPFL/Blue Brain Project */
2+
/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */
33
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
44
/* All rights reserved. */
55
/* */
@@ -39,15 +39,14 @@
3939

4040
#include "DefaultThumbnailGenerator.h"
4141

42-
DefaultThumbnailGenerator::DefaultThumbnailGenerator(const QSize &size)
43-
: ThumbnailGenerator(size)
42+
DefaultThumbnailGenerator::DefaultThumbnailGenerator( const QSize& size )
43+
: ThumbnailGenerator( size )
4444
{
4545
}
4646

47-
QImage DefaultThumbnailGenerator::generate(const QString& filename) const
47+
QImage DefaultThumbnailGenerator::generate( const QString& ) const
4848
{
49-
QImage img = createGradientImage( QColor(Qt::black), QColor(Qt::white) );
50-
paintText(img, "FILE");
51-
addMetadataToImage(img, filename);
49+
QImage img = createGradientImage( QColor( Qt::black ), QColor( Qt::white ));
50+
paintText( img, "FILE" );
5251
return img;
5352
}

tide/core/thumbnail/DefaultThumbnailGenerator.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*********************************************************************/
2-
/* Copyright (c) 2013, EPFL/Blue Brain Project */
2+
/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */
33
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
44
/* All rights reserved. */
55
/* */
@@ -45,9 +45,9 @@
4545
class DefaultThumbnailGenerator : public ThumbnailGenerator
4646
{
4747
public:
48-
DefaultThumbnailGenerator(const QSize& size);
48+
DefaultThumbnailGenerator( const QSize& size );
4949

50-
QImage generate(const QString& filename) const override;
50+
QImage generate( const QString& filename ) const final;
5151
};
5252

53-
#endif // DEFAULTTHUMBNAILGENERATOR_H
53+
#endif

tide/core/thumbnail/FolderThumbnailGenerator.cpp

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@
3939

4040
#include "FolderThumbnailGenerator.h"
4141

42-
#include <QDir>
43-
#include <QPainter>
44-
42+
#include "ContentFactory.h"
4543
#include "ThumbnailGeneratorFactory.h"
4644
#include "ThumbnailGenerator.h"
47-
#include "ContentFactory.h"
4845
#include "log.h"
4946

47+
#include <QDir>
48+
#include <QPainter>
49+
5050
namespace
5151
{
5252
const int FOLDER_THUMBNAILS_X = 2;
@@ -57,75 +57,49 @@ const QString FOLDER_TEXT( "folder" );
5757

5858
FolderThumbnailGenerator::FolderThumbnailGenerator( const QSize& size )
5959
: ThumbnailGenerator( size )
60-
{
61-
}
60+
{}
6261

6362
QImage FolderThumbnailGenerator::generate( const QString& filename ) const
6463
{
6564
const QDir dir( filename );
6665
if( dir.exists( ))
67-
return createFolderImage( dir, true );
66+
return _createFolderImage( dir, true );
6867

6968
put_flog( LOG_ERROR, "invalid directory: %s",
7069
filename.toLocal8Bit().constData( ));
7170
return createErrorImage( "folder" );
7271
}
7372

7473
QImage
75-
FolderThumbnailGenerator::generatePlaceholderImage( const QDir& dir ) const
74+
FolderThumbnailGenerator::_createFolderImage( const QDir& dir,
75+
const bool generateThumbnails ) const
7676
{
7777
QImage img = createGradientImage( Qt::black, Qt::white );
78-
addMetadataToImage( img, dir.path( ));
79-
return img;
80-
}
8178

82-
void FolderThumbnailGenerator::addMetadataToImage( QImage& img,
83-
const QString& url ) const
84-
{
85-
img.setText( "dir", "true" );
86-
ThumbnailGenerator::addMetadataToImage( img, url );
87-
}
88-
89-
QVector<QRectF>
90-
FolderThumbnailGenerator::calculatePlacement( int nX, int nY, float padding,
91-
float totalWidth,
92-
float totalHeight ) const
93-
{
94-
const float totalPaddingWidth = padding*(nX+1);
95-
const float imageWidth = (1.0f-totalPaddingWidth)/(float)nX;
79+
const QFileInfoList& fileList = _getSupportedFilesInDir( dir );
9680

97-
const float totalPaddingHeight = padding*(nY+1);
98-
const float imageHeight = (1.0f-totalPaddingHeight)/(float)nY;
81+
if( generateThumbnails && fileList.size() > 0 )
82+
_paintThumbnailsMosaic( img, fileList );
83+
else
84+
paintText( img, FOLDER_TEXT );
9985

100-
QVector<QRectF> rect;
101-
for( int j = 0; j < nY; ++j )
102-
{
103-
const float y = padding + j*(imageHeight+padding);
104-
for( int i = 0; i < nX; ++i )
105-
{
106-
const float x = padding + i*(imageWidth+padding);
107-
rect.append( QRect( x*totalWidth, y*totalHeight,
108-
imageWidth*totalWidth,
109-
imageHeight*totalHeight ));
110-
}
111-
}
112-
return rect;
86+
return img;
11387
}
11488

115-
void FolderThumbnailGenerator::paintThumbnailsMosaic( QImage& img,
116-
const QFileInfoList&
117-
fileList) const
89+
void FolderThumbnailGenerator::_paintThumbnailsMosaic( QImage& img,
90+
const QFileInfoList&
91+
fileList ) const
11892
{
11993
const int numPreviews = std::min( FOLDER_THUMBNAILS_X*FOLDER_THUMBNAILS_Y,
12094
fileList.size( ));
12195
if( numPreviews == 0 )
12296
return;
12397

124-
QVector<QRectF> rect = calculatePlacement( FOLDER_THUMBNAILS_X,
125-
FOLDER_THUMBNAILS_Y,
126-
FOLDER_THUMBNAILS_PADDING,
127-
img.size().width(),
128-
img.size().height( ));
98+
QVector<QRectF> rect = _calculatePlacement( FOLDER_THUMBNAILS_X,
99+
FOLDER_THUMBNAILS_Y,
100+
FOLDER_THUMBNAILS_PADDING,
101+
img.size().width(),
102+
img.size().height( ));
129103
QPainter painter( &img );
130104
for( int i = 0; i < numPreviews; ++i )
131105
{
@@ -135,33 +109,53 @@ void FolderThumbnailGenerator::paintThumbnailsMosaic( QImage& img,
135109
QImage thumbnail;
136110
// Avoid recursion into subfolders
137111
if( QDir( filename ).exists( ))
138-
thumbnail = createFolderImage( QDir( filename ), false );
112+
thumbnail = _createFolderImage( QDir( filename ), false );
139113
else
140-
thumbnail = ThumbnailGeneratorFactory::getGenerator( filename, size_ )->generate( filename );
114+
{
115+
const auto size = rect[i].size().toSize();
116+
auto generator =
117+
ThumbnailGeneratorFactory::getGenerator( filename, size );
118+
thumbnail = generator->generate( filename );
119+
}
141120

142-
painter.drawImage( rect[i], thumbnail );
121+
// Draw the thumbnail centered in its rectangle, preserving aspect ratio
122+
QSizeF paintedSize( thumbnail.size( ));
123+
paintedSize.scale( rect[i].size(), Qt::KeepAspectRatio );
124+
QRectF paintRect( QPointF(), paintedSize );
125+
paintRect.moveCenter( rect[i].center( ));
126+
painter.drawImage( paintRect, thumbnail );
143127
}
144128
painter.end();
145129
}
146130

147-
QImage
148-
FolderThumbnailGenerator::createFolderImage( const QDir& dir,
149-
const bool generateThumbnails ) const
131+
QVector<QRectF>
132+
FolderThumbnailGenerator::_calculatePlacement( int nX, int nY, float padding,
133+
float totalWidth,
134+
float totalHeight ) const
150135
{
151-
QImage img = generatePlaceholderImage( dir );
152-
153-
const QFileInfoList& fileList = getSupportedFilesInDir( dir );
136+
const float totalPaddingWidth = padding*(nX+1);
137+
const float imageWidth = (1.0f-totalPaddingWidth)/(float)nX;
154138

155-
if( generateThumbnails && fileList.size() > 0 )
156-
paintThumbnailsMosaic(img, fileList);
157-
else
158-
paintText( img, FOLDER_TEXT );
139+
const float totalPaddingHeight = padding*(nY+1);
140+
const float imageHeight = (1.0f-totalPaddingHeight)/(float)nY;
159141

160-
return img;
142+
QVector<QRectF> rect;
143+
for( int j = 0; j < nY; ++j )
144+
{
145+
const float y = padding + j*(imageHeight+padding);
146+
for( int i = 0; i < nX; ++i )
147+
{
148+
const float x = padding + i*(imageWidth+padding);
149+
rect.append( QRect( x*totalWidth, y*totalHeight,
150+
imageWidth*totalWidth,
151+
imageHeight*totalHeight ));
152+
}
153+
}
154+
return rect;
161155
}
162156

163157
QFileInfoList
164-
FolderThumbnailGenerator::getSupportedFilesInDir( QDir dir ) const
158+
FolderThumbnailGenerator::_getSupportedFilesInDir( QDir dir ) const
165159
{
166160
dir.setFilter( QDir::Files | QDir::NoDotAndDotDot );
167161
QStringList filters = ContentFactory::getSupportedFilesFilter();

0 commit comments

Comments
 (0)