Device support: Ensure UI changes are always propagated to the device.

The original problem was that we cannot assume
QLineEdit::editingFinished() is emitted when clicking a button while a
QLineEdit has the focus (QTCREATORBUG-1675). The original solution to
that introduced two more bugs, namely that changes are not visible in
other tabs until the dialog has been closed and reopened and that
pressing "Apply" also applies changes that are done later and which the
user intends to revert by by pressing "Cancel" (QTCREATORBUG-7288).
This patch intends to fix all of these issues.

Task-number: QTCREATORBUG-1675
Task-number: QTCREATORBUG-7288
Change-Id: I569a89f64843e08ee389e3eba6bdcb473ba22393
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Christian Kandeler
2012-09-27 10:20:43 +02:00
parent 30b5534667
commit dff0761406
7 changed files with 45 additions and 9 deletions

View File

@@ -102,7 +102,6 @@ DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent)
m_deviceManager(DeviceManager::cloneInstance()), m_deviceManager(DeviceManager::cloneInstance()),
m_deviceManagerModel(new DeviceManagerModel(m_deviceManager, this)), m_deviceManagerModel(new DeviceManagerModel(m_deviceManager, this)),
m_nameValidator(new NameValidator(m_deviceManager, this)), m_nameValidator(new NameValidator(m_deviceManager, this)),
m_saveSettingsRequested(false),
m_additionalActionsMapper(new QSignalMapper(this)), m_additionalActionsMapper(new QSignalMapper(this)),
m_configWidget(0) m_configWidget(0)
{ {
@@ -115,11 +114,6 @@ DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent)
DeviceSettingsWidget::~DeviceSettingsWidget() DeviceSettingsWidget::~DeviceSettingsWidget()
{ {
if (m_saveSettingsRequested) {
Core::ICore::settings()->setValue(QLatin1String(LastDeviceIndexKey),
currentIndex());
DeviceManager::replaceInstance();
}
DeviceManager::removeClonedInstance(); DeviceManager::removeClonedInstance();
delete m_configWidget; delete m_configWidget;
delete m_ui; delete m_ui;
@@ -237,10 +231,17 @@ void DeviceSettingsWidget::fillInValues()
m_ui->nameLineEdit->setText(current->displayName()); m_ui->nameLineEdit->setText(current->displayName());
} }
void DeviceSettingsWidget::updateDeviceFromUi()
{
deviceNameEditingFinished();
if (m_configWidget)
m_configWidget->updateDeviceFromUi();
}
void DeviceSettingsWidget::saveSettings() void DeviceSettingsWidget::saveSettings()
{ {
// We must defer this step because of a stupid bug on MacOS. See QTCREATORBUG-1675. Core::ICore::settings()->setValue(QLatin1String(LastDeviceIndexKey), currentIndex());
m_saveSettingsRequested = true; DeviceManager::replaceInstance();
} }
int DeviceSettingsWidget::currentIndex() const int DeviceSettingsWidget::currentIndex() const
@@ -329,12 +330,14 @@ void DeviceSettingsWidget::handleAdditionalActionRequest(int actionId)
{ {
const IDevice::ConstPtr device = m_deviceManager->find(currentDevice()->id()); const IDevice::ConstPtr device = m_deviceManager->find(currentDevice()->id());
QTC_ASSERT(device, return); QTC_ASSERT(device, return);
updateDeviceFromUi();
device->executeAction(Core::Id::fromUniqueIdentifier(actionId), this); device->executeAction(Core::Id::fromUniqueIdentifier(actionId), this);
} }
void DeviceSettingsWidget::handleProcessListRequested() void DeviceSettingsWidget::handleProcessListRequested()
{ {
QTC_ASSERT(currentDevice()->canCreateProcessModel(), return); QTC_ASSERT(currentDevice()->canCreateProcessModel(), return);
updateDeviceFromUi();
DeviceProcessesDialog dlg; DeviceProcessesDialog dlg;
dlg.addCloseButton(); dlg.addCloseButton();
dlg.setDevice(currentDevice()); dlg.setDevice(currentDevice());

View File

@@ -81,12 +81,12 @@ private:
void clearDetails(); void clearDetails();
QString parseTestOutput(); QString parseTestOutput();
void fillInValues(); void fillInValues();
void updateDeviceFromUi();
Ui::DeviceSettingsWidget *m_ui; Ui::DeviceSettingsWidget *m_ui;
DeviceManager * const m_deviceManager; DeviceManager * const m_deviceManager;
DeviceManagerModel * const m_deviceManagerModel; DeviceManagerModel * const m_deviceManagerModel;
NameValidator * const m_nameValidator; NameValidator * const m_nameValidator;
bool m_saveSettingsRequested;
QList<QPushButton *> m_additionalActionButtons; QList<QPushButton *> m_additionalActionButtons;
QSignalMapper * const m_additionalActionsMapper; QSignalMapper * const m_additionalActionsMapper;
IDeviceWidget *m_configWidget; IDeviceWidget *m_configWidget;

View File

@@ -50,6 +50,18 @@ namespace ProjectExplorer {
class PROJECTEXPLORER_EXPORT IDeviceWidget : public QWidget class PROJECTEXPLORER_EXPORT IDeviceWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public:
/*!
* \brief Ensures that all changes in the UI are propagated to the device object.
*
* If the device is always updated right when the change happens, the implementation of
* this function can be empty. Note, however, that you cannot generally rely on the
* QLineEdit::editingFinished() signal being emitted on time if some button in the dialog is
* clicked (e.g. "Apply"). So if you have any handlers for line edit changes, they should
* probably be called here.
*/
virtual void updateDeviceFromUi() = 0;
protected: protected:
IDeviceWidget(const IDevice::Ptr &device, QWidget *parent = 0) IDeviceWidget(const IDevice::Ptr &device, QWidget *parent = 0)

View File

@@ -93,6 +93,14 @@ void BlackBerryDeviceConfigurationWidget::debugTokenEditingFinished()
deviceConfiguration()->setDebugToken(ui->debugToken->path()); deviceConfiguration()->setDebugToken(ui->debugToken->path());
} }
void BlackBerryDeviceConfigurationWidget::updateDeviceFromUi()
{
hostNameEditingFinished();
passwordEditingFinished();
keyFileEditingFinished();
debugTokenEditingFinished();
}
void BlackBerryDeviceConfigurationWidget::initGui() void BlackBerryDeviceConfigurationWidget::initGui()
{ {
ui->debugToken->setExpectedKind(Utils::PathChooser::File); ui->debugToken->setExpectedKind(Utils::PathChooser::File);

View File

@@ -62,6 +62,7 @@ private slots:
void debugTokenEditingFinished(); void debugTokenEditingFinished();
private: private:
void updateDeviceFromUi();
void initGui(); void initGui();
BlackBerryDeviceConfiguration::Ptr deviceConfiguration() const; BlackBerryDeviceConfiguration::Ptr deviceConfiguration() const;

View File

@@ -151,6 +151,17 @@ void GenericLinuxDeviceConfigurationWidget::createNewKey()
setPrivateKey(dialog.privateKeyFilePath()); setPrivateKey(dialog.privateKeyFilePath());
} }
void GenericLinuxDeviceConfigurationWidget::updateDeviceFromUi()
{
hostNameEditingFinished();
sshPortEditingFinished();
timeoutEditingFinished();
userNameEditingFinished();
passwordEditingFinished();
keyFileEditingFinished();
handleFreePortsChanged();
}
void GenericLinuxDeviceConfigurationWidget::updatePortsWarningLabel() void GenericLinuxDeviceConfigurationWidget::updatePortsWarningLabel()
{ {
m_ui->portsWarningLabel->setVisible(!device()->freePorts().hasMore()); m_ui->portsWarningLabel->setVisible(!device()->freePorts().hasMore());

View File

@@ -64,6 +64,7 @@ private slots:
void createNewKey(); void createNewKey();
private: private:
void updateDeviceFromUi();
void updatePortsWarningLabel(); void updatePortsWarningLabel();
void initGui(); void initGui();