From 17dfe02d2826e7bb8154f672599978af66844db4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 05:53:18 -0400 Subject: [PATCH 01/22] [3rdparty] Remove QJsonModel and support --- 3rdparty/qjsonitem.cpp | 140 ---------------------------- 3rdparty/qjsonitem.h | 46 --------- 3rdparty/qjsonmodel.cpp | 186 ------------------------------------- 3rdparty/qjsonmodel.h | 42 --------- LICENSES/GPLv3+-QJsonModel | 18 ---- 5 files changed, 432 deletions(-) delete mode 100644 3rdparty/qjsonitem.cpp delete mode 100644 3rdparty/qjsonitem.h delete mode 100644 3rdparty/qjsonmodel.cpp delete mode 100644 3rdparty/qjsonmodel.h delete mode 100644 LICENSES/GPLv3+-QJsonModel diff --git a/3rdparty/qjsonitem.cpp b/3rdparty/qjsonitem.cpp deleted file mode 100644 index 6bb1fa4c7..000000000 --- a/3rdparty/qjsonitem.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - QJsonModel 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QJsonModel. If not, see . - -**********************************************/ - -#include "qjsonitem.h" - -QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) - : mParent( parent ) - , mType( QJsonValue::Type::Null ) -{ -} - -QJsonTreeItem::~QJsonTreeItem() -{ - qDeleteAll(mChilds); - -} - -void QJsonTreeItem::appendChild(QJsonTreeItem *item) -{ - mChilds.append(item); -} - -QJsonTreeItem *QJsonTreeItem::child(int row) -{ - return mChilds.value(row); -} - -QJsonTreeItem *QJsonTreeItem::parent() -{ - return mParent; -} - -int QJsonTreeItem::childCount() const -{ - return mChilds.count(); -} - -int QJsonTreeItem::row() const -{ - if (mParent) - return mParent->mChilds.indexOf(const_cast(this)); - - return 0; -} - -void QJsonTreeItem::setKey(const QString &key) -{ - mKey = key; -} - -void QJsonTreeItem::setValue(const QString &value) -{ - mValue = value; -} - -void QJsonTreeItem::setType(const QJsonValue::Type &type) -{ - mType = type; -} - -QString QJsonTreeItem::key() const -{ - return mKey; -} - -QString QJsonTreeItem::value() const -{ - return mValue; -} - -QJsonValue::Type QJsonTreeItem::type() const -{ - return mType; -} - -QJsonTreeItem* QJsonTreeItem::load(const QJsonValue& value, QJsonTreeItem* parent) -{ - - - QJsonTreeItem * rootItem = new QJsonTreeItem(parent); - rootItem->setKey("root"); - - if ( value.isObject()) - { - - //Get all QJsonValue childs - foreach (QString key , value.toObject().keys()){ - QJsonValue v = value.toObject().value(key); - QJsonTreeItem * child = load(v,rootItem); - child->setKey(key); - child->setType(v.type()); - rootItem->appendChild(child); - - } - - } - - else if ( value.isArray()) - { - //Get all QJsonValue childs - int index = 0; - foreach (QJsonValue v , value.toArray()){ - - QJsonTreeItem * child = load(v,rootItem); - child->setKey(QString::number(index)); - child->setType(v.type()); - rootItem->appendChild(child); - ++index; - } - } - else - { - rootItem->setValue(value.toVariant().toString()); - rootItem->setType(value.type()); - } - - return rootItem; -} - diff --git a/3rdparty/qjsonitem.h b/3rdparty/qjsonitem.h deleted file mode 100644 index 137c59000..000000000 --- a/3rdparty/qjsonitem.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -#ifndef JSONITEM_H -#define JSONITEM_H -#include -#include -#include -#include -class QJsonTreeItem -{ -public: - QJsonTreeItem(QJsonTreeItem * parent = nullptr); - ~QJsonTreeItem(); - void appendChild(QJsonTreeItem * item); - QJsonTreeItem *child(int row); - QJsonTreeItem *parent(); - int childCount() const; - int row() const; - void setKey(const QString& key); - void setValue(const QString& value); - void setType(const QJsonValue::Type& type); - QString key() const; - QString value() const; - QJsonValue::Type type() const; - - - static QJsonTreeItem* load(const QJsonValue& value, QJsonTreeItem * parent = nullptr); - -protected: - - -private: - QString mKey; - QString mValue; - QJsonValue::Type mType; - - QList mChilds; - QJsonTreeItem * mParent; - - -}; - -#endif // JSONITEM_H diff --git a/3rdparty/qjsonmodel.cpp b/3rdparty/qjsonmodel.cpp deleted file mode 100644 index 020d27e42..000000000 --- a/3rdparty/qjsonmodel.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - QJsonModel 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QJsonModel. If not, see . - -**********************************************/ - -#include "qjsonmodel.h" -#include -#include -#include -#include -#include -#include - -QJsonModel::QJsonModel(QObject *parent) : - QAbstractItemModel(parent) - , mRootItem( new QJsonTreeItem ) -{ - mHeaders.append("key"); - mHeaders.append("value"); - - -} - -QJsonModel::~QJsonModel() -{ - delete mRootItem; -} - -bool QJsonModel::load(const QString &fileName) -{ - QFile file(fileName); - bool success = false; - if (file.open(QIODevice::ReadOnly)) { - success = load(&file); - file.close(); - } - else success = false; - - return success; -} - -bool QJsonModel::load(QIODevice *device) -{ - return loadJson(device->readAll()); -} - -bool QJsonModel::loadJson(const QByteArray &json) -{ - mDocument = QJsonDocument::fromJson(json); - - if (!mDocument.isNull()) - { - beginResetModel(); - delete mRootItem; - if (mDocument.isArray()) { - mRootItem = QJsonTreeItem::load(QJsonValue(mDocument.array())); - } else { - mRootItem = QJsonTreeItem::load(QJsonValue(mDocument.object())); - } - endResetModel(); - return true; - } - return false; -} - - -QVariant QJsonModel::data(const QModelIndex &index, int role) const -{ - - if (!index.isValid()) - return QVariant(); - - - QJsonTreeItem *item = static_cast(index.internalPointer()); - - - if ((role == Qt::DecorationRole) && (index.column() == 0)){ - - return mTypeIcons.value(item->type()); - } - - - if (role == Qt::DisplayRole) { - - if (index.column() == 0) - return QString("%1").arg(item->key()); - - if (index.column() == 1) - return QString("%1").arg(item->value()); - } - - - - return QVariant(); - -} - -QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - - return mHeaders.value(section); - } - else - return QVariant(); -} - -QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - QJsonTreeItem *parentItem; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - QJsonTreeItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); -} - -QModelIndex QJsonModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - QJsonTreeItem *childItem = static_cast(index.internalPointer()); - QJsonTreeItem *parentItem = childItem->parent(); - - if (parentItem == mRootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int QJsonModel::rowCount(const QModelIndex &parent) const -{ - QJsonTreeItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -int QJsonModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return 2; -} - -void QJsonModel::setIcon(const QJsonValue::Type &type, const QIcon &icon) -{ - mTypeIcons.insert(type,icon); -} diff --git a/3rdparty/qjsonmodel.h b/3rdparty/qjsonmodel.h deleted file mode 100644 index 32c062ba8..000000000 --- a/3rdparty/qjsonmodel.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -#ifndef QJSONMODEL_H -#define QJSONMODEL_H - -#include -#include "qjsonitem.h" -#include -#include -#include -class QJsonModel : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit QJsonModel(QObject *parent = nullptr); - ~QJsonModel(); - bool load(const QString& fileName); - bool load(QIODevice * device); - bool loadJson(const QByteArray& json); - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - void setIcon(const QJsonValue::Type& type, const QIcon& icon); - - - -private: - QJsonTreeItem * mRootItem; - QJsonDocument mDocument; - QStringList mHeaders; - QHash mTypeIcons; - - -}; - -#endif // QJSONMODEL_H diff --git a/LICENSES/GPLv3+-QJsonModel b/LICENSES/GPLv3+-QJsonModel deleted file mode 100644 index 8a8e272c0..000000000 --- a/LICENSES/GPLv3+-QJsonModel +++ /dev/null @@ -1,18 +0,0 @@ -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - QJsonModel 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QJsonModel. If not, see . - -**********************************************/ From 695e16bb87ae95313ceed206be98df2fd2b25f00 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:21:07 -0400 Subject: [PATCH 02/22] [libcalamaresui] Drop QJsonModel from the library --- src/libcalamaresui/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 04565206e..89a50e2ec 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -18,9 +18,6 @@ set( calamaresui_SOURCES utils/ImageRegistry.cpp utils/Paste.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/qjsonmodel.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/qjsonitem.cpp - viewpages/BlankViewStep.cpp viewpages/ViewStep.cpp From 419329ee494faeeff16d6ba08baca4ce75d3bc00 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:27:13 -0400 Subject: [PATCH 03/22] [libcalamares] Remove friend, add accessor, make includes explicit --- src/libcalamares/GlobalStorage.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h index 6fdb43fa0..b070e23f6 100644 --- a/src/libcalamares/GlobalStorage.h +++ b/src/libcalamares/GlobalStorage.h @@ -22,6 +22,8 @@ #include "CalamaresConfig.h" +#include +#include #include #ifdef WITH_PYTHON @@ -87,13 +89,19 @@ public: /// @brief reads settings from the given filename bool loadYaml( const QString& filename ); + /** @brief Get internal mapping as a constant object + * + * Note that the VariantMap underneath may change, because + * it's not constant in itself. Connect to the changed() + * signal for notifications. + */ + const QVariantMap& data() const { return m; } + signals: void changed(); private: QVariantMap m; - - friend DebugWindow; }; } // namespace Calamares From 85d28af1e20768c8dd99cfa8acd424f6d7bcc3d2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:34:38 -0400 Subject: [PATCH 04/22] [libcalamaresui] Don't include QJsonModel --- src/libcalamaresui/utils/DebugWindow.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcalamaresui/utils/DebugWindow.cpp b/src/libcalamaresui/utils/DebugWindow.cpp index 094511be4..237b8a7ed 100644 --- a/src/libcalamaresui/utils/DebugWindow.cpp +++ b/src/libcalamaresui/utils/DebugWindow.cpp @@ -30,8 +30,6 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" -#include "3rdparty/qjsonmodel.h" - #ifdef WITH_PYTHONQT #include "ViewManager.h" #include "viewpages/PythonQtViewStep.h" @@ -39,10 +37,10 @@ #include #endif -#include #include #include #include +#include /** * @brief crash makes Calamares crash immediately. From e31a498c9b70abebe50bdeaeec661545eab4bc40 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:35:40 -0400 Subject: [PATCH 05/22] [calamares] Move DebugWindow - This is a fairly specialized class, for use only in the whole-application where it ties in with the module system. Move it to the application directory and slim down the UI library. - Include it from the new location. - Add UIC to Calamares (the application) because there's now a designer-based widget in it. --- src/calamares/CMakeLists.txt | 3 +++ src/calamares/CalamaresWindow.cpp | 2 +- src/{libcalamaresui/utils => calamares}/DebugWindow.cpp | 0 src/{libcalamaresui/utils => calamares}/DebugWindow.h | 0 src/{libcalamaresui/utils => calamares}/DebugWindow.ui | 0 src/libcalamaresui/CMakeLists.txt | 6 ------ 6 files changed, 4 insertions(+), 7 deletions(-) rename src/{libcalamaresui/utils => calamares}/DebugWindow.cpp (100%) rename src/{libcalamaresui/utils => calamares}/DebugWindow.h (100%) rename src/{libcalamaresui/utils => calamares}/DebugWindow.ui (100%) diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 5dbf137bb..92521f17a 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -5,6 +5,8 @@ set( calamaresSources CalamaresApplication.cpp CalamaresWindow.cpp + DebugWindow.cpp + progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeItem.cpp progresstree/ProgressTreeModel.cpp @@ -35,6 +37,7 @@ set_target_properties(calamares_bin RUNTIME_OUTPUT_NAME calamares ) calamares_automoc( calamares_bin ) +calamares_autouic( calamares_bin ) target_link_libraries( calamares_bin PRIVATE diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index d80b6cb67..68f29ef18 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -26,7 +26,7 @@ #include "ViewManager.h" #include "progresstree/ProgressTreeView.h" #include "utils/CalamaresUtilsGui.h" -#include "utils/DebugWindow.h" +#include "DebugWindow.h" #include "utils/Logger.h" #include "utils/Retranslator.h" diff --git a/src/libcalamaresui/utils/DebugWindow.cpp b/src/calamares/DebugWindow.cpp similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.cpp rename to src/calamares/DebugWindow.cpp diff --git a/src/libcalamaresui/utils/DebugWindow.h b/src/calamares/DebugWindow.h similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.h rename to src/calamares/DebugWindow.h diff --git a/src/libcalamaresui/utils/DebugWindow.ui b/src/calamares/DebugWindow.ui similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.ui rename to src/calamares/DebugWindow.ui diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 89a50e2ec..111113a47 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -14,7 +14,6 @@ set( calamaresui_SOURCES modulesystem/ViewModule.cpp utils/CalamaresUtilsGui.cpp - utils/DebugWindow.cpp utils/ImageRegistry.cpp utils/Paste.cpp @@ -38,10 +37,6 @@ mark_thirdparty_code( ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp ) -set( calamaresui_UI - utils/DebugWindow.ui -) - if( WITH_PYTHON ) list( APPEND calamaresui_SOURCES modulesystem/PythonJobModule.cpp @@ -69,7 +64,6 @@ endif() calamares_add_library( calamaresui SOURCES ${calamaresui_SOURCES} - UI ${calamaresui_UI} EXPORT_MACRO UIDLLEXPORT_PRO LINK_PRIVATE_LIBRARIES ${OPTIONAL_PYTHON_LIBRARIES} From 2a3ab4dbe768792ac87ec637ffdcfad21cf5ff69 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:21:48 -0400 Subject: [PATCH 06/22] [calamares] Add a model for viewing QVariants directly --- src/calamares/CMakeLists.txt | 1 + src/calamares/VariantModel.cpp | 234 +++++++++++++++++++++++++++++++++ src/calamares/VariantModel.h | 74 +++++++++++ 3 files changed, 309 insertions(+) create mode 100644 src/calamares/VariantModel.cpp create mode 100644 src/calamares/VariantModel.h diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 92521f17a..259e3bf56 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -6,6 +6,7 @@ set( calamaresSources CalamaresWindow.cpp DebugWindow.cpp + VariantModel.cpp progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeItem.cpp diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp new file mode 100644 index 000000000..bdcf8f75c --- /dev/null +++ b/src/calamares/VariantModel.cpp @@ -0,0 +1,234 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "VariantModel.h" + +static void +overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVector* skiplist ) +{ + if ( skiplist ) + { + skiplist->append( parent ); + } + + parent = c++; + if ( item.canConvert< QVariantList >() ) + { + for ( const auto& subitem : item.toList() ) + { + overallLength( subitem, c, parent, skiplist ); + } + } + else if ( item.canConvert< QVariantMap >() ) + { + for ( const auto& subitem : item.toMap() ) + { + overallLength( subitem, c, parent, skiplist ); + } + } +} + +static quintptr +findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) +{ + if ( n < 0 ) + { + return -1; + } + + int index = 0; + while ( ( n >= 0 ) && ( index < skiplist.count() ) ) + { + if ( skiplist[ index ] == value ) + { + if ( --n < 0 ) + { + return index; + } + } + index++; + } + return -1; +} + + +VariantModel::VariantModel( const QVariant* p ) + : m_p( p ) +{ + int x = 0; + overallLength( *p, x, -1, nullptr ); + m_rows.reserve( x ); + x = 0; + overallLength( *p, x, -1, &m_rows ); +} + +VariantModel::~VariantModel() {} + +int +VariantModel::columnCount( const QModelIndex& index ) const +{ + return 2; +} + +int +VariantModel::rowCount( const QModelIndex& index ) const +{ + quintptr p = index.isValid() ? index.internalId() : 0; + return m_rows.count( p ); +} + +QModelIndex +VariantModel::index( int row, int column, const QModelIndex& parent ) const +{ + quintptr p = 0; + + if ( parent.isValid() ) + { + if ( !( parent.internalId() >= m_rows.count() ) ) + { + p = parent.internalId(); + } + } + + return createIndex( row, column, findNth( m_rows, p, row ) ); +} + +QModelIndex +VariantModel::parent( const QModelIndex& index ) const +{ + if ( !index.isValid() || ( index.internalId() > m_rows.count() ) ) + { + return QModelIndex(); + } + + quintptr p = m_rows[ index.internalId() ]; + if ( p == 0 ) + { + return QModelIndex(); + } + + if ( p >= m_rows.count() ) + { + return QModelIndex(); + } + quintptr p_pid = m_rows[ p ]; + int row = 0; + for ( int i = 0; i < p; ++i ) + { + if ( m_rows[ i ] == p_pid ) + { + row++; + } + } + + return createIndex( row, index.column(), p ); +} + +QVariant +VariantModel::data( const QModelIndex& index, int role ) const +{ + if ( role != Qt::DisplayRole ) + { + return QVariant(); + } + + if ( !index.isValid() ) + { + return QVariant(); + } + + if ( ( index.column() < 0 ) || ( index.column() > 1 ) ) + { + return QVariant(); + } + + if ( index.internalId() >= m_rows.count() ) + { + return QVariant(); + } + + const QVariant thing = underlying( parent( index ) ); + + if ( !thing.isValid() ) + { + return QVariant(); + } + + if ( thing.canConvert< QVariantMap >() ) + { + QVariantMap the_map = thing.toMap(); + const auto key = the_map.keys().at( index.row() ); + if ( index.column() == 0 ) + { + return key; + } + else + { + return the_map[ key ]; + } + } + else if ( thing.canConvert< QVariantList >() ) + { + if ( index.column() == 0 ) + { + return index.row(); + } + else + { + QVariantList the_list = thing.toList(); + return the_list.at( index.row() ); + } + } + else + { + if ( index.column() == 0 ) + { + return QVariant(); + } + else + { + return thing; + } + } +} + +const QVariant +VariantModel::underlying( const QModelIndex& index ) const +{ + if ( !index.isValid() ) + { + return *m_p; + } + + const auto& thing = underlying( parent( index ) ); + if ( thing.canConvert< QVariantMap >() ) + { + const auto& the_map = thing.toMap(); + return the_map[ the_map.keys()[ index.row() ] ]; + } + else if ( thing.canConvert< QVariantList >() ) + { + return thing.toList()[ index.row() ]; + } + else + { + return thing; + } + + return QVariant(); +} diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h new file mode 100644 index 000000000..9ea6f6737 --- /dev/null +++ b/src/calamares/VariantModel.h @@ -0,0 +1,74 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef VARIANTMODEL_H +#define VARIANTMODEL_H + +#include +#include +#include + +/** @brief A model that operates directly on a QVariant + * + * A VariantModel operates directly on an underlying + * QVariant, treating QVariantMap and QVariantList as + * nodes with multiple children. In general, putting + * a QVariantMap into a QVariant and passing that into + * the model will get you a tree-like model of the + * VariantMap's data structure. + * + * Take care of object lifetimes and that the underlying + * QVariant does not change during use. + */ +class VariantModel : public QAbstractItemModel +{ +public: + /** @brief Auxiliary data + * + * The nodes of the tree are enumerated into a vector + * (of length equal to the number of nodes in the tree + 1) + * which are used to do index and parent calculations. + */ + using IndexVector = QVector< quintptr >; + + /** @brief Constructor + * + * The QVariant's lifetime is **not** affected by the model, + * so take care that the QVariant lives at least as long as + * the model). Also, don't change the QVariant underneath the model. + */ + VariantModel( const QVariant* p ); + + ~VariantModel() override; + + int columnCount( const QModelIndex& index ) const override; + int rowCount( const QModelIndex& index ) const override; + + QModelIndex index( int row, int column, const QModelIndex& parent ) const override; + QModelIndex parent( const QModelIndex& index ) const override; + QVariant data( const QModelIndex& index, int role ) const override; + +private: + const QVariant* const m_p; + IndexVector m_rows; + + /// @brief Implementation of walking an index through the variant-tree + const QVariant underlying( const QModelIndex& index ) const; +}; + +#endif From 2bd03ad3c09129c7b078e73193c10d20cddfa891 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:40:23 -0400 Subject: [PATCH 07/22] [calamares] Add reload() to update model after underlying data --- src/calamares/VariantModel.cpp | 16 +++++++++++----- src/calamares/VariantModel.h | 11 ++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index bdcf8f75c..fc11794bc 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -70,15 +70,21 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) VariantModel::VariantModel( const QVariant* p ) : m_p( p ) { - int x = 0; - overallLength( *p, x, -1, nullptr ); - m_rows.reserve( x ); - x = 0; - overallLength( *p, x, -1, &m_rows ); + reload(); } VariantModel::~VariantModel() {} +void VariantModel::reload() +{ + int x = 0; + overallLength( *m_p, x, -1, nullptr ); + m_rows.clear(); // Start over + m_rows.reserve( x ); // We'll need this much + x = 0; + overallLength( *m_p, x, -1, &m_rows ); +} + int VariantModel::columnCount( const QModelIndex& index ) const { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 9ea6f6737..b0c93e91c 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -33,7 +33,9 @@ * VariantMap's data structure. * * Take care of object lifetimes and that the underlying - * QVariant does not change during use. + * QVariant does not change during use. If the QVariant + * **does** change, call reload() to re-build the internal + * representation of the tree. */ class VariantModel : public QAbstractItemModel { @@ -56,6 +58,13 @@ public: ~VariantModel() override; + /** @brief Re-build the internal tree + * + * Call this when the underlying variant is changed, which + * might impact how the tree is laid out. + */ + void reload(); + int columnCount( const QModelIndex& index ) const override; int rowCount( const QModelIndex& index ) const override; From eba4dc8df131d247c05395d56ceb5081ddcf3f0e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:48:52 -0400 Subject: [PATCH 08/22] [calamares] Use VariantModel instead of QJsonModel - Drop the round-trip of forming a JSON document from a QVariant, then parsing the document into JSON objects and building a model out of that. View the Variant directly. --- src/calamares/DebugWindow.cpp | 30 +++++++++++++++++------------- src/calamares/DebugWindow.h | 8 ++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp index 237b8a7ed..1680fb7de 100644 --- a/src/calamares/DebugWindow.cpp +++ b/src/calamares/DebugWindow.cpp @@ -20,6 +20,8 @@ #include "DebugWindow.h" #include "ui_DebugWindow.h" +#include "VariantModel.h" + #include "Branding.h" #include "modulesystem/Module.h" #include "modulesystem/ModuleManager.h" @@ -72,23 +74,25 @@ namespace Calamares { DebugWindow::DebugWindow() : QWidget( nullptr ) , m_ui( new Ui::DebugWindow ) + , m_globals( JobQueue::instance()->globalStorage()->data() ) + , m_globals_model( std::make_unique< VariantModel >( &m_globals ) ) + , m_module_model( std::make_unique< VariantModel >( &m_module ) ) { - m_ui->setupUi( this ); - - // GlobalStorage page - QJsonModel* jsonModel = new QJsonModel( this ); - - m_ui->globalStorageView->setModel( jsonModel ); GlobalStorage* gs = JobQueue::instance()->globalStorage(); + m_ui->setupUi( this ); + + m_ui->globalStorageView->setModel( m_globals_model.get() ); + m_ui->globalStorageView->expandAll(); + + // Do above when the GS changes, too connect( gs, &GlobalStorage::changed, this, [ = ] { - jsonModel->loadJson( QJsonDocument::fromVariant( gs->m ).toJson() ); + m_globals = JobQueue::instance()->globalStorage()->data(); + m_globals_model->reload(); m_ui->globalStorageView->expandAll(); } ); - jsonModel->loadJson( QJsonDocument::fromVariant( gs->m ).toJson() ); - m_ui->globalStorageView->expandAll(); // JobQueue page m_ui->jobQueueText->setReadOnly( true ); @@ -109,8 +113,7 @@ DebugWindow::DebugWindow() m_ui->modulesListView->setModel( modulesModel ); m_ui->modulesListView->setSelectionMode( QAbstractItemView::SingleSelection ); - QJsonModel* moduleConfigModel = new QJsonModel( this ); - m_ui->moduleConfigView->setModel( moduleConfigModel ); + m_ui->moduleConfigView->setModel( m_module_model.get() ); #ifdef WITH_PYTHONQT QPushButton* pythonConsoleButton = new QPushButton; @@ -181,7 +184,7 @@ DebugWindow::DebugWindow() #endif connect( m_ui->modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged, - this, [ this, moduleConfigModel + this, [ this #ifdef WITH_PYTHONQT , pythonConsoleButton #endif @@ -191,7 +194,8 @@ DebugWindow::DebugWindow() Module* module = ModuleManager::instance()->moduleInstance( moduleName ); if ( module ) { - moduleConfigModel->loadJson( QJsonDocument::fromVariant( module->configurationMap() ).toJson() ); + m_module = module->configurationMap(); + m_module_model->reload(); m_ui->moduleConfigView->expandAll(); m_ui->moduleTypeLabel->setText( module->typeString() ); m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); diff --git a/src/calamares/DebugWindow.h b/src/calamares/DebugWindow.h index e97f5727b..1a121455e 100644 --- a/src/calamares/DebugWindow.h +++ b/src/calamares/DebugWindow.h @@ -20,8 +20,12 @@ #ifndef CALAMARES_DEBUGWINDOW_H #define CALAMARES_DEBUGWINDOW_H +#include "VariantModel.h" + +#include #include +#include namespace Calamares { @@ -46,6 +50,10 @@ protected: private: Ui::DebugWindow *m_ui; + QVariant m_globals; + QVariant m_module; + std::unique_ptr< VariantModel> m_globals_model; + std::unique_ptr< VariantModel> m_module_model; }; From ab7a559e03476ff98b4bbd61a8a96d1dbd3bdeeb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:58:20 -0400 Subject: [PATCH 09/22] [calamares] Add headerData to model (Key, Value columns) --- src/calamares/VariantModel.cpp | 32 +++++++++++++++++++++++++++++++- src/calamares/VariantModel.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index fc11794bc..965f0f3e0 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -75,7 +75,8 @@ VariantModel::VariantModel( const QVariant* p ) VariantModel::~VariantModel() {} -void VariantModel::reload() +void +VariantModel::reload() { int x = 0; overallLength( *m_p, x, -1, nullptr ); @@ -213,6 +214,35 @@ VariantModel::data( const QModelIndex& index, int role ) const } } +QVariant +VariantModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( role != Qt::DisplayRole ) + { + return QVariant(); + } + + if ( orientation == Qt::Horizontal ) + { + if ( section == 0 ) + { + return tr( "Key" ); + } + else if ( section == 1 ) + { + return tr( "Value" ); + } + else + { + return QVariant(); + } + } + else + { + return QVariant(); + } +} + const QVariant VariantModel::underlying( const QModelIndex& index ) const { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index b0c93e91c..9c4256f6a 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -71,6 +71,7 @@ public: QModelIndex index( int row, int column, const QModelIndex& parent ) const override; QModelIndex parent( const QModelIndex& index ) const override; QVariant data( const QModelIndex& index, int role ) const override; + QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; private: const QVariant* const m_p; From ea0acf1606d369a350c1ffc1a958c6260789c441 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 15:25:37 +0200 Subject: [PATCH 10/22] [calamares] Apply current coding style --- src/calamares/progresstree/ProgressTreeView.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp index 5c81e3851..d4f652363 100644 --- a/src/calamares/progresstree/ProgressTreeView.cpp +++ b/src/calamares/progresstree/ProgressTreeView.cpp @@ -76,9 +76,10 @@ ProgressTreeView::setModel( QAbstractItemModel* model ) QTreeView::setModel( model ); expandAll(); - connect( Calamares::ViewManager::instance(), - &Calamares::ViewManager::currentStepChanged, - this, - [this]() { viewport()->update(); }, - Qt::UniqueConnection ); + connect( + Calamares::ViewManager::instance(), + &Calamares::ViewManager::currentStepChanged, + this, + [this]() { viewport()->update(); }, + Qt::UniqueConnection ); } From f5af4818fbc15bb02fb709de20b0387731227b76 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 15:27:40 +0200 Subject: [PATCH 11/22] [calamares] Apply current coding style --- src/calamares/CalamaresWindow.cpp | 2 +- src/calamares/DebugWindow.cpp | 140 ++++++++++++++---------------- src/calamares/DebugWindow.h | 13 +-- 3 files changed, 72 insertions(+), 83 deletions(-) diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index 68f29ef18..1638d6392 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -22,11 +22,11 @@ #include "CalamaresWindow.h" #include "Branding.h" +#include "DebugWindow.h" #include "Settings.h" #include "ViewManager.h" #include "progresstree/ProgressTreeView.h" #include "utils/CalamaresUtilsGui.h" -#include "DebugWindow.h" #include "utils/Logger.h" #include "utils/Retranslator.h" diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp index 1680fb7de..6891851a7 100644 --- a/src/calamares/DebugWindow.cpp +++ b/src/calamares/DebugWindow.cpp @@ -55,21 +55,29 @@ crash() } /// @brief Print out the widget tree (names) in indented form. -static void dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) +static void +dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) { if ( !widget ) + { return; + } deb << Logger::Continuation; - for (int i = 0; i < depth; ++i ) + for ( int i = 0; i < depth; ++i ) + { deb << ' '; + } deb << widget->objectName(); - for ( const auto* w : widget->findChildren( QString(), Qt::FindDirectChildrenOnly ) ) - dumpWidgetTree( deb, w, depth+1 ); + for ( const auto* w : widget->findChildren< QWidget* >( QString(), Qt::FindDirectChildrenOnly ) ) + { + dumpWidgetTree( deb, w, depth + 1 ); + } } -namespace Calamares { +namespace Calamares +{ DebugWindow::DebugWindow() : QWidget( nullptr ) @@ -86,9 +94,7 @@ DebugWindow::DebugWindow() m_ui->globalStorageView->expandAll(); // Do above when the GS changes, too - connect( gs, &GlobalStorage::changed, - this, [ = ] - { + connect( gs, &GlobalStorage::changed, this, [=] { m_globals = JobQueue::instance()->globalStorage()->data(); m_globals_model->reload(); m_ui->globalStorageView->expandAll(); @@ -96,11 +102,9 @@ DebugWindow::DebugWindow() // JobQueue page m_ui->jobQueueText->setReadOnly( true ); - connect( JobQueue::instance(), &JobQueue::queueChanged, - this, [ this ]( const JobList& jobs ) - { + connect( JobQueue::instance(), &JobQueue::queueChanged, this, [this]( const JobList& jobs ) { QStringList text; - for ( const auto &job : jobs ) + for ( const auto& job : jobs ) { text.append( job->prettyName() ); } @@ -121,21 +125,17 @@ DebugWindow::DebugWindow() m_ui->modulesVerticalLayout->insertWidget( 1, pythonConsoleButton ); pythonConsoleButton->hide(); - QObject::connect( pythonConsoleButton, &QPushButton::clicked, - this, [ this, moduleConfigModel ] - { + QObject::connect( pythonConsoleButton, &QPushButton::clicked, this, [this, moduleConfigModel] { QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); Module* module = ModuleManager::instance()->moduleInstance( moduleName ); - if ( module->interface() != Module::Interface::PythonQt || - module->type() != Module::Type::View ) + if ( module->interface() != Module::Interface::PythonQt || module->type() != Module::Type::View ) return; for ( ViewStep* step : ViewManager::instance()->viewSteps() ) { if ( step->moduleInstanceKey() == module->instanceKey() ) { - PythonQtViewStep* pqvs = - qobject_cast< PythonQtViewStep* >( step ); + PythonQtViewStep* pqvs = qobject_cast< PythonQtViewStep* >( step ); if ( pqvs ) { QWidget* consoleWindow = new QWidget; @@ -152,23 +152,17 @@ DebugWindow::DebugWindow() QLabel* bottomLabel = new QLabel( consoleWindow ); bottomLayout->addWidget( bottomLabel ); - QString line = - QString( "Module: %1
" - "Python class: %2" ) - .arg( module->instanceKey() ) - .arg( console->property( "classname" ).toString() ); + QString line = QString( "Module: %1
" + "Python class: %2" ) + .arg( module->instanceKey() ) + .arg( console->property( "classname" ).toString() ); bottomLabel->setText( line ); QPushButton* closeButton = new QPushButton( consoleWindow ); closeButton->setText( "&Close" ); - QObject::connect( closeButton, &QPushButton::clicked, - [ consoleWindow ] - { - consoleWindow->close(); - } ); + QObject::connect( closeButton, &QPushButton::clicked, [consoleWindow] { consoleWindow->close(); } ); bottomLayout->addWidget( closeButton ); - bottomLabel->setSizePolicy( QSizePolicy::Expanding, - QSizePolicy::Preferred ); + bottomLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); consoleWindow->setParent( this ); consoleWindow->setWindowFlags( Qt::Window ); @@ -183,58 +177,52 @@ DebugWindow::DebugWindow() #endif - connect( m_ui->modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged, - this, [ this + connect( m_ui->modulesListView->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + [this #ifdef WITH_PYTHONQT - , pythonConsoleButton + , + pythonConsoleButton #endif - ] - { - QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); - Module* module = ModuleManager::instance()->moduleInstance( moduleName ); - if ( module ) - { - m_module = module->configurationMap(); - m_module_model->reload(); - m_ui->moduleConfigView->expandAll(); - m_ui->moduleTypeLabel->setText( module->typeString() ); - m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); + ] { + QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); + Module* module = ModuleManager::instance()->moduleInstance( moduleName ); + if ( module ) + { + m_module = module->configurationMap(); + m_module_model->reload(); + m_ui->moduleConfigView->expandAll(); + m_ui->moduleTypeLabel->setText( module->typeString() ); + m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); #ifdef WITH_PYTHONQT - pythonConsoleButton->setVisible( - module->interface() == Module::Interface::PythonQt && - module->type() == Module::Type::View ); + pythonConsoleButton->setVisible( module->interface() == Module::Interface::PythonQt + && module->type() == Module::Type::View ); #endif - } - } ); + } + } ); // Tools page connect( m_ui->crashButton, &QPushButton::clicked, this, [] { ::crash(); } ); - connect( m_ui->reloadStylesheetButton, &QPushButton::clicked, - []() - { - for ( auto* w : qApp->topLevelWidgets() ) - { - // Needs to match what's set in CalamaresWindow - if ( w->objectName() == QStringLiteral( "mainApp" ) ) - { - w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); - } - } - }); - connect( m_ui->widgetTreeButton, &QPushButton::clicked, - []() - { - for ( auto* w : qApp->topLevelWidgets() ) - { - Logger::CDebug deb; - dumpWidgetTree( deb, w, 0 ); - } - }); + connect( m_ui->reloadStylesheetButton, &QPushButton::clicked, []() { + for ( auto* w : qApp->topLevelWidgets() ) + { + // Needs to match what's set in CalamaresWindow + if ( w->objectName() == QStringLiteral( "mainApp" ) ) + { + w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); + } + } + } ); + connect( m_ui->widgetTreeButton, &QPushButton::clicked, []() { + for ( auto* w : qApp->topLevelWidgets() ) + { + Logger::CDebug deb; + dumpWidgetTree( deb, w, 0 ); + } + } ); - CALAMARES_RETRANSLATE( - m_ui->retranslateUi( this ); - setWindowTitle( tr( "Debug information" ) ); - ) + CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); setWindowTitle( tr( "Debug information" ) ); ) } @@ -245,4 +233,4 @@ DebugWindow::closeEvent( QCloseEvent* e ) emit closed(); } -} // namespace Calamares +} // namespace Calamares diff --git a/src/calamares/DebugWindow.h b/src/calamares/DebugWindow.h index 1a121455e..764a141c2 100644 --- a/src/calamares/DebugWindow.h +++ b/src/calamares/DebugWindow.h @@ -27,12 +27,13 @@ #include -namespace Calamares { +namespace Calamares +{ // From the .ui file namespace Ui { - class DebugWindow; +class DebugWindow; } class DebugWindow : public QWidget @@ -49,13 +50,13 @@ protected: void closeEvent( QCloseEvent* e ) override; private: - Ui::DebugWindow *m_ui; + Ui::DebugWindow* m_ui; QVariant m_globals; QVariant m_module; - std::unique_ptr< VariantModel> m_globals_model; - std::unique_ptr< VariantModel> m_module_model; + std::unique_ptr< VariantModel > m_globals_model; + std::unique_ptr< VariantModel > m_module_model; }; -} // namespace +} // namespace Calamares #endif From dc09c5700b53c3a01e0bfff1eab68cfbf3d7964f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:15:18 +0200 Subject: [PATCH 12/22] [calamares] Remove unreachable return --- src/calamares/VariantModel.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index 965f0f3e0..5eaf4bac7 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -265,6 +265,4 @@ VariantModel::underlying( const QModelIndex& index ) const { return thing; } - - return QVariant(); } From 6f73151786dbd1bc4d2d3a892c13252b416071e0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:22:22 +0200 Subject: [PATCH 13/22] [libcalamares] Reduce warnings - Although milliseconds::count() is long long, we pass it to a Qt interface that only takes int; let's assume we have only a 32-bit count, since a timeout of 4 billion milliseconds is roughly 46 days, which we'll just call "no timeout". --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 00b879224..ea8f507bd 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -236,8 +236,9 @@ System::runCommand( System::RunLocation location, } process.closeWriteChannel(); - if ( !process.waitForFinished( - timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) + if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() + ? ( static_cast< int >( std::chrono::milliseconds( timeoutSec ).count() ) ) + : -1 ) ) { cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput(); return ProcessResult::Code::TimedOut; From 739363cecd0ef6bdcd6689e53275f8c16363ced2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:28:29 +0200 Subject: [PATCH 14/22] [libcalamaresui] Fix initialization order (reduce warnings) --- src/libcalamaresui/Branding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index 876fdfa80..d3b0de97d 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -125,9 +125,9 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent ) : QObject( parent ) , m_descriptorPath( brandingFilePath ) + , m_slideshowAPI( 1 ) , m_welcomeStyleCalamares( false ) , m_welcomeExpandingLogo( true ) - , m_slideshowAPI( 1 ) { cDebug() << "Using Calamares branding file at" << brandingFilePath; From e81bd52fb53a8640072eae3cdd1b680247c47d17 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:29:55 +0200 Subject: [PATCH 15/22] [initcpio] [initramfs] Set compilation options on tests - calamares_automoc() sets AUTOMOC, but also adds some flags to avoid compilation warnings from the generated MOC code. - drop weird hard-coded include paths --- src/modules/initcpio/CMakeLists.txt | 3 +-- src/modules/initramfs/CMakeLists.txt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/initcpio/CMakeLists.txt b/src/modules/initcpio/CMakeLists.txt index 990220b10..af217fb1a 100644 --- a/src/modules/initcpio/CMakeLists.txt +++ b/src/modules/initcpio/CMakeLists.txt @@ -21,6 +21,5 @@ if( ECM_FOUND AND BUILD_TESTING ) Qt5::Core Qt5::Test ) - set_target_properties( initcpiotest PROPERTIES AUTOMOC TRUE ) - target_include_directories( initcpiotest PRIVATE /usr/local/include ) + calamares_automoc( initcpiotest ) endif() diff --git a/src/modules/initramfs/CMakeLists.txt b/src/modules/initramfs/CMakeLists.txt index c2496b2a1..d7da12d55 100644 --- a/src/modules/initramfs/CMakeLists.txt +++ b/src/modules/initramfs/CMakeLists.txt @@ -21,6 +21,5 @@ if( ECM_FOUND AND BUILD_TESTING ) Qt5::Core Qt5::Test ) - set_target_properties( initramfstest PROPERTIES AUTOMOC TRUE ) - target_include_directories( initramfstest PRIVATE /usr/local/include ) + calamares_automoc( initramfstest ) endif() From 76041a21841d61c6c7fafd8d9206890915bbdacd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:34:53 +0200 Subject: [PATCH 16/22] [dummycpp] Reduce warnings and apply coding style - tired of the (IMO, bogus) clang warnings from the switch() statement with a default:, so swap it out for some cascaded ifs. --- src/modules/dummycpp/DummyCppJob.cpp | 61 ++++++++++++++++------------ src/modules/dummycpp/DummyCppJob.h | 2 +- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/modules/dummycpp/DummyCppJob.cpp b/src/modules/dummycpp/DummyCppJob.cpp index b404eaf63..a38cddc40 100644 --- a/src/modules/dummycpp/DummyCppJob.cpp +++ b/src/modules/dummycpp/DummyCppJob.cpp @@ -20,13 +20,13 @@ #include "DummyCppJob.h" -#include #include +#include #include #include "CalamaresVersion.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" #include "utils/Logger.h" @@ -36,9 +36,7 @@ DummyCppJob::DummyCppJob( QObject* parent ) } -DummyCppJob::~DummyCppJob() -{ -} +DummyCppJob::~DummyCppJob() {} QString @@ -56,19 +54,20 @@ static QString variantHashToString( const QVariantHash& variantHash ); static QString variantToString( const QVariant& variant ) { - switch ( variant.type() ) + if ( variant.type() == QVariant::Map ) { - case QVariant::Map: return variantMapToString( variant.toMap() ); - - case QVariant::Hash: + } + else if ( variant.type() == QVariant::Hash ) + { return variantHashToString( variant.toHash() ); - - case QVariant::List: - case QVariant::StringList: + } + else if ( ( variant.type() == QVariant::List ) || ( variant.type() == QVariant::StringList ) ) + { return variantListToString( variant.toList() ); - - default: + } + else + { return variant.toString(); } } @@ -79,8 +78,10 @@ variantListToString( const QVariantList& variantList ) { QStringList result; for ( const QVariant& variant : variantList ) + { result.append( variantToString( variant ) ); - return '{' + result.join(',') + '}'; + } + return '{' + result.join( ',' ) + '}'; } @@ -89,8 +90,10 @@ variantMapToString( const QVariantMap& variantMap ) { QStringList result; for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it ) + { result.append( it.key() + '=' + variantToString( it.value() ) ); - return '[' + result.join(',') + ']'; + } + return '[' + result.join( ',' ) + ']'; } @@ -99,8 +102,10 @@ variantHashToString( const QVariantHash& variantHash ) { QStringList result; for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it ) + { result.append( it.key() + '=' + variantToString( it.value() ) ); - return '<' + result.join(',') + '>'; + } + return '<' + result.join( ',' ) + '>'; } @@ -108,24 +113,28 @@ Calamares::JobResult DummyCppJob::exec() { // Ported from dummypython - QProcess::execute( "/bin/sh", QStringList() << "-c" << "touch ~/calamares-dummycpp" ); + QProcess::execute( "/bin/sh", + QStringList() << "-c" + << "touch ~/calamares-dummycpp" ); QString accumulator = QDateTime::currentDateTimeUtc().toString( Qt::ISODate ) + '\n'; accumulator += QStringLiteral( "Calamares version: " ) + CALAMARES_VERSION_SHORT + '\n'; accumulator += QStringLiteral( "This job's name: " ) + prettyName() + '\n'; accumulator += QStringLiteral( "Configuration map: %1\n" ).arg( variantMapToString( m_configurationMap ) ); accumulator += QStringLiteral( " *** globalstorage test ***\n" ); - Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); - accumulator += QStringLiteral( "lala: " ) + (globalStorage->contains( "lala" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" )) + '\n'; - accumulator += QStringLiteral( "foo: " ) + (globalStorage->contains( "foo" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" )) + '\n'; + Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); + accumulator += QStringLiteral( "lala: " ) + + ( globalStorage->contains( "lala" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; + accumulator += QStringLiteral( "foo: " ) + + ( globalStorage->contains( "foo" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; accumulator += QStringLiteral( "count: " ) + QString::number( globalStorage->count() ) + '\n'; globalStorage->insert( "item2", "value2" ); globalStorage->insert( "item3", 3 ); accumulator += QStringLiteral( "keys: %1\n" ).arg( globalStorage->keys().join( ',' ) ); accumulator += QStringLiteral( "remove: %1\n" ).arg( QString::number( globalStorage->remove( "item2" ) ) ); - accumulator += QStringLiteral( "values: %1 %2 %3\n" ).arg( - globalStorage->value( "foo" ).toString(), - globalStorage->value( "item2" ).toString(), - globalStorage->value( "item3" ).toString() ); + accumulator += QStringLiteral( "values: %1 %2 %3\n" ) + .arg( globalStorage->value( "foo" ).toString(), + globalStorage->value( "item2" ).toString(), + globalStorage->value( "item3" ).toString() ); emit progress( 0.1 ); cDebug() << "[DUMMYCPP]: " << accumulator; @@ -145,4 +154,4 @@ DummyCppJob::setConfigurationMap( const QVariantMap& configurationMap ) m_configurationMap = configurationMap; } -CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyCppJobFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyCppJobFactory, registerPlugin< DummyCppJob >(); ) diff --git a/src/modules/dummycpp/DummyCppJob.h b/src/modules/dummycpp/DummyCppJob.h index 98c4d19d6..4a79d0378 100644 --- a/src/modules/dummycpp/DummyCppJob.h +++ b/src/modules/dummycpp/DummyCppJob.h @@ -49,4 +49,4 @@ private: CALAMARES_PLUGIN_FACTORY_DECLARATION( DummyCppJobFactory ) -#endif // DUMMYCPPJOB_H +#endif // DUMMYCPPJOB_H From 41173360a71c6c13bb6e1fbcd1bf1c500b075b2c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:36:38 +0200 Subject: [PATCH 17/22] [libcalamares] We're just testing file modes, not whole int range --- src/libcalamares/utils/Tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 2f2b7ff4b..0f7d6cd81 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -158,7 +158,7 @@ LibCalamaresTests::testUmask() mode_t m = CalamaresUtils::setUMask( 022 ); QCOMPARE( CalamaresUtils::setUMask( m ), m ); - for ( int i = 0; i <= 0777 /* octal! */; ++i ) + for ( mode_t i = 0; i <= 0777 /* octal! */; ++i ) { QByteArray name = ( ft.fileName() + QChar( '.' ) + QString::number( i, 8 ) ).toLatin1(); CalamaresUtils::UMask um( i ); From 91d327b224b867960b991bb0afc79d124c373403 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:41:59 +0200 Subject: [PATCH 18/22] [libcalamaresui] Paste TCP port is quint16 - no sense in feeding in an int (and getting a compiler warning for narrowing) into something that by spec is a 16-bit value. --- src/libcalamaresui/utils/Paste.cpp | 2 +- src/libcalamaresui/utils/Paste.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/utils/Paste.cpp b/src/libcalamaresui/utils/Paste.cpp index 6fead59e6..1b9ad4dfe 100644 --- a/src/libcalamaresui/utils/Paste.cpp +++ b/src/libcalamaresui/utils/Paste.cpp @@ -29,7 +29,7 @@ namespace CalamaresUtils { QString -sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ) +sendLogToPastebin( QObject* parent, const QString& ficheHost, quint16 fichePort ) { QString pasteUrlFmt = parent->tr( "Install log posted to:\n%1" ); QFile pasteSourceFile( Logger::logFile() ); diff --git a/src/libcalamaresui/utils/Paste.h b/src/libcalamaresui/utils/Paste.h index 2ac77f2f3..fd088882c 100644 --- a/src/libcalamaresui/utils/Paste.h +++ b/src/libcalamaresui/utils/Paste.h @@ -19,6 +19,8 @@ #ifndef UTILS_PASTE_H #define UTILS_PASTE_H +#include // for quint16 + class QObject; class QString; @@ -29,7 +31,7 @@ namespace CalamaresUtils * * Returns the (string) URL that the pastebin gives us. */ -QString sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ); +QString sendLogToPastebin( QObject* parent, const QString& ficheHost, quint16 fichePort ); } // namespace CalamaresUtils From ec08a293b28fc374b250b3549f1f742563fbc232 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:43:50 +0200 Subject: [PATCH 19/22] [libcalamaresui] Reduce compile warnings - "this" isn't used in the lambda; in future it might be if the lambda needs to get the configuration from settings. --- src/libcalamaresui/ViewManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index b27b36f80..7baefdbd0 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -241,7 +241,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->show(); cDebug() << "Calamares will quit when the dialog closes."; - connect( msgBox, &QMessageBox::buttonClicked, [this,msgBox]( QAbstractButton* button ) { + connect( msgBox, &QMessageBox::buttonClicked, [msgBox]( QAbstractButton* button ) { if ( msgBox->buttonRole( button ) == QMessageBox::ButtonRole::YesRole ) { // TODO: host and port should be configurable @@ -254,9 +254,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail } // TODO: make the URL clickable, or copy it to the clipboard automatically - QMessageBox::critical(nullptr, - pasteUrlTitle, - pasteUrlMsg); + QMessageBox::critical( nullptr, pasteUrlTitle, pasteUrlMsg ); } QApplication::quit(); } ); From 8a7f32d3aa45fd1d34bbb7a704fc8aa39c334544 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:52:54 +0200 Subject: [PATCH 20/22] [libcalamaresui] Polish ImageRegistry - do static initialization more carefully - float -> qreal (double) because that's what the Qt API expects, to reduce type-conversion warnings - apply current coding style --- src/libcalamaresui/utils/ImageRegistry.cpp | 45 +++++++++++++--------- src/libcalamaresui/utils/ImageRegistry.h | 23 +++++++---- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/libcalamaresui/utils/ImageRegistry.cpp b/src/libcalamaresui/utils/ImageRegistry.cpp index 96ea92bbb..5cffac11c 100644 --- a/src/libcalamaresui/utils/ImageRegistry.cpp +++ b/src/libcalamaresui/utils/ImageRegistry.cpp @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry + * + * Copyright 2019, Adriaan de Groot */ /* @@ -23,25 +25,22 @@ #include "ImageRegistry.h" -#include #include +#include #include static QHash< QString, QHash< int, QHash< qint64, QPixmap > > > s_cache; -ImageRegistry* ImageRegistry::s_instance = 0; ImageRegistry* ImageRegistry::instance() { + static ImageRegistry* s_instance = new ImageRegistry(); return s_instance; } -ImageRegistry::ImageRegistry() -{ - s_instance = this; -} +ImageRegistry::ImageRegistry() {} QIcon @@ -52,16 +51,20 @@ ImageRegistry::icon( const QString& image, CalamaresUtils::ImageMode mode ) qint64 -ImageRegistry::cacheKey( const QSize& size, float opacity, QColor tint ) +ImageRegistry::cacheKey( const QSize& size, qreal opacity, QColor tint ) { - return size.width() * 100 + size.height() * 10 + ( opacity * 100.0 ) + tint.value(); + return size.width() * 100 + size.height() * 10 + static_cast< qint64 >( opacity * 100.0 ) + tint.value(); } QPixmap -ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, QColor tint ) +ImageRegistry::pixmap( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + QColor tint ) { - Q_ASSERT( !(size.width() < 0 || size.height() < 0) ); + Q_ASSERT( !( size.width() < 0 || size.height() < 0 ) ); if ( size.width() < 0 || size.height() < 0 ) { return QPixmap(); @@ -110,23 +113,20 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: resultImage.setAlphaChannel( p.toImage().alphaChannel() ); p = QPixmap::fromImage( resultImage ); - } + } pixmap = p; } else + { pixmap = QPixmap( image ); + } if ( !pixmap.isNull() ) { - switch ( mode ) + if ( mode == CalamaresUtils::RoundedCorners ) { - case CalamaresUtils::RoundedCorners: - pixmap = CalamaresUtils::createRoundedImage( pixmap, size ); - break; - - default: - break; + pixmap = CalamaresUtils::createRoundedImage( pixmap, size ); } if ( !size.isNull() && pixmap.size() != size ) @@ -140,7 +140,9 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: pixmap = pixmap.scaledToWidth( size.width(), Qt::SmoothTransformation ); } else + { pixmap = pixmap.scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + } } putInCache( image, size, mode, opacity, pixmap, tint ); @@ -151,7 +153,12 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: void -ImageRegistry::putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint ) +ImageRegistry::putInCache( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + const QPixmap& pixmap, + QColor tint ) { QHash< qint64, QPixmap > subsubcache; QHash< int, QHash< qint64, QPixmap > > subcache; diff --git a/src/libcalamaresui/utils/ImageRegistry.h b/src/libcalamaresui/utils/ImageRegistry.h index e35eaf74a..06ab45831 100644 --- a/src/libcalamaresui/utils/ImageRegistry.h +++ b/src/libcalamaresui/utils/ImageRegistry.h @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry + * + * Copyright 2019, Adriaan de Groot */ /* @@ -26,8 +28,8 @@ #include -#include "utils/CalamaresUtilsGui.h" #include "UiDllMacro.h" +#include "utils/CalamaresUtilsGui.h" class UIDLLEXPORT ImageRegistry { @@ -37,13 +39,20 @@ public: explicit ImageRegistry(); QIcon icon( const QString& image, CalamaresUtils::ImageMode mode = CalamaresUtils::Original ); - QPixmap pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode = CalamaresUtils::Original, float opacity = 1.0, QColor tint = QColor( 0, 0, 0, 0 ) ); + QPixmap pixmap( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode = CalamaresUtils::Original, + qreal opacity = 1.0, + QColor tint = QColor( 0, 0, 0, 0 ) ); private: - qint64 cacheKey( const QSize& size, float opacity, QColor tint ); - void putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint ); - - static ImageRegistry* s_instance; + qint64 cacheKey( const QSize& size, qreal opacity, QColor tint ); + void putInCache( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + const QPixmap& pixmap, + QColor tint ); }; -#endif // IMAGE_REGISTRY_H +#endif // IMAGE_REGISTRY_H From 96ef488f1bbd0c298c7d20efc2722ab46fc21944 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 17:17:46 +0200 Subject: [PATCH 21/22] [calamares] Clean up VariantModel - stop compiler warnings with some judicious casting; that's what you get when a container indexed by int stored those indexes as quintptr. - apply coding style --- src/calamares/VariantModel.cpp | 46 +++++++++++++++++++++------------- src/calamares/VariantModel.h | 4 +++ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index 5eaf4bac7..a7e1243f3 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -19,7 +19,7 @@ #include "VariantModel.h" static void -overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVector* skiplist ) +overallLength( const QVariant& item, quintptr& c, quintptr parent, VariantModel::IndexVector* skiplist ) { if ( skiplist ) { @@ -46,9 +46,11 @@ overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVect static quintptr findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) { + constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); + if ( n < 0 ) { - return -1; + return invalid_index; } int index = 0; @@ -58,12 +60,13 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) { if ( --n < 0 ) { - return index; + // It's bigger than 0 + return static_cast< quintptr >( index ); } } index++; } - return -1; + return invalid_index; } @@ -78,16 +81,19 @@ VariantModel::~VariantModel() {} void VariantModel::reload() { - int x = 0; - overallLength( *m_p, x, -1, nullptr ); + constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); + + quintptr x = 0; m_rows.clear(); // Start over - m_rows.reserve( x ); // We'll need this much - x = 0; - overallLength( *m_p, x, -1, &m_rows ); + if ( m_rows.capacity() < 64 ) + { + m_rows.reserve( 64 ); // Start reasonably-sized + } + overallLength( *m_p, x, invalid_index, &m_rows ); } int -VariantModel::columnCount( const QModelIndex& index ) const +VariantModel::columnCount( const QModelIndex& ) const { return 2; } @@ -106,7 +112,7 @@ VariantModel::index( int row, int column, const QModelIndex& parent ) const if ( parent.isValid() ) { - if ( !( parent.internalId() >= m_rows.count() ) ) + if ( inRange( parent ) ) { p = parent.internalId(); } @@ -115,27 +121,33 @@ VariantModel::index( int row, int column, const QModelIndex& parent ) const return createIndex( row, column, findNth( m_rows, p, row ) ); } +static inline quintptr +deref( const VariantModel::IndexVector& v, quintptr i ) +{ + return v[ static_cast< int >( i ) ]; +} + QModelIndex VariantModel::parent( const QModelIndex& index ) const { - if ( !index.isValid() || ( index.internalId() > m_rows.count() ) ) + if ( !index.isValid() || !inRange( index ) ) { return QModelIndex(); } - quintptr p = m_rows[ index.internalId() ]; + quintptr p = deref( m_rows, index.internalId() ); if ( p == 0 ) { return QModelIndex(); } - if ( p >= m_rows.count() ) + if ( !inRange( p ) ) { return QModelIndex(); } - quintptr p_pid = m_rows[ p ]; + quintptr p_pid = deref( m_rows, p ); int row = 0; - for ( int i = 0; i < p; ++i ) + for ( int i = 0; i < static_cast< int >( p ); ++i ) { if ( m_rows[ i ] == p_pid ) { @@ -164,7 +176,7 @@ VariantModel::data( const QModelIndex& index, int role ) const return QVariant(); } - if ( index.internalId() >= m_rows.count() ) + if ( !inRange( index ) ) { return QVariant(); } diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 9c4256f6a..372400940 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -79,6 +79,10 @@ private: /// @brief Implementation of walking an index through the variant-tree const QVariant underlying( const QModelIndex& index ) const; + + /// @brief Helpers for range-checking + inline bool inRange( quintptr p ) const { return p < static_cast< quintptr >( m_rows.count() ); } + inline bool inRange( const QModelIndex& index ) const { return inRange( index.internalId() ); } }; #endif From 08a08f9b54b0a2fc1f84d30c2ec0d8f6caceb7c7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 17:29:28 +0200 Subject: [PATCH 22/22] [calamares] Minor optimizations and documentation - document the data structure; for the vector V (called m_rows) the values are V_i < i, so that enables microscopic optimizations. --- src/calamares/VariantModel.cpp | 4 ++-- src/calamares/VariantModel.h | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index a7e1243f3..2d8313665 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -53,7 +53,7 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) return invalid_index; } - int index = 0; + int index = static_cast< int >( value ); while ( ( n >= 0 ) && ( index < skiplist.count() ) ) { if ( skiplist[ index ] == value ) @@ -147,7 +147,7 @@ VariantModel::parent( const QModelIndex& index ) const } quintptr p_pid = deref( m_rows, p ); int row = 0; - for ( int i = 0; i < static_cast< int >( p ); ++i ) + for ( int i = static_cast< int >( p_pid ); i < static_cast< int >( p ); ++i ) { if ( m_rows[ i ] == p_pid ) { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 372400940..bdf6da866 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -75,6 +75,30 @@ public: private: const QVariant* const m_p; + + /** @brief Tree representation of the variant. + * + * At index 0 in the vector , we store -1 to indicate the root. + * + * Then we enumerate all the elements in the tree (by traversing + * the variant and using QVariantMap and QVariantList as having + * children, and everything else being a leaf node) and at the index + * for a child, store the index of its parent. This means that direct + * children of the root store a 0 in their indexes, children of the first + * child of the root store a 1, and we can "pointer chase" from an index + * through parents back to index 0. + * + * Because of this structure, the value stored at index i must be + * less than i (except for index 0, which is special). This makes it + * slightly easier to search for a given value *p*, because we can start + * at index *p* (or even *p+1*). + * + * Given an index *i* into the vector corresponding to a child, we know the + * parent, but can also count which row this child should have, by counting + * *other* indexes before *i* with the same parent (and by the ordering + * of values, we can start counting at index *parent-index*). + * + */ IndexVector m_rows; /// @brief Implementation of walking an index through the variant-tree