diff options
Diffstat (limited to 'include')
31 files changed, 2338 insertions, 0 deletions
diff --git a/include/ChatPage.h b/include/ChatPage.h new file mode 100644 index 00000000..c3fa6bf6 --- /dev/null +++ b/include/ChatPage.h @@ -0,0 +1,88 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CHATPAGE_H +#define CHATPAGE_H + +#include <QByteArray> +#include <QNetworkAccessManager> +#include <QPixmap> +#include <QTimer> +#include <QWidget> + +#include "HistoryViewManager.h" +#include "MatrixClient.h" +#include "RoomInfo.h" +#include "RoomList.h" +#include "TextInputWidget.h" +#include "TopRoomBar.h" +#include "UserInfoWidget.h" + +namespace Ui +{ +class ChatPage; +} + +class ChatPage : public QWidget +{ + Q_OBJECT + +public: + explicit ChatPage(QWidget *parent = 0); + ~ChatPage(); + + // Initialize all the components of the UI. + void bootstrap(QString userid, QString homeserver, QString token); + +public slots: + // Updates the user info box. + void updateOwnProfileInfo(QUrl avatar_url, QString display_name); + void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url); + void initialSyncCompleted(SyncResponse response); + void syncCompleted(SyncResponse response); + void changeTopRoomInfo(const RoomInfo &info); + void sendTextMessage(const QString &msg); + void messageSent(const QString event_id, int txn_id); + void startSync(); + +private: + Ui::ChatPage *ui; + + void setOwnAvatar(QByteArray img); + + RoomList *room_list_; + HistoryViewManager *view_manager_; + + TopRoomBar *top_bar_; + TextInputWidget *text_input_; + + QTimer *sync_timer_; + int sync_interval_; + + RoomInfo current_room_; + QMap<QString, QPixmap> room_avatars_; + + UserInfoWidget *user_info_widget_; + + // Matrix client + MatrixClient *matrix_client_; + + // Used for one off media requests. + QNetworkAccessManager *content_downloader_; +}; + +#endif // CHATPAGE_H diff --git a/include/Deserializable.h b/include/Deserializable.h new file mode 100644 index 00000000..6a9b4cd5 --- /dev/null +++ b/include/Deserializable.h @@ -0,0 +1,52 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DESERIALIZABLE_H +#define DESERIALIZABLE_H + +#include <exception> + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonValue> + +class DeserializationException : public std::exception +{ +public: + explicit DeserializationException(const std::string &msg); + virtual const char *what() const throw(); + +private: + std::string msg_; +}; + +// JSON response structs need to implement the interface. +class Deserializable +{ +public: + virtual void deserialize(QJsonValue) throw(DeserializationException) + { + } + virtual void deserialize(QJsonObject) throw(DeserializationException) + { + } + virtual void deserialize(QJsonDocument) throw(DeserializationException) + { + } +}; + +#endif diff --git a/include/HistoryView.h b/include/HistoryView.h new file mode 100644 index 00000000..9266d6ac --- /dev/null +++ b/include/HistoryView.h @@ -0,0 +1,62 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HISTORY_VIEW_H +#define HISTORY_VIEW_H + +#include <QHBoxLayout> +#include <QList> +#include <QScrollArea> +#include <QVBoxLayout> +#include <QWidget> + +#include "HistoryViewItem.h" +#include "Sync.h" + +class HistoryView : public QWidget +{ + Q_OBJECT + +public: + explicit HistoryView(QWidget *parent = 0); + explicit HistoryView(QList<Event> events, QWidget *parent = 0); + ~HistoryView(); + + void addHistoryItem(Event event, QString color, bool with_sender); + void addEvents(const QList<Event> &events); + +public slots: + void sliderRangeChanged(int min, int max); + +private: + static const QList<QString> COLORS; + + void init(); + + QString chooseRandomColor(); + + QVBoxLayout *top_layout_; + QVBoxLayout *scroll_layout_; + + QScrollArea *scroll_area_; + QWidget *scroll_widget_; + + QString last_sender_; + QMap<QString, QString> nick_colors_; +}; + +#endif // HISTORY_VIEW_H diff --git a/include/HistoryViewItem.h b/include/HistoryViewItem.h new file mode 100644 index 00000000..b817194b --- /dev/null +++ b/include/HistoryViewItem.h @@ -0,0 +1,41 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HISTORY_VIEW_ITEM_H +#define HISTORY_VIEW_ITEM_H + +#include <QHBoxLayout> +#include <QLabel> +#include <QWidget> + +#include "Sync.h" + +class HistoryViewItem : public QWidget +{ + Q_OBJECT +public: + HistoryViewItem(Event event, bool with_sender, QString color, QWidget *parent = 0); + ~HistoryViewItem(); + +private: + QHBoxLayout *top_layout_; + + QLabel *time_label_; + QLabel *content_label_; +}; + +#endif // HISTORY_VIEW_ITEM_H diff --git a/include/HistoryViewManager.h b/include/HistoryViewManager.h new file mode 100644 index 00000000..8405d005 --- /dev/null +++ b/include/HistoryViewManager.h @@ -0,0 +1,47 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HISTORY_VIEW_MANAGER_H +#define HISTORY_VIEW_MANAGER_H + +#include <QDebug> +#include <QStackedWidget> +#include <QWidget> + +#include "HistoryView.h" +#include "RoomInfo.h" +#include "Sync.h" + +class HistoryViewManager : public QStackedWidget +{ + Q_OBJECT + +public: + HistoryViewManager(QWidget *parent); + ~HistoryViewManager(); + + void initialize(const Rooms &rooms); + void sync(const Rooms &rooms); + +public slots: + void setHistoryView(const RoomInfo &info); + +private: + QMap<QString, HistoryView *> views_; +}; + +#endif diff --git a/include/InputValidator.h b/include/InputValidator.h new file mode 100644 index 00000000..feeaf70a --- /dev/null +++ b/include/InputValidator.h @@ -0,0 +1,49 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MATRIXIDVALIDATOR_H +#define MATRIXIDVALIDATOR_H + +#include <QRegExp> +#include <QRegExpValidator> + +class InputValidator +{ +public: + InputValidator(QObject *parent = 0); + + // Validators for the different types of input. + QRegExpValidator *id_; + QRegExpValidator *localpart_; + QRegExpValidator *password_; + QRegExpValidator *domain_; + +private: + // Regular expression used to validate the whole matrix id. + const QRegExp matrix_id_; + + // Regular expressino to validate the matrix localpart. + const QRegExp matrix_localpart_; + + // Regular expression to validate a password for a matrix account. + const QRegExp matrix_password_; + + // Regular expression to validate a domain name. + const QRegExp server_domain_; +}; + +#endif // MATRIXIDVALIDATOR_H diff --git a/include/Login.h b/include/Login.h new file mode 100644 index 00000000..857be14b --- /dev/null +++ b/include/Login.h @@ -0,0 +1,56 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LOGIN_H +#define LOGIN_H + +#include <QJsonDocument> + +#include "Deserializable.h" + +class LoginRequest +{ +public: + LoginRequest(); + LoginRequest(QString username, QString password); + + QByteArray serialize(); + + void setPassword(QString password); + void setUser(QString username); + +private: + QString user_; + QString password_; +}; + +class LoginResponse : public Deserializable +{ +public: + void deserialize(QJsonDocument data) throw(DeserializationException) override; + + QString getAccessToken(); + QString getHomeServer(); + QString getUserId(); + +private: + QString access_token_; + QString home_server_; + QString user_id_; +}; + +#endif // LOGIN_H diff --git a/include/LoginPage.h b/include/LoginPage.h new file mode 100644 index 00000000..d6b57efb --- /dev/null +++ b/include/LoginPage.h @@ -0,0 +1,80 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LOGINPAGE_H +#define LOGINPAGE_H + +#include <QHBoxLayout> +#include <QLabel> +#include <QVBoxLayout> +#include <QWidget> + +#include "FlatButton.h" +#include "InputValidator.h" +#include "RaisedButton.h" +#include "TextField.h" + +class LoginPage : public QWidget +{ + Q_OBJECT + +public: + explicit LoginPage(QWidget *parent = 0); + ~LoginPage(); + +signals: + void backButtonClicked(); + + // Emitted after the matrix ID validation. The handler should be + // responsible for performing the actual login with a remote server. + void userLogin(const QString &username, const QString &password, const QString home_server); + +public slots: + // Displays errors produced during the login. + void loginError(QString error_message); + +private slots: + // Callback for the back button. + void onBackButtonClicked(); + + // Callback for the login button. + void onLoginButtonClicked(); + +private: + QVBoxLayout *top_layout_; + + QHBoxLayout *back_layout_; + QHBoxLayout *logo_layout_; + QHBoxLayout *button_layout_; + + QLabel *logo_; + QLabel *error_label_; + + FlatButton *back_button_; + RaisedButton *login_button_; + + QWidget *form_widget_; + QHBoxLayout *form_wrapper_; + QVBoxLayout *form_layout_; + + TextField *username_input_; + TextField *password_input_; + + InputValidator *matrix_id_validator_; +}; + +#endif // LOGINPAGE_H diff --git a/include/MainWindow.h b/include/MainWindow.h new file mode 100644 index 00000000..dbbda3f2 --- /dev/null +++ b/include/MainWindow.h @@ -0,0 +1,84 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +#include "ChatPage.h" +#include "LoginPage.h" +#include "MatrixClient.h" +#include "RegisterPage.h" +#include "SlidingStackWidget.h" +#include "WelcomePage.h" + +namespace Ui +{ +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + // Show the welcome page in the main window. + void showWelcomePage(); + + // Show the login page in the main window. + void showLoginPage(); + + // Show the register page in the main window. + void showRegisterPage(); + + // Show the chat page and start communicating with the given access token. + void showChatPage(QString user_id, QString home_server, QString token); + + // Performs the actual login. + void matrixLogin(const QString &username, const QString &password, const QString &home_server); + + // Performs the actual registration. + void matrixRegister(const QString &username, const QString &password, const QString &server); + +private: + // The UI component of the main window. + Ui::MainWindow *ui_; + + // The initial welcome screen. + WelcomePage *welcome_page_; + + // The login screen. + LoginPage *login_page_; + + // The register page. + RegisterPage *register_page_; + + // A stacked widget that handles the transitions between widgets. + SlidingStackWidget *sliding_stack_; + + // The main chat area. + ChatPage *chat_page_; + + MatrixClient *matrix_client_; +}; + +#endif // MAINWINDOW_H diff --git a/include/MatrixClient.h b/include/MatrixClient.h new file mode 100644 index 00000000..46d6cc5b --- /dev/null +++ b/include/MatrixClient.h @@ -0,0 +1,134 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MATRIXCLIENT_H +#define MATRIXCLIENT_H + +#include <QtNetwork/QNetworkAccessManager> + +#include "Profile.h" +#include "Sync.h" + +/* + * MatrixClient provides the high level API to communicate with + * a Matrix homeserver. All the responses are returned through signals. + */ +class MatrixClient : public QNetworkAccessManager +{ + Q_OBJECT +public: + MatrixClient(QString server, QObject *parent = 0); + ~MatrixClient(); + + // Client API. + void initialSync(); + void sync(); + void sendTextMessage(QString roomid, QString msg); + void login(const QString &username, const QString &password); + void registerUser(const QString &username, const QString &password); + void versions(); + + inline QString getHomeServer(); + inline void incrementTransactionId(); + +public slots: + // Profile + void getOwnProfile(); + + inline void setServer(QString server); + inline void setAccessToken(QString token); + inline void setNextBatchToken(const QString &next_batch); + +signals: + // Emitted after a error during the login. + void loginError(QString error); + + // Emitted after succesfull user login. A new access token is returned by the server. + void loginSuccess(QString user_id, QString home_server, QString token); + + // Returned profile data for the user's account. + void getOwnProfileResponse(QUrl avatar_url, QString display_name); + void initialSyncCompleted(SyncResponse response); + void syncCompleted(SyncResponse response); + void messageSent(QString event_id, int txn_id); + +private slots: + void onResponse(QNetworkReply *reply); + +private: + enum Endpoint { + GetOwnProfile, + GetProfile, + InitialSync, + Login, + Register, + SendTextMessage, + Sync, + Versions, + }; + + // Response handlers. + void onLoginResponse(QNetworkReply *reply); + void onRegisterResponse(QNetworkReply *reply); + void onVersionsResponse(QNetworkReply *reply); + void onGetOwnProfileResponse(QNetworkReply *reply); + void onSendTextMessageResponse(QNetworkReply *reply); + void onInitialSyncResponse(QNetworkReply *reply); + void onSyncResponse(QNetworkReply *reply); + + // Client API prefix. + QString api_url_; + + // The Matrix server used for communication. + QString server_; + + // The access token used for authentication. + QString token_; + + // Increasing transaction ID. + int txn_id_; + + // Token to be used for the next sync. + QString next_batch_; +}; + +inline QString MatrixClient::getHomeServer() +{ + return server_; +} + +inline void MatrixClient::setServer(QString server) +{ + server_ = "https://" + server; +} + +inline void MatrixClient::setAccessToken(QString token) +{ + token_ = token; +} + +inline void MatrixClient::setNextBatchToken(const QString &next_batch) +{ + next_batch_ = next_batch; +} + +inline void MatrixClient::incrementTransactionId() +{ + txn_id_ += 1; +} + +#endif // MATRIXCLIENT_H diff --git a/include/Profile.h b/include/Profile.h new file mode 100644 index 00000000..a36393ec --- /dev/null +++ b/include/Profile.h @@ -0,0 +1,39 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PROFILE_H +#define PROFILE_H + +#include <QJsonDocument> +#include <QUrl> + +#include "Deserializable.h" + +class ProfileResponse : public Deserializable +{ +public: + void deserialize(QJsonDocument data) throw(DeserializationException) override; + + QUrl getAvatarUrl(); + QString getDisplayName(); + +private: + QUrl avatar_url_; + QString display_name_; +}; + +#endif // PROFILE_H diff --git a/include/RegisterPage.h b/include/RegisterPage.h new file mode 100644 index 00000000..f1c3848e --- /dev/null +++ b/include/RegisterPage.h @@ -0,0 +1,74 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef REGISTERPAGE_H +#define REGISTERPAGE_H + +#include <QHBoxLayout> +#include <QLabel> +#include <QVBoxLayout> +#include <QWidget> + +#include "FlatButton.h" +#include "InputValidator.h" +#include "RaisedButton.h" +#include "TextField.h" + +class RegisterPage : public QWidget +{ + Q_OBJECT + +public: + explicit RegisterPage(QWidget *parent = 0); + ~RegisterPage(); + +signals: + void backButtonClicked(); + + // Emitted after successful input validation. The handler should be + // responsible for the actual registering on the remote Matrix server. + void registerUser(const QString &username, const QString &password, const QString &server); + +private slots: + void onBackButtonClicked(); + void onRegisterButtonClicked(); + +private: + QVBoxLayout *top_layout_; + + QHBoxLayout *back_layout_; + QHBoxLayout *logo_layout_; + QHBoxLayout *button_layout_; + + QLabel *logo_; + + FlatButton *back_button_; + RaisedButton *register_button_; + + QWidget *form_widget_; + QHBoxLayout *form_wrapper_; + QVBoxLayout *form_layout_; + + TextField *username_input_; + TextField *password_input_; + TextField *password_confirmation_; + TextField *server_input_; + + InputValidator *validator_; +}; + +#endif // REGISTERPAGE_H diff --git a/include/RoomInfo.h b/include/RoomInfo.h new file mode 100644 index 00000000..9976ba8a --- /dev/null +++ b/include/RoomInfo.h @@ -0,0 +1,49 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ROOM_INFO_H +#define ROOM_INFO_H + +#include <QList> +#include <QString> +#include <QUrl> + +class RoomInfo +{ +public: + RoomInfo(); + RoomInfo(QString name, QString topic = "", QUrl avatar_url = QUrl("")); + + QString id() const; + QString name() const; + QString topic() const; + QUrl avatarUrl() const; + + void setAvatarUrl(const QUrl &url); + void setId(const QString &id); + void setName(const QString &name); + void setTopic(const QString &name); + +private: + QString id_; + QString name_; + QString topic_; + QUrl avatar_url_; + QList<QString> aliases_; +}; + +#endif // ROOM_INFO_H diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h new file mode 100644 index 00000000..4eabfa23 --- /dev/null +++ b/include/RoomInfoListItem.h @@ -0,0 +1,93 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ROOMINFOLISTITEM_H +#define ROOMINFOLISTITEM_H + +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QLabel> +#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/QWidget> + +#include "Avatar.h" +#include "RippleOverlay.h" +#include "RoomInfo.h" + +class RoomInfoListItem : public QWidget +{ + Q_OBJECT + +public: + RoomInfoListItem(RoomInfo info, QWidget *parent = 0); + ~RoomInfoListItem(); + + inline bool isPressed(); + inline RoomInfo info(); + inline void setAvatar(const QImage &avatar_image); + +signals: + void clicked(RoomInfo info_); + +public slots: + void setPressedState(bool state); + +protected: + void mousePressEvent(QMouseEvent *event) override; + +private: + void setElidedText(QLabel *label, QString text, int width); + + RippleOverlay *ripple_overlay_; + + RoomInfo info_; + + QHBoxLayout *topLayout_; + + QVBoxLayout *avatarLayout_; + QVBoxLayout *textLayout_; + + QWidget *avatarWidget_; + QWidget *textWidget_; + + QLabel *roomName_; + QLabel *roomTopic_; + + Avatar *roomAvatar_; + + QString pressed_style_; + QString normal_style_; + + bool is_pressed_; + int max_height_; +}; + +inline bool RoomInfoListItem::isPressed() +{ + return is_pressed_; +} + +inline RoomInfo RoomInfoListItem::info() +{ + return info_; +} + +inline void RoomInfoListItem::setAvatar(const QImage &avatar_image) +{ + roomAvatar_->setImage(avatar_image); +} + +#endif // ROOMINFOLISTITEM_H diff --git a/include/RoomList.h b/include/RoomList.h new file mode 100644 index 00000000..d679c785 --- /dev/null +++ b/include/RoomList.h @@ -0,0 +1,60 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ROOMLIST_H +#define ROOMLIST_H + +#include <QImage> +#include <QUrl> +#include <QWidget> + +#include "RoomInfo.h" +#include "RoomInfoListItem.h" +#include "Sync.h" + +namespace Ui +{ +class RoomList; +} + +class RoomList : public QWidget +{ + Q_OBJECT + +public: + explicit RoomList(QWidget *parent = 0); + ~RoomList(); + + void appendRoom(QString name); + void setInitialRooms(const Rooms &rooms); + void updateRoomAvatar(const QString &roomid, const QImage &avatar_image); + RoomInfo extractRoomInfo(const State &room_state); + +signals: + void roomChanged(const RoomInfo &info); + void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url); + +public slots: + void highlightSelectedRoom(const RoomInfo &info); + +private: + Ui::RoomList *ui; + + QMap<QString, RoomInfoListItem *> available_rooms_; +}; + +#endif // ROOMLIST_H diff --git a/include/SlidingStackWidget.h b/include/SlidingStackWidget.h new file mode 100644 index 00000000..7686c6eb --- /dev/null +++ b/include/SlidingStackWidget.h @@ -0,0 +1,94 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SLIDINGSTACKWIDGET_H +#define SLIDINGSTACKWIDGET_H + +#include <QDebug> +#include <QEasingCurve> +#include <QParallelAnimationGroup> +#include <QPropertyAnimation> +#include <QStackedWidget> +#include <QWidget> + +/* + * SlidingStackWidget allows smooth side shifting of widgets, + * in addition to the hard switching from one to another offered + * by QStackedWidget. + */ + +class SlidingStackWidget : public QStackedWidget +{ + Q_OBJECT + +public: + // Defines the animation direction. + enum AnimationDirection { + LEFT_TO_RIGHT, + RIGHT_TO_LEFT, + AUTOMATIC + }; + + SlidingStackWidget(QWidget *parent); + ~SlidingStackWidget(); + +public slots: + // Move to the next widget. + void slideInNext(); + + // Move to the previous widget. + void slideInPrevious(); + + // Move to a widget by index. + void slideInIndex(int index, enum AnimationDirection direction = AnimationDirection::AUTOMATIC); + + int getWidgetIndex(QWidget *widget); +signals: + // Internal signal to alert the engine for the animation's end. + void animationFinished(); + +protected slots: + // Internal slot to handle the end of the animation. + void onAnimationFinished(); + +protected: + // The method that does the main work for the widget transition. + void slideInWidget(QWidget *widget, enum AnimationDirection direction = AnimationDirection::AUTOMATIC); + + // Indicates whether or not the animation is active. + bool active_; + + // The widget currently displayed. + QWidget *window_; + + // The speed of the animation in milliseconds. + int speed_; + + // The animation type. + enum QEasingCurve::Type animation_type_; + + // Current widget's index. + int now_; + + // Reference point. + QPoint current_position_; + + // Next widget's to show index. + int next_; +}; + +#endif // SLIDINGSTACKWIDGET_H diff --git a/include/Sync.h b/include/Sync.h new file mode 100644 index 00000000..110e8a6e --- /dev/null +++ b/include/Sync.h @@ -0,0 +1,119 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SYNC_H +#define SYNC_H + +#include <QJsonDocument> +#include <QMap> +#include <QString> + +#include "Deserializable.h" + +class Event : public Deserializable +{ +public: + QJsonObject content() const; + QJsonObject unsigned_content() const; + + QString sender() const; + QString state_key() const; + QString type() const; + QString eventId() const; + + uint64_t timestamp() const; + + void deserialize(QJsonValue data) throw(DeserializationException) override; + +private: + QJsonObject content_; + QJsonObject unsigned_; + + QString sender_; + QString state_key_; + QString type_; + QString event_id_; + + uint64_t origin_server_ts_; +}; + +class State : public Deserializable +{ +public: + void deserialize(QJsonValue data) throw(DeserializationException) override; + QList<Event> events() const; + +private: + QList<Event> events_; +}; + +class Timeline : public Deserializable +{ +public: + QList<Event> events() const; + QString previousBatch() const; + bool limited() const; + + void deserialize(QJsonValue data) throw(DeserializationException) override; + +private: + QList<Event> events_; + QString prev_batch_; + bool limited_; +}; + +// TODO: Add support for ehpmeral, account_data, undread_notifications +class JoinedRoom : public Deserializable +{ +public: + State state() const; + Timeline timeline() const; + + void deserialize(QJsonValue data) throw(DeserializationException) override; + +private: + State state_; + Timeline timeline_; + /* Ephemeral ephemeral_; */ + /* AccountData account_data_; */ + /* UnreadNotifications unread_notifications_; */ +}; + +// TODO: Add support for invited and left rooms. +class Rooms : public Deserializable +{ +public: + QMap<QString, JoinedRoom> join() const; + void deserialize(QJsonValue data) throw(DeserializationException) override; + +private: + QMap<QString, JoinedRoom> join_; +}; + +class SyncResponse : public Deserializable +{ +public: + void deserialize(QJsonDocument data) throw(DeserializationException) override; + QString nextBatch() const; + Rooms rooms() const; + +private: + QString next_batch_; + Rooms rooms_; +}; + +#endif // SYNC_H diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h new file mode 100644 index 00000000..35a12892 --- /dev/null +++ b/include/TextInputWidget.h @@ -0,0 +1,53 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TEXT_INPUT_WIDGET_H +#define TEXT_INPUT_WIDGET_H + +#include <QHBoxLayout> +#include <QLineEdit> +#include <QPaintEvent> +#include <QWidget> + +#include "FlatButton.h" + +class TextInputWidget : public QWidget +{ + Q_OBJECT + +public: + TextInputWidget(QWidget *parent = 0); + ~TextInputWidget(); + +public slots: + void onSendButtonClicked(); + +signals: + void sendTextMessage(QString msg); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QHBoxLayout *top_layout_; + QLineEdit *input_; + + FlatButton *send_file_button_; + FlatButton *send_message_button_; +}; + +#endif // TEXT_INPUT_WIDGET_H diff --git a/include/TopRoomBar.h b/include/TopRoomBar.h new file mode 100644 index 00000000..247cb9a2 --- /dev/null +++ b/include/TopRoomBar.h @@ -0,0 +1,79 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TOP_ROOM_BAR_H +#define TOP_ROOM_BAR_H + +#include <QIcon> +#include <QImage> +#include <QLabel> +#include <QPaintEvent> +#include <QVBoxLayout> +#include <QWidget> + +#include "Avatar.h" +#include "FlatButton.h" + +class TopRoomBar : public QWidget +{ + Q_OBJECT +public: + TopRoomBar(QWidget *parent = 0); + ~TopRoomBar(); + + inline void updateRoomAvatar(const QImage &avatar_image); + inline void updateRoomAvatar(const QIcon &icon); + inline void updateRoomName(const QString &name); + inline void updateRoomTopic(const QString &topic); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QHBoxLayout *top_layout_; + QVBoxLayout *text_layout_; + + QLabel *name_label_; + QLabel *topic_label_; + + FlatButton *search_button_; + FlatButton *settings_button_; + + Avatar *avatar_; +}; + +inline void TopRoomBar::updateRoomAvatar(const QImage &avatar_image) +{ + avatar_->setImage(avatar_image); +} + +inline void TopRoomBar::updateRoomAvatar(const QIcon &icon) +{ + avatar_->setIcon(icon); +} + +inline void TopRoomBar::updateRoomName(const QString &name) +{ + name_label_->setText(name); +} + +inline void TopRoomBar::updateRoomTopic(const QString &topic) +{ + topic_label_->setText(topic); +} + +#endif // TOP_ROOM_BAR_H diff --git a/include/UserInfoWidget.h b/include/UserInfoWidget.h new file mode 100644 index 00000000..8cd4b765 --- /dev/null +++ b/include/UserInfoWidget.h @@ -0,0 +1,60 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef USER_INFO_WIDGET_H +#define USER_INFO_WIDGET_H + +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QLabel> +#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/QWidget> + +#include "Avatar.h" +#include "FlatButton.h" + +class UserInfoWidget : public QWidget +{ + Q_OBJECT + +public: + UserInfoWidget(QWidget *parent = 0); + ~UserInfoWidget(); + + void setAvatar(const QImage &img); + void setDisplayName(const QString &name); + void setUserId(const QString &userid); + +private: + Avatar *userAvatar_; + + QHBoxLayout *topLayout_; + QHBoxLayout *avatarLayout_; + QVBoxLayout *textLayout_; + QHBoxLayout *buttonLayout_; + + FlatButton *settingsButton_; + + QLabel *displayNameLabel_; + QLabel *userIdLabel_; + + QString display_name_; + QString userid_; + + QImage avatar_image_; +}; + +#endif diff --git a/include/WelcomePage.h b/include/WelcomePage.h new file mode 100644 index 00000000..3cd6e664 --- /dev/null +++ b/include/WelcomePage.h @@ -0,0 +1,61 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WELCOMEPAGE_H +#define WELCOMEPAGE_H + +#include <QHBoxLayout> +#include <QLabel> +#include <QSpacerItem> +#include <QVBoxLayout> +#include <QWidget> + +#include "RaisedButton.h" + +class WelcomePage : public QWidget +{ + Q_OBJECT + +public: + explicit WelcomePage(QWidget *parent = 0); + ~WelcomePage(); + +signals: + // Notify that the user wants to login in. + void userLogin(); + + // Notify that the user wants to register. + void userRegister(); + +private slots: + void onLoginButtonClicked(); + void onRegisterButtonClicked(); + +private: + QVBoxLayout *top_layout_; + QHBoxLayout *button_layout_; + + QLabel *intro_banner_; + QLabel *intro_text_; + + QSpacerItem *button_spacer_; + + RaisedButton *register_button_; + RaisedButton *login_button_; +}; + +#endif // WELCOMEPAGE_H diff --git a/include/ui/Avatar.h b/include/ui/Avatar.h new file mode 100644 index 00000000..afbf6aad --- /dev/null +++ b/include/ui/Avatar.h @@ -0,0 +1,51 @@ +#ifndef UI_AVATAR_H +#define UI_AVATAR_H + +#include <QIcon> +#include <QImage> +#include <QPixmap> +#include <QWidget> + +#include "Theme.h" + +class Avatar : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor) + Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + +public: + explicit Avatar(QWidget *parent = 0); + ~Avatar(); + + void setBackgroundColor(const QColor &color); + void setIcon(const QIcon &icon); + void setImage(const QImage &image); + void setLetter(const QChar &letter); + void setSize(int size); + void setTextColor(const QColor &color); + + QColor backgroundColor() const; + QColor textColor() const; + int size() const; + + QSize sizeHint() const override; + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + void init(); + + ui::AvatarType type_; + QChar letter_; + QColor background_color_; + QColor text_color_; + QIcon icon_; + QImage image_; + QPixmap pixmap_; + int size_; +}; + +#endif // UI_AVATAR_H diff --git a/include/ui/Badge.h b/include/ui/Badge.h new file mode 100644 index 00000000..774b03ad --- /dev/null +++ b/include/ui/Badge.h @@ -0,0 +1,63 @@ +#ifndef UI_BADGE_H +#define UI_BADGE_H + +#include <QColor> +#include <QIcon> +#include <QWidget> +#include <QtGlobal> + +#include "OverlayWidget.h" + +class Badge : public OverlayWidget +{ + Q_OBJECT + + Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor) + Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition) + +public: + explicit Badge(QWidget *parent = 0); + explicit Badge(const QIcon &icon, QWidget *parent = 0); + explicit Badge(const QString &text, QWidget *parent = 0); + ~Badge(); + + void setBackgroundColor(const QColor &color); + void setTextColor(const QColor &color); + void setIcon(const QIcon &icon); + void setRelativePosition(const QPointF &pos); + void setRelativePosition(qreal x, qreal y); + void setRelativeXPosition(qreal x); + void setRelativeYPosition(qreal y); + void setText(const QString &text); + + QIcon icon() const; + QString text() const; + QColor backgroundColor() const; + QColor textColor() const; + QPointF relativePosition() const; + QSize sizeHint() const override; + qreal relativeXPosition() const; + qreal relativeYPosition() const; + +protected: + void paintEvent(QPaintEvent *event) override; + int getDiameter() const; + +private: + void init(); + + QColor background_color_; + QColor text_color_; + + QIcon icon_; + QSize size_; + QString text_; + + int padding_; + + qreal x_; + qreal y_; +}; + +#endif // UI_BADGE_H diff --git a/include/ui/FlatButton.h b/include/ui/FlatButton.h new file mode 100644 index 00000000..047890c7 --- /dev/null +++ b/include/ui/FlatButton.h @@ -0,0 +1,210 @@ +#ifndef UI_FLAT_BUTTON_H +#define UI_FLAT_BUTTON_H + +#include <QPaintEvent> +#include <QPainter> +#include <QPushButton> +#include <QSequentialAnimationGroup> +#include <QStateMachine> + +#include "RippleOverlay.h" +#include "Theme.h" + +class FlatButton; + +class FlatButtonStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity) + Q_PROPERTY(qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress) + Q_PROPERTY(qreal haloOpacity WRITE setHaloOpacity READ haloOpacity) + Q_PROPERTY(qreal haloSize WRITE setHaloSize READ haloSize) + Q_PROPERTY(qreal haloScaleFactor WRITE setHaloScaleFactor READ haloScaleFactor) + +public: + explicit FlatButtonStateMachine(FlatButton *parent); + ~FlatButtonStateMachine(); + + void setOverlayOpacity(qreal opacity); + void setCheckedOverlayProgress(qreal opacity); + void setHaloOpacity(qreal opacity); + void setHaloSize(qreal size); + void setHaloScaleFactor(qreal factor); + + inline qreal overlayOpacity() const; + inline qreal checkedOverlayProgress() const; + inline qreal haloOpacity() const; + inline qreal haloSize() const; + inline qreal haloScaleFactor() const; + + void startAnimations(); + void setupProperties(); + void updateCheckedStatus(); + +signals: + void buttonPressed(); + void buttonChecked(); + void buttonUnchecked(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState); + void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState); + void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState); + + FlatButton *const button_; + + QState *const top_level_state_; + QState *const config_state_; + QState *const checkable_state_; + QState *const checked_state_; + QState *const unchecked_state_; + QState *const neutral_state_; + QState *const neutral_focused_state_; + QState *const hovered_state_; + QState *const hovered_focused_state_; + QState *const pressed_state_; + + QSequentialAnimationGroup *const halo_animation_; + + qreal overlay_opacity_; + qreal checked_overlay_progress_; + qreal halo_opacity_; + qreal halo_size_; + qreal halo_scale_factor_; + + bool was_checked_; +}; + +inline qreal FlatButtonStateMachine::overlayOpacity() const +{ + return overlay_opacity_; +} + +inline qreal FlatButtonStateMachine::checkedOverlayProgress() const +{ + return checked_overlay_progress_; +} + +inline qreal FlatButtonStateMachine::haloOpacity() const +{ + return halo_opacity_; +} + +inline qreal FlatButtonStateMachine::haloSize() const +{ + return halo_size_; +} + +inline qreal FlatButtonStateMachine::haloScaleFactor() const +{ + return halo_scale_factor_; +} + +class FlatButton : public QPushButton +{ + Q_OBJECT + + Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor) + Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor) + Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ disabledForegroundColor) + Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ disabledBackgroundColor) + Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize) + +public: + explicit FlatButton(QWidget *parent = 0, ui::ButtonPreset preset = ui::FlatPreset); + explicit FlatButton(const QString &text, QWidget *parent = 0, ui::ButtonPreset preset = ui::FlatPreset); + FlatButton(const QString &text, ui::Role role, QWidget *parent = 0, ui::ButtonPreset preset = ui::FlatPreset); + ~FlatButton(); + + void applyPreset(ui::ButtonPreset preset); + + void setBackgroundColor(const QColor &color); + void setBackgroundMode(Qt::BGMode mode); + void setBaseOpacity(qreal opacity); + void setCheckable(bool value); + void setCornerRadius(qreal radius); + void setDisabledBackgroundColor(const QColor &color); + void setDisabledForegroundColor(const QColor &color); + void setFixedRippleRadius(qreal radius); + void setFontSize(qreal size); + void setForegroundColor(const QColor &color); + void setHaloVisible(bool visible); + void setHasFixedRippleRadius(bool value); + void setIconPlacement(ui::ButtonIconPlacement placement); + void setOverlayColor(const QColor &color); + void setOverlayStyle(ui::OverlayStyle style); + void setRippleStyle(ui::RippleStyle style); + void setRole(ui::Role role); + + QColor foregroundColor() const; + QColor backgroundColor() const; + QColor overlayColor() const; + QColor disabledForegroundColor() const; + QColor disabledBackgroundColor() const; + + qreal fontSize() const; + qreal cornerRadius() const; + qreal baseOpacity() const; + + bool isHaloVisible() const; + bool hasFixedRippleRadius() const; + + ui::Role role() const; + ui::OverlayStyle overlayStyle() const; + ui::RippleStyle rippleStyle() const; + ui::ButtonIconPlacement iconPlacement() const; + + Qt::BGMode backgroundMode() const; + + QSize sizeHint() const override; + +protected: + enum { + IconPadding = 12 + }; + + void checkStateSet() override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void paintEvent(QPaintEvent *event) override; + + virtual void paintBackground(QPainter *painter); + virtual void paintHalo(QPainter *painter); + virtual void paintForeground(QPainter *painter); + virtual void updateClipPath(); + + void init(); + +private: + RippleOverlay *ripple_overlay_; + FlatButtonStateMachine *state_machine_; + + ui::Role role_; + ui::RippleStyle ripple_style_; + ui::ButtonIconPlacement icon_placement_; + ui::OverlayStyle overlay_style_; + + Qt::BGMode bg_mode_; + + QColor background_color_; + QColor foreground_color_; + QColor overlay_color_; + QColor disabled_color_; + QColor disabled_background_color_; + + qreal fixed_ripple_radius_; + qreal corner_radius_; + qreal base_opacity_; + qreal font_size_; + + bool use_fixed_ripple_radius_; + bool halo_visible_; +}; + +#endif // UI_FLAT_BUTTON_H diff --git a/include/ui/OverlayWidget.h b/include/ui/OverlayWidget.h new file mode 100644 index 00000000..020393ad --- /dev/null +++ b/include/ui/OverlayWidget.h @@ -0,0 +1,23 @@ +#ifndef UI_OVERLAY_WIDGET_H +#define UI_OVERLAY_WIDGET_H + +#include <QEvent> +#include <QObject> +#include <QWidget> + +class OverlayWidget : public QWidget +{ + Q_OBJECT + +public: + explicit OverlayWidget(QWidget *parent = 0); + ~OverlayWidget(); + +protected: + bool event(QEvent *event) override; + bool eventFilter(QObject *obj, QEvent *event) override; + + QRect overlayGeometry() const; +}; + +#endif // UI_OVERLAY_WIDGET_H diff --git a/include/ui/RaisedButton.h b/include/ui/RaisedButton.h new file mode 100644 index 00000000..7a46173f --- /dev/null +++ b/include/ui/RaisedButton.h @@ -0,0 +1,31 @@ +#ifndef UI_RAISED_BUTTON_H +#define UI_RAISED_BUTTON_H + +#include <QGraphicsDropShadowEffect> +#include <QState> +#include <QStateMachine> + +#include "FlatButton.h" + +class RaisedButton : public FlatButton +{ + Q_OBJECT + +public: + explicit RaisedButton(QWidget *parent = 0); + explicit RaisedButton(const QString &text, QWidget *parent = 0); + ~RaisedButton(); + +protected: + bool event(QEvent *event) override; + +private: + void init(); + + QStateMachine *shadow_state_machine_; + QState *normal_state_; + QState *pressed_state_; + QGraphicsDropShadowEffect *effect_; +}; + +#endif // UI_RAISED_BUTTON_H diff --git a/include/ui/Ripple.h b/include/ui/Ripple.h new file mode 100644 index 00000000..a66a583e --- /dev/null +++ b/include/ui/Ripple.h @@ -0,0 +1,136 @@ +#ifndef UI_RIPPLE_H +#define UI_RIPPLE_H + +#include <QBrush> +#include <QEasingCurve> +#include <QParallelAnimationGroup> +#include <QPoint> +#include <QPropertyAnimation> + +class RippleOverlay; + +class Ripple : public QParallelAnimationGroup +{ + Q_OBJECT + + Q_PROPERTY(qreal radius WRITE setRadius READ radius) + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + +public: + explicit Ripple(const QPoint ¢er, QObject *parent = 0); + Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent = 0); + ~Ripple(); + + inline void setOverlay(RippleOverlay *overlay); + + void setRadius(qreal radius); + void setOpacity(qreal opacity); + void setColor(const QColor &color); + void setBrush(const QBrush &brush); + + inline qreal radius() const; + inline qreal opacity() const; + inline QColor color() const; + inline QBrush brush() const; + inline QPoint center() const; + + inline QPropertyAnimation *radiusAnimation() const; + inline QPropertyAnimation *opacityAnimation() const; + + inline void setOpacityStartValue(qreal value); + inline void setOpacityEndValue(qreal value); + inline void setRadiusStartValue(qreal value); + inline void setRadiusEndValue(qreal value); + inline void setDuration(int msecs); + +protected slots: + void destroy(); + +private: + Q_DISABLE_COPY(Ripple) + + QPropertyAnimation *animate(const QByteArray &property, + const QEasingCurve &easing = QEasingCurve::OutQuad, + int duration = 800); + + void init(); + + RippleOverlay *overlay_; + + QPropertyAnimation *const radius_anim_; + QPropertyAnimation *const opacity_anim_; + + qreal radius_; + qreal opacity_; + + QPoint center_; + QBrush brush_; +}; + +inline void Ripple::setOverlay(RippleOverlay *overlay) +{ + overlay_ = overlay; +} + +inline qreal Ripple::radius() const +{ + return radius_; +} + +inline qreal Ripple::opacity() const +{ + return opacity_; +} + +inline QColor Ripple::color() const +{ + return brush_.color(); +} + +inline QBrush Ripple::brush() const +{ + return brush_; +} + +inline QPoint Ripple::center() const +{ + return center_; +} + +inline QPropertyAnimation *Ripple::radiusAnimation() const +{ + return radius_anim_; +} + +inline QPropertyAnimation *Ripple::opacityAnimation() const +{ + return opacity_anim_; +} + +inline void Ripple::setOpacityStartValue(qreal value) +{ + opacity_anim_->setStartValue(value); +} + +inline void Ripple::setOpacityEndValue(qreal value) +{ + opacity_anim_->setEndValue(value); +} + +inline void Ripple::setRadiusStartValue(qreal value) +{ + radius_anim_->setStartValue(value); +} + +inline void Ripple::setRadiusEndValue(qreal value) +{ + radius_anim_->setEndValue(value); +} + +inline void Ripple::setDuration(int msecs) +{ + radius_anim_->setDuration(msecs); + opacity_anim_->setDuration(msecs); +} + +#endif // UI_RIPPLE_H diff --git a/include/ui/RippleOverlay.h b/include/ui/RippleOverlay.h new file mode 100644 index 00000000..54398efa --- /dev/null +++ b/include/ui/RippleOverlay.h @@ -0,0 +1,58 @@ +#ifndef UI_RIPPLE_OVERLAY_H +#define UI_RIPPLE_OVERLAY_H + +#include <QPainterPath> + +#include "OverlayWidget.h" + +class Ripple; + +class RippleOverlay : public OverlayWidget +{ + Q_OBJECT + +public: + explicit RippleOverlay(QWidget *parent = 0); + ~RippleOverlay(); + + void addRipple(Ripple *ripple); + void addRipple(const QPoint &position, qreal radius = 300); + + void removeRipple(Ripple *ripple); + + inline void setClipping(bool enable); + inline bool hasClipping() const; + + inline void setClipPath(const QPainterPath &path); + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(RippleOverlay) + + void paintRipple(QPainter *painter, Ripple *ripple); + + QList<Ripple *> ripples_; + QPainterPath clip_path_; + bool use_clip_; +}; + +inline void RippleOverlay::setClipping(bool enable) +{ + use_clip_ = enable; + update(); +} + +inline bool RippleOverlay::hasClipping() const +{ + return use_clip_; +} + +inline void RippleOverlay::setClipPath(const QPainterPath &path) +{ + clip_path_ = path; + update(); +} + +#endif // UI_RIPPLE_OVERLAY_H diff --git a/include/ui/TextField.h b/include/ui/TextField.h new file mode 100644 index 00000000..953c8f29 --- /dev/null +++ b/include/ui/TextField.h @@ -0,0 +1,170 @@ +#ifndef UI_TEXT_FIELD_H +#define UI_TEXT_FIELD_H + +#include <QColor> +#include <QLineEdit> +#include <QPaintEvent> +#include <QPropertyAnimation> +#include <QStateMachine> +#include <QtGlobal> + +class TextField; +class TextFieldLabel; +class TextFieldStateMachine; + +class TextField : public QLineEdit +{ + Q_OBJECT + + Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor) + Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor) + Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor) + +public: + explicit TextField(QWidget *parent = 0); + ~TextField(); + + void setInkColor(const QColor &color); + void setBackgroundColor(const QColor &color); + void setLabel(const QString &label); + void setLabelColor(const QColor &color); + void setLabelFontSize(qreal size); + void setShowLabel(bool value); + void setTextColor(const QColor &color); + void setUnderlineColor(const QColor &color); + + QColor inkColor() const; + QColor labelColor() const; + QColor textColor() const; + QColor underlineColor() const; + QColor backgroundColor() const; + QString label() const; + bool hasLabel() const; + qreal labelFontSize() const; + +protected: + bool event(QEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + void init(); + + QColor ink_color_; + QColor background_color_; + QColor label_color_; + QColor text_color_; + QColor underline_color_; + QString label_text_; + TextFieldLabel *label_; + TextFieldStateMachine *state_machine_; + bool show_label_; + qreal label_font_size_; +}; + +class TextFieldLabel : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(qreal scale WRITE setScale READ scale) + Q_PROPERTY(QPointF offset WRITE setOffset READ offset) + Q_PROPERTY(QColor color WRITE setColor READ color) + +public: + TextFieldLabel(TextField *parent); + ~TextFieldLabel(); + + inline void setColor(const QColor &color); + inline void setOffset(const QPointF &pos); + inline void setScale(qreal scale); + + inline QColor color() const; + inline QPointF offset() const; + inline qreal scale() const; + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + TextField *const text_field_; + + QColor color_; + qreal scale_; + qreal x_; + qreal y_; +}; + +inline void TextFieldLabel::setColor(const QColor &color) +{ + color_ = color; + update(); +} + +inline void TextFieldLabel::setOffset(const QPointF &pos) +{ + x_ = pos.x(); + y_ = pos.y(); + update(); +} + +inline void TextFieldLabel::setScale(qreal scale) +{ + scale_ = scale; + update(); +} + +inline QPointF TextFieldLabel::offset() const +{ + return QPointF(x_, y_); +} +inline qreal TextFieldLabel::scale() const +{ + return scale_; +} +inline QColor TextFieldLabel::color() const +{ + return color_; +} + +class TextFieldStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(qreal progress WRITE setProgress READ progress) + +public: + TextFieldStateMachine(TextField *parent); + ~TextFieldStateMachine(); + + inline void setProgress(qreal progress); + void setLabel(TextFieldLabel *label); + + inline qreal progress() const; + +public slots: + void setupProperties(); + +private: + QPropertyAnimation *color_anim_; + QPropertyAnimation *offset_anim_; + + QState *focused_state_; + QState *normal_state_; + + TextField *text_field_; + TextFieldLabel *label_; + + qreal progress_; +}; + +inline void TextFieldStateMachine::setProgress(qreal progress) +{ + progress_ = progress; + text_field_->update(); +} + +inline qreal TextFieldStateMachine::progress() const +{ + return progress_; +} + +#endif // UI_TEXT_FIELD_H diff --git a/include/ui/Theme.h b/include/ui/Theme.h new file mode 100644 index 00000000..41739a98 --- /dev/null +++ b/include/ui/Theme.h @@ -0,0 +1,89 @@ +#ifndef UI_THEME_H +#define UI_THEME_H + +#include <QColor> +#include <QHash> +#include <QObject> + +namespace ui +{ +enum AvatarType { + Icon, + Image, + Letter +}; + +// Default font size. +const int FontSize = 16; + +// Default avatar size. Width and height. +const int AvatarSize = 40; + +enum ButtonPreset { + FlatPreset, + CheckablePreset +}; + +enum RippleStyle { + CenteredRipple, + PositionedRipple, + NoRipple +}; + +enum OverlayStyle { + NoOverlay, + TintedOverlay, + GrayOverlay +}; + +enum Role { + Default, + Primary, + Secondary +}; + +enum ButtonIconPlacement { + LeftIcon, + RightIcon +}; + +enum ProgressType { + DeterminateProgress, + IndeterminateProgress +}; + +enum Color { + Black, + BrightWhite, + FadedWhite, + MediumWhite, + DarkGreen, + LightGreen, + BrightGreen, + Gray, + Red, + Blue, + Transparent +}; + +} // namespace ui + +class Theme : public QObject +{ + Q_OBJECT +public: + explicit Theme(QObject *parent = 0); + ~Theme(); + + QColor getColor(const QString &key) const; + + void setColor(const QString &key, const QColor &color); + void setColor(const QString &key, ui::Color &color); + +private: + QColor rgba(int r, int g, int b, qreal a) const; + + QHash<QString, QColor> colors_; +}; + +#endif // UI_THEME_H diff --git a/include/ui/ThemeManager.h b/include/ui/ThemeManager.h new file mode 100644 index 00000000..426d71ec --- /dev/null +++ b/include/ui/ThemeManager.h @@ -0,0 +1,33 @@ +#ifndef UI_THEME_MANAGER_H +#define UI_THEME_MANAGER_H + +#include <QCommonStyle> + +#include "Theme.h" + +class ThemeManager : public QCommonStyle +{ + Q_OBJECT + +public: + inline static ThemeManager &instance(); + + void setTheme(Theme *theme); + QColor themeColor(const QString &key) const; + +private: + ThemeManager(); + + ThemeManager(ThemeManager const &); + void operator=(ThemeManager const &); + + Theme *theme_; +}; + +inline ThemeManager &ThemeManager::instance() +{ + static ThemeManager instance; + return instance; +} + +#endif // UI_THEME_MANAGER_H |