forked from qt-creator/qt-creator
Android: add service editor to manifest editor
Task-number: QTCREATORBUG-23937 Change-Id: Iec0435721504df744ec985bd3e5cefcc0700e852 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@ add_qtc_plugin(Android
|
|||||||
androidsdkmanagerwidget.cpp androidsdkmanagerwidget.h androidsdkmanagerwidget.ui
|
androidsdkmanagerwidget.cpp androidsdkmanagerwidget.h androidsdkmanagerwidget.ui
|
||||||
androidsdkmodel.cpp androidsdkmodel.h
|
androidsdkmodel.cpp androidsdkmodel.h
|
||||||
androidsdkpackage.cpp androidsdkpackage.h
|
androidsdkpackage.cpp androidsdkpackage.h
|
||||||
|
androidservicewidget.cpp androidservicewidget.h androidservicewidget_p.h
|
||||||
androidsettingswidget.cpp androidsettingswidget.h androidsettingswidget.ui
|
androidsettingswidget.cpp androidsettingswidget.h androidsettingswidget.ui
|
||||||
androidsignaloperation.cpp androidsignaloperation.h
|
androidsignaloperation.cpp androidsignaloperation.h
|
||||||
androidtoolchain.cpp androidtoolchain.h
|
androidtoolchain.cpp androidtoolchain.h
|
||||||
|
@@ -13,6 +13,8 @@ HEADERS += \
|
|||||||
androidmanifesteditoriconwidget.h \
|
androidmanifesteditoriconwidget.h \
|
||||||
androidrunconfiguration.h \
|
androidrunconfiguration.h \
|
||||||
androidruncontrol.h \
|
androidruncontrol.h \
|
||||||
|
androidservicewidget.h \
|
||||||
|
androidservicewidget_p.h \
|
||||||
androidsettingswidget.h \
|
androidsettingswidget.h \
|
||||||
androidtoolchain.h \
|
androidtoolchain.h \
|
||||||
androiderrormessage.h \
|
androiderrormessage.h \
|
||||||
@@ -60,6 +62,7 @@ SOURCES += \
|
|||||||
androidmanifesteditoriconwidget.cpp \
|
androidmanifesteditoriconwidget.cpp \
|
||||||
androidrunconfiguration.cpp \
|
androidrunconfiguration.cpp \
|
||||||
androidruncontrol.cpp \
|
androidruncontrol.cpp \
|
||||||
|
androidservicewidget.cpp \
|
||||||
androidsettingswidget.cpp \
|
androidsettingswidget.cpp \
|
||||||
androidtoolchain.cpp \
|
androidtoolchain.cpp \
|
||||||
androiderrormessage.cpp \
|
androiderrormessage.cpp \
|
||||||
|
@@ -93,6 +93,9 @@ Project {
|
|||||||
"androidsdkmodel.h",
|
"androidsdkmodel.h",
|
||||||
"androidsdkpackage.cpp",
|
"androidsdkpackage.cpp",
|
||||||
"androidsdkpackage.h",
|
"androidsdkpackage.h",
|
||||||
|
"androidservicewidget.cpp",
|
||||||
|
"androidservicewidget.h",
|
||||||
|
"androidservicewidget_p.h",
|
||||||
"androidsettingswidget.cpp",
|
"androidsettingswidget.cpp",
|
||||||
"androidsettingswidget.h",
|
"androidsettingswidget.h",
|
||||||
"androidsettingswidget.ui",
|
"androidsettingswidget.ui",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "androidconstants.h"
|
#include "androidconstants.h"
|
||||||
#include "androidmanifestdocument.h"
|
#include "androidmanifestdocument.h"
|
||||||
#include "androidmanager.h"
|
#include "androidmanager.h"
|
||||||
|
#include "androidservicewidget.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/infobar.h>
|
#include <coreplugin/infobar.h>
|
||||||
@@ -68,6 +69,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
@@ -253,6 +255,9 @@ void AndroidManifestEditorWidget::initializePage()
|
|||||||
|
|
||||||
formLayout->addRow(QString(), m_iconButtons);
|
formLayout->addRow(QString(), m_iconButtons);
|
||||||
|
|
||||||
|
m_services = new AndroidServiceWidget(this);
|
||||||
|
formLayout->addRow(tr("Android services:"), m_services);
|
||||||
|
|
||||||
applicationGroupBox->setLayout(formLayout);
|
applicationGroupBox->setLayout(formLayout);
|
||||||
|
|
||||||
connect(m_appNameLineEdit, &QLineEdit::textEdited,
|
connect(m_appNameLineEdit, &QLineEdit::textEdited,
|
||||||
@@ -264,6 +269,12 @@ void AndroidManifestEditorWidget::initializePage()
|
|||||||
connect(m_styleExtractMethod,
|
connect(m_styleExtractMethod,
|
||||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
this, setDirtyFunc);
|
this, setDirtyFunc);
|
||||||
|
connect(m_services, &AndroidServiceWidget::servicesModified,
|
||||||
|
this, setDirtyFunc);
|
||||||
|
connect(m_services, &AndroidServiceWidget::servicesModified,
|
||||||
|
this, &AndroidManifestEditorWidget::clearInvalidServiceInfo);
|
||||||
|
connect(m_services, &AndroidServiceWidget::servicesInvalid,
|
||||||
|
this, &AndroidManifestEditorWidget::setInvalidServiceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -539,6 +550,14 @@ AndroidManifestEditorWidget::EditorPage AndroidManifestEditorWidget::activePage(
|
|||||||
return AndroidManifestEditorWidget::EditorPage(currentIndex());
|
return AndroidManifestEditorWidget::EditorPage(currentIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool servicesValid(const QList<AndroidServiceData> &services)
|
||||||
|
{
|
||||||
|
for (auto &&x : services)
|
||||||
|
if (!x.isValid())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
|
bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
|
||||||
{
|
{
|
||||||
EditorPage prevPage = activePage();
|
EditorPage prevPage = activePage();
|
||||||
@@ -547,6 +566,11 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (page == Source) {
|
if (page == Source) {
|
||||||
|
if (!servicesValid(m_services->services())) {
|
||||||
|
QMessageBox::critical(nullptr, tr("Service Definition Invalid"),
|
||||||
|
tr("Cannot switch to source when there are invalid services."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
syncToEditor();
|
syncToEditor();
|
||||||
} else {
|
} else {
|
||||||
if (!syncToWidgets())
|
if (!syncToWidgets())
|
||||||
@@ -567,8 +591,14 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
|
|||||||
|
|
||||||
void AndroidManifestEditorWidget::preSave()
|
void AndroidManifestEditorWidget::preSave()
|
||||||
{
|
{
|
||||||
if (activePage() != Source)
|
if (activePage() != Source) {
|
||||||
|
if (!servicesValid(m_services->services())) {
|
||||||
|
QMessageBox::critical(nullptr, tr("Service Definition Invalid"),
|
||||||
|
tr("Cannot save when there are invalid services."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
syncToEditor();
|
syncToEditor();
|
||||||
|
}
|
||||||
|
|
||||||
// no need to emit changed() since this is called as part of saving
|
// no need to emit changed() since this is called as part of saving
|
||||||
updateInfoBar();
|
updateInfoBar();
|
||||||
@@ -707,7 +737,26 @@ void AndroidManifestEditorWidget::hideInfoBar()
|
|||||||
{
|
{
|
||||||
Core::InfoBar *infoBar = m_textEditorWidget->textDocument()->infoBar();
|
Core::InfoBar *infoBar = m_textEditorWidget->textDocument()->infoBar();
|
||||||
infoBar->removeInfo(infoBarId);
|
infoBar->removeInfo(infoBarId);
|
||||||
m_timerParseCheck.stop();
|
m_timerParseCheck.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char kServicesInvalid[] = "AndroidServiceDefinitionInvalid";
|
||||||
|
|
||||||
|
void AndroidManifestEditorWidget::setInvalidServiceInfo()
|
||||||
|
{
|
||||||
|
Core::Id id(kServicesInvalid);
|
||||||
|
if (m_textEditorWidget->textDocument()->infoBar()->containsInfo(id))
|
||||||
|
return;
|
||||||
|
Core::InfoBarEntry info(id,
|
||||||
|
tr("Services invalid. "
|
||||||
|
"Manifest cannot be saved. Correct the service definitions before saving."));
|
||||||
|
m_textEditorWidget->textDocument()->infoBar()->addInfo(info);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidManifestEditorWidget::clearInvalidServiceInfo()
|
||||||
|
{
|
||||||
|
m_textEditorWidget->textDocument()->infoBar()->removeInfo(Core::Id(kServicesInvalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setApiLevel(QComboBox *box, const QDomElement &element, const QString &attribute)
|
void setApiLevel(QComboBox *box, const QDomElement &element, const QString &attribute)
|
||||||
@@ -810,6 +859,33 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
|
|||||||
m_permissionsModel->setPermissions(permissions);
|
m_permissionsModel->setPermissions(permissions);
|
||||||
updateAddRemovePermissionButtons();
|
updateAddRemovePermissionButtons();
|
||||||
|
|
||||||
|
QList<AndroidServiceData> services;
|
||||||
|
QDomElement serviceElem = applicationElement.firstChildElement(QLatin1String("service"));
|
||||||
|
while (!serviceElem.isNull()) {
|
||||||
|
AndroidServiceData service;
|
||||||
|
service.setClassName(serviceElem.attribute(QLatin1String("android:name")));
|
||||||
|
QString process = serviceElem.attribute(QLatin1String("android:process"));
|
||||||
|
service.setRunInExternalProcess(!process.isEmpty());
|
||||||
|
service.setExternalProcessName(process);
|
||||||
|
QDomElement serviceMetadataElem = serviceElem.firstChildElement(QLatin1String("meta-data"));
|
||||||
|
while (!serviceMetadataElem.isNull()) {
|
||||||
|
QString metadataName = serviceMetadataElem.attribute(QLatin1String("android:name"));
|
||||||
|
if (metadataName == QLatin1String("android.app.lib_name")) {
|
||||||
|
QString metadataValue = serviceMetadataElem.attribute(QLatin1String("android:value"));
|
||||||
|
service.setRunInExternalLibrary(metadataValue != QLatin1String("-- %%INSERT_APP_LIB_NAME%% --"));
|
||||||
|
service.setExternalLibraryName(metadataValue);
|
||||||
|
}
|
||||||
|
else if (metadataName == QLatin1String("android.app.arguments")) {
|
||||||
|
QString metadataValue = serviceMetadataElem.attribute(QLatin1String("android:value"));
|
||||||
|
service.setServiceArguments(metadataValue);
|
||||||
|
}
|
||||||
|
serviceMetadataElem = serviceMetadataElem.nextSiblingElement(QLatin1String("meta-data"));
|
||||||
|
}
|
||||||
|
services << service;
|
||||||
|
serviceElem = serviceElem.nextSiblingElement(QLatin1String("service"));
|
||||||
|
}
|
||||||
|
m_services->setServices(services);
|
||||||
|
|
||||||
m_iconButtons->loadIcons();
|
m_iconButtons->loadIcons();
|
||||||
|
|
||||||
m_stayClean = false;
|
m_stayClean = false;
|
||||||
@@ -988,13 +1064,19 @@ void AndroidManifestEditorWidget::parseApplication(QXmlStreamReader &reader, QXm
|
|||||||
|
|
||||||
while (!reader.atEnd()) {
|
while (!reader.atEnd()) {
|
||||||
if (reader.isEndElement()) {
|
if (reader.isEndElement()) {
|
||||||
|
parseNewServices(writer);
|
||||||
writer.writeCurrentToken(reader);
|
writer.writeCurrentToken(reader);
|
||||||
|
m_services->servicesSaved();
|
||||||
return;
|
return;
|
||||||
} else if (reader.isStartElement()) {
|
} else if (reader.isStartElement()) {
|
||||||
if (reader.name() == QLatin1String("activity"))
|
if (reader.name() == QLatin1String("activity"))
|
||||||
parseActivity(reader, writer);
|
parseActivity(reader, writer);
|
||||||
|
else if (reader.name() == QLatin1String("service"))
|
||||||
|
parseService(reader, writer);
|
||||||
else
|
else
|
||||||
parseUnknownElement(reader, writer);
|
parseUnknownElement(reader, writer);
|
||||||
|
} else if (reader.isWhitespace()) {
|
||||||
|
/* no copying of whitespace */
|
||||||
} else {
|
} else {
|
||||||
writer.writeCurrentToken(reader);
|
writer.writeCurrentToken(reader);
|
||||||
}
|
}
|
||||||
@@ -1003,6 +1085,144 @@ void AndroidManifestEditorWidget::parseApplication(QXmlStreamReader &reader, QXm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int findService(const QString &name, const QList<AndroidServiceData> &data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < data.size(); ++i) {
|
||||||
|
if (data[i].className() == name)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeServiceMetadataElement(const char *name,
|
||||||
|
const char *attributeName,
|
||||||
|
const char *value,
|
||||||
|
QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
writer.writeStartElement(QLatin1String("meta-data"));
|
||||||
|
writer.writeAttribute(QLatin1String("android:name"), QLatin1String(name));
|
||||||
|
writer.writeAttribute(QLatin1String(attributeName), QLatin1String(value));
|
||||||
|
writer.writeEndElement();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeServiceMetadataElement(const char *name,
|
||||||
|
const char *attributeName,
|
||||||
|
const QString &value,
|
||||||
|
QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
writer.writeStartElement(QLatin1String("meta-data"));
|
||||||
|
writer.writeAttribute(QLatin1String("android:name"), QLatin1String(name));
|
||||||
|
writer.writeAttribute(QLatin1String(attributeName), value);
|
||||||
|
writer.writeEndElement();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addServiceArgumentsAndLibName(const AndroidServiceData &service, QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
if (!service.isRunInExternalLibrary() && !service.serviceArguments().isEmpty())
|
||||||
|
writeServiceMetadataElement("android.app.arguments", "android:value", service.serviceArguments(), writer);
|
||||||
|
if (service.isRunInExternalLibrary() && !service.externalLibraryName().isEmpty())
|
||||||
|
writeServiceMetadataElement("android.app.lib_name", "android:value", service.externalLibraryName(), writer);
|
||||||
|
else
|
||||||
|
writeServiceMetadataElement("android.app.lib_name", "android:value", "-- %%INSERT_APP_LIB_NAME%% --", writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addServiceMetadata(QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
writeServiceMetadataElement("android.app.qt_sources_resource_id", "android:resource", "@array/qt_sources", writer);
|
||||||
|
writeServiceMetadataElement("android.app.repository", "android:value", "default", writer);
|
||||||
|
writeServiceMetadataElement("android.app.qt_libs_resource_id", "android:resource", "@array/qt_libs", writer);
|
||||||
|
writeServiceMetadataElement("android.app.bundled_libs_resource_id", "android:resource", "@array/bundled_libs", writer);
|
||||||
|
writeServiceMetadataElement("android.app.bundle_local_qt_libs", "android:value", "-- %%BUNDLE_LOCAL_QT_LIBS%% --", writer);
|
||||||
|
writeServiceMetadataElement("android.app.use_local_qt_libs", "android:value", "-- %%USE_LOCAL_QT_LIBS%% --", writer);
|
||||||
|
writeServiceMetadataElement("android.app.libs_prefix", "android:value", "/data/local/tmp/qt/", writer);
|
||||||
|
writeServiceMetadataElement("android.app.load_local_libs_resource_id", "android:resource", "@array/load_local_libs", writer);
|
||||||
|
writeServiceMetadataElement("android.app.load_local_jars", "android:value", "-- %%INSERT_LOCAL_JARS%% --", writer);
|
||||||
|
writeServiceMetadataElement("android.app.static_init_classes", "android:value", "-- %%INSERT_INIT_CLASSES%% --", writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidManifestEditorWidget::parseService(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
Q_ASSERT(reader.isStartElement());
|
||||||
|
const auto &services = m_services->services();
|
||||||
|
QString serviceName = reader.attributes().value(QLatin1String("android:name")).toString();
|
||||||
|
int serviceIndex = findService(serviceName, services);
|
||||||
|
const AndroidServiceData* serviceFound = (serviceIndex >= 0) ? &services[serviceIndex] : nullptr;
|
||||||
|
if (serviceFound && serviceFound->isValid()) {
|
||||||
|
writer.writeStartElement(reader.name().toString());
|
||||||
|
writer.writeAttribute(QLatin1String("android:name"), serviceFound->className());
|
||||||
|
if (serviceFound->isRunInExternalProcess())
|
||||||
|
writer.writeAttribute(QLatin1String("android:process"), serviceFound->externalProcessName());
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readNext();
|
||||||
|
|
||||||
|
bool bundleTagFound = false;
|
||||||
|
|
||||||
|
while (!reader.atEnd()) {
|
||||||
|
if (reader.isEndElement()) {
|
||||||
|
if (serviceFound && serviceFound->isValid()) {
|
||||||
|
addServiceArgumentsAndLibName(*serviceFound, writer);
|
||||||
|
if (serviceFound->isRunInExternalProcess() && !bundleTagFound)
|
||||||
|
addServiceMetadata(writer);
|
||||||
|
writer.writeCurrentToken(reader);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (reader.isStartElement()) {
|
||||||
|
if (serviceFound && !serviceFound->isValid())
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
else if (reader.name() == QLatin1String("meta-data")) {
|
||||||
|
QString metaTagName = reader.attributes().value(QLatin1String("android:name")).toString();
|
||||||
|
if (serviceFound) {
|
||||||
|
if (metaTagName == QLatin1String("android.app.bundle_local_qt_libs"))
|
||||||
|
bundleTagFound = true;
|
||||||
|
if (metaTagName == QLatin1String("android.app.arguments"))
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
else if (metaTagName == QLatin1String("android.app.lib_name"))
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
else if (serviceFound->isRunInExternalProcess()
|
||||||
|
|| metaTagName == QLatin1String("android.app.background_running"))
|
||||||
|
parseUnknownElement(reader, writer);
|
||||||
|
else
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
} else
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
} else
|
||||||
|
parseUnknownElement(reader, writer, true);
|
||||||
|
} else if (reader.isWhitespace()) {
|
||||||
|
/* no copying of whitespace */
|
||||||
|
} else {
|
||||||
|
if (serviceFound)
|
||||||
|
writer.writeCurrentToken(reader);
|
||||||
|
}
|
||||||
|
reader.readNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidManifestEditorWidget::parseNewServices(QXmlStreamWriter &writer)
|
||||||
|
{
|
||||||
|
const auto &services = m_services->services();
|
||||||
|
for (const auto &x : services) {
|
||||||
|
if (x.isNewService() && x.isValid()) {
|
||||||
|
writer.writeStartElement(QLatin1String("service"));
|
||||||
|
writer.writeAttribute(QLatin1String("android:name"), x.className());
|
||||||
|
if (x.isRunInExternalProcess()) {
|
||||||
|
writer.writeAttribute(QLatin1String("android:process"),
|
||||||
|
x.externalProcessName());
|
||||||
|
}
|
||||||
|
addServiceArgumentsAndLibName(x, writer);
|
||||||
|
if (x.isRunInExternalProcess())
|
||||||
|
addServiceMetadata(writer);
|
||||||
|
writer.writeStartElement(QLatin1String("meta-data"));
|
||||||
|
writer.writeAttribute(QLatin1String("android:name"), QLatin1String("android.app.background_running"));
|
||||||
|
writer.writeAttribute(QLatin1String("android:value"), QLatin1String("true"));
|
||||||
|
writer.writeEndElement();
|
||||||
|
writer.writeEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::parseActivity(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
void AndroidManifestEditorWidget::parseActivity(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
||||||
{
|
{
|
||||||
Q_ASSERT(reader.isStartElement());
|
Q_ASSERT(reader.isStartElement());
|
||||||
@@ -1180,20 +1400,24 @@ QString AndroidManifestEditorWidget::parseComment(QXmlStreamReader &reader, QXml
|
|||||||
return commentText;
|
return commentText;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
void AndroidManifestEditorWidget::parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer,
|
||||||
|
bool ignore)
|
||||||
{
|
{
|
||||||
Q_ASSERT(reader.isStartElement());
|
Q_ASSERT(reader.isStartElement());
|
||||||
writer.writeCurrentToken(reader);
|
if (!ignore)
|
||||||
|
writer.writeCurrentToken(reader);
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
|
|
||||||
while (!reader.atEnd()) {
|
while (!reader.atEnd()) {
|
||||||
if (reader.isEndElement()) {
|
if (reader.isEndElement()) {
|
||||||
writer.writeCurrentToken(reader);
|
if (!ignore)
|
||||||
|
writer.writeCurrentToken(reader);
|
||||||
return;
|
return;
|
||||||
} else if (reader.isStartElement()) {
|
} else if (reader.isStartElement()) {
|
||||||
parseUnknownElement(reader, writer);
|
parseUnknownElement(reader, writer, ignore);
|
||||||
} else {
|
} else {
|
||||||
writer.writeCurrentToken(reader);
|
if (!ignore)
|
||||||
|
writer.writeCurrentToken(reader);
|
||||||
}
|
}
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,7 @@ namespace Internal {
|
|||||||
class AndroidManifestEditor;
|
class AndroidManifestEditor;
|
||||||
class AndroidManifestEditorIconContainerWidget;
|
class AndroidManifestEditorIconContainerWidget;
|
||||||
class AndroidManifestEditorWidget;
|
class AndroidManifestEditorWidget;
|
||||||
|
class AndroidServiceWidget;
|
||||||
|
|
||||||
class PermissionsModel: public QAbstractListModel
|
class PermissionsModel: public QAbstractListModel
|
||||||
{
|
{
|
||||||
@@ -136,10 +137,15 @@ private:
|
|||||||
|
|
||||||
void updateInfoBar(const QString &errorMessage, int line, int column);
|
void updateInfoBar(const QString &errorMessage, int line, int column);
|
||||||
void hideInfoBar();
|
void hideInfoBar();
|
||||||
|
void setInvalidServiceInfo();
|
||||||
|
void clearInvalidServiceInfo();
|
||||||
|
|
||||||
void updateTargetComboBox();
|
void updateTargetComboBox();
|
||||||
|
|
||||||
void parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
void parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
void parseApplication(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
void parseApplication(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
|
void parseService(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
|
void parseNewServices(QXmlStreamWriter &writer);
|
||||||
void parseActivity(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
void parseActivity(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
bool parseMetaData(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
bool parseMetaData(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
void parseUsesSdk(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
void parseUsesSdk(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
@@ -147,7 +153,7 @@ private:
|
|||||||
QXmlStreamWriter &writer,
|
QXmlStreamWriter &writer,
|
||||||
const QSet<QString> &permissions);
|
const QSet<QString> &permissions);
|
||||||
QString parseComment(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
QString parseComment(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
||||||
void parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer);
|
void parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer, bool ignore=false);
|
||||||
|
|
||||||
bool m_dirty; // indicates that we need to call syncToEditor()
|
bool m_dirty; // indicates that we need to call syncToEditor()
|
||||||
bool m_stayClean;
|
bool m_stayClean;
|
||||||
@@ -178,6 +184,8 @@ private:
|
|||||||
QPushButton *m_removePermissionButton;
|
QPushButton *m_removePermissionButton;
|
||||||
QComboBox *m_permissionsComboBox;
|
QComboBox *m_permissionsComboBox;
|
||||||
|
|
||||||
|
// Services
|
||||||
|
AndroidServiceWidget *m_services;
|
||||||
QTimer m_timerParseCheck;
|
QTimer m_timerParseCheck;
|
||||||
TextEditor::TextEditorWidget *m_textEditorWidget;
|
TextEditor::TextEditorWidget *m_textEditorWidget;
|
||||||
AndroidManifestEditor *m_editor;
|
AndroidManifestEditor *m_editor;
|
||||||
|
410
src/plugins/android/androidservicewidget.cpp
Normal file
410
src/plugins/android/androidservicewidget.cpp
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "androidservicewidget.h"
|
||||||
|
#include "androidservicewidget_p.h"
|
||||||
|
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
bool AndroidServiceData::isValid() const
|
||||||
|
{
|
||||||
|
return !m_className.isEmpty()
|
||||||
|
&& (!m_isRunInExternalProcess || !m_externalProcessName.isEmpty())
|
||||||
|
&& (!m_isRunInExternalLibrary || !m_externalLibName.isEmpty())
|
||||||
|
&& (m_isRunInExternalLibrary || !m_serviceArguments.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setClassName(const QString &className)
|
||||||
|
{
|
||||||
|
m_className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidServiceData::className() const
|
||||||
|
{
|
||||||
|
return m_className;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setRunInExternalProcess(bool isRunInExternalProcess)
|
||||||
|
{
|
||||||
|
m_isRunInExternalProcess = isRunInExternalProcess;
|
||||||
|
if (!m_isRunInExternalProcess) {
|
||||||
|
m_isRunInExternalLibrary = false;
|
||||||
|
m_externalProcessName.clear();
|
||||||
|
m_externalLibName.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidServiceData::isRunInExternalProcess() const
|
||||||
|
{
|
||||||
|
return m_isRunInExternalProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setExternalProcessName(const QString &externalProcessName)
|
||||||
|
{
|
||||||
|
if (m_isRunInExternalProcess)
|
||||||
|
m_externalProcessName = externalProcessName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidServiceData::externalProcessName() const
|
||||||
|
{
|
||||||
|
return m_externalProcessName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setRunInExternalLibrary(bool isRunInExternalLibrary)
|
||||||
|
{
|
||||||
|
if (m_isRunInExternalProcess)
|
||||||
|
m_isRunInExternalLibrary = isRunInExternalLibrary;
|
||||||
|
if (!m_isRunInExternalLibrary)
|
||||||
|
m_externalLibName.clear();
|
||||||
|
else
|
||||||
|
m_serviceArguments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidServiceData::isRunInExternalLibrary() const
|
||||||
|
{
|
||||||
|
return m_isRunInExternalLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setExternalLibraryName(const QString &externalLibraryName)
|
||||||
|
{
|
||||||
|
if (m_isRunInExternalLibrary)
|
||||||
|
m_externalLibName = externalLibraryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidServiceData::externalLibraryName() const
|
||||||
|
{
|
||||||
|
return m_externalLibName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setServiceArguments(const QString &serviceArguments)
|
||||||
|
{
|
||||||
|
if (!m_isRunInExternalLibrary)
|
||||||
|
m_serviceArguments = serviceArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidServiceData::serviceArguments() const
|
||||||
|
{
|
||||||
|
return m_serviceArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceData::setNewService(bool isNewService)
|
||||||
|
{
|
||||||
|
m_isNewService = isNewService;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidServiceData::isNewService() const
|
||||||
|
{
|
||||||
|
return m_isNewService;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::AndroidServiceModel::setServices(const QList<AndroidServiceData> &androidServices)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_services = androidServices;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<AndroidServiceData> &AndroidServiceWidget::AndroidServiceModel::services()
|
||||||
|
{
|
||||||
|
return m_services;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::AndroidServiceModel::addService()
|
||||||
|
{
|
||||||
|
int rowIndex = m_services.size();
|
||||||
|
beginInsertRows(QModelIndex(), rowIndex, rowIndex);
|
||||||
|
AndroidServiceData service;
|
||||||
|
service.setNewService(true);
|
||||||
|
m_services.push_back(service);
|
||||||
|
endInsertRows();
|
||||||
|
invalidDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::AndroidServiceModel::removeService(int row)
|
||||||
|
{
|
||||||
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
m_services.removeAt(row);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::AndroidServiceModel::servicesSaved()
|
||||||
|
{
|
||||||
|
for (auto && x : m_services)
|
||||||
|
x.setNewService(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AndroidServiceWidget::AndroidServiceModel::rowCount(const QModelIndex &/*parent*/) const
|
||||||
|
{
|
||||||
|
return m_services.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AndroidServiceWidget::AndroidServiceModel::columnCount(const QModelIndex &/*parent*/) const
|
||||||
|
{
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags AndroidServiceWidget::AndroidServiceModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.column() == 0)
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||||
|
else if (index.column() == 1)
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
|
||||||
|
else if (index.column() == 2 && index.row() <= m_services.count()) {
|
||||||
|
if (m_services[index.row()].isRunInExternalProcess())
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||||
|
return Qt::ItemIsSelectable;
|
||||||
|
} else if (index.column() == 3 && index.row() <= m_services.count()) {
|
||||||
|
if (m_services[index.row()].isRunInExternalProcess())
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
|
||||||
|
return Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
|
||||||
|
} else if (index.column() == 4 && index.row() <= m_services.count()) {
|
||||||
|
if (m_services[index.row()].isRunInExternalLibrary())
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||||
|
return Qt::ItemIsSelectable;
|
||||||
|
} else if (index.column() == 5 && index.row() <= m_services.count()) {
|
||||||
|
if (!m_services[index.row()].isRunInExternalLibrary())
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||||
|
return Qt::ItemIsSelectable;
|
||||||
|
}
|
||||||
|
return Qt::ItemIsSelectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AndroidServiceWidget::AndroidServiceModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::ToolTipRole && orientation == Qt::Horizontal) {
|
||||||
|
if (section == 0)
|
||||||
|
return tr("The name of the class implementing the service");
|
||||||
|
else if (section == 1)
|
||||||
|
return tr("Checked if the service is run in an external process");
|
||||||
|
else if (section == 2)
|
||||||
|
return tr("The name of the external process.\n"
|
||||||
|
"Prefix with : if the process is private, use a lowercase name if the process is global.");
|
||||||
|
else if (section == 3)
|
||||||
|
return tr("Checked if the service is in a separate dynamic library");
|
||||||
|
else if (section == 4)
|
||||||
|
return tr("The name of the separate dynamic library");
|
||||||
|
else if (section == 5)
|
||||||
|
return tr("The arguments for telling the app to run the service instead of the main activity");
|
||||||
|
} else if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
||||||
|
if (section == 0)
|
||||||
|
return tr("Service class name");
|
||||||
|
else if (section == 1)
|
||||||
|
return tr("Run in external process");
|
||||||
|
else if (section == 2)
|
||||||
|
return tr("Process name");
|
||||||
|
else if (section == 3)
|
||||||
|
return tr("Run in external library");
|
||||||
|
else if (section == 4)
|
||||||
|
return tr("Library name");
|
||||||
|
else if (section == 5)
|
||||||
|
return tr("Service arguments");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AndroidServiceWidget::AndroidServiceModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!(index.row() >= 0 && index.row() < m_services.count()))
|
||||||
|
return {};
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
if (index.column() == 3)
|
||||||
|
return m_services[index.row()].isRunInExternalLibrary() ? Qt::Checked : Qt::Unchecked;
|
||||||
|
else if (index.column() == 1 && index.row() <= m_services.count())
|
||||||
|
return m_services[index.row()].isRunInExternalProcess() ? Qt::Checked : Qt::Unchecked;
|
||||||
|
return QVariant();
|
||||||
|
} else if (role == Qt::DisplayRole) {
|
||||||
|
if (index.column() == 0)
|
||||||
|
return m_services[index.row()].className();
|
||||||
|
else if (index.column() == 1)
|
||||||
|
return tr("Run in external process");
|
||||||
|
else if (index.column() == 2)
|
||||||
|
return m_services[index.row()].externalProcessName();
|
||||||
|
else if (index.column() == 3)
|
||||||
|
return tr("Run in external library");
|
||||||
|
else if (index.column() == 4)
|
||||||
|
return m_services[index.row()].externalLibraryName();
|
||||||
|
else if (index.column() == 5)
|
||||||
|
return m_services[index.row()].serviceArguments();
|
||||||
|
} else if (role == Qt::ToolTipRole) {
|
||||||
|
if (index.column() == 0 && m_services[index.row()].className().isEmpty())
|
||||||
|
return tr("The class name must be set");
|
||||||
|
else if (index.column() == 2 && m_services[index.row()].isRunInExternalProcess())
|
||||||
|
return tr("The process name must be set for a service run in an external process");
|
||||||
|
else if (index.column() == 4 && m_services[index.row()].isRunInExternalLibrary())
|
||||||
|
return tr("The library name must be set for a service run in an external library");
|
||||||
|
else if (index.column() == 5 && !m_services[index.row()].isRunInExternalLibrary())
|
||||||
|
return tr("The service arguments must be set for a service not run in an external library");
|
||||||
|
} else if (role == Qt::EditRole) {
|
||||||
|
if (index.column() == 0)
|
||||||
|
return m_services[index.row()].className();
|
||||||
|
else if (index.column() == 2)
|
||||||
|
return m_services[index.row()].externalProcessName();
|
||||||
|
else if (index.column() == 4)
|
||||||
|
return m_services[index.row()].externalLibraryName();
|
||||||
|
else if (index.column() == 5)
|
||||||
|
return m_services[index.row()].serviceArguments();
|
||||||
|
} else if (role == Qt::DecorationRole) {
|
||||||
|
if (index.column() == 0) {
|
||||||
|
if (m_services[index.row()].className().isEmpty())
|
||||||
|
return Utils::Icons::WARNING.icon();
|
||||||
|
} else if (index.column() == 2) {
|
||||||
|
if (m_services[index.row()].isRunInExternalProcess()
|
||||||
|
&& m_services[index.row()].externalProcessName().isEmpty())
|
||||||
|
return Utils::Icons::WARNING.icon();
|
||||||
|
} else if (index.column() == 4) {
|
||||||
|
if (m_services[index.row()].isRunInExternalLibrary()
|
||||||
|
&& m_services[index.row()].externalLibraryName().isEmpty())
|
||||||
|
return Utils::Icons::WARNING.icon();
|
||||||
|
} else if (index.column() == 5) {
|
||||||
|
if (!m_services[index.row()].isRunInExternalLibrary()
|
||||||
|
&& m_services[index.row()].serviceArguments().isEmpty())
|
||||||
|
return Utils::Icons::WARNING.icon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidServiceWidget::AndroidServiceModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if (!(index.row() >= 0 && index.row() < m_services.count()))
|
||||||
|
return {};
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
if (index.column() == 1)
|
||||||
|
m_services[index.row()].setRunInExternalProcess((value == Qt::Checked) ? true : false);
|
||||||
|
else if (index.column() == 3)
|
||||||
|
m_services[index.row()].setRunInExternalLibrary((value == Qt::Checked) ? true : false);
|
||||||
|
dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 5));
|
||||||
|
if (m_services[index.row()].isValid())
|
||||||
|
validDataChanged();
|
||||||
|
else
|
||||||
|
invalidDataChanged();
|
||||||
|
} else if (role == Qt::EditRole) {
|
||||||
|
if (index.column() == 0) {
|
||||||
|
QString className = value.toString();
|
||||||
|
if (!className.isEmpty() && className[0] != QChar('.'))
|
||||||
|
className.push_front(QChar('.'));
|
||||||
|
m_services[index.row()].setClassName(className);
|
||||||
|
m_services[index.row()].setNewService(true);
|
||||||
|
} else if (index.column() == 2) {
|
||||||
|
m_services[index.row()].setExternalProcessName(value.toString());
|
||||||
|
} else if (index.column() == 4) {
|
||||||
|
m_services[index.row()].setExternalLibraryName(value.toString());
|
||||||
|
} else if (index.column() == 5) {
|
||||||
|
m_services[index.row()].setServiceArguments(value.toString());
|
||||||
|
}
|
||||||
|
dataChanged(index, index);
|
||||||
|
if (m_services[index.row()].isValid())
|
||||||
|
validDataChanged();
|
||||||
|
else
|
||||||
|
invalidDataChanged();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidServiceWidget::AndroidServiceWidget(QWidget *parent) : QWidget(parent),
|
||||||
|
m_model(new AndroidServiceModel), m_tableView(new QTableView(this))
|
||||||
|
{
|
||||||
|
m_tableView->setModel(m_model.data());
|
||||||
|
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
QSizePolicy sizePolicy;
|
||||||
|
sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding);
|
||||||
|
m_tableView->setSizePolicy(sizePolicy);
|
||||||
|
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
auto layout = new QHBoxLayout(this);
|
||||||
|
layout->addWidget(m_tableView, 1);
|
||||||
|
auto buttonLayout = new QGridLayout();
|
||||||
|
auto addButton = new QPushButton(this);
|
||||||
|
addButton->setText(tr("Add"));
|
||||||
|
buttonLayout->addWidget(addButton, 0, 0);
|
||||||
|
m_removeButton = new QPushButton(this);
|
||||||
|
m_removeButton->setText(tr("Remove"));
|
||||||
|
m_removeButton->setEnabled(false);
|
||||||
|
buttonLayout->addWidget(m_removeButton, 1, 0);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
layout->setAlignment(buttonLayout, Qt::AlignTop);
|
||||||
|
connect(addButton, &QAbstractButton::clicked,
|
||||||
|
this, &AndroidServiceWidget::addService);
|
||||||
|
connect(m_removeButton, &QAbstractButton::clicked,
|
||||||
|
this, &AndroidServiceWidget::removeService);
|
||||||
|
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
[this](const QItemSelection &selected, const QItemSelection &/*deselected*/) {
|
||||||
|
if (!selected.isEmpty())
|
||||||
|
m_removeButton->setEnabled(true);
|
||||||
|
});
|
||||||
|
connect(m_model.data(), &AndroidServiceWidget::AndroidServiceModel::validDataChanged,
|
||||||
|
[this] {servicesModified();});
|
||||||
|
connect(m_model.data(), &AndroidServiceWidget::AndroidServiceModel::invalidDataChanged,
|
||||||
|
[this] {servicesInvalid();});
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidServiceWidget::~AndroidServiceWidget()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::setServices(const QList<AndroidServiceData> &androidServices)
|
||||||
|
{
|
||||||
|
m_removeButton->setEnabled(false);
|
||||||
|
m_model->setServices(androidServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<AndroidServiceData> &AndroidServiceWidget::services()
|
||||||
|
{
|
||||||
|
return m_model->services();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::servicesSaved()
|
||||||
|
{
|
||||||
|
m_model->servicesSaved();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::addService()
|
||||||
|
{
|
||||||
|
m_model->addService();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidServiceWidget::removeService()
|
||||||
|
{
|
||||||
|
auto selections = m_tableView->selectionModel()->selectedRows();
|
||||||
|
for (const auto &x : selections) {
|
||||||
|
m_model->removeService(x.row());
|
||||||
|
m_removeButton->setEnabled(false);
|
||||||
|
servicesModified();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
89
src/plugins/android/androidservicewidget.h
Normal file
89
src/plugins/android/androidservicewidget.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
struct AndroidServiceData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool isValid() const;
|
||||||
|
void setClassName(const QString &className);
|
||||||
|
QString className() const;
|
||||||
|
void setRunInExternalProcess(bool isRunInExternalProcess);
|
||||||
|
bool isRunInExternalProcess() const;
|
||||||
|
void setExternalProcessName(const QString &externalProcessName);
|
||||||
|
QString externalProcessName() const;
|
||||||
|
void setRunInExternalLibrary(bool isRunInExternalLibrary);
|
||||||
|
bool isRunInExternalLibrary() const ;
|
||||||
|
void setExternalLibraryName(const QString &externalLibraryName);
|
||||||
|
QString externalLibraryName() const;
|
||||||
|
void setServiceArguments(const QString &serviceArguments);
|
||||||
|
QString serviceArguments() const;
|
||||||
|
void setNewService(bool isNewService);
|
||||||
|
bool isNewService() const;
|
||||||
|
private:
|
||||||
|
QString m_className;
|
||||||
|
bool m_isRunInExternalProcess = false;
|
||||||
|
QString m_externalProcessName;
|
||||||
|
bool m_isRunInExternalLibrary = false;
|
||||||
|
QString m_externalLibName;
|
||||||
|
QString m_serviceArguments;
|
||||||
|
bool m_isNewService = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AndroidServiceWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AndroidServiceWidget(QWidget *parent = nullptr);
|
||||||
|
~AndroidServiceWidget();
|
||||||
|
void setServices(const QList<AndroidServiceData> &androidServices);
|
||||||
|
const QList<AndroidServiceData> &services();
|
||||||
|
void servicesSaved();
|
||||||
|
private:
|
||||||
|
void addService();
|
||||||
|
void removeService();
|
||||||
|
signals:
|
||||||
|
void servicesModified();
|
||||||
|
void servicesInvalid();
|
||||||
|
private:
|
||||||
|
class AndroidServiceModel;
|
||||||
|
QScopedPointer<AndroidServiceModel> m_model;
|
||||||
|
QTableView *m_tableView;
|
||||||
|
QPushButton *m_removeButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
59
src/plugins/android/androidservicewidget_p.h
Normal file
59
src/plugins/android/androidservicewidget_p.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "androidservicewidget.h"
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class AndroidServiceWidget::AndroidServiceModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
void setServices(const QList<AndroidServiceData> &androidServices);
|
||||||
|
const QList<AndroidServiceData> &services();
|
||||||
|
void addService();
|
||||||
|
void removeService(int row);
|
||||||
|
void servicesSaved();
|
||||||
|
signals:
|
||||||
|
void validDataChanged();
|
||||||
|
void invalidDataChanged();
|
||||||
|
private:
|
||||||
|
int rowCount(const QModelIndex &/*parent*/ = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
private:
|
||||||
|
QList<AndroidServiceData> m_services;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
Reference in New Issue
Block a user