Wow, no offense, but that's a way more confusing implementation that it needs to be. No wonder you are having trouble with circular dependencies.
I think most of your problem stems from the fact that there is no one "in charge" in your GUI. You have a tabbed dialog (a QWidget, actually - ColorSelect) that contains two tabs, neither of which knows about the other but which need to communicate information. And probably, because you couldn't figure out how to do it in Qt Designer, you create and show() your ColorWheel instance separately.
I am going to be presumptuous and refactor your code a bit to make it less interdependent.
First step is to make ColorWheel a proper and independent child of the ColorSelect widget, by "promoting" the QWidget you have created in Designer. To do this, you open the ui file in Designer, right-click on the place where you inserted the QWidget instead of the ColorWheel, and select "Promote to...". This will open the widget promotion dialog. In the Promoted class name box, type "ColorWheel" and it will automatically insert the header file name in the box below. Click "Add", then click Promote and Close. If you inspect the object list, you will now see that the object type for the color wheel is now ColorWheel instead of QWidget.
Next step is to get rid of the dependence of ColorWheel on ColorSelect. Remove the ColorSelect argument from the constructor, remove the member variable, and remove all references to it from the ColorWheel .cpp and .h files. Remove the include of colorselect.h. Replace the call to colorSelect->updatePalette() in the ColorWheel class with a call to emit colorChange(). Move the QPalette stuff out of main() and into the ColorWheel constructor:
ColorWheel
::ColorWheel(QWidget *parent
) : initSize(200,200),
mouseDown(false),
margin(0),
wheelWidth(30),
current(Qt::red),
inWheel(false),
inSquare(false)
{
// resize(initSize);
current = current.toHsv();
// setMinimumSize(200,200);
setCursor(Qt::CrossCursor);
setPalette(wheelPalette);
}
ColorWheel::ColorWheel(QWidget *parent) :
QWidget(parent),
initSize(200,200),
mouseDown(false),
margin(0),
wheelWidth(30),
current(Qt::red),
inWheel(false),
inSquare(false)
{
// resize(initSize);
current = current.toHsv();
// setMinimumSize(200,200);
setCursor(Qt::CrossCursor);
QPalette wheelPalette = palette();
wheelPalette.setBrush(QPalette::Window, QBrush(Qt::white));
setPalette(wheelPalette);
}
To copy to clipboard, switch view to plain text mode
Now, ColorWheel is completely independent of ColorSelect. You need to reconnect the notification about color changes in the wheel so that ColorSelect can follow them. In the ColorSelect constructor, add a connect statement:
connect( ui
->colorWheelWidget,
SIGNAL( colorChange
( const QColor & ) ),
this,
SLOT( updatePalette
( const QColor & ) ) );
connect( ui->colorWheelWidget, SIGNAL( colorChange( const QColor & ) ), this, SLOT( updatePalette( const QColor & ) ) );
To copy to clipboard, switch view to plain text mode
and rewrite the updatePalette() method as a slot:
// .h:
private slots:
void updatePalette
( const QColor & );
// .cpp:
void ColorSelect
::updatePalette( const QColor & color
) {
//get palette
QPalette pal
= ui
->colorPalette
->palette
();
//update palette with colorToRGB
ui->colorPalette->setPalette(pal);
emit colorChanged(color);
qDebug()<< color;
}
// .h:
private slots:
void updatePalette( const QColor & );
// .cpp:
void ColorSelect::updatePalette( const QColor & color )
{
//get palette
QPalette pal = ui->colorPalette->palette();
//update palette with colorToRGB
pal.setColor(QPalette::Window, color);
ui->colorPalette->setPalette(pal);
emit colorChanged(color);
qDebug()<< color;
}
To copy to clipboard, switch view to plain text mode
Next, now that you are building the ColorWheel entirely within ColorSelect, you can dramatically simplify main():
#include "colorselect.h"
#include "serialcom.h"
int main(int argc, char *argv[])
{
SerialCom *serialCom = new SerialCom();
ColorSelect *colorSelect = new ColorSelect(0,serialCom);
colorSelect->setWindowTitle("RGB-LED Color Picker");
//show UI
colorSelect->show();
return a.exec();
}
#include "colorselect.h"
#include "serialcom.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SerialCom *serialCom = new SerialCom();
ColorSelect *colorSelect = new ColorSelect(0,serialCom);
colorSelect->setWindowTitle("RGB-LED Color Picker");
//show UI
colorSelect->show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
Next step is to break the dependence of DeviceDialog on ColorSelect. DeviceDialog's entire purpose is to capture two pieces of text from the user. So, it has no business knowing that ColorSelect is going to add those things to a list widget somewhere. It just simply needs to announce to the world, "Hey, I have new text!" So, DeviceDialog becomes this:
// .h:
#ifndef DEVICEDIALOG_H
#define DEVICEDIALOG_H
#include <QDialog>
namespace Ui {
class DeviceDialog;
}
class DeviceDialog
: public QDialog{
Q_OBJECT
public:
explicit DeviceDialog
(QWidget *parent
= 0);
~DeviceDialog();
signals:
void houseAndUnitChanged
( const QString & house,
const QString & unit
);
private slots:
void on_buttonBox_accepted();
private:
Ui::DeviceDialog *ui;
};
#endif // DEVICEDIALOG_H
// .h:
#ifndef DEVICEDIALOG_H
#define DEVICEDIALOG_H
#include <QDialog>
namespace Ui {
class DeviceDialog;
}
class DeviceDialog : public QDialog
{
Q_OBJECT
public:
explicit DeviceDialog(QWidget *parent = 0);
void setLineEdits(QString);
~DeviceDialog();
signals:
void houseAndUnitChanged( const QString & house, const QString & unit );
private slots:
void on_buttonBox_accepted();
private:
Ui::DeviceDialog *ui;
};
#endif // DEVICEDIALOG_H
To copy to clipboard, switch view to plain text mode
// .cpp
#include "devicedialog.h"
#include "ui_devicedialog.h"
DeviceDialog
::DeviceDialog(QWidget *parent
) : ui(new Ui::DeviceDialog)
{
ui->setupUi(this);
}
DeviceDialog::~DeviceDialog()
{
delete ui;
}
void DeviceDialog
::setLineEdits(QString houseAndUnit
) {
ui->houseLineEdit->setText(houseAndUnit.mid(0,1));
ui->unitLineEdit->setText(houseAndUnit.mid(1,1));
}
void DeviceDialog::on_buttonBox_accepted()
{
emit houseAndUnitChanged( (ui->houseLineEdit->text(), ui->unitLineEdit->text() );
}
// .cpp
#include "devicedialog.h"
#include "ui_devicedialog.h"
DeviceDialog::DeviceDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::DeviceDialog)
{
ui->setupUi(this);
}
DeviceDialog::~DeviceDialog()
{
delete ui;
}
void DeviceDialog::setLineEdits(QString houseAndUnit)
{
ui->houseLineEdit->setText(houseAndUnit.mid(0,1));
ui->unitLineEdit->setText(houseAndUnit.mid(1,1));
}
void DeviceDialog::on_buttonBox_accepted()
{
emit houseAndUnitChanged( (ui->houseLineEdit->text(), ui->unitLineEdit->text() );
}
To copy to clipboard, switch view to plain text mode
Finally, you have to fix up ColorSelect so it handles the DeviceDialog signal:
// .h
private slots:
void onHouseAndUnitChanged
( const QString & house,
const QString & unit
);
// and delete the "DeviceDialog" member variable.
// .cpp
{
DeviceDialog dialog(this);
connect( &dialog,
SIGNAL( houseAndUnitChanged
( const QString &,
const QString & ) ),
this,
SLOT( onHouseAndUnitChanged
( const QString &,
const QString & ) ) );
dialog.setLineEdits(item->data(Qt::UserRole).toString());
dialog.exec();
}
void ColorSelect
::onHouseAndUnitChanged( const QString & house,
const QString & unit
) {
setItemData( house, unit );
}
// .h
private slots:
void onHouseAndUnitChanged( const QString & house, const QString & unit );
// and delete the "DeviceDialog" member variable.
// .cpp
void ColorSelect::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{
DeviceDialog dialog(this);
connect( &dialog, SIGNAL( houseAndUnitChanged( const QString &, const QString & ) ), this, SLOT( onHouseAndUnitChanged( const QString &, const QString & ) ) );
dialog.setLineEdits(item->data(Qt::UserRole).toString());
dialog.exec();
}
void ColorSelect::onHouseAndUnitChanged( const QString & house, const QString & unit )
{
setItemData( house, unit );
}
To copy to clipboard, switch view to plain text mode
There's still more cleanup and refactoring you could do, but now you have something where there are no circular dependencies, and in fact very few dependencies at all.
I've attached a zip file with all the code changes.
colorselect_serial.zip
By the way, I am out of the office until the end of the week, so I won't be following the forum.
Bookmarks