/************************************************************************** ** ** This file is part of Qt Simulator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "configurationwidget.h" #include "ui_inspector.h" #include "configurationreader.h" #include "qsimulatordata_p.h" #include "viewconfiguration.h" #include "widget.h" #include "application.h" #include "deviceitem.h" #include #include #include #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(Orientation); ConfigurationWidget::ConfigurationWidget(const DeviceItem *deviceItem, QWidget *parent) : RemoteControlWidget(parent) , ui_inspector(new Ui_Inspector) , mCorrectionFactor(1) , mViewConfiguration(0) , mDeviceItem(deviceItem) { qRegisterMetaType(); QDesktopWidget *desktop = QApplication::desktop(); mLogicalDpi.setWidth(desktop->logicalDpiX()); mLogicalDpi.setHeight(desktop->logicalDpiY()); setWindowTitle(tr("Qt Simulator Control")); mScriptInterface = new SimulatorScriptInterface(this); initializeApplicationArea(); initializeViewArea(); } ConfigurationWidget::~ConfigurationWidget() { } void ConfigurationWidget::initializeViewArea() { QWidget *target = new QWidget(); ui_inspector->setupUi(target); mOrientationButtons = new QButtonGroup; mOrientationButtons->setParent(ui_inspector->topUp->parent()); mOrientationButtons->addButton(ui_inspector->topUp, static_cast(topUp)); mOrientationButtons->addButton(ui_inspector->rightUp, static_cast(rightUp)); mOrientationButtons->addButton(ui_inspector->topDown, static_cast(topDown)); mOrientationButtons->addButton(ui_inspector->leftUp, static_cast(leftUp)); connect(mOrientationButtons, SIGNAL(buttonClicked(int)), this, SLOT(changeOrientation(int))); updateOrientationsButtonsIcons(false); connect(ui_inspector->scaleSlider, SIGNAL(valueChanged(int)), this, SLOT(changeScaleFactor(int))); connect(ui_inspector->deviceListView, SIGNAL(currentIndexChanged(int)), this, SLOT(changeDeviceSelection(int))); connect(ui_inspector->rotateScreen, SIGNAL(toggled(bool)), this, SLOT(rotateScreenToggled())); mViewPage = new PageWidget(tr("View"), target); mViewPage->setHideable(true); mViewPage->setHasAdvancedButton(true); mViewPage->advancedButton()->setToolTip(tr("Configure DPI correction")); connect(mViewPage, SIGNAL(advancedButtonClicked()), SLOT(showViewConfiguration())); addPage(mViewPage); } void ConfigurationWidget::initializeApplicationArea() { QWidget *target = new QWidget(); QFormLayout *innerLayout = new QFormLayout(); mWidgetTitle = new QLineEdit(); mWidgetTitle->setReadOnly(true); innerLayout->addRow(tr("Topmost widget's title"), mWidgetTitle); mMenuLayout = new QHBoxLayout(); innerLayout->addRow(tr("Application's menubar"), mMenuLayout); QPushButton *exitButton = new QPushButton(tr("Quit")); connect(exitButton, SIGNAL(clicked()), SIGNAL(exitButtonClicked())); innerLayout->addRow(tr("Quit current application"), exitButton); target->setLayout(innerLayout); mAppPage = new PageWidget(tr("Application"), target); mAppPage->setHideable(true); mAppPage->hideContent(); addPage(mAppPage); } int ConfigurationWidget::currentDeviceIndex() const { return ui_inspector->deviceListView->currentIndex(); } QString ConfigurationWidget::currentDeviceName() const { return ui_inspector->deviceListView->currentText(); } void ConfigurationWidget::changeDeviceSelection(int newIndex) { ui_inspector->deviceListView->setCurrentIndex(newIndex); const DeviceData &newData = deviceList.at(newIndex); emit deviceSelectionChanged(newData); updateOrientationButtons(newData); } void ConfigurationWidget::updateMenuBarWidget(Widget *menuBarWidget) { QMenuBar *menuBar = 0; if (menuBarWidget) { menuBar = menuBarWidget->menuBar(); mWidgetTitle->setText(menuBarWidget->title); } else { mWidgetTitle->setText(QString()); } if (mMenuBar == menuBar) return; if (mMenuBar) { mMenuBar->hide(); mMenuLayout->removeWidget(mMenuBar); } mMenuBar = menuBar; if (!menuBar) return; mMenuLayout->insertWidget(0, mMenuBar); mMenuBar->show(); } void ConfigurationWidget::updateOrientationButtonsState(Orientation orientation) { mOrientationButtons->button(orientation)->setChecked(true); } void ConfigurationWidget::updateOrientationsButtonsIcons(bool standardOrientationPortrait) { if (standardOrientationPortrait) { ui_inspector->topUp->setIcon(QIcon(":/ui/icons/topup.png")); ui_inspector->topDown->setIcon(QIcon(":/ui/icons/topdown.png")); ui_inspector->leftUp->setIcon(QIcon(":/ui/icons/leftup.png")); ui_inspector->rightUp->setIcon(QIcon(":/ui/icons/rightup.png")); } else { ui_inspector->topUp->setIcon(QIcon(":/ui/icons/topup_landscape.png")); ui_inspector->topDown->setIcon(QIcon(":/ui/icons/topdown_landscape.png")); ui_inspector->leftUp->setIcon(QIcon(":/ui/icons/leftup_landscape.png")); ui_inspector->rightUp->setIcon(QIcon(":/ui/icons/rightup_landscape.png")); } } void ConfigurationWidget::updateOrientationButtons(const DeviceData &data) { const bool rotateScreen = ui_inspector->rotateScreen->isChecked(); // workaround for calling this from another thread (scripts): // always perform the setEnabled calls in the gui thread - // setEnabled calls sendEvent! QMetaObject::invokeMethod(this, "enableRotationButtons", Qt::QueuedConnection, Q_ARG(bool, rotateScreen), Q_ARG(int, data.supportedOrientations)); if (!mOrientationButtons->checkedButton()->isEnabled() && !data.menus.isEmpty()) { Orientation fallback = data.menus.begin().key(); if (data.supportedOrientations & fallback) mOrientationButtons->button(fallback)->click(); } } void ConfigurationWidget::rotateScreenToggled() { updateOrientationButtons(deviceList.at(currentDeviceIndex())); emit orientationChangeRequested(static_cast(mOrientationButtons->checkedId()), ui_inspector->rotateScreen->isChecked()); } void ConfigurationWidget::initializeSelection() { if (deviceList.count() == 0) return; ui_inspector->deviceListView->setCurrentIndex(0); changeDeviceSelection(0); } void ConfigurationWidget::changeScaleFactor(int sliderPosition) { int index = currentDeviceIndex(); if (index < 0 || index >= deviceList.size()) return; const DeviceData &data = deviceList.at(index); qreal pixelDiagonal = sqrt(pow((qreal)data.resolution.width(), 2) + pow((qreal)data.resolution.height(), 2)); qreal displayWidthInInch = data.diagonalInInch / pixelDiagonal * data.resolution.width(); qreal minimalScale = mLogicalDpi.width() * displayWidthInInch / data.resolution.width() * mCorrectionFactor; emit scaleFactorChanged((minimalScale + qreal(sliderPosition) / 100. * (1. - minimalScale))); } void ConfigurationWidget::changeCorrectionFactor(qreal newFactor) { mCorrectionFactor = newFactor; changeScaleFactor(ui_inspector->scaleSlider->value()); } void ConfigurationWidget::closeEvent(QCloseEvent *event) { event->ignore(); emit closeMainWindow(); } void ConfigurationWidget::writeSettings(const QString &vendor, const QString &name) const { RemoteControlWidget::writeSettings(vendor, name); QSettings settings(vendor, name); settings.beginGroup("ConfigurationWidget"); settings.setValue("scale", ui_inspector->scaleSlider->value()); settings.setValue("corrfactor", mCorrectionFactor); settings.setValue("viewPageVisible", mViewPage->isContentVisible()); settings.setValue("appPageVisible", mAppPage->isContentVisible()); settings.setValue("rotateScreen", ui_inspector->rotateScreen->isChecked()); int index = currentDeviceIndex(); if (index >= 0 && index < deviceList.size()) settings.setValue("device", deviceList.at(index).name); settings.endGroup(); } void ConfigurationWidget::readSettings(const QString &vendor, const QString &name) { RemoteControlWidget::readSettings(vendor, name); QSettings settings(vendor, name); settings.beginGroup("ConfigurationWidget"); bool deviceFound = false; if (settings.contains("device")) { QString deviceName = settings.value("device").toString(); for (int i = 0; i < deviceList.size(); ++i) { if (deviceList.at(i).name == deviceName) { ui_inspector->deviceListView->setCurrentIndex(i); changeDeviceSelection(i); deviceFound = true; break; } } } if (!deviceFound) initializeSelection(); if (settings.contains("scale")) ui_inspector->scaleSlider->setValue(settings.value("scale").toInt()); if (settings.contains("corrfactor")) { changeCorrectionFactor(settings.value("corrfactor").toDouble()); } if (settings.contains("viewPageVisible")) { bool viewPageVisible = settings.value("viewPageVisible").toBool(); if (viewPageVisible) mViewPage->showContent(); else mViewPage->hideContent(); } if (settings.contains("appPageVisible")) { bool appPageVisible = settings.value("appPageVisible").toBool(); if (appPageVisible) mAppPage->showContent(); else mAppPage->hideContent(); } if (settings.contains("rotateScreen")) ui_inspector->rotateScreen->setChecked(settings.value("rotateScreen").toBool()); settings.endGroup(); } void ConfigurationWidget::showViewConfiguration() { if (!mViewConfiguration) { mViewConfiguration = new ViewConfiguration(mCorrectionFactor, this); connect(mViewConfiguration, SIGNAL(correctionFactorChanged(qreal)), SLOT(changeCorrectionFactor(qreal))); } mViewConfiguration->exec(); } void ConfigurationWidget::changeOrientation(int orientation) { emit orientationChangeRequested(static_cast(orientation), ui_inspector->rotateScreen->isChecked()); } bool ConfigurationWidget::initializeDeviceList() { QDir modelsDir("models"); if (!modelsDir.exists()) { QMessageBox errorMsg; errorMsg.setWindowTitle(tr("Folder does not exist")); errorMsg.setText(tr("The \"%1\" folder could not be located in the installation directory.").arg(modelsDir.dirName())); errorMsg.setIcon(QMessageBox::Critical); errorMsg.exec(); return false; } ConfigurationReader confReader; deviceList.clear(); bool noErrors = confReader.processDir(&modelsDir, deviceList); if (!noErrors && !deviceList.isEmpty()) { QMessageBox msgbox; msgbox.setWindowTitle(tr("Errors occurred while reading device configurations")); msgbox.setText(confReader.errorMessageLines()); msgbox.setIcon(QMessageBox::Critical); msgbox.exec(); } if (deviceList.isEmpty()) { QMessageBox errorMsg; errorMsg.setWindowTitle(tr("Devices could not be found")); QString msg; if (!noErrors) { msg = confReader.errorMessageLines(); } msg += tr("No valid device configuration files (.config) could be found in the \"%1\" folder.").arg(modelsDir.dirName()); errorMsg.setText(msg); errorMsg.setIcon(QMessageBox::Critical); errorMsg.exec(); return false; } foreach (const DeviceData &data, deviceList) ui_inspector->deviceListView->addItem(data.name); return true; } SimulatorScriptInterface *ConfigurationWidget::scriptInterface() { return mScriptInterface; } SimulatorScriptInterface::SimulatorScriptInterface(ConfigurationWidget *ui) : QObject(ui), ui(ui) { int enumIndex = metaObject()->indexOfEnumerator("Orientation"); QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); for (int i = 0; i < metaEnum.keyCount(); ++i) setProperty(metaEnum.key(i), metaEnum.key(i)); } SimulatorScriptInterface::~SimulatorScriptInterface() { } /*! \class SimulatorScriptInterface \brief Exposed as simulator. */ /*! \property SimulatorScriptInterface::zoom \brief the device scaling The value can be between between 0 for real-world size and 100 for pixel equivalence. */ int SimulatorScriptInterface::zoom() const { return ui->ui_inspector->scaleSlider->value(); } void SimulatorScriptInterface::setZoom(int z) { if (z < 0) z = 0; else if (z > 100) z = 100; ui->ui_inspector->scaleSlider->setValue(z); } /*! Returns the index of the current device. \sa setDevice(), deviceCount() */ int SimulatorScriptInterface::currentDeviceIndex() const { return ui->currentDeviceIndex(); } /*! Returns the name of the current device. \sa setDevice() */ QString SimulatorScriptInterface::currentDeviceName() const { return ui->currentDeviceName(); } /*! Returns the number of available device models. \sa setDevice(), currentDeviceIndex() */ int SimulatorScriptInterface::deviceCount() const { return ui->deviceList.size(); } /*! Sets the current device to the one with \a index. \sa deviceCount(), currentDeviceIndex() */ void SimulatorScriptInterface::setDevice(int index) { ui->changeDeviceSelection(index); } /*! Sets the current device to be the one identified by \a dev. \sa currentDeviceName() */ void SimulatorScriptInterface::setDevice(const QString &dev) { const QList &devices = ui->deviceList; for (int i = 0; i < devices.size(); ++i) { if (devices.at(i).name == dev) { ui->changeDeviceSelection(i); break; } } } /*! Rotates the current device, and - optionally - the screen. Returns true on success. */ bool SimulatorScriptInterface::setDeviceOrientation(QString newOrientation, bool rotateScreen) { const int enumIndex = metaObject()->indexOfEnumerator("Orientation"); const QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); int orientation = metaEnum.keyToValue(newOrientation.toLatin1()); if (QAbstractButton *button = ui->mOrientationButtons->button(orientation)) { ui->ui_inspector->rotateScreen->setChecked(rotateScreen); if (!button->isEnabled()) return false; button->click(); return true; } return false; } /*! Returns the current device orientation. */ QString SimulatorScriptInterface::deviceOrientation() const { const int enumIndex = metaObject()->indexOfEnumerator("Orientation"); const QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); return metaEnum.valueToKey(ui->mDeviceItem->deviceOrientation()); } /*! Returns the current screen orientation. */ QString SimulatorScriptInterface::screenOrientation() const { const int enumIndex = metaObject()->indexOfEnumerator("Orientation"); const QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); return metaEnum.valueToKey(ui->mDeviceItem->screenOrientation()); } /*! Returns the list of screen orientations. */ QStringList SimulatorScriptInterface::supportedScreenOrientations() const { const int enumIndex = metaObject()->indexOfEnumerator("Orientation"); const QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); QStringList ret; foreach (::Orientation o, ui->mDeviceItem->supportedScreenOrientations()) ret.append(metaEnum.valueToKey(o)); return ret; } void ConfigurationWidget::enableRotationButtons(bool rotateScreen, int supportedOrientations) { if (!rotateScreen) { ui_inspector->topUp->setEnabled(true); ui_inspector->leftUp->setEnabled(true); ui_inspector->rightUp->setEnabled(true); ui_inspector->topDown->setEnabled(true); } else { ui_inspector->topUp->setEnabled(supportedOrientations & topUp); ui_inspector->leftUp->setEnabled(supportedOrientations & leftUp); ui_inspector->rightUp->setEnabled(supportedOrientations & rightUp); ui_inspector->topDown->setEnabled(supportedOrientations & topDown); } }