├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── bin └── .gitignore ├── build └── .gitignore ├── doc ├── Doxyfile ├── html.zip └── images │ ├── about.png │ ├── add-book.png │ ├── administer.png │ ├── book.png │ ├── borrow-book.png │ ├── borrow-record.png │ ├── login.png │ ├── newest-book.png │ ├── record.png │ ├── search.png │ ├── setting.png │ ├── sign-up.png │ ├── star.png │ ├── top.png │ ├── 切换语言.gif │ ├── 刷新缓存(更新排行榜).gif │ ├── 收藏和借阅.gif │ ├── 收藏夹.gif │ ├── 查看书籍.gif │ ├── 添加书籍.png │ ├── 编辑书籍.gif │ ├── 编辑用户信息及注销.gif │ ├── 记录.gif │ ├── 设置权限.png │ └── 还书.png └── src ├── CMakeLists.txt ├── README.md ├── client ├── CMakeLists.txt ├── README.md ├── core │ ├── Book.cpp │ ├── Book.h │ ├── BookBrief.cpp │ ├── BookBrief.h │ ├── BorrowRecord.cpp │ ├── BorrowRecord.h │ ├── BrowseRecord.cpp │ ├── BrowseRecord.h │ ├── KeepRecord.cpp │ ├── KeepRecord.h │ ├── LoginRecord.cpp │ ├── LoginRecord.h │ ├── StarRecord.cpp │ ├── StarRecord.h │ ├── User.cpp │ └── User.h ├── dialog │ ├── DialogBook.cpp │ ├── DialogBook.h │ ├── DialogChooseTime.cpp │ ├── DialogChooseTime.h │ ├── DialogLogin.cpp │ ├── DialogLogin.h │ ├── DialogModifyBook.cpp │ ├── DialogModifyBook.h │ ├── DialogModifyUser.cpp │ ├── DialogModifyUser.h │ ├── DialogRefresh.cpp │ ├── DialogRefresh.h │ ├── DialogSignUp.cpp │ └── DialogSignUp.h ├── listwidget │ ├── ListWidgetBorrowRecord.cpp │ ├── ListWidgetBorrowRecord.h │ ├── ListWidgetBrowseBook.cpp │ ├── ListWidgetBrowseBook.h │ ├── ListWidgetBrowseRecord.cpp │ ├── ListWidgetBrowseRecord.h │ ├── ListWidgetKeepRecord.cpp │ ├── ListWidgetKeepRecord.h │ ├── ListWidgetLoginRecord.cpp │ ├── ListWidgetLoginRecord.h │ ├── ListWidgetStarRecord.cpp │ └── ListWidgetStarRecord.h ├── main.cpp ├── mainwindow │ ├── MainWindow.cpp │ └── MainWindow.h ├── manager │ ├── BookManager.cpp │ ├── BookManager.h │ ├── UserManager.cpp │ └── UserManager.h ├── object │ ├── GetRecords.cpp │ └── GetRecords.h ├── page │ ├── PageAbout.cpp │ ├── PageAbout.h │ ├── PageAddBook.cpp │ ├── PageAddBook.h │ ├── PageAdminister.cpp │ ├── PageAdminister.h │ ├── PageBrowse.cpp │ ├── PageBrowse.h │ ├── PageFavorite.cpp │ ├── PageFavorite.h │ ├── PageRecord.cpp │ ├── PageRecord.h │ ├── PageSetting.cpp │ └── PageSetting.h ├── resource │ ├── i18n │ │ ├── qt_zh_CN.qm │ │ ├── zh_CN.qm │ │ └── zh_CN.ts │ ├── images │ │ └── WidgetLogin │ │ │ ├── close.png │ │ │ ├── drop_down_button.png │ │ │ ├── head.jpg │ │ │ └── min.png │ ├── resource.qrc │ └── style │ │ ├── DialogBook │ │ └── style.css │ │ ├── DialogSignUp │ │ └── style.css │ │ ├── ListWidgetNavigation │ │ └── style.css │ │ ├── WidgetLogin │ │ ├── style.css │ │ └── title.css │ │ └── WidgetMain │ │ └── style.css ├── thread │ ├── ThreadBorrowBook.cpp │ ├── ThreadBorrowBook.h │ ├── ThreadGetBook.cpp │ ├── ThreadGetBook.h │ ├── ThreadGetNewBookList.cpp │ ├── ThreadGetNewBookList.h │ ├── ThreadGetRecord.cpp │ ├── ThreadGetRecord.h │ ├── ThreadGetSearchBookList.cpp │ ├── ThreadGetSearchBookList.h │ ├── ThreadGetTopBookList.cpp │ ├── ThreadGetTopBookList.h │ ├── ThreadLogin.cpp │ ├── ThreadLogin.h │ ├── ThreadLogout.cpp │ ├── ThreadLogout.h │ ├── ThreadModifyUser.cpp │ ├── ThreadModifyUser.h │ ├── ThreadNetwork.cpp │ ├── ThreadNetwork.h │ ├── ThreadReturnBook.cpp │ ├── ThreadReturnBook.h │ ├── ThreadSetBook.cpp │ ├── ThreadSetBook.h │ ├── ThreadSetPriority.cpp │ ├── ThreadSetPriority.h │ ├── ThreadSignUp.cpp │ ├── ThreadSignUp.h │ ├── ThreadStarBook.cpp │ ├── ThreadStarBook.h │ ├── ThreadUnStarBook.cpp │ └── ThreadUnStarBook.h ├── utils.cpp ├── utils.h ├── values.cpp ├── values.h └── widget │ ├── WidgetHead.cpp │ ├── WidgetHead.h │ ├── WidgetLogin.cpp │ ├── WidgetLogin.h │ ├── WidgetLogin.ui │ ├── WidgetLoginTitle.cpp │ ├── WidgetLoginTitle.h │ ├── WidgetMain.cpp │ ├── WidgetMain.h │ ├── WidgetSearchBook.cpp │ ├── WidgetSearchBook.h │ ├── WidgetSetBook.cpp │ └── WidgetSetBook.h ├── core ├── CMakeLists.txt ├── README.md ├── Resource.cpp ├── Resource.h ├── SocketInfo.cpp ├── SocketInfo.h ├── types.h ├── utils.cpp ├── utils.h ├── values.cpp └── values.h ├── server ├── CMakeLists.txt ├── README.md ├── core │ ├── Server.cpp │ ├── Server.h │ ├── Session.cpp │ └── Session.h ├── main.cpp ├── manager │ ├── SessionManager.cpp │ ├── SessionManager.h │ ├── SocketManager.cpp │ ├── SocketManager.h │ ├── UserManager.cpp │ └── UserManager.h ├── utils.cpp ├── utils.h ├── values.cpp └── values.h └── test ├── CMakeLists.txt ├── book ├── 1 │ └── cover.jpg ├── 2 │ └── cover.jpg ├── 3 │ └── cover.jpg ├── 4 │ └── cover.jpg ├── 5 │ └── cover.jpg ├── 6 │ └── cover.jpg ├── 7 │ └── cover.jpg ├── 8 │ └── cover.jpg ├── 9 │ └── cover.jpg ├── 10 │ └── cover.jpg ├── 11 │ └── cover.jpg ├── 12 │ └── cover.jpg ├── 13 │ └── cover.jpg ├── 14 │ └── cover.jpg ├── 15 │ └── cover.jpg ├── 16 │ └── cover.jpg ├── 17 │ └── cover.jpg ├── 18 │ └── cover.jpg ├── 19 │ └── cover.jpg ├── 20 │ └── cover.jpg ├── 21 │ └── cover.jpg └── 22 │ └── cover.jpg ├── testServer1.cpp ├── testServer2.cpp ├── testServer3.cpp └── testServer4.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /tmp -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | env: 12 | global: 13 | - DEPS_DIR=deps 14 | - CMAKE_VERSION=v3.11 15 | - CMAKE_FILE=cmake-3.11.2-Linux-x86_64.tar.gz 16 | matrix: 17 | - CONFIG=Release 18 | - CONFIG=Debug 19 | 20 | addons: 21 | apt: 22 | sources: 23 | - ubuntu-toolchain-r-test 24 | - llvm-toolchain-precise-3.7 25 | 26 | packages: 27 | - mongodb-org-server 28 | - g++-5 29 | - clang-3.8 30 | 31 | install: 32 | # GCC 33 | - if [ "$CXX" = "g++" ]; then export CXX="g++-5"; export CC="gcc-5"; fi 34 | 35 | # Clang 36 | - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.8"; export CC="clang-3.8"; fi 37 | 38 | # Install dependencies 39 | - curl -O https://cmake.org/files/${CMAKE_VERSION}/${CMAKE_FILE} 40 | - tar -zxf ${CMAKE_FILE} -C ${DEPS_DIR}/cmake 41 | - export PATH=${DEPS_DIR}/cmake/bin:${PATH} 42 | 43 | before_script: 44 | - $CC --version 45 | - $CXX --version 46 | - cmake --version 47 | 48 | - cd build 49 | # - cmake -DCMAKE_BUILD_TYPE=$CONFIG -DBUILD_ALL=ON -DBUILD_STATIC=ON .. 50 | 51 | script: 52 | # - make -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | message(STATUS "========================================") 4 | message(STATUS "========================================") 5 | message(STATUS "Building PiLibrary v1.0.0 PI!pi!Pi!pI!") 6 | message(STATUS "Author: xalanq, chang-ran") 7 | message(STATUS "License: LGPL v3.0") 8 | message(STATUS "========================================") 9 | message(STATUS "========================================") 10 | 11 | project(PiLibrary LANGUAGES CXX) 12 | 13 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 14 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.2") 15 | message(FATAL_ERROR "Insufficient GCC version - GCC 4.8.2+ required") 16 | endif() 17 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 18 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0.23506") 19 | message(FATAL_ERROR "Insufficient Microsoft Visual C++ version - MSVC 2015 Update 1+ required") 20 | endif() 21 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") 22 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1") 23 | message(FATAL_ERROR "Insufficient Apple clang version - XCode 5.1+ required") 24 | endif() 25 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 26 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.5") 27 | message(FATAL_ERROR "Insufficient clang version - clang 3.5+ required") 28 | endif() 29 | else() 30 | message(WARNING "Unknown compiler... recklessly proceeding without a version check") 31 | endif() 32 | 33 | set(CMAKE_CXX_STANDARD 11) 34 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 35 | set(CMAKE_CXX_EXTENSIONS OFF) 36 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 37 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/bin) 38 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/bin) 39 | 40 | if (NOT CMAKE_BUILD_TYPE) 41 | message(STATUS "No build type selected, default is Release") 42 | set(CMAKE_BUILD_TYPE "Release") 43 | endif() 44 | 45 | if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 46 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") 47 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 48 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") 49 | endif() 50 | endif() 51 | 52 | add_subdirectory(src) -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /doc/html.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/html.zip -------------------------------------------------------------------------------- /doc/images/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/about.png -------------------------------------------------------------------------------- /doc/images/add-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/add-book.png -------------------------------------------------------------------------------- /doc/images/administer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/administer.png -------------------------------------------------------------------------------- /doc/images/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/book.png -------------------------------------------------------------------------------- /doc/images/borrow-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/borrow-book.png -------------------------------------------------------------------------------- /doc/images/borrow-record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/borrow-record.png -------------------------------------------------------------------------------- /doc/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/login.png -------------------------------------------------------------------------------- /doc/images/newest-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/newest-book.png -------------------------------------------------------------------------------- /doc/images/record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/record.png -------------------------------------------------------------------------------- /doc/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/search.png -------------------------------------------------------------------------------- /doc/images/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/setting.png -------------------------------------------------------------------------------- /doc/images/sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/sign-up.png -------------------------------------------------------------------------------- /doc/images/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/star.png -------------------------------------------------------------------------------- /doc/images/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/top.png -------------------------------------------------------------------------------- /doc/images/切换语言.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/切换语言.gif -------------------------------------------------------------------------------- /doc/images/刷新缓存(更新排行榜).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/刷新缓存(更新排行榜).gif -------------------------------------------------------------------------------- /doc/images/收藏和借阅.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/收藏和借阅.gif -------------------------------------------------------------------------------- /doc/images/收藏夹.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/收藏夹.gif -------------------------------------------------------------------------------- /doc/images/查看书籍.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/查看书籍.gif -------------------------------------------------------------------------------- /doc/images/添加书籍.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/添加书籍.png -------------------------------------------------------------------------------- /doc/images/编辑书籍.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/编辑书籍.gif -------------------------------------------------------------------------------- /doc/images/编辑用户信息及注销.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/编辑用户信息及注销.gif -------------------------------------------------------------------------------- /doc/images/记录.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/记录.gif -------------------------------------------------------------------------------- /doc/images/设置权限.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/设置权限.png -------------------------------------------------------------------------------- /doc/images/还书.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/doc/images/还书.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | option(BUILD_STATIC_X "Build static version" OFF) 2 | option(BUILD_CLIENT_X "Build client" OFF) 3 | option(BUILD_SERVER_X "Build server" OFF) 4 | option(BUILD_BOTH_X "Build server, client" OFF) 5 | option(BUILD_ALL_X "Build server, client, test" OFF) 6 | 7 | if (NOT BUILD_CLIENT_X AND NOT BUILD_SERVER_X AND NOT BUILD_BOTH_X AND NOT BUILD_ALL_X) 8 | message(STATUS "=========Use BUILD_BOTH_X(default)========") 9 | set(BUILD_BOTH_X ON) 10 | endif() 11 | 12 | if (BUILD_STATIC_X) 13 | message(STATUS "==========Build Static Version==========") 14 | else() 15 | message(STATUS "==========Build Dynamic Version=========") 16 | endif() 17 | 18 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 19 | message(STATUS "==========Build Release Version==========") 20 | else() 21 | message(STATUS "==========Build Debug Version===========") 22 | endif() 23 | 24 | message(STATUS "===============Build Core===============") 25 | add_subdirectory(core) 26 | 27 | if (BUILD_CLIENT_X OR BUILD_BOTH_X OR BUILD_ALL_X) 28 | message(STATUS "==============Build Client==============") 29 | add_subdirectory(client) 30 | endif() 31 | 32 | if (BUILD_SERVER_X OR BUILD_BOTH_X OR BUILD_ALL_X) 33 | message(STATUS "==============Build Server==============") 34 | add_subdirectory(server) 35 | endif() 36 | 37 | if (BUILD_SERVER_X_TEST OR BUILD_ALL_X) 38 | message(STATUS "===============Build Test===============") 39 | add_subdirectory(test) 40 | endif() -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ## PiLibrary 源码 2 | 3 | * [client](./client):客户端 4 | * [core](./core):核心接口 5 | * [server](./server):服务端 6 | * [test](./test):单元测试 -------------------------------------------------------------------------------- /src/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(client) 2 | 3 | set(Boost_USE_STATIC_LIBS ON) 4 | set(Boost_USE_MULTITHREADED ON) 5 | set(Boost_USE_STATIC_RUNTIME OFF) 6 | 7 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 8 | set(Boost_USE_RELEASE_LIBS ON) 9 | set(Boost_USE_DEBUG_LIBS OFF) 10 | set(Boost_USE_DEBUG_RUNTIME OFF) 11 | else() 12 | set(Boost_USE_RELEASE_LIBS OFF) 13 | set(Boost_USE_DEBUG_LIBS ON) 14 | set(Boost_USE_DEBUG_RUNTIME ON) 15 | endif() 16 | 17 | set(CMAKE_AUTOMOC ON) 18 | set(CMAKE_AUTOUIC ON) 19 | set(CMAKE_AUTORCC ON) 20 | 21 | find_package(Boost 1.56.0 REQUIRED COMPONENTS regex date_time system thread) 22 | find_package(Qt5Widgets) 23 | find_package(Qt5Core) 24 | find_package(Qt5Gui) 25 | 26 | include_directories(${CMAKE_SOURCE_DIR}/src) 27 | include_directories(${Boost_INCLUDE_DIRS}) 28 | 29 | file(GLOB_RECURSE client_sources *.cpp *h *.qrc) 30 | add_executable(client WIN32 ${client_sources}) 31 | 32 | target_link_libraries(client core ${Boost_LIBRARIES} Qt5::Widgets Qt5::Core Qt5::Gui) -------------------------------------------------------------------------------- /src/client/README.md: -------------------------------------------------------------------------------- 1 | # 客户端 2 | 3 | Qt5 + Boost.Asio -------------------------------------------------------------------------------- /src/client/core/Book.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | Book::xint Book::getAmount() const { 7 | return amount; 8 | } 9 | 10 | Book& Book::setAmount(const xint &value) { 11 | amount = value; 12 | return *this; 13 | } 14 | 15 | Book::xstring Book::getPosition() const { 16 | return position; 17 | } 18 | 19 | Book& Book::setPosition(const xstring &value) { 20 | position = value; 21 | return *this; 22 | } 23 | 24 | Book& Book::setFromPtree(const ptree &pt) { 25 | BookBrief::setFromPtree(pt); 26 | setAmount(pt.get("amount", 0)); 27 | setPosition(pt.get("position", "")); 28 | return *this; 29 | } 30 | 31 | Book Book::fromPtree(const ptree &pt) { 32 | Book book; 33 | book.setFromPtree(pt); 34 | return std::move(book); 35 | } 36 | 37 | Book& Book::updateFromPtree(const ptree &pt) { 38 | BookBrief::updateFromPtree(pt); 39 | auto amount = pt.get_optional("amount"); 40 | auto position = pt.get_optional("position"); 41 | if (amount) 42 | setAmount(*amount); 43 | if (position) 44 | setPosition(*position); 45 | return *this; 46 | } 47 | 48 | Book& Book::cleanCover() { 49 | BookBrief::cleanCover(); 50 | return *this; 51 | } 52 | 53 | const Book& Book::unknown() { 54 | static Book book; 55 | static bool init {false}; 56 | if (!init) { 57 | book.setTitle("Unknown"); 58 | init = true; 59 | } 60 | return book; 61 | } 62 | -------------------------------------------------------------------------------- /src/client/core/Book.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class Book : public BookBrief { 11 | public: 12 | xint getAmount() const; 13 | Book& setAmount(const xint &value); 14 | 15 | xstring getPosition() const; 16 | Book& setPosition(const xstring &value); 17 | 18 | Book& setFromPtree(const ptree &pt); 19 | static Book fromPtree(const ptree &pt); 20 | 21 | Book& updateFromPtree(const ptree &pt); 22 | 23 | Book& cleanCover(); 24 | 25 | static const Book& unknown(); 26 | 27 | private: 28 | xint amount {}; 29 | xstring position {}; 30 | }; 31 | -------------------------------------------------------------------------------- /src/client/core/BookBrief.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | BookBrief::xint BookBrief::getBookid() const { 7 | return bookid; 8 | } 9 | 10 | BookBrief& BookBrief::setBookid(const xint &value) { 11 | bookid = value; 12 | return *this; 13 | } 14 | 15 | BookBrief::xstring BookBrief::getTitle() const { 16 | return title; 17 | } 18 | 19 | BookBrief& BookBrief::setTitle(const xstring &value) { 20 | title = value; 21 | return *this; 22 | } 23 | 24 | BookBrief::xstring BookBrief::getAuthor() const { 25 | return author; 26 | } 27 | 28 | BookBrief& BookBrief::setAuthor(const xstring &value) { 29 | author = value; 30 | return *this; 31 | } 32 | 33 | BookBrief::xstring BookBrief::getISBN() const { 34 | return ISBN; 35 | } 36 | 37 | BookBrief& BookBrief::setISBN(const xstring &value) { 38 | ISBN = value; 39 | return *this; 40 | } 41 | 42 | BookBrief::xstring BookBrief::getPublisher() const { 43 | return publisher; 44 | } 45 | 46 | BookBrief& BookBrief::setPublisher(const xstring &value) { 47 | publisher = value; 48 | return *this; 49 | } 50 | 51 | BookBrief::xstring BookBrief::getIntroduction() const { 52 | return introduction; 53 | } 54 | 55 | BookBrief& BookBrief::setIntroduction(const xstring &value) { 56 | introduction = value; 57 | return *this; 58 | } 59 | 60 | BookBrief::xint BookBrief::getPriority() const { 61 | return priority; 62 | } 63 | 64 | BookBrief& BookBrief::setPriority(const xint &value) { 65 | priority = value; 66 | return *this; 67 | } 68 | 69 | BookBrief::xint BookBrief::getStarCount() const { 70 | return starCount; 71 | } 72 | 73 | BookBrief& BookBrief::setStarCount(const xint &value) { 74 | starCount = value; 75 | return *this; 76 | } 77 | 78 | BookBrief::xll BookBrief::getMaxKeepTime() const { 79 | return maxKeepTime; 80 | } 81 | 82 | BookBrief& BookBrief::setMaxKeepTime(const xll &value) { 83 | maxKeepTime = value; 84 | return *this; 85 | } 86 | 87 | Resource BookBrief::getCover() const { 88 | return cover; 89 | } 90 | 91 | BookBrief& BookBrief::setCover(const Resource &cover) { 92 | this->cover = cover; 93 | return *this; 94 | } 95 | 96 | BookBrief& BookBrief::cleanCover() { 97 | cover.clean(); 98 | return *this; 99 | } 100 | 101 | BookBrief& BookBrief::setFromPtree(const ptree &pt) { 102 | setBookid(pt.get("bookid", 0)); 103 | setTitle(pt.get("title", "")); 104 | setAuthor(pt.get("author", "")); 105 | setISBN(pt.get("ISBN", "")); 106 | setPublisher(pt.get("publisher", "")); 107 | setIntroduction(pt.get("introduction", "")); 108 | setPriority(pt.get("priority", 0)); 109 | setMaxKeepTime(pt.get("maxKeepTime", 0)); 110 | setStarCount(pt.get("starCount", 0)); 111 | return *this; 112 | } 113 | 114 | BookBrief BookBrief::fromPtree(const ptree &pt) { 115 | BookBrief book; 116 | book.setFromPtree(pt); 117 | return std::move(book); 118 | } 119 | 120 | BookBrief& BookBrief::updateFromPtree(const ptree &pt) { 121 | auto bookid = pt.get_optional("bookid"); 122 | auto title = pt.get_optional("title"); 123 | auto author = pt.get_optional("author"); 124 | auto ISBN = pt.get_optional("ISBN"); 125 | auto publisher = pt.get_optional("publisher"); 126 | auto introduction = pt.get_optional("introduction"); 127 | auto priority = pt.get_optional("priority"); 128 | auto maxKeepTime = pt.get_optional("maxKeepTime"); 129 | auto starCount = pt.get_optional("starCount"); 130 | 131 | if (bookid) 132 | setBookid(*bookid); 133 | if (title) 134 | setTitle(*title); 135 | if (author) 136 | setAuthor(*author); 137 | if (ISBN) 138 | setISBN(*ISBN); 139 | if (publisher) 140 | setPublisher(*publisher); 141 | if (introduction) 142 | setIntroduction(*introduction); 143 | if (priority) 144 | setPriority(*priority); 145 | if (maxKeepTime) 146 | setMaxKeepTime(*maxKeepTime); 147 | if (starCount) 148 | setStarCount(*starCount); 149 | return *this; 150 | } 151 | 152 | const BookBrief& BookBrief::unknown() { 153 | static BookBrief book; 154 | static bool init {false}; 155 | if (!init) { 156 | book.setTitle("Unknown"); 157 | init = true; 158 | } 159 | return book; 160 | } 161 | -------------------------------------------------------------------------------- /src/client/core/BookBrief.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | class BookBrief { 10 | public: 11 | typedef X::xll xll; 12 | typedef X::xint xint; 13 | typedef X::ptree ptree; 14 | typedef X::xstring xstring; 15 | 16 | virtual ~BookBrief() = default; 17 | 18 | xint getBookid() const; 19 | BookBrief& setBookid(const xint &value); 20 | 21 | xstring getTitle() const; 22 | BookBrief& setTitle(const xstring &value); 23 | 24 | xstring getAuthor() const; 25 | BookBrief& setAuthor(const xstring &value); 26 | 27 | xstring getISBN() const; 28 | BookBrief& setISBN(const xstring &value); 29 | 30 | xstring getPublisher() const; 31 | BookBrief& setPublisher(const xstring &value); 32 | 33 | xstring getIntroduction() const; 34 | BookBrief& setIntroduction(const xstring &value); 35 | 36 | xint getPriority() const; 37 | BookBrief& setPriority(const xint &value); 38 | 39 | xint getStarCount() const; 40 | BookBrief& setStarCount(const xint &value); 41 | 42 | xll getMaxKeepTime() const; 43 | BookBrief& setMaxKeepTime(const xll &value); 44 | 45 | Resource getCover() const; 46 | BookBrief& setCover(const Resource &cover); 47 | 48 | virtual BookBrief& cleanCover(); 49 | 50 | virtual BookBrief& setFromPtree(const ptree &pt); 51 | static BookBrief fromPtree(const ptree &pt); 52 | 53 | BookBrief& updateFromPtree(const ptree &pt); 54 | 55 | static const BookBrief& unknown(); 56 | 57 | private: 58 | xint bookid {}; 59 | xstring title {}; 60 | xstring author {}; 61 | xstring ISBN {}; 62 | xstring publisher {}; 63 | xstring introduction {}; 64 | xint priority {}; 65 | xll maxKeepTime {}; 66 | xint starCount {}; 67 | Resource cover {}; 68 | }; 69 | -------------------------------------------------------------------------------- /src/client/core/BorrowRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | BorrowRecord::~BorrowRecord() { } 7 | 8 | BorrowRecord::xint BorrowRecord::getBookid() const { 9 | return bookid; 10 | } 11 | 12 | BorrowRecord& BorrowRecord::setBookid(const xint &value) { 13 | bookid = value; 14 | return *this; 15 | } 16 | 17 | BorrowRecord::xll BorrowRecord::getBeginTime() const { 18 | return beginTime; 19 | } 20 | 21 | BorrowRecord& BorrowRecord::setBeginTime(const xll &value) { 22 | beginTime = value; 23 | return *this; 24 | } 25 | 26 | BorrowRecord::xll BorrowRecord::getEndTime() const { 27 | return endTime; 28 | } 29 | 30 | BorrowRecord& BorrowRecord::setEndTime(const xll &value) { 31 | endTime = value; 32 | return *this; 33 | } 34 | 35 | BorrowRecord::xll BorrowRecord::getReturnTime() const { 36 | return returnTime; 37 | } 38 | 39 | BorrowRecord& BorrowRecord::setReturnTime(const xll &value) { 40 | returnTime = value; 41 | return *this; 42 | } 43 | 44 | BorrowRecord& BorrowRecord::setTime(const xll &beginTime, const xll &endTime, const xll &returnTime) { 45 | setBeginTime(beginTime); 46 | setEndTime(endTime); 47 | setReturnTime(returnTime); 48 | return *this; 49 | } 50 | 51 | BorrowRecord& BorrowRecord::setFromPtree(const ptree &pt) { 52 | setBookid(pt.get("bookid", 0)); 53 | setTime(pt.get("beginTime", 0), pt.get("endTime", 0), pt.get("returnTime", 0)); 54 | return *this; 55 | } 56 | 57 | BorrowRecord BorrowRecord::fromPtree(const ptree &pt) { 58 | BorrowRecord record; 59 | record.setFromPtree(pt); 60 | return std::move(record); 61 | } 62 | 63 | bool BorrowRecord::operator < (const BorrowRecord &t) const { 64 | return returnTime == t.returnTime ? (endTime == t.endTime ? (beginTime == t.beginTime ? bookid < t.bookid : beginTime < t.beginTime) : endTime < t.endTime) : returnTime < t.returnTime; 65 | } 66 | -------------------------------------------------------------------------------- /src/client/core/BorrowRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class BorrowRecord { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | virtual ~BorrowRecord(); 16 | 17 | xint getBookid() const; 18 | BorrowRecord& setBookid(const xint &value); 19 | 20 | xll getBeginTime() const; 21 | BorrowRecord& setBeginTime(const xll &value); 22 | 23 | xll getEndTime() const; 24 | BorrowRecord& setEndTime(const xll &value); 25 | 26 | xll getReturnTime() const; 27 | BorrowRecord& setReturnTime(const xll &value); 28 | 29 | BorrowRecord& setTime(const xll &beginTime, const xll &endTime, const xll &returnTime); 30 | 31 | virtual BorrowRecord& setFromPtree(const ptree &pt); 32 | static BorrowRecord fromPtree(const ptree &pt); 33 | 34 | bool operator < (const BorrowRecord &t) const; 35 | 36 | private: 37 | xint bookid {}; 38 | xll beginTime {}; 39 | xll endTime {}; 40 | xll returnTime {}; 41 | }; 42 | -------------------------------------------------------------------------------- /src/client/core/BrowseRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | BrowseRecord::xint BrowseRecord::getBookid() const { 7 | return bookid; 8 | } 9 | 10 | BrowseRecord& BrowseRecord::setBookid(const xint &value) { 11 | bookid = value; 12 | return *this; 13 | } 14 | 15 | BrowseRecord::xll BrowseRecord::getTime() const { 16 | return time; 17 | } 18 | 19 | BrowseRecord& BrowseRecord::setTime(const xll &value) { 20 | time = value; 21 | return *this; 22 | } 23 | 24 | BrowseRecord& BrowseRecord::setFromPtree(const ptree &pt) { 25 | setBookid(pt.get("bookid", 0)); 26 | setTime(pt.get("time", 0)); 27 | return *this; 28 | } 29 | 30 | BrowseRecord BrowseRecord::fromPtree(const ptree &pt) { 31 | BrowseRecord record; 32 | record.setFromPtree(pt); 33 | return std::move(record); 34 | } 35 | 36 | bool BrowseRecord::operator < (const BrowseRecord &a) const { 37 | return time == a.time ? bookid < a.bookid : time < a.time; 38 | } 39 | -------------------------------------------------------------------------------- /src/client/core/BrowseRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class BrowseRecord { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | xint getBookid() const; 16 | BrowseRecord& setBookid(const xint &value); 17 | 18 | xll getTime() const; 19 | BrowseRecord& setTime(const xll &value); 20 | 21 | virtual BrowseRecord& setFromPtree(const ptree &pt); 22 | static BrowseRecord fromPtree(const ptree &pt); 23 | 24 | bool operator < (const BrowseRecord &a) const; 25 | 26 | private: 27 | xint bookid {}; 28 | xll time {}; 29 | }; 30 | -------------------------------------------------------------------------------- /src/client/core/KeepRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | KeepRecord::~KeepRecord() { } 7 | 8 | KeepRecord::xint KeepRecord::getBookid() const { 9 | return bookid; 10 | } 11 | 12 | KeepRecord& KeepRecord::setBookid(const xint &value) { 13 | bookid = value; 14 | return *this; 15 | } 16 | 17 | KeepRecord::xll KeepRecord::getBeginTime() const { 18 | return beginTime; 19 | } 20 | 21 | KeepRecord& KeepRecord::setBeginTime(const xll &value) { 22 | beginTime = value; 23 | return *this; 24 | } 25 | 26 | KeepRecord::xll KeepRecord::getEndTime() const { 27 | return endTime; 28 | } 29 | 30 | KeepRecord& KeepRecord::setEndTime(const xll &value) { 31 | endTime = value; 32 | return *this; 33 | } 34 | 35 | KeepRecord& KeepRecord::setTime(const xll &beginTime, const xll &endTime) { 36 | setBeginTime(beginTime); 37 | setEndTime(endTime); 38 | return *this; 39 | } 40 | 41 | KeepRecord& KeepRecord::setFromPtree(const ptree &pt) { 42 | setBookid(pt.get("bookid", 0)); 43 | setTime(pt.get("beginTime", 0), pt.get("endTime", 0)); 44 | return *this; 45 | } 46 | 47 | KeepRecord KeepRecord::fromPtree(const ptree &pt) { 48 | KeepRecord record; 49 | record.setFromPtree(pt); 50 | return std::move(record); 51 | } 52 | 53 | bool KeepRecord::operator < (const KeepRecord &t) const { 54 | return endTime == t.endTime ? (beginTime == t.beginTime ? bookid < t.bookid : beginTime < t.beginTime) : endTime < t.endTime; 55 | } 56 | -------------------------------------------------------------------------------- /src/client/core/KeepRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class KeepRecord { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | virtual ~KeepRecord(); 16 | 17 | xint getBookid() const; 18 | KeepRecord& setBookid(const xint &value); 19 | 20 | xll getBeginTime() const; 21 | KeepRecord& setBeginTime(const xll &value); 22 | 23 | xll getEndTime() const; 24 | KeepRecord& setEndTime(const xll &value); 25 | 26 | KeepRecord& setTime(const xll &beginTime, const xll &endTime); 27 | 28 | virtual KeepRecord& setFromPtree(const ptree &pt); 29 | static KeepRecord fromPtree(const ptree &pt); 30 | 31 | bool operator < (const KeepRecord &t) const; 32 | 33 | private: 34 | xint bookid {}; 35 | xll beginTime {}; 36 | xll endTime {}; 37 | }; 38 | -------------------------------------------------------------------------------- /src/client/core/LoginRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | LoginRecord::xstring LoginRecord::getIp() const { 7 | return ip; 8 | } 9 | 10 | LoginRecord& LoginRecord::setIp(const xstring &value) { 11 | ip = value; 12 | return *this; 13 | } 14 | 15 | LoginRecord::xll LoginRecord::getTime() const { 16 | return time; 17 | } 18 | 19 | LoginRecord& LoginRecord::setTime(const xll &value) { 20 | time = value; 21 | return *this; 22 | } 23 | 24 | LoginRecord& LoginRecord::setFromPtree(const ptree &pt) { 25 | setIp(pt.get("ip", "")); 26 | setTime(pt.get("time", 0)); 27 | return *this; 28 | } 29 | 30 | LoginRecord LoginRecord::fromPtree(const ptree &pt) { 31 | LoginRecord record; 32 | record.setFromPtree(pt); 33 | return std::move(record); 34 | } 35 | 36 | bool LoginRecord::operator < (const LoginRecord &b) const { 37 | return time == b.time ? ip < b.ip : time < b.time; 38 | } 39 | -------------------------------------------------------------------------------- /src/client/core/LoginRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class LoginRecord { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | xstring getIp() const; 16 | LoginRecord& setIp(const xstring &value); 17 | 18 | xll getTime() const; 19 | LoginRecord& setTime(const xll &value); 20 | 21 | virtual LoginRecord& setFromPtree(const ptree &pt); 22 | static LoginRecord fromPtree(const ptree &pt); 23 | 24 | bool operator < (const LoginRecord &b) const; 25 | 26 | private: 27 | xstring ip {}; 28 | xll time {}; 29 | }; 30 | -------------------------------------------------------------------------------- /src/client/core/StarRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | StarRecord::~StarRecord() { } 7 | 8 | StarRecord::xint StarRecord::getBookid() const { 9 | return bookid; 10 | } 11 | 12 | StarRecord& StarRecord::setBookid(const xint &value) { 13 | bookid = value; 14 | return *this; 15 | } 16 | 17 | StarRecord::xll StarRecord::getTime() const { 18 | return time; 19 | } 20 | 21 | StarRecord& StarRecord::setTime(const xll &value) { 22 | time = value; 23 | return *this; 24 | } 25 | 26 | StarRecord& StarRecord::setFromPtree(const ptree &pt) { 27 | setBookid(pt.get("bookid", 0)); 28 | setTime(pt.get("time", 0)); 29 | return *this; 30 | } 31 | 32 | StarRecord StarRecord::fromPtree(const ptree &pt) { 33 | StarRecord record; 34 | record.setFromPtree(pt); 35 | return record; 36 | } 37 | 38 | bool StarRecord::operator < (const StarRecord &b) const { 39 | return time == b.time ? bookid < b.bookid : time < b.time; 40 | } -------------------------------------------------------------------------------- /src/client/core/StarRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class StarRecord { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | virtual ~StarRecord(); 16 | 17 | xint getBookid() const; 18 | StarRecord& setBookid(const xint &value); 19 | 20 | xll getTime() const; 21 | StarRecord& setTime(const xll &value); 22 | 23 | virtual StarRecord& setFromPtree(const ptree &pt); 24 | static StarRecord fromPtree(const ptree &pt); 25 | 26 | bool operator < (const StarRecord &b) const; 27 | 28 | private: 29 | xint bookid {}; 30 | xll time {}; 31 | }; 32 | -------------------------------------------------------------------------------- /src/client/core/User.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | User::xint User::getUserid() const { 7 | return userid; 8 | } 9 | 10 | User& User::setUserid(const xint &value) { 11 | userid = value; 12 | return *this; 13 | } 14 | 15 | User::xstring User::getUsername() const { 16 | return username; 17 | } 18 | 19 | User& User::setUsername(const xstring &value) { 20 | username = value; 21 | return *this; 22 | } 23 | 24 | User::xstring User::getNickname() const { 25 | return nickname; 26 | } 27 | 28 | User& User::setNickname(const xstring &value) { 29 | nickname = value; 30 | return *this; 31 | } 32 | 33 | User::xstring User::getEmail() const { 34 | return email; 35 | } 36 | 37 | User& User::setEmail(const xstring &value) { 38 | email = value; 39 | return *this; 40 | } 41 | 42 | User::xint User::getPriority() const { 43 | return priority; 44 | } 45 | 46 | User& User::setPriority(const xint &value) { 47 | priority = value; 48 | return *this; 49 | } 50 | 51 | User& User::setFromPtree(const ptree &pt) { 52 | setUserid(pt.get("userid", 0)); 53 | setUsername(pt.get("username", "")); 54 | setNickname(pt.get("nickname", "")); 55 | setEmail(pt.get("email", "")); 56 | setPriority(pt.get("priority", X::USER)); 57 | return *this; 58 | } 59 | 60 | User User::fromPtree(const ptree &pt) { 61 | User user; 62 | user.setFromPtree(pt); 63 | return std::move(user); 64 | } 65 | -------------------------------------------------------------------------------- /src/client/core/User.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class User { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | 15 | virtual ~User() = default; 16 | 17 | xint getUserid() const; 18 | User& setUserid(const xint &value); 19 | 20 | xstring getUsername() const; 21 | User& setUsername(const xstring &value); 22 | 23 | xstring getNickname() const; 24 | User& setNickname(const xstring &value); 25 | 26 | xstring getEmail() const; 27 | User& setEmail(const xstring &value); 28 | 29 | xint getPriority() const; 30 | User& setPriority(const xint &value); 31 | 32 | virtual User& setFromPtree(const ptree &pt); 33 | static User fromPtree(const ptree &pt); 34 | 35 | private: 36 | xint userid {}; 37 | xstring username {}; 38 | xstring nickname {}; 39 | xstring email {}; 40 | xint priority {}; 41 | }; 42 | -------------------------------------------------------------------------------- /src/client/dialog/DialogBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | class DialogBook : public QDialog { 19 | Q_OBJECT 20 | 21 | public: 22 | DialogBook(UserManager &userManager, BookManager &bookManager, const X::xint &bookid, QWidget *parent = Q_NULLPTR); 23 | void setBook(const Book &book); 24 | 25 | signals: 26 | void signalModify(); 27 | 28 | public slots: 29 | void slotStarBegin(); 30 | void slotStarEnd(const X::ErrorCode &ec); 31 | void slotBorrowBegin(); 32 | void slotBorrowEnd(const X::ErrorCode &ec); 33 | void slotModify(); 34 | void slotMore(); 35 | 36 | private: 37 | void setUI(); 38 | void setConnection(); 39 | 40 | private: 41 | QString strStar; 42 | QString strUnStar; 43 | QString strBorrow; 44 | QString strBorrowed; 45 | 46 | UserManager &userManager; 47 | BookManager &bookManager; 48 | Book const * bookPtr; 49 | X::xll keepTime {}; 50 | 51 | QLabel *lblCover; 52 | QLabel *lblTitle; 53 | QLabel *lblAuthor; 54 | QLabel *lblIntroduction; 55 | QLabel *lblPosition; 56 | QLabel *lblMaxKeepTime; 57 | 58 | QLabel *lblBookid; 59 | QLabel *lblPublisher; 60 | QLabel *lblISBN; 61 | QLabel *lblAmount; 62 | 63 | QPushButton *btnStar; 64 | QPushButton *btnBorrow; 65 | QPushButton *btnModify; 66 | QPushButton *btnMore; 67 | }; 68 | -------------------------------------------------------------------------------- /src/client/dialog/DialogChooseTime.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | class DialogChooseTime : public QDialog { 15 | Q_OBJECT 16 | 17 | public: 18 | DialogChooseTime(const X::xll &maxKeepTime, QWidget *parent = Q_NULLPTR); 19 | X::xll getKeepTime() const; 20 | 21 | public slots: 22 | void slotGo(); 23 | void slotChanged(int); 24 | 25 | private: 26 | void setUI(); 27 | void setConnection(); 28 | 29 | private: 30 | QLabel *lblBeginTime; 31 | QLabel *lblEndTime; 32 | QLabel *lblMaxKeepTime; 33 | QLabel *lblWarning; 34 | QLabel *lblError; 35 | QLabel *lblDay; 36 | QLabel *lblHour; 37 | QLabel *lblMinute; 38 | 39 | QSpinBox *spinDay; 40 | QSpinBox *spinHour; 41 | QSpinBox *spinMinute; 42 | 43 | QDialogButtonBox *btns; 44 | 45 | X::xll beginTime; 46 | X::xll keepTime; 47 | X::xll maxKeepTime; 48 | }; 49 | -------------------------------------------------------------------------------- /src/client/dialog/DialogLogin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | DialogLogin::DialogLogin(UserManager &userManager, QWidget *parent) : 12 | QDialog(parent) { 13 | 14 | w = new WidgetLogin(userManager, this); 15 | 16 | setUI(); 17 | setConnection(); 18 | } 19 | 20 | void DialogLogin::setUI() { 21 | move(QApplication::desktop()->screen()->rect().center() - rect().center()); 22 | 23 | setWindowFlags(Qt::FramelessWindowHint); 24 | 25 | auto layout = new QHBoxLayout(this); 26 | layout->addWidget(w); 27 | 28 | setLayout(layout); 29 | 30 | setAttribute(Qt::WA_TranslucentBackground); 31 | QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; 32 | shadow->setBlurRadius(9.0); 33 | shadow->setColor(QColor(0, 0, 0, 160)); 34 | shadow->setOffset(0, 0); 35 | setGraphicsEffect(shadow); 36 | } 37 | 38 | void DialogLogin::setConnection() { 39 | connect(w, &WidgetLogin::signalAccept, this, &QDialog::accept); 40 | } 41 | -------------------------------------------------------------------------------- /src/client/dialog/DialogLogin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class DialogLogin : public QDialog { 11 | Q_OBJECT 12 | 13 | public: 14 | DialogLogin(UserManager &userManager, QWidget *parent = Q_NULLPTR); 15 | 16 | private: 17 | void setUI(); 18 | void setConnection(); 19 | 20 | private: 21 | WidgetLogin *w; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /src/client/dialog/DialogModifyBook.cpp: -------------------------------------------------------------------------------- 1 | // copyright 2018 xalanq, chang-ran 2 | // license: lgpl v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | WidgetModifyBook::WidgetModifyBook(UserManager &userManager, BookManager &bookManager, const Book &book, QWidget *parent) : 12 | WidgetSetBook(userManager, bookManager, parent), 13 | book(book) { 14 | 15 | setUI(); 16 | setConnection(); 17 | } 18 | 19 | void WidgetModifyBook::slotModify() { 20 | WidgetSetBook::getData(); 21 | bookManager.updateBook(pt, cover, std::bind(&WidgetModifyBook::slotModifyEnd, this, std::placeholders::_1)); 22 | } 23 | 24 | void WidgetModifyBook::slotModifyEnd(const X::ErrorCode &ec) { 25 | if (ec == X::NoError) { 26 | QMessageBox::information(this, tr("Modify result"), tr("Successfully!")); 27 | emit signalModify(); 28 | } else { 29 | lblMessage->setText(X::what(ec)); 30 | lblMessage->show(); 31 | } 32 | } 33 | 34 | void WidgetModifyBook::setUI() { 35 | lblBookid->show(); 36 | editBookid->show(); 37 | editBookid->setText(QString::number(book.getBookid())); 38 | editBookid->setDisabled(true); 39 | editTitle->setText(QString::fromStdString(book.getTitle())); 40 | editAuthor->setText(QString::fromStdString(book.getAuthor())); 41 | editISBN->setText(QString::fromStdString(book.getISBN())); 42 | editPublisher->setText(QString::fromStdString(book.getPublisher())); 43 | editIntroduction->document()->setPlainText(QString::fromStdString(book.getIntroduction())); 44 | editIntroduction->document()->setModified(false); 45 | auto priority = book.getPriority(); 46 | for (int i = 0; i < int(priorityInfo.size()); ++i) 47 | if (priorityInfo[i] == priority) { 48 | cbboxPriority->setCurrentIndex(i); 49 | break; 50 | } 51 | editPosition->setText(QString::fromStdString(book.getPosition())); 52 | editAmount->setText(QString::number(book.getAmount())); 53 | 54 | auto maxKeepTime = book.getMaxKeepTime(); 55 | X::xll d = maxKeepTime / 60 / 60 / 24; 56 | X::xll h = maxKeepTime / 60 / 60 - d * 24; 57 | X::xll m = maxKeepTime / 60 - d * 24 * 60 - h * 60; 58 | spinDay->setValue(d); 59 | spinHour->setValue(h); 60 | spinMinute->setValue(m); 61 | beforeKeepTime = maxKeepTime; 62 | 63 | btnAdd->setText(tr("Modif&y")); 64 | 65 | if (book.getCover().getSize()) { 66 | QPixmap p(QSize(114, 160)); 67 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 68 | lblCover->setPixmap(p.scaled(QSize(114, 160))); 69 | } 70 | } 71 | 72 | void WidgetModifyBook::setConnection() { 73 | connect(btnAdd, &QPushButton::clicked, this, &WidgetModifyBook::slotModify); 74 | } 75 | 76 | DialogModifyBook::DialogModifyBook(UserManager &userManager, BookManager &bookManager, const Book &book, QWidget *parent) : 77 | QDialog(parent) { 78 | 79 | w = new WidgetModifyBook(userManager, bookManager, book, this); 80 | 81 | setUI(); 82 | setConnection(); 83 | } 84 | 85 | void DialogModifyBook::setUI() { 86 | setWindowTitle(tr("Modify Book")); 87 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); 88 | 89 | auto layout = new QVBoxLayout; 90 | layout->addWidget(w); 91 | 92 | setLayout(layout); 93 | } 94 | 95 | void DialogModifyBook::setConnection() { 96 | connect(w, SIGNAL(signalModify()), this, SIGNAL(signalModify())); 97 | } 98 | -------------------------------------------------------------------------------- /src/client/dialog/DialogModifyBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | class WidgetModifyBook : public WidgetSetBook { 12 | Q_OBJECT 13 | 14 | public: 15 | WidgetModifyBook(UserManager &userManager, BookManager &bookManager, const Book &book, QWidget *parent = Q_NULLPTR); 16 | 17 | signals: 18 | void signalModify(); 19 | 20 | public slots: 21 | void slotModify(); 22 | void slotModifyEnd(const X::ErrorCode &ec); 23 | 24 | private: 25 | void setUI(); 26 | void setConnection(); 27 | 28 | private: 29 | const Book &book; 30 | }; 31 | 32 | class DialogModifyBook : public QDialog { 33 | Q_OBJECT 34 | 35 | public: 36 | DialogModifyBook(UserManager &userManager, BookManager &bookManager, const Book &book, QWidget *parent = Q_NULLPTR); 37 | 38 | signals: 39 | void signalModify(); 40 | 41 | private: 42 | void setUI(); 43 | void setConnection(); 44 | 45 | private: 46 | WidgetModifyBook *w; 47 | }; 48 | -------------------------------------------------------------------------------- /src/client/dialog/DialogModifyUser.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | class DialogModifyUser : public QDialog { 16 | Q_OBJECT 17 | 18 | public: 19 | DialogModifyUser(UserManager &userManager, QWidget *parent); 20 | 21 | public slots: 22 | void slotModifyBegin(); 23 | void slotModifyEnd(const X::ErrorCode &ec); 24 | 25 | private: 26 | void setUI(); 27 | void setConnection(); 28 | 29 | private: 30 | UserManager &userManager; 31 | 32 | QLabel *lblUserid; 33 | QLabel *lblPriority; 34 | 35 | QLineEdit *editNickname; 36 | QLineEdit *editEmail; 37 | QLineEdit *editPasswordOld; 38 | QLineEdit *editPasswordNew; 39 | QLineEdit *editPasswordNewConfirm; 40 | 41 | QLabel *labelMessage; 42 | 43 | QDialogButtonBox *btns; 44 | }; 45 | -------------------------------------------------------------------------------- /src/client/dialog/DialogRefresh.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | DialogRefresh::DialogRefresh(QWidget *parent) : 11 | QDialog(parent) { 12 | 13 | lblRefresh = new QLabel(this); 14 | 15 | setUI(); 16 | } 17 | 18 | void DialogRefresh::setUI() { 19 | setWindowTitle(tr("Refreshing")); 20 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); 21 | 22 | lblRefresh->setText(tr("Refreshing...\nPlease wait a while...")); 23 | lblRefresh->setAlignment(Qt::AlignCenter); 24 | lblRefresh->setMargin(50); 25 | 26 | auto layout = new QVBoxLayout; 27 | 28 | layout->addWidget(lblRefresh); 29 | setLayout(layout); 30 | 31 | adjustSize(); 32 | move(QApplication::desktop()->screen()->rect().center() - rect().center()); 33 | } 34 | -------------------------------------------------------------------------------- /src/client/dialog/DialogRefresh.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | class DialogRefresh : public QDialog { 10 | Q_OBJECT 11 | 12 | public: 13 | DialogRefresh(QWidget *parent = Q_NULLPTR); 14 | 15 | private: 16 | void setUI(); 17 | 18 | private: 19 | QLabel *lblRefresh; 20 | }; 21 | -------------------------------------------------------------------------------- /src/client/dialog/DialogSignUp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | class DialogSignUp : public QDialog { 15 | Q_OBJECT 16 | 17 | public: 18 | DialogSignUp(QWidget *parent); 19 | 20 | public slots: 21 | void slotSignUpBegin(); 22 | void slotSignUpEnd(const X::ErrorCode &ec); 23 | 24 | private: 25 | void setUI(); 26 | void setConnection(); 27 | 28 | private: 29 | QLineEdit *editUsername; 30 | QLineEdit *editNickname; 31 | QLineEdit *editPassword; 32 | QLineEdit *editPasswordConfirm; 33 | QLineEdit *editEmail; 34 | 35 | QLabel *lblMessage; 36 | 37 | QDialogButtonBox *btns; 38 | }; 39 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBorrowRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | ListWidgetItemBorrowRecord::ListWidgetItemBorrowRecord(const BookBrief &book, const BorrowRecord &record) : 11 | book(book), 12 | record(record) { 13 | 14 | setUI(); 15 | } 16 | 17 | const BookBrief& ListWidgetItemBorrowRecord::getBook() const { 18 | return book; 19 | } 20 | 21 | void ListWidgetItemBorrowRecord::update(const BookBrief &book, const BorrowRecord &record) { 22 | this->book = book; 23 | this->record = record; 24 | setUI(); 25 | } 26 | 27 | void ListWidgetItemBorrowRecord::setUI() { 28 | QPixmap p(QSize(148, 208)); 29 | if (book.getCover().getSize()) 30 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 31 | else 32 | p.fill(Qt::black); 33 | 34 | QIcon icon; 35 | icon.addPixmap(p.scaled(QSize(148, 208))); 36 | setIcon(icon); 37 | 38 | auto beginTime = record.getBeginTime(); 39 | auto endTime = record.getEndTime(); 40 | auto returnTime = record.getReturnTime(); 41 | setText(QObject::tr("Bookid: ") + 42 | QString::number(book.getBookid()) + 43 | QObject::tr("\nTitle: ") + 44 | QString::fromStdString(book.getTitle()) + 45 | QObject::tr("\nbeginTime: ") + 46 | QString::fromStdString(X::time_to_str(beginTime)) + 47 | QObject::tr("\nendTime: ") + 48 | QString::fromStdString(X::time_to_str(endTime)) + 49 | QObject::tr("\nreturnTime: ") + 50 | (returnTime ? QString::fromStdString(X::time_to_str(returnTime)) : QObject::tr("not returned yet"))); 51 | } 52 | 53 | ListWidgetBorrowRecord::ListWidgetBorrowRecord(QWidget *parent) : 54 | QListWidget(parent) { 55 | 56 | setUI(); 57 | } 58 | 59 | void ListWidgetBorrowRecord::add(const BookBrief &book, const BorrowRecord &record, int row) { 60 | insertItem(row, new ListWidgetItemBorrowRecord(book, record)); 61 | } 62 | 63 | void ListWidgetBorrowRecord::update(const BookBrief &book, const BorrowRecord &record, int row) { 64 | auto it = dynamic_cast (item(row)); 65 | if (it) 66 | it->update(book, record); 67 | } 68 | 69 | void ListWidgetBorrowRecord::setUI() { 70 | setMovement(QListView::Static); 71 | setIconSize(QSize(148, 208)); 72 | setUniformItemSizes(true); 73 | setResizeMode(QListWidget::Adjust); 74 | } -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBorrowRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class ListWidgetItemBorrowRecord : public QListWidgetItem { 13 | public: 14 | ListWidgetItemBorrowRecord(const BookBrief &book, const BorrowRecord &record); 15 | const BookBrief& getBook() const; 16 | void update(const BookBrief &book, const BorrowRecord &record); 17 | 18 | private: 19 | void setUI(); 20 | 21 | private: 22 | BookBrief book; 23 | BorrowRecord record; 24 | }; 25 | 26 | class ListWidgetBorrowRecord : public QListWidget { 27 | Q_OBJECT 28 | 29 | public: 30 | ListWidgetBorrowRecord(QWidget *parent = Q_NULLPTR); 31 | void add(const BookBrief &book, const BorrowRecord &record, int row = 0); 32 | void update(const BookBrief &book, const BorrowRecord &record, int row); 33 | 34 | private: 35 | void setUI(); 36 | }; 37 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBrowseBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | ListWidgetItemBook::ListWidgetItemBook(const BookBrief &book, bool star) : 16 | book(book), 17 | star(star) { 18 | 19 | setUI(); 20 | } 21 | 22 | const BookBrief& ListWidgetItemBook::getBook() const { 23 | return book; 24 | } 25 | 26 | void ListWidgetItemBook::update(const BookBrief &book, bool star) { 27 | this->book = book; 28 | this->star = star; 29 | setUI(); 30 | } 31 | 32 | void ListWidgetItemBook::setUI() { 33 | QPixmap p(QSize(148, 208)); 34 | if (book.getCover().getSize()) 35 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 36 | else 37 | p.fill(Qt::black); 38 | 39 | QString str = QString::fromWCharArray(L"❤ "); 40 | X::xint cnt = book.getStarCount(); 41 | if (cnt > 10000) 42 | str += QString::number(cnt / 1000) + QObject::tr("k"); 43 | else 44 | str += QString::number(cnt); 45 | 46 | QFont font; 47 | font.setFamily("Microsoft YaHei"); 48 | font.setPointSize(9); 49 | 50 | p = p.scaled(QSize(148, 208)); 51 | 52 | QPainter painter(&p); 53 | painter.setRenderHint(QPainter::Antialiasing); 54 | painter.fillRect(0, 7, 50, 23, QColor(0, 0, 0, 50)); 55 | if (star) { 56 | painter.setBrush(Qt::red); 57 | painter.setPen(Qt::red); 58 | } else { 59 | painter.setBrush(Qt::white); 60 | painter.setPen(Qt::white); 61 | } 62 | painter.setFont(font); 63 | painter.drawText(QPoint(5, 25), str); 64 | 65 | QIcon icon; 66 | icon.addPixmap(p); 67 | 68 | setIcon(icon); 69 | setText(QString::fromStdString(book.getTitle() + '\n' + book.getAuthor())); 70 | } 71 | 72 | ListWidgetBrowseBook::ListWidgetBrowseBook(UserManager &userManager, BookManager &bookManager, QWidget *parent) : 73 | QListWidget(parent), 74 | userManager(userManager), 75 | bookManager(bookManager) { 76 | 77 | setUI(); 78 | setConnection(); 79 | } 80 | 81 | void ListWidgetBrowseBook::add(const BookBrief &book, bool star, int row) { 82 | insertItem(row, new ListWidgetItemBook(book, star)); 83 | } 84 | 85 | void ListWidgetBrowseBook::update(const BookBrief &book, bool star, int row) { 86 | auto it = dynamic_cast (item(row)); 87 | if (it) 88 | it->update(book, star); 89 | } 90 | 91 | void ListWidgetBrowseBook::updateStar(const X::xint &bookid, bool star) { 92 | auto it = books.find(bookid); 93 | if (it != books.end()) 94 | bookManager.getBookBrief(bookid, std::bind(&ListWidgetBrowseBook::update, this, std::placeholders::_1, star, it->second)); 95 | } 96 | 97 | void ListWidgetBrowseBook::slotGetBookList(const X::ErrorCode &ec, const X::ptree &pt, bool reverse) { 98 | if (ec != X::NoError) 99 | return; 100 | auto arr = pt.get_child("bookid"); 101 | if (reverse) 102 | arr.reverse(); 103 | books.clear(); 104 | std::vector l; 105 | for (auto &&child : arr) { 106 | auto bookid = child.second.get_value(); 107 | l.push_back(bookid); 108 | } 109 | int tot = int(l.size()); 110 | for (int i = 0; i < tot; ++i) 111 | add(BookBrief::unknown(), 0); 112 | for (int i = 0; i < tot; ++i) { 113 | auto bookid = l[i]; 114 | auto pos = tot - 1 - i; 115 | bookManager.getBookBrief(bookid, std::bind(&ListWidgetBrowseBook::update, this, std::placeholders::_1, userManager.isStaredBook(bookid), pos)); 116 | books[bookid] = pos; 117 | } 118 | emit signalReady(); 119 | } 120 | 121 | void ListWidgetBrowseBook::slotItemClicked(QListWidgetItem *item) { 122 | auto x = dynamic_cast (item); 123 | auto dialog = new DialogBook(userManager, bookManager, x->getBook().getBookid(), this); 124 | connect(dialog, SIGNAL(signalModify()), this, SIGNAL(signalModify())); 125 | dialog->show(); 126 | } 127 | 128 | void ListWidgetBrowseBook::setUI() { 129 | setViewMode(QListView::IconMode); 130 | setMovement(QListView::Static); 131 | setIconSize(QSize(148, 208)); 132 | setUniformItemSizes(true); 133 | setResizeMode(QListWidget::Adjust); 134 | setStyleSheet("QListWidget::Item{padding-bottom:10px;}"); 135 | } 136 | 137 | void ListWidgetBrowseBook::setConnection() { 138 | connect(this, 139 | &ListWidgetBrowseBook::itemDoubleClicked, 140 | this, 141 | &ListWidgetBrowseBook::slotItemClicked); 142 | } 143 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBrowseBook.h: -------------------------------------------------------------------------------- 1 | // copyright 2018 xalanq, chang-ran 2 | // license: lgpl v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class ListWidgetItemBook : public QListWidgetItem { 18 | public: 19 | ListWidgetItemBook(const BookBrief &book, bool star); 20 | const BookBrief& getBook() const; 21 | void update(const BookBrief &book, bool star); 22 | 23 | private: 24 | void setUI(); 25 | 26 | private: 27 | BookBrief book; 28 | bool star; 29 | }; 30 | 31 | class ListWidgetBrowseBook : public QListWidget { 32 | Q_OBJECT 33 | 34 | public: 35 | ListWidgetBrowseBook(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 36 | void add(const BookBrief &book, bool star, int row = 0); 37 | void update(const BookBrief &book, bool star, int row); 38 | void updateStar(const X::xint &bookid, bool star); 39 | 40 | signals: 41 | void signalReady(); 42 | void signalModify(); 43 | 44 | public slots: 45 | void slotGetBookList(const X::ErrorCode &ec, const X::ptree &pt, bool reverse = false); 46 | void slotItemClicked(QListWidgetItem *item); 47 | 48 | private: 49 | void setUI(); 50 | void setConnection(); 51 | 52 | private: 53 | UserManager &userManager; 54 | BookManager &bookManager; 55 | 56 | std::map books; 57 | }; 58 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBrowseRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | ListWidgetItemBrowseRecord::ListWidgetItemBrowseRecord(const BookBrief &book, const BrowseRecord &record) : 10 | book(book), 11 | record(record) { 12 | 13 | setUI(); 14 | } 15 | 16 | const BookBrief& ListWidgetItemBrowseRecord::getBook() const { 17 | return book; 18 | } 19 | 20 | void ListWidgetItemBrowseRecord::update(const BookBrief &book, const BrowseRecord &record) { 21 | this->book = book; 22 | this->record = record; 23 | setUI(); 24 | } 25 | 26 | void ListWidgetItemBrowseRecord::setUI() { 27 | QPixmap p(QSize(148, 208)); 28 | if (book.getCover().getSize()) 29 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 30 | else 31 | p.fill(Qt::black); 32 | 33 | QIcon icon; 34 | icon.addPixmap(p.scaled(QSize(148, 208))); 35 | setIcon(icon); 36 | 37 | setText(QObject::tr("Title: ") + 38 | QString::fromStdString(book.getTitle()) + 39 | QObject::tr("\nTime: ") + 40 | QString::fromStdString(X::time_to_str(record.getTime()))); 41 | } 42 | 43 | ListWidgetBrowseRecord::ListWidgetBrowseRecord(QWidget *parent) : 44 | QListWidget(parent) { 45 | 46 | setUI(); 47 | } 48 | 49 | void ListWidgetBrowseRecord::add(const BookBrief &book, const BrowseRecord &record, int row) { 50 | insertItem(row, new ListWidgetItemBrowseRecord(book, record)); 51 | } 52 | 53 | void ListWidgetBrowseRecord::update(const BookBrief &book, const BrowseRecord &record, int row) { 54 | auto it = dynamic_cast (item(row)); 55 | if (it) 56 | it->update(book, record); 57 | } 58 | 59 | void ListWidgetBrowseRecord::setUI() { 60 | setMovement(QListView::Static); 61 | setIconSize(QSize(148, 208)); 62 | setUniformItemSizes(true); 63 | setResizeMode(QListWidget::Adjust); 64 | } 65 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetBrowseRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class ListWidgetItemBrowseRecord : public QListWidgetItem { 13 | public: 14 | ListWidgetItemBrowseRecord(const BookBrief &book, const BrowseRecord &record); 15 | const BookBrief& getBook() const; 16 | void update(const BookBrief &book, const BrowseRecord &record); 17 | 18 | private: 19 | void setUI(); 20 | 21 | private: 22 | BookBrief book; 23 | BrowseRecord record; 24 | }; 25 | 26 | class ListWidgetBrowseRecord : public QListWidget { 27 | Q_OBJECT 28 | 29 | public: 30 | ListWidgetBrowseRecord(QWidget *parent = Q_NULLPTR); 31 | void add(const BookBrief &book, const BrowseRecord &record, int row = 0); 32 | void update(const BookBrief &book, const BrowseRecord &record, int row); 33 | 34 | private: 35 | void setUI(); 36 | }; 37 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetKeepRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | ListWidgetItemKeepRecord::ListWidgetItemKeepRecord(const BookBrief &book, const KeepRecord &record) : 10 | book(book), 11 | record(record) { 12 | 13 | setUI(); 14 | } 15 | 16 | const BookBrief& ListWidgetItemKeepRecord::getBook() const { 17 | return book; 18 | } 19 | 20 | void ListWidgetItemKeepRecord::update(const BookBrief &book, const KeepRecord &record) { 21 | this->book = book; 22 | this->record = record; 23 | setUI(); 24 | } 25 | 26 | void ListWidgetItemKeepRecord::setUI() { 27 | QPixmap p(QSize(148, 208)); 28 | if (book.getCover().getSize()) 29 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 30 | else 31 | p.fill(Qt::black); 32 | 33 | QIcon icon; 34 | icon.addPixmap(p.scaled(QSize(148, 208))); 35 | setIcon(icon); 36 | 37 | setText(QObject::tr("Bookid: ") + 38 | QString::number(book.getBookid()) + 39 | QObject::tr("\nTitle: ") + 40 | QString::fromStdString(book.getTitle()) + 41 | QObject::tr("\nbeginTime: ") + 42 | QString::fromStdString(X::time_to_str(record.getBeginTime())) + 43 | QObject::tr("\nendTime: ") + 44 | QString::fromStdString(X::time_to_str(record.getEndTime()))); 45 | } 46 | 47 | ListWidgetKeepRecord::ListWidgetKeepRecord(QWidget *parent) : 48 | QListWidget(parent) { 49 | 50 | setUI(); 51 | } 52 | 53 | void ListWidgetKeepRecord::add(const BookBrief &book, const KeepRecord &record, int row) { 54 | insertItem(row, new ListWidgetItemKeepRecord(book, record)); 55 | } 56 | 57 | void ListWidgetKeepRecord::update(const BookBrief &book, const KeepRecord &record, int row) { 58 | auto it = dynamic_cast (item(row)); 59 | if (it) 60 | it->update(book, record); 61 | } 62 | 63 | void ListWidgetKeepRecord::setUI() { 64 | setMovement(QListView::Static); 65 | setIconSize(QSize(148, 208)); 66 | setUniformItemSizes(true); 67 | setResizeMode(QListWidget::Adjust); 68 | } 69 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetKeepRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class ListWidgetItemKeepRecord : public QListWidgetItem { 13 | public: 14 | ListWidgetItemKeepRecord(const BookBrief &book, const KeepRecord &record); 15 | const BookBrief& getBook() const; 16 | void update(const BookBrief &book, const KeepRecord &record); 17 | 18 | private: 19 | void setUI(); 20 | 21 | private: 22 | BookBrief book; 23 | KeepRecord record; 24 | }; 25 | 26 | class ListWidgetKeepRecord : public QListWidget { 27 | Q_OBJECT 28 | 29 | public: 30 | ListWidgetKeepRecord(QWidget *parent = Q_NULLPTR); 31 | void add(const BookBrief &book, const KeepRecord &record, int row = 0); 32 | void update(const BookBrief &book, const KeepRecord &record, int row); 33 | 34 | private: 35 | void setUI(); 36 | }; 37 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetLoginRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ListWidgetLoginRecord::ListWidgetLoginRecord(QWidget *parent) : 8 | QListWidget(parent) { 9 | 10 | setUI(); 11 | } 12 | 13 | void ListWidgetLoginRecord::add(const LoginRecord &record) { 14 | auto item = new QListWidgetItem( 15 | tr("IP Address: ") + 16 | record.getIp().c_str() + 17 | tr(", \tTime: ") + 18 | QString::fromStdString(X::time_to_str(record.getTime())) 19 | ); 20 | addItem(item); 21 | } 22 | 23 | void ListWidgetLoginRecord::setUI() { 24 | } 25 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetLoginRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class ListWidgetLoginRecord : public QListWidget { 12 | Q_OBJECT 13 | 14 | public: 15 | ListWidgetLoginRecord(QWidget *parent = Q_NULLPTR); 16 | void add(const LoginRecord &record); 17 | 18 | private: 19 | void setUI(); 20 | }; 21 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetStarRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | ListWidgetItemStarRecord::ListWidgetItemStarRecord(const BookBrief &book, const StarRecord &record) : 10 | book(book), 11 | record(record) { 12 | 13 | setUI(); 14 | } 15 | 16 | const BookBrief& ListWidgetItemStarRecord::getBook() const { 17 | return book; 18 | } 19 | 20 | void ListWidgetItemStarRecord::update(const BookBrief &book, const StarRecord &record) { 21 | this->book = book; 22 | this->record = record; 23 | setUI(); 24 | } 25 | 26 | void ListWidgetItemStarRecord::setUI() { 27 | QPixmap p(QSize(148, 208)); 28 | if (book.getCover().getSize()) 29 | p.loadFromData((uchar *)book.getCover().getData(), book.getCover().getSize()); 30 | else 31 | p.fill(Qt::black); 32 | 33 | QIcon icon; 34 | icon.addPixmap(p.scaled(QSize(148, 208))); 35 | setIcon(icon); 36 | 37 | setText(QObject::tr("Title: ") + 38 | QString::fromStdString(book.getTitle()) + 39 | QObject::tr("\nTime: ") + 40 | QString::fromStdString(X::time_to_str(record.getTime()))); 41 | } 42 | 43 | ListWidgetStarRecord::ListWidgetStarRecord(QWidget *parent) : 44 | QListWidget(parent) { 45 | 46 | setUI(); 47 | } 48 | 49 | void ListWidgetStarRecord::add(const BookBrief &book, const StarRecord &record, int row) { 50 | insertItem(row, new ListWidgetItemStarRecord(book, record)); 51 | } 52 | 53 | void ListWidgetStarRecord::update(const BookBrief &book, const StarRecord &record, int row) { 54 | auto it = dynamic_cast (item(row)); 55 | if (it) 56 | it->update(book, record); 57 | } 58 | 59 | void ListWidgetStarRecord::setUI() { 60 | setMovement(QListView::Static); 61 | setIconSize(QSize(148, 208)); 62 | setUniformItemSizes(true); 63 | setResizeMode(QListWidget::Adjust); 64 | } 65 | -------------------------------------------------------------------------------- /src/client/listwidget/ListWidgetStarRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class ListWidgetItemStarRecord : public QListWidgetItem { 13 | public: 14 | ListWidgetItemStarRecord(const BookBrief &book, const StarRecord &record); 15 | const BookBrief& getBook() const; 16 | void update(const BookBrief &book, const StarRecord &record); 17 | 18 | private: 19 | void setUI(); 20 | 21 | private: 22 | BookBrief book; 23 | StarRecord record; 24 | }; 25 | 26 | class ListWidgetStarRecord : public QListWidget { 27 | Q_OBJECT 28 | 29 | public: 30 | ListWidgetStarRecord(QWidget *parent = Q_NULLPTR); 31 | void add(const BookBrief &book, const StarRecord &record, int row = 0); 32 | void update(const BookBrief &book, const StarRecord &record, int row); 33 | 34 | private: 35 | void setUI(); 36 | }; 37 | -------------------------------------------------------------------------------- /src/client/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) { 14 | // QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 15 | QCoreApplication::setOrganizationName(QString::fromStdString(X::ORG_NAME)); 16 | QCoreApplication::setApplicationName(QString::fromStdString(X::APP_NAME)); 17 | 18 | QApplication a(argc, argv); 19 | 20 | auto language = QSettings().value("Setting/Language", "default").toString(); 21 | if (language == "default") 22 | language = QLocale::system().name(); 23 | 24 | auto *translator = new QTranslator; 25 | translator->load(":/i18n/" + language); 26 | QApplication::installTranslator(translator); 27 | auto *translatorQt = new QTranslator; 28 | translatorQt->load(":/i18n/qt_" + language); 29 | QApplication::installTranslator(translatorQt); 30 | 31 | MainWindow w; 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /src/client/mainwindow/MainWindow.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | MainWindow::MainWindow(QWidget *parent) : 14 | QMainWindow(parent) { 15 | 16 | widgetMain = nullptr; 17 | userManager = nullptr; 18 | bookManager = nullptr; 19 | go(); 20 | } 21 | 22 | MainWindow::~MainWindow() { 23 | saveSetting(); 24 | } 25 | 26 | void MainWindow::go() { 27 | if (widgetMain) 28 | delete widgetMain; 29 | if (userManager) { 30 | userManager->refresh(); 31 | delete userManager; 32 | } 33 | if (bookManager) { 34 | bookManager->refresh(); 35 | delete bookManager; 36 | } 37 | 38 | userManager = new UserManager; 39 | bookManager = new BookManager(*userManager); 40 | 41 | login(); 42 | 43 | widgetMain = new WidgetMain(*userManager, *bookManager, this); 44 | 45 | setUI(); 46 | setConnection(); 47 | loadSetting(); 48 | show(); 49 | } 50 | 51 | void MainWindow::loadSetting() { 52 | QSettings setting; 53 | setting.beginGroup("MainWindow"); 54 | 55 | restoreState(setting.value("State").toByteArray()); 56 | 57 | setting.endGroup(); 58 | } 59 | 60 | void MainWindow::saveSetting() { 61 | QSettings setting; 62 | setting.beginGroup("MainWindow"); 63 | 64 | setting.setValue("State", saveState()); 65 | 66 | setting.endGroup(); 67 | widgetMain->saveSetting(); 68 | } 69 | 70 | void MainWindow::logout() { 71 | auto thread = new ThreadLogout(userManager->getToken(), this); 72 | connect(thread, &ThreadLogout::done, this, [this] { 73 | hide(); 74 | go(); 75 | }); 76 | connect(thread, &ThreadLogout::finished, thread, &QObject::deleteLater); 77 | thread->start(); 78 | } 79 | 80 | void MainWindow::setUI() { 81 | setCentralWidget(widgetMain); 82 | setMinimumSize(QSize(1280, 760)); 83 | adjustSize(); 84 | move(QApplication::desktop()->screen()->rect().center() - rect().center()); 85 | 86 | menuBar()->setVisible(false); 87 | } 88 | 89 | void MainWindow::setConnection() { 90 | connect(widgetMain, &WidgetMain::signalLogout, this, &MainWindow::logout); 91 | } 92 | 93 | void MainWindow::login() { 94 | DialogLogin dialog(*userManager); 95 | if (dialog.exec() != QDialog::Accepted) 96 | exit(0); 97 | if (userManager->getToken() == 0) 98 | exit(0); 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/client/mainwindow/MainWindow.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class MainWindow : public QMainWindow { 14 | Q_OBJECT 15 | 16 | public: 17 | MainWindow(QWidget *parent = Q_NULLPTR); 18 | ~MainWindow(); 19 | void go(); 20 | void loadSetting(); 21 | void saveSetting(); 22 | 23 | public slots: 24 | void logout(); 25 | 26 | private: 27 | void setUI(); 28 | void setConnection(); 29 | void login(); 30 | 31 | private: 32 | UserManager *userManager; 33 | BookManager *bookManager; 34 | WidgetMain *widgetMain; 35 | }; 36 | -------------------------------------------------------------------------------- /src/client/manager/BookManager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | class BookManager : public QObject { 19 | Q_OBJECT 20 | 21 | public: 22 | typedef X::xll xll; 23 | typedef X::xint xint; 24 | typedef X::ptree ptree; 25 | typedef X::xstring xstring; 26 | typedef X::ErrorCode ErrorCode; 27 | typedef X::ActionCode ActionCode; 28 | 29 | BookManager(UserManager &userManager); 30 | 31 | bool hasBook(const xint &bookid) const; 32 | bool hasBookBrief(const xint &bookid) const; 33 | 34 | const Book& getBook(const xint &bookid) const; 35 | void getBook(const xint &bookid, std::function f); 36 | 37 | const BookBrief& getBookBrief(const xint &bookid) const; 38 | void getBookBrief(const xint &bookid, std::function f); 39 | 40 | void updateStar(const xint &bookid, bool star); 41 | 42 | void addBook(const ptree &pt, const Resource &cover, std::function f); 43 | 44 | void updateBook(const ptree &pt, const Resource &cover, std::function f); 45 | 46 | void installBrowseEvent(std::function f); 47 | void clearBrowseEvent(); 48 | 49 | void refresh(); 50 | 51 | public slots: 52 | void slotGetBook(const ErrorCode &ec, const ptree &pt, const xint &bookid, const Resource &cover); 53 | void slotGetBookBrief(const ErrorCode &ec, const ptree &pt, const xint &bookid, const Resource &cover); 54 | void slotAddBook(ErrorCode ec, std::function f); 55 | void slotUpdateBook(ErrorCode ec, const ptree &pt, const Resource &cover, std::function f); 56 | 57 | private: 58 | void _getBook(const xint &bookid); 59 | void _getBookBrief(const xint &bookid); 60 | 61 | void popThread(); 62 | 63 | void emitBrowseEvents(xint bookid); 64 | 65 | private: 66 | UserManager &userManager; 67 | std::map mapBook; 68 | std::map mapBookBrief; 69 | std::queue queueGetBook; 70 | std::queue queueGetBookBrief; 71 | std::map>> mapGetBookFunction; 72 | std::map>> mapGetBookBriefFunction; 73 | int threadCounts {}; 74 | int threadLimit {}; 75 | std::vector> browseEvents {}; 76 | }; -------------------------------------------------------------------------------- /src/client/manager/UserManager.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | bool UserManager::isAdminister() const { 7 | return user.getPriority() >= X::ADMINISTER; 8 | } 9 | 10 | UserManager::xll UserManager::getToken() const { 11 | return token; 12 | } 13 | 14 | User& UserManager::getUser() { 15 | return user; 16 | } 17 | 18 | void UserManager::setToken(const xll &token) { 19 | this->token = token; 20 | } 21 | 22 | void UserManager::setUser(const ptree &pt) { 23 | user.setFromPtree(pt); 24 | } 25 | 26 | void UserManager::starBook(const xint &bookid) { 27 | starBooks.insert(bookid); 28 | emitStarEvents(bookid, true); 29 | } 30 | 31 | void UserManager::unStarBook(const xint &bookid) { 32 | starBooks.erase(bookid); 33 | emitStarEvents(bookid, false); 34 | } 35 | 36 | bool UserManager::isStaredBook(const xint &bookid) { 37 | return starBooks.find(bookid) != starBooks.end(); 38 | } 39 | 40 | void UserManager::clearStar() { 41 | starBooks.clear(); 42 | starEvents.clear(); 43 | } 44 | 45 | void UserManager::installStarEvent(std::function f) { 46 | starEvents.push_back(f); 47 | } 48 | 49 | void UserManager::clearStarEvent() { 50 | starEvents.clear(); 51 | } 52 | 53 | void UserManager::borrowBook(const xint &bookid, const xll &beginTime, const xll &endTime) { 54 | borrowBooks.insert(bookid); 55 | emitBorrowEvents(bookid, beginTime, endTime); 56 | } 57 | 58 | bool UserManager::isBorrowedBook(const xint &bookid) { 59 | return borrowBooks.find(bookid) != borrowBooks.end(); 60 | } 61 | 62 | void UserManager::clearBorrowBook() { 63 | borrowBooks.clear(); 64 | } 65 | 66 | void UserManager::installBorrowEvent(std::function f) { 67 | borrowEvents.push_back(f); 68 | } 69 | 70 | void UserManager::clearBorrowEvent() { 71 | borrowEvents.clear(); 72 | } 73 | 74 | void UserManager::refresh() { 75 | starBooks.clear(); 76 | starEvents.clear(); 77 | borrowBooks.clear(); 78 | borrowEvents.clear(); 79 | } 80 | 81 | void UserManager::emitStarEvents(xint bookid, bool star) { 82 | for (auto f: starEvents) 83 | f(bookid, star); 84 | } 85 | 86 | void UserManager::emitBorrowEvents(xint bookid, xll beginTime, xll endTime) { 87 | for (auto f: borrowEvents) 88 | f(bookid, beginTime, endTime); 89 | } 90 | -------------------------------------------------------------------------------- /src/client/manager/UserManager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | class UserManager { 14 | public: 15 | typedef X::xll xll; 16 | typedef X::xint xint; 17 | typedef X::ptree ptree; 18 | typedef X::xstring xstring; 19 | 20 | bool isAdminister() const; 21 | 22 | xll getToken() const; 23 | void setToken(const xll &token); 24 | 25 | User& getUser(); 26 | void setUser(const ptree &pt); 27 | 28 | void starBook(const xint &bookid); 29 | void unStarBook(const xint &bookid); 30 | bool isStaredBook(const xint &bookid); 31 | void clearStar(); 32 | void installStarEvent(std::function f); 33 | void clearStarEvent(); 34 | 35 | void borrowBook(const xint &bookid, const xll &beginTime, const xll &endTime); 36 | bool isBorrowedBook(const xint &bookid); 37 | void clearBorrowBook(); 38 | void installBorrowEvent(std::function f); 39 | void clearBorrowEvent(); 40 | 41 | void refresh(); 42 | 43 | private: 44 | void emitStarEvents(xint bookid, bool star); 45 | void emitBorrowEvents(xint bookid, xll beginTime, xll endTime); 46 | 47 | private: 48 | xll token {}; 49 | User user {}; 50 | std::set starBooks {}; 51 | std::set borrowBooks {}; 52 | std::vector> starEvents {}; 53 | std::vector> borrowEvents {}; 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /src/client/object/GetRecords.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | // I hate Qt that it can't template with Q_OBJECT 8 | 9 | #define WTF(CLASS_NAME, TYPE_NAME, ACTION_CODE, ARRAY_NAME) \ 10 | CLASS_NAME::CLASS_NAME(const X::xll &token, BookManager &bookManager, const X::xint &number, const X::xint &begin, QObject *parent) : \ 11 | QObject(parent), \ 12 | token(token), \ 13 | bookManager(bookManager), \ 14 | number(number), \ 15 | begin(begin) { \ 16 | } \ 17 | void CLASS_NAME::start() { \ 18 | auto thread = new ThreadGetRecord(token, ACTION_CODE, number, begin, this); \ 19 | connect(thread, &ThreadGetRecord::done, this, &CLASS_NAME::slotEnd); \ 20 | connect(thread, &ThreadGetRecord::finished, thread, &QObject::deleteLater); \ 21 | thread->start(); \ 22 | } \ 23 | void CLASS_NAME::slotEnd(const X::ErrorCode &ec, const X::ptree &pt) { \ 24 | if (ec != X::NoError) \ 25 | return; \ 26 | auto arr = pt.get_child(ARRAY_NAME); \ 27 | recordList.clear(); \ 28 | for (auto &&child : arr) { \ 29 | auto record = TYPE_NAME::fromPtree(child.second); \ 30 | recordList.push_back(record); \ 31 | } \ 32 | emit done(recordList); \ 33 | deleteLater(); \ 34 | } 35 | 36 | WTF(GetBrowseRecords, BrowseRecord, X::GetBrowseRecord, "browseRecord") 37 | WTF(GetKeepRecords, KeepRecord, X::GetKeepRecord, "keepRecord") 38 | WTF(GetBorrowRecords, BorrowRecord, X::GetBorrowRecord, "borrowRecord") 39 | WTF(GetStarRecords, StarRecord, X::GetStarRecord, "starRecord") -------------------------------------------------------------------------------- /src/client/object/GetRecords.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class GetBrowseRecords : public QObject { 18 | Q_OBJECT 19 | 20 | public: 21 | GetBrowseRecords(const X::xll &token, BookManager &bookManager, const X::xint &number, const X::xint &begin, QObject *parent = Q_NULLPTR); 22 | void start(); 23 | 24 | signals: 25 | void done(const std::vector &records); 26 | 27 | public slots: 28 | void slotEnd(const X::ErrorCode &ec, const X::ptree &pt); 29 | 30 | private: 31 | X::xll token; 32 | BookManager &bookManager; 33 | X::xint number; 34 | X::xint begin; 35 | std::vector recordList; 36 | }; 37 | 38 | class GetKeepRecords : public QObject { 39 | Q_OBJECT 40 | 41 | public: 42 | GetKeepRecords(const X::xll &token, BookManager &bookManager, const X::xint &number, const X::xint &begin, QObject *parent = Q_NULLPTR); 43 | void start(); 44 | 45 | signals: 46 | void done(const std::vector &records); 47 | 48 | public slots: 49 | void slotEnd(const X::ErrorCode &ec, const X::ptree &pt); 50 | 51 | private: 52 | X::xll token; 53 | BookManager &bookManager; 54 | X::xint number; 55 | X::xint begin; 56 | std::vector recordList; 57 | }; 58 | 59 | class GetBorrowRecords : public QObject { 60 | Q_OBJECT 61 | 62 | public: 63 | GetBorrowRecords(const X::xll &token, BookManager &bookManager, const X::xint &number, const X::xint &begin, QObject *parent = Q_NULLPTR); 64 | void start(); 65 | 66 | signals: 67 | void done(const std::vector &records); 68 | 69 | public slots: 70 | void slotEnd(const X::ErrorCode &ec, const X::ptree &pt); 71 | 72 | private: 73 | X::xll token; 74 | BookManager &bookManager; 75 | X::xint number; 76 | X::xint begin; 77 | std::vector recordList; 78 | }; 79 | 80 | class GetStarRecords : public QObject { 81 | Q_OBJECT 82 | 83 | public: 84 | GetStarRecords(const X::xll &token, BookManager &bookManager, const X::xint &number, const X::xint &begin, QObject *parent = Q_NULLPTR); 85 | void start(); 86 | 87 | signals: 88 | void done(const std::vector &records); 89 | 90 | public slots: 91 | void slotEnd(const X::ErrorCode &ec, const X::ptree &pt); 92 | 93 | private: 94 | X::xll token; 95 | BookManager &bookManager; 96 | X::xint number; 97 | X::xint begin; 98 | std::vector recordList; 99 | }; 100 | -------------------------------------------------------------------------------- /src/client/page/PageAbout.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | PageAbout::PageAbout(QWidget *parent) : 11 | QWidget(parent) { 12 | 13 | label = new QLabel(this); 14 | btnUpdate = new QPushButton(this); 15 | 16 | setUI(); 17 | setConnection(); 18 | } 19 | 20 | void PageAbout::setUI() { 21 | auto lblLayout = new QHBoxLayout; 22 | auto btnLayout = new QHBoxLayout; 23 | auto layout = new QVBoxLayout; 24 | 25 | lblLayout->addStretch(); 26 | lblLayout->addWidget(label); 27 | lblLayout->addStretch(); 28 | 29 | btnLayout->addStretch(); 30 | btnLayout->addWidget(btnUpdate); 31 | btnLayout->addStretch(); 32 | 33 | layout->addStretch(); 34 | layout->addLayout(lblLayout); 35 | layout->addLayout(btnLayout); 36 | layout->addStretch(); 37 | 38 | setLayout(layout); 39 | layout->setContentsMargins(0, 0, 0, 0); 40 | } 41 | 42 | void PageAbout::setConnection() { 43 | label->setText(tr( 44 | "

%1 v%2

\ 45 |

Copyright © 2018 by %3.

\ 46 |

Email: %4

\ 47 |

Website: %6

\ 48 |

Github: %8

\ 49 |

Lisence: LGPL v3.0

"). 50 | arg(QString::fromStdString(X::APP_NAME).toHtmlEscaped()). 51 | arg(QString::fromStdString(X::VERSION).toHtmlEscaped()). 52 | arg(QString::fromStdString(X::AUTHOR[0] + ", " + X::AUTHOR[1]).toHtmlEscaped()). 53 | arg(QString::fromStdString(X::EMAIL[0] + ", " + X::EMAIL[1]).toHtmlEscaped()). 54 | arg(QString::fromStdString(X::WEBSITE).toHtmlEscaped()). 55 | arg(QString::fromStdString(X::WEBSITE).toHtmlEscaped()). 56 | arg(QString::fromStdString(X::GITHUB).toHtmlEscaped()). 57 | arg(QString::fromStdString(X::GITHUB).toHtmlEscaped()) 58 | ); 59 | label->setOpenExternalLinks(true); 60 | label->setWordWrap(true); 61 | label->setFixedWidth(600); 62 | 63 | btnUpdate->setText(tr("Check update")); 64 | } 65 | -------------------------------------------------------------------------------- /src/client/page/PageAbout.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class PageAbout : public QWidget { 11 | Q_OBJECT 12 | 13 | public: 14 | PageAbout(QWidget *parent = Q_NULLPTR); 15 | 16 | private: 17 | void setUI(); 18 | void setConnection(); 19 | 20 | private: 21 | QLabel *label; 22 | QPushButton *btnUpdate; 23 | }; 24 | -------------------------------------------------------------------------------- /src/client/page/PageAddBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | PageAddBook::PageAddBook(UserManager &userManager, BookManager &bookManager, QWidget *parent) : 10 | WidgetSetBook(userManager, bookManager, parent) { 11 | 12 | setUI(); 13 | setConnection(); 14 | } 15 | 16 | void PageAddBook::slotAdd() { 17 | WidgetSetBook::getData(); 18 | bookManager.addBook(pt, cover, std::bind(&PageAddBook::slotAddEnd, this, std::placeholders::_1)); 19 | } 20 | 21 | void PageAddBook::slotAddEnd(const X::ErrorCode &ec) { 22 | if (ec == X::NoError) { 23 | QMessageBox::information(this, tr("Add result"), tr("Successfully!")); 24 | } else { 25 | lblMessage->setText(X::what(ec)); 26 | lblMessage->show(); 27 | } 28 | } 29 | 30 | void PageAddBook::setUI() { 31 | lblBookid->hide(); 32 | editBookid->setDisabled(true); 33 | editBookid->hide(); 34 | } 35 | 36 | void PageAddBook::setConnection() { 37 | connect(btnAdd, &QPushButton::clicked, this, &PageAddBook::slotAdd); 38 | } 39 | -------------------------------------------------------------------------------- /src/client/page/PageAddBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class PageAddBook : public WidgetSetBook { 13 | Q_OBJECT 14 | 15 | public: 16 | PageAddBook(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 17 | 18 | public slots: 19 | void slotAdd(); 20 | void slotAddEnd(const X::ErrorCode &ec); 21 | 22 | private: 23 | void setUI(); 24 | void setConnection(); 25 | }; 26 | -------------------------------------------------------------------------------- /src/client/page/PageAdminister.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | class PageAdminister : public QWidget { 17 | Q_OBJECT 18 | 19 | public: 20 | PageAdminister(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 21 | 22 | signals: 23 | void signalReady(); 24 | 25 | public slots: 26 | void slotReturn(); 27 | void slotSetPriority(); 28 | 29 | private: 30 | void setUI(); 31 | void setConnection(); 32 | 33 | private: 34 | UserManager &userManager; 35 | BookManager &bookManager; 36 | 37 | QLabel *lblReturnUserid; 38 | QLabel *lblReturnBookid; 39 | QLineEdit *editReturnUserid; 40 | QLineEdit *editReturnBookid; 41 | QPushButton *btnReturn; 42 | 43 | QLabel *lblSetPriorityUserid; 44 | QLabel *lblSetPriority; 45 | QLineEdit *editSetPriorityUserid; 46 | QComboBox *cbboxSetPriority; 47 | QPushButton *btnSetPriority; 48 | 49 | QStringList priorityList; 50 | std::vector priorityInfo; 51 | }; 52 | -------------------------------------------------------------------------------- /src/client/page/PageBrowse.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | PageBrowse::PageBrowse(UserManager &userManager, BookManager &bookManager, QWidget *parent) : 13 | QWidget(parent), 14 | userManager(userManager), 15 | bookManager(bookManager) { 16 | 17 | tabWidget = new QTabWidget(this); 18 | 19 | listWidgetNewBook = new ListWidgetBrowseBook(userManager, bookManager, this); 20 | 21 | listWidgetTopBook = new ListWidgetBrowseBook(userManager, bookManager, this); 22 | 23 | widgetSearchBook = new WidgetSearchBook(this); 24 | listWidgetSearchBook = new ListWidgetBrowseBook(userManager, bookManager, this); 25 | 26 | setUI(); 27 | setConnection(); 28 | } 29 | 30 | void PageBrowse::updateStar(const X::xint &bookid, bool star) { 31 | listWidgetNewBook->updateStar(bookid, star); 32 | listWidgetTopBook->updateStar(bookid, star); 33 | listWidgetSearchBook->updateStar(bookid, star); 34 | } 35 | 36 | void PageBrowse::slotReady() { 37 | if (++readyCount == 2) { 38 | emit signalReady(); 39 | } 40 | } 41 | 42 | void PageBrowse::refresh() { 43 | readyCount = 0; 44 | { 45 | listWidgetNewBook->clear(); 46 | auto thread = new ThreadGetNewBookList(userManager.getToken(), 15, this); 47 | connect(thread, &ThreadGetNewBookList::done, listWidgetNewBook, std::bind(&ListWidgetBrowseBook::slotGetBookList, listWidgetNewBook, std::placeholders::_1, std::placeholders::_2, false)); 48 | connect(thread, &ThreadGetNewBookList::finished, thread, &QObject::deleteLater); 49 | thread->start(); 50 | } 51 | { 52 | listWidgetTopBook->clear(); 53 | auto thread = new ThreadGetTopBookList(userManager.getToken(), 15, this); 54 | connect(thread, &ThreadGetTopBookList::done, listWidgetTopBook, std::bind(&ListWidgetBrowseBook::slotGetBookList, listWidgetTopBook, std::placeholders::_1, std::placeholders::_2, true)); 55 | connect(thread, &ThreadGetTopBookList::finished, thread, &QObject::deleteLater); 56 | thread->start(); 57 | } 58 | } 59 | 60 | void PageBrowse::slotSearch(const X::ptree &pt) { 61 | listWidgetSearchBook->clear(); 62 | auto thread = new ThreadGetSearchBookList(userManager.getToken(), pt, this); 63 | connect(thread, &ThreadGetSearchBookList::done, listWidgetSearchBook, std::bind(&ListWidgetBrowseBook::slotGetBookList, listWidgetSearchBook, std::placeholders::_1, std::placeholders::_2, false)); 64 | connect(thread, &ThreadGetSearchBookList::finished, thread, &QObject::deleteLater); 65 | thread->start(); 66 | } 67 | 68 | void PageBrowse::setUI() { 69 | listWidgetNewBook->setFrameStyle(QFrame::NoFrame); 70 | listWidgetTopBook->setFrameStyle(QFrame::NoFrame); 71 | listWidgetSearchBook->setFrameStyle(QFrame::NoFrame); 72 | 73 | tabWidget->addTab(listWidgetNewBook, tr("Newest Book")); 74 | tabWidget->addTab(listWidgetTopBook, tr("Top Book")); 75 | 76 | QWidget *w = new QWidget(this); 77 | auto layoutSearch = new QVBoxLayout; 78 | layoutSearch->addWidget(widgetSearchBook); 79 | layoutSearch->addWidget(listWidgetSearchBook); 80 | w->setLayout(layoutSearch); 81 | w->setContentsMargins(0, 0, 0, 0); 82 | 83 | tabWidget->addTab(w, tr("Search Book")); 84 | tabWidget->setContentsMargins(0, 0, 0, 0); 85 | layoutSearch->setContentsMargins(0, 0, 0, 0); 86 | 87 | auto layout = new QVBoxLayout; 88 | layout->addWidget(tabWidget); 89 | setLayout(layout); 90 | 91 | layout->setContentsMargins(0, 10, 0, 0); 92 | } 93 | 94 | void PageBrowse::setConnection() { 95 | connect(listWidgetNewBook, 96 | SIGNAL(signalModify()), 97 | this, 98 | SIGNAL(signalModify())); 99 | connect(listWidgetTopBook, 100 | SIGNAL(signalModify()), 101 | this, 102 | SIGNAL(signalModify())); 103 | connect(listWidgetSearchBook, 104 | SIGNAL(signalModify()), 105 | this, 106 | SIGNAL(signalModify())); 107 | connect(listWidgetNewBook, 108 | SIGNAL(signalReady()), 109 | this, 110 | SLOT(slotReady())); 111 | connect(listWidgetTopBook, 112 | SIGNAL(signalReady()), 113 | this, 114 | SLOT(slotReady())); 115 | connect(widgetSearchBook, 116 | &WidgetSearchBook::searchInfo, 117 | this, 118 | &PageBrowse::slotSearch); 119 | } 120 | -------------------------------------------------------------------------------- /src/client/page/PageBrowse.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | class PageBrowse : public QWidget { 16 | Q_OBJECT 17 | 18 | public: 19 | PageBrowse(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 20 | void updateStar(const X::xint &bookid, bool star); 21 | 22 | signals: 23 | void signalReady(); 24 | void signalModify(); 25 | 26 | public slots: 27 | void slotReady(); 28 | void refresh(); 29 | void slotSearch(const X::ptree &pt); 30 | 31 | private: 32 | void setUI(); 33 | void setConnection(); 34 | 35 | private: 36 | UserManager &userManager; 37 | BookManager &bookManager; 38 | 39 | QTabWidget *tabWidget; 40 | 41 | ListWidgetBrowseBook *listWidgetNewBook; 42 | 43 | ListWidgetBrowseBook *listWidgetTopBook; 44 | 45 | WidgetSearchBook *widgetSearchBook; 46 | ListWidgetBrowseBook *listWidgetSearchBook; 47 | 48 | int readyCount; 49 | }; 50 | -------------------------------------------------------------------------------- /src/client/page/PageFavorite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | PageFavorite::PageFavorite(UserManager &userManager, BookManager &bookManager, QWidget *parent) : 14 | QWidget(parent), 15 | userManager(userManager), 16 | bookManager(bookManager) { 17 | 18 | listWidgetStarRecord = new ListWidgetStarRecord(this); 19 | 20 | setUI(); 21 | setConnection(); 22 | } 23 | 24 | void PageFavorite::updateStar(const X::xint &bookid, bool star) { 25 | if (!star) { 26 | for (int i = 0; i < listWidgetStarRecord->count(); ++i) { 27 | auto item = dynamic_cast (listWidgetStarRecord->item(i)); 28 | if (item->getBook().getBookid() == bookid) { 29 | listWidgetStarRecord->takeItem(i); 30 | break; 31 | } 32 | } 33 | } else { 34 | StarRecord record; 35 | record.setBookid(bookid); 36 | record.setTime(time(0)); 37 | bookManager.getBookBrief(bookid, std::bind(&ListWidgetStarRecord::add, listWidgetStarRecord, std::placeholders::_1, record, 0)); 38 | } 39 | } 40 | 41 | void PageFavorite::slotGetStarRecord(const std::vector &records) { 42 | int tot = int(records.size()); 43 | for (int i = 0; i < tot; ++i) { 44 | listWidgetStarRecord->add(BookBrief::unknown(), records[i]); 45 | userManager.starBook(records[i].getBookid()); 46 | } 47 | for (int i = 0; i < tot; ++i) 48 | bookManager.getBookBrief(records[i].getBookid(), std::bind(&ListWidgetStarRecord::update, listWidgetStarRecord, std::placeholders::_1, records[i], tot - 1 - i)); 49 | emit signalReady(); 50 | } 51 | 52 | void PageFavorite::slotItemClicked(QListWidgetItem *item) { 53 | auto x = dynamic_cast (item); 54 | auto dialog = new DialogBook(userManager, bookManager, x->getBook().getBookid(), this); 55 | connect(dialog, SIGNAL(signalModify()), this, SIGNAL(signalModify())); 56 | dialog->show(); 57 | } 58 | 59 | void PageFavorite::refresh() { 60 | userManager.clearStar(); 61 | listWidgetStarRecord->clear(); 62 | auto obj = new GetStarRecords(userManager.getToken(), bookManager, 2147483647, 0); 63 | connect(obj, &GetStarRecords::done, this, &PageFavorite::slotGetStarRecord); 64 | obj->start(); 65 | } 66 | 67 | void PageFavorite::setUI() { 68 | listWidgetStarRecord->setFrameStyle(QFrame::NoFrame); 69 | 70 | auto layout = new QVBoxLayout; 71 | layout->addWidget(listWidgetStarRecord); 72 | setLayout(layout); 73 | 74 | layout->setContentsMargins(0, 0, 0, 0); 75 | } 76 | 77 | void PageFavorite::setConnection() { 78 | connect(listWidgetStarRecord, 79 | &ListWidgetStarRecord::itemDoubleClicked, 80 | this, 81 | &PageFavorite::slotItemClicked); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/client/page/PageFavorite.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class PageFavorite : public QWidget { 13 | Q_OBJECT 14 | 15 | public: 16 | PageFavorite(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 17 | void updateStar(const X::xint &bookid, bool star); 18 | 19 | signals: 20 | void signalReady(); 21 | void signalModify(); 22 | 23 | public slots: 24 | void slotGetStarRecord(const std::vector &records); 25 | void slotItemClicked(QListWidgetItem *item); 26 | 27 | void refresh(); 28 | 29 | private: 30 | void setUI(); 31 | void setConnection(); 32 | 33 | private: 34 | UserManager &userManager; 35 | BookManager &bookManager; 36 | 37 | ListWidgetStarRecord *listWidgetStarRecord; 38 | }; 39 | -------------------------------------------------------------------------------- /src/client/page/PageRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | class PageRecord : public QWidget { 20 | Q_OBJECT 21 | 22 | public: 23 | PageRecord(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 24 | void updateBorrow(const X::xint &bookid, const X::xll &beginTime, const X::xll &endTime); 25 | void updateBrowse(const X::xint &bookid); 26 | 27 | signals: 28 | void signalReady(); 29 | void signalModify(); 30 | 31 | public slots: 32 | void slotGetBrowseRecord(const std::vector &records); 33 | void slotGetKeepRecord(const std::vector &records); 34 | void slotGetBorrowRecord(const std::vector &records); 35 | void slotGetLoginRecord(const X::ErrorCode &ec, const X::ptree &pt); 36 | 37 | void slotBrowseRecordItemClicked(QListWidgetItem *item); 38 | void slotKeepRecordItemClicked(QListWidgetItem *item); 39 | void slotBorrowRecordItemClicked(QListWidgetItem *item); 40 | 41 | void refresh(); 42 | void refreshBrowseRecord(); 43 | void refreshKeepRecord(); 44 | void refreshBorrowRecord(); 45 | void refreshLoginRecord(); 46 | 47 | private: 48 | void setUI(); 49 | void setConnection(); 50 | 51 | private: 52 | UserManager &userManager; 53 | BookManager &bookManager; 54 | 55 | QTabWidget *tabWidget; 56 | ListWidgetBrowseRecord *listWidgetBrowseRecord; 57 | ListWidgetKeepRecord *listWidgetKeepRecord; 58 | ListWidgetBorrowRecord *listWidgetBorrowRecord; 59 | ListWidgetLoginRecord *listWidgetLoginRecord; 60 | }; 61 | -------------------------------------------------------------------------------- /src/client/page/PageSetting.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/page/PageSetting.cpp -------------------------------------------------------------------------------- /src/client/page/PageSetting.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | class PageSetting : public QWidget { 16 | Q_OBJECT 17 | 18 | public: 19 | PageSetting(UserManager &userManager, QWidget *parent = Q_NULLPTR); 20 | 21 | signals: 22 | void signalRefresh(); 23 | void signalModifyUser(); 24 | void signalLogout(); 25 | 26 | public slots: 27 | void slotModify(); 28 | void slotLogout(); 29 | void slotChangeLanguage(int index); 30 | 31 | private: 32 | void setUI(); 33 | void setConnection(); 34 | 35 | private: 36 | UserManager &userManager; 37 | 38 | QPushButton *btnModify; 39 | QPushButton *btnLogout; 40 | 41 | QPushButton *btnRefresh; 42 | 43 | QComboBox *cbboxLanguage; 44 | QLabel *lblLanguage; 45 | 46 | QStringList languageList; 47 | QStringList languageFileName; 48 | }; 49 | -------------------------------------------------------------------------------- /src/client/resource/i18n/qt_zh_CN.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/i18n/qt_zh_CN.qm -------------------------------------------------------------------------------- /src/client/resource/i18n/zh_CN.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/i18n/zh_CN.qm -------------------------------------------------------------------------------- /src/client/resource/images/WidgetLogin/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/images/WidgetLogin/close.png -------------------------------------------------------------------------------- /src/client/resource/images/WidgetLogin/drop_down_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/images/WidgetLogin/drop_down_button.png -------------------------------------------------------------------------------- /src/client/resource/images/WidgetLogin/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/images/WidgetLogin/head.jpg -------------------------------------------------------------------------------- /src/client/resource/images/WidgetLogin/min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/images/WidgetLogin/min.png -------------------------------------------------------------------------------- /src/client/resource/resource.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/WidgetLogin/drop_down_button.png 4 | images/WidgetLogin/head.jpg 5 | i18n/zh_CN.qm 6 | i18n/qt_zh_CN.qm 7 | style/WidgetLogin/style.css 8 | style/WidgetLogin/title.css 9 | images/WidgetLogin/close.png 10 | images/WidgetLogin/min.png 11 | style/DialogSignUp/style.css 12 | style/ListWidgetNavigation/style.css 13 | style/WidgetMain/style.css 14 | style/DialogBook/style.css 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/client/resource/style/DialogBook/style.css: -------------------------------------------------------------------------------- 1 | * { font-family: Microsoft YaHei; } 2 | 3 | QDialog { 4 | background: white; 5 | } 6 | 7 | QPushButton#btnMore { 8 | text-align:left; 9 | color: rgb(38, 133, 227); 10 | background-color: transparent; 11 | } 12 | 13 | QPushButton#btnMore:hover { 14 | color: rgb(97, 179, 246); 15 | } 16 | 17 | QPushButton#btnMore:pressed { 18 | color: rgb(0, 109, 176); 19 | } -------------------------------------------------------------------------------- /src/client/resource/style/DialogSignUp/style.css: -------------------------------------------------------------------------------- 1 | * { font-family: Microsoft YaHei; } 2 | 3 | QLineEdit { 4 | background: white; 5 | padding-left: 5px; 6 | padding-top: 1px; 7 | border-radius: 3px; 8 | border: 1px solid rgb(209, 209, 209); 9 | } 10 | 11 | QLineEdit:hover { 12 | border: 1px solid rgb(21, 131, 221); 13 | } 14 | 15 | DialogSignUp { 16 | background: white; 17 | } 18 | 19 | QPushButton { 20 | color: white; 21 | background-color: rgb(14, 150, 254); 22 | border-radius: 5px; 23 | } 24 | 25 | QPushButton:hover { 26 | color: white; 27 | background-color: rgb(44, 137, 255); 28 | } 29 | 30 | QPushButton:pressed { 31 | color: white; 32 | background-color: rgb(14, 135, 228); 33 | padding-left: 3px; 34 | padding-top: 3px; 35 | } 36 | -------------------------------------------------------------------------------- /src/client/resource/style/ListWidgetNavigation/style.css: -------------------------------------------------------------------------------- 1 | * { font-family: Microsoft YaHei; } 2 | 3 | QListWidget::item { 4 | padding: 20px; 5 | } 6 | -------------------------------------------------------------------------------- /src/client/resource/style/WidgetLogin/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/client/resource/style/WidgetLogin/style.css -------------------------------------------------------------------------------- /src/client/resource/style/WidgetLogin/title.css: -------------------------------------------------------------------------------- 1 | /* Reference: https://blog.csdn.net/goforwardtostep/article/details/53792702 */ 2 | 3 | * { font-family: Microsoft YaHei; } 4 | 5 | /* 最小化按钮 */ 6 | QPushButton#btnMin { 7 | border-image: url(:/images/WidgetLogin/min.png) 0 60 0 0; 8 | } 9 | 10 | QPushButton#btnMin:hover { 11 | border-image: url(:/images/WidgetLogin/min.png) 0 30 0 30; 12 | } 13 | 14 | QPushButton#btnMin:pressed { 15 | border-image: url(:/images/WidgetLogin/min.png) 0 0 0 60; 16 | } 17 | 18 | /* 关闭按钮 */ 19 | QPushButton#btnClose { 20 | border-image: url(:/images/WidgetLogin/close.png) 0 60 0 0; 21 | border-top-right-radius: 3; 22 | } 23 | 24 | QPushButton#btnClose:hover { 25 | border-image: url(:/images/WidgetLogin/close.png) 0 30 0 30; 26 | border-top-right-radius: 3; 27 | } 28 | 29 | QPushButton#btnClose:pressed { 30 | border-image: url(:/images/WidgetLogin/close.png) 0 0 0 60; 31 | border-top-right-radius: 3; 32 | } -------------------------------------------------------------------------------- /src/client/resource/style/WidgetMain/style.css: -------------------------------------------------------------------------------- 1 | QTabWidget::pane { /* The tab widget frame */ 2 | border-top: 1px solid #C2C7CB; 3 | } 4 | 5 | QTabWidget::tab-bar { 6 | left: 5px; /* move to the right by 5px */ 7 | } 8 | 9 | /* Style the tab using the tab sub-control. Note that 10 | it reads QTabBar _not_ QTabWidget */ 11 | QTabBar::tab { 12 | border: 1px solid #C4C4C3; 13 | border-bottom-color: #C2C7CB; /* same as the pane color */ 14 | border-top-left-radius: 4px; 15 | border-top-right-radius: 4px; 16 | min-width: 8ex; 17 | padding: 10px; 18 | } 19 | 20 | QTabBar::tab:selected, QTabBar::tab:hover { 21 | background: white; 22 | } 23 | 24 | QTabBar::tab:selected { 25 | border-color: #9B9B9B; 26 | border-bottom-color: #C2C7CB; /* same as pane color */ 27 | } 28 | 29 | QTabBar::tab:!selected { 30 | margin-top: 2px; /* make non-selected tabs look smaller */ 31 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadBorrowBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadBorrowBook::ThreadBorrowBook(const xll &token, const xint &bookid, const xll &keepTime, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | bookid(bookid), 11 | keepTime(keepTime) { 12 | } 13 | 14 | void ThreadBorrowBook::run() { 15 | xll token = this->token; 16 | ptree pt; 17 | ActionCode ac = X::NoAction; 18 | ErrorCode ec = X::NoError; 19 | 20 | pt.put("bookid", this->bookid); 21 | pt.put("keepTime", this->keepTime); 22 | 23 | try { 24 | auto socket = newSocket(); 25 | X::tcp_sync_write(socket, token, X::BorrowBook, pt); 26 | pt = ptree(); 27 | X::tcp_sync_read(socket, token, ac, pt); 28 | socket.close(); 29 | ec = static_cast (pt.get("error_code")); 30 | } catch (std::exception &) { 31 | ec = X::UnknownError; 32 | } 33 | 34 | emit done(ec); 35 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadBorrowBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadBorrowBook : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadBorrowBook(const xll &token, const xint &bookid, const xll &keepTime, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint bookid; 23 | xll keepTime; 24 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadGetBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadGetBook::ThreadGetBook(const xll &token, const xint &bookid, bool brief, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | bookid(bookid), 11 | brief(brief) { 12 | 13 | qRegisterMetaType("Resource"); 14 | } 15 | 16 | void ThreadGetBook::run() { 17 | xll token = this->token; 18 | ptree pt; 19 | ActionCode ac = X::NoAction; 20 | ErrorCode ec = X::NoError; 21 | Resource cover; 22 | 23 | pt.put("bookid", this->bookid); 24 | 25 | try { 26 | auto socket = newSocket(); 27 | X::tcp_sync_write(socket, token, brief ? X::GetBookBrief : X::GetBook, pt); 28 | pt = ptree(); 29 | X::tcp_sync_read(socket, token, ac, pt); 30 | ec = static_cast (pt.get("error_code")); 31 | if (ec == X::NoError) { 32 | ptree p; 33 | p.put("bookid", this->bookid); 34 | ActionCode a; 35 | X::tcp_sync_write(socket, token, X::GetBookCover, p); 36 | p = ptree(); 37 | cover = X::tcp_sync_read_with_file(socket, token, a, p); 38 | } 39 | socket.close(); 40 | } catch (std::exception &) { 41 | ec = X::InvalidBook; 42 | pt = ptree(); 43 | cover.clean(); 44 | } 45 | 46 | emit done(ec, pt, cover); 47 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadGetBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | class ThreadGetBook : public ThreadNetwork { 10 | Q_OBJECT 11 | 12 | public: 13 | ThreadGetBook(const xll &token, const xint &bookid, bool brief, QObject *parent = Q_NULLPTR); 14 | 15 | signals: 16 | void done(const ErrorCode &ec, const ptree &pt, const Resource &cover); 17 | 18 | private: 19 | void run() override; 20 | 21 | private: 22 | xll token; 23 | xint bookid; 24 | bool brief; 25 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadGetNewBookList.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadGetNewBookList::ThreadGetNewBookList(const xll &token, const xint &number, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | number(number) { 11 | } 12 | 13 | void ThreadGetNewBookList::run() { 14 | xll token = this->token; 15 | ptree pt; 16 | ActionCode ac = X::NoAction; 17 | ErrorCode ec = X::NoError; 18 | 19 | pt.put("number", this->number); 20 | 21 | try { 22 | auto socket = newSocket(); 23 | X::tcp_sync_write(socket, token, X::GetNewBookList, pt); 24 | pt = ptree(); 25 | X::tcp_sync_read(socket, token, ac, pt); 26 | socket.close(); 27 | ec = static_cast (pt.get("error_code")); 28 | } catch (std::exception &) { 29 | ec = X::UnknownError; 30 | pt = ptree(); 31 | } 32 | 33 | emit done(ec, pt); 34 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadGetNewBookList.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadGetNewBookList : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadGetNewBookList(const xll &token, const xint &number, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec, const ptree &pt); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint number; 23 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadGetRecord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadGetRecord::ThreadGetRecord(const xll &token, const ActionCode &type, const xint &number, const xint &begin, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | type(type), 11 | number(number), 12 | begin(begin) { 13 | } 14 | 15 | void ThreadGetRecord::run() { 16 | xll token = this->token; 17 | ptree pt; 18 | ActionCode ac = X::NoAction; 19 | ErrorCode ec = X::NoError; 20 | 21 | pt.put("number", this->number); 22 | pt.put("begin", this->begin); 23 | 24 | try { 25 | auto socket = newSocket(); 26 | X::tcp_sync_write(socket, token, this->type, pt); 27 | pt = ptree(); 28 | X::tcp_sync_read(socket, token, ac, pt); 29 | socket.close(); 30 | ec = static_cast (pt.get("error_code")); 31 | } catch (std::exception &) { 32 | ec = X::UnknownError; 33 | pt = ptree(); 34 | } 35 | 36 | emit done(ec, pt); 37 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadGetRecord.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadGetRecord : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadGetRecord(const xll &token, const ActionCode &type, const xint &number, const xint& begin = 0, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec, const ptree &pt); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | ActionCode type; 23 | xint number; 24 | xint begin; 25 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadGetSearchBookList.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadGetSearchBookList::ThreadGetSearchBookList(const xll &token, const ptree &pt, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | pt(pt) { 11 | } 12 | 13 | void ThreadGetSearchBookList::run() { 14 | xll token = this->token; 15 | ActionCode ac = X::NoAction; 16 | ErrorCode ec = X::NoError; 17 | 18 | try { 19 | auto socket = newSocket(); 20 | X::tcp_sync_write(socket, token, X::GetSearchBookList, pt); 21 | pt = ptree(); 22 | X::tcp_sync_read(socket, token, ac, pt); 23 | socket.close(); 24 | ec = static_cast (pt.get("error_code")); 25 | } catch (std::exception &) { 26 | ec = X::UnknownError; 27 | pt = ptree(); 28 | } 29 | 30 | emit done(ec, pt); 31 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadGetSearchBookList.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadGetSearchBookList : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadGetSearchBookList(const xll &token, const ptree &pt, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec, const ptree &pt); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | ptree pt; 23 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadGetTopBookList.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadGetTopBookList::ThreadGetTopBookList(const xll &token, const xint &number, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | number(number) { 11 | } 12 | 13 | void ThreadGetTopBookList::run() { 14 | xll token = this->token; 15 | ptree pt; 16 | ActionCode ac = X::NoAction; 17 | ErrorCode ec = X::NoError; 18 | 19 | pt.put("number", this->number); 20 | 21 | try { 22 | auto socket = newSocket(); 23 | X::tcp_sync_write(socket, token, X::GetTopBookList, pt); 24 | pt = ptree(); 25 | X::tcp_sync_read(socket, token, ac, pt); 26 | socket.close(); 27 | ec = static_cast (pt.get("error_code")); 28 | } catch (std::exception &) { 29 | ec = X::UnknownError; 30 | pt = ptree(); 31 | } 32 | 33 | emit done(ec, pt); 34 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadGetTopBookList.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadGetTopBookList : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadGetTopBookList(const xll &token, const xint &number, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec, const ptree &pt); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint number; 23 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadLogin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadLogin::ThreadLogin(const QString &username, const QString &password, QObject *parent) : 8 | ThreadNetwork(parent), 9 | username(username.toStdString()), 10 | password(password.toStdString()) { 11 | } 12 | 13 | void ThreadLogin::run() { 14 | xll token = 0; 15 | ptree pt; 16 | ActionCode ac = X::NoAction; 17 | ErrorCode ec = X::NoError; 18 | 19 | pt.put("username", username); 20 | pt.put("password", password); 21 | 22 | try { 23 | auto socket = newSocket(); 24 | X::tcp_sync_write(socket, token, X::Login, pt); 25 | pt = ptree(); 26 | X::tcp_sync_read(socket, token, ac, pt); 27 | socket.close(); 28 | ec = static_cast (pt.get("error_code")); 29 | } catch (std::exception &) { 30 | ec = X::LoginFailed; 31 | token = 0; 32 | pt = ptree(); 33 | } 34 | 35 | emit done(ec, token, pt); 36 | } 37 | -------------------------------------------------------------------------------- /src/client/thread/ThreadLogin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class ThreadLogin : public ThreadNetwork { 11 | Q_OBJECT 12 | 13 | public: 14 | ThreadLogin(const QString &username, const QString &password, QObject *parent = Q_NULLPTR); 15 | 16 | signals: 17 | void done(const ErrorCode &ec, const xll &token, const ptree &pt); 18 | 19 | private: 20 | void run() override; 21 | 22 | private: 23 | xstring username; 24 | xstring password; 25 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadLogout.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadLogout::ThreadLogout(const xll &token, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token) { 10 | } 11 | 12 | void ThreadLogout::run() { 13 | xll token = this->token; 14 | ptree pt; 15 | ActionCode ac = X::NoAction; 16 | ErrorCode ec = X::NoError; 17 | 18 | try { 19 | auto socket = newSocket(); 20 | X::tcp_sync_write(socket, token, X::Logout, pt); 21 | pt = ptree(); 22 | X::tcp_sync_read(socket, token, ac, pt); 23 | socket.close(); 24 | ec = static_cast (pt.get("error_code")); 25 | } catch (std::exception &) { 26 | ec = X::UnknownError; 27 | } 28 | 29 | emit done(ec); 30 | } 31 | -------------------------------------------------------------------------------- /src/client/thread/ThreadLogout.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class ThreadLogout : public ThreadNetwork { 11 | Q_OBJECT 12 | 13 | public: 14 | ThreadLogout(const xll &token, QObject *parent = Q_NULLPTR); 15 | 16 | signals: 17 | void done(const ErrorCode &ec); 18 | 19 | private: 20 | void run() override; 21 | 22 | private: 23 | xll token; 24 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadModifyUser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadModifyUser::ThreadModifyUser(const xll &token, const QString &nickname, const QString &email, const QString &passwordOld, const QString &passwordNew, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | nickname(nickname.toStdString()), 11 | email(email.toStdString()), 12 | passwordOld(passwordOld.toStdString()), 13 | passwordNew(passwordNew.toStdString()) { 14 | 15 | } 16 | 17 | void ThreadModifyUser::run() { 18 | xll token = this->token; 19 | ptree pt; 20 | ActionCode ac = X::NoAction; 21 | ErrorCode ec = X::NoError; 22 | 23 | pt.put("nickname", nickname); 24 | pt.put("email", email); 25 | pt.put("passwordOld", passwordOld); 26 | if (passwordNew.size() > 0) 27 | pt.put("passwordNew", passwordNew); 28 | 29 | try { 30 | auto socket = newSocket(); 31 | X::tcp_sync_write(socket, token, X::Modify, pt); 32 | pt = ptree(); 33 | X::tcp_sync_read(socket, token, ac, pt); 34 | socket.close(); 35 | ec = static_cast (pt.get("error_code")); 36 | } catch (std::exception &) { 37 | ec = X::ModifyFailed; 38 | } 39 | 40 | emit done(ec); 41 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadModifyUser.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class ThreadModifyUser : public ThreadNetwork { 11 | Q_OBJECT 12 | 13 | public: 14 | ThreadModifyUser(const xll &token, const QString &nickname, const QString &email, const QString &passwordOld, const QString &passwordNew, QObject *parent = Q_NULLPTR); 15 | 16 | signals: 17 | void done(const ErrorCode &ec); 18 | 19 | private: 20 | void run() override; 21 | 22 | private: 23 | xll token; 24 | xstring nickname; 25 | xstring email; 26 | xstring passwordOld; 27 | xstring passwordNew; 28 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadNetwork.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | 8 | ThreadNetwork::ThreadNetwork(QObject *parent) : 9 | QThread(parent), 10 | io_service(), 11 | ep(boost::asio::ip::address::from_string( 12 | QSettings().value("Network/server_url", "127.0.0.1").toString().toStdString()), 13 | QSettings().value("Network/server_port", 2333).toInt()) { 14 | qRegisterMetaType("xll"); 15 | qRegisterMetaType("xint"); 16 | qRegisterMetaType("ptree"); 17 | qRegisterMetaType("xstring"); 18 | qRegisterMetaType("ErrorCode"); 19 | qRegisterMetaType("ActionCode"); 20 | } 21 | 22 | boost::asio::ip::tcp::socket ThreadNetwork::newSocket() { 23 | boost::asio::ip::tcp::socket socket(io_service); 24 | socket.connect(ep); 25 | return std::move(socket); 26 | } 27 | -------------------------------------------------------------------------------- /src/client/thread/ThreadNetwork.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | class ThreadNetwork : public QThread { 13 | Q_OBJECT 14 | 15 | public: 16 | typedef X::xll xll; 17 | typedef X::xint xint; 18 | typedef X::ptree ptree; 19 | typedef X::xstring xstring; 20 | typedef X::ErrorCode ErrorCode; 21 | typedef X::ActionCode ActionCode; 22 | 23 | ThreadNetwork(QObject *parent = Q_NULLPTR); 24 | virtual ~ThreadNetwork() = default; 25 | 26 | boost::asio::ip::tcp::socket newSocket(); 27 | 28 | private: 29 | boost::asio::io_service io_service; 30 | boost::asio::ip::tcp::endpoint ep; 31 | }; 32 | -------------------------------------------------------------------------------- /src/client/thread/ThreadReturnBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadReturnBook::ThreadReturnBook(const xll &token, const xint &userid, const xint &bookid, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | userid(userid), 11 | bookid(bookid) { 12 | } 13 | 14 | void ThreadReturnBook::run() { 15 | xll token = this->token; 16 | ptree pt; 17 | ActionCode ac = X::NoAction; 18 | ErrorCode ec = X::NoError; 19 | 20 | pt.put("userid", this->userid); 21 | pt.put("bookid", this->bookid); 22 | 23 | try { 24 | auto socket = newSocket(); 25 | X::tcp_sync_write(socket, token, X::ReturnBook, pt); 26 | pt = ptree(); 27 | X::tcp_sync_read(socket, token, ac, pt); 28 | socket.close(); 29 | ec = static_cast (pt.get("error_code")); 30 | } catch (std::exception &) { 31 | ec = X::UnknownError; 32 | } 33 | 34 | emit done(ec); 35 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadReturnBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadReturnBook : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadReturnBook(const xll &token, const xint &userid, const xint &bookid, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint userid; 23 | xint bookid; 24 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadSetBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadSetBook::ThreadSetBook(const xll &token, const ptree &pt, const Resource &cover, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | pt(pt), 11 | cover(cover) { 12 | } 13 | 14 | void ThreadSetBook::run() { 15 | ActionCode ac = X::NoAction; 16 | ErrorCode ec = X::NoError; 17 | 18 | auto bookid = pt.get("bookid"); 19 | try { 20 | auto socket = newSocket(); 21 | X::tcp_sync_write(socket, token, X::SetBook, pt); 22 | pt = ptree(); 23 | X::tcp_sync_read(socket, token, ac, pt); 24 | ec = static_cast (pt.get("error_code")); 25 | 26 | if (ec == X::NoError && cover.getSize()) { 27 | pt = ptree(); 28 | pt.put("bookid", bookid); 29 | pt.put("fileSize", cover.getSize()); 30 | X::tcp_sync_write_with_file(socket, token, X::SetBookCover, pt, cover); 31 | pt = ptree(); 32 | X::tcp_sync_read(socket, token, ac, pt); 33 | ec = static_cast (pt.get("error_code")); 34 | } 35 | socket.close(); 36 | } catch (std::exception &) { 37 | ec = X::UnknownError; 38 | } 39 | 40 | emit done(ec); 41 | } 42 | -------------------------------------------------------------------------------- /src/client/thread/ThreadSetBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | class ThreadSetBook : public ThreadNetwork { 10 | Q_OBJECT 11 | 12 | public: 13 | ThreadSetBook(const xll &token, const ptree &pt, const Resource &cover, QObject *parent = Q_NULLPTR); 14 | 15 | signals: 16 | void done(const ErrorCode &ec); 17 | 18 | private: 19 | void run() override; 20 | 21 | private: 22 | xll token; 23 | ptree pt; 24 | Resource cover; 25 | }; 26 | -------------------------------------------------------------------------------- /src/client/thread/ThreadSetPriority.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadSetPriority::ThreadSetPriority(const xll &token, const xint &userid, const xint &priority, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | userid(userid), 11 | priority(priority) { 12 | } 13 | 14 | void ThreadSetPriority::run() { 15 | xll token = this->token; 16 | ptree pt; 17 | ActionCode ac = X::NoAction; 18 | ErrorCode ec = X::NoError; 19 | 20 | pt.put("userid", this->userid); 21 | pt.put("priority", this->priority); 22 | 23 | try { 24 | auto socket = newSocket(); 25 | X::tcp_sync_write(socket, token, X::SetPriority, pt); 26 | pt = ptree(); 27 | X::tcp_sync_read(socket, token, ac, pt); 28 | socket.close(); 29 | ec = static_cast (pt.get("error_code")); 30 | } catch (std::exception &) { 31 | ec = X::UnknownError; 32 | } 33 | 34 | emit done(ec); 35 | } 36 | -------------------------------------------------------------------------------- /src/client/thread/ThreadSetPriority.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class ThreadSetPriority : public ThreadNetwork { 11 | Q_OBJECT 12 | 13 | public: 14 | ThreadSetPriority(const xll &token, const xint &userid, const xint &priority, QObject *parent = Q_NULLPTR); 15 | 16 | signals: 17 | void done(const ErrorCode &ec); 18 | 19 | private: 20 | void run() override; 21 | 22 | private: 23 | xll token; 24 | xint userid; 25 | xint priority; 26 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadSignUp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadSignUp::ThreadSignUp(const QString &username, const QString &nickname, const QString &password, const QString &email, QObject *parent) : 8 | ThreadNetwork(parent), 9 | username(username.toStdString()), 10 | nickname(nickname.toStdString()), 11 | password(password.toStdString()), 12 | email(email.toStdString()) { 13 | } 14 | 15 | void ThreadSignUp::run() { 16 | xll token = 0; 17 | ptree pt; 18 | ActionCode ac = X::NoAction; 19 | ErrorCode ec = X::NoError; 20 | 21 | pt.put("username", username); 22 | pt.put("nickname", nickname); 23 | pt.put("password", password); 24 | pt.put("email", email); 25 | 26 | try { 27 | auto socket = newSocket(); 28 | X::tcp_sync_write(socket, token, X::Register, pt); 29 | pt = ptree(); 30 | X::tcp_sync_read(socket, token, ac, pt); 31 | socket.close(); 32 | ec = static_cast (pt.get("error_code")); 33 | } catch (std::exception &) { 34 | ec = X::RegisterFailed; 35 | } 36 | 37 | emit done(ec); 38 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadSignUp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class ThreadSignUp : public ThreadNetwork { 11 | Q_OBJECT 12 | 13 | public: 14 | ThreadSignUp(const QString &username, const QString &nickname, const QString &password, const QString &email, QObject *parent = Q_NULLPTR); 15 | 16 | signals: 17 | void done(const ErrorCode &ec); 18 | 19 | private: 20 | void run() override; 21 | 22 | private: 23 | xstring username; 24 | xstring nickname; 25 | xstring password; 26 | xstring email; 27 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadStarBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadStarBook::ThreadStarBook(const xll &token, const xint &bookid, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | bookid(bookid) { 11 | } 12 | 13 | void ThreadStarBook::run() { 14 | xll token = this->token; 15 | ptree pt; 16 | ActionCode ac = X::NoAction; 17 | ErrorCode ec = X::NoError; 18 | 19 | pt.put("bookid", this->bookid); 20 | 21 | try { 22 | auto socket = newSocket(); 23 | X::tcp_sync_write(socket, token, X::StarBook, pt); 24 | pt = ptree(); 25 | X::tcp_sync_read(socket, token, ac, pt); 26 | socket.close(); 27 | ec = static_cast (pt.get("error_code")); 28 | } catch (std::exception &) { 29 | ec = X::UnknownError; 30 | } 31 | 32 | emit done(ec); 33 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadStarBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadStarBook : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadStarBook(const xll &token, const xint &bookid, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint bookid; 23 | }; -------------------------------------------------------------------------------- /src/client/thread/ThreadUnStarBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | ThreadUnStarBook::ThreadUnStarBook(const xll &token, const xint &bookid, QObject *parent) : 8 | ThreadNetwork(parent), 9 | token(token), 10 | bookid(bookid) { 11 | } 12 | 13 | void ThreadUnStarBook::run() { 14 | xll token = this->token; 15 | ptree pt; 16 | ActionCode ac = X::NoAction; 17 | ErrorCode ec = X::NoError; 18 | 19 | pt.put("bookid", this->bookid); 20 | 21 | try { 22 | auto socket = newSocket(); 23 | X::tcp_sync_write(socket, token, X::UnStarBook, pt); 24 | pt = ptree(); 25 | X::tcp_sync_read(socket, token, ac, pt); 26 | socket.close(); 27 | ec = static_cast (pt.get("error_code")); 28 | } catch (std::exception &) { 29 | ec = X::UnknownError; 30 | } 31 | 32 | emit done(ec); 33 | } -------------------------------------------------------------------------------- /src/client/thread/ThreadUnStarBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class ThreadUnStarBook : public ThreadNetwork { 9 | Q_OBJECT 10 | 11 | public: 12 | ThreadUnStarBook(const xll &token, const xint &bookid, QObject *parent = Q_NULLPTR); 13 | 14 | signals: 15 | void done(const ErrorCode &ec); 16 | 17 | private: 18 | void run() override; 19 | 20 | private: 21 | xll token; 22 | xint bookid; 23 | }; -------------------------------------------------------------------------------- /src/client/utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace X { 10 | QString what(const ErrorCode &ec) { 11 | switch (ec) { 12 | case NoError: 13 | return QObject::tr("No Error"); 14 | case UnknownError: 15 | return QObject::tr("Unknown Error"); 16 | case InvalidBody: 17 | return QObject::tr("Invalid Body"); 18 | case LoginFailed: 19 | return QObject::tr("Login Failed"); 20 | case NoSuchUser: 21 | return QObject::tr("No Such User"); 22 | case AlreadyLogin: 23 | return QObject::tr("Already Login"); 24 | case RegisterFailed: 25 | return QObject::tr("Register Failed"); 26 | case InvalidUsername: 27 | return QObject::tr("Invalid Username"); 28 | case InvalidNickname: 29 | return QObject::tr("Invalid Nickname"); 30 | case InvalidPassword: 31 | return QObject::tr("Invalid Password"); 32 | case InvalidEmail: 33 | return QObject::tr("Invalid Email"); 34 | case AlreadyRegister: 35 | return QObject::tr("Already Register"); 36 | case ModifyFailed: 37 | return QObject::tr("Modify Failed"); 38 | case InvalidNewPassword: 39 | return QObject::tr("Invalid New Password"); 40 | case NotLogin: 41 | return QObject::tr("No Login"); 42 | case InvalidToken: 43 | return QObject::tr("Invalid Token"); 44 | case InvalidBook: 45 | return QObject::tr("Invalid Book"); 46 | case NoSuchBook: 47 | return QObject::tr("No Such Book"); 48 | case NoRestBook: 49 | return QObject::tr("No Rest Book"); 50 | case AlreadyHave: 51 | return QObject::tr("Already Have"); 52 | case NoHave: 53 | return QObject::tr("No Have"); 54 | case InvalidTime: 55 | return QObject::tr("Invalid Time"); 56 | case AlreadyStar: 57 | return QObject::tr("Already Star"); 58 | case NoSuchStar: 59 | return QObject::tr("No Such Star"); 60 | case NoPermission: 61 | return QObject::tr("No Permission"); 62 | case InvalidResource: 63 | return QObject::tr("Invalid Resource"); 64 | case NoSuchResource: 65 | return QObject::tr("No Such Resource"); 66 | default: 67 | return QObject::tr("No Such Error"); 68 | } 69 | } 70 | 71 | bool loadStyleSheet(QWidget *w, const QString &filename) { 72 | QFile f(filename); 73 | f.open(QFile::ReadOnly); 74 | if (f.isOpen()) { 75 | w->setStyleSheet(f.readAll()); 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/client/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace X { 12 | extern QString what(const ErrorCode &ec); 13 | extern bool loadStyleSheet(QWidget *w, const QString &filename); 14 | } -------------------------------------------------------------------------------- /src/client/values.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | namespace X { 7 | const xstring &ORG_NAME = "Pi"; 8 | const xstring &APP_NAME = "PiLibrary"; 9 | const xstring &VERSION = "1.0.0"; 10 | const xstring &saltBegin = "Ht1*dvj+W"; 11 | const xstring &saltEnd = "zs-8Oh_wqn"; 12 | } 13 | -------------------------------------------------------------------------------- /src/client/values.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace X { 9 | extern const xstring &ORG_NAME; 10 | extern const xstring &APP_NAME; 11 | extern const xstring &VERSION; 12 | extern const xstring &saltBegin; 13 | extern const xstring &saltEnd; 14 | } 15 | -------------------------------------------------------------------------------- /src/client/widget/WidgetHead.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | WidgetHead::WidgetHead(UserManager &userManager, QWidget *parent) : 10 | QWidget(parent), 11 | userManager(userManager) { 12 | 13 | lblNickname = new QLabel(this); 14 | 15 | setUI(); 16 | } 17 | 18 | void WidgetHead::slotModify() { 19 | lblNickname->setText(tr("Hello\n") + QString::fromStdString(userManager.getUser().getNickname())); 20 | } 21 | 22 | void WidgetHead::setUI() { 23 | lblNickname->setWordWrap(true); 24 | lblNickname->setAlignment(Qt::AlignCenter); 25 | lblNickname->setFixedHeight(100); 26 | 27 | auto layout = new QHBoxLayout; 28 | layout->addWidget(lblNickname, Qt::AlignCenter); 29 | 30 | setLayout(layout); 31 | slotModify(); 32 | } 33 | -------------------------------------------------------------------------------- /src/client/widget/WidgetHead.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class WidgetHead : public QWidget { 12 | Q_OBJECT 13 | 14 | public: 15 | WidgetHead(UserManager &userManager, QWidget *parent = Q_NULLPTR); 16 | 17 | public slots: 18 | void slotModify(); 19 | 20 | private: 21 | void setUI(); 22 | 23 | private: 24 | UserManager &userManager; 25 | 26 | QLabel *lblNickname; 27 | }; -------------------------------------------------------------------------------- /src/client/widget/WidgetLogin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "ui_WidgetLogin.h" 19 | 20 | class WidgetLogin : public QWidget, private Ui::WidgetLogin { 21 | Q_OBJECT 22 | 23 | public: 24 | WidgetLogin(UserManager &userManager, QWidget *parent = Q_NULLPTR); 25 | ~WidgetLogin(); 26 | void loadSetting(); 27 | void saveSetting(); 28 | 29 | signals: 30 | void signalAccept(); 31 | 32 | public slots: 33 | void slotLoginBegin(); 34 | void slotLoginEnd(const X::ErrorCode &ec, const X::xll &token, const X::ptree &pt); 35 | void slotRegister(); 36 | 37 | private: 38 | void setUI(); 39 | void setConnection(); 40 | 41 | private: 42 | UserManager &userManager; 43 | 44 | WidgetLoginTitle *title; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /src/client/widget/WidgetLoginTitle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | WidgetLoginTitle::WidgetLoginTitle(QWidget *moveWidget, QWidget *parent) : 12 | QWidget(parent) { 13 | 14 | btnMin = new QPushButton(this); 15 | btnMin->setObjectName("btnMin"); 16 | btnClose = new QPushButton(this); 17 | btnClose->setObjectName("btnClose"); 18 | this->moveWidget = moveWidget; 19 | 20 | setUI(); 21 | setConnection(); 22 | } 23 | 24 | void WidgetLoginTitle::setUI() { 25 | static const int W = 50; 26 | static const int H = 50; 27 | 28 | X::loadStyleSheet(this, ":/style/WidgetLogin/title.css"); 29 | 30 | btnMin->setFixedSize(QSize(W, H)); 31 | btnMin->setFocusPolicy(Qt::NoFocus); 32 | btnClose->setFixedSize(QSize(W, H)); 33 | btnClose->setFocusPolicy(Qt::NoFocus); 34 | 35 | QHBoxLayout *layout = new QHBoxLayout(this); 36 | 37 | layout->addStretch(); 38 | layout->addWidget(btnMin); 39 | layout->addWidget(btnClose); 40 | layout->setContentsMargins(0, 0, 0, 0); 41 | layout->setSpacing(0); 42 | 43 | setFixedHeight(H); 44 | setWindowFlags(Qt::FramelessWindowHint); 45 | } 46 | 47 | void WidgetLoginTitle::setConnection() { 48 | connect(btnMin, &QPushButton::clicked, this, &WidgetLoginTitle::slotMin); 49 | connect(btnClose, &QPushButton::clicked, this, &WidgetLoginTitle::slotClose); 50 | } 51 | 52 | void WidgetLoginTitle::mousePressEvent(QMouseEvent *event) { 53 | isPressed = true; 54 | startPoint = event->globalPos(); 55 | QWidget::mousePressEvent(event); 56 | } 57 | 58 | void WidgetLoginTitle::mouseMoveEvent(QMouseEvent *event) { 59 | if (isPressed) { 60 | auto now = event->globalPos(); 61 | auto moveDelta = now - startPoint; 62 | startPoint = now; 63 | moveWidget->move(moveWidget->pos() + moveDelta); 64 | } 65 | QWidget::mouseMoveEvent(event); 66 | } 67 | 68 | void WidgetLoginTitle::mouseReleaseEvent(QMouseEvent *event) { 69 | isPressed = false; 70 | QWidget::mouseReleaseEvent(event); 71 | } 72 | 73 | void WidgetLoginTitle::slotMin() { 74 | emit signalMin(); 75 | } 76 | 77 | void WidgetLoginTitle::slotClose() { 78 | emit signalClose(); 79 | } 80 | -------------------------------------------------------------------------------- /src/client/widget/WidgetLoginTitle.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | class WidgetLoginTitle : public QWidget { 13 | Q_OBJECT 14 | 15 | public: 16 | WidgetLoginTitle(QWidget *moveWidget, QWidget *parent = Q_NULLPTR); 17 | 18 | signals: 19 | void signalMin(); 20 | void signalClose(); 21 | 22 | private slots: 23 | void slotMin(); 24 | void slotClose(); 25 | 26 | private: 27 | void setUI(); 28 | void setConnection(); 29 | 30 | protected: 31 | void mousePressEvent(QMouseEvent *event) override; 32 | void mouseMoveEvent(QMouseEvent *event) override; 33 | void mouseReleaseEvent(QMouseEvent *event) override; 34 | 35 | private: 36 | QPushButton *btnMin; 37 | QPushButton *btnClose; 38 | QWidget *moveWidget; 39 | 40 | QPoint startPoint; 41 | bool isPressed {false}; 42 | }; -------------------------------------------------------------------------------- /src/client/widget/WidgetMain.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | class WidgetMain : public QWidget { 25 | Q_OBJECT 26 | 27 | public: 28 | WidgetMain(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 29 | void loadSetting(); 30 | void saveSetting(); 31 | 32 | signals: 33 | void signalLogout(); 34 | 35 | public slots: 36 | void setEvents(); 37 | void refresh(bool force = true); 38 | 39 | private: 40 | void setUI(); 41 | void setConnection(); 42 | void initListWidget(); 43 | void initPageWidget(); 44 | 45 | private: 46 | UserManager &userManager; 47 | BookManager &bookManager; 48 | 49 | QSettings setting; 50 | 51 | WidgetHead *widgetHead; 52 | QListWidget *listWidget; 53 | QStackedWidget *pageWidget; 54 | QScrollArea *scrollArea; 55 | 56 | PageAbout *pageAbout; 57 | PageAddBook *pageAddBook; 58 | PageBrowse *pageBrowse; 59 | PageFavorite *pageFavorite; 60 | PageRecord *pageRecord; 61 | PageAdminister *pageAdminister; 62 | PageSetting *pageSetting; 63 | 64 | DialogRefresh *dialogRefresh; 65 | 66 | int eventCount; 67 | }; 68 | -------------------------------------------------------------------------------- /src/client/widget/WidgetSearchBook.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | WidgetSearchBook::WidgetSearchBook(QWidget *parent) : 13 | QWidget(parent) { 14 | 15 | #define XNEW(name) \ 16 | lbl##name = new QLabel(this); \ 17 | edit##name = new QLineEdit(this); \ 18 | regex##name = new QCheckBox(this); 19 | 20 | XNEW(Title) 21 | XNEW(Author) 22 | XNEW(Introduction) 23 | XNEW(Position) 24 | XNEW(Bookid) 25 | XNEW(Publisher) 26 | XNEW(ISBN) 27 | 28 | btnSearch = new QPushButton(this); 29 | btnMore = new QPushButton(this); 30 | 31 | setUI(); 32 | setConnection(); 33 | } 34 | 35 | void WidgetSearchBook::slotSearch() { 36 | X::ptree pt; 37 | 38 | #define XPUT(low, big) \ 39 | auto low = edit##big->text(); \ 40 | if (low.size()) { \ 41 | if (regex##big->isChecked()) \ 42 | pt.put(#low, low.toStdString()); \ 43 | else \ 44 | pt.put(#low, X::escape(low.toStdString())); \ 45 | } 46 | 47 | XPUT(title, Title) 48 | XPUT(author, Author) 49 | XPUT(introduction, Introduction) 50 | XPUT(position, Position) 51 | XPUT(bookid, Bookid) 52 | XPUT(publisher, Publisher) 53 | XPUT(ISBN, ISBN) 54 | 55 | emit searchInfo(pt); 56 | } 57 | 58 | void WidgetSearchBook::slotMore() { 59 | if (lblAuthor->isHidden()) { 60 | #define XSHOW(name) \ 61 | lbl##name->show(); \ 62 | edit##name->show(); \ 63 | regex##name->show(); 64 | 65 | regexTitle->show(); 66 | XSHOW(Author) 67 | XSHOW(Introduction) 68 | XSHOW(Position) 69 | XSHOW(Publisher) 70 | XSHOW(Bookid) 71 | XSHOW(ISBN) 72 | } else { 73 | #define XHIDE(name) \ 74 | lbl##name->hide(); \ 75 | edit##name->hide(); \ 76 | regex##name->hide(); 77 | 78 | regexTitle->hide(); 79 | XHIDE(Author) 80 | XHIDE(Introduction) 81 | XHIDE(Position) 82 | XHIDE(Publisher) 83 | XHIDE(Bookid) 84 | XHIDE(ISBN) 85 | } 86 | } 87 | 88 | void WidgetSearchBook::setUI() { 89 | int maxWidth = 130; 90 | 91 | auto layout = new QVBoxLayout; 92 | 93 | auto layoutTitle = new QHBoxLayout; 94 | lblTitle->setFixedWidth(maxWidth); 95 | lblTitle->setBuddy(editTitle); 96 | btnSearch->setText(tr("&Search")); 97 | btnMore->setText(tr("&More")); 98 | regexTitle->setText(tr("&Regex")); 99 | regexTitle->hide(); 100 | layoutTitle->addWidget(lblTitle); 101 | layoutTitle->addWidget(editTitle); 102 | layoutTitle->addWidget(btnSearch); 103 | layoutTitle->addWidget(btnMore); 104 | layoutTitle->addWidget(regexTitle); 105 | layout->addLayout(layoutTitle); 106 | 107 | #define XSETUI(name) \ 108 | auto layout##name = new QHBoxLayout; \ 109 | lbl##name->setBuddy(edit##name); \ 110 | lbl##name->setFixedWidth(maxWidth); \ 111 | lbl##name->hide(); \ 112 | edit##name->hide(); \ 113 | regex##name->setText(tr("&Regex")); \ 114 | regex##name->hide(); \ 115 | layout##name->addWidget(lbl##name); \ 116 | layout##name->addWidget(edit##name); \ 117 | layout##name->addWidget(regex##name); \ 118 | layout->addLayout(layout##name); 119 | 120 | XSETUI(Author) 121 | XSETUI(Introduction) 122 | XSETUI(Position) 123 | XSETUI(Bookid) 124 | XSETUI(Publisher) 125 | XSETUI(ISBN) 126 | 127 | lblTitle->setText(tr("Title: ")); 128 | lblAuthor->setText(tr("&Author: ")); 129 | lblIntroduction->setText(tr("&Introduction: ")); 130 | lblPosition->setText(tr("&Position: ")); 131 | lblBookid->setText(tr("&Bookid: ")); 132 | lblPublisher->setText(tr("&Publisher: ")); 133 | lblISBN->setText(tr("&ISBN: ")); 134 | 135 | btnSearch->setDefault(true); 136 | 137 | setLayout(layout); 138 | } 139 | 140 | void WidgetSearchBook::setConnection() { 141 | connect(btnSearch, &QPushButton::clicked, this, &WidgetSearchBook::slotSearch); 142 | connect(btnMore, &QPushButton::clicked, this, &WidgetSearchBook::slotMore); 143 | 144 | #define XENTER(name) \ 145 | connect(name, &QLineEdit::returnPressed, btnSearch, std::bind(&QPushButton::clicked, btnSearch, true)); 146 | 147 | XENTER(editTitle) 148 | XENTER(editAuthor) 149 | XENTER(editIntroduction) 150 | XENTER(editPosition) 151 | XENTER(editBookid) 152 | XENTER(editPublisher) 153 | XENTER(editISBN) 154 | } 155 | -------------------------------------------------------------------------------- /src/client/widget/WidgetSearchBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | class WidgetSearchBook : public QWidget { 15 | Q_OBJECT 16 | 17 | public: 18 | WidgetSearchBook(QWidget *parent); 19 | 20 | signals: 21 | void searchInfo(const X::ptree &pt); 22 | 23 | public slots: 24 | void slotSearch(); 25 | void slotMore(); 26 | 27 | private: 28 | void setUI(); 29 | void setConnection(); 30 | 31 | private: 32 | QLabel *lblTitle; 33 | QLabel *lblAuthor; 34 | QLabel *lblIntroduction; 35 | QLabel *lblPosition; 36 | QLabel *lblBookid; 37 | QLabel *lblPublisher; 38 | QLabel *lblISBN; 39 | 40 | QLineEdit *editTitle; 41 | QLineEdit *editAuthor; 42 | QLineEdit *editIntroduction; 43 | QLineEdit *editPosition; 44 | QLineEdit *editBookid; 45 | QLineEdit *editPublisher; 46 | QLineEdit *editISBN; 47 | 48 | QCheckBox *regexTitle; 49 | QCheckBox *regexAuthor; 50 | QCheckBox *regexIntroduction; 51 | QCheckBox *regexPosition; 52 | QCheckBox *regexBookid; 53 | QCheckBox *regexPublisher; 54 | QCheckBox *regexISBN; 55 | 56 | QPushButton *btnSearch; 57 | QPushButton *btnMore; 58 | }; 59 | -------------------------------------------------------------------------------- /src/client/widget/WidgetSetBook.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | class WidgetSetBook : public QWidget { 24 | Q_OBJECT 25 | 26 | public: 27 | WidgetSetBook(UserManager &userManager, BookManager &bookManager, QWidget *parent = Q_NULLPTR); 28 | void getData(); 29 | 30 | public slots: 31 | void slotUpload(); 32 | 33 | private: 34 | void setUI(); 35 | void setConnection(); 36 | 37 | protected: 38 | UserManager &userManager; 39 | BookManager &bookManager; 40 | 41 | QLabel *lblCover; 42 | QLabel *lblBookid; 43 | QLabel *lblTitle; 44 | QLabel *lblAuthor; 45 | QLabel *lblISBN; 46 | QLabel *lblPublisher; 47 | QLabel *lblIntroduction; 48 | QLabel *lblPriority; 49 | QLabel *lblPosition; 50 | QLabel *lblAmount; 51 | QLabel *lblKeepTime; 52 | QLabel *lblDay; 53 | QLabel *lblHour; 54 | QLabel *lblMinute; 55 | QLabel *lblMessage; 56 | 57 | QLineEdit *editBookid; 58 | QLineEdit *editTitle; 59 | QLineEdit *editAuthor; 60 | QLineEdit *editISBN; 61 | QLineEdit *editPublisher; 62 | QPlainTextEdit *editIntroduction; 63 | QComboBox *cbboxPriority; 64 | QLineEdit *editPosition; 65 | QLineEdit *editAmount; 66 | 67 | QPushButton *btnUploadCover; 68 | QPushButton *btnAdd; 69 | 70 | QSpinBox *spinDay; 71 | QSpinBox *spinHour; 72 | QSpinBox *spinMinute; 73 | 74 | QStringList priorityList; 75 | std::vector priorityInfo; 76 | 77 | X::ptree pt; 78 | Resource cover; 79 | X::xll beforeKeepTime; 80 | }; 81 | -------------------------------------------------------------------------------- /src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(core) 2 | 3 | set(Boost_USE_STATIC_LIBS ON) 4 | set(Boost_USE_MULTITHREADED ON) 5 | set(Boost_USE_STATIC_RUNTIME OFF) 6 | 7 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 8 | set(Boost_USE_RELEASE_LIBS ON) 9 | set(Boost_USE_DEBUG_LIBS OFF) 10 | set(Boost_USE_DEBUG_RUNTIME OFF) 11 | else() 12 | set(Boost_USE_RELEASE_LIBS OFF) 13 | set(Boost_USE_DEBUG_LIBS ON) 14 | set(Boost_USE_DEBUG_RUNTIME ON) 15 | endif() 16 | 17 | find_package(Boost 1.56.0 REQUIRED COMPONENTS system filesystem) 18 | 19 | include_directories(${CMAKE_SOURCE_DIR}/src) 20 | include_directories(${Boost_INCLUDE_DIRS}) 21 | 22 | file(GLOB core_sources *.cpp) 23 | add_library(core ${core_sources}) 24 | 25 | target_link_libraries(core PUBLIC ${Boost_LIBRARIES}) 26 | -------------------------------------------------------------------------------- /src/core/README.md: -------------------------------------------------------------------------------- 1 | # 核心接口 2 | -------------------------------------------------------------------------------- /src/core/Resource.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | Resource::Resource(char *data, const size_t &size) : 12 | data(data), 13 | size(size) { } 14 | 15 | Resource::Resource(const Resource &r) : 16 | data(r.data), 17 | size(r.size) { } 18 | 19 | Resource::Resource(Resource &&r) : 20 | data(std::move(r.data)), 21 | size(std::move(r.size)) { 22 | r.data = nullptr; 23 | r.size = 0; 24 | } 25 | 26 | Resource& Resource::operator = (const Resource &r) { 27 | data = r.data; 28 | size = r.size; 29 | return *this; 30 | } 31 | 32 | Resource& Resource::operator = (Resource &&r) { 33 | data = std::move(r.data); 34 | size = std::move(r.size); 35 | r.data = nullptr; 36 | r.size = 0; 37 | return *this; 38 | } 39 | 40 | char* Resource::getData() { 41 | return data; 42 | } 43 | 44 | const char* Resource::getData() const { 45 | return data; 46 | } 47 | 48 | Resource& Resource::setData(char *data) { 49 | this->data = data; 50 | return *this; 51 | } 52 | 53 | size_t Resource::getSize() const { 54 | return size; 55 | } 56 | 57 | Resource& Resource::setSize(const size_t &size) { 58 | this->size = size; 59 | return *this; 60 | } 61 | 62 | void Resource::clean() { 63 | if (data) { 64 | size = 0; 65 | delete[] data; 66 | } 67 | } 68 | 69 | std::map Resource::resourceTemp {}; 70 | 71 | size_t Resource::fileSize(const xstring &path) { 72 | struct stat statbuff; 73 | if (stat(path.c_str(), &statbuff) >= 0) 74 | return statbuff.st_size; 75 | return 0; 76 | } 77 | 78 | bool Resource::add(const xstring &path, const Resource &file) { 79 | auto f = Resource::copy(file); 80 | boost::filesystem::path p(path); 81 | boost::filesystem::create_directories(p.parent_path()); 82 | FILE *fio = fopen(path.c_str(), "wb"); 83 | if (fio == NULL) 84 | return false; 85 | if (fwrite(f.getData(), f.getSize(), 1, fio) != 1) 86 | return false; 87 | fclose(fio); 88 | auto &t = resourceTemp[path]; 89 | t.clean(); 90 | t = f; 91 | return true; 92 | } 93 | 94 | Resource Resource::get(const xstring &path) { 95 | auto &t = resourceTemp[path]; 96 | FILE *fio = fopen(path.c_str(), "rb"); 97 | if (fio == NULL) { 98 | t.clean(); 99 | return nullptr; 100 | } 101 | if (t.getSize()) 102 | return t; 103 | Resource file; 104 | auto size = fileSize(path); 105 | file.setSize(size) 106 | .setData(new char[size]); 107 | if (fread(file.getData(), size, 1, fio) != 1) 108 | file.clean(); 109 | fclose(fio); 110 | return file; 111 | } 112 | 113 | Resource Resource::copy(const Resource &file) { 114 | char *s = new char[file.size]; 115 | memcpy(s, file.data, file.size); 116 | return Resource(s, file.size); 117 | } 118 | -------------------------------------------------------------------------------- /src/core/Resource.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | class Resource { 11 | public: 12 | typedef X::xll xll; 13 | typedef X::xint xint; 14 | typedef X::xstring xstring; 15 | 16 | Resource(char *data = nullptr, const size_t &size = 0); 17 | Resource(const Resource &r); 18 | Resource(Resource &&r); 19 | Resource& operator = (const Resource &r); 20 | Resource& operator = (Resource &&r); 21 | 22 | char* getData(); 23 | const char* getData() const; 24 | Resource& setData(char *data); 25 | 26 | size_t getSize() const; 27 | Resource& setSize(const size_t &size); 28 | 29 | void clean(); 30 | 31 | static std::map resourceTemp; 32 | 33 | static size_t fileSize(const xstring &path); 34 | static bool add(const xstring &path, const Resource &file); 35 | static Resource get(const xstring &path); 36 | static Resource copy(const Resource &file); 37 | 38 | private: 39 | char *data {}; 40 | size_t size {}; 41 | }; 42 | -------------------------------------------------------------------------------- /src/core/SocketInfo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | const char SocketInfo::IDENTIFIER = -101; 12 | 13 | SocketInfo::SocketInfo() { 14 | size = 0; 15 | buffer = 0; 16 | } 17 | 18 | SocketInfo::~SocketInfo() { 19 | if (buffer) 20 | delete[] buffer; 21 | } 22 | 23 | void SocketInfo::setSize(const size_t &size) { 24 | if (this->size < size) { 25 | if (buffer) 26 | delete[] buffer; 27 | buffer = new char[size]; 28 | this->size = size; 29 | } 30 | } 31 | 32 | size_t SocketInfo::getSize() const { 33 | return size; 34 | } 35 | 36 | SocketInfo::xll SocketInfo::decodeHeaderToken() const { 37 | return *static_cast ((const void *)(buffer)); 38 | } 39 | 40 | SocketInfo::xint SocketInfo::decodeHeaderLength() const { 41 | return *static_cast ((const void *)(buffer + sizeof(xll))); 42 | } 43 | 44 | SocketInfo::ActionCode SocketInfo::decodeHeaderActionCode() const { 45 | return *static_cast ((const void *)(buffer + sizeof(xll) + sizeof(xint))); 46 | } 47 | 48 | void SocketInfo::decodeBody(const xint &length, ptree &pt) const { 49 | std::stringstream ss; 50 | const xstring str(buffer, length); 51 | ss << str; 52 | boost::property_tree::read_json(ss, pt); 53 | } 54 | 55 | void SocketInfo::encodeIndentifier() { 56 | buffer[0] = IDENTIFIER; 57 | } 58 | 59 | void SocketInfo::encodeHeaderToken(const xll &token) { 60 | memcpy(buffer + 1, (const void *)(&token), sizeof(xll)); 61 | } 62 | 63 | void SocketInfo::encodeHeaderLength(const xint &length) { 64 | memcpy(buffer + 1 + sizeof(xll), (const void *)(&length), sizeof(xint)); 65 | } 66 | 67 | void SocketInfo::encodeHeaderActionCode(const ActionCode &ac) { 68 | memcpy(buffer + 1 + sizeof(xll) + sizeof(xint), (const void *)(&ac), sizeof(ActionCode)); 69 | } 70 | 71 | void SocketInfo::encodeBody(const char *data, const size_t &length) { 72 | memcpy(buffer + 1 + sizeof(xll) + sizeof(xint) + sizeof(ActionCode), data, length); 73 | } 74 | 75 | void SocketInfo::encodeFile(const xint &mainLength, const char *data, const size_t &length) { 76 | memcpy(buffer + mainLength, data, length); 77 | } 78 | 79 | void SocketInfo::encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const char *data, const size_t &length) { 80 | encodeIndentifier(); 81 | encodeHeaderToken(token); 82 | encodeHeaderLength(bodyLength); 83 | encodeHeaderActionCode(ac); 84 | encodeBody(data, length); 85 | } 86 | 87 | void SocketInfo::encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const xstring &str) { 88 | encodeMain(token, bodyLength, ac, str.c_str(), str.size()); 89 | } 90 | 91 | void SocketInfo::encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const ptree &pt) { 92 | encodeMain(token, bodyLength, ac, encodePtree(pt)); 93 | } 94 | 95 | SocketInfo::xstring SocketInfo::encodePtree(const ptree &pt, bool pretty) { 96 | std::stringstream ss; 97 | boost::property_tree::write_json(ss, pt, pretty); 98 | return std::move(ss.str()); 99 | } 100 | 101 | void SocketInfo::decodePtree(const xstring &str, ptree &pt) { 102 | std::stringstream ss; 103 | ss << str; 104 | boost::property_tree::read_json(ss, pt); 105 | } 106 | 107 | const char *SocketInfo::getBuffer() const { 108 | return buffer; 109 | } 110 | 111 | char *SocketInfo::getBuffer() { 112 | return buffer; 113 | } 114 | 115 | void SocketInfo::setBuffer(char *buffer) { 116 | this->buffer = buffer; 117 | } 118 | -------------------------------------------------------------------------------- /src/core/SocketInfo.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class SocketInfo { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::ptree ptree; 13 | typedef X::xstring xstring; 14 | typedef X::ActionCode ActionCode; 15 | 16 | enum { 17 | HEADER_SIZE = sizeof(xll) + sizeof(xint) + sizeof(ActionCode), 18 | BODY_SIZE = 2048 19 | }; 20 | static const char IDENTIFIER; 21 | 22 | SocketInfo(); 23 | ~SocketInfo(); 24 | SocketInfo(const SocketInfo &) = delete; 25 | SocketInfo &operator = (const SocketInfo &) = delete; 26 | 27 | void setSize(const size_t &size); 28 | size_t getSize() const; 29 | 30 | xll decodeHeaderToken() const; 31 | xint decodeHeaderLength() const; 32 | ActionCode decodeHeaderActionCode() const; 33 | void decodeBody(const xint &length, ptree &pt) const; 34 | 35 | void encodeIndentifier(); 36 | void encodeHeaderToken(const xll &token); 37 | void encodeHeaderLength(const xint &length); 38 | void encodeHeaderActionCode(const ActionCode &ac); 39 | void encodeBody(const char *data, const size_t &length); 40 | void encodeFile(const xint &mainLength, const char *data, const size_t &length); 41 | void encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const char *data, const size_t &length); 42 | void encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const xstring &str); 43 | void encodeMain(const xll &token, const xint &bodyLength, const ActionCode &ac, const ptree &pt); 44 | 45 | static xstring encodePtree(const ptree &pt, bool pretty = false); 46 | static void decodePtree(const xstring &str, ptree &pt); 47 | 48 | const char *getBuffer() const; 49 | char *getBuffer(); 50 | void setBuffer(char *buffer); 51 | 52 | private: 53 | char *buffer; 54 | size_t size; 55 | }; 56 | -------------------------------------------------------------------------------- /src/core/types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using std::cerr; 12 | 13 | namespace X { 14 | typedef boost::property_tree::ptree ptree; 15 | typedef int32_t xint; 16 | typedef int64_t xll; 17 | typedef std::string xstring; 18 | 19 | enum UserPriority { 20 | USER = 1, 21 | ADMINISTER = 50, 22 | SUPER_ADMINISTER = 100 23 | }; 24 | 25 | enum ErrorCode { 26 | NoError = 0, 27 | 28 | UnknownError, 29 | 30 | InvalidBody, 31 | 32 | LoginFailed, 33 | NoSuchUser, 34 | AlreadyLogin, 35 | 36 | RegisterFailed, 37 | InvalidUsername, 38 | InvalidNickname, 39 | InvalidPassword, 40 | InvalidEmail, 41 | AlreadyRegister, 42 | 43 | ModifyFailed, 44 | InvalidNewPassword, 45 | 46 | NotLogin, 47 | InvalidToken, 48 | 49 | InvalidBook, 50 | NoSuchBook, 51 | 52 | NoRestBook, 53 | AlreadyHave, 54 | NoHave, 55 | InvalidTime, 56 | 57 | AlreadyStar, 58 | NoSuchStar, 59 | 60 | NoPermission, 61 | 62 | InvalidResource, 63 | NoSuchResource 64 | }; 65 | 66 | enum ActionCode { 67 | NoAction = 0, 68 | Error, 69 | Login, 70 | LoginFeedback, 71 | Register, 72 | RegisterFeedback, 73 | Modify, 74 | ModifyFeedback, 75 | Logout, 76 | LogoutFeedback, 77 | BorrowBook, 78 | BorrowBookFeedback, 79 | ReturnBook, 80 | ReturnBookFeedback, 81 | StarBook, 82 | StarBookFeedback, 83 | UnStarBook, 84 | UnStarBookFeedback, 85 | GetBook, 86 | GetBookFeedback, 87 | GetBookBrief, 88 | GetBookBriefFeedback, 89 | SetBook, 90 | SetBookFeedback, 91 | GetLoginRecord, 92 | GetLoginRecordFeedback, 93 | GetStarRecord, 94 | GetStarRecordFeedback, 95 | GetBorrowRecord, 96 | GetBorrowRecordFeedback, 97 | GetBrowseRecord, 98 | GetBrowseRecordFeedback, 99 | GetKeepRecord, 100 | GetKeepRecordFeedback, 101 | GetNewBookList, 102 | GetNewBookListFeedback, 103 | GetBookCover, 104 | GetBookCoverFeedback, 105 | SetBookCover, 106 | SetBookCoverFeedback, 107 | GetSearchBookList, 108 | GetSearchBookListFeedback, 109 | SetPriority, 110 | SetPriorityFeedback, 111 | GetTopBookList, 112 | GetTopBookListFeedback 113 | }; 114 | } 115 | -------------------------------------------------------------------------------- /src/core/utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace X { 11 | bool checkUsername(const xstring &username) { 12 | static const std::regex patternUsername("[\\w\\.\\-]+"); 13 | if (username.size() < 1 || username.size() > 100 || !std::regex_match(username, patternUsername)) 14 | return false; 15 | return true; 16 | } 17 | 18 | bool checkNickname(const xstring &nickname) { 19 | if (nickname.size() < 1 || nickname.size() > 100) 20 | return false; 21 | return true; 22 | } 23 | 24 | bool checkPassword(const xstring &password) { 25 | if (password.size() < 6 || password.size() > 100) 26 | return false; 27 | return true; 28 | } 29 | 30 | bool checkEmail(const xstring &email) { 31 | static const std::regex patternEmail("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+"); 32 | if (email.size() < 5 || email.size() > 100 || !std::regex_match(email, patternEmail)) 33 | return false; 34 | return true; 35 | } 36 | 37 | xstring escape(const xstring &str) { 38 | static const std::regex specialChars(R"([.^$|()\[\]{}*+?\\\&])"); 39 | return std::regex_replace(str, specialChars, R"(\$&)"); 40 | } 41 | 42 | xstring time_to_str(const xll &time) { 43 | time_t t = time; 44 | xstring str = asctime(localtime(&t)); 45 | str.pop_back(); 46 | return str; 47 | } 48 | 49 | void tcp_sync_read(boost::asio::ip::tcp::socket &socket, xll &token, ActionCode &ac, ptree &pt) { 50 | SocketInfo info; 51 | 52 | info.setSize(SocketInfo::HEADER_SIZE); 53 | 54 | boost::asio::read( 55 | socket, 56 | boost::asio::buffer(info.getBuffer(), 1), 57 | boost::asio::transfer_exactly(1) 58 | ); 59 | boost::asio::read( 60 | socket, 61 | boost::asio::buffer(info.getBuffer(), SocketInfo::HEADER_SIZE), 62 | boost::asio::transfer_exactly(SocketInfo::HEADER_SIZE) 63 | ); 64 | 65 | token = info.decodeHeaderToken(); 66 | auto length = info.decodeHeaderLength(); 67 | ac = info.decodeHeaderActionCode(); 68 | 69 | info.setSize(length); 70 | 71 | boost::asio::read( 72 | socket, 73 | boost::asio::buffer(info.getBuffer(), length), 74 | boost::asio::transfer_exactly(length) 75 | ); 76 | 77 | info.decodeBody(length, pt); 78 | } 79 | 80 | Resource tcp_sync_read_with_file(boost::asio::ip::tcp::socket &socket, xll &token, ActionCode &ac, ptree &pt) { 81 | tcp_sync_read(socket, token, ac, pt); 82 | Resource file; 83 | auto size = pt.get("fileSize", 0); 84 | 85 | if (size) { 86 | SocketInfo info; 87 | info.setSize(size); 88 | 89 | boost::asio::read( 90 | socket, 91 | boost::asio::buffer(info.getBuffer(), size), 92 | boost::asio::transfer_exactly(size) 93 | ); 94 | 95 | file.setData(info.getBuffer()).setSize(size); 96 | info.setBuffer(nullptr); 97 | } 98 | return file; 99 | } 100 | 101 | void tcp_sync_write(boost::asio::ip::tcp::socket &socket, const xll &token, const ActionCode &ac, const ptree &pt) { 102 | SocketInfo info; 103 | auto str = SocketInfo::encodePtree(pt); 104 | auto bodySize = xint(str.size()); 105 | auto mainSize = SocketInfo::HEADER_SIZE + 1 + bodySize; 106 | 107 | info.setSize(mainSize); 108 | info.encodeMain(token, bodySize, ac, str); 109 | 110 | boost::asio::write( 111 | socket, 112 | boost::asio::buffer(info.getBuffer(), mainSize) 113 | ); 114 | } 115 | 116 | void tcp_sync_write_with_file(boost::asio::ip::tcp::socket &socket, const xll &token, const ActionCode &ac, const ptree &pt, const Resource &file) { 117 | auto fileSize = file.getSize(); 118 | if (fileSize) { 119 | SocketInfo info; 120 | auto str = SocketInfo::encodePtree(pt); 121 | auto bodySize = xint(str.size()); 122 | auto mainSize = SocketInfo::HEADER_SIZE + 1 + bodySize; 123 | auto size = mainSize + fileSize; 124 | 125 | info.setSize(size); 126 | info.encodeMain(token, bodySize, ac, str); 127 | info.encodeFile(mainSize, file.getData(), fileSize); 128 | 129 | boost::asio::write( 130 | socket, 131 | boost::asio::buffer(info.getBuffer(), size) 132 | ); 133 | } 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /src/core/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace X { 12 | extern bool checkUsername(const xstring &username); 13 | extern bool checkNickname(const xstring &nickname); 14 | extern bool checkPassword(const xstring &password); 15 | extern bool checkEmail(const xstring &email); 16 | extern xstring escape(const xstring &str); 17 | 18 | extern xstring time_to_str(const xll &time); 19 | 20 | extern void tcp_sync_read(boost::asio::ip::tcp::socket &socket, xll &token, ActionCode &ac, ptree &pt); 21 | extern Resource tcp_sync_read_with_file(boost::asio::ip::tcp::socket &socket, xll &token, ActionCode &ac, ptree &pt); 22 | extern void tcp_sync_write(boost::asio::ip::tcp::socket &socket, const xll &token, const ActionCode &ac, const ptree &pt); 23 | extern void tcp_sync_write_with_file(boost::asio::ip::tcp::socket &socket, const xll &token, const ActionCode &ac, const ptree &pt, const Resource &file); 24 | } -------------------------------------------------------------------------------- /src/core/values.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | namespace X { 7 | const xstring AUTHOR[] = {"xalanq", "chang-ran"}; 8 | const xstring EMAIL[] = {"xalanq@gmail.com", "chang-r17@mails.tsinghua.edu.cn"}; 9 | const xstring &WEBSITE = "blog.xalanq.com"; 10 | const xstring &GITHUB = "github.com/xalanq/PiLibrary"; 11 | } -------------------------------------------------------------------------------- /src/core/values.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace X { 9 | extern const xstring AUTHOR[]; 10 | extern const xstring EMAIL[]; 11 | extern const xstring &WEBSITE; 12 | extern const xstring &GITHUB; 13 | } -------------------------------------------------------------------------------- /src/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(server) 2 | 3 | set(Boost_USE_STATIC_LIBS ON) 4 | set(Boost_USE_MULTITHREADED ON) 5 | set(Boost_USE_STATIC_RUNTIME OFF) 6 | 7 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 8 | set(Boost_USE_RELEASE_LIBS ON) 9 | set(Boost_USE_DEBUG_LIBS OFF) 10 | set(Boost_USE_DEBUG_RUNTIME OFF) 11 | else() 12 | set(Boost_USE_RELEASE_LIBS OFF) 13 | set(Boost_USE_DEBUG_LIBS ON) 14 | set(Boost_USE_DEBUG_RUNTIME ON) 15 | endif() 16 | 17 | find_package(Boost 1.56.0 REQUIRED COMPONENTS regex date_time system thread) 18 | 19 | if (BUILD_STATIC_X) 20 | find_package(libmongocxx-static 3.2.0 REQUIRED) 21 | else() 22 | find_package(libmongocxx 3.2.0 REQUIRED) 23 | endif() 24 | 25 | include_directories(${CMAKE_SOURCE_DIR}/src) 26 | include_directories(${Boost_INCLUDE_DIRS}) 27 | 28 | file(GLOB_RECURSE server_sources *.cpp) 29 | add_executable(server ${server_sources}) 30 | 31 | target_link_libraries(server PUBLIC ${Boost_LIBRARIES}) 32 | target_link_libraries(server PUBLIC core) 33 | 34 | if (BUILD_STATIC_X) 35 | target_include_directories(server PUBLIC ${LIBMONGOCXX_STATIC_INCLUDE_DIRS}) 36 | target_link_libraries(server PUBLIC ${LIBMONGOCXX_STATIC_LIBRARIES}) 37 | target_compile_definitions(server PUBLIC ${LIBMONGOCXX_STATIC_DEFINITIONS}) 38 | 39 | list(FIND LIBMONGOCXX_STATIC_DEFINITIONS "BSONCXX_STATIC" LIST_IDX) 40 | if (${LIST_IDX} EQUAL -1) 41 | message(FATAL_ERROR "Expected BSONCXX_STATIC to be defined") 42 | endif() 43 | list(FIND LIBMONGOCXX_STATIC_DEFINITIONS "MONGOCXX_STATIC" LIST_IDX) 44 | if (${LIST_IDX} EQUAL -1) 45 | message(FATAL_ERROR "Expected MONGOCXX_STATIC to be defined") 46 | endif() 47 | else() 48 | target_include_directories(server PUBLIC ${LIBMONGOCXX_INCLUDE_DIRS}) 49 | target_link_libraries(server PUBLIC ${LIBMONGOCXX_LIBRARIES}) 50 | target_compile_definitions(server PUBLIC ${LIBMONGOCXX_DEFINITIONS}) 51 | 52 | list(FIND LIBMONGOCXX_DEFINITIONS "BSONCXX_STATIC" LIST_IDX) 53 | if (${LIST_IDX} GREATER -1) 54 | message(FATAL_ERROR "Expected BSONCXX_STATIC to not be defined") 55 | endif() 56 | list(FIND LIBMONGOCXX_DEFINITIONS "MONGOCXX_STATIC" LIST_IDX) 57 | if (${LIST_IDX} GREATER -1) 58 | message(FATAL_ERROR "Expected MONGOCXX_STATIC to not be defined") 59 | endif() 60 | endif() -------------------------------------------------------------------------------- /src/server/README.md: -------------------------------------------------------------------------------- 1 | # 服务端 2 | 3 | Boost.Asio + MongoDB -------------------------------------------------------------------------------- /src/server/core/Server.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | using std::cout; 11 | 12 | Server::Server(boost::asio::io_service &service, const ptree &config) : 13 | acceptor(service, boost::asio::ip::tcp::endpoint( 14 | boost::asio::ip::address::from_string(config.get ("server_url")), 15 | config.get ("server_port"))), 16 | socket( 17 | service), 18 | thread_number( 19 | config.get ("thread_number")), 20 | userManager( 21 | config.get ("mongodb_url"), 22 | config.get ("mongodb_db_name")), 23 | sessionManager( 24 | config.get ("default_alive_ms")) { 25 | } 26 | 27 | void Server::start(const ptree &config) { 28 | xint thread_number = config.get("thread_number"); 29 | 30 | cout << "Listening: " << config.get ("server_url") << ":" << config.get ("server_port") << '\n'; 31 | cout << "mongo_url: " << config.get("mongodb_url") << '\n'; 32 | cout << "mongo_db_name: " << config.get("mongodb_db_name") << '\n'; 33 | cout << "Thread number: " << thread_number << '\n'; 34 | cout << "Default alive time: " << config.get ("default_alive_ms") << " ms\n"; 35 | 36 | boost::asio::io_service service; 37 | Server server(service, config); 38 | server.start(); 39 | 40 | for (int i = 0; i < thread_number - 1; ++i) { 41 | boost::thread( 42 | [&service]() { 43 | service.run(); 44 | } 45 | ); 46 | } 47 | service.run(); 48 | cout << "done\n"; 49 | } 50 | 51 | void Server::start() { 52 | initRoot(); 53 | doAccept(); 54 | } 55 | 56 | void Server::doAccept() { 57 | acceptor.async_accept(socket, 58 | [this](const error_code &ec) { 59 | if (!ec) { 60 | try { 61 | std::make_shared (std::move(socket), sessionManager, userManager)->start(); 62 | } catch (std::exception &e) { 63 | cerr << "Error Message: " << e.what() << '\n'; 64 | } 65 | } 66 | doAccept(); 67 | } 68 | ); 69 | } 70 | 71 | void Server::initRoot() { 72 | cout << "Linking mongodb...\n"; 73 | try { 74 | bool empty = userManager.isDBEmpty(); 75 | cout << "Mongodb is available!\n"; 76 | if (empty) { 77 | cout << "\n=============Attention=============\n"; 78 | cout << "Database is empty, create a Super Administer user.\n"; 79 | cout << "Username: \t\t PiRoot\n"; 80 | cout << "Default Password: \t pi123456\n"; 81 | cout << "Please change the password as soon as possible.\n"; 82 | cout << "===================================\n\n"; 83 | ptree pt; 84 | pt.put("username", "PiRoot"); 85 | pt.put("nickname", "root"); 86 | pt.put("password", "2d515aaf7a77cb6744bf91a49af70928bfb9f04b"); 87 | pt.put("email", "root@pi.com"); 88 | userManager.registerUser(pt, X::SUPER_ADMINISTER); 89 | } 90 | } catch (std::exception &e) { 91 | cout << "Error: Mongodb is unavailable! Please checkout the mongodb's uri.\n"; 92 | cout << "Error Message: " << e.what() << '\n'; 93 | exit(0); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/server/core/Server.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class Server { 17 | public: 18 | typedef boost::system::system_error system_error; 19 | typedef boost::system::error_code error_code; 20 | typedef X::xll xll; 21 | typedef X::xint xint; 22 | typedef X::ptree ptree; 23 | typedef X::xstring xstring; 24 | 25 | Server(boost::asio::io_service &service, const ptree &config); 26 | static void start(const ptree &config); 27 | 28 | private: 29 | void start(); 30 | void doAccept(); 31 | void initRoot(); 32 | 33 | boost::asio::ip::tcp::acceptor acceptor; 34 | boost::asio::ip::tcp::socket socket; 35 | xint thread_number; 36 | UserManager userManager; 37 | SessionManager sessionManager; 38 | }; 39 | -------------------------------------------------------------------------------- /src/server/core/Session.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | 8 | Session::Session(const xll &token, const xint &userid, const xll &alive, const xint &priority) : 9 | token(token), 10 | userid(userid), 11 | alive(alive), 12 | priority(priority) { 13 | 14 | } 15 | 16 | Session::xll Session::getNowTime() { 17 | return time(0); 18 | } 19 | 20 | Session::xll Session::getToken() const { 21 | return token; 22 | } 23 | 24 | void Session::setToken(const xll &value) { 25 | token = value; 26 | } 27 | 28 | Session::xint Session::getUserid() const { 29 | return userid; 30 | } 31 | 32 | void Session::setUserid(const xint &value) { 33 | userid = value; 34 | } 35 | 36 | Session::xll Session::getAlive() const { 37 | return alive; 38 | } 39 | 40 | void Session::setAlive(const xll &value) { 41 | alive = value; 42 | } 43 | 44 | Session::xint Session::getPriority() const { 45 | return priority; 46 | } 47 | 48 | void Session::setPriority(const xint &value) { 49 | priority = value; 50 | } 51 | -------------------------------------------------------------------------------- /src/server/core/Session.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | class Session { 9 | public: 10 | typedef X::xll xll; 11 | typedef X::xint xint; 12 | typedef X::xstring xstring; 13 | 14 | Session(const xll &token = 0, const xint &userid = 0, const xll &alive = 0, const xint &priority = 0); 15 | 16 | static xll getNowTime(); 17 | 18 | xll getToken() const; 19 | void setToken(const xll &value); 20 | 21 | xint getUserid() const; 22 | void setUserid(const xint &value); 23 | 24 | xll getAlive() const; 25 | void setAlive(const xll &value); 26 | 27 | xint getPriority() const; 28 | void setPriority(const xint &value); 29 | 30 | private: 31 | xll token; 32 | xint userid; 33 | xll alive; 34 | xint priority; 35 | }; 36 | -------------------------------------------------------------------------------- /src/server/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | int main() { 18 | cout << "===================================\n"; 19 | cout << X::APP_NAME << " v" << X::VERSION << '\n'; 20 | cout << "Author: " << X::AUTHOR[0] << ", " << X::AUTHOR[1] << '\n'; 21 | cout << "Website: " << X::WEBSITE << '\n'; 22 | cout << "GitHub: " << X::GITHUB << '\n'; 23 | cout << "===================================\n"; 24 | cout << '\n'; 25 | 26 | mongocxx::instance _ {}; 27 | boost::property_tree::ptree config; 28 | 29 | ifstream f("config.json"); 30 | if (f) 31 | boost::property_tree::read_json("config.json", config); 32 | else 33 | cout << "Config file is not exist, create new one[./config.json]\n"; 34 | if (!config.get_optional("server_url")) 35 | config.put("server_url", "127.0.0.1"); 36 | if (!config.get_optional("server_port")) 37 | config.put("server_port", 2333); 38 | if (!config.get_optional("mongodb_url")) 39 | config.put("mongodb_url", "mongodb://localhost:23332/?minPoolSize=32&maxPoolSize=32"); 40 | if (!config.get_optional("mongodb_db_name")) 41 | config.put("mongodb_db_name", "pi"); 42 | if (!config.get_optional("default_alive_ms")) 43 | config.put("default_alive_ms", 30000ll); 44 | if (!config.get_optional("thread_number")) 45 | config.put("thread_number", 32); 46 | boost::property_tree::write_json("config.json", config); 47 | Server::start(config); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /src/server/manager/SessionManager.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | SessionManager::SessionManager(const xll &defaultAlive) : 7 | eng(std::random_device()()), 8 | defaultAlive(defaultAlive) { 9 | } 10 | 11 | void SessionManager::removeExpired() { 12 | boost::upgrade_lock _lock(_access); 13 | boost::upgrade_to_unique_lock _uniqueLock(_lock); 14 | for (; dataAlive.size(); ) { 15 | auto p = *dataAlive.begin(); 16 | if (p->getAlive() < Session::getNowTime()) 17 | remove(p); 18 | else 19 | break; 20 | } 21 | } 22 | 23 | bool SessionManager::add(const SessionManager::ptr &p, bool force) { 24 | removeExpired(); 25 | if (force) { 26 | auto it = findUserid(p->getUserid()); 27 | if (it != nullptr) 28 | remove(it); 29 | } 30 | boost::upgrade_lock _lock(_access); 31 | boost::upgrade_to_unique_lock _uniqueLock(_lock); 32 | auto pr = dataToken.insert(p); 33 | dataAlive.insert(p); 34 | dataUserid.insert(p); 35 | return pr.second; 36 | } 37 | 38 | bool SessionManager::add(const Session &session, bool force) { 39 | auto p = std::make_shared (session); 40 | return add(p, force); 41 | } 42 | 43 | bool SessionManager::add(const xll &token, const xint &userid, const xll &alive, const xint &priority, bool force) { 44 | auto p = std::make_shared (token, userid, alive, priority); 45 | return add(p, force); 46 | } 47 | 48 | bool SessionManager::remove(const SessionManager::ptr &p) { 49 | boost::upgrade_lock _lock(_access); 50 | boost::upgrade_to_unique_lock _uniqueLock(_lock); 51 | try { 52 | dataAlive.erase(p); 53 | dataToken.erase(p); 54 | dataUserid.erase(p); 55 | } catch (std::exception &e) { 56 | cerr << "(remove)" << e.what() << '\n'; 57 | return 0; 58 | } 59 | return 1; 60 | } 61 | 62 | bool SessionManager::removeByToken(const xll &token) { 63 | auto p = findToken(token); 64 | if (p == nullptr) 65 | return 0; 66 | return remove(p); 67 | } 68 | 69 | bool SessionManager::removeByUserid(const xint &userid) { 70 | auto p = findUserid(userid); 71 | if (p == nullptr) 72 | return 0; 73 | return remove(p); 74 | } 75 | 76 | bool SessionManager::setAliveTime(const xll &token, const xll &alive) { 77 | auto p = findToken(token); 78 | if (p == nullptr) 79 | return 0; 80 | if (!remove(p)) 81 | return 0; 82 | p->setAlive(alive); 83 | if (alive < Session::getNowTime()) 84 | return 0; 85 | return add(p); 86 | } 87 | 88 | SessionManager::ptr SessionManager::findToken(const xll &token) { 89 | auto p = std::make_shared (token); 90 | removeExpired(); 91 | boost::shared_lock _lock(_access); 92 | auto it = dataToken.find(p); 93 | if (it == dataToken.end()) 94 | return nullptr; 95 | return *it; 96 | } 97 | 98 | SessionManager::ptr SessionManager::findUserid(const xint &userid) { 99 | auto p = std::make_shared (0, userid); 100 | removeExpired(); 101 | boost::shared_lock _lock(_access); 102 | auto it = dataUserid.find(p); 103 | if (it == dataUserid.end()) 104 | return nullptr; 105 | return *it; 106 | } 107 | 108 | SessionManager::xll SessionManager::getRandToken() { 109 | auto getter = [this] { 110 | xll token = distr(eng); 111 | for (; token == 0; ++token); 112 | return token; 113 | }; 114 | xll token = getter(); 115 | for (; findToken(token) != nullptr; token = getter()); 116 | return token; 117 | } 118 | 119 | SessionManager::xll SessionManager::getDefaultAlive() const { 120 | return defaultAlive; 121 | } 122 | -------------------------------------------------------------------------------- /src/server/manager/SessionManager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | class SessionManager { 17 | public: 18 | typedef X::xll xll; 19 | typedef X::xint xint; 20 | typedef X::xstring xstring; 21 | typedef std::shared_ptr ptr; 22 | 23 | SessionManager(const xll &defaultAlive); 24 | void removeExpired(); 25 | 26 | bool add(const ptr &p, bool force = false); 27 | bool add(const Session &session, bool force = false); 28 | bool add(const xll &token, const xint &userid, const xll &alive, const xint &priority, bool force = false); 29 | 30 | bool remove(const ptr &p); 31 | bool removeByToken(const xll &token); 32 | bool removeByUserid(const xint &userid); 33 | 34 | bool setAliveTime(const xll &token, const xll &alive); 35 | 36 | ptr findToken(const xll &token); 37 | ptr findUserid(const xint &userid); 38 | 39 | xll getRandToken(); 40 | 41 | xll getDefaultAlive() const; 42 | 43 | struct compareAlive { 44 | bool operator () (const ptr &a, const ptr &b) const { 45 | return a->getAlive() < b->getAlive(); 46 | } 47 | }; 48 | struct compareToken { 49 | bool operator () (const ptr &a, const ptr &b) const { 50 | return a->getToken() < b->getToken(); 51 | } 52 | }; 53 | struct compareUserid { 54 | bool operator () (const ptr &a, const ptr &b) const { 55 | return a->getUserid() < b->getUserid(); 56 | } 57 | }; 58 | 59 | private: 60 | std::multiset dataAlive; 61 | std::set dataToken; 62 | std::set dataUserid; 63 | std::uniform_int_distribution distr; 64 | std::mt19937_64 eng; 65 | xll defaultAlive; 66 | boost::shared_mutex _access; 67 | }; 68 | -------------------------------------------------------------------------------- /src/server/manager/SocketManager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // one read and one write as a turn 15 | class SocketManager : public std::enable_shared_from_this { 16 | public: 17 | typedef boost::system::system_error system_error; 18 | typedef boost::system::error_code error_code; 19 | typedef X::xll xll; 20 | typedef X::xint xint; 21 | typedef X::ptree ptree; 22 | typedef X::xstring xstring; 23 | typedef X::ErrorCode ErrorCode; 24 | typedef X::ActionCode ActionCode; 25 | 26 | SocketManager(boost::asio::ip::tcp::socket socket, SessionManager &sessionManager, UserManager &userManager); 27 | void start(); 28 | void stop(); 29 | 30 | private: 31 | void read(); 32 | void readHeader(); 33 | void readBody(const xll &token, const xint &length, const ActionCode &ac); 34 | 35 | void write(const ErrorCode &ec, const ActionCode &ac = X::NoAction, const xll &token = 0, ptree pt = ptree(), const Resource &file = Resource()); 36 | 37 | void saveFile(const ErrorCode &ec, const ActionCode &ac, const xll &token, const ptree &pt); 38 | 39 | void doLogin(const ptree &pt, const xll &token); 40 | void doRegister(const ptree &pt, const xll &token); 41 | void doLogout(const ptree &, const xll &token); 42 | void doModify(ptree pt, const xll &token); 43 | 44 | void doBorrowBook(ptree pt, const xll &token); 45 | void doReturnBook(ptree pt, const xll &token); 46 | 47 | void doStarBook(ptree pt, const xll &token); 48 | void doUnStarBook(ptree pt, const xll &token); 49 | 50 | void doGetBook(ptree pt, const xll &token); 51 | void doGetBookBrief(ptree pt, const xll &token); 52 | void doSetBook(ptree pt, const xll &token); 53 | 54 | void doGetRecord(ptree pt, const xll &token, const xstring &type, const ActionCode &feedback); 55 | 56 | void doGetNewBookList(ptree pt, const xll &token); 57 | 58 | void doGetBookCover(ptree pt, const xll &token); 59 | void doSetBookCover(ptree pt, const xll &token); 60 | 61 | void doGetSearchBookList(ptree pt, const xll &token); 62 | 63 | void doSetPriority(ptree pt, const xll &token); 64 | 65 | void doGetTopBookList(ptree pt, const xll &token); 66 | 67 | boost::asio::ip::tcp::socket socket; 68 | SocketInfo info; 69 | SessionManager &sessionManager; 70 | UserManager &userManager; 71 | }; 72 | -------------------------------------------------------------------------------- /src/server/manager/UserManager.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | namespace mongo { 23 | using bsoncxx::builder::stream::array; 24 | using bsoncxx::builder::stream::close_array; 25 | using bsoncxx::builder::stream::close_document; 26 | using bsoncxx::builder::stream::document; 27 | using bsoncxx::builder::stream::finalize; 28 | using bsoncxx::builder::basic::kvp; 29 | using bsoncxx::builder::basic::make_document; 30 | using bsoncxx::builder::basic::make_array; 31 | using bsoncxx::builder::stream::open_array; 32 | using bsoncxx::builder::stream::open_document; 33 | using bsoncxx::stdx::string_view; 34 | using mongocxx::client; 35 | using mongocxx::collection; 36 | using mongocxx::pool; 37 | using mongocxx::pipeline; 38 | using mongocxx::uri; 39 | using mongocxx::validation_criteria; 40 | } 41 | 42 | class UserManager { 43 | public: 44 | typedef X::xll xll; 45 | typedef X::xint xint; 46 | typedef X::ptree ptree; 47 | typedef X::xstring xstring; 48 | typedef X::ErrorCode ErrorCode; 49 | 50 | UserManager(const xstring &mongo_url, const xstring &mongo_db_name); 51 | 52 | bool isDBEmpty(); 53 | 54 | bool isUser(const xint &userid); 55 | bool isUser(const xstring &username); 56 | 57 | xint getPriority(const xint &userid); 58 | 59 | ptree loginUser(const ptree &pt); 60 | ErrorCode registerUser(const ptree &pt, int priority = X::USER); 61 | ErrorCode modifyUser(const ptree &pt); 62 | 63 | ErrorCode borrowBook(const ptree &pt); 64 | ErrorCode returnBook(const ptree &pt); 65 | 66 | ErrorCode starBook(const ptree &pt); 67 | ErrorCode unStarBook(const ptree &pt); 68 | 69 | ptree getBook(const ptree &pt); 70 | ptree getBookBrief(const ptree &pt); 71 | ErrorCode setBook(const ptree &pt); 72 | 73 | ptree getRecord(const ptree &pt); 74 | 75 | ptree getNewBookList(const ptree &pt); 76 | 77 | xstring getResource(const ptree &pt); 78 | ErrorCode setResource(const ptree &pt); 79 | 80 | ptree getSearchBookList(const ptree &pt); 81 | 82 | ErrorCode setPriority(const ptree &pt); 83 | 84 | ptree getTopBookList(const ptree &pt); 85 | 86 | // not open for user, so ensure the userid exists in the below methods 87 | void recordLogin(const ptree &pt); 88 | 89 | private: 90 | mongo::pool pool; 91 | xstring _db_name; 92 | const char *db_name; 93 | }; 94 | -------------------------------------------------------------------------------- /src/server/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace X { 9 | extern xstring what(const ErrorCode &ec); 10 | extern xstring what(const ActionCode &ac); 11 | } -------------------------------------------------------------------------------- /src/server/values.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | namespace X { 7 | const xstring &APP_NAME = "PiLibrary Server"; 8 | const xstring &VERSION = "1.0.0"; 9 | } 10 | -------------------------------------------------------------------------------- /src/server/values.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace X { 9 | extern const xstring &APP_NAME; 10 | extern const xstring &VERSION; 11 | } 12 | -------------------------------------------------------------------------------- /src/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(testServer) 2 | 3 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/test) 4 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/bin/test) 5 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/bin/test) 6 | 7 | file(COPY "book" DESTINATION "${CMAKE_SOURCE_DIR}/bin/test/") 8 | 9 | set(Boost_USE_STATIC_LIBS ON) 10 | set(Boost_USE_MULTITHREADED ON) 11 | set(Boost_USE_STATIC_RUNTIME OFF) 12 | 13 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 14 | set(Boost_USE_RELEASE_LIBS ON) 15 | set(Boost_USE_DEBUG_LIBS OFF) 16 | set(Boost_USE_DEBUG_RUNTIME OFF) 17 | else() 18 | set(Boost_USE_RELEASE_LIBS OFF) 19 | set(Boost_USE_DEBUG_LIBS ON) 20 | set(Boost_USE_DEBUG_RUNTIME ON) 21 | endif() 22 | 23 | find_package(Boost 1.56.0 REQUIRED COMPONENTS regex date_time system thread) 24 | 25 | include_directories(${CMAKE_SOURCE_DIR}/src) 26 | include_directories(${Boost_INCLUDE_DIRS}) 27 | 28 | add_executable(testServer1 testServer1.cpp ../server/utils.cpp) 29 | add_executable(testServer2 testServer2.cpp ../server/utils.cpp) 30 | add_executable(testServer3 testServer3.cpp ../server/utils.cpp) 31 | add_executable(testServer4 testServer4.cpp ../server/utils.cpp) 32 | 33 | target_link_libraries(testServer1 PUBLIC ${Boost_LIBRARIES}) 34 | target_link_libraries(testServer1 PUBLIC core) 35 | target_link_libraries(testServer2 PUBLIC ${Boost_LIBRARIES}) 36 | target_link_libraries(testServer2 PUBLIC core) 37 | target_link_libraries(testServer3 PUBLIC ${Boost_LIBRARIES}) 38 | target_link_libraries(testServer3 PUBLIC core) 39 | target_link_libraries(testServer4 PUBLIC ${Boost_LIBRARIES}) 40 | target_link_libraries(testServer4 PUBLIC core) 41 | -------------------------------------------------------------------------------- /src/test/book/1/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/1/cover.jpg -------------------------------------------------------------------------------- /src/test/book/10/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/10/cover.jpg -------------------------------------------------------------------------------- /src/test/book/11/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/11/cover.jpg -------------------------------------------------------------------------------- /src/test/book/12/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/12/cover.jpg -------------------------------------------------------------------------------- /src/test/book/13/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/13/cover.jpg -------------------------------------------------------------------------------- /src/test/book/14/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/14/cover.jpg -------------------------------------------------------------------------------- /src/test/book/15/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/15/cover.jpg -------------------------------------------------------------------------------- /src/test/book/16/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/16/cover.jpg -------------------------------------------------------------------------------- /src/test/book/17/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/17/cover.jpg -------------------------------------------------------------------------------- /src/test/book/18/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/18/cover.jpg -------------------------------------------------------------------------------- /src/test/book/19/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/19/cover.jpg -------------------------------------------------------------------------------- /src/test/book/2/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/2/cover.jpg -------------------------------------------------------------------------------- /src/test/book/20/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/20/cover.jpg -------------------------------------------------------------------------------- /src/test/book/21/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/21/cover.jpg -------------------------------------------------------------------------------- /src/test/book/22/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/22/cover.jpg -------------------------------------------------------------------------------- /src/test/book/3/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/3/cover.jpg -------------------------------------------------------------------------------- /src/test/book/4/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/4/cover.jpg -------------------------------------------------------------------------------- /src/test/book/5/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/5/cover.jpg -------------------------------------------------------------------------------- /src/test/book/6/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/6/cover.jpg -------------------------------------------------------------------------------- /src/test/book/7/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/7/cover.jpg -------------------------------------------------------------------------------- /src/test/book/8/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/8/cover.jpg -------------------------------------------------------------------------------- /src/test/book/9/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xalanq/PiLibrary/5d2a9614ab109a475b4499ebcfe3c60ec804445e/src/test/book/9/cover.jpg -------------------------------------------------------------------------------- /src/test/testServer1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 xalanq, chang-ran 2 | // License: LGPL v3.0 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using boost::asio::ip::tcp; 10 | boost::asio::io_service io_service; 11 | tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 2333); 12 | 13 | typedef X::xll xll; 14 | typedef X::xint xint; 15 | typedef X::ptree ptree; 16 | typedef X::xstring xstring; 17 | typedef X::ActionCode ActionCode; 18 | typedef X::ErrorCode ErrorCode; 19 | 20 | // for login, logout, register 21 | int main() { 22 | srand(time(0) + clock()); 23 | try { 24 | for (int op; std::cin >> op; ) { 25 | tcp::socket s(io_service); 26 | xll token = 0; 27 | ptree pt; 28 | ActionCode ac = X::NoAction; 29 | 30 | cerr << "connect to " << ep.address() << ":" << 2333 << '\n'; 31 | s.connect(ep); 32 | 33 | if (op == 1) { 34 | // login 35 | pt.put("username", "xalanq" + std::to_string(rand() % 10)); 36 | pt.put("password", "e472685f5f963edaaae04708972d6442e4b397e3"); 37 | cerr << "Login send\n" << "token: " << token << "\n" << SocketInfo::encodePtree(pt, true) << '\n'; 38 | 39 | X::tcp_sync_write(s, 0, X::Login, pt); 40 | pt = ptree(); 41 | X::tcp_sync_read(s, token, ac, pt); 42 | 43 | cerr << "token: " << token << ", action_code: " << X::what(ac) << '\n' << SocketInfo::encodePtree(pt, true) << '\n'; 44 | 45 | 46 | // logout 47 | pt = ptree(); 48 | cerr << "Logout send\n" << "token: " << token << "\n" << SocketInfo::encodePtree(pt, true) << '\n'; 49 | 50 | X::tcp_sync_write(s, token, X::Logout, pt); 51 | pt = ptree(); 52 | X::tcp_sync_read(s, token, ac, pt); 53 | 54 | cerr << "token: " << token << ", action_code: " << X::what(ac) << '\n' << SocketInfo::encodePtree(pt, true) << '\n'; 55 | } else { 56 | // register 57 | pt.put("username", "xalanq" + std::to_string(rand() % 10)); 58 | pt.put("nickname", "Alan Clarke"); 59 | pt.put("password", "e472685f5f963edaaae04708972d6442e4b397e3"); 60 | pt.put("email", "xalanq@gmail.com"); 61 | cerr << "Register send\n" << "token: " << token << "\n" << SocketInfo::encodePtree(pt, true) << '\n'; 62 | 63 | X::tcp_sync_write(s, 0, X::Register, pt); 64 | pt = ptree(); 65 | X::tcp_sync_read(s, token, ac, pt); 66 | 67 | cerr << "token: " << token << ", action_code: " << X::what(ac) << '\n' << SocketInfo::encodePtree(pt, true) << '\n'; 68 | } 69 | s.close(); 70 | } 71 | } catch (std::exception &e) { 72 | cerr << e.what() << '\n'; 73 | } 74 | 75 | return 0; 76 | } --------------------------------------------------------------------------------