Skip to content

Commit 3df1264

Browse files
Thumbnails option fix (#39)
* Add thumbnails option Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com> * Thumbnails option fix Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com> --------- Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
1 parent e8f7db5 commit 3df1264

File tree

10 files changed

+117
-29
lines changed

10 files changed

+117
-29
lines changed

lib/toucanView/TimeLayout.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ namespace toucan
119119
value.min.y,
120120
std::max(t1 - t0, timeWidget->getMinWidth()),
121121
childSizeHint.h));
122-
};
122+
}
123123
}
124124
}
125125

lib/toucanView/TimelineItem.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "App.h"
77
#include "FilesModel.h"
88
#include "StackItem.h"
9+
#include "WindowModel.h"
910

1011
#include <dtk/ui/ScrollArea.h>
1112

@@ -49,6 +50,15 @@ namespace toucan
4950
{
5051
_select(shared_from_this(), selection);
5152
});
53+
54+
_thumbnailsObserver = dtk::ValueObserver<bool>::create(
55+
data.app->getWindowModel()->observeThumbnails(),
56+
[this](bool value)
57+
{
58+
_thumbnails = value;
59+
_setSizeUpdate();
60+
_setDrawUpdate();
61+
});
5262
}
5363

5464
TimelineItem::~TimelineItem()
@@ -98,9 +108,14 @@ namespace toucan
98108
for (const auto& child : getChildren())
99109
{
100110
const dtk::Size2I& sizeHint = child->getSizeHint();
111+
int h = timeHeight;
112+
if (_thumbnails)
113+
{
114+
h += _size.thumbnailHeight;
115+
}
101116
child->setGeometry(dtk::Box2I(
102117
g.min.x,
103-
g.min.y + timeHeight + _size.thumbnailHeight,
118+
g.min.y + h,
104119
sizeHint.w,
105120
sizeHint.h));
106121
}
@@ -165,7 +180,10 @@ namespace toucan
165180
dtk::Size2I sizeHint(
166181
_timeRange.duration().rescaled_to(1.0).value() * _scale,
167182
_size.fontMetrics.lineHeight + _size.margin * 2);
168-
sizeHint.h += _size.thumbnailHeight;
183+
if (_thumbnails)
184+
{
185+
sizeHint.h += _size.thumbnailHeight;
186+
}
169187
sizeHint.h += childSizeHint;
170188
_setSizeHint(sizeHint);
171189
}
@@ -177,35 +195,38 @@ namespace toucan
177195
const dtk::Box2I& g = getGeometry();
178196
const int thumbnailWidth = _size.thumbnailHeight * _thumbnailGenerator->getAspect();
179197
const int y = g.min.y + _size.fontMetrics.lineHeight + _size.margin * 2;
180-
for (int x = g.min.x; x < g.max.x && thumbnailWidth > 0; x += thumbnailWidth)
198+
if (_thumbnails)
181199
{
182-
const dtk::Box2I g2(x, y, thumbnailWidth, _size.thumbnailHeight);
183-
if (dtk::intersects(g2, drawRect))
200+
for (int x = g.min.x; x < g.max.x && thumbnailWidth > 0; x += thumbnailWidth)
184201
{
185-
const OTIO_NS::RationalTime t = posToTime(x);
186-
std::shared_ptr<dtk::Image> image;
187-
if (_thumbnailCache->get(getThumbnailCacheKey(nullptr, t, _size.thumbnailHeight), image))
202+
const dtk::Box2I g2(x, y, thumbnailWidth, _size.thumbnailHeight);
203+
if (dtk::intersects(g2, drawRect))
188204
{
189-
if (image)
205+
const OTIO_NS::RationalTime t = posToTime(x);
206+
std::shared_ptr<dtk::Image> image;
207+
if (_thumbnailCache->get(getThumbnailCacheKey(nullptr, t, _size.thumbnailHeight), image))
190208
{
191-
event.render->drawImage(
192-
image,
193-
dtk::Box2I(x, y, image->getWidth(), image->getHeight()));
194-
}
195-
}
196-
else
197-
{
198-
const auto j = std::find_if(
199-
_thumbnailRequests.begin(),
200-
_thumbnailRequests.end(),
201-
[this, t](const ThumbnailRequest& request)
209+
if (image)
202210
{
203-
return t == request.time && _size.thumbnailHeight == request.height;
204-
});
205-
if (j == _thumbnailRequests.end())
211+
event.render->drawImage(
212+
image,
213+
dtk::Box2I(x, y, image->getWidth(), image->getHeight()));
214+
}
215+
}
216+
else
206217
{
207-
_thumbnailRequests.push_back(
208-
_thumbnailGenerator->getThumbnail(t, _size.thumbnailHeight));
218+
const auto j = std::find_if(
219+
_thumbnailRequests.begin(),
220+
_thumbnailRequests.end(),
221+
[this, t](const ThumbnailRequest& request)
222+
{
223+
return t == request.time && _size.thumbnailHeight == request.height;
224+
});
225+
if (j == _thumbnailRequests.end())
226+
{
227+
_thumbnailRequests.push_back(
228+
_thumbnailGenerator->getThumbnail(t, _size.thumbnailHeight));
229+
}
209230
}
210231
}
211232
}

lib/toucanView/TimelineItem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ namespace toucan
8585
std::function<void(const OTIO_NS::RationalTime&)> _currentTimeCallback;
8686
OTIO_NS::TimeRange _inOutRange;
8787
std::shared_ptr<SelectionModel> _selectionModel;
88+
bool _thumbnails = true;
8889
std::shared_ptr<ThumbnailGenerator> _thumbnailGenerator;
8990
std::list<ThumbnailRequest> _thumbnailRequests;
9091
std::shared_ptr<dtk::LRUCache<std::string, std::shared_ptr<dtk::Image> > > _thumbnailCache;
@@ -116,5 +117,6 @@ namespace toucan
116117
MouseData _mouse;
117118

118119
std::shared_ptr<dtk::ListObserver<SelectionItem > > _selectionObserver;
120+
std::shared_ptr<dtk::ValueObserver<bool> > _thumbnailsObserver;
119121
};
120122
}

lib/toucanView/TimelineWidget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "App.h"
77
#include "FilesModel.h"
88
#include "TimelineItem.h"
9+
#include "WindowModel.h"
910

1011
namespace toucan
1112
{

lib/toucanView/VideoClipItem.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "App.h"
77
#include "File.h"
8+
#include "WindowModel.h"
89

910
#include <toucanRender/Util.h>
1011

@@ -91,6 +92,13 @@ namespace toucan
9192
}
9293

9394
_textUpdate();
95+
96+
_thumbnailsObserver = dtk::ValueObserver<bool>::create(
97+
data.app->getWindowModel()->observeThumbnails(),
98+
[this](bool value)
99+
{
100+
_thumbnailsWidget->setVisible(value);
101+
});
94102
}
95103

96104
VideoClipItem::~VideoClipItem()
@@ -139,7 +147,8 @@ namespace toucan
139147
_size.displayScale = event.displayScale;
140148
_size.border = event.style->getSizeRole(dtk::SizeRole::Border, event.displayScale);
141149
}
142-
_setSizeHint(_layout->getSizeHint());
150+
dtk::Size2I sizeHint = _layout->getSizeHint();
151+
_setSizeHint(sizeHint);
143152
}
144153

145154
void VideoClipItem::drawEvent(
@@ -148,7 +157,7 @@ namespace toucan
148157
{
149158
IItem::drawEvent(drawRect, event);
150159
dtk::Box2I g = _label->getGeometry();
151-
if (_thumbnailsWidget)
160+
if (_thumbnailsWidget->isVisible(true))
152161
{
153162
const dtk::Box2I& g2 = _thumbnailsWidget->getGeometry();
154163
g = dtk::Box2I(g.min, g2.max);

lib/toucanView/VideoClipItem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ namespace toucan
6363
std::shared_ptr<TimeLayout> _markerLayout;
6464
std::vector<std::shared_ptr<MarkerItem> > _markerItems;
6565

66+
std::shared_ptr<dtk::ValueObserver<bool> > _thumbnailsObserver;
67+
6668
struct SizeData
6769
{
6870
bool init = true;

lib/toucanView/WindowMenu.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,17 @@ namespace toucan
182182
});
183183
_menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/3.0"]);
184184

185+
_actions["Window/Thumbnails"] = std::make_shared<dtk::Action>(
186+
"Thumbnails",
187+
[appWeak](bool value)
188+
{
189+
if (auto app = appWeak.lock())
190+
{
191+
app->getWindowModel()->setThumbnails(value);
192+
}
193+
});
194+
addItem(_actions["Window/Thumbnails"]);
195+
185196
_actions["Window/Tooltips"] = std::make_shared<dtk::Action>(
186197
"Tooltips",
187198
[appWeak](bool value)
@@ -226,6 +237,13 @@ namespace toucan
226237
_menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/3.0"], 3.F == value);
227238
});
228239

240+
_thumbnailsObserver = dtk::ValueObserver<bool>::create(
241+
app->getWindowModel()->observeThumbnails(),
242+
[this](bool value)
243+
{
244+
setItemChecked(_actions["Window/Thumbnails"], value);
245+
});
246+
229247
_tooltipsObserver = dtk::ValueObserver<bool>::create(
230248
app->getWindowModel()->observeTooltips(),
231249
[this](bool value)

lib/toucanView/WindowMenu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace toucan
4444
std::shared_ptr<dtk::ValueObserver<bool> > _fullScreenObserver;
4545
std::shared_ptr<dtk::MapObserver<WindowComponent, bool> > _componentsObserver;
4646
std::shared_ptr<dtk::ValueObserver<float> > _displayScaleObserver;
47+
std::shared_ptr<dtk::ValueObserver<bool> > _thumbnailsObserver;
4748
std::shared_ptr<dtk::ValueObserver<bool> > _tooltipsObserver;
4849
};
4950
}

lib/toucanView/WindowModel.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <nlohmann/json.hpp>
1111

12+
#include <iostream>
1213
#include <sstream>
1314

1415
namespace toucan
@@ -30,6 +31,7 @@ namespace toucan
3031
{ WindowComponent::Playback, true },
3132
{ WindowComponent::InfoBar, true }
3233
};
34+
bool thumbnails = true;
3335
bool tooltips = true;
3436
try
3537
{
@@ -44,7 +46,12 @@ namespace toucan
4446
i.second = j->get<bool>();
4547
}
4648
}
47-
auto i = json.find("Tooltips");
49+
auto i = json.find("Thumbnails");
50+
if (i != json.end() && i->is_boolean())
51+
{
52+
thumbnails = i->get<bool>();
53+
}
54+
i = json.find("Tooltips");
4855
if (i != json.end() && i->is_boolean())
4956
{
5057
tooltips = i->get<bool>();
@@ -54,6 +61,7 @@ namespace toucan
5461
{}
5562

5663
_components = dtk::ObservableMap<WindowComponent, bool>::create(components);
64+
_thumbnails = dtk::ObservableValue<bool>::create(thumbnails);
5765
_tooltips = dtk::ObservableValue<bool>::create(tooltips);
5866
}
5967

@@ -66,6 +74,7 @@ namespace toucan
6674
ss << i.first;
6775
json[ss.str()] = i.second;
6876
}
77+
json["Thumbnails"] = _thumbnails->get();
6978
json["Tooltips"] = _tooltips->get();
7079
_settings->set("WindowModel", json);
7180
}
@@ -95,6 +104,21 @@ namespace toucan
95104
_components->setItemOnlyIfChanged(component, value);
96105
}
97106

107+
bool WindowModel::getThumbnails() const
108+
{
109+
return _thumbnails->get();
110+
}
111+
112+
std::shared_ptr<dtk::IObservableValue<bool> > WindowModel::observeThumbnails() const
113+
{
114+
return _thumbnails;
115+
}
116+
117+
void WindowModel::setThumbnails(bool value)
118+
{
119+
_thumbnails->setIfChanged(value);
120+
}
121+
98122
bool WindowModel::getTooltips() const
99123
{
100124
return _tooltips->get();

lib/toucanView/WindowModel.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ namespace toucan
4646
//! Set a window component.
4747
void setComponent(WindowComponent, bool);
4848

49+
//! Get whether thumbnails are enabled.
50+
bool getThumbnails() const;
51+
52+
//! Observe whether thumbnails are enabled.
53+
std::shared_ptr<dtk::IObservableValue<bool> > observeThumbnails() const;
54+
55+
//! Set whether thumbnails are enabled.
56+
void setThumbnails(bool);
57+
4958
//! Get whether tooltips are enabled.
5059
bool getTooltips() const;
5160

@@ -58,6 +67,7 @@ namespace toucan
5867
private:
5968
std::shared_ptr<dtk::Settings> _settings;
6069
std::shared_ptr<dtk::ObservableMap<WindowComponent, bool> > _components;
70+
std::shared_ptr<dtk::ObservableValue<bool> > _thumbnails;
6171
std::shared_ptr<dtk::ObservableValue<bool> > _tooltips;
6272
};
6373
}

0 commit comments

Comments
 (0)