diff --git a/.ci/install.sh b/.ci/install.sh index 57e73e03..776d4d23 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -3,14 +3,6 @@ set -ex if [ "$TRAVIS_OS_NAME" = "osx" ]; then - brew update - - # uninstall packages, that would get upgraded by upgrading cmake (and we don't need) - brew uninstall --force cgal node sfcgal postgis - - brew install qt5 lmdb clang-format ninja libsodium cmark - brew upgrade boost cmake icu4c || true - brew tap nlohmann/json brew install --with-cmake nlohmann_json @@ -25,11 +17,11 @@ fi if [ "$TRAVIS_OS_NAME" = "linux" ]; then + sudo update-alternatives --install /usr/bin/gcc gcc "/usr/bin/${CC}" 10 + sudo update-alternatives --install /usr/bin/g++ g++ "/usr/bin/${CXX}" 10 - if [ -z "$QT_VERSION" ]; then - QT_VERSION="592" - QT_PKG="59" - fi + sudo update-alternatives --set gcc "/usr/bin/${CC}" + sudo update-alternatives --set g++ "/usr/bin/${CXX}" wget https://cmake.org/files/v3.15/cmake-3.15.5-Linux-x86_64.sh sudo sh cmake-3.15.5-Linux-x86_64.sh --skip-license --prefix=/usr/local @@ -40,21 +32,4 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then tar xfz libsodium-1.0.17.tar.gz cd libsodium-1.0.17/ ./configure && make && sudo make install ) - - sudo add-apt-repository -y ppa:beineri/opt-qt${QT_VERSION}-trusty - # needed for git-lfs, otherwise the follow apt update fails. - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 6B05F25D762E3157 - - # needed for mongodb repository: https://github.com/travis-ci/travis-ci/issues/9037 - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 - - sudo apt update -qq - sudo apt install -qq -y \ - qt${QT_PKG}base \ - qt${QT_PKG}tools \ - qt${QT_PKG}svg \ - qt${QT_PKG}multimedia \ - qt${QT_PKG}quickcontrols2 \ - qt${QT_PKG}graphicaleffects \ - liblmdb-dev fi diff --git a/.ci/linux/deploy.sh b/.ci/linux/deploy.sh index 524d72d5..ff8ef6ca 100755 --- a/.ci/linux/deploy.sh +++ b/.ci/linux/deploy.sh @@ -36,7 +36,7 @@ unset LD_LIBRARY_PATH ARCH=$(uname -m) export ARCH -LD_LIBRARY_PATH=$(pwd)/.deps/usr/lib/:$LD_LIBRARY_PATH +LD_LIBRARY_PATH=$(pwd)/.deps/usr/lib/:/usr/local/lib/:$LD_LIBRARY_PATH export LD_LIBRARY_PATH for res in ./linuxdeployqt*.AppImage diff --git a/.ci/script.sh b/.ci/script.sh index 06536278..7e9a8d81 100755 --- a/.ci/script.sh +++ b/.ci/script.sh @@ -3,17 +3,9 @@ set -ex if [ "$TRAVIS_OS_NAME" = "linux" ]; then - export CC=${C_COMPILER} - export CXX=${CXX_COMPILER} # make build use all available cores export CMAKE_BUILD_PARALLEL_LEVEL=$(cat /proc/cpuinfo | awk '/^processor/{print $3}' | wc -l) - sudo update-alternatives --install /usr/bin/gcc gcc "/usr/bin/${C_COMPILER}" 10 - sudo update-alternatives --install /usr/bin/g++ g++ "/usr/bin/${CXX_COMPILER}" 10 - - sudo update-alternatives --set gcc "/usr/bin/${C_COMPILER}" - sudo update-alternatives --set g++ "/usr/bin/${CXX_COMPILER}" - export PATH="/usr/local/bin/:${PATH}" cmake --version fi diff --git a/.travis.yml b/.travis.yml index 3abb8bfd..1e2bc5b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: cpp sudo: required -dist: trusty +dist: xenial notifications: webhooks: @@ -19,61 +19,108 @@ matrix: include: - os: osx compiler: clang - # Use the default osx image, because that one is actually tested to work with homebrew and probably the oldest supported version - # osx_image: xcode9 + # C++17 support + osx_image: xcode10.2 env: - - DEPLOYMENT=1 - - USE_BUNDLED_BOOST=0 - - USE_BUNDLED_CMARK=0 - - USE_BUNDLED_JSON=0 - - MTX_STATIC=1 + - DEPLOYMENT=1 + - USE_BUNDLED_BOOST=0 + - USE_BUNDLED_CMARK=0 + - USE_BUNDLED_JSON=0 + - MTX_STATIC=1 + addons: + homebrew: + taps: nlohmann/json + packages: + - boost + - clang-format + - cmake + - cmark + - icu4c + - libsodium + - lmdb + - ninja + - openssl + - qt5 - os: linux - compiler: gcc + compiler: gcc-7 env: - - CXX_COMPILER=g++-5 - - C_COMPILER=gcc-5 - - QT_VERSION="-5.10.1" - - QT_PKG=510 + - CXX=g++-7 + - CC=gcc-7 + - QT_PKG=512 - DEPLOYMENT=1 - USE_BUNDLED_BOOST=1 - USE_BUNDLED_CMARK=1 - USE_BUNDLED_JSON=1 addons: apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["g++-5", "ninja-build"] + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:beineri/opt-qt-5.12.6-xenial' + packages: + - g++-7 + - ninja-build + - qt512base + - qt512tools + - qt512svg + - qt512multimedia + - qt512quickcontrols2 + - qt512graphicaleffects + - liblmdb-dev + - libgl1-mesa-dev # needed for missing gl.h - os: linux - compiler: gcc + compiler: gcc-8 env: - - CXX_COMPILER=g++-8 - - C_COMPILER=gcc-8 - - QT_VERSION=592 + - CXX=g++-8 + - CC=gcc-8 - QT_PKG=59 - USE_BUNDLED_BOOST=1 - USE_BUNDLED_CMARK=1 - USE_BUNDLED_JSON=1 addons: apt: - sources: ["ubuntu-toolchain-r-test"] - packages: ["g++-8", "ninja-build"] + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:beineri/opt-qt597-xenial' + packages: + - g++-8 + - ninja-build + - qt59base + - qt59tools + - qt59svg + - qt59multimedia + - qt59quickcontrols2 + - qt59graphicaleffects + - liblmdb-dev + - libgl1-mesa-dev # needed for missing gl.h - os: linux - compiler: clang + compiler: clang-6 env: - - CXX_COMPILER=clang++-5.0 - - C_COMPILER=clang-5.0 - - QT_VERSION=592 + - CXX=clang++-6.0 + - CC=clang-6.0 - QT_PKG=59 - USE_BUNDLED_BOOST=1 - USE_BUNDLED_CMARK=1 - USE_BUNDLED_JSON=1 addons: apt: - sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"] - packages: ["clang-5.0", "g++-7", "ninja-build"] + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-6.0 + - sourceline: 'ppa:beineri/opt-qt597-xenial' + packages: + - clang++-6.0 + - g++-7 + - ninja-build + - qt59base + - qt59tools + - qt59svg + - qt59multimedia + - qt59quickcontrols2 + - qt59graphicaleffects + - liblmdb-dev + - libgl1-mesa-dev # needed for missing gl.h before_install: - - export CXX=${CXX_COMPILER} - - export CC=${C_COMPILER} # Use TRAVIS_TAG if defined, or the short commit SHA otherwise - export VERSION=${TRAVIS_TAG:-$(git rev-parse --short HEAD)} install: diff --git a/CMakeLists.txt b/CMakeLists.txt index 67a1dfb0..39dadc64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,6 @@ option(ASAN "Compile with address sanitizers" OFF) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -add_definitions(-DBOOST_MPL_LIMIT_LIST_SIZE=30) -add_definitions(-DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) - include(GNUInstallDirs) # Include Qt basic functions @@ -15,8 +12,8 @@ include(QtCommon) project(nheko LANGUAGES C CXX) set(CPACK_PACKAGE_VERSION_MAJOR "0") -set(CPACK_PACKAGE_VERSION_MINOR "6") -set(CPACK_PACKAGE_VERSION_PATCH "4") +set(CPACK_PACKAGE_VERSION_MINOR "7") +set(CPACK_PACKAGE_VERSION_PATCH "0") set(PROJECT_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set(PROJECT_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) set(PROJECT_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) @@ -27,7 +24,7 @@ fix_project_version() # Set additional project information set(COMPANY "Nheko") -set(COPYRIGHT "Copyright (c) 2018 Nheko Contributors") +set(COPYRIGHT "Copyright (c) 2019 Nheko Contributors") set(IDENTIFIER "com.github.mujx.nheko") add_project_meta(META_FILES_TO_INCLUDE) @@ -91,7 +88,7 @@ if (NOT MSVC) set(CMAKE_C_COMPILER gcc) endif(NOT MSVC) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) if(NOT MSVC) @@ -106,7 +103,7 @@ if(NOT MSVC) -fsized-deallocation \ -fdiagnostics-color=always \ -Wunreachable-code \ - -std=c++14" + -std=c++17" ) if (NOT CMAKE_COMPILER_IS_GNUCXX) # -Wshadow is buggy and broken in GCC, so do not enable it. diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index fbe9275f..cf42b7b5 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -46,10 +46,10 @@ set(BOOST_SHA256 set( MTXCLIENT_URL - https://github.com/Nheko-Reborn/mtxclient/archive/1945952864ef87a6afeb57b0beb80756d0647381.zip + https://github.com/Nheko-Reborn/mtxclient/archive/fd5208d85ecc9e077fe0fde5424ba225849cccf7.zip ) set(MTXCLIENT_HASH - 727cd145c0c1e9c168aaeded3b7cc9801c63b4da5e8cd0a4782982d08770816e) + 24ef9d5562ed6d83d6c28f6c8de559487029f3bdc35d9fe8e5799283ff999513) set( TWEENY_URL https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz diff --git a/deps/cmake/Json.cmake b/deps/cmake/Json.cmake index 3b63550e..c5e66cea 100644 --- a/deps/cmake/Json.cmake +++ b/deps/cmake/Json.cmake @@ -13,7 +13,7 @@ ExternalProject_Add( -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} BUILD_COMMAND ${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}/json - INSTALL_COMMAND make install + INSTALL_COMMAND ${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}/json --target install ) list(APPEND THIRD_PARTY_DEPS Json) diff --git a/src/Cache.cpp b/src/Cache.cpp index 083dbe89..d3aec9db 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -26,7 +27,6 @@ #include #include -#include #include #include "Cache.h" @@ -395,7 +395,7 @@ Cache::saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr txn.commit(); } -boost::optional +std::optional Cache::getOlmSession(const std::string &curve25519, const std::string &session_id) { using namespace mtx::crypto; @@ -413,7 +413,7 @@ Cache::getOlmSession(const std::string &curve25519, const std::string &session_i return unpickle(data, SECRET); } - return boost::none; + return std::nullopt; } std::vector @@ -967,8 +967,8 @@ Cache::saveState(const mtx::responses::Sync &res) bool has_new_tags = false; for (const auto &evt : room.second.account_data.events) { // for now only fetch tag events - if (evt.type() == typeid(Event)) { - auto tags_evt = boost::get>(evt); + if (std::holds_alternative>(evt)) { + auto tags_evt = std::get>(evt); has_new_tags = true; for (const auto &tag : tags_evt.content.tags) { updatedInfo.tags.push_back(tag.first); @@ -1049,19 +1049,17 @@ Cache::saveInvite(lmdb::txn &txn, using namespace mtx::events::state; for (const auto &e : room.invite_state) { - if (boost::get>(&e) != nullptr) { - auto msg = boost::get>(e); + if (auto msg = std::get_if>(&e)) { + auto display_name = msg->content.display_name.empty() + ? msg->state_key + : msg->content.display_name; - auto display_name = msg.content.display_name.empty() - ? msg.state_key - : msg.content.display_name; - - MemberInfo tmp{display_name, msg.content.avatar_url}; + MemberInfo tmp{display_name, msg->content.avatar_url}; lmdb::dbi_put( - txn, membersdb, lmdb::val(msg.state_key), lmdb::val(json(tmp).dump())); + txn, membersdb, lmdb::val(msg->state_key), lmdb::val(json(tmp).dump())); } else { - boost::apply_visitor( + std::visit( [&txn, &statesdb](auto msg) { bool res = lmdb::dbi_put(txn, statesdb, @@ -1122,7 +1120,7 @@ Cache::roomsWithTagUpdates(const mtx::responses::Sync &res) for (const auto &room : res.rooms.join) { bool hasUpdates = false; for (const auto &evt : room.second.account_data.events) { - if (evt.type() == typeid(Event)) { + if (std::holds_alternative>(evt)) { hasUpdates = true; } } @@ -1940,7 +1938,7 @@ Cache::saveTimelineMessages(lmdb::txn &txn, if (isStateEvent(e)) continue; - if (boost::get>(&e) != nullptr) + if (std::holds_alternative>(e)) continue; json obj = json::object(); diff --git a/src/Cache.h b/src/Cache.h index f5e1cfa0..878ac9ce 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -17,7 +17,8 @@ #pragma once -#include +#include +#include #include #include @@ -25,11 +26,11 @@ #include #include +#include + #include #include #include -#include -#include #include "Logging.h" #include "MatrixClient.h" @@ -453,8 +454,8 @@ public: // void saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session); std::vector getOlmSessions(const std::string &curve25519); - boost::optional getOlmSession(const std::string &curve25519, - const std::string &session_id); + std::optional getOlmSession(const std::string &curve25519, + const std::string &session_id); void saveOlmAccount(const std::string &pickled); std::string restoreOlmAccount(); @@ -517,52 +518,50 @@ private: using namespace mtx::events; using namespace mtx::events::state; - if (boost::get>(&event) != nullptr) { - const auto e = boost::get>(event); - - switch (e.content.membership) { + if (auto e = std::get_if>(&event); e != nullptr) { + switch (e->content.membership) { // // We only keep users with invite or join membership. // case Membership::Invite: case Membership::Join: { - auto display_name = e.content.display_name.empty() - ? e.state_key - : e.content.display_name; + auto display_name = e->content.display_name.empty() + ? e->state_key + : e->content.display_name; // Lightweight representation of a member. - MemberInfo tmp{display_name, e.content.avatar_url}; + MemberInfo tmp{display_name, e->content.avatar_url}; lmdb::dbi_put(txn, membersdb, - lmdb::val(e.state_key), + lmdb::val(e->state_key), lmdb::val(json(tmp).dump())); insertDisplayName(QString::fromStdString(room_id), - QString::fromStdString(e.state_key), + QString::fromStdString(e->state_key), QString::fromStdString(display_name)); insertAvatarUrl(QString::fromStdString(room_id), - QString::fromStdString(e.state_key), - QString::fromStdString(e.content.avatar_url)); + QString::fromStdString(e->state_key), + QString::fromStdString(e->content.avatar_url)); break; } default: { lmdb::dbi_del( - txn, membersdb, lmdb::val(e.state_key), lmdb::val("")); + txn, membersdb, lmdb::val(e->state_key), lmdb::val("")); removeDisplayName(QString::fromStdString(room_id), - QString::fromStdString(e.state_key)); + QString::fromStdString(e->state_key)); removeAvatarUrl(QString::fromStdString(room_id), - QString::fromStdString(e.state_key)); + QString::fromStdString(e->state_key)); break; } } return; - } else if (boost::get>(&event) != nullptr) { + } else if (std::holds_alternative>(event)) { setEncryptedRoom(txn, room_id); return; } @@ -570,7 +569,7 @@ private: if (!isStateEvent(event)) return; - boost::apply_visitor( + std::visit( [&txn, &statesdb](auto e) { lmdb::dbi_put( txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump())); @@ -584,17 +583,17 @@ private: using namespace mtx::events; using namespace mtx::events::state; - return boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr; + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); } template @@ -603,11 +602,11 @@ private: using namespace mtx::events; using namespace mtx::events::state; - return boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr; + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); } bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e) @@ -615,11 +614,11 @@ private: using namespace mtx::events; using namespace mtx::events::state; - return boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr || - boost::get>(&e) != nullptr; + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); } void saveInvites(lmdb::txn &txn, diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 35d262ac..c496acab 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -54,7 +54,7 @@ constexpr int CHECK_CONNECTIVITY_INTERVAL = 15'000; constexpr int RETRY_TIMEOUT = 5'000; constexpr size_t MAX_ONETIME_KEYS = 50; -Q_DECLARE_METATYPE(boost::optional) +Q_DECLARE_METATYPE(std::optional) ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) : QWidget(parent) @@ -64,8 +64,8 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) { setObjectName("chatPage"); - qRegisterMetaType>( - "boost::optional"); + qRegisterMetaType>( + "std::optional"); topLayout_ = new QHBoxLayout(this); topLayout_->setSpacing(0); @@ -318,7 +318,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) auto bin = dev->peek(dev->size()); auto payload = std::string(bin.data(), bin.size()); - boost::optional encryptedFile; + std::optional encryptedFile; if (cache::client()->isRoomEncrypted(current_room_.toStdString())) { mtx::crypto::BinaryBuf buf; std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload); @@ -371,7 +371,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, [this](QString roomid, QString filename, - boost::optional encryptedFile, + std::optional encryptedFile, QString url, QString mimeClass, QString mime, diff --git a/src/ChatPage.h b/src/ChatPage.h index 20e156af..6ca30b3d 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -18,8 +18,9 @@ #pragma once #include -#include -#include +#include +#include + #include #include @@ -98,7 +99,7 @@ signals: void uploadFailed(const QString &msg); void mediaUploaded(const QString &roomid, const QString &filename, - const boost::optional &file, + const std::optional &file, const QString &url, const QString &mimeClass, const QString &mime, @@ -252,9 +253,8 @@ ChatPage::getMemberships(const std::vector &collection) const using Member = mtx::events::StateEvent; for (const auto &event : collection) { - if (boost::get(event) != nullptr) { - auto member = boost::get(event); - memberships.emplace(member.state_key, member); + if (auto member = std::get_if(event)) { + memberships.emplace(member->state_key, *member); } } diff --git a/src/Olm.cpp b/src/Olm.cpp index c1598570..9c1a25df 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -1,4 +1,4 @@ -#include +#include #include "Olm.h" @@ -289,14 +289,13 @@ request_keys(const std::string &room_id, const std::string &event_id) return; } - if (boost::get>(&res) == nullptr) { + if (!std::holds_alternative>(res)) { nhlog::net()->info( "retrieved event is not encrypted: {} from {}", event_id, room_id); return; } - olm::send_key_request_for(room_id, - boost::get>(res)); + olm::send_key_request_for(room_id, std::get>(res)); }); } diff --git a/src/Utils.cpp b/src/Utils.cpp index 8f9e0643..3d69162f 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -9,9 +9,10 @@ #include #include #include + #include +#include -#include #include #include "Config.h" @@ -122,34 +123,33 @@ utils::getMessageDescription(const TimelineEvent &event, using Video = mtx::events::RoomEvent; using Encrypted = mtx::events::EncryptedEvent; - if (boost::get