#ifndef MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED #define MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED #include namespace MOBase { class IPluginGame; } namespace Ui { class CreateInstanceDialog; }; namespace cid { class Page; } class PluginContainer; class Settings; // this is a wizard for creating a new instance, it is made out of Page objects, // see createinstancedialogpages.h // // each page can give back one or more pieces of information that is collected // in creationInfo() and used by finish() to do the actual creation // // pages can be disabled if they return true in skip(), which happens globally // for some (IntroPage has a setting in the registry), depending on context // (NexusPage is skipped if the Nexus authorization already exists) or explicitly (when // only some info about the instance is missing on startup, such as a game // variant) // class CreateInstanceDialog : public QDialog { Q_OBJECT public: enum class Actions { Find = 1 }; // instance type // enum Types { NoType = 0, Global, Portable }; // all the paths required by the instance, some may be empty, such as // basically all of them except for `base` when the user doesn't use the // "Advanced" part of the paths page // struct Paths { QString base; QString downloads; QString mods; QString profiles; QString overwrite; QString ini; auto operator<=>(const Paths&) const = default; }; struct ProfileSettings { bool localInis; bool localSaves; bool archiveInvalidation; auto operator<=>(const ProfileSettings&) const = default; }; // all the info filled in the various pages // struct CreationInfo { Types type; MOBase::IPluginGame* game; QString gameLocation; QString gameVariant; QString instanceName; QString dataPath; QString iniPath; Paths paths; ProfileSettings profileSettings; }; CreateInstanceDialog(const PluginContainer& pc, Settings* s, QWidget* parent = nullptr); ~CreateInstanceDialog(); Ui::CreateInstanceDialog* getUI(); const PluginContainer& pluginContainer(); Settings* settings(); // disables all the pages except for the given one, used on startup when some // specific info is missing template void setSinglePage(const QString& instanceName) { for (auto&& p : m_pages) { if (auto* tp = dynamic_cast(p.get())) { tp->setSkip(false); } else { p->setSkip(true); } } setSinglePageImpl(instanceName); } // returns the page having the give path, or null // template Page* getPage() { for (auto&& p : m_pages) { if (auto* tp = dynamic_cast(p.get())) { return tp; } } return nullptr; } // moves to the next page; if `allowFinish` is true, calls finish() if // currently on the last page // void next(bool allowFinish = true); // moves to the previous page, if any // void back(); // whether the current page reports that it is ready; if this is the last // page, next() would call finish() // bool canNext() const; // whether the current page is not the first one and there is an enabled page // prior // bool canBack() const; // selects the given page by index; this doesn't check if the page should be // skipped // void selectPage(std::size_t i); // moves by `d` pages, can be negative to move back // void changePage(int d); // creates the instance and closes the dialog // void finish(); // updates the navigation buttons based on the current page // void updateNavigation(); // whether this is the last enabled page // bool isOnLastPage() const; // returns whether the user has requested to switch to the new instance // bool switching() const; // gathers the info from all the pages as it appears, paths are not fixed; // see creationInfo() // CreationInfo rawCreationInfo() const; // gathers the info from all the pages: paths are converted to absolute and // the base dir variable is expanded everywhere; see rawCreationInfo() // CreationInfo creationInfo() const; private: std::unique_ptr ui; const PluginContainer& m_pc; Settings* m_settings; std::vector> m_pages; QString m_originalNext; bool m_switching; bool m_singlePage; // creates a shortcut for the given sequence // void addShortcut(QKeySequence seq, std::function f); // creates a shortcut for the given sequence and executes the action when // activated // void addShortcutAction(QKeySequence seq, Actions a); // calls action() with the given action on the selected page, if any // void doAction(Actions a); // called from setSinglePage(), does whatever doesn't need the T // void setSinglePageImpl(const QString& instanceName); // adds a line to the creation log // void logCreation(const QString& s); void logCreation(const std::wstring& s); // calls the given member function on all pages until one returns an object // that's not empty; used by gatherInfo() // template auto getSelected(MF mf, Args&&... args) const { // return type using T = decltype((std::declval().*mf)(std::forward(args)...)); for (auto&& p : m_pages) { const auto t = (p.get()->*mf)(std::forward(args)...); if (t != T()) { return t; } } return T(); } }; #endif // MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED