MobileWizards: Add option for booster to harmattan configure page

Split up maemo- and harmattan wizard pages, and add a checkbox
for enabling booster specifically for harmattan.

Change-Id: If5653abbf6d29b5f946718d10bc12404df19c16c
Reviewed-on: http://codereview.qt.nokia.com/3731
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Alessandro Portale <alessandro.portale@nokia.com>
Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
This commit is contained in:
Kai Koehne
2011-08-16 13:41:08 +02:00
committed by Eike Ziller
parent d687d11240
commit f7de570fa3
10 changed files with 285 additions and 44 deletions

View File

@@ -137,6 +137,7 @@ FORMS += makestep.ui \
wizards/mobileappwizardgenericoptionspage.ui \ wizards/mobileappwizardgenericoptionspage.ui \
wizards/mobileappwizardsymbianoptionspage.ui \ wizards/mobileappwizardsymbianoptionspage.ui \
wizards/mobileappwizardmaemooptionspage.ui \ wizards/mobileappwizardmaemooptionspage.ui \
wizards/mobileappwizardharmattanoptionspage.ui \
wizards/qtquickcomponentsetoptionspage.ui wizards/qtquickcomponentsetoptionspage.ui
RESOURCES += qt4projectmanager.qrc \ RESOURCES += qt4projectmanager.qrc \

View File

@@ -42,6 +42,7 @@
#endif // CREATORLESSTEST #endif // CREATORLESSTEST
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h>
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
@@ -62,8 +63,11 @@ const QString AbstractMobileApp::FileStubVersion(QLatin1String("version"));
const int AbstractMobileApp::StubVersion = 6; const int AbstractMobileApp::StubVersion = 6;
AbstractMobileApp::AbstractMobileApp() AbstractMobileApp::AbstractMobileApp()
: m_orientation(ScreenOrientationAuto) : QObject()
, m_canSupportMeegoBooster(false)
, m_orientation(ScreenOrientationAuto)
, m_networkEnabled(true) , m_networkEnabled(true)
, m_supportsMeegoBooster(false)
{ {
} }
@@ -209,6 +213,9 @@ QByteArray AbstractMobileApp::generateDesktopFile(QString *errorMessage, int fil
} else if (fileType == AbstractGeneratedFileInfo::DesktopFileHarmattan) { } else if (fileType == AbstractGeneratedFileInfo::DesktopFileHarmattan) {
desktopFileContent.replace("Icon=thisApp", desktopFileContent.replace("Icon=thisApp",
"Icon=/usr/share/icons/hicolor/80x80/apps/" + projectName().toUtf8() + "80.png"); "Icon=/usr/share/icons/hicolor/80x80/apps/" + projectName().toUtf8() + "80.png");
if (m_supportsMeegoBooster)
desktopFileContent.replace("Exec=", "Exec=/usr/bin/invoker --type=d -s ");
else
desktopFileContent.replace("Exec=", "Exec=/usr/bin/single-instance "); desktopFileContent.replace("Exec=", "Exec=/usr/bin/single-instance ");
} }
return desktopFileContent.replace("thisApp", projectName().toUtf8()); return desktopFileContent.replace("thisApp", projectName().toUtf8());
@@ -416,6 +423,22 @@ QString AbstractMobileApp::error() const
return m_error; return m_error;
} }
bool AbstractMobileApp::canSupportMeegoBooster() const
{
return m_canSupportMeegoBooster;
}
bool AbstractMobileApp::supportsMeegoBooster() const
{
return m_supportsMeegoBooster;
}
void AbstractMobileApp::setSupportsMeegoBooster(bool supportMeegoBooster)
{
QTC_ASSERT(canSupportMeegoBooster(), return);
m_supportsMeegoBooster = supportMeegoBooster;
}
QByteArray AbstractMobileApp::readBlob(const QString &filePath, QByteArray AbstractMobileApp::readBlob(const QString &filePath,
QString *errorMsg) const QString *errorMsg) const
{ {

View File

@@ -133,6 +133,10 @@ public:
QString path(int fileType) const; QString path(int fileType) const;
QString error() const; QString error() const;
bool canSupportMeegoBooster() const;
bool supportsMeegoBooster() const;
void setSupportsMeegoBooster(bool supportBooster);
#ifndef CREATORLESSTEST #ifndef CREATORLESSTEST
virtual Core::GeneratedFiles generateFiles(QString *errorMessage) const; virtual Core::GeneratedFiles generateFiles(QString *errorMessage) const;
#else #else
@@ -168,6 +172,8 @@ protected:
static const int StubVersion; static const int StubVersion;
QString m_error; QString m_error;
bool m_canSupportMeegoBooster;
private: private:
QByteArray generateDesktopFile(QString *errorMessage, int fileType) const; QByteArray generateDesktopFile(QString *errorMessage, int fileType) const;
QByteArray generateMainCpp(QString *errorMessage) const; QByteArray generateMainCpp(QString *errorMessage) const;
@@ -194,6 +200,7 @@ private:
QString m_symbianTargetUid; QString m_symbianTargetUid;
ScreenOrientation m_orientation; ScreenOrientation m_orientation;
bool m_networkEnabled; bool m_networkEnabled;
bool m_supportsMeegoBooster;
}; };
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -70,8 +70,8 @@ AbstractMobileAppWizardDialog::AbstractMobileAppWizardDialog(QWidget *parent, co
m_genericOptionsPage = new Internal::MobileAppWizardGenericOptionsPage; m_genericOptionsPage = new Internal::MobileAppWizardGenericOptionsPage;
m_symbianOptionsPage = new Internal::MobileAppWizardSymbianOptionsPage; m_symbianOptionsPage = new Internal::MobileAppWizardSymbianOptionsPage;
m_maemoOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(64); m_maemoOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage;
m_harmattanOptionsPage = new Internal::MobileAppWizardMaemoOptionsPage(80); m_harmattanOptionsPage = new Internal::MobileAppWizardHarmattanOptionsPage;
} }
void AbstractMobileAppWizardDialog::addMobilePages() void AbstractMobileAppWizardDialog::addMobilePages()
@@ -241,6 +241,7 @@ QWizard *AbstractMobileAppWizard::createWizardDialog(QWidget *parent,
wdlg->m_symbianOptionsPage->setNetworkEnabled(app()->networkEnabled()); wdlg->m_symbianOptionsPage->setNetworkEnabled(app()->networkEnabled());
wdlg->m_maemoOptionsPage->setPngIcon(app()->maemoPngIcon64()); wdlg->m_maemoOptionsPage->setPngIcon(app()->maemoPngIcon64());
wdlg->m_harmattanOptionsPage->setPngIcon(app()->maemoPngIcon80()); wdlg->m_harmattanOptionsPage->setPngIcon(app()->maemoPngIcon80());
wdlg->m_harmattanOptionsPage->setBoosterOptionEnabled(app()->canSupportMeegoBooster());
connect(wdlg, SIGNAL(projectParametersChanged(QString, QString)), connect(wdlg, SIGNAL(projectParametersChanged(QString, QString)),
SLOT(useProjectPath(QString, QString))); SLOT(useProjectPath(QString, QString)));
foreach (QWizardPage *p, extensionPages) foreach (QWizardPage *p, extensionPages)
@@ -259,6 +260,9 @@ Core::GeneratedFiles AbstractMobileAppWizard::generateFiles(const QWizard *wizar
app()->setNetworkEnabled(wdlg->m_symbianOptionsPage->networkEnabled()); app()->setNetworkEnabled(wdlg->m_symbianOptionsPage->networkEnabled());
app()->setMaemoPngIcon64(wdlg->m_maemoOptionsPage->pngIcon()); app()->setMaemoPngIcon64(wdlg->m_maemoOptionsPage->pngIcon());
app()->setMaemoPngIcon80(wdlg->m_harmattanOptionsPage->pngIcon()); app()->setMaemoPngIcon80(wdlg->m_harmattanOptionsPage->pngIcon());
if (wdlg->isHarmattanTargetSelected())
app()->setSupportsMeegoBooster(wdlg->isHarmattanTargetSelected()
&& wdlg->m_harmattanOptionsPage->supportsBooster());
prepareGenerateFiles(wizard, errorMessage); prepareGenerateFiles(wizard, errorMessage);
return app()->generateFiles(errorMessage); return app()->generateFiles(errorMessage);
} }

View File

@@ -48,6 +48,7 @@ namespace Internal {
class MobileAppWizardGenericOptionsPage; class MobileAppWizardGenericOptionsPage;
class MobileAppWizardSymbianOptionsPage; class MobileAppWizardSymbianOptionsPage;
class MobileAppWizardMaemoOptionsPage; class MobileAppWizardMaemoOptionsPage;
class MobileAppWizardHarmattanOptionsPage;
} }
/// \internal /// \internal
@@ -82,7 +83,7 @@ private:
Internal::MobileAppWizardGenericOptionsPage *m_genericOptionsPage; Internal::MobileAppWizardGenericOptionsPage *m_genericOptionsPage;
Internal::MobileAppWizardSymbianOptionsPage *m_symbianOptionsPage; Internal::MobileAppWizardSymbianOptionsPage *m_symbianOptionsPage;
Internal::MobileAppWizardMaemoOptionsPage *m_maemoOptionsPage; Internal::MobileAppWizardMaemoOptionsPage *m_maemoOptionsPage;
Internal::MobileAppWizardMaemoOptionsPage *m_harmattanOptionsPage; Internal::MobileAppWizardHarmattanOptionsPage *m_harmattanOptionsPage;
TargetSetupPage *m_targetsPage; TargetSetupPage *m_targetsPage;
int m_genericOptionsPageId; int m_genericOptionsPageId;

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MobileAppWizardHarmattanOptionsPage</class>
<widget class="QWizardPage" name="MobileAppWizardHarmattanOptionsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>WizardPage</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="appIconLabel">
<property name="text">
<string>Application icon (80x80):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="pngIconButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="makeBoostableCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Generate code to speed up the launching on the device.</string>
</property>
<property name="text">
<string>Make application boostable</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -17,7 +17,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="appIconLabel"> <widget class="QLabel" name="appIconLabel">
<property name="text"> <property name="text">
<string>Application icon (%%w%%x%%h%%):</string> <string>Application icon (64x64):</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -33,6 +33,7 @@
#include "mobileappwizardpages.h" #include "mobileappwizardpages.h"
#include "ui_mobileappwizardgenericoptionspage.h" #include "ui_mobileappwizardgenericoptionspage.h"
#include "ui_mobileappwizardmaemooptionspage.h" #include "ui_mobileappwizardmaemooptionspage.h"
#include "ui_mobileappwizardharmattanoptionspage.h"
#include "ui_mobileappwizardsymbianoptionspage.h" #include "ui_mobileappwizardsymbianoptionspage.h"
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
@@ -67,6 +68,14 @@ class MobileAppWizardMaemoOptionsPagePrivate
friend class MobileAppWizardMaemoOptionsPage; friend class MobileAppWizardMaemoOptionsPage;
}; };
class MobileAppWizardHarmattanOptionsPagePrivate
{
Ui::MobileAppWizardHarmattanOptionsPage ui;
QSize iconSize;
QString pngIcon;
friend class MobileAppWizardHarmattanOptionsPage;
};
MobileAppWizardGenericOptionsPage::MobileAppWizardGenericOptionsPage(QWidget *parent) MobileAppWizardGenericOptionsPage::MobileAppWizardGenericOptionsPage(QWidget *parent)
: QWizardPage(parent) : QWizardPage(parent)
, m_d(new MobileAppWizardGenericOptionsPagePrivate) , m_d(new MobileAppWizardGenericOptionsPagePrivate)
@@ -167,18 +176,12 @@ void MobileAppWizardSymbianOptionsPage::openSvgIcon()
setSvgIcon(svgIcon); setSvgIcon(svgIcon);
} }
MobileAppWizardMaemoOptionsPage::MobileAppWizardMaemoOptionsPage(QWidget *parent)
MobileAppWizardMaemoOptionsPage::MobileAppWizardMaemoOptionsPage(int appIconSize,
QWidget *parent)
: QWizardPage(parent) : QWizardPage(parent)
, m_d(new MobileAppWizardMaemoOptionsPagePrivate) , m_d(new MobileAppWizardMaemoOptionsPagePrivate)
{ {
m_d->ui.setupUi(this); m_d->ui.setupUi(this);
QString iconLabelText = m_d->ui.appIconLabel->text(); m_d->iconSize = QSize(64, 64);
iconLabelText.replace(QLatin1String("%%w%%"), QString::number(appIconSize));
iconLabelText.replace(QLatin1String("%%h%%"), QString::number(appIconSize));
m_d->ui.appIconLabel->setText(iconLabelText);
m_d->iconSize = QSize(appIconSize, appIconSize);
m_d->ui.pngIconButton->setIconSize(m_d->iconSize); m_d->ui.pngIconButton->setIconSize(m_d->iconSize);
connect(m_d->ui.pngIconButton, SIGNAL(clicked()), this, SLOT(openPngIcon())); connect(m_d->ui.pngIconButton, SIGNAL(clicked()), this, SLOT(openPngIcon()));
} }
@@ -193,42 +196,66 @@ QString MobileAppWizardMaemoOptionsPage::pngIcon() const
return m_d->pngIcon; return m_d->pngIcon;
} }
void MobileAppWizardMaemoOptionsPage::setPngIcon(const QString &icon)
class PngIconScaler : public QObject
{
Q_OBJECT
public:
PngIconScaler(const QSize &expectedSize, const QString &iconPath)
: m_expectedSize(expectedSize)
, m_iconPath(iconPath)
, m_pixmap(iconPath)
{ {
QString error;
QPixmap iconPixmap(icon);
if (iconPixmap.isNull()) {
QMessageBox::critical(this, tr("Invalid Icon"),
tr("The file is not a valid image."));
return;
} }
QString actualIconPath; bool hasRightSize() const { return m_expectedSize == m_pixmap.size(); }
if (iconPixmap.size() == m_d->iconSize) { QPixmap pixmap() const { return m_pixmap; }
actualIconPath = icon;
} else { bool scale(QString *newPath) {
const QMessageBox::StandardButton button = QMessageBox::warning(this, const QMessageBox::StandardButton button
tr("Wrong Icon Size"), tr("The icon needs to be %1x%2 pixels big, " = QMessageBox::warning(QApplication::activeWindow(),
"but is not. Do you want Creator to scale it?") tr("Wrong Icon Size"),
.arg(m_d->iconSize.width()).arg(m_d->iconSize.height()), tr("The icon needs to be %1x%2 pixels big, "
"but is not. Do you want Qt Creator to scale it?")
.arg(m_expectedSize.width()).arg(m_expectedSize.height()),
QMessageBox::Ok | QMessageBox::Cancel); QMessageBox::Ok | QMessageBox::Cancel);
if (button != QMessageBox::Ok) if (button != QMessageBox::Ok)
return; return false;
iconPixmap = iconPixmap.scaled(m_d->iconSize);
m_pixmap = m_pixmap.scaled(m_expectedSize);
Utils::TempFileSaver saver; Utils::TempFileSaver saver;
saver.setAutoRemove(false); saver.setAutoRemove(false);
if (!saver.hasError()) if (!saver.hasError())
saver.setResult(iconPixmap.save( saver.setResult(m_pixmap.save(
saver.file(), QFileInfo(icon).suffix().toAscii().constData())); saver.file(), QFileInfo(m_iconPath).suffix().toAscii().constData()));
if (!saver.finalize()) { if (!saver.finalize()) {
QMessageBox::critical(this, tr("File Error"), QMessageBox::critical(QApplication::activeWindow(),
tr("File Error"),
tr("Could not copy icon file: %1").arg(saver.errorString())); tr("Could not copy icon file: %1").arg(saver.errorString()));
return false;
}
*newPath = saver.fileName();
return true;
}
private:
QSize m_expectedSize;
QString m_iconPath;
QPixmap m_pixmap;
};
void MobileAppWizardMaemoOptionsPage::setPngIcon(const QString &icon)
{
QString actualIconPath;
PngIconScaler scaler(m_d->iconSize, icon);
if (scaler.hasRightSize()) {
actualIconPath = icon;
} else {
if (!scaler.scale(&actualIconPath))
return; return;
} }
actualIconPath = saver.fileName();
}
m_d->ui.pngIconButton->setIcon(iconPixmap); m_d->ui.pngIconButton->setIcon(scaler.pixmap());
m_d->pngIcon = actualIconPath; m_d->pngIcon = actualIconPath;
} }
@@ -241,5 +268,62 @@ void MobileAppWizardMaemoOptionsPage::openPngIcon()
setPngIcon(iconPath); setPngIcon(iconPath);
} }
MobileAppWizardHarmattanOptionsPage::MobileAppWizardHarmattanOptionsPage(QWidget *parent)
: QWizardPage(parent)
, m_d(new MobileAppWizardHarmattanOptionsPagePrivate)
{
m_d->ui.setupUi(this);
m_d->iconSize = QSize(80, 80);
m_d->ui.pngIconButton->setIconSize(m_d->iconSize);
connect(m_d->ui.pngIconButton, SIGNAL(clicked()), this, SLOT(openPngIcon()));
}
MobileAppWizardHarmattanOptionsPage::~MobileAppWizardHarmattanOptionsPage()
{
delete m_d;
}
QString MobileAppWizardHarmattanOptionsPage::pngIcon() const
{
return m_d->pngIcon;
}
void MobileAppWizardHarmattanOptionsPage::setPngIcon(const QString &icon)
{
QString actualIconPath;
PngIconScaler scaler(m_d->iconSize, icon);
if (scaler.hasRightSize()) {
actualIconPath = icon;
} else {
if (!scaler.scale(&actualIconPath))
return;
}
m_d->ui.pngIconButton->setIcon(scaler.pixmap());
m_d->pngIcon = actualIconPath;
}
void MobileAppWizardHarmattanOptionsPage::openPngIcon()
{
const QString iconPath = QFileDialog::getOpenFileName(this,
m_d->ui.appIconLabel->text(), m_d->pngIcon,
QLatin1String("*.png"));
if (!iconPath.isEmpty())
setPngIcon(iconPath);
}
void MobileAppWizardHarmattanOptionsPage::setBoosterOptionEnabled(bool enable)
{
m_d->ui.makeBoostableCheckBox->setEnabled(enable);
m_d->ui.makeBoostableCheckBox->setChecked(enable);
}
bool MobileAppWizardHarmattanOptionsPage::supportsBooster() const
{
return m_d->ui.makeBoostableCheckBox->isChecked();
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager
#include "mobileappwizardpages.moc"

View File

@@ -85,8 +85,7 @@ class MobileAppWizardMaemoOptionsPage : public QWizardPage
Q_DISABLE_COPY(MobileAppWizardMaemoOptionsPage) Q_DISABLE_COPY(MobileAppWizardMaemoOptionsPage)
public: public:
explicit MobileAppWizardMaemoOptionsPage(int appIconSize, explicit MobileAppWizardMaemoOptionsPage(QWidget *parent = 0);
QWidget *parent = 0);
virtual ~MobileAppWizardMaemoOptionsPage(); virtual ~MobileAppWizardMaemoOptionsPage();
QString pngIcon() const; QString pngIcon() const;
@@ -99,6 +98,27 @@ private:
class MobileAppWizardMaemoOptionsPagePrivate *m_d; class MobileAppWizardMaemoOptionsPagePrivate *m_d;
}; };
class MobileAppWizardHarmattanOptionsPage : public QWizardPage
{
Q_OBJECT
public:
explicit MobileAppWizardHarmattanOptionsPage(QWidget *parent = 0);
virtual ~MobileAppWizardHarmattanOptionsPage();
QString pngIcon() const;
void setPngIcon(const QString &icon);
void setBoosterOptionEnabled(bool enable);
bool supportsBooster() const;
private slots:
void openPngIcon();
private:
class MobileAppWizardHarmattanOptionsPagePrivate *m_d;
};
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -102,6 +102,7 @@ QtQuickApp::QtQuickApp()
, m_mainQmlMode(ModeGenerate) , m_mainQmlMode(ModeGenerate)
, m_componentSet(QtQuick10Components) , m_componentSet(QtQuick10Components)
{ {
m_canSupportMeegoBooster = true;
} }
QtQuickApp::~QtQuickApp() QtQuickApp::~QtQuickApp()
@@ -226,16 +227,16 @@ QString QtQuickApp::mainWindowClassName() const
bool QtQuickApp::adaptCurrentMainCppTemplateLine(QString &line) const bool QtQuickApp::adaptCurrentMainCppTemplateLine(QString &line) const
{ {
const QLatin1Char quote('"'); const QLatin1Char quote('"');
bool adaptLine = true;
if (line.contains(QLatin1String("// MAINQML"))) { if (line.contains(QLatin1String("// MAINQML"))) {
insertParameter(line, quote + path(MainQmlDeployed) + quote); insertParameter(line, quote + path(MainQmlDeployed) + quote);
} else if (line.contains(QLatin1String("// ADDIMPORTPATH"))) { } else if (line.contains(QLatin1String("// ADDIMPORTPATH"))) {
if (m_modules.isEmpty()) if (m_modules.isEmpty())
adaptLine = false; return false;
else else
insertParameter(line, quote + path(ModulesDir) + quote); insertParameter(line, quote + path(ModulesDir) + quote);
} }
return adaptLine; return true;
} }
void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line, void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line,
@@ -263,6 +264,11 @@ void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line,
if (componentSet() == Symbian10Components) if (componentSet() == Symbian10Components)
nextLine.remove(0, 2); // remove comment nextLine.remove(0, 2); // remove comment
proFile << nextLine << endl; proFile << nextLine << endl;
} else if (line.contains(QLatin1String("# HARMATTAN_BOOSTABLE"))) {
QString nextLine = proFileTemplate.readLine(); // eats '# CONFIG += qdeclarative-boostable'
if (supportsMeegoBooster())
nextLine.remove(0, 2); // remove comment
proFile << nextLine << endl;
} }
} }