0

I have class MainWindow that will contain several QWidgetTables with their own headers and other members. For now, I would like to define custom table classes within class MainWindow because they are pretty simple. See Example below:

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(SSHClient &client, QWidget *parent = 0);

public slots:
    struct Workflow_Table {
        QTableWidget* widget;
        QStandardItemModel model;
        QStringList headers;

        void addRow(){}
        void removeRow(){}
    } workflow_table;


private:
    SSHClient& client;
    Ui::MainWindow* ui;

    CTL ctl;
};

Within Ui::MainWindow I have QPushButtons to add and remove rows for workflow_table. I would like to connect these QPushButton::clicked signals to MainWindow::Workflow_Table::addRow, but I haven't had any success, nor do I know if what I'm attemping is even possible.

MainWindow::MainWindow(SSHClient &client, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    client(client)
{
    ui->setupUi(this);

    //class CTL is a not a QObject class, yet std::bind causes it to act like a slot here. This statement compiles and runs fine.
    connect(ui->button_load_ctl, &QPushButton::clicked, this, std::bind(&CTL::saveas, &ctl, "saved.ctl"));

    //Error: 3 Arguments provided - 4 Expected. I'm almost certain this won't work.
    connect(ui->button_add, &QPushButton::clicked, this, &MainWindow::Workflow_Table::addRow);

    //Error: Not a signal or slot declaration. Not sure why this isn't working.
    connect(ui->button_add, &QPushButton::clicked, this, std::bind(&MainWindow::Workflow_Table::addRow, &workflow_table));

    //This doesn't work either. Error 1.
    connect(ui->button_add, &QPushButton::clicked, this, std::bind(&Workflow_Table::addRow, &workflow_table));

}

Is it possible that I can connect MainWindow::Workflow_Table::addRow (without making Workflow_Table a QObject) to a QPushButton::clicked signal from MainWindow?

The easy solution is to make Workflow_Table a QObject, but I'm curious if I can still connect the Workflow_Table's functions since they're defined under the scope of a QObject. I have been able to connect other non-slot functions by using std::bind like the CTL::saveas function so I would think I can do something similar here. I have also tried moving Workflow_Table under the public and public slots access specifiers but neither has worked.

E. Pratt
  • 84
  • 2
  • 8
  • 1
    the easiest way is to put `addRow()` inside `onPushButton_clicked()`. Using the Meta Object system is quite an overkill for just clicking and adding rows. – Joseph D. May 20 '17 at 03:57

1 Answers1

-1

It all works - it's your fault for not showing an actual, complete example that fails. When I paste it into an empty project, everything compiles except the second connect, there you have to use std::bind or a lambda so that the addRow() has something to work with.

Generally speaking, it's pointless to use bind if the lambda would be shorter, so just use lambdas when code clarity gains from it.

This works:

// https://github.com/KubaO/stackoverflown/tree/master/questions/connect-bind-44081724
#include <QtWidgets>
#include <functional>

class Class : public QWidget
{
   Q_OBJECT
   QPushButton button;
   struct CTL {
      void saveas(const QString &);
   } ctl;
   struct Workflow_Table {
       void addRow() {}
   } workflow_table;

public:
   Class() {
      connect(&button, &QPushButton::clicked, this, std::bind(&CTL::saveas, &ctl, "saved.ctl"));
      connect(&button, &QPushButton::clicked, this, [this]{ workflow_table.addRow(); });
      connect(&button, &QPushButton::clicked, this, std::bind(&Workflow_Table::addRow, &workflow_table));

      // better yet
      connect(&button, &QPushButton::clicked, this, [this]{ ctl.saveas("saved.ctl"); });
      connect(&button, &QPushButton::clicked, this, [this]{ workflow_table.addRow(); });

      // or simply, if we know that `this` will outlive `button` (they do by design here),
      // and that both button and this live in the same thread (again, they do by design here)
      connect(&button, &QPushButton::clicked, [this]{ ctl.saveas("saved.ctl"); });
      connect(&button, &QPushButton::clicked, [this]{ workflow_table.addRow(); });
   }
};

int main() {}
#include "main.moc"
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313