1 /* Copyright 2013-2019 MultiMC Contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include <QAbstractListModel>
19 
20 #include <QString>
21 #include <QList>
22 #include <memory>
23 
24 #include "Library.h"
25 #include "LaunchProfile.h"
26 #include "Component.h"
27 #include "ProfileUtils.h"
28 #include "BaseVersion.h"
29 #include "MojangDownloadInfo.h"
30 #include "multimc_logic_export.h"
31 #include "net/Mode.h"
32 
33 class MinecraftInstance;
34 struct ComponentListData;
35 class ComponentUpdateTask;
36 
37 class MULTIMC_LOGIC_EXPORT ComponentList : public QAbstractListModel
38 {
39     Q_OBJECT
40     friend ComponentUpdateTask;
41 public:
42     enum Columns
43     {
44         NameColumn = 0,
45         VersionColumn,
46         NUM_COLUMNS
47     };
48 
49     explicit ComponentList(MinecraftInstance * instance);
50     virtual ~ComponentList();
51 
52     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
53     virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
54     virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
55     virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
56     virtual int columnCount(const QModelIndex &parent) const override;
57     virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
58 
59     /// call this to explicitly mark the component list as loaded - this is used to build a new component list from scratch.
60     void buildingFromScratch();
61 
62     /// install more jar mods
63     void installJarMods(QStringList selectedFiles);
64 
65     /// install a jar/zip as a replacement for the main jar
66     void installCustomJar(QString selectedFile);
67 
68     enum MoveDirection { MoveUp, MoveDown };
69     /// move component file # up or down the list
70     void move(const int index, const MoveDirection direction);
71 
72     /// remove component file # - including files/records
73     bool remove(const int index);
74 
75     /// remove component file by id - including files/records
76     bool remove(const QString id);
77 
78     bool customize(int index);
79 
80     bool revertToBase(int index);
81 
82     /// reload the list, reload all components, resolve dependencies
83     void reload(Net::Mode netmode);
84 
85     // reload all components, resolve dependencies
86     void resolve(Net::Mode netmode);
87 
88     /// get current running task...
89     shared_qobject_ptr<Task> getCurrentTask();
90 
91     std::shared_ptr<LaunchProfile> getProfile() const;
92 
93     // NOTE: used ONLY by MinecraftInstance to provide legacy version mappings from instance config
94     void setOldConfigVersion(const QString &uid, const QString &version);
95 
96     QString getComponentVersion(const QString &uid) const;
97 
98     bool setComponentVersion(const QString &uid, const QString &version, bool important = false);
99 
100     bool installEmpty(const QString &uid, const QString &name);
101 
102     QString patchFilePathForUid(const QString &uid) const;
103 
104     /// if there is a save scheduled, do it now.
105     void saveNow();
106 
107 signals:
108     void minecraftChanged();
109 
110 public:
111     /// get the profile component by id
112     Component * getComponent(const QString &id);
113 
114     /// get the profile component by index
115     Component * getComponent(int index);
116 
117 private:
118     void scheduleSave();
119     bool saveIsScheduled() const;
120 
121     /// apply the component patches. Catches all the errors and returns true/false for success/failure
122     void invalidateLaunchProfile();
123 
124     /// Add the component to the internal list of patches
125     void appendComponent(ComponentPtr component);
126     /// insert component so that its index is ideally the specified one (returns real index)
127     void insertComponent(size_t index, ComponentPtr component);
128 
129     QString componentsFilePath() const;
130     QString patchesPattern() const;
131 
132 private slots:
133     void save_internal();
134     void updateSucceeded();
135     void updateFailed(const QString & error);
136     void componentDataChanged();
137     void disableInteraction(bool disable);
138 
139 private:
140     bool load();
141     bool installJarMods_internal(QStringList filepaths);
142     bool installCustomJar_internal(QString filepath);
143     bool removeComponent_internal(ComponentPtr patch);
144 
145     bool migratePreComponentConfig();
146 
147 private: /* data */
148 
149     std::unique_ptr<ComponentListData> d;
150 };
151