Android: Android SDK manager user interface

Task-number: QTCREATORBUG-18978
Change-Id: I421ea66fcd4f3cf38e6cfd3be58a35b3f9204c6f
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
Vikas Pachdha
2017-09-18 13:48:00 +02:00
parent 4b1429de55
commit 476b133e91
10 changed files with 1381 additions and 140 deletions

View File

@@ -0,0 +1,316 @@
/****************************************************************************
**
** Copyright (C) 2017 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 "androidsdkmodel.h"
#include "androidmanager.h"
#include "androidsdkmanager.h"
#include "utils/algorithm.h"
#include "utils/qtcassert.h"
#include "utils/utilsicons.h"
#include <QIcon>
namespace Android {
namespace Internal {
const int packageColCount = 4;
AndroidSdkModel::AndroidSdkModel(AndroidSdkManager *sdkManager, QObject *parent)
: QAbstractItemModel(parent),
m_sdkManager(sdkManager)
{
QTC_CHECK(m_sdkManager);
connect(m_sdkManager, &AndroidSdkManager::packageReloadBegin, [this]() {
clearContainers();
beginResetModel();
});
connect(m_sdkManager, &AndroidSdkManager::packageReloadFinished, [this]() {
refreshData();
endResetModel();
});
}
QVariant AndroidSdkModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_UNUSED(orientation)
QVariant data;
if (role == Qt::DisplayRole) {
switch (section) {
case packageNameColumn:
data = tr("Package");
break;
case packageRevisionColumn:
data = tr("Revision");
break;
case apiLevelColumn:
data = tr("API");
break;
case operationColumn:
data = tr("Operation");
break;
default:
break;
}
}
return data;
}
QModelIndex AndroidSdkModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid()) {
// Packages under top items.
if (parent.row() == 0) {
// Tools packages
if (row < m_tools.count())
return createIndex(row, column, const_cast<AndroidSdkPackage *>(m_tools.at(row)));
} else if (parent.row() < m_sdkPlatforms.count() + 1) {
// Platform packages
const SdkPlatform *sdkPlatform = m_sdkPlatforms.at(parent.row() - 1);
SystemImageList images = sdkPlatform->systemImages(AndroidSdkPackage::AnyValidState);
if (row < images.count() + 1) {
if (row == 0)
return createIndex(row, column, const_cast<SdkPlatform *>(sdkPlatform));
else
return createIndex(row, column, images.at(row - 1));
}
}
} else if (row < m_sdkPlatforms.count() + 1) {
return createIndex(row, column); // Top level items (Tools & platform)
}
return QModelIndex();
}
QModelIndex AndroidSdkModel::parent(const QModelIndex &index) const
{
void *ip = index.internalPointer();
if (!ip)
return QModelIndex();
auto package = static_cast<const AndroidSdkPackage *>(ip);
if (package->type() == AndroidSdkPackage::SystemImagePackage) {
auto image = static_cast<const SystemImage *>(package);
int row = m_sdkPlatforms.indexOf(const_cast<SdkPlatform *>(image->platform()));
if (row > -1)
return createIndex(row + 1, 0);
} else if (package->type() == AndroidSdkPackage::SdkPlatformPackage) {
int row = m_sdkPlatforms.indexOf(static_cast<const SdkPlatform *>(package));
if (row > -1)
return createIndex(row + 1, 0);
} else {
return createIndex(0, 0); // Tools
}
return QModelIndex();
}
int AndroidSdkModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return m_sdkPlatforms.count() + 1;
if (!parent.internalPointer()) {
if (parent.row() == 0) // Tools
return m_tools.count();
if (parent.row() <= m_sdkPlatforms.count()) {
const SdkPlatform * platform = m_sdkPlatforms.at(parent.row() - 1);
return platform->systemImages(AndroidSdkPackage::AnyValidState).count() + 1;
}
}
return 0;
}
int AndroidSdkModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return packageColCount;
}
QVariant AndroidSdkModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (!index.parent().isValid()) {
// Top level tools
if (index.row() == 0) {
return role == Qt::DisplayRole && index.column() == packageNameColumn ?
QVariant(tr("Tools")) : QVariant();
}
// Top level platforms
const SdkPlatform *platform = m_sdkPlatforms.at(index.row() - 1);
if (role == Qt::DisplayRole) {
if (index.column() == packageNameColumn) {
QString androidName = AndroidManager::androidNameForApiLevel(platform->apiLevel());
if (androidName.startsWith("Android"))
return androidName;
else
return platform->displayText();
} else if (index.column() == apiLevelColumn) {
return platform->apiLevel();
}
}
return QVariant();
}
auto p = static_cast<const AndroidSdkPackage *>(index.internalPointer());
QString apiLevelStr;
if (p->type() == AndroidSdkPackage::SdkPlatformPackage)
apiLevelStr = QString::number(static_cast<const SdkPlatform *>(p)->apiLevel());
if (p->type() == AndroidSdkPackage::SystemImagePackage)
apiLevelStr = QString::number(static_cast<const SystemImage *>(p)->platform()->apiLevel());
if (role == Qt::DisplayRole) {
switch (index.column()) {
case packageNameColumn:
return p->type() == AndroidSdkPackage::SdkPlatformPackage ?
tr("SDK Platform") : p->displayText();
case packageRevisionColumn:
return p->revision().toString();
case apiLevelColumn:
return apiLevelStr;
case operationColumn:
if (p->type() == AndroidSdkPackage::SdkToolsPackage &&
p->state() == AndroidSdkPackage::Installed) {
return tr("Update Only");
} else {
return p->state() == AndroidSdkPackage::Installed ? tr("Uninstall") : tr("Install");
}
default:
break;
}
}
if (role == Qt::DecorationRole && index.column() == packageNameColumn) {
return p->state() == AndroidSdkPackage::Installed ? Utils::Icons::OK.icon() :
Utils::Icons::EMPTY16.icon();
}
if (role == Qt::CheckStateRole && index.column() == operationColumn )
return m_changeState.contains(p) ? Qt::Checked : Qt::Unchecked;
if (role == Qt::ToolTipRole)
return QString("%1 - (%2)").arg(p->descriptionText()).arg(p->sdkStylePath());
if (role == PackageTypeRole)
return p->type();
if (role == PackageStateRole)
return p->state();
return QVariant();
}
QHash<int, QByteArray> AndroidSdkModel::roleNames() const
{
QHash <int, QByteArray> roles;
roles[PackageTypeRole] = "PackageRole";
roles[PackageStateRole] = "PackageState";
return roles;
}
Qt::ItemFlags AndroidSdkModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags f = QAbstractItemModel::flags(index);
if (index.column() == operationColumn)
f |= Qt::ItemIsUserCheckable;
void *ip = index.internalPointer();
if (ip && index.column() == operationColumn) {
auto package = static_cast<const AndroidSdkPackage *>(ip);
if (package->state() == AndroidSdkPackage::Installed &&
package->type() == AndroidSdkPackage::SdkToolsPackage) {
f &= ~Qt::ItemIsEnabled;
}
}
return f;
}
bool AndroidSdkModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
void *ip = index.internalPointer();
if (ip && role == Qt::CheckStateRole) {
auto package = static_cast<const AndroidSdkPackage *>(ip);
if (value.toInt() == Qt::Checked) {
m_changeState << package;
emit dataChanged(index, index, {Qt::CheckStateRole});
} else if (m_changeState.remove(package)) {
emit dataChanged(index, index, {Qt::CheckStateRole});
}
return true;
}
return false;
}
QList<const AndroidSdkPackage *> AndroidSdkModel::userSelection() const
{
return m_changeState.toList();
}
void AndroidSdkModel::resetSelection()
{
beginResetModel();
m_changeState.clear();
endResetModel();
}
void AndroidSdkModel::clearContainers()
{
m_sdkPlatforms.clear();
m_tools.clear();
m_changeState.clear();
}
void AndroidSdkModel::refreshData()
{
clearContainers();
for (AndroidSdkPackage *p : m_sdkManager->allSdkPackages()) {
if (p->type() == AndroidSdkPackage::SdkPlatformPackage)
m_sdkPlatforms << static_cast<SdkPlatform *>(p);
else
m_tools << p;
}
Utils::sort(m_sdkPlatforms, [](const SdkPlatform *p1, const SdkPlatform *p2) {
return p1->apiLevel() > p2->apiLevel();
});
Utils::sort(m_tools, [](const AndroidSdkPackage *p1, const AndroidSdkPackage *p2) {
if (p1->state() == p2->state()) {
if (p1->type() == p2->type())
return p1->revision() > p2->revision();
else
return p1->type() > p2->type();
} else {
return p1->state() < p2->state();
}
});
}
} // namespace Internal
} // namespace Android