Project

General

Profile

Actions

Bug #6102

closed

Can't chain signals from children up to parent widget

Added by Grzesiek Buraczewski about 7 years ago. Updated about 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
Start date:
11/05/2017
Due date:
% Done:

0%

Estimated time:

Description

Hi,

I have problem with Planner example after some modifications

@

WWidget* PlannerCalendar::renderCell(WWidget* widget, const WDate& date)

{

if (!widget)

{

widget = new CalendarCell();

}

CalendarCell* cc = (CalendarCell*)widget;

cc->update(user_, date);

cc->cellWasModified().connect(this, &PlannerCalendar::calendarWasModified); // this part gives error

/*

*cellWasModified() returns signal which I want to chain to 2nd function calendarWasModified() which should emit signal herself when triggered

  • up to 3rd widget (parent) but I'm stuck. I get this error in the compiler
    */

return cc;

}

@

error:

In file included from /usr/local/include/Wt/WSignal.h:13:0,

from /usr/local/include/Wt/WWidget.h:14,

from /usr/local/include/Wt/WCompositeWidget.h:10,

from /usr/local/include/Wt/WCalendar.h:10,

from ../PlannerCalendar.h:14,

from ../PlannerCalendar.cpp:7:

/usr/local/include/Wt/Signals/signals.hpp: In instantiation of 'struct Wt::Signals::Impl::function_traits<Wt::SignalWt::WString& (PlannerCalendar::*)()>':

/usr/local/include/Wt/Signals/signals.hpp:444:14: required from 'Wt::Signals::connection Wt::Signals::Impl::connectFunction(Wt::Signals::Signal<Args ...>&, typename std::enable_if<(! std::is_bind_expression::value), const F&>::type, const Wt::Core::observable*) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); Args = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection; typename std::enable_if<(! std::is_bind_expression::value), const F&>::type = Wt::SignalWt::WString& (PlannerCalendar::* const&)()]'

/usr/local/include/Wt/WSignal.h:656:49: required from 'Wt::Signals::connection Wt::Signal::connect(const Wt::WObject
, const F&) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); A = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection]'

../PlannerCalendar.cpp:32:76: required from here

/usr/local/include/Wt/Signals/signals.hpp:302:58: error: 'operator()' is not a member of 'Wt::SignalWt::WString& (PlannerCalendar::*)()'

struct function_traits : public function_traits<decltype(&Function::operator())>

^

/usr/local/include/Wt/Signals/signals.hpp: In instantiation of 'Wt::Signals::connection Wt::Signals::Impl::connectFunction(Wt::Signals::Signal<Args ...>&, typename std::enable_if<(! std::is_bind_expression::value), const F&>::type, const Wt::Core::observable
) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); Args = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection; typename std::enable_if<(! std::is_bind_expression::value), const F&>::type = Wt::SignalWt::WString& (PlannerCalendar::* const&)()]':

/usr/local/include/Wt/WSignal.h:656:49: required from 'Wt::Signals::connection Wt::Signal::connect(const Wt::WObject
, const F&) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); A = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection]'

../PlannerCalendar.cpp:32:76: required from here

/usr/local/include/Wt/Signals/signals.hpp:444:14: error: 'argCount' is not a member of 'Wt::Signals::Impl::function_traits<Wt::SignalWt::WString& (PlannerCalendar::*)()>'

::connect(signal, target, Signals::Impl::toFunction(function));

^

/usr/local/include/Wt/Signals/signals.hpp: In instantiation of 'struct Wt::Signals::Impl::function_traits<Wt::SignalWt::WString& (PlannerCalendar::* const)()>':

/usr/local/include/Wt/Signals/signals.hpp:313:46: required by substitution of 'template typename Wt::Signals::Impl::function_traits::function Wt::Signals::Impl::toFunction(Function&) [with Function = Wt::SignalWt::WString& (PlannerCalendar::* const)()]'

/usr/local/include/Wt/Signals/signals.hpp:444:56: required from 'Wt::Signals::connection Wt::Signals::Impl::connectFunction(Wt::Signals::Signal<Args ...>&, typename std::enable_if<(! std::is_bind_expression::value), const F&>::type, const Wt::Core::observable
) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); Args = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection; typename std::enable_if<(! std::is_bind_expression::value), const F&>::type = Wt::SignalWt::WString& (PlannerCalendar::* const&)()]'

/usr/local/include/Wt/WSignal.h:656:49: required from 'Wt::Signals::connection Wt::Signal::connect(const Wt::WObject
, const F&) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); A = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection]'

../PlannerCalendar.cpp:32:76: required from here

/usr/local/include/Wt/Signals/signals.hpp:302:58: error: 'operator()' is not a member of 'Wt::SignalWt::WString& (PlannerCalendar::* const)()'

struct function_traits : public function_traits<decltype(&Function::operator())>

^

/usr/local/include/Wt/Signals/signals.hpp: In instantiation of 'Wt::Signals::connection Wt::Signals::Impl::connectFunction(Wt::Signals::Signal<Args ...>&, typename std::enable_if<(! std::is_bind_expression::value), const F&>::type, const Wt::Core::observable
) [with F = Wt::SignalWt::WString& (PlannerCalendar::)(); Args = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection; typename std::enable_if<(! std::is_bind_expression::value), const F&>::type = Wt::SignalWt::WString& (PlannerCalendar::* const&)()]':

/usr/local/include/Wt/WSignal.h:656:49: required from 'Wt::Signals::connection Wt::Signal::connect(const Wt::WObject
, const F&) [with F = Wt::SignalWt::WString& (PlannerCalendar::*)(); A = {Wt::WString}; Wt::Signals::connection = Wt::Signals::Impl::Connection]'

../PlannerCalendar.cpp:32:76: required from here

/usr/local/include/Wt/Signals/signals.hpp:444:56: error: no matching function for call to 'toFunction(Wt::SignalWt::WString& (PlannerCalendar::* const&)())'

::connect(signal, target, Signals::Impl::toFunction(function));

^

/usr/local/include/Wt/Signals/signals.hpp:313:46: note: candidate: template typename Wt::Signals::Impl::function_traits::function Wt::Signals::Impl::toFunction(Function&)

typename function_traits::function toFunction(Function& lambda)

^

/usr/local/include/Wt/Signals/signals.hpp:313:46: note: substitution of deduced template arguments resulted in errors seen above

make: * [PlannerCalendar.o] Error 1

subdir.mk:45: recipe for target 'PlannerCalendar.o' failed


Files

PlannerCalendar.h (929 Bytes) PlannerCalendar.h Roel Standaert, 11/10/2017 03:23 PM
PlannerCalendar.C (1.01 KB) PlannerCalendar.C Roel Standaert, 11/10/2017 03:23 PM
Actions #1

Updated by Grzesiek Buraczewski about 7 years ago

cc->cellWasModified().connect(std::bind(&PlannerCalendar::calendarWasModified, this ));

std::bind fixed it for me, but why i got this error without bind ??

Actions #2

Updated by Roel Standaert about 7 years ago

  • Status changed from New to Feedback

Could you provide a more complete example, maybe a patch file with all of your changes? I've tried it out, and it seems to be compiling fine on my end. (I'm on Ubuntu 16.04 with GCC 5.4, by the way.)

Actions #3

Updated by Grzesiek Buraczewski about 7 years ago

I have the same spec. Ubuntu 16.04 , gcc 5.4.1

// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef CALENDAR_CELL_H_
#define CALENDAR_CELL_H_

#include "UserAccount.h"

#include <Wt/WContainerWidget.h>

//debuging
#include <iostream>

using namespace Wt;

class CalendarCell : public WContainerWidget
{
public:
  CalendarCell();

  void update(const dbo::ptr<UserAccount>& user, const WDate& date);

  WDate date() {return date_; }
  dbo::ptr<UserAccount> user() { return user_; }

  Signal<WString>& cellWasModified() { std::cout << "from CalendarCell" << std::endl; return cellModified_;}; //hard coded
  Signal<WString> cellModified_;

private:
  WDate date_;
  dbo::ptr<UserAccount> user_;
  std::unique_ptr<WDialog> dialog_;

  void showEntryDialog();
  void showAllEntriesDialog();
};

#endif //CALENDAR_CELL_H_

/*
 * Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#include "CalendarCell.h"
#include "EntryDialog.h"
#include "AllEntriesDialog.h"
#include "Login/PlannerApplication.h"
#include "Entry.h"

#include <Wt/WDate.h>
#include <Wt/WText.h>

#include <Wt/WSignal.h>

#include <string>


CalendarCell::CalendarCell()
  : WContainerWidget()
{
  resize(100, 120); // single cell size

  setStyleClass("cell");
  setToolTip(tr("calendar.cell.tooltip"));

  clicked().connect(this, &CalendarCell::showEntryDialog);
}

void CalendarCell::update(const dbo::ptr<UserAccount>& user, const WDate& date)
{
  date_ = date;
  user_ = user;
  //Signal
  std::cout << "edit from cell" << std::endl;
  cellModified_.emit(""); // hard coded for debugin
  //
  clear();

  dbo::Session& session = PlannerApplication::plannerApplication()->session;
  dbo::Transaction transaction(session);

  WString day;
  day += std::to_string(date.day());
  if (date.day() == 1)
  {
    day += " " + WDate::longMonthName(date.month());
  }
  auto header = cpp14::make_unique<WText>(day);
  header->setStyleClass("cell-header");
  addWidget(std::move(header));

  typedef dbo::collection< dbo::ptr<Entry> > Entries;
  Entries entries = user->entriesInRange(date, date.addDays(1));

  const unsigned maxEntries = 4;
  unsigned counter = 0;
  for (Entries::const_iterator i = entries.begin();
       i != entries.end(); ++i, ++counter) {
    if (counter == maxEntries) {
      auto extra =
        cpp14::make_unique<WText>(tr("calendar.cell.extra")
          .arg((int)(entries.size() - maxEntries)));
      auto extraPtr = addWidget(std::move(extra));
      extraPtr->setStyleClass("cell-extra");

      extraPtr->clicked().preventPropagation();
      extraPtr->clicked().connect(this, &CalendarCell::showAllEntriesDialog);
      break;
    }

    WString format = EntryDialog::timeFormat;
    auto textToCell = cpp14::make_unique<WText>(
            // I commented this out becase this app is not exact to hour day planer but rather
            // week planing app
            //(*i)->start.toString(format) +
            //"-" +
            //(*i)->stop.toString(format) +
            /*": " + */ (*i)->summary);


    //ADD color acording to status of task
    if((*i)->isFinished.empty())
    {
        textToCell->setStyleClass("unfinished-task");
    }
    else
    {
        textToCell->setStyleClass("finished-task");
    }

    addWidget(std::move(textToCell));

  }

  transaction.commit();
}

void CalendarCell::showEntryDialog()
{
  WString title =
    tr("calendar.entry.title").arg(date_.toString("ddd, d MMM yyyy"));

    dialog_ = cpp14::make_unique<EntryDialog>(title, this);
    dialog_->show();
}

void CalendarCell::showAllEntriesDialog()
{
  WString title =
    tr("calendar.cell.all-entries.title")
    .arg(date_.toString("ddd, d MMM yyyy"));

  dialog_ = cpp14::make_unique<AllEntriesDialog>(title, this);
  dialog_->show();
}

And this is the planner calendar class

// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#ifndef PLANNER_CALENDAR_H_
#define PLANNER_CALENDAR_H_

#include "UserAccount.h"

#include <Wt/Dbo/Dbo.h>
#include <Wt/WCalendar.h>
#include <Wt/WSignal.h>
#include <Wt/WDate.h>

using namespace Wt;

class PlannerCalendar : public WCalendar
{
public:
  PlannerCalendar(dbo::ptr<UserAccount> user);

  Signal<WString>& calendarWasModified() {return calendarModified_ ;} //TODO implement its now hard coded
  Signal<WString> calendarModified_;

  void onlyForDebuging() {std::cout << "Debug worked in PlannerCalendar" << std::endl; calendarModified_.emit("");}
protected:
  virtual WWidget* renderCell(WWidget* widget, const WDate& date) override;

private:
  dbo::ptr<UserAccount> user_;
};

#endif //PLANNER_CALENDAR_H_

And .cpp file

/*
 * Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#include "PlannerCalendar.h"
#include "CalendarCell.h"
#include "Entry.h"
#include <Wt/WWidget.h>
#include <memory>

using namespace Wt;

PlannerCalendar::PlannerCalendar(dbo::ptr<UserAccount> user)
  : WCalendar(),
    user_(user)
{
  setStyleClass(styleClass() + " calendar");
  //setSelectionMode(SelectionMode::None);
}

WWidget* PlannerCalendar::renderCell(WWidget* widget, const WDate& date)
{
  if (!widget)
  {
    widget = new CalendarCell();
  }

  CalendarCell* cc = (CalendarCell*)widget;
  cc->update(user_, date);


  cc->cellWasModified().connect(this, &PlannerCalendar::calendarWasModified);
  cc->cellWasModified().connect(this ,&PlannerCalendar::onlyForDebuging);

  //calendarModified_.emit(WString("tom")); //TODO hardcoded
 // cc->cellWasModified().connect(this, &PlannerCalendar::calendarWasModified);
  return cc;
}

I dont know how to send multiple files so i post them here.

Updated by Roel Standaert about 7 years ago

I see what you're doing wrong: you are trying to connect the cellWasModified() signal to a method that returns a Signal. That's not how you should do that: you have to connect it to a method that returns void, and emits the cellWasModified() signal, see the modified files I attached.

Actions #5

Updated by Roel Standaert about 7 years ago

  • Status changed from Feedback to Closed

Closing this since it's not an issue with Wt.

Actions

Also available in: Atom PDF