From b84dfddd1b24e82dccb5a20d9c30570d26846e76 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Sat, 16 Mar 2013 03:01:51 +0100 Subject: Use the actual selection for instance launch. --- gui/mainwindow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index e691c8c4..676ec45e 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -198,10 +198,18 @@ void MainWindow::on_instanceView_customContextMenuRequested ( const QPoint &pos void MainWindow::on_actionLaunchInstance_triggered() { - QModelIndex index = view->currentIndex(); - if(index.isValid()) + QAbstractItemView * iv = view; + auto smodel = iv->selectionModel(); + QModelIndex mindex; + if(smodel->hasSelection()) { - Instance * inst = (Instance *) index.data(InstanceModel::InstancePointerRole).value(); + auto rows = smodel->selectedRows(); + mindex = rows.at(0); + } + + if(mindex.isValid()) + { + Instance * inst = (Instance *) mindex.data(InstanceModel::InstancePointerRole).value(); doLogin(inst->id()); } } -- cgit From 65faabeed48584c461ca21d784c3f1d46f67f832 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Mon, 18 Mar 2013 23:00:46 +0100 Subject: Connect instance list to model. --- gui/instancemodel.cpp | 27 +++++++++++++++++++++++++- gui/instancemodel.h | 6 ++++++ gui/mainwindow.cpp | 6 +++--- libmultimc/include/instancelist.h | 41 ++++++++++++++++++++++++++++++++------- libmultimc/src/instancelist.cpp | 40 +++++++++++++++++++++++++++++++++----- libutil/CMakeLists.txt | 3 --- main.cpp | 19 +----------------- 7 files changed, 105 insertions(+), 37 deletions(-) diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp index 73d0dbc1..49909940 100644 --- a/gui/instancemodel.cpp +++ b/gui/instancemodel.cpp @@ -6,8 +6,33 @@ InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent ) : QAbstractListModel ( parent ), m_instances ( &instances ) { cachedIcon = QIcon(":/icons/multimc/scalable/apps/multimc.svg"); + 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(); +} + +// TODO: this doesn't trigger yet +void InstanceModel::onInstanceChanged ( int index ) +{ + +} + +void InstanceModel::onInvalidated() +{ + beginResetModel(); + currentInstancesNumber = m_instances->count(); + endResetModel(); +} + + int InstanceModel::rowCount ( const QModelIndex& parent ) const { Q_UNUSED ( parent ); @@ -17,7 +42,7 @@ int InstanceModel::rowCount ( const QModelIndex& parent ) const QModelIndex InstanceModel::index ( int row, int column, const QModelIndex& parent ) const { Q_UNUSED ( parent ); - if ( row < 0 || row >= m_instances->count() ) + if ( row < 0 || row >= currentInstancesNumber ) return QModelIndex(); return createIndex ( row, column, ( void* ) m_instances->at ( row ).data() ); } diff --git a/gui/instancemodel.h b/gui/instancemodel.h index 995c51ec..de43b7b8 100644 --- a/gui/instancemodel.h +++ b/gui/instancemodel.h @@ -22,9 +22,15 @@ public: 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; QIcon cachedIcon; + int currentInstancesNumber; }; class InstanceProxyModel : public KCategorizedSortFilterProxyModel diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 676ec45e..b799bdcf 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -64,8 +64,6 @@ MainWindow::MainWindow ( QWidget *parent ) : { ui->setupUi ( this ); // Create the widget - instList.loadList(); - view = new KCategorizedView ( ui->centralWidget ); drawer = new KCategoryDrawer ( view ); @@ -100,7 +98,9 @@ MainWindow::MainWindow ( QWidget *parent ) : view->setModel ( proxymodel ); connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(instanceActivated(const QModelIndex &))); - + + // Load the instances. + instList.loadList(); } MainWindow::~MainWindow() diff --git a/libmultimc/include/instancelist.h b/libmultimc/include/instancelist.h index d4e7556a..3eef8bdc 100644 --- a/libmultimc/include/instancelist.h +++ b/libmultimc/include/instancelist.h @@ -17,16 +17,14 @@ #define INSTANCELIST_H #include - #include -#include "siglist.h" - +#include "instance.h" #include "libmmc_config.h" class Instance; -class LIBMULTIMC_EXPORT InstanceList : public QObject, public SigList< QSharedPointer > +class LIBMULTIMC_EXPORT InstanceList : public QObject { Q_OBJECT public: @@ -46,14 +44,43 @@ public: QString instDir() const { return m_instDir; } /*! - * \brief Loads the instance list. + * \brief Loads the instance list. Triggers notifications. */ InstListError loadList(); - DEFINE_SIGLIST_SIGNALS(QSharedPointer); - SETUP_SIGLIST_SIGNALS(QSharedPointer); + /*! + * \brief Get the instance at index + */ + InstancePtr at(int i) const + { + return m_instances.at(i); + }; + + /*! + * \brief Get the count of loaded instances + */ + int count() const + { + return m_instances.count(); + }; + + /// Clear all instances. Triggers notifications. + void clear(); + + /// Add an instance. Triggers notifications, returns the new index + int add(InstancePtr t); + + /// Get an instance by ID + InstancePtr getInstanceById (QString id); + +signals: + void instanceAdded(int index); + void instanceChanged(int index); + void invalidated(); + protected: QString m_instDir; + QList< InstancePtr > m_instances; }; #endif // INSTANCELIST_H diff --git a/libmultimc/src/instancelist.cpp b/libmultimc/src/instancelist.cpp index 78650634..83a72afb 100644 --- a/libmultimc/src/instancelist.cpp +++ b/libmultimc/src/instancelist.cpp @@ -15,11 +15,10 @@ #include "include/instancelist.h" -#include "siglist_impl.h" - #include #include #include +#include #include "include/instance.h" #include "include/instanceloader.h" @@ -37,7 +36,7 @@ InstanceList::InstListError InstanceList::loadList() { QDir dir(m_instDir); QDirIterator iter(dir); - + m_instances.clear(); while (iter.hasNext()) { QString subDir = iter.next(); @@ -78,10 +77,41 @@ InstanceList::InstListError InstanceList::loadList() qDebug(QString("Loaded instance %1").arg(inst->name()).toUtf8()); inst->setParent(this); - append(QSharedPointer(inst)); + m_instances.append(inst); } } } - + emit invalidated(); return NoError; } + +/// Clear all instances. Triggers notifications. +void InstanceList::clear() +{ + m_instances.clear(); + emit invalidated(); +}; + +/// Add an instance. Triggers notifications, returns the new index +int InstanceList::add(InstancePtr t) +{ + m_instances.append(t); + emit instanceAdded(count() - 1); + return count() - 1; +} + +InstancePtr InstanceList::getInstanceById(QString instId) +{ + QListIterator iter(m_instances); + InstancePtr inst; + while(iter.hasNext()) + { + inst = iter.next(); + if (inst->id() == instId) + break; + } + if (inst->id() != instId) + return InstancePtr(); + else + return iter.peekPrevious(); +} \ No newline at end of file diff --git a/libutil/CMakeLists.txt b/libutil/CMakeLists.txt index 5b2c3837..11b21426 100644 --- a/libutil/CMakeLists.txt +++ b/libutil/CMakeLists.txt @@ -31,9 +31,6 @@ include/pathutils.h include/osutils.h include/userutils.h include/cmdutils.h - -include/siglist.h -include/siglist_impl.h ) SET(LIBUTIL_SOURCES diff --git a/main.cpp b/main.cpp index cf193ff0..7c82d6d8 100644 --- a/main.cpp +++ b/main.cpp @@ -57,23 +57,6 @@ public: this->instId = instId; } -private: - InstancePtr findInstance(QString instId) - { - QListIterator iter(instances); - InstancePtr inst; - while(iter.hasNext()) - { - inst = iter.next(); - if (inst->id() == instId) - break; - } - if (inst->id() != instId) - return InstancePtr(); - else - return iter.peekPrevious(); - } - private slots: void onTerminated() { @@ -117,7 +100,7 @@ public: instances.loadList(); std::cout << "Launching Instance '" << qPrintable(instId) << "'" << std::endl; - instance = findInstance(instId); + instance = instances.getInstanceById(instId); if (instance.isNull()) { std::cout << "Could not find instance requested. note that you have to specify the ID, not the NAME" << std::endl; -- cgit From 7e222c3e8f4d1c007edafc31e75e7712813dd64b Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Mon, 18 Mar 2013 23:35:54 +0100 Subject: Loading instance groups and exposing them to the model --- gui/instancemodel.cpp | 2 +- libmultimc/include/instance.h | 7 +++ libmultimc/src/instancelist.cpp | 109 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp index 49909940..0051602b 100644 --- a/gui/instancemodel.cpp +++ b/gui/instancemodel.cpp @@ -78,7 +78,7 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const case KCategorizedSortFilterProxyModel::CategorySortRole: case KCategorizedSortFilterProxyModel::CategoryDisplayRole: { - return "IT'S A GROUP"; + return pdata->group(); } default: break; diff --git a/libmultimc/include/instance.h b/libmultimc/include/instance.h index c41e6718..9334dff8 100644 --- a/libmultimc/include/instance.h +++ b/libmultimc/include/instance.h @@ -65,6 +65,9 @@ class LIBMULTIMC_EXPORT Instance : public QObject //! The instance's notes. Q_PROPERTY(QString notes READ notes WRITE setNotes) + //! The instance's group. + Q_PROPERTY(QString group READ group WRITE setGroup) + /*! * Whether or not the instance's minecraft.jar needs to be rebuilt. * If this is true, when the instance launches, its jar mods will be @@ -181,6 +184,9 @@ public: virtual QString notes() const { return settings().get("notes").toString(); } virtual void setNotes(QString val) { settings().set("notes", val); } + virtual QString group() const { return m_group; } + virtual void setGroup(QString val) { m_group = val; } + virtual bool shouldRebuild() const { return settings().get("NeedsRebuild").toBool(); } virtual void setShouldRebuild(bool val) { settings().set("NeedsRebuild", val); } @@ -279,6 +285,7 @@ public: private: QString m_rootDir; + QString m_group; SettingsObject *m_settings; }; diff --git a/libmultimc/src/instancelist.cpp b/libmultimc/src/instancelist.cpp index 83a72afb..a835fcfe 100644 --- a/libmultimc/src/instancelist.cpp +++ b/libmultimc/src/instancelist.cpp @@ -19,12 +19,17 @@ #include #include #include +#include +#include +#include +#include #include "include/instance.h" #include "include/instanceloader.h" #include "pathutils.h" +const static int GROUP_FILE_FORMAT_VERSION = 1; InstanceList::InstanceList(const QString &instDir, QObject *parent) : QObject(parent), m_instDir("instances") @@ -36,6 +41,104 @@ InstanceList::InstListError InstanceList::loadList() { QDir dir(m_instDir); QDirIterator iter(dir); + + QString groupFileName = m_instDir + "/instgroups.json"; + // temporary map from instance ID to group name + QMap groupMap; + + // HACK: this is really an if. breaks after one iteration. + while (QFileInfo(groupFileName).exists()) + { + QFile groupFile(groupFileName); + + if (!groupFile.open(QIODevice::ReadOnly)) + { + // An error occurred. Ignore it. + qDebug("Failed to read instance group file."); + break; + } + + QTextStream in(&groupFile); + QString jsonStr = in.readAll(); + groupFile.close(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8(), &error); + + if (error.error != QJsonParseError::NoError) + { + qWarning(QString("Failed to parse instance group file: %1 at offset %2"). + arg(error.errorString(), QString::number(error.offset)).toUtf8()); + break; + } + + if (!jsonDoc.isObject()) + { + qWarning("Invalid group file. Root entry should be an object."); + break; + } + + QJsonObject rootObj = jsonDoc.object(); + + // Make sure the format version matches. + if (rootObj.value("formatVersion").toVariant().toInt() == GROUP_FILE_FORMAT_VERSION) + { + // Get the group list. + if (!rootObj.value("groups").isObject()) + { + qWarning("Invalid group list JSON: 'groups' should be an object."); + break; + } + + // Iterate through the list. + QJsonObject groupList = rootObj.value("groups").toObject(); + + for (QJsonObject::iterator iter = groupList.begin(); + iter != groupList.end(); iter++) + { + QString groupName = iter.key(); + + // If not an object, complain and skip to the next one. + if (!iter.value().isObject()) + { + qWarning(QString("Group '%1' in the group list should " + "be an object.").arg(groupName).toUtf8()); + continue; + } + + QJsonObject groupObj = iter.value().toObject(); + /* + // Create the group object. + InstanceGroup *group = new InstanceGroup(groupName, this); + groups.push_back(group); + + // If 'hidden' isn't a bool value, just assume it's false. + if (groupObj.value("hidden").isBool() && groupObj.value("hidden").toBool()) + { + group->setHidden(groupObj.value("hidden").toBool()); + } + */ + + if (!groupObj.value("instances").isArray()) + { + qWarning(QString("Group '%1' in the group list is invalid. " + "It should contain an array " + "called 'instances'.").arg(groupName).toUtf8()); + continue; + } + + // Iterate through the list of instances in the group. + QJsonArray instancesArray = groupObj.value("instances").toArray(); + + for (QJsonArray::iterator iter2 = instancesArray.begin(); + iter2 != instancesArray.end(); iter2++) + { + groupMap[(*iter2).toString()] = groupName; + } + } + } + break; + } m_instances.clear(); while (iter.hasNext()) { @@ -74,7 +177,11 @@ InstanceList::InstListError InstanceList::loadList() else { QSharedPointer inst(instPtr); - + auto iter = groupMap.find(inst->id()); + if(iter != groupMap.end()) + { + inst->setGroup((*iter)); + } qDebug(QString("Loaded instance %1").arg(inst->name()).toUtf8()); inst->setParent(this); m_instances.append(inst); -- cgit From d67d58e662159d53ee5fde37a6f60903f6350731 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Tue, 19 Mar 2013 03:20:49 +0100 Subject: Added background cat. Proof of concept :3 --- gui/instancedelegate.cpp | 12 +++++++++--- gui/mainwindow.cpp | 17 ++++++++++++++++- multimc.qrc | 3 +++ resources/catbgrnd2.png | Bin 0 -> 78285 bytes 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 resources/catbgrnd2.png diff --git a/gui/instancedelegate.cpp b/gui/instancedelegate.cpp index dac2dacb..86b7d399 100644 --- a/gui/instancedelegate.cpp +++ b/gui/instancedelegate.cpp @@ -33,9 +33,15 @@ ListViewDelegate::ListViewDelegate ( QObject* parent ) : QStyledItemDelegate ( p void drawSelectionRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect) { - if (!(option.state & QStyle::State_Selected)) - return; - painter->fillRect ( rect, option.palette.brush ( QPalette::Highlight ) ); + if ((option.state & QStyle::State_Selected)) + painter->fillRect ( rect, option.palette.brush ( QPalette::Highlight ) ); + else + { + QColor backgroundColor = option.palette.color(QPalette::Background); + backgroundColor.setAlpha(160); + painter->fillRect ( rect, QBrush(backgroundColor) ); + } + } void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect) diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index b799bdcf..a96d80a7 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -66,7 +66,22 @@ MainWindow::MainWindow ( QWidget *parent ) : // Create the widget view = new KCategorizedView ( ui->centralWidget ); drawer = new KCategoryDrawer ( view ); - + /* + QPalette pal = view->palette(); + pal.setBrush(QPalette::Base, QBrush(QPixmap(QString::fromUtf8(":/backgrounds/kitteh")))); + view->setPalette(pal); + */ + view->setStyleSheet( + "QListView\ + {\ + background-image: url(:/backgrounds/kitteh);\ + background-attachment: fixed;\ + background-clip: padding;\ + background-position: top right;\ + background-repeat: none;\ + background-color:palette(base);\ + }"); + view->setSelectionMode ( QAbstractItemView::SingleSelection ); //view->setSpacing( KDialog::spacingHint() ); view->setCategoryDrawer ( drawer ); diff --git a/multimc.qrc b/multimc.qrc index cfcc9829..acd9efd2 100644 --- a/multimc.qrc +++ b/multimc.qrc @@ -34,4 +34,7 @@ resources/icons/multimc.svg resources/XdgIcon.theme + + resources/catbgrnd2.png + diff --git a/resources/catbgrnd2.png b/resources/catbgrnd2.png new file mode 100644 index 00000000..2b949e0b Binary files /dev/null and b/resources/catbgrnd2.png differ -- cgit From 7d7e4034f48b578c87a4651075c2b73dc236181b Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Tue, 19 Mar 2013 06:24:34 +0100 Subject: Property change propagation, changing instance groups, icon preview --- gui/instancemodel.cpp | 13 ++++++++----- gui/instancemodel.h | 1 - gui/mainwindow.cpp | 33 ++++++++++++++++++++++++++++++--- gui/mainwindow.h | 7 ++++++- libmultimc/include/instance.h | 29 +++++++++++++++++++++++++---- libmultimc/include/instancelist.h | 3 +++ libmultimc/src/instancelist.cpp | 13 +++++++++++++ 7 files changed, 85 insertions(+), 14 deletions(-) diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp index 0051602b..3c96c8f0 100644 --- a/gui/instancemodel.cpp +++ b/gui/instancemodel.cpp @@ -5,7 +5,6 @@ InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent ) : QAbstractListModel ( parent ), m_instances ( &instances ) { - cachedIcon = QIcon(":/icons/multimc/scalable/apps/multimc.svg"); currentInstancesNumber = m_instances->count(); connect(m_instances,SIGNAL(instanceAdded(int)),this,SLOT(onInstanceAdded(int))); connect(m_instances,SIGNAL(instanceChanged(int)),this,SLOT(onInstanceChanged(int))); @@ -19,10 +18,10 @@ void InstanceModel::onInstanceAdded ( int index ) endInsertRows(); } -// TODO: this doesn't trigger yet void InstanceModel::onInstanceChanged ( int index ) { - + QModelIndex mx = InstanceModel::index(index); + dataChanged(mx,mx); } void InstanceModel::onInvalidated() @@ -71,8 +70,12 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const } case Qt::DecorationRole: { - // FIXME: replace with an icon cache - return cachedIcon; + // FIXME: replace with an icon cache/renderer + QString path = ":/icons/instances/"; + path += pdata->iconKey(); + QIcon icon(path); + return icon; + //else return QIcon(":/icons/multimc/scalable/apps/multimc.svg"); } // for now. case KCategorizedSortFilterProxyModel::CategorySortRole: diff --git a/gui/instancemodel.h b/gui/instancemodel.h index de43b7b8..208ee68e 100644 --- a/gui/instancemodel.h +++ b/gui/instancemodel.h @@ -29,7 +29,6 @@ public slots: private: const InstanceList* m_instances; - QIcon cachedIcon; int currentInstancesNumber; }; diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index a96d80a7..78f58713 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -116,6 +116,11 @@ MainWindow::MainWindow ( QWidget *parent ) : // Load the instances. instList.loadList(); + // just a test + /* + instList.at(0)->setGroup("TEST GROUP"); + instList.at(0)->setName("TEST ITEM"); + */ } MainWindow::~MainWindow() @@ -140,6 +145,18 @@ void MainWindow::on_actionAddInstance_triggered() newInstDlg->exec(); } +void MainWindow::on_actionChangeInstGroup_triggered() +{ + Instance* inst = selectedInstance(); + if(inst) + { + QString name ( inst->group() ); + name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ), QLineEdit::Normal, name ); + inst->setGroup(name); + } +} + + void MainWindow::on_actionViewInstanceFolder_triggered() { openInDefaultProgram ( globalSettings->get ( "InstanceDir" ).toString() ); @@ -210,8 +227,7 @@ void MainWindow::on_instanceView_customContextMenuRequested ( const QPoint &pos instContextMenu->exec ( view->mapToGlobal ( pos ) ); } - -void MainWindow::on_actionLaunchInstance_triggered() +Instance* MainWindow::selectedInstance() { QAbstractItemView * iv = view; auto smodel = iv->selectionModel(); @@ -224,7 +240,18 @@ void MainWindow::on_actionLaunchInstance_triggered() if(mindex.isValid()) { - Instance * inst = (Instance *) mindex.data(InstanceModel::InstancePointerRole).value(); + return (Instance *) mindex.data(InstanceModel::InstancePointerRole).value(); + } + else + return nullptr; +} + + +void MainWindow::on_actionLaunchInstance_triggered() +{ + Instance* inst = selectedInstance(); + if(inst) + { doLogin(inst->id()); } } diff --git a/gui/mainwindow.h b/gui/mainwindow.h index c2dedf74..5d990639 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -44,14 +44,19 @@ public: // Browser Dialog void openWebPage(QUrl url); + +private: + Instance *selectedInstance(); private slots: void on_actionAbout_triggered(); void on_actionAddInstance_triggered(); - void on_actionViewInstanceFolder_triggered(); + void on_actionChangeInstGroup_triggered(); + void on_actionViewInstanceFolder_triggered(); + void on_actionRefresh_triggered(); void on_actionViewCentralModsFolder_triggered(); diff --git a/libmultimc/include/instance.h b/libmultimc/include/instance.h index 9334dff8..258a0dab 100644 --- a/libmultimc/include/instance.h +++ b/libmultimc/include/instance.h @@ -176,16 +176,28 @@ public: //// General Info //// virtual QString name() { return settings().get("name").toString(); } - virtual void setName(QString val) { settings().set("name", val); } + virtual void setName(QString val) + { + settings().set("name", val); + emit propertiesChanged(this); + } virtual QString iconKey() const { return settings().get("iconKey").toString(); } - virtual void setIconKey(QString val) { settings().set("iconKey", val); } + virtual void setIconKey(QString val) + { + settings().set("iconKey", val); + emit propertiesChanged(this); + } virtual QString notes() const { return settings().get("notes").toString(); } virtual void setNotes(QString val) { settings().set("notes", val); } virtual QString group() const { return m_group; } - virtual void setGroup(QString val) { m_group = val; } + virtual void setGroup(QString val) + { + m_group = val; + emit propertiesChanged(this); + } virtual bool shouldRebuild() const { return settings().get("NeedsRebuild").toBool(); } virtual void setShouldRebuild(bool val) { settings().set("NeedsRebuild", val); } @@ -208,7 +220,10 @@ public: virtual qint64 lastLaunch() { return settings().get("lastLaunchTime").value(); } virtual void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch()) - { settings().set("lastLaunchTime", val); } + { + settings().set("lastLaunchTime", val); + emit propertiesChanged(this); + } ////// Directories ////// @@ -283,6 +298,12 @@ public: */ virtual SettingsObject &settings() const; +signals: + /*! + * \brief Signal emitted when properties relevant to the instance view change + */ + void propertiesChanged(Instance * inst); + private: QString m_rootDir; QString m_group; diff --git a/libmultimc/include/instancelist.h b/libmultimc/include/instancelist.h index 3eef8bdc..a0d8788a 100644 --- a/libmultimc/include/instancelist.h +++ b/libmultimc/include/instancelist.h @@ -78,6 +78,9 @@ signals: void instanceChanged(int index); void invalidated(); +private slots: + void propertiesChanged(Instance * inst); + protected: QString m_instDir; QList< InstancePtr > m_instances; diff --git a/libmultimc/src/instancelist.cpp b/libmultimc/src/instancelist.cpp index a835fcfe..f9c525d0 100644 --- a/libmultimc/src/instancelist.cpp +++ b/libmultimc/src/instancelist.cpp @@ -185,6 +185,7 @@ InstanceList::InstListError InstanceList::loadList() qDebug(QString("Loaded instance %1").arg(inst->name()).toUtf8()); inst->setParent(this); m_instances.append(inst); + connect(instPtr, SIGNAL(propertiesChanged(Instance*)),this, SLOT(propertiesChanged(Instance*))); } } } @@ -221,4 +222,16 @@ InstancePtr InstanceList::getInstanceById(QString instId) return InstancePtr(); else return iter.peekPrevious(); +} + +void InstanceList::propertiesChanged(Instance * inst) +{ + for(int i = 0; i < m_instances.count(); i++) + { + if(inst == m_instances[i].data()) + { + emit instanceChanged(i); + break; + } + } } \ No newline at end of file -- cgit From e4806ab08d0293d395c1718ab16d28ba2ae9d0ed Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Wed, 20 Mar 2013 07:59:35 +0100 Subject: Add SVG icon rendering/cache --- CMakeLists.txt | 5 +- gui/iconcache.cpp | 127 +++++++++++++++++++++++++++++++++ gui/iconcache.h | 43 +++++++++++ gui/instancemodel.cpp | 7 +- gui/mainwindow.cpp | 1 + resources/icons/instances/skeleton.svg | 40 ++--------- 6 files changed, 187 insertions(+), 36 deletions(-) create mode 100644 gui/iconcache.cpp create mode 100644 gui/iconcache.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cf6e1aab..fad09575 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,6 @@ ENDIF() # First, include header overrides include_directories(hacks) - ######## 3rd Party Libs ######## # Find the required Qt parts @@ -155,7 +154,7 @@ MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}") ######## Configure header ######## configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/include/config.h") - +include_directories(${PROJECT_BINARY_DIR}/include) ################################ FILES ################################ @@ -172,6 +171,7 @@ gui/aboutdialog.h gui/consolewindow.h gui/instancemodel.h gui/instancedelegate.h +gui/iconcache.h multimc_pragma.h @@ -200,6 +200,7 @@ gui/aboutdialog.cpp gui/consolewindow.cpp gui/instancemodel.cpp gui/instancedelegate.cpp +gui/iconcache.cpp java/javautils.cpp java/annotations.cpp diff --git a/gui/iconcache.cpp b/gui/iconcache.cpp new file mode 100644 index 00000000..520a7839 --- /dev/null +++ b/gui/iconcache.cpp @@ -0,0 +1,127 @@ +#include "iconcache.h" +#include +#include +#include +#include +#include + +IconCache* IconCache::m_Instance = 0; +QMutex IconCache::mutex; +#define MAX_SIZE 1024 + +class Private : public QWebView +{ + Q_OBJECT + +public: + QString name; + QSize size; + QMap icons; + +public: + Private() + { + connect(this, SIGNAL(loadFinished(bool)), this, SLOT(svgLoaded(bool))); + setFixedSize(MAX_SIZE, MAX_SIZE); + + QPalette pal = palette(); + pal.setColor(QPalette::Base, Qt::transparent); + setPalette(pal); + setAttribute(Qt::WA_OpaquePaintEvent, false); + size = QSize(128,128); + } + void renderSVGIcon(QString name); + +signals: + void svgRendered(); + +private slots: + void svgLoaded(bool ok); +}; + +void Private::svgLoaded(bool ok) +{ + if (!ok) + { + emit svgRendered(); + return; + } + // check for SVG root tag + QString root = page()->currentFrame()->documentElement().tagName(); + if (root.compare("svg", Qt::CaseInsensitive) != 0) + { + emit svgRendered(); + return; + } + + // get the size of the svg image, check if it's valid + auto elem = page()->currentFrame()->documentElement(); + double width = elem.attribute("width").toDouble(); + double height = elem.attribute("height").toDouble(); + if (width == 0.0 || height == 0.0 || width == MAX_SIZE || height == MAX_SIZE) + { + emit svgRendered(); + return; + } + + // create the target surface + QSize t = size.isValid() ? size : QSize(width, height); + QImage img(t, QImage::Format_ARGB32_Premultiplied); + img.fill(Qt::transparent); + + // prepare the painter, scale to required size + QPainter p(&img); + if(size.isValid()) + { + p.scale(size.width() / width, size.height() / height); + } + + // the best quality + p.setRenderHint(QPainter::Antialiasing); + p.setRenderHint(QPainter::TextAntialiasing); + p.setRenderHint(QPainter::SmoothPixmapTransform); + + page()->mainFrame()->render(&p,QWebFrame::ContentsLayer); + p.end(); + + icons[name] = QIcon(QPixmap::fromImage(img)); + emit svgRendered(); +} + +void Private::renderSVGIcon ( QString name ) +{ + // use event loop to wait for signal + QEventLoop loop; + this->name = name; + QString prefix = "qrc:/icons/instances/"; + QObject::connect(this, SIGNAL(svgRendered()), &loop, SLOT(quit())); + load(QUrl(prefix + name)); + loop.exec(); +} + +IconCache::IconCache():d(new Private()) +{ +} + +QIcon IconCache::getIcon ( QString name ) +{ + if(name == "default") + name = "infinity"; + { + auto iter = d->icons.find(name); + if(iter != d->icons.end()) + return *iter; + } + d->renderSVGIcon(name); + auto iter = d->icons.find(name); + if(iter != d->icons.end()) + return *iter; + + // Fallback for icons that don't exist. + QString path = ":/icons/instances/infinity"; + //path += name; + d->icons[name] = QIcon(path); + return d->icons[name]; +} + +#include "iconcache.moc" \ No newline at end of file diff --git a/gui/iconcache.h b/gui/iconcache.h new file mode 100644 index 00000000..5c5e4142 --- /dev/null +++ b/gui/iconcache.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +class Private; + +class IconCache +{ +public: + static IconCache* instance() + { + if (!m_Instance) + { + mutex.lock(); + if (!m_Instance) + m_Instance = new IconCache; + mutex.unlock(); + } + return m_Instance; + } + + static void drop() + { + mutex.lock(); + delete m_Instance; + m_Instance = 0; + mutex.unlock(); + } + + QIcon getIcon(QString name); + +private: + IconCache(); + // hide copy constructor + IconCache(const IconCache &); + // hide assign op + IconCache& operator=(const IconCache &); + static IconCache* m_Instance; + static QMutex mutex; + Private* d; +}; + \ No newline at end of file diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp index 3c96c8f0..8db985e8 100644 --- a/gui/instancemodel.cpp +++ b/gui/instancemodel.cpp @@ -1,6 +1,7 @@ #include "instancemodel.h" #include #include +#include "iconcache.h" InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent ) : QAbstractListModel ( parent ), m_instances ( &instances ) @@ -70,11 +71,15 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const } case Qt::DecorationRole: { + IconCache * ic = IconCache::instance(); // FIXME: replace with an icon cache/renderer + /* QString path = ":/icons/instances/"; path += pdata->iconKey(); QIcon icon(path); - return icon; + */ + QString key = pdata->iconKey(); + return ic->getIcon(key); //else return QIcon(":/icons/multimc/scalable/apps/multimc.svg"); } // for now. diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 78f58713..5a915e8c 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -71,6 +71,7 @@ MainWindow::MainWindow ( QWidget *parent ) : pal.setBrush(QPalette::Base, QBrush(QPixmap(QString::fromUtf8(":/backgrounds/kitteh")))); view->setPalette(pal); */ + view->setStyleSheet( "QListView\ {\ diff --git a/resources/icons/instances/skeleton.svg b/resources/icons/instances/skeleton.svg index b2da5a46..5d55f272 100644 --- a/resources/icons/instances/skeleton.svg +++ b/resources/icons/instances/skeleton.svg @@ -13,26 +13,13 @@ height="32" id="svg2" version="1.1" - inkscape:version="0.48.3.1 r9886" + inkscape:version="0.48.4 r9939" sodipodi:docname="skeleton.svg" inkscape:export-filename="/home/peterix/projects/MultiMC4/src/resources/insticons/skeleton128.png" inkscape:export-xdpi="360" inkscape:export-ydpi="360"> - - - - - - image/svg+xml - + @@ -612,7 +586,7 @@ x="7.9999995" y="1036.3622" /> Date: Sun, 24 Feb 2013 17:06:00 +0100 Subject: Port minecraft.jar version detection to Qt --- java/constants.h | 12 +++-- java/javautils.cpp | 130 +++++++++++++++++++++++++++++------------------------ java/javautils.h | 25 +++++++++-- 3 files changed, 101 insertions(+), 66 deletions(-) diff --git a/java/constants.h b/java/constants.h index 2f968d2e..80697ebe 100644 --- a/java/constants.h +++ b/java/constants.h @@ -7,7 +7,7 @@ namespace java class constant { public: - enum type_t:uint8_t + enum type_t : uint8_t { j_hole = 0, // HACK: this is a hole in the array, because java is crazy j_string_data = 1, @@ -22,6 +22,7 @@ namespace java j_interface_methodref = 11, j_nameandtype = 12 } type; + constant(util::membuffer & buf ) { buf.read(type); @@ -66,10 +67,12 @@ namespace java break; } } + constant(int fake) { type = j_hole; } + std::string toString() { std::ostringstream ss; @@ -142,7 +145,8 @@ namespace java uint16_t descriptor_index; } name_and_type; }; - }; + }; + /** * A helper class that represents the custom container used in Java class file for storage of constants */ @@ -181,7 +185,7 @@ namespace java index++; } } - }; + } typedef std::vector container_type; /** * Access constants based on jar file index numbers (index of the first element is 1) @@ -204,5 +208,5 @@ namespace java } private: container_type constants; - }; + }; } diff --git a/java/javautils.cpp b/java/javautils.cpp index a07d1541..bf4b5cdf 100644 --- a/java/javautils.cpp +++ b/java/javautils.cpp @@ -1,69 +1,81 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan + * + * 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 "multimc_pragma.h" #include "classfile.h" #include "javautils.h" -//#include -#include -//#include -//#include "mcversionlist.h" + +#include +#include namespace javautils { -QString GetMinecraftJarVersion(QString jar) + +QString GetMinecraftJarVersion(QString jarName) { - return "Unknown"; - /* - wxString fullpath = jar.GetFullPath(); - wxString version = MCVer_Unknown; - if(!jar.FileExists()) - return version; - std::auto_ptr entry; - // convert the local name we are looking for into the internal format - wxString name = wxZipEntry::GetInternalName("net/minecraft/client/Minecraft.class",wxPATH_UNIX); + QString version = MCVer_Unknown; + + // check if minecraft.jar exists + QFile jar(jarName); + if (!jar.exists()) + return version; + + // open minecraft.jar + QuaZip zip(&jar); + if (!zip.open(QuaZip::mdUnzip)) + return version; + + // open Minecraft.class + zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); + QuaZipFile Minecraft(&zip); + if (!Minecraft.open(QuaZipFile::ReadOnly)) + return version; - // open the zip - wxFFileInputStream inStream(jar.GetFullPath()); - wxZipInputStream zipIn(inStream); + // read Minecraft.class + qint64 size = Minecraft.size(); + char *classfile = new char[size]; + Minecraft.read(classfile, size); + + // parse Minecraft.class + try { + char *temp = classfile; + java::classfile MinecraftClass(temp, size); + java::constant_pool constants = MinecraftClass.constants; + for(java::constant_pool::container_type::const_iterator iter=constants.begin(); + iter != constants.end(); iter++) + { + const java::constant & constant = *iter; + if (constant.type != java::constant::j_string_data) + continue; + const std::string & str = constant.str_data; + if (str.compare(0, 20, "Minecraft Minecraft ") == 0) + { + version = str.substr(20).data(); + break; + } + } + } catch(java::classfile_exception &) {} + + // clean up + delete[] classfile; + Minecraft.close(); + zip.close(); + jar.close(); + + return version; +} - // call GetNextEntry() until the required internal name is found - do - { - entry.reset(zipIn.GetNextEntry()); - } - while (entry.get() != NULL && entry->GetInternalName() != name); - auto myentry = entry.get(); - if (myentry == NULL) - return version; - - // we got the entry, read the data - std::size_t size = myentry->GetSize(); - char *classdata = new char[size]; - zipIn.Read(classdata,size); - try - { - char * temp = classdata; - java::classfile Minecraft_jar(temp,size); - auto cnst = Minecraft_jar.constants; - auto iter = cnst.begin(); - while (iter != cnst.end()) - { - const java::constant & constant = *iter; - if(constant.type != java::constant::j_string_data) - { - iter++; - continue; - } - auto & str = constant.str_data; - const char * lookfor = "Minecraft Minecraft "; // length = 20 - if(str.compare(0,20,lookfor) == 0) - { - version = str.substr(20).data(); - break; - } - iter++; - } - } catch(java::classfile_exception &){} - delete[] classdata; - return version; - */ } -} \ No newline at end of file diff --git a/java/javautils.h b/java/javautils.h index c8b5a793..7f9b6d89 100644 --- a/java/javautils.h +++ b/java/javautils.h @@ -1,9 +1,28 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan + * + * 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. + */ #pragma once #include + +#define MCVer_Unknown "Unknown" + namespace javautils { - /* - * Get the version from a minecraft.jar by parsing its class files. Expensive! + /** + * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! */ QString GetMinecraftJarVersion(QString jar); -} \ No newline at end of file +} -- cgit From f01bf10dc511268ead551a191a6a3211c006ba44 Mon Sep 17 00:00:00 2001 From: Orochimarufan Date: Sun, 24 Feb 2013 18:22:35 +0100 Subject: Implement Keyring system base --- CMakeLists.txt | 7 +++ libsettings/include/keyring.h | 85 ++++++++++++++++++++++++++++++++++++ libsettings/src/keyring.cpp | 63 +++++++++++++++++++++++++++ libsettings/src/stubkeyring.cpp | 96 +++++++++++++++++++++++++++++++++++++++++ libsettings/src/stubkeyring.h | 42 ++++++++++++++++++ test.cpp | 60 ++++++++++++++++++++++++++ 6 files changed, 353 insertions(+) create mode 100644 libsettings/include/keyring.h create mode 100644 libsettings/src/keyring.cpp create mode 100644 libsettings/src/stubkeyring.cpp create mode 100644 libsettings/src/stubkeyring.h create mode 100644 test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ae3e784..6f0204c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ find_package(ZLIB REQUIRED) # Add quazip add_subdirectory(quazip) +include_directories(quazip) # Add bspatch add_subdirectory(patchlib) @@ -260,6 +261,12 @@ libUtil libSettings libMultiMC libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS}) ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libMultiMC libGroupView) +IF(DEFINED MMC_KEYRING_TEST) +# test.cpp +ADD_EXECUTABLE(Test test.cpp) +QT5_USE_MODULES(Test Core) +TARGET_LINK_LIBRARIES(Test libmmcutil libmmcsettings) +ENDIF() ################################ INSTALLATION AND PACKAGING ################################ # use QtCreator's QTDIR var diff --git a/libsettings/include/keyring.h b/libsettings/include/keyring.h new file mode 100644 index 00000000..4563a268 --- /dev/null +++ b/libsettings/include/keyring.h @@ -0,0 +1,85 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan + * + * 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 KEYRING_H +#define KEYRING_H + +#include + +#include "libsettings_config.h" + +/** + * @file libsettings/include/keyring.h + * Access to System Keyrings + */ + +/** + * @brief The Keyring class + * the System Keyring/Keychain/Wallet/Vault/etc + */ +class LIBMMCSETTINGS_EXPORT Keyring : public QObject +{ + Q_OBJECT +public: + /** + * @brief the System Keyring instance + * @return the Keyring instance + */ + static Keyring *instance(); + + /** + * @brief store a password in the Keyring + * @param service the service name + * @param username the account name + * @param password the password to store + * @return success + */ + virtual bool storePassword(QString service, QString username, QString password) = 0; + + /** + * @brief get a password from the Keyring + * @param service the service name + * @param username the account name + * @return the password (success=!isNull()) + */ + virtual QString getPassword(QString service, QString username) = 0; + + /** + * @brief lookup a password + * @param service the service name + * @param username the account name + * @return wether the password is available + */ + virtual bool hasPassword(QString service, QString username) = 0; + + /** + * @brief get a list of all stored accounts. + * @param service the service name + * @return + */ + virtual QStringList getStoredAccounts(QString service) = 0; + +protected: + /// fall back to StubKeyring if false + virtual bool isValid() { return false; } + +private: + static Keyring *m_instance; + static void destroy(); +}; + +#endif // KEYRING_H diff --git a/libsettings/src/keyring.cpp b/libsettings/src/keyring.cpp new file mode 100644 index 00000000..1b13e35c --- /dev/null +++ b/libsettings/src/keyring.cpp @@ -0,0 +1,63 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan + * + * 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 "include/keyring.h" + +#include "osutils.h" + +#include "stubkeyring.h" + +// system specific keyrings +/*#if defined(OSX) +class OSXKeychain; +#define KEYRING OSXKeychain +#elif defined(LINUX) +class XDGKeyring; +#define KEYRING XDGKeyring +#elif defined(WINDOWS) +class Win32Keystore; +#define KEYRING Win32Keystore +#else +#pragma message Keyrings are not supported on your os. Falling back to the insecure StubKeyring +#endif*/ + +Keyring *Keyring::instance() +{ + if (m_instance == nullptr) + { +#ifdef KEYRING + m_instance = new KEYRING(); + if (!m_instance->isValid()) + { + qWarning("Could not create SystemKeyring! falling back to StubKeyring."); + m_instance = new StubKeyring(); + } +#else + qWarning("Keyrings are not supported on your OS. Fallback StubKeyring is insecure!"); + m_instance = new StubKeyring(); +#endif + atexit(Keyring::destroy); + } + return m_instance; +} + +void Keyring::destroy() +{ + delete m_instance; +} + +Keyring *Keyring::m_instance; diff --git a/libsettings/src/stubkeyring.cpp b/libsettings/src/stubkeyring.cpp new file mode 100644 index 00000000..0e29d2f2 --- /dev/null +++ b/libsettings/src/stubkeyring.cpp @@ -0,0 +1,96 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan + * + * 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 "stubkeyring.h" + +#include + +// Scrambling +// this is NOT SAFE, but it's not plain either. +int scrambler = 0x9586309; + +QString scramble(QString in_) +{ + QByteArray in = in_.toUtf8(); + QByteArray out; + for (int i = 0; i + * + * 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 STUBKEYRING_H +#define STUBKEYRING_H + +#include "include/keyring.h" + +#include + +class StubKeyring : public Keyring +{ + Q_OBJECT +public: + virtual bool storePassword(QString service, QString username, QString password); + virtual QString getPassword(QString service, QString username); + virtual bool hasPassword(QString service, QString username); + virtual QStringList getStoredAccounts(QString service); + +private: + friend class Keyring; + explicit StubKeyring(); + virtual bool isValid() { return true; } + + QSettings m_settings; +}; + +#endif // STUBKEYRING_H diff --git a/test.cpp b/test.cpp new file mode 100644 index 00000000..26600220 --- /dev/null +++ b/test.cpp @@ -0,0 +1,60 @@ + +#include + +#include "keyring.h" +#include "cmdutils.h" + +using namespace Util::Commandline; + +#include + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + app.setApplicationName("MMC Keyring test"); + app.setOrganizationName("Orochimarufan"); + + Parser p; + p.addArgument("user", false); + p.addArgument("password", false); + p.addSwitch("set"); + p.addSwitch("get"); + p.addSwitch("list"); + p.addOption("service", "Test"); + p.addShortOpt("service", 's'); + + QHash args; + try { + args = p.parse(app.arguments()); + } catch (ParsingError) { + std::cout << "Syntax error." << std::endl; + return 1; + } + + if (args["set"].toBool()) { + if (args["user"].isNull() || args["password"].isNull()) { + std::cout << "set operation needs bot user and password set" << std::endl; + return 1; + } + + return Keyring::instance()->storePassword(args["service"].toString(), + args["user"].toString(), args["password"].toString()); + } else if (args["get"].toBool()) { + if (args["user"].isNull()) { + std::cout << "get operation needs user set" << std::endl; + return 1; + } + + std::cout << "Password: " << qPrintable(Keyring::instance()->getPassword(args["service"].toString(), + args["user"].toString())) << std::endl; + return 0; + } else if (args["list"].toBool()) { + QStringList accounts = Keyring::instance()->getStoredAccounts(args["service"].toString()); + std::cout << "stored accounts:" << std::endl << '\t' << qPrintable(accounts.join("\n\t")) << std::endl; + return 0; + } else { + std::cout << "No operation given!" << std::endl; + std::cout << qPrintable(p.compileHelp(argv[0])) << std::endl; + return 1; + } +} -- cgit From f4c9cb8c1d395422b7e4f1c27ac92b6df08a39bb Mon Sep 17 00:00:00 2001 From: Orochimarufan Date: Mon, 25 Feb 2013 22:47:03 +0100 Subject: refactor indendation, fix a bug in MinecraftProcess & fix a bug in InstanceLauncher --- java/constants.h | 8 +-- java/javautils.cpp | 86 ++++++++++++++++---------------- java/javautils.h | 4 +- libmultimc/include/minecraftprocess.h | 2 +- libmultimc/src/minecraftprocess.cpp | 2 + libsettings/include/keyring.h | 78 ++++++++++++++--------------- libsettings/src/keyring.cpp | 30 +++++------ libsettings/src/stubkeyring.cpp | 62 +++++++++++------------ libsettings/src/stubkeyring.h | 20 ++++---- libutil/include/cmdutils.h | 17 +++---- libutil/src/cmdutils.cpp | 16 +++--- main.cpp | 7 +-- test.cpp | 94 +++++++++++++++++------------------ 13 files changed, 211 insertions(+), 215 deletions(-) diff --git a/java/constants.h b/java/constants.h index 80697ebe..61aa5687 100644 --- a/java/constants.h +++ b/java/constants.h @@ -7,7 +7,7 @@ namespace java class constant { public: - enum type_t : uint8_t + enum type_t : uint8_t { j_hole = 0, // HACK: this is a hole in the array, because java is crazy j_string_data = 1, @@ -145,7 +145,7 @@ namespace java uint16_t descriptor_index; } name_and_type; }; - }; + }; /** * A helper class that represents the custom container used in Java class file for storage of constants @@ -185,7 +185,7 @@ namespace java index++; } } - } + } typedef std::vector container_type; /** * Access constants based on jar file index numbers (index of the first element is 1) @@ -208,5 +208,5 @@ namespace java } private: container_type constants; - }; + }; } diff --git a/java/javautils.cpp b/java/javautils.cpp index bf4b5cdf..4a359031 100644 --- a/java/javautils.cpp +++ b/java/javautils.cpp @@ -26,56 +26,56 @@ namespace javautils QString GetMinecraftJarVersion(QString jarName) { - QString version = MCVer_Unknown; + QString version = MCVer_Unknown; - // check if minecraft.jar exists - QFile jar(jarName); - if (!jar.exists()) - return version; + // check if minecraft.jar exists + QFile jar(jarName); + if (!jar.exists()) + return version; - // open minecraft.jar - QuaZip zip(&jar); - if (!zip.open(QuaZip::mdUnzip)) - return version; + // open minecraft.jar + QuaZip zip(&jar); + if (!zip.open(QuaZip::mdUnzip)) + return version; - // open Minecraft.class - zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); - QuaZipFile Minecraft(&zip); - if (!Minecraft.open(QuaZipFile::ReadOnly)) - return version; + // open Minecraft.class + zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); + QuaZipFile Minecraft(&zip); + if (!Minecraft.open(QuaZipFile::ReadOnly)) + return version; - // read Minecraft.class - qint64 size = Minecraft.size(); - char *classfile = new char[size]; - Minecraft.read(classfile, size); + // read Minecraft.class + qint64 size = Minecraft.size(); + char *classfile = new char[size]; + Minecraft.read(classfile, size); - // parse Minecraft.class - try { - char *temp = classfile; - java::classfile MinecraftClass(temp, size); - java::constant_pool constants = MinecraftClass.constants; - for(java::constant_pool::container_type::const_iterator iter=constants.begin(); - iter != constants.end(); iter++) - { - const java::constant & constant = *iter; - if (constant.type != java::constant::j_string_data) - continue; - const std::string & str = constant.str_data; - if (str.compare(0, 20, "Minecraft Minecraft ") == 0) - { - version = str.substr(20).data(); - break; - } - } - } catch(java::classfile_exception &) {} + // parse Minecraft.class + try { + char *temp = classfile; + java::classfile MinecraftClass(temp, size); + java::constant_pool constants = MinecraftClass.constants; + for(java::constant_pool::container_type::const_iterator iter=constants.begin(); + iter != constants.end(); iter++) + { + const java::constant & constant = *iter; + if (constant.type != java::constant::j_string_data) + continue; + const std::string & str = constant.str_data; + if (str.compare(0, 20, "Minecraft Minecraft ") == 0) + { + version = str.substr(20).data(); + break; + } + } + } catch(java::classfile_exception &) {} - // clean up - delete[] classfile; - Minecraft.close(); - zip.close(); - jar.close(); + // clean up + delete[] classfile; + Minecraft.close(); + zip.close(); + jar.close(); - return version; + return version; } } diff --git a/java/javautils.h b/java/javautils.h index 7f9b6d89..883eff1d 100644 --- a/java/javautils.h +++ b/java/javautils.h @@ -21,8 +21,8 @@ namespace javautils { - /** - * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! + /** + * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! */ QString GetMinecraftJarVersion(QString jar); } diff --git a/libmultimc/include/minecraftprocess.h b/libmultimc/include/minecraftprocess.h index 8986f7ad..d6b9f612 100644 --- a/libmultimc/include/minecraftprocess.h +++ b/libmultimc/include/minecraftprocess.h @@ -85,7 +85,7 @@ protected: QStringList m_arguments; void genArgs(); - void log(QString text); + void log(QString text, ConsoleWindow::WriteMode mode = ConsoleWindow::MULTIMC); protected slots: void finish(int, QProcess::ExitStatus status); diff --git a/libmultimc/src/minecraftprocess.cpp b/libmultimc/src/minecraftprocess.cpp index 943d76b1..3aecb1ee 100644 --- a/libmultimc/src/minecraftprocess.cpp +++ b/libmultimc/src/minecraftprocess.cpp @@ -197,6 +197,8 @@ void MinecraftProcess::launch() start(m_instance->settings().get("JavaPath").toString(), m_arguments); if (!waitForStarted()) { + log("Could not launch minecraft!", ConsoleWindow::ERROR); + return; //TODO: error handling } diff --git a/libsettings/include/keyring.h b/libsettings/include/keyring.h index 4563a268..afdc3bba 100644 --- a/libsettings/include/keyring.h +++ b/libsettings/include/keyring.h @@ -6,7 +6,7 @@ * 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 + * 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, @@ -33,53 +33,53 @@ */ class LIBMMCSETTINGS_EXPORT Keyring : public QObject { - Q_OBJECT + Q_OBJECT public: - /** - * @brief the System Keyring instance - * @return the Keyring instance - */ - static Keyring *instance(); + /** + * @brief the System Keyring instance + * @return the Keyring instance + */ + static Keyring *instance(); - /** - * @brief store a password in the Keyring - * @param service the service name - * @param username the account name - * @param password the password to store - * @return success - */ - virtual bool storePassword(QString service, QString username, QString password) = 0; + /** + * @brief store a password in the Keyring + * @param service the service name + * @param username the account name + * @param password the password to store + * @return success + */ + virtual bool storePassword(QString service, QString username, QString password) = 0; - /** - * @brief get a password from the Keyring - * @param service the service name - * @param username the account name - * @return the password (success=!isNull()) - */ - virtual QString getPassword(QString service, QString username) = 0; + /** + * @brief get a password from the Keyring + * @param service the service name + * @param username the account name + * @return the password (success=!isNull()) + */ + virtual QString getPassword(QString service, QString username) = 0; - /** - * @brief lookup a password - * @param service the service name - * @param username the account name - * @return wether the password is available - */ - virtual bool hasPassword(QString service, QString username) = 0; + /** + * @brief lookup a password + * @param service the service name + * @param username the account name + * @return wether the password is available + */ + virtual bool hasPassword(QString service, QString username) = 0; - /** - * @brief get a list of all stored accounts. - * @param service the service name - * @return - */ - virtual QStringList getStoredAccounts(QString service) = 0; + /** + * @brief get a list of all stored accounts. + * @param service the service name + * @return + */ + virtual QStringList getStoredAccounts(QString service) = 0; protected: - /// fall back to StubKeyring if false - virtual bool isValid() { return false; } + /// fall back to StubKeyring if false + virtual bool isValid() { return false; } private: - static Keyring *m_instance; - static void destroy(); + static Keyring *m_instance; + static void destroy(); }; #endif // KEYRING_H diff --git a/libsettings/src/keyring.cpp b/libsettings/src/keyring.cpp index 1b13e35c..9eaba684 100644 --- a/libsettings/src/keyring.cpp +++ b/libsettings/src/keyring.cpp @@ -6,7 +6,7 @@ * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless