diff options
author | Andrew <forkk@forkk.net> | 2013-12-01 14:28:47 -0600 |
---|---|---|
committer | Andrew <forkk@forkk.net> | 2013-12-01 14:28:47 -0600 |
commit | 613699b3626aea750093ab7eaaeccaa28c0e87c6 (patch) | |
tree | 7fd542b8f4be10359ba2aaeac9834f1b5c86a750 | |
parent | 2427ad687137bbcfc7303a931d7e0b74d5325e48 (diff) | |
parent | 75c4d97b90e39f2bda6e682def0fdda044cbcf6f (diff) | |
download | MultiMC-613699b3626aea750093ab7eaaeccaa28c0e87c6.tar MultiMC-613699b3626aea750093ab7eaaeccaa28c0e87c6.tar.gz MultiMC-613699b3626aea750093ab7eaaeccaa28c0e87c6.tar.lz MultiMC-613699b3626aea750093ab7eaaeccaa28c0e87c6.tar.xz MultiMC-613699b3626aea750093ab7eaaeccaa28c0e87c6.zip |
Merge branch 'develop' of github.com:MultiMC/MultiMC5 into develop
56 files changed, 778 insertions, 563 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f3cacbe2..79a69225 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,14 +27,14 @@ ENDIF() ######## Set compiler flags ######## IF(APPLE) message(STATUS "Using APPLE CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") ELSEIF(UNIX) # assume GCC, add C++0x/C++11 stuff MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") ELSEIF(MINGW) MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall") ENDIF() ################################ INCLUDE LIBRARIES ################################ @@ -48,6 +48,23 @@ find_package(Qt5LinguistTools REQUIRED) include_directories(${Qt5Widgets_INCLUDE_DIRS}) +# The Qt5 cmake files don't provide its install paths, so ask qmake. +get_target_property(QMAKE_EXECUTABLE Qt5::qmake LOCATION) +function(QUERY_QMAKE VAR RESULT) + exec_program(${QMAKE_EXECUTABLE} ARGS "-query ${VAR}" RETURN_VALUE return_code OUTPUT_VARIABLE output ) + if(NOT return_code) + file(TO_CMAKE_PATH "${output}" output) + set(${RESULT} ${output} PARENT_SCOPE) + endif(NOT return_code) +endfunction(QUERY_QMAKE) + +query_qmake(QT_INSTALL_PLUGINS QT_PLUGINS_DIR) +query_qmake(QT_INSTALL_IMPORTS QT_IMPORTS_DIR) +query_qmake(QT_INSTALL_LIBS QT_LIBS_DIR) +query_qmake(QT_HOST_DATA QT_DATA_DIR) +set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) + + ######## Included Libs ######## # Add quazip @@ -289,11 +306,14 @@ logic/auth/MojangAccount.h logic/auth/MojangAccount.cpp logic/auth/YggdrasilTask.h logic/auth/YggdrasilTask.cpp -logic/auth/AuthenticateTask.h -logic/auth/AuthenticateTask.cpp -logic/auth/ValidateTask.h -logic/auth/ValidateTask.cpp - +logic/auth/flows/AuthenticateTask.h +logic/auth/flows/AuthenticateTask.cpp +logic/auth/flows/RefreshTask.cpp +logic/auth/flows/RefreshTask.cpp +logic/auth/flows/ValidateTask.h +logic/auth/flows/ValidateTask.cpp +logic/auth/flows/InvalidateTask.h +logic/auth/flows/InvalidateTask.cpp # legacy instances logic/LegacyInstance.h @@ -439,7 +459,6 @@ CONFIGURE_FILE(generated.qrc.in generated.qrc) QT5_ADD_RESOURCES(GENERATED_QRC ${CMAKE_CURRENT_BINARY_DIR}/generated.qrc) QT5_ADD_RESOURCES(GRAPHICS_QRC graphics.qrc) - # Add executable ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GRAPHICS_QRC} ${GENERATED_QRC} ${MULTIMC_RCS}) @@ -449,110 +468,122 @@ TARGET_LINK_LIBRARIES(MultiMC xz-embedded unpack200 quazip libUtil libSettings l QT5_USE_MODULES(MultiMC Core Widgets Network Xml ${MultiMC_QT_ADDITIONAL_MODULES}) ADD_DEPENDENCIES(MultiMC MultiMCLauncher JavaCheck) -option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF) -IF(BUILD_KEYRING_TEST) - # test.cpp - ADD_EXECUTABLE(Test test.cpp) - QT5_USE_MODULES(Test Core) - TARGET_LINK_LIBRARIES(Test libUtil libSettings) -ENDIF() - ################################ INSTALLATION AND PACKAGING ################################ -# use QtCreator's QTDIR var -IF(DEFINED ENV{QTDIR}) - SET(Qt5_DIR $ENV{QTDIR}) -ENDIF() -######## Plugin and library folders ######## - -SET(PLUGIN_DEST_DIR plugins) -SET(QTCONF_DEST_DIR .) -SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC") - -IF(WIN32) - SET(PLUGIN_DEST_DIR .) - SET(QTCONF_DEST_DIR .) - SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe") -ENDIF() +######## Packaging/install paths setup ######## -IF(UNIX) -IF(APPLE) +IF(UNIX AND APPLE) SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS) SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources) - SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app") -ELSE() - SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC") -ENDIF() -ENDIF() - -SET(QT_PLUGINS_DIR ${Qt5_DIR}/plugins) -SET(QT_LIBRARY_DIRS ${Qt5_DIR}/lib) - + SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app") -######## OS X Bundle Info ######## - -IF(APPLE) SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC") SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.") - SET(MACOSX_BUNDLE_BUNDLE_VERSION - "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}") + SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}") #SET(MACOSX_BUNDLE_GUI_IDENTIFIER "") SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns) -ENDIF(APPLE) +ELSEIF(UNIX) + SET(PLUGIN_DEST_DIR plugins) + SET(QTCONF_DEST_DIR .) + SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC") +ELSEIF(WIN32) + SET(PLUGIN_DEST_DIR .) + SET(QTCONF_DEST_DIR .) + SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe") +ENDIF() + +# directories to look for dependencies +SET(DIRS "${QT_LIBS_DIR}") ######## Install ######## #### Executable #### -IF(WIN32) -INSTALL(TARGETS MultiMC - BUNDLE DESTINATION . COMPONENT Runtime - LIBRARY DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION . COMPONENT Runtime -) -ENDIF() -IF(UNIX) -IF(APPLE) -INSTALL(TARGETS MultiMC - BUNDLE DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime -) -ELSE() -INSTALL(TARGETS MultiMC - BUNDLE DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION bin COMPONENT Runtime -) -INSTALL(PROGRAMS package/linux/MultiMC DESTINATION .) -ENDIF() -ENDIF() +IF(APPLE AND UNIX) ## OSX + INSTALL(TARGETS MultiMC + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION MultiMC.app/Contents/MacOS COMPONENT Runtime + ) +ELSEIF(UNIX) ## LINUX and similar + INSTALL(TARGETS MultiMC + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION bin COMPONENT Runtime + ) + INSTALL(PROGRAMS package/linux/MultiMC DESTINATION .) -#### Plugins #### +ELSEIF(WIN32) ## WINDOWS + INSTALL(TARGETS MultiMC + BUNDLE DESTINATION . COMPONENT Runtime + LIBRARY DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION . COMPONENT Runtime + ) +ENDIF() -OPTION(MultiMC_INSTALL_SHARED_LIBS "if set, Qt's shared libraries will be copied to the installation directory on install") +#### Dist package logic #### -IF (MultiMC_INSTALL_SHARED_LIBS) - # Image formats - INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime) +if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") +# Image formats +INSTALL( + DIRECTORY "${QT_PLUGINS_DIR}/imageformats" + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "tga|svg|tiff|mng" EXCLUDE +) - # Platform plugins - INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/platforms" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime) +# Platform plugins +INSTALL( + DIRECTORY "${QT_PLUGINS_DIR}/platforms" + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "minimal|linuxfb|offscreen" EXCLUDE +) +else() +# Image formats +INSTALL( + DIRECTORY "${QT_PLUGINS_DIR}/imageformats" + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "tga|svg|tiff|mng" EXCLUDE + REGEX "d\\." EXCLUDE + REGEX "_debug\\." EXCLUDE +) - # qtconf - INSTALL(CODE " - FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\") - " COMPONENT Runtime) +# Platform plugins +INSTALL( + DIRECTORY "${QT_PLUGINS_DIR}/platforms" + DESTINATION ${PLUGIN_DEST_DIR} + COMPONENT Runtime + REGEX "minimal|linuxfb|offscreen" EXCLUDE + REGEX "d\\." EXCLUDE + REGEX "_debug\\." EXCLUDE +) +endif() + +# qtconf +INSTALL( + CODE " +FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\") +" + COMPONENT Runtime +) - # Dirs to look for dependencies. - SET(DIRS "${QT_LIBRARY_DIRS}") +INSTALL( + CODE " +FILE(GLOB_RECURSE QTPLUGINS \"\${CMAKE_INSTALL_PREFIX}/${PLUGIN_DEST_DIR}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") +function(gp_resolved_file_type_override resolved_file type_var) + if(resolved_file MATCHES \"^/usr/lib/libQt\") + message(\"resolving \${resolved_file} as other\") + set(\${type_var} other PARENT_SCOPE) + endif() +endfunction() + +include(BundleUtilities) +fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\") +" + COMPONENT Runtime +) - INSTALL(CODE " - file(GLOB_RECURSE QTPLUGINS - \"\${CMAKE_INSTALL_PREFIX}/${PLUGIN_DEST_DIR}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") - include(BundleUtilities) - fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\") - " COMPONENT Runtime) -ENDIF() ######## Package ######## @@ -596,14 +627,12 @@ include_directories(${PROJECT_BINARY_DIR}/include) file (GLOB TRANSLATIONS_FILES translations/*.ts) option (UPDATE_TRANSLATIONS "Update source translation translations/*.ts files (WARNING: make clean will delete the source .ts files! Danger!)") -if (UPDATE_TRANSLATIONS) - qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES}) -else (UPDATE_TRANSLATIONS) - qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES}) -endif (UPDATE_TRANSLATIONS) +IF(UPDATE_TRANSLATIONS) + qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES}) +ELSE() + qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES}) +ENDIF() add_custom_target (translations DEPENDS ${QM_FILES}) install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations) - - diff --git a/MultiMC.cpp b/MultiMC.cpp index a41f5f0a..e10292ab 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -189,6 +189,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv), case QNetworkProxy::FtpCachingProxy: proxyDesc = "FTP caching: "; break; + default: + proxyDesc = "DERP proxy: "; + break; } proxyDesc += QString("%3@%1:%2 pass %4") .arg(proxy.hostName()) @@ -326,6 +329,7 @@ void MultiMC::initGlobalSettings() m_settings->registerSetting(new Setting("InstSortMode", "Name")); + m_settings->registerSetting(new Setting("SelectedInstance", QString())); // Persistent value for the client ID m_settings->registerSetting(new Setting("YggdrasilClientToken", "")); diff --git a/depends/groupview/src/categorizedview.cpp b/depends/groupview/src/categorizedview.cpp index f4449949..1345205c 100644 --- a/depends/groupview/src/categorizedview.cpp +++ b/depends/groupview/src/categorizedview.cpp @@ -58,18 +58,6 @@ struct KCategorizedView::Private::Item struct KCategorizedView::Private::Block { - Block() - : topLeft ( QPoint() ) - , height ( -1 ) - , firstIndex ( QModelIndex() ) - , quarantineStart ( QModelIndex() ) - , items ( QList<Item>() ) - , outOfQuarantine ( false ) - , alternate ( false ) - , collapsed ( false ) - { - } - bool operator!= ( const Block &rhs ) const { return firstIndex != rhs.firstIndex; @@ -83,7 +71,7 @@ struct KCategorizedView::Private::Block } QPoint topLeft; - int height; + int height = -1; QPersistentModelIndex firstIndex; // if we have n elements on this block, and we inserted an element at position i. The quarantine // will start at index (i, column, parent). This means that for all elements j where i <= j <= n, the @@ -97,25 +85,16 @@ struct KCategorizedView::Private::Block // this affects the whole block, not items separately. items contain the topLeft point relative // to the block. Because of insertions or removals a whole block can be moved, so the whole block // will enter in quarantine, what is faster than moving all items in absolute terms. - bool outOfQuarantine; + bool outOfQuarantine = false; // should we alternate its color ? is just a hint, could not be used - bool alternate; - bool collapsed; + bool alternate = false; + bool collapsed = false; }; KCategorizedView::Private::Private ( KCategorizedView *q ) : q ( q ) - , proxyModel ( 0 ) - , categoryDrawer ( 0 ) - , categorySpacing ( 5 ) - , alternatingBlockColors ( false ) - , collapsibleBlocks ( false ) , hoveredBlock ( new Block() ) - , hoveredIndex ( QModelIndex() ) - , pressedPosition ( QPoint() ) - , rubberBandRect ( QRect() ) - , constantItemWidth( 0 ) { } diff --git a/depends/groupview/src/categorizedview_p.h b/depends/groupview/src/categorizedview_p.h index 13809312..524bba3a 100644 --- a/depends/groupview/src/categorizedview_p.h +++ b/depends/groupview/src/categorizedview_p.h @@ -137,14 +137,15 @@ public: */ void _k_slotCollapseOrExpandClicked(QModelIndex); - KCategorizedView *q; - KCategorizedSortFilterProxyModel *proxyModel; - KCategoryDrawer *categoryDrawer; - int categorySpacing; - bool alternatingBlockColors; - bool collapsibleBlocks; - bool constantItemWidth; - + KCategorizedView *q = nullptr; + KCategorizedSortFilterProxyModel *proxyModel = nullptr; + KCategoryDrawer *categoryDrawer = nullptr; + int categorySpacing = 5; + bool alternatingBlockColors = false; + bool collapsibleBlocks = false; + bool constantItemWidth = false; + + // FIXME: this is some really weird logic. Investigate. Block *hoveredBlock; QString hoveredCategory; QModelIndex hoveredIndex; diff --git a/depends/groupview/src/categorydrawer.cpp b/depends/groupview/src/categorydrawer.cpp index 04903206..214ce3b2 100644 --- a/depends/groupview/src/categorydrawer.cpp +++ b/depends/groupview/src/categorydrawer.cpp @@ -42,9 +42,9 @@ public: ~Private() { } + KCategorizedView *view; int leftMargin; int rightMargin; - KCategorizedView *view; }; KCategoryDrawer::KCategoryDrawer(KCategorizedView *view) diff --git a/depends/pack200/src/bands.cpp b/depends/pack200/src/bands.cpp index 1c10b35b..1608d838 100644 --- a/depends/pack200/src/bands.cpp +++ b/depends/pack200/src/bands.cpp @@ -79,7 +79,6 @@ void band::readData(int expectedLength) // Read one value to see what it might be. int XB = _meta_default; - int cp1 = 0, cp2 = 0; if (!is_BYTE1) { // must be a variable-length coding @@ -109,7 +108,6 @@ void band::readData(int expectedLength) { // Skip over the escape value. u->rp = xvs.rp; - cp1 = 1; } else { diff --git a/depends/pack200/src/bytes.h b/depends/pack200/src/bytes.h index 2e4a9daf..6ed0b729 100644 --- a/depends/pack200/src/bytes.h +++ b/depends/pack200/src/bytes.h @@ -87,7 +87,7 @@ struct bytes bytes res; res.ptr = ptr + beg; res.len = end - beg; - assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit() - 1)); + assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1))); return res; } // building C strings inside byte buffers: diff --git a/depends/pack200/src/coding.cpp b/depends/pack200/src/coding.cpp index 226ba458..3e311131 100644 --- a/depends/pack200/src/coding.cpp +++ b/depends/pack200/src/coding.cpp @@ -121,7 +121,6 @@ coding *coding::init() this->min = this->umin = 0; if (S != 0 && range != 0) { - int Smask = (1 << S) - 1; int64_t maxPosCode = range - 1; int64_t maxNegCode = range - 1; while (IS_NEG_CODE(S, maxPosCode)) diff --git a/depends/pack200/src/unpack.cpp b/depends/pack200/src/unpack.cpp index b286269d..55d253b2 100644 --- a/depends/pack200/src/unpack.cpp +++ b/depends/pack200/src/unpack.cpp @@ -483,10 +483,6 @@ void unpacker::putu1ref(entry *e) putu1_at(put_space(1), oidx); } -static int total_cp_size[] = {0, 0}; -static int largest_cp_ref[] = {0, 0}; -static int hash_probes[] = {0, 0}; - // Allocation of small and large blocks. enum @@ -705,7 +701,7 @@ void unpacker::read_file_header() unpack_abort("impossible archive size"); // bad input data return; } - if (archive_size < header_size_1) + if (archive_size < (size_t)header_size_1) { unpack_abort("too much read-ahead"); // somehow we pre-fetched too much? return; @@ -1316,8 +1312,6 @@ void unpacker::read_signature_values(entry *cpMap, int len) // Cf. PackageReader.readConstantPool void unpacker::read_cp() { - byte *rp0 = rp; - int i; for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) @@ -1596,7 +1590,6 @@ band **unpacker::attr_definitions::buildBands(unpacker::layout_definition *lo) const char *unpacker::attr_definitions::parseIntLayout(const char *lp, band *&res, byte le_kind, bool can_be_signed) { - const char *lp0 = lp; band *b = U_NEW(band, 1); char le = *lp++; int spec = UNSIGNED5_spec; @@ -1638,7 +1631,6 @@ const char *unpacker::attr_definitions::parseIntLayout(const char *lp, band *&re const char *unpacker::attr_definitions::parseNumeral(const char *lp, int &res) { - const char *lp0 = lp; bool sgn = false; if (*lp == '0') { @@ -1703,7 +1695,6 @@ band **unpacker::attr_definitions::popBody(int bs_base) const char *unpacker::attr_definitions::parseLayout(const char *lp, band **&res, int curCble) { - const char *lp0 = lp; int bs_base = band_stack.length(); bool top_level = (bs_base == 0); band *b; @@ -3135,8 +3126,6 @@ unpacker::read_bcs() void unpacker::read_bands() { - byte *rp0 = rp; - read_file_header(); if (cp.nentries == 0) @@ -3312,7 +3301,7 @@ void constant_pool::initMemberIndexes() // Get the pre-existing indexes: int nclasses = tag_count[CONSTANT_Class]; - entry *classes = tag_base[CONSTANT_Class] + entries; + // entry *classes = tag_base[CONSTANT_Class] + entries; // UNUSED int nfields = tag_count[CONSTANT_Fieldref]; entry *fields = tag_base[CONSTANT_Fieldref] + entries; int nmethods = tag_count[CONSTANT_Methodref]; @@ -3563,8 +3552,6 @@ void unpacker::start(void *packptr, size_t len) void unpacker::check_options() { - const char *strue = "true"; - const char *sfalse = "false"; if (deflate_hint_or_zero != 0) { bool force_deflate_hint = (deflate_hint_or_zero > 0); diff --git a/depends/pack200/src/unpack200.cpp b/depends/pack200/src/unpack200.cpp index 2ff8c34a..0a9d2714 100644 --- a/depends/pack200/src/unpack200.cpp +++ b/depends/pack200/src/unpack200.cpp @@ -97,8 +97,6 @@ static int read_magic(unpacker *u, char peek[], int peeklen) void unpack_200(std::string input_path, std::string output_path) { unpacker u; - int status = 0; - FILE *input = fopen(input_path.c_str(), "rb"); if (!input) { diff --git a/depends/quazip/unzip.c b/depends/quazip/unzip.c index 6e115ae6..52bc081f 100644 --- a/depends/quazip/unzip.c +++ b/depends/quazip/unzip.c @@ -1173,7 +1173,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) if (password != NULL) { int i; - s->pcrc_32_tab = get_crc_table(); + s->pcrc_32_tab = (const unsigned long*) get_crc_table(); init_keys(password,s->keys,s->pcrc_32_tab); if (ZSEEK(s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + diff --git a/depends/quazip/zip.c b/depends/quazip/zip.c index bf8c0a10..a36a20a1 100644 --- a/depends/quazip/zip.c +++ b/depends/quazip/zip.c @@ -903,7 +903,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, unsigned char bufHead[RAND_HEAD_LEN]; unsigned int sizeHead; zi->ci.encrypt = 1; - zi->ci.pcrc_32_tab = get_crc_table(); + zi->ci.pcrc_32_tab = (const unsigned long*) get_crc_table(); /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ crcForCrypting = (uLong)zi->ci.dosDate << 16; // ATTANTION! Without this row, you don't unpack your password protected archive in other app. diff --git a/depends/settings/include/keyring.h b/depends/settings/include/keyring.h index 747211de..a4da23b1 100644 --- a/depends/settings/include/keyring.h +++ b/depends/settings/include/keyring.h @@ -34,6 +34,11 @@ class LIBSETTINGS_EXPORT Keyring { public: /** + * @brief virtual dtor + */ + virtual ~Keyring() {}; + + /** * @brief the System Keyring instance * @return the Keyring instance */ diff --git a/depends/settings/src/stubkeyring.h b/depends/settings/src/stubkeyring.h index f25cefde..1f4b1be0 100644 --- a/depends/settings/src/stubkeyring.h +++ b/depends/settings/src/stubkeyring.h @@ -24,6 +24,11 @@ class StubKeyring : public Keyring { public: + /** + * @brief virtual dtor + */ + virtual ~StubKeyring() {}; + virtual bool storePassword(QString service, QString username, QString password); virtual QString getPassword(QString service, QString username); virtual bool hasPassword(QString service, QString username); diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp index d8a1b69d..d0210df6 100644 --- a/gui/ConsoleWindow.cpp +++ b/gui/ConsoleWindow.cpp @@ -58,13 +58,23 @@ void ConsoleWindow::writeColor(QString text, const char *color) ui->text->appendHtml(QString("<font color=\"%1\">%2</font>").arg(color).arg(text)); else ui->text->appendPlainText(text); - // scroll down - QScrollBar *bar = ui->text->verticalScrollBar(); - bar->setValue(bar->maximum()); } void ConsoleWindow::write(QString data, MessageLevel::Enum mode) { + QScrollBar *bar = ui->text->verticalScrollBar(); + int max_bar = bar->maximum(); + int val_bar = bar->value(); + if(m_scroll_active) + { + if(m_last_scroll_value > val_bar) + m_scroll_active = false; + } + else + { + m_scroll_active = val_bar == max_bar; + } + if (data.endsWith('\n')) data = data.left(data.length() - 1); QStringList paragraphs = data.split('\n'); @@ -93,6 +103,11 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode) else while (iter.hasNext()) writeColor(iter.next()); + if(m_scroll_active) + { + bar->setValue(bar->maximum()); + } + m_last_scroll_value = bar->value(); } void ConsoleWindow::clear() diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h index e0a47bc6..2d948484 100644 --- a/gui/ConsoleWindow.h +++ b/gui/ConsoleWindow.h @@ -38,6 +38,16 @@ public: */ void setMayClose(bool mayclose); +private: + /** + * @brief write a colored paragraph + * @param data the string + * @param color the css color name + * this will only insert a single paragraph. + * \n are ignored. a real \n is always appended. + */ + void writeColor(QString data, const char *color = nullptr); + signals: void isClosing(); @@ -52,15 +62,6 @@ slots: void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC); /** - * @brief write a colored paragraph - * @param data the string - * @param color the css color name - * this will only insert a single paragraph. - * \n are ignored. a real \n is always appended. - */ - void writeColor(QString data, const char *color = nullptr); - - /** * @brief clear the text widget */ void clear(); @@ -82,4 +83,6 @@ private: Ui::ConsoleWindow *ui = nullptr; MinecraftProcess *proc = nullptr; bool m_mayclose = true; + int m_last_scroll_value = 0; + bool m_scroll_active = true; }; diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index cb81958b..854091c6 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -69,8 +69,9 @@ #include "logic/lists/IconList.h" #include "logic/lists/JavaVersionList.h" -#include "logic/auth/AuthenticateTask.h" -#include "logic/auth/ValidateTask.h" +#include "logic/auth/flows/AuthenticateTask.h" +#include "logic/auth/flows/RefreshTask.h" +#include "logic/auth/flows/ValidateTask.h" #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" @@ -244,6 +245,28 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect(assets_downloader, SIGNAL(finished()), SLOT(assetsFinished())); assets_downloader->start(); } + + const QString currentInstanceId = MMC->settings()->get("SelectedInstance").toString(); + if (!currentInstanceId.isNull()) + { + const QModelIndex index = MMC->instances()->getInstanceIndexById(currentInstanceId); + if (index.isValid()) + { + const QModelIndex mappedIndex = proxymodel->mapFromSource(index); + view->setCurrentIndex(mappedIndex); + } + else + { + view->setCurrentIndex(proxymodel->index(0, 0)); + } + } + else + { + view->setCurrentIndex(proxymodel->index(0, 0)); + } + + // removing this looks stupid + view->setFocus(); } MainWindow::~MainWindow() @@ -254,7 +277,6 @@ MainWindow::~MainWindow() delete assets_downloader; } - void MainWindow::repopulateAccountsMenu() { accountMenu->clear(); @@ -769,16 +791,16 @@ void MainWindow::doLaunchInst(BaseInstance* instance, MojangAccountPtr account) { // We'll need to validate the access token to make sure the account is still logged in. ProgressDialog progDialog(this); - ValidateTask validateTask(account, &progDialog); - progDialog.exec(&validateTask); - - if (validateTask.successful()) + RefreshTask refreshtask(account, &progDialog); + progDialog.exec(&refreshtask); + + if (refreshtask.successful()) { prepareLaunch(m_selectedInstance, account); } else { - YggdrasilTask::Error* error = validateTask.getError(); + YggdrasilTask::Error *error = refreshtask.getError(); if (error != nullptr) { @@ -790,17 +812,20 @@ void MainWindow::doLaunchInst(BaseInstance* instance, MojangAccountPtr account) } else { - CustomMessageBox::selectable(this, tr("Access Token Validation Error"), + CustomMessageBox::selectable( + this, tr("Access Token Validation Error"), tr("There was an error when trying to validate your access token.\n" - "Details: %s").arg(error->getDisplayMessage()), + "Details: %s").arg(error->getDisplayMessage()), QMessageBox::Warning, QMessageBox::Ok)->exec(); } } else { - CustomMessageBox::selectable(this, tr("Access Token Validation Error"), + CustomMessageBox::selectable( + this, tr("Access Token Validation Error"), tr("There was an unknown error when trying to validate your access token." - "The authentication server might be down, or you might not be connected to the Internet."), + "The authentication server might be down, or you might not be connected to " + "the Internet."), QMessageBox::Warning, QMessageBox::Ok)->exec(); } } @@ -857,10 +882,7 @@ void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account console = new ConsoleWindow(proc); connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded())); - // I think this will work... - QString username = account->username(); - QString session_id = account->accessToken(); - proc->setLogin(username, session_id); + proc->setLogin(account); proc->launch(); } @@ -983,10 +1005,14 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); auto ico = MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); + + MMC->settings()->set("SelectedInstance", m_selectedInstance->id()); } else { selectionBad(); + + MMC->settings()->set("SelectedInstance", QString()); } } diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp index dfac4989..f5268b61 100644 --- a/gui/dialogs/AccountListDialog.cpp +++ b/gui/dialogs/AccountListDialog.cpp @@ -20,7 +20,7 @@ #include <logger/QsLog.h> -#include <logic/auth/AuthenticateTask.h> +#include <logic/auth/flows/AuthenticateTask.h> #include <logic/net/NetJob.h> #include <gui/dialogs/EditAccountDialog.h> @@ -29,9 +29,8 @@ #include <MultiMC.h> -AccountListDialog::AccountListDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AccountListDialog) +AccountListDialog::AccountListDialog(QWidget *parent) + : QDialog(parent), ui(new Ui::AccountListDialog) { ui->setupUi(this); @@ -44,8 +43,8 @@ AccountListDialog::AccountListDialog(QWidget *parent) : connect(selectionModel, &QItemSelectionModel::selectionChanged, [this] (const QItemSelection& sel, const QItemSelection& dsel) { updateButtonStates(); }); - connect(m_accounts.get(), SIGNAL(listChanged), SLOT(listChanged)); - connect(m_accounts.get(), SIGNAL(activeAccountChanged), SLOT(listChanged)); + connect(m_accounts.get(), SIGNAL(listChanged()), SLOT(listChanged())); + connect(m_accounts.get(), SIGNAL(activeAccountChanged()), SLOT(listChanged())); updateButtonStates(); } @@ -60,7 +59,6 @@ void AccountListDialog::listChanged() updateButtonStates(); } - void AccountListDialog::on_addAccountBtn_clicked() { addAccount(tr("Please enter your Mojang or Minecraft account username and password to add your account.")); @@ -84,7 +82,7 @@ void AccountListDialog::on_setDefaultBtn_clicked() QModelIndex selected = selection.first(); MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>(); m_accounts->setActiveAccount(account->username()); - } + } } void AccountListDialog::on_noDefaultBtn_clicked() @@ -104,7 +102,7 @@ void AccountListDialog::updateButtonStates() ui->rmAccountBtn->setEnabled(selection.size() > 0); ui->setDefaultBtn->setEnabled(selection.size() > 0); - + ui->noDefaultBtn->setDown(m_accounts->activeAccount().get() == nullptr); } @@ -146,4 +144,3 @@ void AccountListDialog::addAccount(const QString& errMsg) } } } - diff --git a/gui/dialogs/AccountListDialog.h b/gui/dialogs/AccountListDialog.h index 634d944a..84ff8e0e 100644 --- a/gui/dialogs/AccountListDialog.h +++ b/gui/dialogs/AccountListDialog.h @@ -21,7 +21,8 @@ #include "logic/lists/MojangAccountList.h" -namespace Ui { +namespace Ui +{ class AccountListDialog; } @@ -29,7 +30,7 @@ class AuthenticateTask; class AccountListDialog : public QDialog { -Q_OBJECT + Q_OBJECT public: explicit AccountListDialog(QWidget *parent = 0); ~AccountListDialog(); @@ -62,4 +63,3 @@ slots: private: Ui::AccountListDialog *ui; }; - diff --git a/gui/dialogs/AccountSelectDialog.cpp b/gui/dialogs/AccountSelectDialog.cpp index db1bd192..b8fa9e42 100644 --- a/gui/dialogs/AccountSelectDialog.cpp +++ b/gui/dialogs/AccountSelectDialog.cpp @@ -20,15 +20,14 @@ #include <logger/QsLog.h> -#include <logic/auth/AuthenticateTask.h> +#include <logic/auth/flows/AuthenticateTask.h> #include <gui/dialogs/ProgressDialog.h> #include <MultiMC.h> -AccountSelectDialog::AccountSelectDialog(const QString& message, int flags, QWidget *parent) : - QDialog(parent), - ui(new Ui::AccountSelectDialog) +AccountSelectDialog::AccountSelectDialog(const QString &message, int flags, QWidget *parent) + : QDialog(parent), ui(new Ui::AccountSelectDialog) { ui->setupUi(this); @@ -85,4 +84,3 @@ void AccountSelectDialog::on_buttonBox_rejected() { close(); } - diff --git a/gui/dialogs/AccountSelectDialog.h b/gui/dialogs/AccountSelectDialog.h index 41af4f7c..a539e7e9 100644 --- a/gui/dialogs/AccountSelectDialog.h +++ b/gui/dialogs/AccountSelectDialog.h @@ -21,17 +21,18 @@ #include "logic/lists/MojangAccountList.h" -namespace Ui { +namespace Ui +{ class AccountSelectDialog; } class AccountSelectDialog : public QDialog { -Q_OBJECT + Q_OBJECT public: enum Flags { - NoFlags=0, + NoFlags = 0, /*! * Shows a check box on the dialog that allows the user to specify that the account @@ -75,7 +76,7 @@ public: public slots: void on_buttonBox_accepted(); - + void on_buttonBox_rejected(); protected: @@ -87,4 +88,3 @@ protected: private: Ui::AccountSelectDialog *ui; }; - diff --git a/gui/dialogs/CopyInstanceDialog.cpp b/gui/dialogs/CopyInstanceDialog.cpp index 4d588a1e..9d7ac30c 100644 --- a/gui/dialogs/CopyInstanceDialog.cpp +++ b/gui/dialogs/CopyInstanceDialog.cpp @@ -33,7 +33,7 @@ #include "logic/BaseInstance.h" CopyInstanceDialog::CopyInstanceDialog(BaseInstance *original, QWidget *parent) - : m_original(original), QDialog(parent), ui(new Ui::CopyInstanceDialog) + :QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); diff --git a/gui/dialogs/EditAccountDialog.cpp b/gui/dialogs/EditAccountDialog.cpp index d28336f7..dd3f0523 100644 --- a/gui/dialogs/EditAccountDialog.cpp +++ b/gui/dialogs/EditAccountDialog.cpp @@ -16,11 +16,10 @@ #include "EditAccountDialog.h" #include "ui_EditAccountDialog.h" -EditAccountDialog::EditAccountDialog(const QString& text, QWidget *parent, int flags) : - QDialog(parent), - ui(new Ui::EditAccountDialog) +EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags) + : QDialog(parent), ui(new Ui::EditAccountDialog) { - ui->setupUi(this); + ui->setupUi(this); ui->label->setText(text); ui->label->setVisible(!text.isEmpty()); @@ -31,7 +30,7 @@ EditAccountDialog::EditAccountDialog(const QString& text, QWidget *parent, int f EditAccountDialog::~EditAccountDialog() { - delete ui; + delete ui; } QString EditAccountDialog::username() const @@ -43,4 +42,3 @@ QString EditAccountDialog::password() const { return ui->passTextBox->text(); } - diff --git a/gui/dialogs/EditAccountDialog.h b/gui/dialogs/EditAccountDialog.h index 847c3be5..be3a88d8 100644 --- a/gui/dialogs/EditAccountDialog.h +++ b/gui/dialogs/EditAccountDialog.h @@ -17,16 +17,18 @@ #include <QDialog> -namespace Ui { +namespace Ui +{ class EditAccountDialog; } class EditAccountDialog : public QDialog { -Q_OBJECT + Q_OBJECT public: - explicit EditAccountDialog(const QString& text="", QWidget *parent = 0, int flags=UsernameField | PasswordField); + explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0, + int flags = UsernameField | PasswordField); ~EditAccountDialog(); /*! @@ -41,7 +43,7 @@ public: enum Flags { - NoFlags=0, + NoFlags = 0, //! Specifies that the dialog should have a username field. UsernameField, @@ -53,4 +55,3 @@ public: private: Ui::EditAccountDialog *ui; }; - diff --git a/gui/dialogs/EditNotesDialog.cpp b/gui/dialogs/EditNotesDialog.cpp index cd52e694..a265a4d0 100644 --- a/gui/dialogs/EditNotesDialog.cpp +++ b/gui/dialogs/EditNotesDialog.cpp @@ -21,8 +21,8 @@ #include <QApplication> EditNotesDialog::EditNotesDialog(QString notes, QString name, QWidget *parent) - : m_instance_notes(notes), m_instance_name(name), QDialog(parent), - ui(new Ui::EditNotesDialog) + : QDialog(parent), ui(new Ui::EditNotesDialog), m_instance_name(name), + m_instance_notes(notes) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); diff --git a/gui/dialogs/InstanceSettings.cpp b/gui/dialogs/InstanceSettings.cpp index f059047f..bc6b266a 100644 --- a/gui/dialogs/InstanceSettings.cpp +++ b/gui/dialogs/InstanceSettings.cpp @@ -32,7 +32,7 @@ #include <QMessageBox> InstanceSettings::InstanceSettings(SettingsObject *obj, QWidget *parent) - : m_obj(obj), QDialog(parent), ui(new Ui::InstanceSettings) + : QDialog(parent), ui(new Ui::InstanceSettings), m_obj(obj) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); diff --git a/gui/dialogs/LegacyModEditDialog.cpp b/gui/dialogs/LegacyModEditDialog.cpp index 25a1c616..66d53ee1 100644 --- a/gui/dialogs/LegacyModEditDialog.cpp +++ b/gui/dialogs/LegacyModEditDialog.cpp @@ -31,7 +31,7 @@ #include <QKeyEvent> LegacyModEditDialog::LegacyModEditDialog(LegacyInstance *inst, QWidget *parent) - : m_inst(inst), QDialog(parent), ui(new Ui::LegacyModEditDialog) + : QDialog(parent), ui(new Ui::LegacyModEditDialog), m_inst(inst) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); diff --git a/gui/dialogs/OneSixModEditDialog.cpp b/gui/dialogs/OneSixModEditDialog.cpp index dea1b86b..51ea2d19 100644 --- a/gui/dialogs/OneSixModEditDialog.cpp +++ b/gui/dialogs/OneSixModEditDialog.cpp @@ -40,7 +40,7 @@ #include "logic/ForgeInstaller.h" OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) - : m_inst(inst), QDialog(parent), ui(new Ui::OneSixModEditDialog) + : QDialog(parent), ui(new Ui::OneSixModEditDialog), m_inst(inst) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); diff --git a/gui/widgets/InstanceDelegate.cpp b/gui/widgets/InstanceDelegate.cpp index 487fed61..5020b8b6 100644 --- a/gui/widgets/InstanceDelegate.cpp +++ b/gui/widgets/InstanceDelegate.cpp @@ -21,45 +21,45 @@ #include <QtCore/qmath.h> // Origin: Qt -static void viewItemTextLayout ( QTextLayout &textLayout, int lineWidth, qreal &height, qreal &widthUsed ) +static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height, + qreal &widthUsed) { height = 0; widthUsed = 0; textLayout.beginLayout(); QString str = textLayout.text(); - while ( true ) + while (true) { QTextLine line = textLayout.createLine(); - if ( !line.isValid() ) + if (!line.isValid()) break; - if(line.textLength() == 0) + if (line.textLength() == 0) break; - line.setLineWidth ( lineWidth ); - line.setPosition ( QPointF ( 0, height ) ); + line.setLineWidth(lineWidth); + line.setPosition(QPointF(0, height)); height += line.height(); - widthUsed = qMax ( widthUsed, line.naturalTextWidth() ); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); } textLayout.endLayout(); } -#define QFIXED_MAX (INT_MAX/256) +#define QFIXED_MAX (INT_MAX / 256) -ListViewDelegate::ListViewDelegate ( QObject* parent ) : QStyledItemDelegate ( parent ) +ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent) { - } -void drawSelectionRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect) +void drawSelectionRect(QPainter *painter, const QStyleOptionViewItemV4 &option, + const QRect &rect) { if ((option.state & QStyle::State_Selected)) - painter->fillRect ( rect, option.palette.brush ( QPalette::Highlight ) ); + painter->fillRect(rect, option.palette.brush(QPalette::Highlight)); else { QColor backgroundColor = option.palette.color(QPalette::Background); backgroundColor.setAlpha(160); - painter->fillRect ( rect, QBrush(backgroundColor) ); + painter->fillRect(rect, QBrush(backgroundColor)); } - } void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect) @@ -67,11 +67,12 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, cons if (!(option.state & QStyle::State_HasFocus)) return; QStyleOptionFocusRect opt; - opt.direction = option.direction; - opt.fontMetrics = option.fontMetrics; - opt.palette = option.palette; - opt.rect = rect; - //opt.state = option.state | QStyle::State_KeyboardFocusChange | QStyle::State_Item; + opt.direction = option.direction; + opt.fontMetrics = option.fontMetrics; + opt.palette = option.palette; + opt.rect = rect; + // opt.state = option.state | QStyle::State_KeyboardFocusChange | + // QStyle::State_Item; auto col = option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base; opt.backgroundColor = option.palette.color(col); // Apparently some widget styles expect this hint to not be set @@ -84,29 +85,31 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, cons painter->setRenderHint(QPainter::Antialiasing); } -static QSize viewItemTextSize ( const QStyleOptionViewItemV4 *option ) +static QSize viewItemTextSize(const QStyleOptionViewItemV4 *option) { QStyle *style = option->widget ? option->widget->style() : QApplication::style(); QTextOption textOption; - textOption.setWrapMode ( QTextOption::WrapAtWordBoundaryOrAnywhere ); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); QTextLayout textLayout; - textLayout.setTextOption ( textOption ); - textLayout.setFont ( option->font ); - textLayout.setText ( option->text ); - const int textMargin = style->pixelMetric ( QStyle::PM_FocusFrameHMargin, option, option->widget ) + 1; - QRect bounds ( 0,0,100 - 2*textMargin,600 ); + textLayout.setTextOption(textOption); + textLayout.setFont(option->font); + textLayout.setText(option->text); + const int textMargin = + style->pixelMetric(QStyle::PM_FocusFrameHMargin, option, option->widget) + 1; + QRect bounds(0, 0, 100 - 2 * textMargin, 600); qreal height = 0, widthUsed = 0; - viewItemTextLayout ( textLayout, bounds.width(), height, widthUsed ); - const QSize size ( qCeil ( widthUsed ), qCeil ( height ) ); - return QSize ( size.width() + 2 * textMargin, size.height() ); + viewItemTextLayout(textLayout, bounds.width(), height, widthUsed); + const QSize size(qCeil(widthUsed), qCeil(height)); + return QSize(size.width() + 2 * textMargin, size.height()); } -void ListViewDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const +void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; - initStyleOption ( &opt, index ); + initStyleOption(&opt, index); painter->save(); - painter->setClipRect ( opt.rect ); + painter->setClipRect(opt.rect); opt.features |= QStyleOptionViewItem::WrapText; opt.text = index.data().toString(); @@ -115,26 +118,27 @@ void ListViewDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& op QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); - //const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize); + // const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize); const int iconSize = 48; QRect iconbox = opt.rect; - const int textMargin = style->pixelMetric ( QStyle::PM_FocusFrameHMargin, 0, opt.widget ) + 1; + const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1; QRect textRect = opt.rect; QRect textHighlightRect = textRect; // clip the decoration on top, remove width padding - textRect.adjust ( textMargin,iconSize + textMargin + 5,-textMargin,0 ); - - textHighlightRect.adjust ( 0,iconSize + 5,0,0 ); + textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0); + + textHighlightRect.adjust(0, iconSize + 5, 0, 0); // draw background { - QSize textSize = viewItemTextSize ( &opt ); + // FIXME: unused + // QSize textSize = viewItemTextSize ( &opt ); QPalette::ColorGroup cg; QStyleOptionViewItemV4 opt2(opt); - - if((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled)) + + if ((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled)) { - if(! ( opt.state & QStyle::State_Active )) + if (!(opt.state & QStyle::State_Active)) cg = QPalette::Inactive; else cg = QPalette::Normal; @@ -144,31 +148,33 @@ void ListViewDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& op cg = QPalette::Disabled; } opt2.palette.setCurrentColorGroup(cg); - + // fill in background, if any - if ( opt.backgroundBrush.style() != Qt::NoBrush ) + if (opt.backgroundBrush.style() != Qt::NoBrush) { QPointF oldBO = painter->brushOrigin(); - painter->setBrushOrigin ( opt.rect.topLeft() ); - painter->fillRect ( opt.rect, opt.backgroundBrush ); - painter->setBrushOrigin ( oldBO ); + painter->setBrushOrigin(opt.rect.topLeft()); + painter->fillRect(opt.rect, opt.backgroundBrush); + painter->setBrushOrigin(oldBO); } - - if ( opt.showDecorationSelected ) + + if (opt.showDecorationSelected) { - drawSelectionRect(painter,opt2, opt.rect); - drawFocusRect(painter,opt2, opt.rect); - //painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) ); + drawSelectionRect(painter, opt2, opt.rect); + drawFocusRect(painter, opt2, opt.rect); + // painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) ); } else { - - //if ( opt.state & QStyle::State_Selected ) + + // if ( opt.state & QStyle::State_Selected ) { - //QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt, opt.widget ); - //painter->fillRect ( textHighlightRect, opt.palette.brush ( cg, QPalette::Highlight ) ); - drawSelectionRect(painter,opt2, textHighlightRect); - drawFocusRect(painter,opt2, textHighlightRect); + // QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt, + // opt.widget ); + // painter->fillRect ( textHighlightRect, opt.palette.brush ( cg, + // QPalette::Highlight ) ); + drawSelectionRect(painter, opt2, textHighlightRect); + drawFocusRect(painter, opt2, textHighlightRect); } } } @@ -176,71 +182,73 @@ void ListViewDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& op // draw the icon { QIcon::Mode mode = QIcon::Normal; - if ( ! ( opt.state & QStyle::State_Enabled ) ) + if (!(opt.state & QStyle::State_Enabled)) mode = QIcon::Disabled; - else if ( opt.state & QStyle::State_Selected ) + else if (opt.state & QStyle::State_Selected) mode = QIcon::Selected; QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off; - iconbox.setHeight ( iconSize ); - opt.icon.paint ( painter, iconbox, Qt::AlignCenter, mode, state ); + iconbox.setHeight(iconSize); + opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state); } // set the text colors - QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; - if ( cg == QPalette::Normal && ! ( opt.state & QStyle::State_Active ) ) + QPalette::ColorGroup cg = + opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) cg = QPalette::Inactive; - if ( opt.state & QStyle::State_Selected ) + if (opt.state & QStyle::State_Selected) { - painter->setPen ( opt.palette.color ( cg, QPalette::HighlightedText ) ); + painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); } else { - painter->setPen ( opt.palette.color ( cg, QPalette::Text ) ); + painter->setPen(opt.palette.color(cg, QPalette::Text)); } // draw the text QTextOption textOption; - textOption.setWrapMode ( QTextOption::WrapAtWordBoundaryOrAnywhere ); - textOption.setTextDirection ( opt.direction ); - textOption.setAlignment ( QStyle::visualAlignment ( opt.direction, opt.displayAlignment ) ); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + textOption.setTextDirection(opt.direction); + textOption.setAlignment(QStyle::visualAlignment(opt.direction, opt.displayAlignment)); QTextLayout textLayout; - textLayout.setTextOption ( textOption ); - textLayout.setFont ( opt.font ); - textLayout.setText ( opt.text ); + textLayout.setTextOption(textOption); + textLayout.setFont(opt.font); + textLayout.setText(opt.text); qreal width, height; - viewItemTextLayout ( textLayout, textRect.width(), height, width ); + viewItemTextLayout(textLayout, textRect.width(), height, width); const int lineCount = textLayout.lineCount(); - const QRect layoutRect = QStyle::alignedRect ( opt.direction, opt.displayAlignment, QSize ( textRect.width(), int ( height ) ), textRect ); + const QRect layoutRect = QStyle::alignedRect( + opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect); const QPointF position = layoutRect.topLeft(); - for ( int i = 0; i < lineCount; ++i ) + for (int i = 0; i < lineCount; ++i) { - const QTextLine line = textLayout.lineAt ( i ); - line.draw ( painter, position ); + const QTextLine line = textLayout.lineAt(i); + line.draw(painter, position); } painter->restore(); } - -QSize ListViewDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const +QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; - initStyleOption ( &opt, index ); + initStyleOption(&opt, index); opt.features |= QStyleOptionViewItem::WrapText; opt.text = index.data().toString(); opt.textElideMode = Qt::ElideRight; opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter; QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); - const int textMargin = style->pixelMetric ( QStyle::PM_FocusFrameHMargin, &option, opt.widget ) + 1; + const int textMargin = + style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1; int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables - QSize szz = viewItemTextSize ( &opt ); + QSize szz = viewItemTextSize(&opt); height += szz.height(); // FIXME: maybe the icon items could scale and keep proportions? - QSize sz ( 100,height ); + QSize sz(100, height); return sz; } - diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index c38f75ef..6f8222b7 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -30,7 +30,7 @@ BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir, SettingsObject *settings_obj, QObject *parent) - : inst_d(d_in), QObject(parent) + : QObject(parent), inst_d(d_in) { I_D(BaseInstance); d->m_settings = settings_obj; diff --git a/logic/InstanceFactory.cpp b/logic/InstanceFactory.cpp index e1f1f202..66b271d0 100644 --- a/logic/InstanceFactory.cpp +++ b/logic/InstanceFactory.cpp @@ -133,16 +133,12 @@ InstanceFactory::InstCreateError InstanceFactory::copyInstance(BaseInstance *&ne { case NoLoadError: return NoCreateError; - case UnknownLoadError: - { - rootDir.removeRecursively(); - return UnknownCreateError; - } case NotAnInstance: - { rootDir.removeRecursively(); return CantCreateDir; + default: + case UnknownLoadError: + rootDir.removeRecursively(); + return UnknownCreateError; } - } - ; } diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp index fb37245f..daad7281 100644 --- a/logic/JavaChecker.cpp +++ b/logic/JavaChecker.cpp @@ -8,7 +8,7 @@ JavaChecker::JavaChecker(QObject *parent) : QObject(parent) { } -int JavaChecker::performCheck(QString path) +void JavaChecker::performCheck(QString path) { if(QFile::exists(CHECKER_FILE)) { diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h index 60f8b56f..34782383 100644 --- a/logic/JavaChecker.h +++ b/logic/JavaChecker.h @@ -17,7 +17,7 @@ class JavaChecker : public QObject Q_OBJECT public: explicit JavaChecker(QObject *parent = 0); - int performCheck(QString path); + void performCheck(QString path); signals: void checkFinished(JavaCheckResult result); diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 6ac03e76..72b6c51a 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -274,7 +274,6 @@ bool LegacyInstance::setIntendedVersionId(QString version) bool LegacyInstance::shouldUpdate() const { - I_D(LegacyInstance); QVariant var = settings().get("ShouldUpdate"); if (!var.isValid() || var.toBool() == false) { diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index e4a26054..5d99bfae 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -71,6 +71,26 @@ void MinecraftProcess::setWorkdir(QString path) m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath()); } +QString MinecraftProcess::censorPrivateInfo(QString in) +{ + if(!m_account) + return in; + else + { + QString sessionId = m_account->sessionId(); + QString accessToken = m_account->accessToken(); + QString clientToken = m_account->clientToken(); + QString profileId = m_account->currentProfile()->id(); + QString profileName = m_account->currentProfile()->name(); + in.replace(sessionId, "<SESSION ID>"); + in.replace(accessToken, "<ACCESS TOKEN>"); + in.replace(clientToken, "<CLIENT TOKEN>"); + in.replace(profileId, "<PROFILE ID>"); + in.replace(profileName, "<PROFILE NAME>"); + return in; + } +} + // console window void MinecraftProcess::on_stdErr() { @@ -83,8 +103,7 @@ void MinecraftProcess::on_stdErr() for (int i = 0; i < lines.size() - 1; i++) { QString &line = lines[i]; - emit log(line /*.replace(username, "<Username>").replace(sessionID, "<Session ID>")*/, - getLevel(line, MessageLevel::Error)); + emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Error)); } if (!complete) m_err_leftover = lines.last(); @@ -101,8 +120,7 @@ void MinecraftProcess::on_stdOut() for (int i = 0; i < lines.size() - 1; i++) { QString &line = lines[i]; - emit log(line.replace(username, "<Username>").replace(sessionID, "<Session ID>"), - getLevel(line, MessageLevel::Message)); + emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Message)); } if (!complete) m_out_leftover = lines.last(); @@ -173,8 +191,8 @@ void MinecraftProcess::launch() emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory())); QString JavaPath = m_instance->settings().get("JavaPath").toString(); emit log(QString("Java path: '%1'").arg(JavaPath)); - emit log(QString("Arguments: '%1'").arg( - m_args.join("' '").replace(username, "<Username>").replace(sessionID, "<Session ID>"))); + QString allArgs = m_args.join("' '"); + emit log(QString("Arguments: '%1'").arg(censorPrivateInfo(allArgs))); start(JavaPath, m_args); if (!waitForStarted()) { diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index e38d2f83..bd0151cc 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -69,10 +69,9 @@ public: void killMinecraft(); - inline void setLogin(QString user, QString sid) + inline void setLogin(MojangAccountPtr account) { - username = user; - sessionID = sid; + m_account = account; } signals: @@ -104,11 +103,13 @@ signals: void log(QString text, MessageLevel::Enum level = MessageLevel::MultiMC); protected: - BaseInstance *m_instance; + BaseInstance *m_instance = nullptr; QStringList m_args; QString m_err_leftover; QString m_out_leftover; QProcess m_prepostlaunchprocess; + bool killed = false; + MojangAccountPtr m_account; protected slots: @@ -117,8 +118,7 @@ slots: void on_stdOut(); private: - bool killed; + QString censorPrivateInfo(QString in); MessageLevel::Enum getLevel(const QString &message, MessageLevel::Enum defaultLevel); - QString sessionID; - QString username; + }; diff --git a/logic/ModList.cpp b/logic/ModList.cpp index 8ec73955..d5235fe9 100644 --- a/logic/ModList.cpp +++ b/logic/ModList.cpp @@ -39,18 +39,26 @@ void ModList::startWatching() { is_watching = m_watcher->addPath(m_dir.absolutePath()); if (is_watching) + { QLOG_INFO() << "Started watching " << m_dir.absolutePath(); + } else + { QLOG_INFO() << "Failed to start watching " << m_dir.absolutePath(); + } } void ModList::stopWatching() { is_watching = !m_watcher->removePath(m_dir.absolutePath()); if (!is_watching) + { QLOG_INFO() << "Stopped watching " << m_dir.absolutePath(); + } else + { QLOG_INFO() << "Failed to stop watching " << m_dir.absolutePath(); + } } bool ModList::update() @@ -64,7 +72,6 @@ bool ModList::update() bool orderWasInvalid = false; // first, process the ordered items (if any) - int currentOrderIndex = 0; QStringList listOrder = readListFile(); for (auto item : listOrder) { @@ -363,6 +370,7 @@ QVariant ModList::headerData(int section, Qt::Orientation orientation, int role) case 2: return QString("Minecraft"); } + return QString(); } Qt::ItemFlags ModList::flags(const QModelIndex &index) const diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 27713860..08b63bf9 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -235,7 +235,6 @@ void OneSixInstance::setShouldUpdate(bool val) bool OneSixInstance::shouldUpdate() const { - I_D(OneSixInstance); QVariant var = settings().get("ShouldUpdate"); if (!var.isValid() || var.toBool() == false) { diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index dfb958b2..25e16328 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -198,7 +198,6 @@ void OneSixUpdate::jarlibStart() auto metacache = MMC->metacache(); QList<ForgeXzDownloadPtr> ForgeLibs; - bool already_forge_xz = false; for (auto lib : libs) { if (lib->hint() == "local") diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index 4f3839bc..4a61cf19 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -23,8 +23,7 @@ #include <logger/QsLog.h> -MojangAccount::MojangAccount(const QString& username, QObject* parent) : - QObject(parent) +MojangAccount::MojangAccount(const QString &username, QObject *parent) : QObject(parent) { // Generate a client token. m_clientToken = QUuid::createUuid().toString(); @@ -34,9 +33,9 @@ MojangAccount::MojangAccount(const QString& username, QObject* parent) : m_currentProfile = -1; } -MojangAccount::MojangAccount(const QString& username, const QString& clientToken, - const QString& accessToken, QObject* parent) : - QObject(parent) +MojangAccount::MojangAccount(const QString &username, const QString &clientToken, + const QString &accessToken, QObject *parent) + : QObject(parent) { m_username = username; m_clientToken = clientToken; @@ -45,7 +44,7 @@ MojangAccount::MojangAccount(const QString& username, const QString& clientToken m_currentProfile = -1; } -MojangAccount::MojangAccount(const MojangAccount& other, QObject* parent) +MojangAccount::MojangAccount(const MojangAccount &other, QObject *parent) { m_username = other.username(); m_clientToken = other.clientToken(); @@ -55,7 +54,6 @@ MojangAccount::MojangAccount(const MojangAccount& other, QObject* parent) m_currentProfile = other.m_currentProfile; } - QString MojangAccount::username() const { return m_username; @@ -66,18 +64,17 @@ QString MojangAccount::clientToken() const return m_clientToken; } -void MojangAccount::setClientToken(const QString& clientToken) +void MojangAccount::setClientToken(const QString &clientToken) { m_clientToken = clientToken; } - QString MojangAccount::accessToken() const { return m_accessToken; } -void MojangAccount::setAccessToken(const QString& accessToken) +void MojangAccount::setAccessToken(const QString &accessToken) { m_accessToken = accessToken; } @@ -92,7 +89,7 @@ const QList<AccountProfile> MojangAccount::profiles() const return m_profiles; } -const AccountProfile* MojangAccount::currentProfile() const +const AccountProfile *MojangAccount::currentProfile() const { if (m_currentProfile < 0) { @@ -105,9 +102,9 @@ const AccountProfile* MojangAccount::currentProfile() const return &m_profiles.at(m_currentProfile); } -bool MojangAccount::setProfile(const QString& profileId) +bool MojangAccount::setProfile(const QString &profileId) { - const QList<AccountProfile>& profiles = this->profiles(); + const QList<AccountProfile> &profiles = this->profiles(); for (int i = 0; i < profiles.length(); i++) { if (profiles.at(i).id() == profileId) @@ -119,14 +116,14 @@ bool MojangAccount::setProfile(const QString& profileId) return false; } -void MojangAccount::loadProfiles(const ProfileList& profiles) +void MojangAccount::loadProfiles(const ProfileList &profiles) { m_profiles.clear(); for (auto profile : profiles) m_profiles.append(profile); } -MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject& object) +MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) { // The JSON object must at least have a username for it to be valid. if (!object.value("username").isString()) @@ -134,7 +131,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject& object) QLOG_ERROR() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type."; return nullptr; } - + QString username = object.value("username").toString(""); QString clientToken = object.value("clientToken").toString(""); QString accessToken = object.value("accessToken").toString(""); @@ -201,7 +198,7 @@ AccountProfile::AccountProfile(const QString& id, const QString& name) m_name = name; } -AccountProfile::AccountProfile(const AccountProfile& other) +AccountProfile::AccountProfile(const AccountProfile &other) { m_id = other.m_id; m_name = other.m_name; @@ -217,4 +214,7 @@ QString AccountProfile::name() const return m_name; } - +void MojangAccount::propagateChange() +{ + emit changed(); +} diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index 062b8aa2..25a85790 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -19,6 +19,7 @@ #include <QString> #include <QList> #include <QJsonObject> +#include <QPair> #include <memory> @@ -27,7 +28,6 @@ class MojangAccount; typedef std::shared_ptr<MojangAccount> MojangAccountPtr; Q_DECLARE_METATYPE(MojangAccountPtr) - /** * Class that represents a profile within someone's Mojang account. * @@ -38,56 +38,69 @@ Q_DECLARE_METATYPE(MojangAccountPtr) class AccountProfile { public: - AccountProfile(const QString& id, const QString& name); - AccountProfile(const AccountProfile& other); + AccountProfile(const QString &id, const QString &name); + AccountProfile(const AccountProfile &other); QString id() const; QString name() const; + protected: QString m_id; QString m_name; }; - typedef QList<AccountProfile> ProfileList; +struct User +{ + QString id; + // pair of key:value + // we don't know if the keys:value mapping is 1:1, so a list is used. + QList<QPair<QString, QString>> properties; +}; /** * Object that stores information about a certain Mojang account. * - * Said information may include things such as that account's username, client token, and access + * Said information may include things such as that account's username, client token, and access * token if the user chose to stay logged in. */ class MojangAccount : public QObject { -Q_OBJECT + Q_OBJECT public: /** * Constructs a new MojangAccount with the given username. * The client token will be generated automatically and the access token will be blank. */ - explicit MojangAccount(const QString& username, QObject* parent = 0); + explicit MojangAccount(const QString &username, QObject *parent = 0); /** * Constructs a new MojangAccount with the given username, client token, and access token. */ - explicit MojangAccount(const QString& username, const QString& clientToken, const QString& accessToken, QObject* parent = 0); + explicit MojangAccount(const QString &username, const QString &clientToken, + const QString &accessToken, QObject *parent = 0); /** * Constructs a new MojangAccount matching the given account. */ - MojangAccount(const MojangAccount& other, QObject* parent); + MojangAccount(const MojangAccount &other, QObject *parent); /** * Loads a MojangAccount from the given JSON object. */ - static MojangAccountPtr loadFromJson(const QJsonObject& json); + static MojangAccountPtr loadFromJson(const QJsonObject &json); /** * Saves a MojangAccount to a JSON object and returns it. */ QJsonObject saveToJson(); + /** + * Update the account on disk and lists (it changed, for whatever reason) + * This is called by various Yggdrasil tasks. + */ + void propagateChange(); /** * This MojangAccount's username. May be an email address if the account is migrated. @@ -103,7 +116,7 @@ public: /** * Sets the MojangAccount's client token to the given value. */ - void setClientToken(const QString& token); + void setClientToken(const QString &token); /** * This MojangAccount's access token. @@ -114,7 +127,7 @@ public: /** * Changes this MojangAccount's access token to the given value. */ - void setAccessToken(const QString& token); + void setAccessToken(const QString &token); /** * Get full session ID @@ -130,25 +143,31 @@ public: * Returns a pointer to the currently selected profile. * If no profile is selected, returns the first profile in the profile list or nullptr if there are none. */ - const AccountProfile* currentProfile() const; + const AccountProfile *currentProfile() const; /** * Sets the currently selected profile to the profile with the given ID string. * If profileId is not in the list of available profiles, the function will simply return false. */ - bool setProfile(const QString& profileId); + bool setProfile(const QString &profileId); /** * Clears the current account profile list and replaces it with the given profile list. */ - void loadProfiles(const ProfileList& profiles); + void loadProfiles(const ProfileList &profiles); +signals: + /** + * This isgnal is emitted whrn the account changes + */ + void changed(); protected: QString m_username; QString m_clientToken; - QString m_accessToken; // Blank if not logged in. - int m_currentProfile; // Index of the selected profile within the list of available profiles. -1 if nothing is selected. + QString m_accessToken; // Blank if not logged in. + int m_currentProfile; // Index of the selected profile within the list of available + // profiles. -1 if nothing is selected. ProfileList m_profiles; // List of available profiles. + User m_user; // the user structure, whatever it is. }; - diff --git a/logic/auth/YggdrasilTask.cpp b/logic/auth/YggdrasilTask.cpp index 31c8fbab..797e84cd 100644 --- a/logic/auth/YggdrasilTask.cpp +++ b/logic/auth/YggdrasilTask.cpp @@ -25,13 +25,12 @@ #include <MultiMC.h> #include <logic/auth/MojangAccount.h> -YggdrasilTask::YggdrasilTask(MojangAccountPtr account, QObject* parent) : Task(parent) +YggdrasilTask::YggdrasilTask(MojangAccountPtr account, QObject *parent) : Task(parent) { m_error = nullptr; m_account = account; } - YggdrasilTask::~YggdrasilTask() { if (m_error) @@ -46,17 +45,18 @@ void YggdrasilTask::executeTask() QJsonDocument doc(getRequestContent()); auto worker = MMC->qnam(); - connect(worker.get(), SIGNAL(finished(QNetworkReply*)), this, - SLOT(processReply(QNetworkReply*))); + connect(worker.get(), SIGNAL(finished(QNetworkReply *)), this, + SLOT(processReply(QNetworkReply *))); QUrl reqUrl("https://authserver.mojang.com/" + getEndpoint()); QNetworkRequest netRequest(reqUrl); netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - m_netReply = worker->post(netRequest, doc.toJson()); + + QByteArray requestData = doc.toJson(); + m_netReply = worker->post(netRequest, requestData); } -void YggdrasilTask::processReply(QNetworkReply* reply) +void YggdrasilTask::processReply(QNetworkReply *reply) { setStatus(getStateMessage(STATE_PROCESSING_RESPONSE)); @@ -76,7 +76,6 @@ void YggdrasilTask::processReply(QNetworkReply* reply) QJsonParseError jsonError; QByteArray replyData = reply->readAll(); QJsonDocument doc = QJsonDocument::fromJson(replyData, &jsonError); - // Check the response code. int responseCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -85,15 +84,16 @@ void YggdrasilTask::processReply(QNetworkReply* reply) // If the response code was 200, then there shouldn't be an error. Make sure anyways. // Also, sometimes an empty reply indicates success. If there was no data received, // pass an empty json object to the processResponse function. - if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) + if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) { if (!processResponse(replyData.size() > 0 ? doc.object() : QJsonObject())) { - YggdrasilTask::Error* err = getError(); + YggdrasilTask::Error *err = getError(); if (err) emitFailed(err->getErrorMessage()); else - emitFailed(tr("An unknown error occurred when processing the response from the authentication server.")); + emitFailed(tr("An unknown error occurred when processing the response " + "from the authentication server.")); } else { @@ -166,4 +166,3 @@ MojangAccountPtr YggdrasilTask::getMojangAccount() const { return this->m_account; } - diff --git a/logic/auth/YggdrasilTask.h b/logic/auth/YggdrasilTask.h index 5a433aeb..62638c9d 100644 --- a/logic/auth/YggdrasilTask.h +++ b/logic/auth/YggdrasilTask.h @@ -24,15 +24,14 @@ class QNetworkReply; - /** * A Yggdrasil task is a task that performs an operation on a given mojang account. */ class YggdrasilTask : public Task { -Q_OBJECT + Q_OBJECT public: - explicit YggdrasilTask(MojangAccountPtr account, QObject* parent=0); + explicit YggdrasilTask(MojangAccountPtr account, QObject *parent = 0); ~YggdrasilTask(); /** @@ -49,7 +48,10 @@ public: QString getCause() const { return m_cause; } /// Gets the string to display in the GUI for describing this error. - QString getDisplayMessage() { return getErrorMessage(); } + QString getDisplayMessage() + { + return getErrorMessage(); + } protected: QString m_shortError; @@ -66,7 +68,7 @@ public: * Returns a pointer to a YggdrasilTask::Error object if an error has occurred. * If no error has occurred, returns a null pointer. */ - virtual Error* getError() const; + virtual Error *getError() const; protected: /** @@ -120,11 +122,11 @@ protected: MojangAccountPtr m_account; - QNetworkReply* m_netReply; + QNetworkReply *m_netReply; - Error* m_error; + Error *m_error; -protected slots: - void processReply(QNetworkReply* reply); +protected +slots: + void processReply(QNetworkReply *reply); }; - diff --git a/logic/auth/AuthenticateTask.cpp b/logic/auth/flows/AuthenticateTask.cpp index bf7a54f9..ec2004d6 100644 --- a/logic/auth/AuthenticateTask.cpp +++ b/logic/auth/flows/AuthenticateTask.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <logic/auth/AuthenticateTask.h> +#include <logic/auth/flows/AuthenticateTask.h> #include <logic/auth/MojangAccount.h> @@ -26,8 +26,9 @@ #include "logger/QsLog.h" -AuthenticateTask::AuthenticateTask(MojangAccountPtr account, const QString& password, QObject* parent) : - YggdrasilTask(account, parent), m_password(password) +AuthenticateTask::AuthenticateTask(MojangAccountPtr account, const QString &password, + QObject *parent) + : YggdrasilTask(account, parent), m_password(password) { } @@ -37,20 +38,22 @@ QJsonObject AuthenticateTask::getRequestContent() const * { * "agent": { // optional * "name": "Minecraft", // So far this is the only encountered value - * "version": 1 // This number might be increased + * "version": 1 // This number might be increased * // by the vanilla client in the future * }, * "username": "mojang account name", // Can be an email address or player name for // unmigrated accounts * "password": "mojang account password", * "clientToken": "client identifier" // optional + * "requestUser": true/false // request the user structure * } */ QJsonObject req; { QJsonObject agent; - // C++ makes string literals void* for some stupid reason, so we have to tell it QString... Thanks Obama. + // C++ makes string literals void* for some stupid reason, so we have to tell it + // QString... Thanks Obama. agent.insert("name", QString("Minecraft")); agent.insert("version", 1); req.insert("agent", agent); @@ -58,6 +61,7 @@ QJsonObject AuthenticateTask::getRequestContent() const req.insert("username", getMojangAccount()->username()); req.insert("password", m_password); + req.insert("requestUser", true); // If we already have a client token, give it to the server. // Otherwise, let the server give us one. @@ -69,10 +73,12 @@ QJsonObject AuthenticateTask::getRequestContent() const bool AuthenticateTask::processResponse(QJsonObject responseData) { - // Read the response data. We need to get the client token, access token, and the selected profile. + // Read the response data. We need to get the client token, access token, and the selected + // profile. QLOG_DEBUG() << "Processing authentication response."; - - // If we already have a client token, make sure the one the server gave us matches our existing one. + + // If we already have a client token, make sure the one the server gave us matches our + // existing one. QLOG_DEBUG() << "Getting client token."; QString clientToken = responseData.value("clientToken").toString(""); if (clientToken.isEmpty()) @@ -82,16 +88,17 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) QLOG_ERROR() << "Server didn't send a client token."; return false; } - if (!getMojangAccount()->clientToken().isEmpty() && clientToken != getMojangAccount()->clientToken()) + if (!getMojangAccount()->clientToken().isEmpty() && + clientToken != getMojangAccount()->clientToken()) { - // The server changed our client token! Obey its wishes, but complain. That's what I do for my parents, so... - QLOG_WARN() << "Server changed our client token to '" << clientToken + // The server changed our client token! Obey its wishes, but complain. That's what I do + // for my parents, so... + QLOG_WARN() << "Server changed our client token to '" << clientToken << "'. This shouldn't happen, but it isn't really a big deal."; } // Set the client token. getMojangAccount()->setClientToken(clientToken); - // Now, we set the access token. QLOG_DEBUG() << "Getting access token."; QString accessToken = responseData.value("accessToken").toString(""); @@ -104,10 +111,9 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // Set the access token. getMojangAccount()->setAccessToken(accessToken); - // Now we load the list of available profiles. - // Mojang hasn't yet implemented the profile system, - // but we might as well support what's there so we + // Mojang hasn't yet implemented the profile system, + // but we might as well support what's there so we // don't have trouble implementing it later. QLOG_DEBUG() << "Loading profile list."; QJsonArray availableProfiles = responseData.value("availableProfiles").toArray(); @@ -121,10 +127,11 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) if (id.isEmpty() || name.isEmpty()) { - // This should never happen, but we might as well + // This should never happen, but we might as well // warn about it if it does so we can debug it easily. // You never know when Mojang might do something truly derpy. - QLOG_WARN() << "Found entry in available profiles list with missing ID or name field. Ignoring it."; + QLOG_WARN() << "Found entry in available profiles list with missing ID or name " + "field. Ignoring it."; } // Now, add a new AccountProfile entry to the list. @@ -133,10 +140,8 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // Put the list of profiles we loaded into the MojangAccount object. getMojangAccount()->loadProfiles(loadedProfiles); - - // Finally, we set the current profile to the correct value. This is pretty simple. - // We do need to make sure that the current profile that the server gave us + // We do need to make sure that the current profile that the server gave us // is actually in the available profiles list. // If it isn't, we'll just fail horribly (*shouldn't* ever happen, but you never know). QLOG_DEBUG() << "Setting current profile."; @@ -151,51 +156,23 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) if (!getMojangAccount()->setProfile(currentProfileId)) { // TODO: Set an error to display to the user. - QLOG_ERROR() << "Server specified a selected profile that wasn't in the available profiles list."; + QLOG_ERROR() << "Server specified a selected profile that wasn't in the available " + "profiles list."; return false; } - /* -public class User -{ - private String id; - private List<Property> properties; - - public String getId() - { - return this.id; - } - - public List<Property> getProperties() { - return this.properties; - } - public class Property { - private String name; - private String value; - - public Property() { } - public String getKey() { return this.name; } - - public String getValue() - { - return this.value; - } - } -} -*/ - // this is what the vanilla launcher passes to the userProperties launch param // doesn't seem to be used for anything so far? I don't get any of this data on my account // (peterixxx) // is it a good idea to log this? - if(responseData.contains("user")) + if (responseData.contains("user")) { auto obj = responseData.value("user").toObject(); auto userId = obj.value("id").toString(); auto propArray = obj.value("properties").toArray(); QLOG_DEBUG() << "User ID: " << userId; QLOG_DEBUG() << "User Properties: "; - for(auto prop: propArray) + for (auto prop : propArray) { auto propTuple = prop.toObject(); auto name = propTuple.value("name").toString(); @@ -203,8 +180,9 @@ public class User QLOG_DEBUG() << name << " : " << value; } } - - // We've made it through the minefield of possible errors. Return true to indicate that we've succeeded. + + // We've made it through the minefield of possible errors. Return true to indicate that + // we've succeeded. QLOG_DEBUG() << "Finished reading authentication response."; return true; } @@ -226,5 +204,3 @@ QString AuthenticateTask::getStateMessage(const YggdrasilTask::State state) cons return YggdrasilTask::getStateMessage(state); } } - - diff --git a/logic/auth/AuthenticateTask.h b/logic/auth/flows/AuthenticateTask.h index 54a6b79a..3b99caad 100644 --- a/logic/auth/AuthenticateTask.h +++ b/logic/auth/flows/AuthenticateTask.h @@ -22,25 +22,25 @@ #include <QJsonObject> /** - * The authenticate task takes a MojangAccount with no access token and password and attempts to authenticate with Mojang's servers. + * The authenticate task takes a MojangAccount with no access token and password and attempts to + * authenticate with Mojang's servers. * If successful, it will set the MojangAccount's access token. */ class AuthenticateTask : public YggdrasilTask { -Q_OBJECT + Q_OBJECT public: - AuthenticateTask(MojangAccountPtr account, const QString& password, QObject* parent=0); + AuthenticateTask(MojangAccountPtr account, const QString &password, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const; - + virtual QString getEndpoint() const; virtual bool processResponse(QJsonObject responseData); - + QString getStateMessage(const YggdrasilTask::State state) const; private: QString m_password; }; - diff --git a/logic/auth/flows/InvalidateTask.cpp b/logic/auth/flows/InvalidateTask.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/logic/auth/flows/InvalidateTask.cpp diff --git a/logic/auth/flows/InvalidateTask.h b/logic/auth/flows/InvalidateTask.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/logic/auth/flows/InvalidateTask.h diff --git a/logic/auth/flows/RefreshTask.cpp b/logic/auth/flows/RefreshTask.cpp new file mode 100644 index 00000000..b56ed9bc --- /dev/null +++ b/logic/auth/flows/RefreshTask.cpp @@ -0,0 +1,156 @@ +/* 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 <logic/auth/flows/RefreshTask.h> + +#include <logic/auth/MojangAccount.h> + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QVariant> +#include <QDebug> + +#include "logger/QsLog.h" + +RefreshTask::RefreshTask(MojangAccountPtr account, QObject *parent) + : YggdrasilTask(account, parent) +{ +} + +QJsonObject RefreshTask::getRequestContent() const +{ + /* + * { + * "clientToken": "client identifier" + * "accessToken": "current access token to be refreshed" + * "selectedProfile": // specifying this causes errors + * { + * "id": "profile ID" + * "name": "profile name" + * } + * "requestUser": true/false // request the user structure + * } + */ + auto account = getMojangAccount(); + QJsonObject req; + req.insert("clientToken", account->clientToken()); + req.insert("accessToken", account->accessToken()); + /* + { + auto currentProfile = account->currentProfile(); + QJsonObject profile; + profile.insert("id", currentProfile->id()); + profile.insert("name", currentProfile->name()); + req.insert("selectedProfile", profile); + } + */ + req.insert("requestUser", true); + + return req; +} + +bool RefreshTask::processResponse(QJsonObject responseData) +{ + auto account = getMojangAccount(); + + // Read the response data. We need to get the client token, access token, and the selected + // profile. + QLOG_DEBUG() << "Processing authentication response."; + + // If we already have a client token, make sure the one the server gave us matches our + // existing one. + QString clientToken = responseData.value("clientToken").toString(""); + if (clientToken.isEmpty()) + { + // Fail if the server gave us an empty client token + // TODO: Set an error properly to display to the user. + QLOG_ERROR() << "Server didn't send a client token."; + return false; + } + if (!account->clientToken().isEmpty() && clientToken != account->clientToken()) + { + // The server changed our client token! Obey its wishes, but complain. That's what I do + // for my parents, so... + QLOG_ERROR() << "Server changed our client token to '" << clientToken + << "'. This shouldn't happen, but it isn't really a big deal."; + return false; + } + + // Now, we set the access token. + QLOG_DEBUG() << "Getting new access token."; + QString accessToken = responseData.value("accessToken").toString(""); + if (accessToken.isEmpty()) + { + // Fail if the server didn't give us an access token. + // TODO: Set an error properly to display to the user. + QLOG_ERROR() << "Server didn't send an access token."; + return false; + } + + // we validate that the server responded right. (our current profile = returned current + // profile) + QJsonObject currentProfile = responseData.value("selectedProfile").toObject(); + QString currentProfileId = currentProfile.value("id").toString(""); + if (account->currentProfile()->id() != currentProfileId) + { + // TODO: Set an error to display to the user. + QLOG_ERROR() << "Server didn't specify the same selected profile as ours."; + return false; + } + + // this is what the vanilla launcher passes to the userProperties launch param + if (responseData.contains("user")) + { + auto obj = responseData.value("user").toObject(); + auto userId = obj.value("id").toString(); + auto propArray = obj.value("properties").toArray(); + QLOG_DEBUG() << "User ID: " << userId; + QLOG_DEBUG() << "User Properties: "; + for (auto prop : propArray) + { + auto propTuple = prop.toObject(); + auto name = propTuple.value("name").toString(); + auto value = propTuple.value("value").toString(); + QLOG_DEBUG() << name << " : " << value; + } + } + + // We've made it through the minefield of possible errors. Return true to indicate that + // we've succeeded. + QLOG_DEBUG() << "Finished reading refresh response."; + // Reset the access token. + account->setAccessToken(accessToken); + account->propagateChange(); + return true; +} + +QString RefreshTask::getEndpoint() const +{ + return "refresh"; +} + +QString RefreshTask::getStateMessage(const YggdrasilTask::State state) const +{ + switch (state) + { + case STATE_SENDING_REQUEST: + return tr("Refreshing: Sending request."); + case STATE_PROCESSING_RESPONSE: + return tr("Refreshing: Processing response."); + default: + return YggdrasilTask::getStateMessage(state); + } +} diff --git a/logic/auth/flows/RefreshTask.h b/logic/auth/flows/RefreshTask.h new file mode 100644 index 00000000..2596f6c7 --- /dev/null +++ b/logic/auth/flows/RefreshTask.h @@ -0,0 +1,43 @@ +/* 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. + */ + +#pragma once + +#include <logic/auth/YggdrasilTask.h> + +#include <QObject> +#include <QString> +#include <QJsonObject> + +/** + * The authenticate task takes a MojangAccount with a possibly timed-out access token + * and attempts to authenticate with Mojang's servers. + * If successful, it will set the new access token. The token is considered validated. + */ +class RefreshTask : public YggdrasilTask +{ + Q_OBJECT +public: + RefreshTask(MojangAccountPtr account, QObject *parent = 0); + +protected: + virtual QJsonObject getRequestContent() const; + + virtual QString getEndpoint() const; + + virtual bool processResponse(QJsonObject responseData); + + QString getStateMessage(const YggdrasilTask::State state) const; +}; diff --git a/logic/auth/ValidateTask.cpp b/logic/auth/flows/ValidateTask.cpp index 994d24e4..d9e0e46b 100644 --- a/logic/auth/ValidateTask.cpp +++ b/logic/auth/flows/ValidateTask.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <logic/auth/ValidateTask.h> +#include <logic/auth/flows/ValidateTask.h> #include <logic/auth/MojangAccount.h> @@ -26,8 +26,8 @@ #include "logger/QsLog.h" -ValidateTask::ValidateTask(MojangAccountPtr account, QObject* parent) : - YggdrasilTask(account, parent) +ValidateTask::ValidateTask(MojangAccountPtr account, QObject *parent) + : YggdrasilTask(account, parent) { } @@ -62,5 +62,3 @@ QString ValidateTask::getStateMessage(const YggdrasilTask::State state) const return YggdrasilTask::getStateMessage(state); } } - - diff --git a/logic/auth/ValidateTask.h b/logic/auth/flows/ValidateTask.h index 5bbc69c7..3ff78c6a 100644 --- a/logic/auth/ValidateTask.h +++ b/logic/auth/flows/ValidateTask.h @@ -26,19 +26,18 @@ */ class ValidateTask : public YggdrasilTask { -Q_OBJECT + Q_OBJECT public: - ValidateTask(MojangAccountPtr account, QObject* parent=0); + ValidateTask(MojangAccountPtr account, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const; - + virtual QString getEndpoint() const; virtual bool processResponse(QJsonObject responseData); - + QString getStateMessage(const YggdrasilTask::State state) const; private: }; - diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp index 7081dc6f..b9595578 100644 --- a/logic/lists/InstanceList.cpp +++ b/logic/lists/InstanceList.cpp @@ -281,14 +281,6 @@ InstanceList::InstListError InstanceList::loadList() auto &loader = InstanceFactory::get(); auto error = loader.loadInstance(instPtr, subDir); - switch (error) - { - case InstanceFactory::NoLoadError: - break; - case InstanceFactory::NotAnInstance: - break; - } - if (error != InstanceFactory::NoLoadError && error != InstanceFactory::NotAnInstance) { QString errorMsg = QString("Failed to load instance %1: ") @@ -362,8 +354,13 @@ int InstanceList::add(InstancePtr t) return count() - 1; } -InstancePtr InstanceList::getInstanceById(QString instId) +InstancePtr InstanceList::getInstanceById(QString instId) const { + if (m_instances.isEmpty()) + { + return InstancePtr(); + } + QListIterator<InstancePtr> iter(m_instances); InstancePtr inst; while (iter.hasNext()) @@ -378,7 +375,12 @@ InstancePtr InstanceList::getInstanceById(QString instId) return iter.peekPrevious(); } -int InstanceList::getInstIndex(BaseInstance *inst) +QModelIndex InstanceList::getInstanceIndexById(const QString &id) const +{ + return index(getInstIndex(getInstanceById(id).get())); +} + +int InstanceList::getInstIndex(BaseInstance *inst) const { for (int i = 0; i < m_instances.count(); i++) { diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h index d08501eb..8cd39746 100644 --- a/logic/lists/InstanceList.h +++ b/logic/lists/InstanceList.h @@ -91,7 +91,9 @@ public: int add(InstancePtr t); /// Get an instance by ID - InstancePtr getInstanceById(QString id); + InstancePtr getInstanceById(QString id) const; + + QModelIndex getInstanceIndexById(const QString &id) const; signals: void dataIsInvalid(); @@ -106,7 +108,7 @@ slots: void groupChanged(); private: - int getInstIndex(BaseInstance *inst); + int getInstIndex(BaseInstance *inst) const; protected: QString m_instDir; diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp index ec1937ad..466cc934 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/lists/MojangAccountList.cpp @@ -44,7 +44,6 @@ MojangAccountPtr MojangAccountList::findAccount(const QString &username) const return nullptr; } - const MojangAccountPtr MojangAccountList::at(int i) const { return MojangAccountPtr(m_accounts.at(i)); @@ -53,12 +52,13 @@ const MojangAccountPtr MojangAccountList::at(int i) const void MojangAccountList::addAccount(const MojangAccountPtr account) { beginResetModel(); + connect(account.get(), SIGNAL(changed()), SLOT(accountChanged())); m_accounts.append(account); endResetModel(); onListChanged(); } -void MojangAccountList::removeAccount(const QString& username) +void MojangAccountList::removeAccount(const QString &username) { beginResetModel(); for (auto account : m_accounts) @@ -81,7 +81,6 @@ void MojangAccountList::removeAccount(QModelIndex index) onListChanged(); } - MojangAccountPtr MojangAccountList::activeAccount() const { if (m_activeAccount.isEmpty()) @@ -90,7 +89,7 @@ MojangAccountPtr MojangAccountList::activeAccount() const return findAccount(m_activeAccount); } -void MojangAccountList::setActiveAccount(const QString& username) +void MojangAccountList::setActiveAccount(const QString &username) { beginResetModel(); if (username.isEmpty()) @@ -109,6 +108,11 @@ void MojangAccountList::setActiveAccount(const QString& username) onActiveChanged(); } +void MojangAccountList::accountChanged() +{ + // the list changed. there is no doubt. + onListChanged(); +} void MojangAccountList::onListChanged() { @@ -127,13 +131,11 @@ void MojangAccountList::onActiveChanged() emit activeAccountChanged(); } - int MojangAccountList::count() const { return m_accounts.count(); } - QVariant MojangAccountList::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -220,10 +222,11 @@ void MojangAccountList::updateListData(QList<MojangAccountPtr> versions) endResetModel(); } -bool MojangAccountList::loadList(const QString& filePath) +bool MojangAccountList::loadList(const QString &filePath) { QString path = filePath; - if (path.isEmpty()) path = m_listFilePath; + if (path.isEmpty()) + path = m_listFilePath; if (path.isEmpty()) { QLOG_ERROR() << "Can't load Mojang account list. No file path given and no default set."; @@ -231,7 +234,7 @@ bool MojangAccountList::loadList(const QString& filePath) } QFile file(path); - + // Try to open the file and fail if we can't. // TODO: We should probably report this error to the user. if (!file.open(QIODevice::ReadOnly)) @@ -286,6 +289,7 @@ bool MojangAccountList::loadList(const QString& filePath) MojangAccountPtr account = MojangAccount::loadFromJson(accountObj); if (account.get() != nullptr) { + connect(account.get(), SIGNAL(changed()), SLOT(accountChanged())); m_accounts.append(account); } else @@ -297,14 +301,15 @@ bool MojangAccountList::loadList(const QString& filePath) // Load the active account. m_activeAccount = root.value("activeAccount").toString(""); - + return true; } -bool MojangAccountList::saveList(const QString& filePath) +bool MojangAccountList::saveList(const QString &filePath) { QString path(filePath); - if (path.isEmpty()) path = m_listFilePath; + if (path.isEmpty()) + path = m_listFilePath; if (path.isEmpty()) { QLOG_ERROR() << "Can't save Mojang account list. No file path given and no default set."; @@ -337,7 +342,6 @@ bool MojangAccountList::saveList(const QString& filePath) // Create a JSON document object to convert our JSON to bytes. QJsonDocument doc(root); - // Now that we're done building the JSON object, we can write it to the file. QLOG_DEBUG() << "Writing account list to file."; QFile file(path); @@ -362,6 +366,5 @@ bool MojangAccountList::saveList(const QString& filePath) void MojangAccountList::setListFilePath(QString path, bool autosave) { m_listFilePath = path; - autosave = autosave; + m_autosave = autosave; } - diff --git a/logic/lists/MojangAccountList.h b/logic/lists/MojangAccountList.h index 908f5a7a..744f3c51 100644 --- a/logic/lists/MojangAccountList.h +++ b/logic/lists/MojangAccountList.h @@ -22,7 +22,6 @@ #include "logic/auth/MojangAccount.h" - /*! * \brief List of available Mojang accounts. * This should be loaded in the background by MultiMC on startup. @@ -44,10 +43,10 @@ public: enum VListColumns { // TODO: Add icon column. - + // First column - Active? ActiveColumn = 0, - + // Second column - Name NameColumn, }; @@ -74,7 +73,7 @@ public: /*! * Removes the mojang account with the given username from the account list. */ - virtual void removeAccount(const QString& username); + virtual void removeAccount(const QString &username); /*! * Removes the account at the given QModelIndex. @@ -88,7 +87,7 @@ public: * one doesn't exist. */ virtual MojangAccountPtr findAccount(const QString &username) const; - + /*! * Sets the default path to save the list file to. * If autosave is true, this list will automatically save to the given path whenever it changes. @@ -96,21 +95,21 @@ public: * after calling this function to ensure an autosaved change doesn't overwrite the list you intended * to load. */ - virtual void setListFilePath(QString path, bool autosave=false); + virtual void setListFilePath(QString path, bool autosave = false); /*! * \brief Loads the account list from the given file path. * If the given file is an empty string (default), will load from the default account list file. * \return True if successful, otherwise false. */ - virtual bool loadList(const QString& file=""); + virtual bool loadList(const QString &file = ""); /*! * \brief Saves the account list to the given file. * If the given file is an empty string (default), will save from the default account list file. * \return True if successful, otherwise false. */ - virtual bool saveList(const QString& file=""); + virtual bool saveList(const QString &file = ""); /*! * \brief Gets a pointer to the account that the user has selected as their "active" account. @@ -124,12 +123,13 @@ public: * Sets the given account as the current active account. * If the username given is an empty string, sets the active account to nothing. */ - virtual void setActiveAccount(const QString& username); + virtual void setActiveAccount(const QString &username); signals: /*! * Signal emitted to indicate that the account list has changed. - * This will also fire if the value of an element in the list changes (will be implemented later). + * This will also fire if the value of an element in the list changes (will be implemented + * later). */ void listChanged(); @@ -138,6 +138,13 @@ signals: */ void activeAccountChanged(); +public +slots: + /** + * This is called when one of the accounts changes and the list needs to be updated + */ + void accountChanged(); + protected: /*! * Called whenever the list changes. @@ -166,7 +173,7 @@ protected: * If true, the account list will automatically save to the account list path when it changes. * Ignored if m_listFilePath is blank. */ - bool m_autosave; + bool m_autosave = false; protected slots: @@ -184,4 +191,3 @@ slots: */ virtual void updateListData(QList<MojangAccountPtr> versions); }; - diff --git a/test.cpp b/test.cpp deleted file mode 100644 index 2b015454..00000000 --- a/test.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include <iostream> - -#include "keyring.h" -#include "cmdutils.h" - -using namespace Util::Commandline; - -#include <QCoreApplication> - -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<QString, QVariant> 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; - } -} |