diff --git a/CMakeLists.txt b/CMakeLists.txt index 58d4e21d..5938b07b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,6 @@ gui/logindialog.h gui/taskdialog.h gui/aboutdialog.h gui/consolewindow.h -gui/instancemodel.h gui/instancedelegate.h gui/versionselectdialog.h gui/lwjglselectdialog.h @@ -230,7 +229,6 @@ gui/logindialog.cpp gui/taskdialog.cpp gui/aboutdialog.cpp gui/consolewindow.cpp -gui/instancemodel.cpp gui/instancedelegate.cpp gui/versionselectdialog.cpp gui/lwjglselectdialog.cpp diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp deleted file mode 100644 index 39dea34b..00000000 --- a/gui/instancemodel.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "instancemodel.h" -#include -#include -#include -//#include "iconcache.h" - -InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent ) - : QAbstractListModel ( parent ), m_instances ( &instances ) -{ - currentInstancesNumber = m_instances->count(); - connect(m_instances,SIGNAL(instanceAdded(int)),this,SLOT(onInstanceAdded(int))); - connect(m_instances,SIGNAL(instanceChanged(int)),this,SLOT(onInstanceChanged(int))); - connect(m_instances,SIGNAL(invalidated()),this,SLOT(onInvalidated())); -} - -void InstanceModel::onInstanceAdded ( int index ) -{ - beginInsertRows(QModelIndex(), index, index); - currentInstancesNumber ++; - endInsertRows(); -} - -void InstanceModel::onInstanceChanged ( int index ) -{ - QModelIndex mx = InstanceModel::index(index); - dataChanged(mx,mx); -} - -void InstanceModel::onInvalidated() -{ - beginResetModel(); - currentInstancesNumber = m_instances->count(); - endResetModel(); -} - - -int InstanceModel::rowCount ( const QModelIndex& parent ) const -{ - Q_UNUSED ( parent ); - return m_instances->count(); -} - -QModelIndex InstanceModel::index ( int row, int column, const QModelIndex& parent ) const -{ - Q_UNUSED ( parent ); - if ( row < 0 || row >= currentInstancesNumber ) - return QModelIndex(); - return createIndex ( row, column, ( void* ) m_instances->at ( row ).data() ); -} - -QVariant InstanceModel::data ( const QModelIndex& index, int role ) const -{ - if ( !index.isValid() ) - { - return QVariant(); - } - BaseInstance *pdata = static_cast ( index.internalPointer() ); - switch ( role ) - { - case InstancePointerRole: - { - QVariant v = qVariantFromValue((void *) pdata); - return v; - } - case Qt::DisplayRole: - { - return pdata->name(); - } - case Qt::ToolTipRole: - { - return pdata->instanceRoot(); - } - case Qt::DecorationRole: - { - IconList * ic = IconList::instance(); - // FIXME: replace with an icon cache/renderer - /* - QString path = ":/icons/instances/"; - path += pdata->iconKey(); - QIcon icon(path); - */ - QString key = pdata->iconKey(); - return ic->getIcon(key); - //else return QIcon(":/icons/multimc/scalable/apps/multimc.svg"); - } - // for now. - case KCategorizedSortFilterProxyModel::CategorySortRole: - case KCategorizedSortFilterProxyModel::CategoryDisplayRole: - { - return pdata->group(); - } - default: - break; - } - return QVariant(); -} - -Qt::ItemFlags InstanceModel::flags ( const QModelIndex& index ) const -{ - Qt::ItemFlags f; - if ( index.isValid() ) - { - f |= ( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); - } - return f; -} - -InstanceProxyModel::InstanceProxyModel ( QObject *parent ) - : KCategorizedSortFilterProxyModel ( parent ) -{ - // disable since by default we are globally sorting by date: - setCategorizedModel(true); -} - -bool InstanceProxyModel::subSortLessThan ( - const QModelIndex& left, const QModelIndex& right ) const -{ - BaseInstance *pdataLeft = static_cast ( left.internalPointer() ); - BaseInstance *pdataRight = static_cast ( right.internalPointer() ); - //kDebug() << *pdataLeft << *pdataRight; - return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0; - //return pdataLeft->name() < pdataRight->name(); -} - -#include "instancemodel.moc" - diff --git a/gui/instancemodel.h b/gui/instancemodel.h deleted file mode 100644 index 52b58081..00000000 --- a/gui/instancemodel.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include "categorizedsortfilterproxymodel.h" -#include "logic/lists/InstanceList.h" -#include - -class InstanceModel : public QAbstractListModel -{ - Q_OBJECT -public: - enum AdditionalRoles - { - InstancePointerRole = 0x34B1CB48 ///< Return pointer to real instance - }; - explicit InstanceModel ( const InstanceList& instances, - QObject *parent = 0 ); - - QModelIndex index ( int row, int column = 0, - const QModelIndex& parent = QModelIndex() ) const; - int rowCount ( const QModelIndex& parent = QModelIndex() ) const; - QVariant data ( const QModelIndex& index, int role ) const; - Qt::ItemFlags flags ( const QModelIndex& index ) const; - -public slots: - void onInstanceAdded(int index); - void onInstanceChanged(int index); - void onInvalidated(); - -private: - const InstanceList* m_instances; - int currentInstancesNumber; -}; - -class InstanceProxyModel : public KCategorizedSortFilterProxyModel -{ -public: - explicit InstanceProxyModel ( QObject *parent = 0 ); - -protected: - virtual bool subSortLessThan ( const QModelIndex& left, const QModelIndex& right ) const; -}; - diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 5b6e034c..52971acf 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -63,7 +63,6 @@ #include #include -#include "instancemodel.h" #include "instancedelegate.h" #include "IconPickerDialog.h" #include "LabeledToolButton.h" @@ -108,12 +107,11 @@ MainWindow::MainWindow ( QWidget *parent ) : view->setUniformItemWidths(true); view->installEventFilter(this); - model = new InstanceModel ( instList,this ); proxymodel = new InstanceProxyModel ( this ); proxymodel->setSortRole ( KCategorizedSortFilterProxyModel::CategorySortRole ); proxymodel->setFilterRole ( KCategorizedSortFilterProxyModel::CategorySortRole ); //proxymodel->setDynamicSortFilter ( true ); - proxymodel->setSourceModel ( model ); + proxymodel->setSourceModel ( &instList ); proxymodel->sort ( 0 ); view->setFrameShape ( QFrame::NoFrame ); @@ -137,6 +135,7 @@ MainWindow::MainWindow ( QWidget *parent ) : this, SLOT(instanceChanged(const QModelIndex &,const QModelIndex &)) ); + connect(&instList,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); // Load the instances. FIXME: this is not the place I'd say. instList.loadList(); @@ -160,7 +159,6 @@ MainWindow::~MainWindow() { delete ui; delete proxymodel; - delete model; delete drawer; delete assets_downloader; } @@ -228,7 +226,7 @@ void MainWindow::instanceActivated ( QModelIndex index ) { if(!index.isValid()) return; - BaseInstance * inst = (BaseInstance *) index.data(InstanceModel::InstancePointerRole).value(); + BaseInstance * inst = (BaseInstance *) index.data(InstanceList::InstancePointerRole).value(); doLogin(); } @@ -380,8 +378,7 @@ void MainWindow::on_actionDeleteInstance_triggered() QString("This is permanent! Are you sure?\nAbout to delete: ") + m_selectedInstance->name()); if (response == QMessageBox::Yes) { - QDir(m_selectedInstance->instanceRoot()).removeRecursively(); - instList.loadList(); + m_selectedInstance->nuke(); } } } @@ -596,25 +593,32 @@ void MainWindow::on_actionInstanceSettings_triggered() void MainWindow::instanceChanged( const QModelIndex& current, const QModelIndex& previous ) { - QString iconKey = "infinity"; - - if(current.isValid() && nullptr != (m_selectedInstance = (BaseInstance *) current.data(InstanceModel::InstancePointerRole).value())) + if(current.isValid() && nullptr != (m_selectedInstance = (BaseInstance *) current.data(InstanceList::InstancePointerRole).value())) { ui->instanceToolBar->setEnabled(true); - iconKey = m_selectedInstance->iconKey(); + QString iconKey = m_selectedInstance->iconKey(); renameButton->setText(m_selectedInstance->name()); ui->actionChangeInstLWJGLVersion->setEnabled(m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion")); ui->actionEditInstMods->setEnabled(m_selectedInstance->menuActionEnabled("actionEditInstMods")); statusBar()->clearMessage(); statusBar()->showMessage(m_selectedInstance->getStatusbarDescription()); + IconList * iconListModel = IconList::instance(); + auto ico =iconListModel->getIcon(iconKey); + ui->actionChangeInstIcon->setIcon(ico); } else { - statusBar()->clearMessage(); - ui->instanceToolBar->setEnabled(false); - renameButton->setText("Rename Instance"); + selectionBad(); } - +} + +void MainWindow::selectionBad() +{ + m_selectedInstance = nullptr; + QString iconKey = "infinity"; + statusBar()->clearMessage(); + ui->instanceToolBar->setEnabled(false); + renameButton->setText("Rename Instance"); IconList * iconListModel = IconList::instance(); auto ico =iconListModel->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); @@ -622,7 +626,6 @@ void MainWindow::instanceChanged( const QModelIndex& current, const QModelIndex& - void MainWindow::on_actionEditInstNotes_triggered() { if (!m_selectedInstance) diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 6456346d..42f118b1 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -24,7 +24,6 @@ class LabeledToolButton; class QLabel; -class InstanceModel; class InstanceProxyModel; class KCategorizedView; class KCategoryDrawer; @@ -119,6 +118,8 @@ public slots: void instanceChanged (const QModelIndex & current,const QModelIndex & previous); + void selectionBad(); + void startTask(Task *task); void launchInstance(BaseInstance *inst, LoginResponse response); @@ -130,7 +131,6 @@ private: Ui::MainWindow *ui; KCategoryDrawer * drawer; KCategorizedView * view; - InstanceModel * model; InstanceProxyModel * proxymodel; InstanceList instList; MinecraftProcess *proc; diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index 6593e715..bd3229c8 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -17,6 +17,7 @@ #include "BaseInstance_p.h" #include +#include #include "inisettingsobject.h" #include "setting.h" @@ -83,6 +84,13 @@ BaseInstance::BaseInstance( BaseInstancePrivate* d_in, settings().registerSetting(new OverrideSetting("AutoCloseConsole", globalSettings->getSetting("AutoCloseConsole"))); } +void BaseInstance::nuke() +{ + QDir(instanceRoot()).removeRecursively(); + emit nuked(this); +} + + QString BaseInstance::id() const { return QFileInfo(instanceRoot()).fileName(); diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index a1e6075a..cc9422be 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -48,6 +48,9 @@ public: /// virtual destructor to make sure the destruction is COMPLETE virtual ~BaseInstance() {}; + /// nuke thoroughly - deletes the instance contents, notifies the list/model which is responsible of cleaning up the husk + void nuke(); + /// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to be unique. QString id() const; @@ -169,6 +172,11 @@ signals: * \brief Signal emitted when groups are affected in any way */ void groupChanged(); + /*! + * \brief The instance just got nuked. Hurray! + */ + void nuked(BaseInstance * inst); + protected: QSharedPointer inst_d; }; diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp index 1d33d8d6..1d13e3f2 100644 --- a/logic/lists/InstanceList.cpp +++ b/logic/lists/InstanceList.cpp @@ -26,13 +26,14 @@ #include "logic/lists/InstanceList.h" #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" +#include #include "pathutils.h" const static int GROUP_FILE_FORMAT_VERSION = 1; InstanceList::InstanceList(const QString &instDir, QObject *parent) : - QObject(parent), m_instDir("instances") + QAbstractListModel ( parent ), m_instDir("instances") { } @@ -42,6 +43,69 @@ InstanceList::~InstanceList() saveGroupList(); } +int InstanceList::rowCount ( const QModelIndex& parent ) const +{ + Q_UNUSED ( parent ); + return m_instances.count(); +} + +QModelIndex InstanceList::index ( int row, int column, const QModelIndex& parent ) const +{ + Q_UNUSED ( parent ); + if ( row < 0 || row >= m_instances.size() ) + return QModelIndex(); + return createIndex ( row, column, ( void* ) m_instances.at ( row ).data() ); +} + +QVariant InstanceList::data ( const QModelIndex& index, int role ) const +{ + if ( !index.isValid() ) + { + return QVariant(); + } + BaseInstance *pdata = static_cast ( index.internalPointer() ); + switch ( role ) + { + case InstancePointerRole: + { + QVariant v = qVariantFromValue((void *) pdata); + return v; + } + case Qt::DisplayRole: + { + return pdata->name(); + } + case Qt::ToolTipRole: + { + return pdata->instanceRoot(); + } + case Qt::DecorationRole: + { + IconList * ic = IconList::instance(); + QString key = pdata->iconKey(); + return ic->getIcon(key); + } + // for now. + case KCategorizedSortFilterProxyModel::CategorySortRole: + case KCategorizedSortFilterProxyModel::CategoryDisplayRole: + { + return pdata->group(); + } + default: + break; + } + return QVariant(); +} + +Qt::ItemFlags InstanceList::flags ( const QModelIndex& index ) const +{ + Qt::ItemFlags f; + if ( index.isValid() ) + { + f |= ( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); + } + return f; +} void InstanceList::groupChanged() { @@ -197,6 +261,8 @@ InstanceList::InstListError InstanceList::loadList() QMap groupMap; loadGroupList(groupMap); + beginResetModel(); + m_instances.clear(); QDir dir(m_instDir); QDirIterator iter(dir); @@ -251,25 +317,34 @@ InstanceList::InstListError InstanceList::loadList() m_instances.append(inst); connect(instPtr, SIGNAL(propertiesChanged(BaseInstance*)),this, SLOT(propertiesChanged(BaseInstance*))); connect(instPtr, SIGNAL(groupChanged()),this, SLOT(groupChanged())); + connect(instPtr, SIGNAL(nuked(BaseInstance*)), this, SLOT(instanceNuked(BaseInstance*))); } } - emit invalidated(); + endResetModel(); + emit dataIsInvalid(); return NoError; } /// Clear all instances. Triggers notifications. void InstanceList::clear() { + beginResetModel(); saveGroupList(); m_instances.clear(); - emit invalidated(); + endResetModel(); + emit dataIsInvalid(); }; /// Add an instance. Triggers notifications, returns the new index int InstanceList::add(InstancePtr t) { + beginInsertRows(QModelIndex(), m_instances.size(), m_instances.size()); m_instances.append(t); - emit instanceAdded(count() - 1); + t->setParent(this); + connect(t.data(), SIGNAL(propertiesChanged(BaseInstance*)),this, SLOT(propertiesChanged(BaseInstance*))); + connect(t.data(), SIGNAL(groupChanged()),this, SLOT(groupChanged())); + connect(t.data(), SIGNAL(nuked(BaseInstance*)), this, SLOT(instanceNuked(BaseInstance*))); + endInsertRows(); return count() - 1; } @@ -289,14 +364,54 @@ InstancePtr InstanceList::getInstanceById(QString instId) return iter.peekPrevious(); } -void InstanceList::propertiesChanged(BaseInstance * inst) +int InstanceList::getInstIndex ( BaseInstance* inst ) { for(int i = 0; i < m_instances.count(); i++) { if(inst == m_instances[i].data()) { - emit instanceChanged(i); - break; + return i; } } + return -1; } + + +void InstanceList::instanceNuked ( BaseInstance* inst ) +{ + int i = getInstIndex(inst); + if(i != -1) + { + beginRemoveRows(QModelIndex(),i,i); + m_instances.removeAt(i); + endRemoveRows(); + } +} + + +void InstanceList::propertiesChanged(BaseInstance * inst) +{ + int i = getInstIndex(inst); + if(i != -1) + { + emit dataChanged(index(i), index(i)); + } +} + +InstanceProxyModel::InstanceProxyModel ( QObject *parent ) + : KCategorizedSortFilterProxyModel ( parent ) +{ + // disable since by default we are globally sorting by date: + setCategorizedModel(true); +} + +bool InstanceProxyModel::subSortLessThan (const QModelIndex& left, const QModelIndex& right ) const +{ + BaseInstance *pdataLeft = static_cast ( left.internalPointer() ); + BaseInstance *pdataRight = static_cast ( right.internalPointer() ); + //kDebug() << *pdataLeft << *pdataRight; + return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0; + //return pdataLeft->name() < pdataRight->name(); +} + +#include "InstanceList.moc" \ No newline at end of file diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h index 50ba56f3..501edeb1 100644 --- a/logic/lists/InstanceList.h +++ b/logic/lists/InstanceList.h @@ -17,12 +17,15 @@ #include #include +#include +#include "categorizedsortfilterproxymodel.h" +#include #include "logic/BaseInstance.h" class BaseInstance; -class InstanceList : public QObject +class InstanceList : public QAbstractListModel { Q_OBJECT private: @@ -33,6 +36,16 @@ public: explicit InstanceList(const QString &instDir, QObject *parent = 0); virtual ~InstanceList(); +public: + QModelIndex index ( int row, int column = 0, const QModelIndex& parent = QModelIndex() ) const; + int rowCount ( const QModelIndex& parent = QModelIndex() ) const; + QVariant data ( const QModelIndex& index, int role ) const; + Qt::ItemFlags flags ( const QModelIndex& index ) const; + + enum AdditionalRoles + { + InstancePointerRole = 0x34B1CB48 ///< Return pointer to real instance + }; /*! * \brief Error codes returned by functions in the InstanceList class. * NoError Indicates that no error occurred. @@ -75,16 +88,26 @@ public: /// Get an instance by ID InstancePtr getInstanceById (QString id); - signals: - void instanceAdded(int index); - void instanceChanged(int index); - void invalidated(); + void dataIsInvalid(); private slots: void propertiesChanged(BaseInstance * inst); + void instanceNuked(BaseInstance * inst); void groupChanged(); +private: + int getInstIndex(BaseInstance * inst); protected: QString m_instDir; QList< InstancePtr > m_instances; }; + +class InstanceProxyModel : public KCategorizedSortFilterProxyModel +{ +public: + explicit InstanceProxyModel ( QObject *parent = 0 ); + +protected: + virtual bool subSortLessThan ( const QModelIndex& left, const QModelIndex& right ) const; +}; +