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
|