<commit_before>#include <QSettings>

#include "QGCSettingsWidget.h"
#include "MainWindow.h"
#include "ui_QGCSettingsWidget.h"

#include "LinkManager.h"
#include "MAVLinkProtocol.h"
#include "MAVLinkSettingsWidget.h"
#include "GAudioOutput.h"

//, Qt::WindowFlags flags

QGCSettingsWidget::QGCSettingsWidget(QWidget *parent, Qt::WindowFlags flags) :
    QDialog(parent, flags),
    mainWindow((MainWindow*)parent),
    ui(new Ui::QGCSettingsWidget)
{
    ui->setupUi(this);

    // Center the window on the screen.
    QRect position = frameGeometry();
    position.moveCenter(QDesktopWidget().availableGeometry().center());
    move(position.topLeft());

    // Add all protocols
    QList<ProtocolInterface*> protocols = LinkManager::instance()->getProtocols();
    foreach (ProtocolInterface* protocol, protocols) {
        MAVLinkProtocol* mavlink = dynamic_cast<MAVLinkProtocol*>(protocol);
        if (mavlink) {
            MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(mavlink, this);
            ui->tabWidget->addTab(msettings, "MAVLink");
        }
    }

    this->window()->setWindowTitle(tr("QGroundControl Settings"));

    // Settings reset
    connect(ui->resetSettingsButton, SIGNAL(clicked()), this, SLOT(resetSettings()));

    // Audio preferences
    ui->audioMuteCheckBox->setChecked(GAudioOutput::instance()->isMuted());
    connect(ui->audioMuteCheckBox, SIGNAL(toggled(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui->audioMuteCheckBox, SLOT(setChecked(bool)));

    // Reconnect
    ui->reconnectCheckBox->setChecked(mainWindow->autoReconnectEnabled());
    connect(ui->reconnectCheckBox, SIGNAL(clicked(bool)), mainWindow, SLOT(enableAutoReconnect(bool)));

    // Low power mode
    ui->lowPowerCheckBox->setChecked(mainWindow->lowPowerModeEnabled());
    connect(ui->lowPowerCheckBox, SIGNAL(clicked(bool)), mainWindow, SLOT(enableLowPowerMode(bool)));

    // Dock widget title bars
    ui->titleBarCheckBox->setChecked(mainWindow->dockWidgetTitleBarsEnabled());
    connect(ui->titleBarCheckBox,SIGNAL(clicked(bool)),mainWindow,SLOT(enableDockWidgetTitleBars(bool)));

    // Custom mode

    ui->customModeComboBox->addItem(tr("Default: Generic MAVLink and serial links"), MainWindow::CUSTOM_MODE_NONE);
    ui->customModeComboBox->addItem(tr("Wifi: Generic MAVLink, wifi or serial links"), MainWindow::CUSTOM_MODE_WIFI);
    ui->customModeComboBox->addItem(tr("PX4: Optimized for PX4 Autopilot Users"), MainWindow::CUSTOM_MODE_PX4);
    ui->customModeComboBox->addItem(tr("APM: Optimized for ArduPilot Users"), MainWindow::CUSTOM_MODE_APM);

    ui->customModeComboBox->setCurrentIndex(ui->customModeComboBox->findData(mainWindow->getCustomMode()));
    connect(ui->customModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectCustomMode(int)));

    // Intialize the style UI to the proper values obtained from the MainWindow.
    MainWindow::QGC_MAINWINDOW_STYLE style = mainWindow->getStyle();
    ui->styleChooser->setCurrentIndex(style);
    if (style == MainWindow::QGC_MAINWINDOW_STYLE_DARK)
    {
        ui->styleSheetFile->setText(mainWindow->getDarkStyleSheet());
    }
    else
    {
        ui->styleSheetFile->setText(mainWindow->getLightStyleSheet());
    }

    // And then connect all the signals for the UI for changing styles.
    connect(ui->styleChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged(int)));
    connect(ui->styleCustomButton, SIGNAL(clicked()), this, SLOT(selectStylesheet()));
    connect(ui->styleDefaultButton, SIGNAL(clicked()), this, SLOT(setDefaultStyle()));
    connect(ui->styleSheetFile, SIGNAL(editingFinished()), this, SLOT(lineEditFinished()));

    // Close / destroy
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(deleteLater()));
}

QGCSettingsWidget::~QGCSettingsWidget()
{
    delete ui;
}

void QGCSettingsWidget::selectStylesheet()
{
    // Let user select style sheet. The root directory for the file picker is the user's home directory if they haven't loaded a custom style.
    // Otherwise it defaults to the directory of that custom file.
    QString findDir;
    QString oldStylesheet(ui->styleSheetFile->text());
    QFile styleSheet(oldStylesheet);
    if (styleSheet.exists() && oldStylesheet[0] != ':')
    {
        findDir = styleSheet.fileName();
    }
    else
    {
        findDir = QDir::homePath();
    }

    // Prompt the user to select a new style sheet. Do nothing if they cancel.
    QString newStyleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), findDir, tr("CSS Stylesheet (*.css);;"));
    if (newStyleFileName.isNull()) {
        return;
    }

    // Load the new style sheet if a valid one was selected, notifying the user
    // of an error if necessary.
    QFile newStyleFile(newStyleFileName);
    if (!newStyleFile.exists() || !updateStyle(newStyleFileName))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did not load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(newStyleFileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
    // And update the UI as needed.
    else
    {
        ui->styleSheetFile->setText(newStyleFileName);
    }
}

bool QGCSettingsWidget::updateStyle(QString style)
{
    switch (ui->styleChooser->currentIndex())
    {
    case 0:
        return mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, style);
    case 1:
        return mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, style);
    default:
        return false;
    }
}

void QGCSettingsWidget::lineEditFinished()
{
    QString newStyleFileName(ui->styleSheetFile->text());
    QFile newStyleFile(newStyleFileName);
    if (!newStyleFile.exists() || !updateStyle(newStyleFileName))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did not load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(newStyleFileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}

void QGCSettingsWidget::styleChanged(int index)
{
    if (index == 1)
    {
        ui->styleSheetFile->setText(mainWindow->getLightStyleSheet());
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, mainWindow->getLightStyleSheet());
    }
    else
    {
        ui->styleSheetFile->setText(mainWindow->getDarkStyleSheet());
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, mainWindow->getDarkStyleSheet());
    }
}

void QGCSettingsWidget::setDefaultStyle()
{
    if (ui->styleChooser->currentIndex() == 1)
    {
        ui->styleSheetFile->setText(MainWindow::defaultLightStyle);
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, MainWindow::defaultLightStyle);
    }
    else
    {
        ui->styleSheetFile->setText(MainWindow::defaultDarkStyle);
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, MainWindow::defaultDarkStyle);
    }
}

void QGCSettingsWidget::selectCustomMode(int mode)
{
    MainWindow::instance()->setCustomMode(static_cast<enum MainWindow::CUSTOM_MODE>(ui->customModeComboBox->itemData(mode).toInt()));
    MainWindow::instance()->showInfoMessage(tr("Please restart QGroundControl"), tr("The optimization selection was changed. The application needs to be closed and restarted to put all optimizations into effect."));
}

void QGCSettingsWidget::resetSettings()
{
    QSettings settings;
    settings.sync();
    settings.clear();
    // Write current application version
    settings.setValue("QGC_APPLICATION_VERSION", QGC_APPLICATION_VERSION);
    settings.sync();
}
<commit_msg>QDesktopWidget() doesn't work in Qt5, use QApplication::desktop() instead.<commit_after>#include <QSettings>

#include "QGCSettingsWidget.h"
#include "MainWindow.h"
#include "ui_QGCSettingsWidget.h"

#include "LinkManager.h"
#include "MAVLinkProtocol.h"
#include "MAVLinkSettingsWidget.h"
#include "GAudioOutput.h"

//, Qt::WindowFlags flags

QGCSettingsWidget::QGCSettingsWidget(QWidget *parent, Qt::WindowFlags flags) :
    QDialog(parent, flags),
    mainWindow((MainWindow*)parent),
    ui(new Ui::QGCSettingsWidget)
{
    ui->setupUi(this);

    // Center the window on the screen.
    QRect position = frameGeometry();
    position.moveCenter(QApplication::desktop()->availableGeometry().center());
    move(position.topLeft());

    // Add all protocols
    QList<ProtocolInterface*> protocols = LinkManager::instance()->getProtocols();
    foreach (ProtocolInterface* protocol, protocols) {
        MAVLinkProtocol* mavlink = dynamic_cast<MAVLinkProtocol*>(protocol);
        if (mavlink) {
            MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(mavlink, this);
            ui->tabWidget->addTab(msettings, "MAVLink");
        }
    }

    this->window()->setWindowTitle(tr("QGroundControl Settings"));

    // Settings reset
    connect(ui->resetSettingsButton, SIGNAL(clicked()), this, SLOT(resetSettings()));

    // Audio preferences
    ui->audioMuteCheckBox->setChecked(GAudioOutput::instance()->isMuted());
    connect(ui->audioMuteCheckBox, SIGNAL(toggled(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui->audioMuteCheckBox, SLOT(setChecked(bool)));

    // Reconnect
    ui->reconnectCheckBox->setChecked(mainWindow->autoReconnectEnabled());
    connect(ui->reconnectCheckBox, SIGNAL(clicked(bool)), mainWindow, SLOT(enableAutoReconnect(bool)));

    // Low power mode
    ui->lowPowerCheckBox->setChecked(mainWindow->lowPowerModeEnabled());
    connect(ui->lowPowerCheckBox, SIGNAL(clicked(bool)), mainWindow, SLOT(enableLowPowerMode(bool)));

    // Dock widget title bars
    ui->titleBarCheckBox->setChecked(mainWindow->dockWidgetTitleBarsEnabled());
    connect(ui->titleBarCheckBox,SIGNAL(clicked(bool)),mainWindow,SLOT(enableDockWidgetTitleBars(bool)));

    // Custom mode

    ui->customModeComboBox->addItem(tr("Default: Generic MAVLink and serial links"), MainWindow::CUSTOM_MODE_NONE);
    ui->customModeComboBox->addItem(tr("Wifi: Generic MAVLink, wifi or serial links"), MainWindow::CUSTOM_MODE_WIFI);
    ui->customModeComboBox->addItem(tr("PX4: Optimized for PX4 Autopilot Users"), MainWindow::CUSTOM_MODE_PX4);
    ui->customModeComboBox->addItem(tr("APM: Optimized for ArduPilot Users"), MainWindow::CUSTOM_MODE_APM);

    ui->customModeComboBox->setCurrentIndex(ui->customModeComboBox->findData(mainWindow->getCustomMode()));
    connect(ui->customModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectCustomMode(int)));

    // Intialize the style UI to the proper values obtained from the MainWindow.
    MainWindow::QGC_MAINWINDOW_STYLE style = mainWindow->getStyle();
    ui->styleChooser->setCurrentIndex(style);
    if (style == MainWindow::QGC_MAINWINDOW_STYLE_DARK)
    {
        ui->styleSheetFile->setText(mainWindow->getDarkStyleSheet());
    }
    else
    {
        ui->styleSheetFile->setText(mainWindow->getLightStyleSheet());
    }

    // And then connect all the signals for the UI for changing styles.
    connect(ui->styleChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged(int)));
    connect(ui->styleCustomButton, SIGNAL(clicked()), this, SLOT(selectStylesheet()));
    connect(ui->styleDefaultButton, SIGNAL(clicked()), this, SLOT(setDefaultStyle()));
    connect(ui->styleSheetFile, SIGNAL(editingFinished()), this, SLOT(lineEditFinished()));

    // Close / destroy
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(deleteLater()));
}

QGCSettingsWidget::~QGCSettingsWidget()
{
    delete ui;
}

void QGCSettingsWidget::selectStylesheet()
{
    // Let user select style sheet. The root directory for the file picker is the user's home directory if they haven't loaded a custom style.
    // Otherwise it defaults to the directory of that custom file.
    QString findDir;
    QString oldStylesheet(ui->styleSheetFile->text());
    QFile styleSheet(oldStylesheet);
    if (styleSheet.exists() && oldStylesheet[0] != ':')
    {
        findDir = styleSheet.fileName();
    }
    else
    {
        findDir = QDir::homePath();
    }

    // Prompt the user to select a new style sheet. Do nothing if they cancel.
    QString newStyleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), findDir, tr("CSS Stylesheet (*.css);;"));
    if (newStyleFileName.isNull()) {
        return;
    }

    // Load the new style sheet if a valid one was selected, notifying the user
    // of an error if necessary.
    QFile newStyleFile(newStyleFileName);
    if (!newStyleFile.exists() || !updateStyle(newStyleFileName))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did not load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(newStyleFileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
    // And update the UI as needed.
    else
    {
        ui->styleSheetFile->setText(newStyleFileName);
    }
}

bool QGCSettingsWidget::updateStyle(QString style)
{
    switch (ui->styleChooser->currentIndex())
    {
    case 0:
        return mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, style);
    case 1:
        return mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, style);
    default:
        return false;
    }
}

void QGCSettingsWidget::lineEditFinished()
{
    QString newStyleFileName(ui->styleSheetFile->text());
    QFile newStyleFile(newStyleFileName);
    if (!newStyleFile.exists() || !updateStyle(newStyleFileName))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did not load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(newStyleFileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}

void QGCSettingsWidget::styleChanged(int index)
{
    if (index == 1)
    {
        ui->styleSheetFile->setText(mainWindow->getLightStyleSheet());
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, mainWindow->getLightStyleSheet());
    }
    else
    {
        ui->styleSheetFile->setText(mainWindow->getDarkStyleSheet());
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, mainWindow->getDarkStyleSheet());
    }
}

void QGCSettingsWidget::setDefaultStyle()
{
    if (ui->styleChooser->currentIndex() == 1)
    {
        ui->styleSheetFile->setText(MainWindow::defaultLightStyle);
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_LIGHT, MainWindow::defaultLightStyle);
    }
    else
    {
        ui->styleSheetFile->setText(MainWindow::defaultDarkStyle);
        mainWindow->loadStyle(MainWindow::QGC_MAINWINDOW_STYLE_DARK, MainWindow::defaultDarkStyle);
    }
}

void QGCSettingsWidget::selectCustomMode(int mode)
{
    MainWindow::instance()->setCustomMode(static_cast<enum MainWindow::CUSTOM_MODE>(ui->customModeComboBox->itemData(mode).toInt()));
    MainWindow::instance()->showInfoMessage(tr("Please restart QGroundControl"), tr("The optimization selection was changed. The application needs to be closed and restarted to put all optimizations into effect."));
}

void QGCSettingsWidget::resetSettings()
{
    QSettings settings;
    settings.sync();
    settings.clear();
    // Write current application version
    settings.setValue("QGC_APPLICATION_VERSION", QGC_APPLICATION_VERSION);
    settings.sync();
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

/* CrystalGenerator.C
*  2012 Stefan Nickels
*/

// ----------------------------------------------------
// $Maintainer: Stefan Nickels $
// $Authors:    Stefan Nickels $
// ----------------------------------------------------

#include <BALL/XRAY/crystalGenerator.h>
#include <BALL/XRAY/crystalInfo.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/FORMAT/commandlineParser.h>
#include <BALL/FORMAT/parameters.h>
#include <BALL/FORMAT/parameterSection.h>
#include <BALL/SYSTEM/path.h>

#include "version.h"

using namespace std;
using namespace BALL;

int main(int argc, char* argv[])
{
	// instantiate CommandlineParser object supplying
	// - tool name
	// - short description
	// - version string
	// - build date
	// - category
	CommandlineParser parpars("X-Ray CrystalGenerator", "creates crystals", "VERSION", String(__DATE__), "Structure Creation");

  parpars.registerParameter("i",  "input pdb file",    INFILE,  true);
	parpars.registerParameter("o",  "output pdb file",   OUTFILE, true);

  // the space group
	parpars.registerParameter("sg", "space group symbol in Herman-Mauguin notation", STRING, true);

	CrystalGenerator generator;

	// Fill the space group symbol list
	generator.getSpaceGroupFilename();
	Path path;
	String filename = generator.getSpaceGroupFilename();
	String filepath = path.find(filename);
	if (filepath == "")
	{
			throw Exception::FileNotFound(__FILE__, __LINE__, filename);
	}

	Parameters* param = new Parameters(filepath);
	if (!param->isValid()) return false;

	ParameterSection* pms = new ParameterSection();
	pms->extractSection(*param, "SpacegroupList");
	if (!pms->isValid()) return false;

	delete param;

	list<String> space_groups;
	for (Position i = 0; i < pms->getNumberOfKeys(); i++)
	{
		space_groups.push_back(pms->getValue(i,0).c_str());
	}

	delete pms;

	parpars.setParameterRestrictions("sg", space_groups);

  // the cell axes
  parpars.registerParameter("axis_a", "cell axis a", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_a", 0, 100);
	parpars.registerParameter("axis_b", "cell axis b", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_b", 0, 100);
	parpars.registerParameter("axis_c", "cell axis c", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_c", 0, 100);

  // the cell angles
	parpars.registerParameter("angle_alpha", "cell angle alpha", DOUBLE, false);
	parpars.setParameterRestrictions("angle_alpha", 0., 359.);
	parpars.registerParameter("angle_beta", "cell angle beta", DOUBLE, false);
	parpars.setParameterRestrictions("angle_beta", 0., 359.);
	parpars.registerParameter("angle_gamma", "cell angle gamma", DOUBLE, false);
	parpars.setParameterRestrictions("angle_gamma", 0., 359.);

  // the unit cell indices to create
  parpars.registerParameter("from_uc_a", "from unit cell index a", INT, true);
	parpars.setParameterRestrictions("from_uc_a", 0, 9);
	parpars.registerParameter("from_uc_b", "from unit cell index b", INT, true);
	parpars.setParameterRestrictions("from_uc_b", 0, 9);
	parpars.registerParameter("from_uc_c", "from unit cell index c", INT, true);
	parpars.setParameterRestrictions("from_uc_c", 0, 9);
	parpars.registerParameter("to_uc_a", "to unit cell index a", INT, true);
	parpars.setParameterRestrictions("from_uc_a", 0, 9);
	parpars.registerParameter("to_uc_b", "to unit cell index b", INT, true);
	parpars.setParameterRestrictions("from_uc_b", 0, 9);
	parpars.registerParameter("to_uc_c", "to unit cell index c", INT, true);
	parpars.setParameterRestrictions("from_uc_c", 0, 9);

  String man = "TODO: Manual";
	parpars.setToolManual(man);

  parpars.setSupportedFormats("i","pdb");
  parpars.setSupportedFormats("o","pdb");

	parpars.parse(argc, argv);

  PDBFile file;
  file.open(parpars.get("i"));
  System system;
  file >> system;

  generator.setSystem(&system);

  boost::shared_ptr<CrystalInfo> ci_ptr(new CrystalInfo());
  ci_ptr->setSpaceGroup(parpars.get("sg"));
	ci_ptr->setCellEdgeLengthA(parpars.get("axis_a").toDouble());
	ci_ptr->setCellEdgeLengthB(parpars.get("axis_b").toDouble());
	ci_ptr->setCellEdgeLengthC(parpars.get("axis_c").toDouble());
	ci_ptr->setCellAngleAlpha(Angle(parpars.get("angle_alpha").toDouble(), false));
	ci_ptr->setCellAngleBeta(Angle(parpars.get("angle_beta").toDouble(), false));

  ci_ptr->setCellAngleGamma(Angle(parpars.get("angle_gamma").toDouble(), false));

	generator.setCrystalInfo(ci_ptr);

	System* output = 0;
	std::list<System*> crystal = generator.generatePacking(parpars.get("from_uc_a").toInt(), parpars.get("to_uc_a").toInt(),
																												 parpars.get("from_uc_b").toInt(), parpars.get("to_uc_b").toInt(),
																												 parpars.get("from_uc_c").toInt(), parpars.get("to_uc_c").toInt());
	output = new System();
	output->setName(system.getName());
	std::list<System*>::iterator it_c = crystal.begin();

	for(;it_c != crystal.end(); it_c++)
	{
		output->spliceAfter(**it_c);
	}

	PDBFile outfile(parpars.get("o"), ios::out);
	outfile << *output;
	outfile.close();

	Log << "seems to be done." << endl;

}

<commit_msg>Fixed CrystalGenerator tool for Galaxy<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

/* CrystalGenerator.C
*  2012 Stefan Nickels
*/

// ----------------------------------------------------
// $Maintainer: Stefan Nickels $
// $Authors:    Stefan Nickels $
// ----------------------------------------------------

#include <BALL/XRAY/crystalGenerator.h>
#include <BALL/XRAY/crystalInfo.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/FORMAT/commandlineParser.h>
#include <BALL/FORMAT/parameters.h>
#include <BALL/FORMAT/parameterSection.h>
#include <BALL/SYSTEM/path.h>

#include "version.h"

using namespace std;
using namespace BALL;

int main(int argc, char* argv[])
{
	// instantiate CommandlineParser object supplying
	// - tool name
	// - short description
	// - version string
	// - build date
	// - category
	CommandlineParser parpars("CrystalGenerator", "creates crystals", "VERSION", String(__DATE__), "Structure Creation");

  parpars.registerParameter("i",  "input pdb file",    INFILE,  true);
	parpars.registerParameter("o",  "output pdb file",   OUTFILE, true);

  // the space group
	parpars.registerParameter("sg", "space group symbol in Herman-Mauguin notation", STRING, true);

	CrystalGenerator generator;

	// Fill the space group symbol list
	generator.getSpaceGroupFilename();
	Path path;
	String filename = generator.getSpaceGroupFilename();
	String filepath = path.find(filename);
	if (filepath == "")
	{
			throw Exception::FileNotFound(__FILE__, __LINE__, filename);
	}

	Parameters* param = new Parameters(filepath);
	if (!param->isValid()) return false;

	ParameterSection* pms = new ParameterSection();
	pms->extractSection(*param, "SpacegroupList");
	if (!pms->isValid()) return false;

	delete param;

	list<String> space_groups;
	for (Position i = 0; i < pms->getNumberOfKeys(); i++)
	{
		space_groups.push_back(pms->getValue(i,0).c_str());
	}

	delete pms;

	parpars.setParameterRestrictions("sg", space_groups);

  // the cell axes
  parpars.registerParameter("axis_a", "cell axis a", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_a", 0, 100);
	parpars.registerParameter("axis_b", "cell axis b", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_b", 0, 100);
	parpars.registerParameter("axis_c", "cell axis c", DOUBLE, false);
	//parpars.setParameterRestrictions("axis_c", 0, 100);

  // the cell angles
	parpars.registerParameter("angle_alpha", "cell angle alpha", DOUBLE, false);
	parpars.setParameterRestrictions("angle_alpha", 0., 359.);
	parpars.registerParameter("angle_beta", "cell angle beta", DOUBLE, false);
	parpars.setParameterRestrictions("angle_beta", 0., 359.);
	parpars.registerParameter("angle_gamma", "cell angle gamma", DOUBLE, false);
	parpars.setParameterRestrictions("angle_gamma", 0., 359.);

  // the unit cell indices to create
  parpars.registerParameter("from_uc_a", "from unit cell index a", INT, true);
	parpars.setParameterRestrictions("from_uc_a", 0, 9);
	parpars.registerParameter("from_uc_b", "from unit cell index b", INT, true);
	parpars.setParameterRestrictions("from_uc_b", 0, 9);
	parpars.registerParameter("from_uc_c", "from unit cell index c", INT, true);
	parpars.setParameterRestrictions("from_uc_c", 0, 9);
	parpars.registerParameter("to_uc_a", "to unit cell index a", INT, true);
	parpars.setParameterRestrictions("from_uc_a", 0, 9);
	parpars.registerParameter("to_uc_b", "to unit cell index b", INT, true);
	parpars.setParameterRestrictions("from_uc_b", 0, 9);
	parpars.registerParameter("to_uc_c", "to unit cell index c", INT, true);
	parpars.setParameterRestrictions("from_uc_c", 0, 9);

  String man = "TODO: Manual";
	parpars.setToolManual(man);

  parpars.setSupportedFormats("i","pdb");
  parpars.setSupportedFormats("o","pdb");

	parpars.parse(argc, argv);

  PDBFile file;
  file.open(parpars.get("i"));
  System system;
  file >> system;

  generator.setSystem(&system);

  boost::shared_ptr<CrystalInfo> ci_ptr(new CrystalInfo());
  ci_ptr->setSpaceGroup(parpars.get("sg"));
	ci_ptr->setCellEdgeLengthA(parpars.get("axis_a").toDouble());
	ci_ptr->setCellEdgeLengthB(parpars.get("axis_b").toDouble());
	ci_ptr->setCellEdgeLengthC(parpars.get("axis_c").toDouble());
	ci_ptr->setCellAngleAlpha(Angle(parpars.get("angle_alpha").toDouble(), false));
	ci_ptr->setCellAngleBeta(Angle(parpars.get("angle_beta").toDouble(), false));

  ci_ptr->setCellAngleGamma(Angle(parpars.get("angle_gamma").toDouble(), false));

	generator.setCrystalInfo(ci_ptr);

	System* output = 0;
	std::list<System*> crystal = generator.generatePacking(parpars.get("from_uc_a").toInt(), parpars.get("to_uc_a").toInt(),
																												 parpars.get("from_uc_b").toInt(), parpars.get("to_uc_b").toInt(),
																												 parpars.get("from_uc_c").toInt(), parpars.get("to_uc_c").toInt());
	output = new System();
	output->setName(system.getName());
	std::list<System*>::iterator it_c = crystal.begin();

	for(;it_c != crystal.end(); it_c++)
	{
		output->spliceAfter(**it_c);
	}

	PDBFile outfile(parpars.get("o"), ios::out);
	outfile << *output;
	outfile.close();

	Log << "seems to be done." << endl;

}

<|endoftext|>


<commit_before>/* Copyright © 2001-2015, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "journey_pattern_container.h"
#include "type/pt_data.h"
#include <type_traits>

namespace navitia { namespace routing {

namespace nt = navitia::type;

template<> std::vector<const nt::DiscreteVehicleJourney*>&
JourneyPattern::get_vjs<nt::DiscreteVehicleJourney>() {
    return discrete_vjs;
}
template<> std::vector<const nt::FrequencyVehicleJourney*>&
JourneyPattern::get_vjs<nt::FrequencyVehicleJourney>() {
    return freq_vjs;
}

void JourneyPatternContainer::load(const nt::PT_Data& pt_data) {
    map.clear();
    jps.clear();
    jpps.clear();
    jps_from_route.assign(pt_data.routes);
    jp_from_vj.assign(pt_data.vehicle_journeys);
    for (const auto* jp: pt_data.journey_patterns) {
        for (const auto& vj: jp->discrete_vehicle_journey_list) { add_vj(*vj); }
        for (const auto& vj: jp->frequency_vehicle_journey_list) { add_vj(*vj); }
    }
}

const JppIdx& JourneyPatternContainer::get_jpp(const type::StopTime& st) const {
    const auto& jp = get(jp_from_vj[VjIdx(*st.vehicle_journey)]);
    return jp.jpps.at(st.journey_pattern_point->order);
}

template<typename VJ>
JourneyPatternContainer::JpKey JourneyPatternContainer::make_key(const VJ& vj) {
    JourneyPatternContainer::JpKey key;
    key.route_idx = RouteIdx(*vj.journey_pattern->route);
    key.is_freq = std::is_same<VJ, nt::FrequencyVehicleJourney>::value;
    for (const auto& st: vj.stop_time_list) {
        key.jpp_keys.emplace_back(SpIdx(*st.journey_pattern_point->stop_point),
                                  st.local_traffic_zone,
                                  st.properties);
    }
    return key;
}

static bool st_are_equals(const nt::VehicleJourney& vj1, const nt::VehicleJourney& vj2) {
    for (auto it1 = vj1.stop_time_list.begin(), it2 = vj2.stop_time_list.begin();
         it1 !=  vj1.stop_time_list.end() && it2 !=  vj2.stop_time_list.end();
         ++it1, ++it2) {
        if (it1->arrival_time != it2->arrival_time || it1->departure_time != it2->departure_time) {
            return false;
        }
    }
    return true;
}

template<typename VJ> static bool
overtake(const VJ& vj, const std::vector<const VJ*> vjs) {
    if (vj.stop_time_list.empty()) { return false; }
    for (const VJ* cur_vj: vjs) {
        assert(vj.stop_time_list.size() == cur_vj->stop_time_list.size());

        // if the validity patterns do not overlap, it can't overtake
        if ((vj.validity_pattern->days & cur_vj->validity_pattern->days).none() &&
            (vj.adapted_validity_pattern->days & cur_vj->adapted_validity_pattern->days).none()) {
            continue;
        }

        // if the stop times are the same, they don't overtake
        if (st_are_equals(vj, *cur_vj)) { continue; }

        const bool vj_is_first =
            vj.stop_time_list.front().departure_time < cur_vj->stop_time_list.front().departure_time;
        const VJ& vj1 = vj_is_first ? vj : *cur_vj;
        const VJ& vj2 = vj_is_first ? *cur_vj : vj;
        for (auto it1 = vj1.stop_time_list.begin(), it2 = vj2.stop_time_list.begin();
             it1 !=  vj1.stop_time_list.end() && it2 !=  vj2.stop_time_list.end();
             ++it1, ++it2) {
            if (it1->arrival_time >= it2->arrival_time ||
                it1->departure_time >= it2->departure_time) {
                return true;
            }
        }
    }
    return false;
}

template<typename VJ>
void JourneyPatternContainer::add_vj(const VJ& vj) {
    // Get the existing jps according to the key.
    const auto key = make_key(vj);
    auto& jps = map[key];

    // The vj must not overtake the other vj in its jp, thus searching
    // for one satisfying jp.
    for (auto& jp_idx: jps) {
        auto& jp = get_mut(jp_idx);
        auto& vjs = jp.template get_vjs<VJ>();
        if (! overtake(vj, vjs)) {
            // Great, found a valid jp, inserting and stopping
            vjs.push_back(&vj);
            jp_from_vj[VjIdx(vj)] = jp_idx;
            return;
        }
    }

    // We did not find a jp, creating a new one.
    const auto jp_idx = make_jp(key);
    jps.push_back(jp_idx);
    jps_from_route[key.route_idx].push_back(jp_idx);
    get_mut(jp_idx).template get_vjs<VJ>().push_back(&vj);
    jp_from_vj[VjIdx(vj)] = jp_idx;
}

JpIdx JourneyPatternContainer::make_jp(const JpKey& key) {
    const auto jp_idx = JpIdx(jps.size());
    jps.emplace_back();
    auto& jp = jps.back();
    jp.route_idx = key.route_idx;
    uint16_t order = 0;
    for (const auto& jpp_key: key.jpp_keys) {
        jp.jpps.push_back(make_jpp(jp_idx, jpp_key.sp_idx, order++));
    }
    return jp_idx;
}

JppIdx JourneyPatternContainer::make_jpp(const JpIdx& jp_idx, const SpIdx& sp_idx, uint16_t order) {
    const auto idx = JppIdx(jpps.size());
    jpps.push_back({jp_idx, sp_idx, order});
    return idx;
}

JourneyPattern& JourneyPatternContainer::get_mut(const JpIdx& idx) {
    assert(idx.val < jps.size());
    return jps[idx.val];
}

}}// namespace navitia::routing
<commit_msg>routing: fix after rebase<commit_after>/* Copyright © 2001-2015, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "journey_pattern_container.h"
#include "type/pt_data.h"
#include <type_traits>
#include <boost/algorithm/cxx11/all_of.hpp>

namespace navitia { namespace routing {

namespace nt = navitia::type;

template<> std::vector<const nt::DiscreteVehicleJourney*>&
JourneyPattern::get_vjs<nt::DiscreteVehicleJourney>() {
    return discrete_vjs;
}
template<> std::vector<const nt::FrequencyVehicleJourney*>&
JourneyPattern::get_vjs<nt::FrequencyVehicleJourney>() {
    return freq_vjs;
}

void JourneyPatternContainer::load(const nt::PT_Data& pt_data) {
    map.clear();
    jps.clear();
    jpps.clear();
    jps_from_route.assign(pt_data.routes);
    jp_from_vj.assign(pt_data.vehicle_journeys);
    for (const auto* jp: pt_data.journey_patterns) {
        for (const auto& vj: jp->discrete_vehicle_journey_list) { add_vj(*vj); }
        for (const auto& vj: jp->frequency_vehicle_journey_list) { add_vj(*vj); }
    }
}

const JppIdx& JourneyPatternContainer::get_jpp(const type::StopTime& st) const {
    const auto& jp = get(jp_from_vj[VjIdx(*st.vehicle_journey)]);
    return jp.jpps.at(st.journey_pattern_point->order);
}

template<typename VJ>
JourneyPatternContainer::JpKey JourneyPatternContainer::make_key(const VJ& vj) {
    JourneyPatternContainer::JpKey key;
    key.route_idx = RouteIdx(*vj.journey_pattern->route);
    key.is_freq = std::is_same<VJ, nt::FrequencyVehicleJourney>::value;
    for (const auto& st: vj.stop_time_list) {
        key.jpp_keys.emplace_back(SpIdx(*st.journey_pattern_point->stop_point),
                                  st.local_traffic_zone,
                                  st.properties);
    }
    return key;
}

static bool st_are_equals(const nt::VehicleJourney& vj1, const nt::VehicleJourney& vj2) {
    for (auto it1 = vj1.stop_time_list.begin(), it2 = vj2.stop_time_list.begin();
         it1 !=  vj1.stop_time_list.end() && it2 !=  vj2.stop_time_list.end();
         ++it1, ++it2) {
        if (it1->arrival_time != it2->arrival_time || it1->departure_time != it2->departure_time) {
            return false;
        }
    }
    return true;
}

template<typename VJ> static bool
overtake(const VJ& vj, const std::vector<const VJ*> vjs) {
    if (vj.stop_time_list.empty()) { return false; }
    for (const VJ* cur_vj: vjs) {
        assert(vj.stop_time_list.size() == cur_vj->stop_time_list.size());

        // if the validity patterns do not overlap, it can't overtake
        const auto levels = {nt::RTLevel::Theoric, nt::RTLevel::Adapted, nt::RTLevel::RealTime};
        const bool dont_overlap = boost::algorithm::all_of(levels, [&](nt::RTLevel lvl) {
                if (vj.validity_patterns[lvl] == nullptr) { return true; }
                if (cur_vj->validity_patterns[lvl] == nullptr) { return true; }
                return (vj.validity_patterns[lvl]->days & cur_vj->validity_patterns[lvl]->days).none();
            });
        if (dont_overlap) { continue; }

        // if the stop times are the same, they don't overtake
        if (st_are_equals(vj, *cur_vj)) { continue; }

        const bool vj_is_first =
            vj.stop_time_list.front().departure_time < cur_vj->stop_time_list.front().departure_time;
        const VJ& vj1 = vj_is_first ? vj : *cur_vj;
        const VJ& vj2 = vj_is_first ? *cur_vj : vj;
        for (auto it1 = vj1.stop_time_list.begin(), it2 = vj2.stop_time_list.begin();
             it1 !=  vj1.stop_time_list.end() && it2 !=  vj2.stop_time_list.end();
             ++it1, ++it2) {
            if (it1->arrival_time >= it2->arrival_time ||
                it1->departure_time >= it2->departure_time) {
                return true;
            }
        }
    }
    return false;
}

template<typename VJ>
void JourneyPatternContainer::add_vj(const VJ& vj) {
    // Get the existing jps according to the key.
    const auto key = make_key(vj);
    auto& jps = map[key];

    // The vj must not overtake the other vj in its jp, thus searching
    // for one satisfying jp.
    for (auto& jp_idx: jps) {
        auto& jp = get_mut(jp_idx);
        auto& vjs = jp.template get_vjs<VJ>();
        if (! overtake(vj, vjs)) {
            // Great, found a valid jp, inserting and stopping
            vjs.push_back(&vj);
            jp_from_vj[VjIdx(vj)] = jp_idx;
            return;
        }
    }

    // We did not find a jp, creating a new one.
    const auto jp_idx = make_jp(key);
    jps.push_back(jp_idx);
    jps_from_route[key.route_idx].push_back(jp_idx);
    get_mut(jp_idx).template get_vjs<VJ>().push_back(&vj);
    jp_from_vj[VjIdx(vj)] = jp_idx;
}

JpIdx JourneyPatternContainer::make_jp(const JpKey& key) {
    const auto jp_idx = JpIdx(jps.size());
    jps.emplace_back();
    auto& jp = jps.back();
    jp.route_idx = key.route_idx;
    uint16_t order = 0;
    for (const auto& jpp_key: key.jpp_keys) {
        jp.jpps.push_back(make_jpp(jp_idx, jpp_key.sp_idx, order++));
    }
    return jp_idx;
}

JppIdx JourneyPatternContainer::make_jpp(const JpIdx& jp_idx, const SpIdx& sp_idx, uint16_t order) {
    const auto idx = JppIdx(jpps.size());
    jpps.push_back({jp_idx, sp_idx, order});
    return idx;
}

JourneyPattern& JourneyPatternContainer::get_mut(const JpIdx& idx) {
    assert(idx.val < jps.size());
    return jps[idx.val];
}

}}// namespace navitia::routing
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011-2012 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "edge.h"
#include "edge_exception.h"

#include "stamp.h"
#include "types.h"

#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/weak_ptr.hpp>

#include <queue>

/**
 * \file edge.cxx
 *
 * \brief Implementation of the \link vistk::edge edge\endlink class.
 */

namespace vistk
{

config::key_t const edge::config_dependency = config::key_t("_dependency");
config::key_t const edge::config_capacity = config::key_t("capacity");

class edge::priv
{
  public:
    priv(bool depends_, size_t capacity_);
    ~priv();

    typedef boost::weak_ptr<process> process_ref_t;

    bool has_data() const;
    bool full_of_data() const;
    void complete_check() const;

    bool const depends;
    size_t const capacity;
    bool downstream_complete;

    process_ref_t upstream;
    process_ref_t downstream;

    std::queue<edge_datum_t> q;

    boost::condition_variable cond_have_data;
    boost::condition_variable cond_have_space;

    mutable boost::mutex mutex;
    mutable boost::mutex complete_mutex;
};

edge
::edge(config_t const& config)
{
  if (!config)
  {
    throw null_edge_config_exception();
  }

  bool const depends = config->get_value<bool>(config_dependency, true);
  size_t const capacity = config->get_value<size_t>(config_capacity, 0);

  d.reset(new priv(depends, capacity));
}

edge
::~edge()
{
}

bool
edge
::makes_dependency() const
{
  return d->depends;
}

bool
edge
::has_data() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->has_data();
}

bool
edge
::full_of_data() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->full_of_data();
}

size_t
edge
::datum_count() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->q.size();
}

void
edge
::push_datum(edge_datum_t const& datum)
{
  {
    boost::mutex::scoped_lock const lock(d->complete_mutex);

    (void)lock;

    if (d->downstream_complete)
    {
      return;
    }
  }

  {
    boost::mutex::scoped_lock lock(d->mutex);

    while (d->full_of_data())
    {
      d->cond_have_space.wait(lock);
    }

    d->q.push(datum);
  }

  d->cond_have_data.notify_one();
}

edge_datum_t
edge
::get_datum()
{
  d->complete_check();

  edge_datum_t dat;

  {
    boost::mutex::scoped_lock lock(d->mutex);

    while (!d->has_data())
    {
      d->cond_have_data.wait(lock);
    }

    dat = d->q.front();

    d->q.pop();
  }

  d->cond_have_space.notify_one();

  return dat;
}

edge_datum_t
edge
::peek_datum()
{
  d->complete_check();

  boost::mutex::scoped_lock lock(d->mutex);

  while (!d->has_data())
  {
    d->cond_have_data.wait(lock);
  }

  return d->q.front();
}

void
edge
::pop_datum()
{
  d->complete_check();

  boost::mutex::scoped_lock lock(d->mutex);

  while (!d->has_data())
  {
    d->cond_have_data.wait(lock);
  }

  d->q.pop();

  d->cond_have_space.notify_one();
}

void
edge
::mark_downstream_as_complete()
{
  boost::mutex::scoped_lock complete_lock(d->complete_mutex);

  (void)complete_lock;

  d->downstream_complete = true;

  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  while (d->q.size())
  {
    d->q.pop();
  }
}

bool
edge
::is_downstream_complete() const
{
  boost::mutex::scoped_lock const lock(d->complete_mutex);

  (void)lock;

  return d->downstream_complete;
}

void
edge
::set_upstream_process(process_t process)
{
  if (!process)
  {
    throw null_process_connection_exception();
  }

  if (!d->upstream.expired())
  {
    process_t const up = d->upstream.lock();

    throw input_already_connected_exception(up->name(), process->name());
  }

  d->upstream = process;
}

void
edge
::set_downstream_process(process_t process)
{
  if (!process)
  {
    throw null_process_connection_exception();
  }

  if (!d->downstream.expired())
  {
    process_t const down = d->downstream.lock();

    throw output_already_connected_exception(down->name(), process->name());
  }

  d->downstream = process;
}

bool
operator == (edge_datum_t const& a, edge_datum_t const& b)
{
  return (( a.get<0>() ==  b.get<0>()) &&
          (*a.get<1>() == *b.get<1>()));
}

edge::priv
::priv(bool depends_, size_t capacity_)
  : depends(depends_)
  , capacity(capacity_)
  , downstream_complete(false)
{
}

edge::priv
::~priv()
{
}

bool
edge::priv
::has_data() const
{
  return (q.size() != 0);
}

bool
edge::priv
::full_of_data() const
{
  if (!capacity)
  {
    return false;
  }

  return (q.size() == capacity);
}

void
edge::priv
::complete_check() const
{
  boost::mutex::scoped_lock const lock(complete_mutex);

  (void)lock;

  if (downstream_complete)
  {
    throw datum_requested_after_complete();
  }
}

}
<commit_msg>Narrow the scope of the lock<commit_after>/*ckwg +5
 * Copyright 2011-2012 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "edge.h"
#include "edge_exception.h"

#include "stamp.h"
#include "types.h"

#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/weak_ptr.hpp>

#include <queue>

/**
 * \file edge.cxx
 *
 * \brief Implementation of the \link vistk::edge edge\endlink class.
 */

namespace vistk
{

config::key_t const edge::config_dependency = config::key_t("_dependency");
config::key_t const edge::config_capacity = config::key_t("capacity");

class edge::priv
{
  public:
    priv(bool depends_, size_t capacity_);
    ~priv();

    typedef boost::weak_ptr<process> process_ref_t;

    bool has_data() const;
    bool full_of_data() const;
    void complete_check() const;

    bool const depends;
    size_t const capacity;
    bool downstream_complete;

    process_ref_t upstream;
    process_ref_t downstream;

    std::queue<edge_datum_t> q;

    boost::condition_variable cond_have_data;
    boost::condition_variable cond_have_space;

    mutable boost::mutex mutex;
    mutable boost::mutex complete_mutex;
};

edge
::edge(config_t const& config)
{
  if (!config)
  {
    throw null_edge_config_exception();
  }

  bool const depends = config->get_value<bool>(config_dependency, true);
  size_t const capacity = config->get_value<size_t>(config_capacity, 0);

  d.reset(new priv(depends, capacity));
}

edge
::~edge()
{
}

bool
edge
::makes_dependency() const
{
  return d->depends;
}

bool
edge
::has_data() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->has_data();
}

bool
edge
::full_of_data() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->full_of_data();
}

size_t
edge
::datum_count() const
{
  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  return d->q.size();
}

void
edge
::push_datum(edge_datum_t const& datum)
{
  {
    boost::mutex::scoped_lock const lock(d->complete_mutex);

    (void)lock;

    if (d->downstream_complete)
    {
      return;
    }
  }

  {
    boost::mutex::scoped_lock lock(d->mutex);

    while (d->full_of_data())
    {
      d->cond_have_space.wait(lock);
    }

    d->q.push(datum);
  }

  d->cond_have_data.notify_one();
}

edge_datum_t
edge
::get_datum()
{
  d->complete_check();

  edge_datum_t dat;

  {
    boost::mutex::scoped_lock lock(d->mutex);

    while (!d->has_data())
    {
      d->cond_have_data.wait(lock);
    }

    dat = d->q.front();

    d->q.pop();
  }

  d->cond_have_space.notify_one();

  return dat;
}

edge_datum_t
edge
::peek_datum()
{
  d->complete_check();

  boost::mutex::scoped_lock lock(d->mutex);

  while (!d->has_data())
  {
    d->cond_have_data.wait(lock);
  }

  return d->q.front();
}

void
edge
::pop_datum()
{
  d->complete_check();

  {
    boost::mutex::scoped_lock lock(d->mutex);

    while (!d->has_data())
    {
      d->cond_have_data.wait(lock);
    }

    d->q.pop();
  }

  d->cond_have_space.notify_one();
}

void
edge
::mark_downstream_as_complete()
{
  boost::mutex::scoped_lock complete_lock(d->complete_mutex);

  (void)complete_lock;

  d->downstream_complete = true;

  boost::mutex::scoped_lock const lock(d->mutex);

  (void)lock;

  while (d->q.size())
  {
    d->q.pop();
  }
}

bool
edge
::is_downstream_complete() const
{
  boost::mutex::scoped_lock const lock(d->complete_mutex);

  (void)lock;

  return d->downstream_complete;
}

void
edge
::set_upstream_process(process_t process)
{
  if (!process)
  {
    throw null_process_connection_exception();
  }

  if (!d->upstream.expired())
  {
    process_t const up = d->upstream.lock();

    throw input_already_connected_exception(up->name(), process->name());
  }

  d->upstream = process;
}

void
edge
::set_downstream_process(process_t process)
{
  if (!process)
  {
    throw null_process_connection_exception();
  }

  if (!d->downstream.expired())
  {
    process_t const down = d->downstream.lock();

    throw output_already_connected_exception(down->name(), process->name());
  }

  d->downstream = process;
}

bool
operator == (edge_datum_t const& a, edge_datum_t const& b)
{
  return (( a.get<0>() ==  b.get<0>()) &&
          (*a.get<1>() == *b.get<1>()));
}

edge::priv
::priv(bool depends_, size_t capacity_)
  : depends(depends_)
  , capacity(capacity_)
  , downstream_complete(false)
{
}

edge::priv
::~priv()
{
}

bool
edge::priv
::has_data() const
{
  return (q.size() != 0);
}

bool
edge::priv
::full_of_data() const
{
  if (!capacity)
  {
    return false;
  }

  return (q.size() == capacity);
}

void
edge::priv
::complete_check() const
{
  boost::mutex::scoped_lock const lock(complete_mutex);

  (void)lock;

  if (downstream_complete)
  {
    throw datum_requested_after_complete();
  }
}

}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 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 "s60devicerunconfigurationwidget.h"
#include "s60devicerunconfiguration.h"
#include "s60runconfigbluetoothstarter.h"
#include "bluetoothlistener_gui.h"
#include "s60manager.h"
#include "launcher.h"
#include "bluetoothlistener.h"
#include "bluetoothlistener_gui.h"
#include "serialdevicelister.h"

#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
#include <utils/pathchooser.h>

#include <QtCore/QTimer>
#include <QtGui/QRadioButton>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QComboBox>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QFormLayout>
#include <QtGui/QToolButton>
#include <QtGui/QStyle>
#include <QtGui/QApplication>
#include <QtGui/QSpacerItem>

Q_DECLARE_METATYPE(Qt4ProjectManager::Internal::CommunicationDevice)

namespace Qt4ProjectManager {
namespace Internal {

S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget(
            S60DeviceRunConfiguration *runConfiguration,
            QWidget *parent)
    : QWidget(parent),
    m_runConfiguration(runConfiguration),
    m_detailsWidget(new Utils::DetailsWidget),
    m_serialPortsCombo(new QComboBox),
    m_nameLineEdit(new QLineEdit(m_runConfiguration->name())),
    m_sisxFileLabel(new QLabel(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"))),
    m_deviceInfoButton(new QToolButton),
    m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))),
    m_deviceInfoLabel(new QLabel),
    m_infoTimeOutTimer(0)
{
    QVBoxLayout *mainBoxLayout = new QVBoxLayout();
    mainBoxLayout->setMargin(0);
    setLayout(mainBoxLayout);
    mainBoxLayout->addWidget(m_detailsWidget);
    QWidget *detailsContainer = new QWidget;
    m_detailsWidget->setWidget(detailsContainer);

    QVBoxLayout *detailsBoxLayout = new QVBoxLayout();
    detailsBoxLayout->setMargin(0);
    detailsContainer->setLayout(detailsBoxLayout);

    QFormLayout *formLayout = new QFormLayout();
    formLayout->setMargin(0);
    detailsBoxLayout->addLayout(formLayout);
    // Name control
    QLabel *nameLabel = new QLabel(tr("Name:"));
    nameLabel->setBuddy(m_nameLineEdit);
    formLayout->addRow(nameLabel, m_nameLineEdit);
    formLayout->addRow(tr("Install File:"), m_sisxFileLabel);

    updateSerialDevices();
    connect(S60Manager::instance()->serialDeviceLister(), SIGNAL(updated()),
            this, SLOT(updateSerialDevices()));
    // Serial devices control
    connect(m_serialPortsCombo, SIGNAL(activated(int)), this, SLOT(setSerialPort(int)));
    QHBoxLayout *serialPortHBoxLayout = new QHBoxLayout;
    serialPortHBoxLayout->addWidget(m_serialPortsCombo);
    serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));

    formLayout->addRow(tr("Device on Serial Port:"), serialPortHBoxLayout);

    // Device Info with button. Widgets are enabled in above call to updateSerialDevices()
    QHBoxLayout *infoHBoxLayout = new QHBoxLayout;
    m_deviceInfoLabel->setWordWrap(true);
    infoHBoxLayout->addWidget(m_deviceInfoLabel);
    infoHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
    infoHBoxLayout->addWidget(m_deviceInfoButton);
    m_deviceInfoButton->setIcon(qApp->style()->standardIcon(QStyle::SP_MessageBoxInformation));
    m_deviceInfoButton->setToolTip(tr("Queries the device for information"));
    connect(m_deviceInfoButton, SIGNAL(clicked()), this, SLOT(updateDeviceInfo()));
    formLayout->addRow(m_deviceInfoDescriptionLabel, infoHBoxLayout);

    // Signature/certificate stuff.
    QWidget *signatureWidget = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout();
    signatureWidget->setLayout(layout);
    detailsBoxLayout->addWidget(signatureWidget);
    QRadioButton *selfSign = new QRadioButton(tr("Self-signed certificate"));
    QHBoxLayout *customHBox = new QHBoxLayout();
    customHBox->setMargin(0);
    QVBoxLayout *radioLayout = new QVBoxLayout();
    QRadioButton *customSignature = new QRadioButton();
    radioLayout->addWidget(customSignature);
    radioLayout->addStretch(10);
    customHBox->addLayout(radioLayout);
    QFormLayout *customLayout = new QFormLayout();
    customLayout->setMargin(0);
    customLayout->setLabelAlignment(Qt::AlignRight);
    Utils::PathChooser *signaturePath = new Utils::PathChooser();
    signaturePath->setExpectedKind(Utils::PathChooser::File);
    signaturePath->setPromptDialogTitle(tr("Choose certificate file (.cer)"));
    customLayout->addRow(new QLabel(tr("Custom certificate:")), signaturePath);
    Utils::PathChooser *keyPath = new Utils::PathChooser();
    keyPath->setExpectedKind(Utils::PathChooser::File);
    keyPath->setPromptDialogTitle(tr("Choose key file (.key / .pem)"));
    customLayout->addRow(new QLabel(tr("Key file:")), keyPath);
    customHBox->addLayout(customLayout);
    customHBox->addStretch(10);
    layout->addWidget(selfSign);
    layout->addLayout(customHBox);
    layout->addStretch(10);

    switch (m_runConfiguration->signingMode()) {
    case S60DeviceRunConfiguration::SignSelf:
        selfSign->setChecked(true);
        break;
    case S60DeviceRunConfiguration::SignCustom:
        customSignature->setChecked(true);
        break;
    }

    signaturePath->setPath(m_runConfiguration->customSignaturePath());
    keyPath->setPath(m_runConfiguration->customKeyPath());

    connect(m_nameLineEdit, SIGNAL(textEdited(QString)),
            this, SLOT(nameEdited(QString)));
    connect(m_runConfiguration, SIGNAL(targetInformationChanged()),
            this, SLOT(updateTargetInformation()));
    connect(selfSign, SIGNAL(toggled(bool)), this, SLOT(selfSignToggled(bool)));
    connect(customSignature, SIGNAL(toggled(bool)), this, SLOT(customSignatureToggled(bool)));
    connect(signaturePath, SIGNAL(changed(QString)), this, SLOT(signaturePathChanged(QString)));
    connect(keyPath, SIGNAL(changed(QString)), this, SLOT(keyPathChanged(QString)));
    updateSummary();
}

void S60DeviceRunConfigurationWidget::updateSerialDevices()
{
    m_serialPortsCombo->clear();
    clearDeviceInfo();
    const QString previousRunConfigurationPortName = m_runConfiguration->serialPortName();
    const QList<CommunicationDevice> devices = S60Manager::instance()->serialDeviceLister()->communicationDevices();
    int newIndex = -1;
    for (int i = 0; i < devices.size(); ++i) {
        const CommunicationDevice &device = devices.at(i);
        m_serialPortsCombo->addItem(device.friendlyName, qVariantFromValue(device));
        if (device.portName == previousRunConfigurationPortName)
            newIndex = i;
    }
    // Set new index: prefer to keep old or set to 0, if available.
    if (newIndex == -1 && !devices.empty())
        newIndex = 0;
    m_serialPortsCombo->setCurrentIndex(newIndex);
    if (newIndex == -1) {
        m_deviceInfoButton->setEnabled(false);
        m_runConfiguration->setSerialPortName(QString());
    } else {
        m_deviceInfoButton->setEnabled(true);
        const QString newPortName = device(newIndex).portName;
        if (newPortName != previousRunConfigurationPortName)
            m_runConfiguration->setSerialPortName(newPortName);
    }
}

CommunicationDevice S60DeviceRunConfigurationWidget::device(int i) const
{
    if (i >= 0) {
        const QVariant data = m_serialPortsCombo->itemData(i);
        if (qVariantCanConvert<Qt4ProjectManager::Internal::CommunicationDevice>(data))
            return qVariantValue<Qt4ProjectManager::Internal::CommunicationDevice>(data);
    }
    return CommunicationDevice(SerialPortCommunication);
}

CommunicationDevice S60DeviceRunConfigurationWidget::currentDevice() const
{
    return device(m_serialPortsCombo->currentIndex());
}

void S60DeviceRunConfigurationWidget::nameEdited(const QString &text)
{
    m_runConfiguration->setName(text);
}

void S60DeviceRunConfigurationWidget::updateTargetInformation()
{
    m_sisxFileLabel->setText(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"));
}

void S60DeviceRunConfigurationWidget::setSerialPort(int index)
{
    const CommunicationDevice d = device(index);
    m_runConfiguration->setSerialPortName(d.portName);
    m_runConfiguration->setCommunicationType(d.type);
    m_deviceInfoButton->setEnabled(index >= 0);
    clearDeviceInfo();
    updateSummary();
}

void S60DeviceRunConfigurationWidget::selfSignToggled(bool toggle)
{
    if (toggle)
        m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignSelf);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::customSignatureToggled(bool toggle)
{
    if (toggle)
        m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignCustom);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::signaturePathChanged(const QString &path)
{
    m_runConfiguration->setCustomSignaturePath(path);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::keyPathChanged(const QString &path)
{
    m_runConfiguration->setCustomKeyPath(path);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::updateSummary()
{
    //: Summary text of S60 device run configuration
    const QString device = m_serialPortsCombo->currentIndex() != -1 ?
                           m_serialPortsCombo->currentText() :
                           tr("<No Device>");
    const QString signature = m_runConfiguration->signingMode() == S60DeviceRunConfiguration::SignCustom ?
                              tr("(custom certificate)") :
                              tr("(self-signed certificate)");
    m_detailsWidget->setSummaryText(tr("Summary: Run on '%1' %2").arg(device, signature));
}

void S60DeviceRunConfigurationWidget::clearDeviceInfo()
{
    // Restore text & color
    m_deviceInfoLabel->clear();
    m_deviceInfoLabel->setStyleSheet(QString());
}

void S60DeviceRunConfigurationWidget::setDeviceInfoLabel(const QString &message, bool isError)
{
    m_deviceInfoLabel->setStyleSheet(isError ?
                                     QString(QLatin1String("background-color: red;")) :
                                     QString());
    m_deviceInfoLabel->setText(message);
    m_deviceInfoLabel->adjustSize();
}

void S60DeviceRunConfigurationWidget::updateDeviceInfo()
{
    QString message;
    setDeviceInfoLabel(tr("Connecting..."));
    const bool ok = getDeviceInfo(&message);
    setDeviceInfoLabel(message, !ok);
}

bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
{
    message->clear();
    // Do a launcher run with the ping protocol. Instantiate launcher on heap
    // as not to introduce delays when destructing a device with timeout
    trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, QSharedPointer<trk::TrkDevice>(), this);
    const CommunicationDevice commDev = currentDevice();
    launcher->setSerialFrame(commDev.type == SerialPortCommunication);
    launcher->setTrkServerName(commDev.portName);
    // Prompt the user to start
    if (commDev.type == BlueToothCommunication) {
        S60RunConfigBluetoothStarter starter(launcher->trkDevice());
        starter.setDevice(launcher->trkServerName());
        const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, this, message);
        switch (src) {
        case trk::BluetoothGuiConnected:
            break;
        case trk::BluetoothGuiCanceled:
            launcher->deleteLater();
            return true;
        case trk::BluetoothGuiError:
            launcher->deleteLater();
            return false;
        };
    }
    if (!launcher->startServer(message)) {
        launcher->deleteLater();
        return false;
    }
    // Set up event loop in the foreground with a timer to quit in case of  timeout.
    QEventLoop eventLoop;
    if (!m_infoTimeOutTimer) {
        m_infoTimeOutTimer = new QTimer(this);
        m_infoTimeOutTimer->setInterval(3000);
        m_infoTimeOutTimer->setSingleShot(true);
    }
    connect(m_infoTimeOutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
    connect(launcher, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    // Go!
    QApplication::setOverrideCursor(Qt::BusyCursor);
    m_infoTimeOutTimer->start();
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    m_infoTimeOutTimer->disconnect();
    QApplication::restoreOverrideCursor();
    // Anything received?
    *message = launcher->deviceDescription();
    launcher->deleteLater();
    if (message->isEmpty()) {
        *message = tr("A timeout occurred while querying the device. Check whether Trk is running");
        return false;
    }
    return true;
}

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>S60: Fix the run configuration status label<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 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 "s60devicerunconfigurationwidget.h"
#include "s60devicerunconfiguration.h"
#include "s60runconfigbluetoothstarter.h"
#include "bluetoothlistener_gui.h"
#include "s60manager.h"
#include "launcher.h"
#include "bluetoothlistener.h"
#include "bluetoothlistener_gui.h"
#include "serialdevicelister.h"

#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
#include <utils/pathchooser.h>

#include <QtCore/QTimer>
#include <QtGui/QRadioButton>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QComboBox>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QFormLayout>
#include <QtGui/QToolButton>
#include <QtGui/QStyle>
#include <QtGui/QApplication>
#include <QtGui/QSpacerItem>

Q_DECLARE_METATYPE(Qt4ProjectManager::Internal::CommunicationDevice)

namespace Qt4ProjectManager {
namespace Internal {

S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget(
            S60DeviceRunConfiguration *runConfiguration,
            QWidget *parent)
    : QWidget(parent),
    m_runConfiguration(runConfiguration),
    m_detailsWidget(new Utils::DetailsWidget),
    m_serialPortsCombo(new QComboBox),
    m_nameLineEdit(new QLineEdit(m_runConfiguration->name())),
    m_sisxFileLabel(new QLabel(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"))),
    m_deviceInfoButton(new QToolButton),
    m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))),
    m_deviceInfoLabel(new QLabel),
    m_infoTimeOutTimer(0)
{
    QVBoxLayout *mainBoxLayout = new QVBoxLayout();
    mainBoxLayout->setMargin(0);
    setLayout(mainBoxLayout);
    mainBoxLayout->addWidget(m_detailsWidget);
    QWidget *detailsContainer = new QWidget;
    m_detailsWidget->setWidget(detailsContainer);

    QVBoxLayout *detailsBoxLayout = new QVBoxLayout();
    detailsBoxLayout->setMargin(0);
    detailsContainer->setLayout(detailsBoxLayout);

    QFormLayout *formLayout = new QFormLayout();
    formLayout->setMargin(0);
    detailsBoxLayout->addLayout(formLayout);
    // Name control
    QLabel *nameLabel = new QLabel(tr("Name:"));
    nameLabel->setBuddy(m_nameLineEdit);
    formLayout->addRow(nameLabel, m_nameLineEdit);
    formLayout->addRow(tr("Install File:"), m_sisxFileLabel);

    updateSerialDevices();
    connect(S60Manager::instance()->serialDeviceLister(), SIGNAL(updated()),
            this, SLOT(updateSerialDevices()));
    // Serial devices control
    connect(m_serialPortsCombo, SIGNAL(activated(int)), this, SLOT(setSerialPort(int)));
    QHBoxLayout *serialPortHBoxLayout = new QHBoxLayout;
    serialPortHBoxLayout->addWidget(m_serialPortsCombo);
    serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));

    formLayout->addRow(tr("Device on Serial Port:"), serialPortHBoxLayout);

    // Device Info with button. Widgets are enabled in above call to updateSerialDevices()
    QHBoxLayout *infoHBoxLayout = new QHBoxLayout;
    m_deviceInfoLabel->setWordWrap(true);
    m_deviceInfoLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
    infoHBoxLayout->addWidget(m_deviceInfoLabel);
    infoHBoxLayout->addWidget(m_deviceInfoButton);
    m_deviceInfoButton->setIcon(qApp->style()->standardIcon(QStyle::SP_MessageBoxInformation));
    m_deviceInfoButton->setToolTip(tr("Queries the device for information"));
    connect(m_deviceInfoButton, SIGNAL(clicked()), this, SLOT(updateDeviceInfo()));
    formLayout->addRow(m_deviceInfoDescriptionLabel, infoHBoxLayout);

    // Signature/certificate stuff.
    QWidget *signatureWidget = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout();
    signatureWidget->setLayout(layout);
    detailsBoxLayout->addWidget(signatureWidget);
    QRadioButton *selfSign = new QRadioButton(tr("Self-signed certificate"));
    QHBoxLayout *customHBox = new QHBoxLayout();
    customHBox->setMargin(0);
    QVBoxLayout *radioLayout = new QVBoxLayout();
    QRadioButton *customSignature = new QRadioButton();
    radioLayout->addWidget(customSignature);
    radioLayout->addStretch(10);
    customHBox->addLayout(radioLayout);
    QFormLayout *customLayout = new QFormLayout();
    customLayout->setMargin(0);
    customLayout->setLabelAlignment(Qt::AlignRight);
    Utils::PathChooser *signaturePath = new Utils::PathChooser();
    signaturePath->setExpectedKind(Utils::PathChooser::File);
    signaturePath->setPromptDialogTitle(tr("Choose certificate file (.cer)"));
    customLayout->addRow(new QLabel(tr("Custom certificate:")), signaturePath);
    Utils::PathChooser *keyPath = new Utils::PathChooser();
    keyPath->setExpectedKind(Utils::PathChooser::File);
    keyPath->setPromptDialogTitle(tr("Choose key file (.key / .pem)"));
    customLayout->addRow(new QLabel(tr("Key file:")), keyPath);
    customHBox->addLayout(customLayout);
    customHBox->addStretch(10);
    layout->addWidget(selfSign);
    layout->addLayout(customHBox);
    layout->addStretch(10);

    switch (m_runConfiguration->signingMode()) {
    case S60DeviceRunConfiguration::SignSelf:
        selfSign->setChecked(true);
        break;
    case S60DeviceRunConfiguration::SignCustom:
        customSignature->setChecked(true);
        break;
    }

    signaturePath->setPath(m_runConfiguration->customSignaturePath());
    keyPath->setPath(m_runConfiguration->customKeyPath());

    connect(m_nameLineEdit, SIGNAL(textEdited(QString)),
            this, SLOT(nameEdited(QString)));
    connect(m_runConfiguration, SIGNAL(targetInformationChanged()),
            this, SLOT(updateTargetInformation()));
    connect(selfSign, SIGNAL(toggled(bool)), this, SLOT(selfSignToggled(bool)));
    connect(customSignature, SIGNAL(toggled(bool)), this, SLOT(customSignatureToggled(bool)));
    connect(signaturePath, SIGNAL(changed(QString)), this, SLOT(signaturePathChanged(QString)));
    connect(keyPath, SIGNAL(changed(QString)), this, SLOT(keyPathChanged(QString)));
    updateSummary();
}

void S60DeviceRunConfigurationWidget::updateSerialDevices()
{
    m_serialPortsCombo->clear();
    clearDeviceInfo();
    const QString previousRunConfigurationPortName = m_runConfiguration->serialPortName();
    const QList<CommunicationDevice> devices = S60Manager::instance()->serialDeviceLister()->communicationDevices();
    int newIndex = -1;
    for (int i = 0; i < devices.size(); ++i) {
        const CommunicationDevice &device = devices.at(i);
        m_serialPortsCombo->addItem(device.friendlyName, qVariantFromValue(device));
        if (device.portName == previousRunConfigurationPortName)
            newIndex = i;
    }
    // Set new index: prefer to keep old or set to 0, if available.
    if (newIndex == -1 && !devices.empty())
        newIndex = 0;
    m_serialPortsCombo->setCurrentIndex(newIndex);
    if (newIndex == -1) {
        m_deviceInfoButton->setEnabled(false);
        m_runConfiguration->setSerialPortName(QString());
    } else {
        m_deviceInfoButton->setEnabled(true);
        const QString newPortName = device(newIndex).portName;
        if (newPortName != previousRunConfigurationPortName)
            m_runConfiguration->setSerialPortName(newPortName);
    }
}

CommunicationDevice S60DeviceRunConfigurationWidget::device(int i) const
{
    if (i >= 0) {
        const QVariant data = m_serialPortsCombo->itemData(i);
        if (qVariantCanConvert<Qt4ProjectManager::Internal::CommunicationDevice>(data))
            return qVariantValue<Qt4ProjectManager::Internal::CommunicationDevice>(data);
    }
    return CommunicationDevice(SerialPortCommunication);
}

CommunicationDevice S60DeviceRunConfigurationWidget::currentDevice() const
{
    return device(m_serialPortsCombo->currentIndex());
}

void S60DeviceRunConfigurationWidget::nameEdited(const QString &text)
{
    m_runConfiguration->setName(text);
}

void S60DeviceRunConfigurationWidget::updateTargetInformation()
{
    m_sisxFileLabel->setText(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"));
}

void S60DeviceRunConfigurationWidget::setSerialPort(int index)
{
    const CommunicationDevice d = device(index);
    m_runConfiguration->setSerialPortName(d.portName);
    m_runConfiguration->setCommunicationType(d.type);
    m_deviceInfoButton->setEnabled(index >= 0);
    clearDeviceInfo();
    updateSummary();
}

void S60DeviceRunConfigurationWidget::selfSignToggled(bool toggle)
{
    if (toggle)
        m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignSelf);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::customSignatureToggled(bool toggle)
{
    if (toggle)
        m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignCustom);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::signaturePathChanged(const QString &path)
{
    m_runConfiguration->setCustomSignaturePath(path);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::keyPathChanged(const QString &path)
{
    m_runConfiguration->setCustomKeyPath(path);
    updateSummary();
}

void S60DeviceRunConfigurationWidget::updateSummary()
{
    //: Summary text of S60 device run configuration
    const QString device = m_serialPortsCombo->currentIndex() != -1 ?
                           m_serialPortsCombo->currentText() :
                           tr("<No Device>");
    const QString signature = m_runConfiguration->signingMode() == S60DeviceRunConfiguration::SignCustom ?
                              tr("(custom certificate)") :
                              tr("(self-signed certificate)");
    m_detailsWidget->setSummaryText(tr("Summary: Run on '%1' %2").arg(device, signature));
}

void S60DeviceRunConfigurationWidget::clearDeviceInfo()
{
    // Restore text & color
    m_deviceInfoLabel->clear();
    m_deviceInfoLabel->setStyleSheet(QString());
}

void S60DeviceRunConfigurationWidget::setDeviceInfoLabel(const QString &message, bool isError)
{
    m_deviceInfoLabel->setStyleSheet(isError ?
                                     QString(QLatin1String("background-color: red;")) :
                                     QString());
    m_deviceInfoLabel->setText(message);
    m_deviceInfoLabel->adjustSize();
}

void S60DeviceRunConfigurationWidget::updateDeviceInfo()
{
    QString message;
    setDeviceInfoLabel(tr("Connecting..."));
    const bool ok = getDeviceInfo(&message);
    setDeviceInfoLabel(message, !ok);
}

bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
{
    message->clear();
    // Do a launcher run with the ping protocol. Instantiate launcher on heap
    // as not to introduce delays when destructing a device with timeout
    trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, QSharedPointer<trk::TrkDevice>(), this);
    const CommunicationDevice commDev = currentDevice();
    launcher->setSerialFrame(commDev.type == SerialPortCommunication);
    launcher->setTrkServerName(commDev.portName);
    // Prompt the user to start
    if (commDev.type == BlueToothCommunication) {
        S60RunConfigBluetoothStarter starter(launcher->trkDevice());
        starter.setDevice(launcher->trkServerName());
        const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, this, message);
        switch (src) {
        case trk::BluetoothGuiConnected:
            break;
        case trk::BluetoothGuiCanceled:
            launcher->deleteLater();
            return true;
        case trk::BluetoothGuiError:
            launcher->deleteLater();
            return false;
        };
    }
    if (!launcher->startServer(message)) {
        launcher->deleteLater();
        return false;
    }
    // Set up event loop in the foreground with a timer to quit in case of  timeout.
    QEventLoop eventLoop;
    if (!m_infoTimeOutTimer) {
        m_infoTimeOutTimer = new QTimer(this);
        m_infoTimeOutTimer->setInterval(3000);
        m_infoTimeOutTimer->setSingleShot(true);
    }
    connect(m_infoTimeOutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
    connect(launcher, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    // Go!
    QApplication::setOverrideCursor(Qt::BusyCursor);
    m_infoTimeOutTimer->start();
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    m_infoTimeOutTimer->disconnect();
    QApplication::restoreOverrideCursor();
    // Anything received?
    *message = launcher->deviceDescription();
    launcher->deleteLater();
    if (message->isEmpty()) {
        *message = tr("A timeout occurred while querying the device. Check whether Trk is running");
        return false;
    }
    return true;
}

} // namespace Internal
} // namespace Qt4ProjectManager
<|endoftext|>