diff --git a/qtox.pro b/qtox.pro
index 3c95c22ba..450978f61 100644
--- a/qtox.pro
+++ b/qtox.pro
@@ -33,7 +33,8 @@ FORMS += \
src/widget/form/settings/privacysettings.ui \
src/widget/form/loadhistorydialog.ui \
src/widget/form/setpassworddialog.ui \
- src/widget/form/settings/advancedsettings.ui
+ src/widget/form/settings/advancedsettings.ui \
+ src/android.ui
CONFIG += c++11
diff --git a/src/android.ui b/src/android.ui
new file mode 100644
index 000000000..1c22c54b4
--- /dev/null
+++ b/src/android.ui
@@ -0,0 +1,905 @@
+
+
+ Android
+
+
+
+ 0
+ 0
+ 320
+ 480
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
-
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Maximum
+
+
+
+ 5
+ 20
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ true
+
+
+
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 240
+ 240
+ 240
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+
+
+ 11
+ 75
+ true
+
+
+
+ Your name
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 193
+ 193
+ 193
+
+
+
+
+
+
+ 193
+ 193
+ 193
+
+
+
+
+
+
+
+
+ 193
+ 193
+ 193
+
+
+
+
+
+
+ 193
+ 193
+ 193
+
+
+
+
+
+
+
+
+ 14
+ 14
+ 14
+
+
+
+
+
+
+ 14
+ 14
+ 14
+
+
+
+
+
+
+
+
+ 8
+
+
+
+ Your status
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 20
+ 40
+
+
+
+ Qt::NoFocus
+
+
+
+
+
+
+ 10
+ 10
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::LeftToRight
+
+
+ true
+
+
+ QFrame::NoFrame
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 320
+ 385
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 55
+ 35
+
+
+
+
+ 55
+ 35
+
+
+
+ Qt::NoFocus
+
+
+ Add friends
+
+
+ false
+
+
+
+
+
+
+
+
+
+ :/img/add.png:/img/add.png
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+
+ 55
+ 35
+
+
+
+ Qt::NoFocus
+
+
+ Create a group chat
+
+
+ false
+
+
+
+
+
+
+ :/img/group_button.png:/img/group_button.png
+
+
+ true
+
+
+
+ -
+
+
+
+ 55
+ 35
+
+
+
+
+ 55
+ 35
+
+
+
+ Qt::NoFocus
+
+
+ View completed file transfers
+
+
+
+
+
+
+ :/img/transfer.png:/img/transfer.png
+
+
+ true
+
+
+
+ -
+
+
+
+ 55
+ 35
+
+
+
+
+ 55
+ 35
+
+
+
+ Qt::NoFocus
+
+
+ Change your settings
+
+
+
+
+
+
+ :/img/settings.png:/img/settings.png
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AdjustingScrollArea
+ QScrollArea
+ src/widget/adjustingscrollarea.h
+ 1
+
+
+ CroppingLabel
+ QLabel
+ src/widget/croppinglabel.h
+
+
+
+
+
+
+
diff --git a/src/nexus.cpp b/src/nexus.cpp
index 9c80bcfcd..6a56f8bd6 100644
--- a/src/nexus.cpp
+++ b/src/nexus.cpp
@@ -72,7 +72,21 @@ void Nexus::start()
GUI::getInstance();
// Connections
-#ifndef Q_OS_ANDROID
+#ifdef Q_OS_ANDROID
+ connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected);
+ connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected);
+ //connect(core, &Core::failedToStart, androidgui, &AndroidGUI::onFailedToStartCore);
+ //connect(core, &Core::badProxy, androidgui, &AndroidGUI::onBadProxyCore);
+ connect(core, &Core::statusSet, androidgui, &AndroidGUI::onStatusSet);
+ connect(core, &Core::usernameSet, androidgui, &AndroidGUI::setUsername);
+ connect(core, &Core::statusMessageSet, androidgui, &AndroidGUI::setStatusMessage);
+ connect(core, &Core::selfAvatarChanged, androidgui, &AndroidGUI::onSelfAvatarLoaded);
+
+ connect(androidgui, &AndroidGUI::statusSet, core, &Core::setStatus);
+ //connect(androidgui, &AndroidGUI::friendRequested, core, &Core::requestFriendship);
+ //connect(androidgui, &AndroidGUI::friendRequestAccepted, core, &Core::acceptFriendRequest);
+ //connect(androidgui, &AndroidGUI::changeProfile, core, &Core::switchConfiguration);
+#else
connect(core, &Core::connected, widget, &Widget::onConnected);
connect(core, &Core::disconnected, widget, &Widget::onDisconnected);
connect(core, &Core::failedToStart, widget, &Widget::onFailedToStartCore);
diff --git a/src/widget/androidgui.cpp b/src/widget/androidgui.cpp
index 7ae41d983..8dd2b7a9d 100644
--- a/src/widget/androidgui.cpp
+++ b/src/widget/androidgui.cpp
@@ -1,13 +1,169 @@
#include "androidgui.h"
+#include "ui_android.h"
+#include "friendlistwidget.h"
+#include "maskablepixmapwidget.h"
+#include "src/core.h"
+#include "src/friend.h"
+#include "src/friendlist.h"
+#include "src/group.h"
+#include "src/grouplist.h"
+#include "src/misc/settings.h"
+#include "src/misc/style.h"
+#include "src/nexus.h"
+#include "src/widget/friendwidget.h"
+#include "src/widget/groupwidget.h"
#include
+#include
AndroidGUI::AndroidGUI(QWidget *parent) :
- QWidget(parent)
+ QWidget(parent),
+ ui{new Ui::Android}
{
- l = new QLabel("qTox Android", this);
+ ui->setupUi(this);
+
+ ui->friendList->setStyleSheet(Style::resolve(Style::getStylesheet(":ui/friendList/friendList.css")));
+
+ profilePicture = new MaskablePixmapWidget(this, QSize(40, 40), ":/img/avatar_mask.png");
+ profilePicture->setPixmap(QPixmap(":/img/contact_dark.png"));
+ profilePicture->setClickable(true);
+ ui->myProfile->insertWidget(0, profilePicture);
+ ui->myProfile->insertSpacing(1, 7);
+
+ ui->tooliconsZone->setStyleSheet(Style::resolve("QPushButton{background-color:@themeDark;border:none;}QPushButton:hover{background-color:@themeMediumDark;border:none;}"));
+ ui->statusHead->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css"));
+
+ contactListWidget = new FriendListWidget();
+ ui->friendList->setWidget(contactListWidget);
+ ui->friendList->setLayoutDirection(Qt::RightToLeft);
+
+ ui->nameLabel->setEditable(true);
+ ui->statusLabel->setEditable(true);
+
+ ui->statusPanel->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css"));
+
+ QMenu *statusButtonMenu = new QMenu(ui->statusButton);
+ QAction* setStatusOnline = statusButtonMenu->addAction(AndroidGUI::tr("Online","Button to set your status to 'Online'"));
+ setStatusOnline->setIcon(QIcon(":ui/statusButton/dot_online.png"));
+ QAction* setStatusAway = statusButtonMenu->addAction(AndroidGUI::tr("Away","Button to set your status to 'Away'"));
+ setStatusAway->setIcon(QIcon(":ui/statusButton/dot_idle.png"));
+ QAction* setStatusBusy = statusButtonMenu->addAction(AndroidGUI::tr("Busy","Button to set your status to 'Busy'"));
+ setStatusBusy->setIcon(QIcon(":ui/statusButton/dot_busy.png"));
+ ui->statusButton->setMenu(statusButtonMenu);
+
+ ui->statusButton->setProperty("status", "offline");
+ Style::repolish(ui->statusButton);
+
+ // Disable some widgets until we're connected to the DHT
+ ui->statusButton->setEnabled(false);
+
+ Style::setThemeColor(Settings::getInstance().getThemeColor());
+ Style::setThemeColor(1);
+ reloadTheme();
+
+ connect(ui->nameLabel, &CroppingLabel::textChanged, this, &AndroidGUI::onUsernameChanged);
+ connect(ui->statusLabel, &CroppingLabel::textChanged, this, &AndroidGUI::onStatusMessageChanged);
}
AndroidGUI::~AndroidGUI()
{
- delete l;
+ delete profilePicture;
+ delete contactListWidget;
}
+
+void AndroidGUI::reloadTheme()
+{
+ QString statusPanelStyle = Style::getStylesheet(":/ui/window/statusPanel.css");
+ ui->tooliconsZone->setStyleSheet(Style::resolve("QPushButton{background-color:@themeDark;border:none;}QPushButton:hover{background-color:@themeMediumDark;border:none;}"));
+ ui->statusPanel->setStyleSheet(statusPanelStyle);
+ ui->statusHead->setStyleSheet(statusPanelStyle);
+ ui->friendList->setStyleSheet(Style::getStylesheet(":ui/friendList/friendList.css"));
+ ui->statusButton->setStyleSheet(Style::getStylesheet(":ui/statusButton/statusButton.css"));
+
+ for (Friend* f : FriendList::getAllFriends())
+ f->getFriendWidget()->reloadTheme();
+
+ for (Group* g : GroupList::getAllGroups())
+ g->getGroupWidget()->reloadTheme();
+}
+
+void AndroidGUI::onSelfAvatarLoaded(const QPixmap& pic)
+{
+ profilePicture->setPixmap(pic);
+}
+
+void AndroidGUI::onConnected()
+{
+ ui->statusButton->setEnabled(true);
+ if (beforeDisconnect == Status::Offline)
+ emit statusSet(Status::Online);
+ else
+ emit statusSet(beforeDisconnect);
+}
+
+void AndroidGUI::onDisconnected()
+{
+ QString stat = ui->statusButton->property("status").toString();
+ if (stat == "online")
+ beforeDisconnect = Status::Online;
+ else if (stat == "busy")
+ beforeDisconnect = Status::Busy;
+ else if (stat == "away")
+ beforeDisconnect = Status::Away;
+ else
+ beforeDisconnect = Status::Offline;
+
+ ui->statusButton->setEnabled(false);
+ emit statusSet(Status::Offline);
+}
+
+void AndroidGUI::onUsernameChanged(const QString& newUsername, const QString& oldUsername)
+{
+ setUsername(oldUsername); // restore old username until Core tells us to set it
+ Nexus::getCore()->setUsername(newUsername);
+}
+
+void AndroidGUI::setUsername(const QString& username)
+{
+ ui->nameLabel->setText(username);
+ ui->nameLabel->setToolTip(username); // for overlength names
+ QString sanename = username;
+ sanename.remove(QRegExp("[\\t\\n\\v\\f\\r\\x0000]"));
+ nameMention = QRegExp("\\b" + QRegExp::escape(username) + "\\b", Qt::CaseInsensitive);
+ sanitizedNameMention = QRegExp("\\b" + QRegExp::escape(sanename) + "\\b", Qt::CaseInsensitive);
+}
+
+void AndroidGUI::onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage)
+{
+ ui->statusLabel->setText(oldStatusMessage); // restore old status message until Core tells us to set it
+ ui->statusLabel->setToolTip(oldStatusMessage); // for overlength messsages
+ Nexus::getCore()->setStatusMessage(newStatusMessage);
+}
+
+void AndroidGUI::setStatusMessage(const QString &statusMessage)
+{
+ ui->statusLabel->setText(statusMessage);
+ ui->statusLabel->setToolTip(statusMessage); // for overlength messsages
+}
+
+void AndroidGUI::onStatusSet(Status status)
+{
+ //We have to use stylesheets here, there's no way to
+ //prevent the button icon from moving when pressed otherwise
+ switch (status)
+ {
+ case Status::Online:
+ ui->statusButton->setProperty("status" ,"online");
+ break;
+ case Status::Away:
+ ui->statusButton->setProperty("status" ,"away");
+ break;
+ case Status::Busy:
+ ui->statusButton->setProperty("status" ,"busy");
+ break;
+ case Status::Offline:
+ ui->statusButton->setProperty("status" ,"offline");
+ break;
+ }
+ Style::repolish(ui->statusButton);
+}
+
diff --git a/src/widget/androidgui.h b/src/widget/androidgui.h
index 853483ce2..c820bb878 100644
--- a/src/widget/androidgui.h
+++ b/src/widget/androidgui.h
@@ -1,9 +1,15 @@
#ifndef ANDROIDGUI_H
#define ANDROIDGUI_H
+#include "src/corestructs.h"
#include
-class QLabel;
+class MaskablePixmapWidget;
+class FriendListWidget;
+
+namespace Ui {
+class Android;
+}
class AndroidGUI : public QWidget
{
@@ -12,8 +18,35 @@ public:
explicit AndroidGUI(QWidget *parent = 0);
~AndroidGUI();
+public slots:
+ void onConnected();
+ void onDisconnected();
+ void onStatusSet(Status status);
+ void onSelfAvatarLoaded(const QPixmap &pic);
+ void setUsername(const QString& username);
+ void setStatusMessage(const QString &statusMessage);
+
+signals:
+ void friendRequestAccepted(const QString& userId);
+ void friendRequested(const QString& friendAddress, const QString& message);
+ void statusSet(Status status);
+ void statusSelected(Status status);
+ void usernameChanged(const QString& username);
+ void statusMessageChanged(const QString& statusMessage);
+
private:
- QLabel* l;
+ void reloadTheme();
+
+private slots:
+ void onUsernameChanged(const QString& newUsername, const QString& oldUsername);
+ void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage);
+
+private:
+ Ui::Android* ui;
+ MaskablePixmapWidget* profilePicture;
+ FriendListWidget* contactListWidget;
+ Status beforeDisconnect = Status::Offline;
+ QRegExp nameMention, sanitizedNameMention;
};
#endif // ANDROIDGUI_H
diff --git a/src/widget/gui.cpp b/src/widget/gui.cpp
index d6b8a7dc0..12515fc3c 100644
--- a/src/widget/gui.cpp
+++ b/src/widget/gui.cpp
@@ -73,6 +73,19 @@ void GUI::reloadTheme()
}
}
+void GUI::showInfo(const QString& title, const QString& msg)
+{
+ if (QThread::currentThread() == qApp->thread())
+ {
+ getInstance()._showInfo(title, msg);
+ }
+ else
+ {
+ QMetaObject::invokeMethod(&getInstance(), "_showInfo", Qt::BlockingQueuedConnection,
+ Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
+ }
+}
+
void GUI::showWarning(const QString& title, const QString& msg)
{
if (QThread::currentThread() == qApp->thread())
@@ -86,15 +99,15 @@ void GUI::showWarning(const QString& title, const QString& msg)
}
}
-void GUI::showInfo(const QString& title, const QString& msg)
+void GUI::showError(const QString& title, const QString& msg)
{
if (QThread::currentThread() == qApp->thread())
{
- getInstance()._showInfo(title, msg);
+ getInstance()._showError(title, msg);
}
else
{
- QMetaObject::invokeMethod(&getInstance(), "_showInfo", Qt::BlockingQueuedConnection,
+ QMetaObject::invokeMethod(&getInstance(), "_showError", Qt::BlockingQueuedConnection,
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
}
}
@@ -182,14 +195,19 @@ void GUI::_reloadTheme()
#endif
}
+void GUI::_showInfo(const QString& title, const QString& msg)
+{
+ QMessageBox::information(getMainWidget(), title, msg);
+}
+
void GUI::_showWarning(const QString& title, const QString& msg)
{
QMessageBox::warning(getMainWidget(), title, msg);
}
-void GUI::_showInfo(const QString& title, const QString& msg)
+void GUI::_showError(const QString& title, const QString& msg)
{
- QMessageBox::information(getMainWidget(), title, msg);
+ QMessageBox::critical(getMainWidget(), title, msg);
}
bool GUI::_askQuestion(const QString& title, const QString& msg,
diff --git a/src/widget/gui.h b/src/widget/gui.h
index 70cc73a7c..926685467 100644
--- a/src/widget/gui.h
+++ b/src/widget/gui.h
@@ -23,10 +23,12 @@ public:
static void setWindowTitle(const QString& title);
/// Reloads the application theme and redraw the window
static void reloadTheme();
- /// Show a warning to the user, for example in a message box
- static void showWarning(const QString& title, const QString& msg);
/// Show some text to the user, for example in a message box
static void showInfo(const QString& title, const QString& msg);
+ /// Show a warning to the user, for example in a message box
+ static void showWarning(const QString& title, const QString& msg);
+ /// Show an error to the user, for example in a message box
+ static void showError(const QString& title, const QString& msg);
/// Asks the user a question, for example in a message box.
/// If warning is true, we will use a special warning style.
/// Returns the answer.
@@ -57,8 +59,9 @@ private slots:
void _setEnabled(bool state);
void _setWindowTitle(const QString& title);
void _reloadTheme();
- void _showWarning(const QString& title, const QString& msg);
void _showInfo(const QString& title, const QString& msg);
+ void _showWarning(const QString& title, const QString& msg);
+ void _showError(const QString& title, const QString& msg);
bool _askQuestion(const QString& title, const QString& msg,
bool defaultAns = false, bool warning = true);
QString _itemInputDialog(QWidget * parent, const QString & title,
diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp
index 3868e1ece..f6cd0ab6f 100644
--- a/src/widget/widget.cpp
+++ b/src/widget/widget.cpp
@@ -1133,8 +1133,10 @@ void Widget::clearAllReceipts()
void Widget::reloadTheme()
{
+ QString statusPanelStyle = Style::getStylesheet(":/ui/window/statusPanel.css");
ui->tooliconsZone->setStyleSheet(Style::resolve("QPushButton{background-color:@themeDark;border:none;}QPushButton:hover{background-color:@themeMediumDark;border:none;}"));
- ui->statusPanel->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css"));
+ ui->statusPanel->setStyleSheet(statusPanelStyle);
+ ui->statusHead->setStyleSheet(statusPanelStyle);
ui->friendList->setStyleSheet(Style::getStylesheet(":ui/friendList/friendList.css"));
ui->statusButton->setStyleSheet(Style::getStylesheet(":ui/statusButton/statusButton.css"));
diff --git a/ui/window/statusPanel.css b/ui/window/statusPanel.css
index 2c9b77d7a..536c50918 100644
--- a/ui/window/statusPanel.css
+++ b/ui/window/statusPanel.css
@@ -12,12 +12,19 @@ QLineEdit
background-color: @themeDark;
}
+#statusPanel > #statusHead
+{
+ background-color: @themeDark;
+}
+
#statusPanel > #statusHead > #nameLabel {
+ background-color: @themeDark;
font: @extraBig;
color: @white;
}
#statusPanel > #statusHead > #statusLabel {
+ background-color: @themeDark;
font: @medium;
color: @lightGrey;
}