You oversubscribed something almost trivial. You are also excessive.
Yes, it is always useful to distract logic from the user interface, but in the case of your specific example, an additional level of data abstraction is not needed, mainly because you do not have different data sets, you only have two values that really are part of the logic and do not deserve level of data abstraction.
Now it would be different if you had a traditional “list of items” model and your view is a list / tree / table, but your case is one of one form.
In your case, the correct design would be the Converter class, which includes the current model data, the controller and the conversion logic, and the ConverterUI class, which is essentially your form of presentation. You save the template code and component connection.
Having said that, you are free to go through excessive length for excess.
1 - you give these changes from the view to the connection with the controller, therefore it will always be displayed in the corresponding view, the controller does not have any relation to what kind, how many views can be, or if there is a look at all. QSignalMapper is an option, but it is quite limited - it supports only one parameter and only a few types of parameters. I myself honestly prefer one linear slot, they are more flexible and not everything that is difficult to write, plus they are reusable code, which is sometimes useful. Lambdas is a great new feature, and using these functions will make you look cooler, but in your particular case they will not make that much difference, and only lambdas does not deserve the transition to Qt5. However, there are many more reasons to upgrade Qt5 other than lambdas.
2 - signals and slots, you know that you are editing, so you only update this
3 - the transmission of values through signals is more elegant and does not require your controller to maintain a link to the view and control which view, as described in 1
4 - as seen from the MVC diagram, the view has a read-only reference. Therefore, if you want MVC “by the book”, then what you need.

In the previous example, I improved (somewhat, still unverified), now there is Data , which is just a regular structure, you definitely do not want this to be a QObject if you have many of them, since QObject is a huge amount of memory, Model , which supports the data set, Controller , which iterates the basic data set Model and reads and writes data, View , which is attached to the controller and App , which combines the model and two independent controllers for it and two independent views. There is limited functionality - you can go to the next available record of the data set, change or delete, in this example there is no addition or reordering, you can implement them as an exercise. Changes will propagate back to the model and, thus, reflect in each controller and corresponding representation. You can have several different views tied to one controller. The controller model is currently fixed, but if you want to change it, you must go through a procedure similar to setting the controller for presentation, that is, disconnect the old one before connecting to the new one, although if you delete the old one, it will automatically shut down.
struct Data { QString d1, d2; }; class Model : public QObject { Q_OBJECT QVector<Data> dataSet; public: Model() { dataSet << Data{"John", "Doe"} << Data{"Jane", "Doe"} << Data{"Clark", "Kent"} << Data{"Rick", "Sanchez"}; } int size() const { return dataSet.size(); } public slots: QString getd1(int i) const { return i > -1 && i < dataSet.size() ? dataSet[i].d1 : ""; } QString getd2(int i) const { return i > -1 && i < dataSet.size() ? dataSet[i].d2 : ""; } void setd1(int i, const QString & d) { if (i > -1 && i < dataSet.size()) { if (dataSet[i].d1 != d) { dataSet[i].d1 = d; emit d1Changed(i); } } } void setd2(int i, const QString & d) { if (i > -1 && i < dataSet.size()) { if (dataSet[i].d2 != d) { dataSet[i].d2 = d; emit d2Changed(i); } } } void remove(int i) { if (i > -1 && i < dataSet.size()) { removing(i); dataSet.remove(i); removed(); } } signals: void removing(int); void removed(); void d1Changed(int); void d2Changed(int); }; class Controller : public QObject { Q_OBJECT Model * data; int index; bool shifting; public: Controller(Model * _m) : data(_m), index(-1), shifting(false) { connect(data, SIGNAL(d1Changed(int)), this, SLOT(ond1Changed(int))); connect(data, SIGNAL(d2Changed(int)), this, SLOT(ond2Changed(int))); connect(data, SIGNAL(removing(int)), this, SLOT(onRemoving(int))); connect(data, SIGNAL(removed()), this, SLOT(onRemoved())); if (data->size()){ index = 0; dataChanged(); } } public slots: QString getd1() const { return data->getd1(index); } QString getd2() const { return data->getd2(index); } void setd1(const QString & d) { data->setd1(index, d); } void setd2(const QString & d) { data->setd2(index, d); } void remove() { data->remove(index); } private slots: void onRemoving(int i) { if (i <= index) shifting = true; } void onRemoved() { if (shifting) { shifting = false; if ((index > 0) || (index && !data->size())) --index; dataChanged(); } } void ond1Changed(int i) { if (i == index) d1Changed(); } void ond2Changed(int i) { if (i == index) d2Changed(); } void fetchNext() { if (data->size()) { index = (index + 1) % data->size(); dataChanged(); } } signals: void dataChanged(); void d1Changed(); void d2Changed(); }; class View : public QWidget { Q_OBJECT Controller * c; QLineEdit * l1, * l2; QPushButton * b1, * b2, * bnext, * bremove; public: View(Controller * _c) : c(nullptr) { QVBoxLayout * l = new QVBoxLayout; setLayout(l); l->addWidget(l1 = new QLineEdit(this)); l->addWidget(b1 = new QPushButton("set", this)); connect(b1, SIGNAL(clicked(bool)), this, SLOT(setd1())); l->addWidget(l2 = new QLineEdit(this)); l->addWidget(b2 = new QPushButton("set", this)); connect(b2, SIGNAL(clicked(bool)), this, SLOT(setd2())); l->addWidget(bnext = new QPushButton("next", this)); l->addWidget(bremove = new QPushButton("remove", this)); setController(_c); } void setController(Controller * _c) { if (_c != c) { if (c) { disconnect(c, SIGNAL(d1Changed()), this, SLOT(updateL1())); disconnect(c, SIGNAL(d2Changed()), this, SLOT(updateL2())); disconnect(c, SIGNAL(dataChanged()), this, SLOT(updateForm())); disconnect(bnext, SIGNAL(clicked(bool)), c, SLOT(fetchNext())); disconnect(bremove, SIGNAL(clicked(bool)), c, SLOT(remove())); c = nullptr; } c = _c; if (c) { connect(c, SIGNAL(d1Changed()), this, SLOT(updateL1())); connect(c, SIGNAL(d2Changed()), this, SLOT(updateL2())); connect(c, SIGNAL(dataChanged()), this, SLOT(updateForm())); connect(bnext, SIGNAL(clicked(bool)), c, SLOT(fetchNext())); connect(bremove, SIGNAL(clicked(bool)), c, SLOT(remove())); } } updateForm(); } public slots: void updateL1() { l1->setText(c ? c->getd1() : ""); } void updateL2() { l2->setText(c ? c->getd2() : ""); } void updateForm() { updateL1(); updateL2(); } void setd1() { c->setd1(l1->text()); } void setd2() { c->setd2(l2->text()); } }; class App : public QWidget { Q_OBJECT Model m; Controller c1, c2; public: App() : c1(&m), c2(&m) { QVBoxLayout * l = new QVBoxLayout; setLayout(l); l->addWidget(new View(&c1)); l->addWidget(new View(&c2)); } };