Skip to content

Commit

Permalink
Several changes:
Browse files Browse the repository at this point in the history
    - fix WFileUpload regressions on IE
    - Emit QueryModel dataChanged after setData commits (Bruce Toll)
    - Add unit test for QueryModel dataChanged. (Bruce Toll)
  • Loading branch information
Koen Deforche committed Dec 31, 2015
1 parent 8df4af6 commit 946a943
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 42 deletions.
18 changes: 10 additions & 8 deletions src/Wt/Dbo/QueryModel_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,23 @@ bool QueryModel<Result>::setData(const WModelIndex& index,
const boost::any& value, int role)
{
if (role == EditRole) {
Transaction transaction(query_.session());
{
Transaction transaction(query_.session());

Result& result = resultRow(index.row());
Result& result = resultRow(index.row());

int column = columns_[index.column()].fieldIdx_;
int column = columns_[index.column()].fieldIdx_;

const FieldInfo& field = fields()[column];
const FieldInfo& field = fields()[column];

boost::any dbValue = Wt::convertAnyToAny(value, *field.type());
boost::any dbValue = Wt::convertAnyToAny(value, *field.type());

query_result_traits<Result>::setValue(result, column, dbValue);
query_result_traits<Result>::setValue(result, column, dbValue);

invalidateRow(index.row());
transaction.commit();
}

transaction.commit();
invalidateRow(index.row());

return true;
} else
Expand Down
8 changes: 3 additions & 5 deletions src/Wt/WFileUpload
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public:
* \sa uploaded()
* \sa WApplication::requestTooLarge()
*/
Signal< ::int64_t >& fileTooLarge() { return fileTooLarge_; }
JSignal< ::int64_t >& fileTooLarge() { return fileTooLarge_; }

/*! \brief %Signal emitted when the user selected a new file.
*
Expand Down Expand Up @@ -330,7 +330,7 @@ private:

std::vector<Http::UploadedFile> uploadedFiles_;

Signal< ::int64_t > fileTooLarge_;
JSignal< ::int64_t > fileTooLarge_;

Signal< ::uint64_t, ::uint64_t > dataReceived_;

Expand All @@ -354,9 +354,7 @@ protected:
virtual void propagateSetEnabled(bool enabled);

private:
void handleFileTooLarge(int fileSize);

JSignal< ::int64_t > tooLarge_;
void handleFileTooLarge(::int64_t fileSize);


void onUploaded();
Expand Down
63 changes: 34 additions & 29 deletions src/Wt/WFileUpload.C
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,16 @@ protected:
<< "._p_.update(null, '"
<< fileUpload_->uploaded().encodeCmd() << "', null, true);";
} else {
o << "window.parent.postMessage("
<< "{ fu: '" << fileUpload_->id() << "',"
o << " window.parent.postMessage("
<< "JSON.stringify({ fu: '" << fileUpload_->id() << "',"
<< " signal: '"
<< fileUpload_->uploaded().encodeCmd() << "'}, '*');";
<< fileUpload_->uploaded().encodeCmd() << "'}), '*');";
}
} else if (request.tooLarge()) {
LOG_DEBUG("Resource handleRequest(): signaling file-too-large");

o << fileUpload_->tooLarge_.createCall();
std::string s = boost::lexical_cast<std::string>(request.tooLarge());
o << fileUpload_->fileTooLarge().createCall(s);
}
} else {
LOG_DEBUG("Resource handleRequest(): no signal");
Expand All @@ -94,11 +95,8 @@ protected:
"</script></head>"
"<body onload=\"load();\"></body></html>";

if (request.tooLarge())
fileUpload_->tooLargeSize_ = request.tooLarge();
else
if (!files.empty())
fileUpload_->setFiles(files);
if (!request.tooLarge() && !files.empty())
fileUpload_->setFiles(files);
}

private:
Expand All @@ -118,14 +116,11 @@ const char *WFileUpload::UPLOADED_SIGNAL = "M_uploaded";
WFileUpload::WFileUpload(WContainerWidget *parent)
: WWebWidget(parent),
textSize_(20),
fileTooLarge_(this),
fileTooLarge_(this, "fileTooLarge"),
dataReceived_(this),
progressBar_(0),
tooLarge_(this, "tooLargeSignal"),
tooLargeSize_(0)
progressBar_(0)
{
setInline(true);
tooLarge_.connect(boost::bind(&WFileUpload::handleFileTooLarge, this, _1));
create();
}

Expand Down Expand Up @@ -181,7 +176,6 @@ void WFileUpload::onData(::uint64_t current, ::uint64_t total)
+ fileUploadTarget_->url() + "';");
if (flags_.test(BIT_UPLOADING)) {
flags_.reset(BIT_UPLOADING);
tooLargeSize_ = dataExceeded;
handleFileTooLarge(dataExceeded);

WApplication *app = WApplication::instance();
Expand Down Expand Up @@ -237,7 +231,7 @@ EventSignal<>& WFileUpload::changed()
return *voidEventSignal(CHANGE_SIGNAL, true);
}

void WFileUpload::handleFileTooLarge(int fileSize)
void WFileUpload::handleFileTooLarge(::int64_t fileSize)
{
fileTooLarge().emit(fileSize);
}
Expand Down Expand Up @@ -316,16 +310,19 @@ void WFileUpload::updateDom(DomElement& element, bool all)

std::string command =
"{"
"debugger; \n"
"var x = " WT_CLASS ".$('in" + id() + "') \n"
" if (x.files != null) \n"
" for (var i = 0; i < x.files.length; i++) { \n"
"var x = " WT_CLASS ".$('in" + id() + "');"
" if (x.files != null) {"
" for (var i = 0; i < x.files.length; i++) { "
" var f = x.files[i];"
" if(f.size < " + maxFileSize + ") \n"
" " + jsRef() + ".submit() \n"
" else \n"
" " + tooLarge_.createCall("f.size") +
" }};";
" if(f.size < " + maxFileSize + ") { "
" " + jsRef() + ".submit(); "
" } else { "
" " + fileTooLarge().createCall("f.size") +
" }"
" }"
" } else "
" " + jsRef() + ".submit(); "
" };";

element.callJavaScript(command);
flags_.reset(BIT_DO_UPLOAD);
Expand Down Expand Up @@ -446,13 +443,21 @@ DomElement *WFileUpload::createDomElement(WApplication *app)

form->addChild(input);

doJavaScript("window.addEventListener('message', function(event) {"
std::stringstream s;

doJavaScript("var f = function(event) {"
"""if (" + jsRef() + ".action.indexOf(event.origin) === 0) {"
"" "if (event.data.fu == '" + id() + "')"
"" "var data = JSON.parse(event.data);"
"" "if (data.fu == '" + id() + "')"
+ app->javaScriptClass()
+ "._p_.update(null, event.data.signal, null, true);"
+ "._p_.update(null, data.signal, null, true);"
"""}"
"}, false);");
"};"
"if (window.addEventListener) "
"""window.addEventListener('message', f, false);"
"else "
"""window.attachEvent('onmessage', f);"
);
} else {
result->setAttribute("type", "file");
if (flags_.test(BIT_MULTIPLE))
Expand Down
89 changes: 89 additions & 0 deletions test/dbo/DboTest.C
Original file line number Diff line number Diff line change
Expand Up @@ -2316,3 +2316,92 @@ BOOST_AUTO_TEST_CASE( dbo_test25 )
}
#endif // FIREBIRD
}

BOOST_AUTO_TEST_CASE( dbo_test26 )
{
#ifndef SQLITE3 // sqlite3 ":memory:" does not share database between sessions
DboFixture f;

dbo::Session *session_ = f.session_;

struct CheckExpected : Wt::WObject {
DboFixture& f_;
dbo::Session *session2_;

CheckExpected(DboFixture &f) : f_(f) {
session2_ = new dbo::Session();
session2_->setConnectionPool(*f_.connectionPool_);
session2_->mapClass<F>(SCHEMA "table_f");
}

virtual ~CheckExpected() {
delete session2_;
}

bool operator() (std::string &expected) {
{
dbo::Transaction t2(*session2_);
dbo::ptr<F> c = session2_->find<F>();
if (c->firstName != expected)
BOOST_ERROR(std::string("CheckExpected: firstName != expected, firstName: '") +
c->firstName + "', expected: '" + expected + "'");
else
BOOST_TEST_MESSAGE(std::string("CheckExpected OK: firstName: '") +
c->firstName + "', expected: '" + expected + "'");
}
return true;
}
} checkExpected(f);

{
dbo::Transaction t(*session_);

session_->add(new F("Alice", "Kramden", "Female"));

dbo::Query< dbo::ptr<F> > query = session_->find<F>();
dbo::QueryModel< dbo::ptr<F> > *model
= new dbo::QueryModel< dbo::ptr<F> >();

model->setQuery(query);
model->addAllFieldsAsColumns();

BOOST_REQUIRE(model->columnCount() == 5);
BOOST_REQUIRE(model->rowCount() == 1);
t.commit();

BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");

std::string ExpectedFirstName = "Alice";
BOOST_REQUIRE(checkExpected(ExpectedFirstName));

/*
* Set-up a handler to verify that updates are visible
* in a second session when model->dataChanged() is emitted
*/
model->dataChanged().connect(boost::bind<bool>(boost::ref(checkExpected),
boost::ref(ExpectedFirstName)));

/*
* The setItemData() convenience method commits
* a transaction prior to emitting dataChanged()
*/
ExpectedFirstName = "AliceTwo";
Wt::WAbstractItemModel::DataMap map;
map[Wt::EditRole] = ExpectedFirstName;
model->setItemData(model->index(0, 2), map); // checkExpected() will be called

BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == ExpectedFirstName);

/*
* The setData() should be equivalent to above setItemData() and
* commit a transaction prior to emitting dataChanged()
*/
ExpectedFirstName = "AliceThree";
model->setData(0, 2, ExpectedFirstName); // checkExpected() will be called

BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == ExpectedFirstName);

delete model;
}
#endif // SQLITE3
}

0 comments on commit 946a943

Please sign in to comment.