From 00893b3cfc68f12c09e84643d255044a488b0eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 22 Jan 2013 05:56:12 +0100 Subject: Instance model (or at least something like it) --- data/inifile.cpp | 17 ++- data/instancebase.cpp | 64 +++++++- data/instancebase.h | 20 ++- data/instancelist.cpp | 52 ------- data/instancelist.h | 38 ----- data/instancemodel.cpp | 403 +++++++++++++++++++++++++++++++++++++++++++++++++ data/instancemodel.h | 137 +++++++++++++++++ 7 files changed, 633 insertions(+), 98 deletions(-) delete mode 100644 data/instancelist.cpp delete mode 100644 data/instancelist.h create mode 100644 data/instancemodel.cpp create mode 100644 data/instancemodel.h (limited to 'data') diff --git a/data/inifile.cpp b/data/inifile.cpp index df94e43e..2d68caf6 100644 --- a/data/inifile.cpp +++ b/data/inifile.cpp @@ -49,12 +49,23 @@ bool INIFile::loadFile(QString fileName) QStringList lines = in.readAll().split('\n'); for (int i = 0; i < lines.count(); i++) { + QString & lineRaw = lines[i]; // Ignore comments. - QString line = lines[i].left('#').trimmed(); + QString line = lineRaw.left(lineRaw.indexOf('#')).trimmed(); - QString key = line.section('=', 0).trimmed(); - QVariant value(line.section('=', 1).trimmed()); + int eqPos = line.indexOf('='); + if(eqPos == -1) + continue; + QString key = line.left(eqPos).trimmed(); + QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); + QVariant value(valueStr); + /* + QString dbg = key; + dbg += " = "; + dbg += valueStr; + qDebug(dbg.toLocal8Bit()); + */ this->operator [](key) = value; } diff --git a/data/instancebase.cpp b/data/instancebase.cpp index 15dc54f4..a5ef35a2 100644 --- a/data/instancebase.cpp +++ b/data/instancebase.cpp @@ -16,6 +16,7 @@ #include "instancebase.h" #include +#include #include "../util/pathutils.h" @@ -23,10 +24,27 @@ InstanceBase::InstanceBase(QString dir, QObject *parent) : QObject(parent), rootDir(dir) { - QFileInfo cfgFile; + QFileInfo cfgFile(PathCombine(rootDir, "instance.cfg")); if (cfgFile.exists()) - config.loadFile(PathCombine(rootDir, "instance.cfg")); + { + if(!config.loadFile(cfgFile.absoluteFilePath())) + { + QString debugmsg("Can't load instance config file for instance "); + debugmsg+= getInstID(); + qDebug(debugmsg.toLocal8Bit()); + } + } + else + { + QString debugmsg("Can't find instance config file for instance "); + debugmsg+= getInstID(); + debugmsg += " : "; + debugmsg += + debugmsg+=" ... is this an instance even?"; + qDebug(debugmsg.toLocal8Bit()); + } + currentGroup = nullptr; } QString InstanceBase::getRootDir() const @@ -47,3 +65,45 @@ void InstanceBase::setInstName(QString name) { config.set("name", name); } + +QString InstanceBase::getInstID() const +{ + return QDir(rootDir).dirName(); +} + +InstanceModelItem* InstanceBase::getParent() const +{ + return currentGroup; +} + +QVariant InstanceBase::data ( int role ) const +{ + switch(role) + { + case Qt::DisplayRole: + return getInstName(); + default: + return QVariant(); + } +} +int InstanceBase::getRow() const +{ + return currentGroup->getIndexOf((InstanceBase*)this); +} + +InstanceModelItem* InstanceBase::getChild ( int index ) const +{ + return nullptr; +} +InstanceModel* InstanceBase::getModel() const +{ + return currentGroup->getModel(); +} +IMI_type InstanceBase::getModelItemType() const +{ + return IMI_Instance; +} +int InstanceBase::numChildren() const +{ + return 0; +} diff --git a/data/instancebase.h b/data/instancebase.h index 8c61aee0..fa043c5f 100644 --- a/data/instancebase.h +++ b/data/instancebase.h @@ -20,9 +20,11 @@ #include #include "../data/inifile.h" +#include "instancemodel.h" -class InstanceBase : public QObject +class InstanceBase : public QObject, public InstanceModelItem { + friend class InstanceGroup; Q_OBJECT public: explicit InstanceBase(QString rootDir, QObject *parent = 0); @@ -32,13 +34,25 @@ public: QString getInstName() const; void setInstName(QString name); -protected: + QString getInstID() const; + virtual IMI_type getModelItemType() const; + virtual InstanceModelItem* getParent() const; + virtual int numChildren() const; + virtual InstanceModelItem* getChild ( int index ) const; + virtual InstanceModel* getModel() const; + virtual QVariant data ( int column ) const; + virtual int getRow() const; private: - QString rootDir; + void setGroup ( InstanceGroup* group ) + { + currentGroup = group; + }; + QString rootDir; INIFile config; + InstanceGroup * currentGroup; }; #endif // INSTANCEBASE_H diff --git a/data/instancelist.cpp b/data/instancelist.cpp deleted file mode 100644 index 7385ba86..00000000 --- a/data/instancelist.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "instancelist.h" - -#include -#include - -#include "stdinstance.h" - -#include "../util/pathutils.h" - -InstanceList::InstanceList() : - QList() -{ - -} - -void InstanceList::addInstance(InstanceBase *inst) -{ - append(inst); -} - -void InstanceList::loadInstances(QString dir) -{ - qDebug("Loading instances"); - QDir instDir(dir); - QDirIterator iter(instDir); - - while (iter.hasNext()) - { - QString subDir = iter.next(); - if (QFileInfo(PathCombine(subDir, "instance.cfg")).exists()) - { - // TODO Differentiate between different instance types. - InstanceBase* inst = new StdInstance(subDir); - addInstance(inst); - } - } -} diff --git a/data/instancelist.h b/data/instancelist.h deleted file mode 100644 index 83ea48e2..00000000 --- a/data/instancelist.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef INSTANCELIST_H -#define INSTANCELIST_H - -#include - -#include "instancebase.h" - -class InstanceList : public QList -{ -public: - explicit InstanceList(); - - void addInstance(InstanceBase *inst); - - void loadInstances(QString dir); - -signals: - -public slots: - -}; - -#endif // INSTANCELIST_H diff --git a/data/instancemodel.cpp b/data/instancemodel.cpp new file mode 100644 index 00000000..239be5c5 --- /dev/null +++ b/data/instancemodel.cpp @@ -0,0 +1,403 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "instancemodel.h" + +#include +#include +#include +#include "stdinstance.h" + +#include "../util/pathutils.h" + +#include +#include + + +#define GROUP_FILE_FORMAT_VERSION 1 + +InstanceModel::InstanceModel( QObject* parent ) : + QAbstractItemModel() +{ +} + +InstanceModel::~InstanceModel() +{ + saveGroupInfo(); + for(int i = 0; i < groups.size(); i++) + { + delete groups[i]; + } +} + +void InstanceModel::addInstance( InstanceBase* inst, const QString& groupName ) +{ + auto group = getGroupByName(groupName); + group->addInstance(inst); +} + +void InstanceGroup::addInstance ( InstanceBase* inst ) +{ + instances.append(inst); + inst->setGroup(this); + // TODO: notify model. +} + + +void InstanceModel::initialLoad(QString dir) +{ + groupFile = dir + "/instgroups.json"; + implicitGroup = new InstanceGroup("Ungrouped", this); + groups.append(implicitGroup); + + // temporary map from instance ID to group name + QMap groupMap; + + using namespace boost::property_tree; + ptree pt; + + try + { + read_json(groupFile.toStdString(), pt); + + if (pt.get_optional("formatVersion") != GROUP_FILE_FORMAT_VERSION) + { + // TODO: Discard old formats. + } + + BOOST_FOREACH(const ptree::value_type& vp, pt.get_child("groups")) + { + ptree gPt = vp.second; + QString groupName = QString::fromUtf8(vp.first.c_str()); + + InstanceGroup *group = new InstanceGroup(groupName, this); + groups.push_back(group); + + if (gPt.get_child_optional("hidden")) + group->setHidden(gPt.get("hidden")); + + QVector groupInstances; + BOOST_FOREACH(const ptree::value_type& v, gPt.get_child("instances")) + { + QString key = QString::fromUtf8(v.second.data().c_str()); + groupMap[key] = groupName; + } + } + } + catch (json_parser_error e) + { + qDebug("Failed to read group list. JSON parser error."); +// wxLogError(_(), +// e.line(), wxStr(e.message()).c_str()); + } + catch (ptree_error e) + { + qDebug("Failed to read group list. Unknown ptree error."); + } + + qDebug("Loading instances"); + QDir instDir(dir); + QDirIterator iter(instDir); + + while (iter.hasNext()) + { + QString subDir = iter.next(); + if (QFileInfo(PathCombine(subDir, "instance.cfg")).exists()) + { + // TODO Differentiate between different instance types. + InstanceBase* inst = new StdInstance(subDir); + QString instID = inst->getInstID(); + auto iter = groupMap.find(instID); + if(iter != groupMap.end()) + { + addInstance(inst,iter.value()); + } + else + { + addInstance(inst); + } + } + } +} + +int InstanceModel::columnCount ( const QModelIndex& parent ) const +{ + // for now... + return 1; +} + +QVariant InstanceModel::data ( const QModelIndex& index, int role ) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole) + return QVariant(); + + InstanceModelItem *item = static_cast(index.internalPointer()); + + return item->data(index.column()); +} + +QModelIndex InstanceModel::index ( int row, int column, const QModelIndex& parent ) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + InstanceModelItem *parentItem; + + if (!parent.isValid()) + parentItem = (InstanceModelItem *) this; + else + parentItem = static_cast(parent.internalPointer()); + + InstanceModelItem *childItem = parentItem->getChild(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); + +} + +QModelIndex InstanceModel::parent ( const QModelIndex& index ) const +{ + if (!index.isValid()) + return QModelIndex(); + + InstanceModelItem *childItem = static_cast(index.internalPointer()); + InstanceModelItem *parentItem = childItem->getParent(); + + if (parentItem == this) + return QModelIndex(); + + return createIndex(parentItem->getRow(), 0, parentItem); +} + +int InstanceModel::rowCount ( const QModelIndex& parent ) const +{ + InstanceModelItem *parentItem; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentItem = (InstanceModelItem*) this; + else + parentItem = static_cast(parent.internalPointer()); + + return parentItem->numChildren(); +} + +bool InstanceModel::saveGroupInfo() const +{ + /* + using namespace boost::property_tree; + ptree pt; + + pt.put("formatVersion", GROUP_FILE_FORMAT_VERSION); + + try + { + typedef QMap > GroupListMap; + + GroupListMap groupLists; + for (auto iter = instances.begin(); iter != instances.end(); iter++) + { + InstanceGroup *group = getInstanceGroup(*iter); + + if (group != nullptr) + groupLists[group].push_back(*iter); + } + + ptree groupsPtree; + for (auto iter = groupLists.begin(); iter != groupLists.end(); iter++) + { + auto group = iter.key(); + auto & gList = iter.value(); + + ptree groupTree; + + groupTree.put("hidden", group->isHidden()); + + ptree instList; + for (auto iter2 = gList.begin(); iter2 != gList.end(); iter2++) + { + std::string instID((*iter2)->getInstID().toUtf8()); + instList.push_back(std::make_pair("", ptree(instID))); + } + groupTree.put_child("instances", instList); + + groupsPtree.push_back(std::make_pair(std::string(group->getName().toUtf8()), groupTree)); + } + pt.put_child("groups", groupsPtree); + + write_json(groupFile.toStdString(), pt); + } + catch (json_parser_error e) + { +// wxLogError(_("Failed to read group list.\nJSON parser error at line %i: %s"), +// e.line(), wxStr(e.message()).c_str()); + return false; + } + catch (ptree_error e) + { +// wxLogError(_("Failed to save group list. Unknown ptree error.")); + return false; + } + + return true; + */ + return false; +} + +void InstanceModel::setInstanceGroup ( InstanceBase* inst, const QString& groupName ) +{ + /* + InstanceGroup *prevGroup = getInstanceGroup(inst); + + if (prevGroup != nullptr) + { + groupsMap.remove(inst); + } + + if (!groupName.isEmpty()) + { + InstanceGroup *newGroup = nullptr; + + for (auto iter = root->groups.begin(); iter != root->groups.end(); iter++) + { + if ((*iter)->getName() == groupName) + { + newGroup = *iter; + } + } + + if (newGroup == nullptr) + { + newGroup = new InstanceGroup(groupName, this); + root->groups.push_back(newGroup); + } + + groupsMap[inst] = newGroup; + } + + // TODO: propagate change, reflect in model, etc. + //InstanceGroupChanged(inst); + */ +} + +InstanceGroup* InstanceModel::getGroupByName ( const QString& name ) const +{ + for (auto iter = groups.begin(); iter != groups.end(); iter++) + { + if ((*iter)->getName() == name) + return *iter; + } + return nullptr; +} +/* +void InstanceModel::setGroupFile ( QString filename ) +{ + groupFile = filename; +}*/ + +int InstanceModel::numChildren() const +{ + return groups.count(); +} + +InstanceModelItem* InstanceModel::getChild ( int index ) const +{ + return groups[index]; +} + +QVariant InstanceModel::data ( int role ) const +{ + switch(role) + { + case Qt::DisplayRole: + return "name"; + } + return QVariant(); +} + + +InstanceGroup::InstanceGroup(const QString& name, InstanceModel *parent) +{ + this->name = name; + this->model = parent; + this->hidden = false; +} + +InstanceGroup::~InstanceGroup() +{ + for(int i = 0; i < instances.size(); i++) + { + delete instances[i]; + } +} + + +QString InstanceGroup::getName() const +{ + return name; +} + +void InstanceGroup::setName(const QString& name) +{ + this->name = name; + //TODO: propagate change +} + +InstanceModelItem* InstanceGroup::getParent() const +{ + return model; +} + +bool InstanceGroup::isHidden() const +{ + return hidden; +} + +void InstanceGroup::setHidden(bool hidden) +{ + this->hidden = hidden; + //TODO: propagate change +} + +int InstanceGroup::getRow() const +{ + return model->getIndexOf( this); +} + +InstanceModelItem* InstanceGroup::getChild ( int index ) const +{ + return instances[index]; +} + +int InstanceGroup::numChildren() const +{ + return instances.size(); +} + +QVariant InstanceGroup::data ( int role ) const +{ + switch(role) + { + case Qt::DisplayRole: + return name; + default: + return QVariant(); + } +} \ No newline at end of file diff --git a/data/instancemodel.h b/data/instancemodel.h new file mode 100644 index 00000000..7b6cb8c6 --- /dev/null +++ b/data/instancemodel.h @@ -0,0 +1,137 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INSTANCELIST_H +#define INSTANCELIST_H + +#include +#include +#include +#include + +enum IMI_type +{ + IMI_Root, + IMI_Group, + IMI_Instance +}; + +class InstanceModel; +class InstanceGroup; +class InstanceBase; + +class InstanceModelItem +{ + public: + virtual IMI_type getModelItemType() const = 0; + virtual InstanceModelItem * getParent() const = 0; + virtual int numChildren() const = 0; + virtual InstanceModelItem * getChild(int index) const = 0; + virtual InstanceModel * getModel() const = 0; + virtual QVariant data(int role) const = 0; + virtual int getRow() const = 0; +}; + +class InstanceGroup : public InstanceModelItem +{ +public: + InstanceGroup(const QString& name, InstanceModel * model); + ~InstanceGroup(); + + QString getName() const; + void setName(const QString& name); + + bool isHidden() const; + void setHidden(bool hidden); + + virtual IMI_type getModelItemType() const + { + return IMI_Group; + } + virtual InstanceModelItem* getParent() const; + virtual InstanceModelItem* getChild ( int index ) const; + virtual int numChildren() const; + virtual InstanceModel * getModel() const + { + return model; + }; + virtual QVariant data ( int column ) const; + int getIndexOf(InstanceBase * inst) + { + return instances.indexOf(inst); + }; + virtual int getRow() const; + void addInstance ( InstanceBase* inst ); +protected: + QString name; + InstanceModel * model; + QVector instances; + bool hidden; + int row; +}; + +class InstanceModel : public QAbstractItemModel, public InstanceModelItem +{ +public: + explicit InstanceModel(QObject *parent = 0); + ~InstanceModel(); + + virtual int columnCount ( const QModelIndex& parent = QModelIndex() ) const; + virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; + virtual QModelIndex index ( int row, int column, const QModelIndex& parent = QModelIndex() ) const; + virtual QModelIndex parent ( const QModelIndex& child ) const; + virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; + + void addInstance(InstanceBase *inst, const QString& groupName = "Ungrouped"); + void setInstanceGroup(InstanceBase *inst, const QString & groupName); + InstanceGroup* getGroupByName(const QString & name) const; + + void initialLoad(QString dir); + bool saveGroupInfo() const; + + virtual IMI_type getModelItemType() const + { + return IMI_Root; + } + virtual InstanceModelItem * getParent() const + { + return nullptr; + }; + virtual int numChildren() const; + virtual InstanceModelItem* getChild ( int index ) const; + virtual InstanceModel* getModel() const + { + return nullptr; + }; + virtual QVariant data ( int column ) const; + int getIndexOf(const InstanceGroup * grp) const + { + return groups.indexOf((InstanceGroup *) grp); + }; + virtual int getRow() const + { + return 0; + }; +signals: + +public slots: + +private: + QString groupFile; + QVector groups; + InstanceGroup * implicitGroup; +}; + +#endif // INSTANCELIST_H -- cgit v1.2.3