Skip to content

Commit 6b52bc8

Browse files
author
Koen Deforche
committed
Several changes:
- Fix internal path URL to base dir (in some cases) - Added more clarifications related to issue #3682 - Implemented issue #2692: use placeholder attribute - Implemented issue #4922: allow foreign keys to be specified as-is - Fix #4791: allow WDialog::setMaximumSize() with % values. - Fix #4767: error with WTableView + popup handling
1 parent 5aeada4 commit 6b52bc8

29 files changed

+708
-158
lines changed

ReleaseNotes.html

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,125 @@ <h1>Wt Release notes</h1>
2222
the way you build Wt, the way you configure Wt or the Wt API and
2323
behaviour.
2424

25+
<h2>Release 3.3.6 (?, 2016)</h2>
26+
<p>
27+
This release has a focus on bug fixes and some new features:
28+
</p>
29+
<dl>
30+
<dt>
31+
Support for WebSocket compression in wthttp
32+
</dt>
33+
<dd>
34+
WebSocket traffic is now compressed, if possible.
35+
</dd>
36+
<dt>
37+
Time entry improvements
38+
</dt>
39+
<dd>
40+
<a href="classWt_1_1WTimeEdit.html">WTimeEdit</a> now supports AM/PM in its format,
41+
<a href="classWt_1_1WTimeValidator.html">WTimeValidator</a> now allows to select a minimum
42+
and maximum time and supports multiple formats,
43+
<a href="classWt_1_1WTimePicker.html">WTimePicker</a> can now work up to
44+
millisecond precision, and is now rendered with spinboxes.
45+
</dd>
46+
<dt>
47+
Skia version updated
48+
</dt>
49+
<dd>
50+
The Skia backend for <a href="classWt_1_1WRasterImage.html">WRasterImage</a> is now compatible with more recent versions of Skia. If you need
51+
to support an older version of Skia, use <tt>-DWT_SKIA_OLD=ON</tt>. The Skia version of the Windows builds
52+
has been updated from 394c7bb to 834d9e1.
53+
</dd>
54+
<dt>
55+
Wt::Dbo
56+
</dt>
57+
<dd>
58+
It's now possible to mark foreign keys as literal with a &ldquo;&gt;&rdquo; prefix, so Wt::Dbo can better map to
59+
an existing schema. Note that for consistency, this also means that the schema generated for ManyToMany relationships
60+
has been changed to include the id column names if a joinId has been specified. If you specify a joinId for ManyToMany
61+
relationships, you'll have to change it to include a &ldquo;&gt;&rdquo; before it in order to keep the same database schema.
62+
</dd>
63+
<dt>
64+
Scroll position
65+
</dt>
66+
<dd>
67+
It's now possible to retrieve the scroll position of a
68+
<a href="classWt_1_1WContainerWidget.html">WContainerWidget</a>
69+
with
70+
<a href="classWt_1_1WContainerWidget.html#a0a7ce553b2b5107412a3bed8700355cb">scrollTop()</a>
71+
and
72+
<a href="classWt_1_1WContainerWidget.html#a9a60d382fcd1490081087ce4f3649864">scrollLeft()</a>.
73+
</dd>
74+
<dt>
75+
Invalidation of stateless slots
76+
</dt>
77+
<dd>
78+
<a href="classWt_1_1WObject.html#a6dde4ce1e833a9966709daf3c0dedc9f">WObject::isNotStateless()</a>
79+
has been added, so functions called from functions that are marked as stateless can unmark
80+
it as stateless, reverting to plain server-side dynamic UI updates.
81+
</dd>
82+
<dt>
83+
<a href="classWt_1_1Auth_1_1Dbo_1_1UserDatabase.html">Auth::Dbo::UserDatabase</a>
84+
</dt>
85+
<dd>
86+
The <a href="classWt_1_1Auth_1_1Dbo_1_1UserDatabase.html">Dbo UserDatabase</a> implementation now
87+
compares e-mail addresses case insensitively. The <a href="classWt_1_1Auth_1_1AuthService.html">AuthService</a>
88+
can be passed in the constructor, so the <a href="classWt_1_1Auth_1_1Dbo_1_1UserDatabase.html">UserDatabase</a>
89+
knows whether the IdentityPolicy is EmailAddressIdentity.
90+
</dd>
91+
<dt>
92+
Charting library
93+
</dt>
94+
<dd>
95+
There have been many bug fixes and improvements to the charting library and the interactive features
96+
introduced in Wt 3.3.5:
97+
<ul>
98+
<li>Series <a href="classWt_1_1Chart_1_1WCartesianChart.html#ad05997dbc2d59862e38272985abda9a9">can be selected</a>
99+
on a <a href="classWt_1_1Chart_1_1WCartesianChart.html">WCartesianChart</a>.
100+
LineSeries <a href="classWt_1_1Chart_1_1WCartesianChart.html#a6078b67f146e686bd482d846dfe463cb">can be manipulated</a>.</li>
101+
<li><a href="classWt_1_1Chart_1_1WAxis.html#a16d188d56c2b62b7b3f2ddb6fa96d7cc">WAxis::setZoom()</a> and
102+
<a href="classWt_1_1Chart_1_1WAxis.html#a2f6a11d9d47036f8806c5a8412dfd24c">WAxis::setPan()</a>
103+
have been deprecated in favor of the easier to use
104+
<a href="classWt_1_1Chart_1_1WAxis.html#a0be187399e7cb4877f2c5e3837eba6ea">WAxis::setZoomRange()</a>.
105+
You can listen to changes in zoom range with the
106+
<a href="classWt_1_1Chart_1_1WAxis.html#a7e432917f0f23f18db3a043397a81904">WAxis::zoomRangeChanged()</a> signal.</li>
107+
<li>Series set as hidden will still be shown on a <a href="classWt_1_1Chart_1_1WAxisSliderWidget.html">WAxisSliderWidget</a>.
108+
The typical application for this is to show a coarse model on the slider widget, and a more detailed one on the chart.</li>
109+
<li>
110+
In order to provide better performance for charts containing a lot of data, the charting library has been
111+
overhauled to use <a href="classWt_1_1Chart_1_1WAbstractChartModel.html">WAbstractChartModel</a>s,
112+
instead of <a href="classWt_1_1WAbstractItemModel.html">WAbstractItemModel</a>s, avoiding the use of
113+
boost::any. The <a href="classWt_1_1Chart_1_1WStandardChartProxyModel.html">WStandardChartProxyModel</a>
114+
wraps a <a href="classWt_1_1WAbstractItemModel.html">WAbstractItemModel</a> so that those can still be used with charts.
115+
Note that this changes the return type of the
116+
<a href="classWt_1_1Chart_1_1WAbstractChart.html#a477522bb1720fb20006c81be455b3366">WAbstractChart::model()</a> method.
117+
</li>
118+
<li>A chart's axes can now be <a href="classWt_1_1Chart_1_1WAxis.html#a2bb7c8ec67ed2ff0b57953ea40cd87ef">inverted</a>.
119+
<li>Stacked series: negative values are now stacked separately from positive values.</li>
120+
<li><a href="classWt_1_1Chart_1_1CurveLabel.html">Curve labels</a> can now be drawn on charts, so that curves,
121+
or certain points on curves, can be labeled.</li>
122+
<li><a href="classWt_1_1Chart_1_1WAxis.html#afca24479982f10759be69703de5f4cd4">WAxis::getLabelTicks()</a>
123+
has been modified with an argument
124+
<a href="structWt_1_1Chart_1_1AxisConfig.html">AxisConfig</a>, so that different axis ticks can be drawn depending
125+
on the side that the axis is dawn on, or the zoom level it is drawn at. This is a breaking change if you override getLabelTicks.
126+
<a href="classWt_1_1Chart_1_1WAxis.html#a71928aabf753854274d753e266aabfc2">WAxis::setLabelTransform()</a>
127+
as a simpler method to change the tick
128+
labels depending on the side the axis is drawn on.</li>
129+
<li><a href="classWt_1_1Chart_1_1WDataSeries.html">WDataSeries</a> is no longer a simple value class. The interface of
130+
<a href="classWt_1_1Chart_1_1WCartesianChart.html">WCartesianChart</a> has been modified to reflect that: the old
131+
interface that copies WDataSeries over has been deprecated in favor of an interface that takes pointers to
132+
<a href="classWt_1_1Chart_1_1WDataSeries.html">WDataSeries</a>.</li>
133+
<li>It's now possible to <a href="classWt_1_1Chart_1_1WDataSeries.html#ae668a1a90ccf668e426fc2d9e370bf2c">specify a different model</a>
134+
for each <a href="classWt_1_1Chart_1_1WDataSeries.html">WDataSeries</a>.</li>
135+
<li><a href="classWt_1_1Chart_1_1WPieChart.html#a0ff69f626136fa56e7de27f6a10d770d">Chart::WPieChart::createLabelWidget()</a>
136+
has been added, making it possible to replace the labels of a
137+
<a href="classWt_1_1Chart_1_1WPieChart.html">WPieChart</a>
138+
with widgets.</li>
139+
<li>Tooltips on charts can now be deferred, which can improve performance of interactive charts, and if you have a lot of tooltips.</li>
140+
</ul>
141+
</dd>
142+
</dl>
143+
25144
<h2>Release 3.3.5 (Dec 31, 2015)</h2>
26145
<p>
27146
This release has a focus on bug fixes but also one or two new features:

src/Wt/Auth/Dbo/UserDatabase

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public:
226226
virtual bool setEmail(const User& user, const std::string& address) {
227227
WithUser find(*this, user);
228228

229-
if (session_.find<DboType>().where("\"email\" = ?")
229+
if (session_.find<DboType>().where("lower(\"email\") = lower(?)")
230230
.bind(address).resultList().size() != 0)
231231
return false;
232232

src/Wt/Chart/WPieChart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,12 @@ public:
263263
/**
264264
* @brief createLabelWidget possition textWidget where the text would be
265265
* rendered.
266-
* Assuming that textWidget is added to a container with same dimentions as
266+
* Assuming that textWidget is added to a container with same dimensions as
267267
* the WPieChart.
268268
* This should be used in combinaltion with drawLabel().
269269
*
270270
* @return The new WContainerWidget that contains textWidget and can be placed
271-
* on an other layer that has the same dimentions as the WPieChart.
271+
* on an other layer that has the same dimensions as the WPieChart.
272272
* \sa drawLabel()
273273
*
274274
* Usage example, PieChart with label links.

src/Wt/Dbo/DbAction_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ void InitSchema::actCollection(const CollectionRef<C>& field)
139139
mapping_.sets.push_back
140140
(Impl::SetInfo(joinTableName, field.type(), joinName, field.joinId(),
141141
field.fkConstraints()));
142+
if (field.literalJoinId())
143+
mapping_.sets.back().flags |= Impl::SetInfo::LiteralSelfId;
142144
}
143145

144146
/*

src/Wt/Dbo/Field

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,14 @@ public:
181181
collection< ptr<C> >& value() const { return value_; }
182182
const std::string& joinName() const { return joinName_; }
183183
const std::string& joinId() const { return joinId_; }
184+
bool literalJoinId() const { return literalJoinId_; }
184185
RelationType type() const { return type_; }
185186
int fkConstraints() const { return fkConstraints_; }
186187

187188
private:
188189
collection< ptr<C> >& value_;
189190
std::string joinName_, joinId_;
191+
bool literalJoinId_;
190192
RelationType type_;
191193
int fkConstraints_;
192194
};
@@ -198,6 +200,7 @@ public:
198200
PtrRef(ptr<C>& value, const std::string& name, int size, int fkConstraints);
199201

200202
const std::string& name() const { return name_; }
203+
bool literalForeignKey() const { return literalForeignKey_; }
201204
int fkConstraints() const { return fkConstraints_; }
202205
ptr<C>& value() const { return value_; }
203206
typename dbo_traits<C>::IdType id() const { return value_.id(); }
@@ -213,6 +216,7 @@ public:
213216
private:
214217
ptr<C>& value_;
215218
std::string name_;
219+
bool literalForeignKey_;
216220
int size_;
217221
int fkConstraints_;
218222
};
@@ -321,6 +325,12 @@ void field(Action& action, ptr<C>& value, const std::string& name,
321325
* This function binds the pointer field \p value to the database
322326
* foreign key field(s) \p name <tt>+ "_" +</tt> (C's primary key(s)).
323327
*
328+
* If the name starts with a <tt>&gt;</tt>, the <tt>&gt;</tt> is omitted and
329+
* the name is used literally, instead of \p name <tt>+ "_" +</tt> (C's primary key(s)),
330+
* e.g. if the primary key of C is <tt>id</tt>, then the name <tt>foo</tt> translates to a
331+
* column with the name <tt>foo_id</tt>, and the name <tt>&gt;foo</tt> translates to
332+
* a column with the name <tt>foo</tt>.
333+
*
324334
* If the name is omitted or empty, then C's mapped table name is used.
325335
*
326336
* A belongsTo() will usually have a counter-part hasMany() or
@@ -371,11 +381,13 @@ void belongsTo(Action& action, ptr<C>& value,
371381
* from how a hasMany() call backs a collection by a SQL query).
372382
*
373383
* The query is defined by the database field(s) \p name <tt>+ "_" +
374-
* </tt> (C's primary key(s))</tt>, in the mapped table for C. This
384+
* </tt> (C's primary key(s)), in the mapped table for C. This
375385
* should be the same <i>name</i> as passed to the matching
376386
* belongsTo() method for the other side of the relation. If the \p
377387
* name is omitted or empty, then the mapped table name of the current
378-
* class is used.
388+
* class is used. If the name starts with <tt>&gt;</tt>, the <tt>&gt;</tt>
389+
* is discarded, and the name is used literally, instead of \p name <tt>+ "_" +
390+
* </tt> (C's primary key(s)).
379391
*
380392
* A hasOne() must have a counter-part belongsTo() declaration in the
381393
* referenced class \p C.
@@ -433,8 +445,13 @@ void hasMany(Action& action, collection< ptr<C> >& value,
433445
* Wt::Dbo::ManyToMany ManyToMany\endlink.
434446
*
435447
* The \p joinId is used to reference this side of the relationship in
436-
* the join table. If \p joinId is left blank, the value will be table
437-
* name <tt>+ "_" +</tt> (primary key(s)) of the current class.
448+
* the join table, e.g. if \p joinId is <tt>foo</tt> and the primary key
449+
* is <tt>id</tt>, then this side of the join table will be named <tt>foo_id</tt>.
450+
* If \p joinId is left blank, the value will be table
451+
* name <tt>+ "_" +</tt> (primary key(s)) of the current class. If \p joinId
452+
* starts with <tt>&gt;</tt>, the <tt>&gt;</tt> is omitted, and the joinId
453+
* is used literally (the primary key of the current class is not appended),
454+
* e.g. <tt>&gt;foo</tt> maps to the column name <tt>foo</tt>.
438455
*
439456
* A hasMany() must have a counter-part belongsTo() or hasMany()
440457
* declaration in the referenced class \p C.

src/Wt/Dbo/Field_impl.h

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,33 @@ CollectionRef<C>::CollectionRef(collection< ptr<C> >& value,
6666
const std::string& joinName,
6767
const std::string& joinId,
6868
int fkConstraints)
69-
: value_(value), joinName_(joinName), joinId_(joinId), type_(type),
70-
fkConstraints_(fkConstraints)
71-
{ }
69+
: value_(value), joinName_(joinName), joinId_(joinId),
70+
literalJoinId_(false),
71+
type_(type), fkConstraints_(fkConstraints)
72+
{
73+
if (type == ManyToOne && !joinName.empty() && joinName[0] == '>') {
74+
joinName_ = std::string(joinName.c_str() + 1, joinName.size() - 1);
75+
}
76+
if (type == ManyToMany && !joinId.empty() && joinId[0] == '>') {
77+
joinId_ = std::string(joinId.c_str() + 1, joinId.size() - 1);
78+
literalJoinId_ = true;
79+
}
80+
}
7281

7382
template <class C>
7483
PtrRef<C>::PtrRef(ptr<C>& value, const std::string& name, int size,
7584
int fkConstraints)
7685
: value_(value),
7786
name_(name),
87+
literalForeignKey_(false),
7888
size_(size),
7989
fkConstraints_(fkConstraints)
80-
{ }
90+
{
91+
if (!name.empty() && name[0] == '>') {
92+
name_ = std::string(name.c_str() + 1, name.size() - 1);
93+
literalForeignKey_ = true;
94+
}
95+
}
8196

8297
template <class C, class A, class Enable = void>
8398
struct LoadLazyHelper
@@ -124,7 +139,11 @@ void PtrRef<C>::visit(A& action, Session *session) const
124139
idFieldName = mapping->surrogateIdFieldName;
125140
}
126141

127-
field(action, id, name_ + "_" + idFieldName, size);
142+
if (literalForeignKey()) {
143+
field(action, id, name_, size);
144+
} else {
145+
field(action, id, name_ + "_" + idFieldName, size);
146+
}
128147

129148
LoadLazyHelper<C, A>::loadLazy(value_, id, session);
130149
}
@@ -133,7 +152,11 @@ template <class C>
133152
WeakPtrRef<C>::WeakPtrRef(weak_ptr<C>& value, const std::string& joinName)
134153
: value_(value),
135154
joinName_(joinName)
136-
{ }
155+
{
156+
if (!joinName.empty() && joinName[0] == '>') {
157+
joinName_ = std::string(joinName.c_str() + 1, joinName.size() - 1);
158+
}
159+
}
137160

138161
template <class C>
139162
const std::type_info *PtrRef<C>::type() const

src/Wt/Dbo/Session

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,17 @@ namespace Wt {
2929
template <class C, typename T> struct LoadHelper;
3030

3131
struct WTDBO_API SetInfo {
32+
enum SetInfoFlags {
33+
// Normally, if there is no surrogate key, the field name of the natural id
34+
// is appended to joinSelfId/joinOtherId. These flags prevent that.
35+
LiteralSelfId = 0x1, // joinSelfId is literal, don't append primary key name
36+
LiteralOtherId = 0x2 // joinOtherId is literal, don't append primary key name
37+
};
38+
3239
const char *tableName;
3340
std::string joinName;
3441
std::string joinSelfId, joinOtherId;
42+
int flags;
3543
RelationType type;
3644
int fkConstraints, otherFkConstraints;
3745

@@ -559,7 +567,8 @@ private:
559567
std::string foreignKeyName);
560568

561569
std::vector<JoinId> getJoinIds(Impl::MappingInfo *mapping,
562-
const std::string& joinId);
570+
const std::string& joinId,
571+
bool literalJoinId);
563572

564573
void createTable(Impl::MappingInfo *mapping,
565574
std::set<std::string>& tablesCreated,
@@ -580,11 +589,13 @@ private:
580589
const std::string& joinId1,
581590
const std::string& joinId2,
582591
int fkConstraints1, int fkConstraints2,
592+
bool literalJoinId1, bool literalJoinId2,
583593
std::set<std::string>& tablesCreated,
584594
std::ostream *sout);
585595
void addJoinTableFields(Impl::MappingInfo& joinTableMapping,
586596
Impl::MappingInfo *mapping, const std::string& joinId,
587-
const std::string& foreignKeyName, int fkConstraints);
597+
const std::string& foreignKeyName, int fkConstraints,
598+
bool literalJoinId);
588599
void createJoinIndex(Impl::MappingInfo& joinTableMapping,
589600
Impl::MappingInfo *mapping,
590601
const std::string& joinId,

0 commit comments

Comments
 (0)