refactor: implement new lrc api
- use new lrc models for
- smartlist
- conversation view
- account selector
Change-Id: I0a009d4e9be6f84100f49ba176d853e05364c351
diff --git a/RingWinClient.pro b/RingWinClient.pro
index 06c6805..af7e37b 100644
--- a/RingWinClient.pro
+++ b/RingWinClient.pro
@@ -41,7 +41,7 @@
}
SOURCES += main.cpp\
- mainwindow.cpp \
+ mainwindow.cpp \
callwidget.cpp \
configurationwidget.cpp \
navwidget.cpp \
@@ -59,13 +59,11 @@
videooverlay.cpp \
imdelegate.cpp \
contactpicker.cpp \
- contactmethodpicker.cpp \
globalsystemtray.cpp \
- smartlistdelegate.cpp \
+ conversationitemdelegate.cpp \
+ conversationsfilterwidget.cpp \
callutilsdialog.cpp \
- combar.cpp \
idlabel.cpp \
- smartlist.cpp \
ringcontactlineedit.cpp \
pixbufmanipulator.cpp \
qualitydialog.cpp \
@@ -74,13 +72,16 @@
sendcontactrequestwidget.cpp \
currentaccountwidget.cpp \
contactrequestwidget.cpp \
- contactrequestitemdelegate.cpp \
- quickactcontactrequestwidget.cpp \
- contactrequestlistwidget.cpp \
+ smartlistselectorbuttonnotifier.cpp \
deleteaccountdialog.cpp \
bannedcontactswidget.cpp \
photoboothwidget.cpp \
- deletecontactdialog.cpp
+ smartlistmodel.cpp \
+ smartlistview.cpp \
+ accountitemdelegate.cpp \
+ accountlistmodel.cpp \
+ messagemodel.cpp \
+ invitebuttonswidget.cpp
HEADERS += mainwindow.h \
callwidget.h \
@@ -100,14 +101,12 @@
videooverlay.h \
imdelegate.h \
contactpicker.h \
- contactmethodpicker.h \
settingskey.h \
globalsystemtray.h \
- smartlistdelegate.h \
+ conversationitemdelegate.h \
+ conversationsfilterwidget.h \
callutilsdialog.h \
- combar.h \
idlabel.h \
- smartlist.h \
ringcontactlineedit.h \
pixbufmanipulator.h \
qualitydialog.h \
@@ -117,14 +116,17 @@
sendcontactrequestwidget.h \
currentaccountwidget.h \
contactrequestwidget.h \
- contactrequestitemdelegate.h \
- quickactcontactrequestwidget.h \
- contactrequestlistwidget.h \
+ smartlistselectorbuttonnotifier.h \
deleteaccountdialog.h \
bannedcontactswidget.h \
photoboothwidget.h \
- deletecontactdialog.h \
- lrcinstance.h
+ lrcinstance.h \
+ smartlistmodel.h \
+ smartlistview.h \
+ accountitemdelegate.h \
+ accountlistmodel.h \
+ messagemodel.h \
+ invitebuttonswidget.h
contains(DEFINES, URI_PROTOCOL) {
HEADERS += shmclient.h
@@ -141,20 +143,17 @@
videoview.ui \
videooverlay.ui \
contactpicker.ui \
- contactmethodpicker.ui \
callutilsdialog.ui \
- combar.ui \
qualitydialog.ui \
ringbutton.ui \
photoboothdialog.ui \
sendcontactrequestwidget.ui \
currentaccountwidget.ui \
contactrequestwidget.ui \
- quickactcontactrequestwidget.ui \
deleteaccountdialog.ui \
bannedcontactswidget.ui \
photoboothwidget.ui \
- deletecontactdialog.ui
+ invitebuttonswidget.ui
win32: LIBS += -lole32 -luuid -lshlwapi -lgdi32
LIBS += -lqrencode
diff --git a/accountitemdelegate.cpp b/accountitemdelegate.cpp
new file mode 100644
index 0000000..346d750
--- /dev/null
+++ b/accountitemdelegate.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "accountitemdelegate.h"
+
+#include <QApplication>
+#include <QTextDocument>
+#include <QPixmap>
+
+#include "utils.h"
+#include "accountlistmodel.h"
+#include "ringthemeutils.h"
+
+#undef REGISTERED
+
+AccountItemDelegate::AccountItemDelegate(QObject *parent)
+ : QItemDelegate(parent)
+{
+}
+
+void
+AccountItemDelegate::paint(QPainter* painter,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index) const
+{
+ QStyleOptionViewItem opt(option);
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ // Not having focus removes dotted lines around the item
+ if (opt.state & QStyle::State_HasFocus) {
+ opt.state.setFlag(QStyle::State_HasFocus, false);
+ }
+
+ // First, we draw the control itself
+ QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
+
+ bool selected = false;
+ if (option.state & QStyle::State_Selected) {
+ selected = true;
+ opt.state ^= QStyle::State_Selected;
+ painter->fillRect(option.rect, RingTheme::smartlistSelection_);
+ }
+ else if (option.state & QStyle::State_MouseOver) {
+ painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
+ }
+
+ QRect &rect = opt.rect;
+
+ // Avatar drawing
+ opt.decorationSize = QSize(avatarSize_, avatarSize_);
+ opt.decorationPosition = QStyleOptionViewItem::Left;
+ opt.decorationAlignment = Qt::AlignCenter;
+
+ QRect rectAvatar(dy_ + rect.left(), rect.top() + dy_, avatarSize_, avatarSize_);
+ drawDecoration(painter, opt, rectAvatar,
+ QPixmap::fromImage(index.data(AccountListModel::Role::Picture).value<QImage>())
+ .scaled(avatarSize_, avatarSize_, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+
+ QFont font(painter->font());
+
+ // Presence indicator
+ QPainterPath outerCircle, innerCircle;
+ QPointF center(rectAvatar.right() - avatarSize_ / 6, (rectAvatar.bottom() - avatarSize_ / 6) + 1);
+ qreal outerCRadius = avatarSize_ / 6, innerCRadius = outerCRadius * 0.75;
+ outerCircle.addEllipse(center, outerCRadius, outerCRadius);
+ innerCircle.addEllipse(center, innerCRadius, innerCRadius);
+ auto status = index.data(static_cast<int>(AccountListModel::Role::Status)).value<int>();
+ auto isPresent = Utils::toEnum<lrc::api::account::Status>(status) == lrc::api::account::Status::REGISTERED;
+ if (isPresent) {
+ painter->fillPath(outerCircle, Qt::white);
+ painter->fillPath(innerCircle, RingTheme::presenceGreen_);
+ }
+
+ font.setPointSize(fontSize_);
+ QPen pen(painter->pen());
+
+ painter->setPen(pen);
+
+ QRect rectTexts(dx_ + rect.left() + dx_ + avatarSize_,
+ rect.top(),
+ rect.width(),
+ rect.height() / 2);
+
+ // The name is displayed at the avatar's right
+ QVariant name = index.data(static_cast<int>(AccountListModel::Role::Alias));
+ if (name.isValid())
+ {
+ font.setItalic(false);
+ font.setBold(true);
+ pen.setColor(RingTheme::lightBlack_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ QFontMetrics fontMetrics(font);
+ QString nameStr = fontMetrics.elidedText(name.value<QString>(), Qt::ElideRight,
+ rectTexts.width() - avatarSize_ - dx_);
+ painter->drawText(rectTexts, Qt::AlignVCenter | Qt::AlignLeft, nameStr);
+ }
+
+ // Display the ID under the name
+ QString idStr = index.data(static_cast<int>(AccountListModel::Role::Username)).value<QString>();
+ if (idStr != name.toString()) {
+ font.setItalic(false);
+ font.setBold(false);
+ pen.setColor(RingTheme::grey_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ QFontMetrics fontMetrics(font);
+ if (!idStr.isNull()) {
+ idStr = fontMetrics.elidedText(idStr, Qt::ElideRight,
+ rectTexts.width() - avatarSize_ - dx_ * 2);
+ painter->drawText(QRect(dx_ + rect.left() + dx_ + avatarSize_,
+ rect.top() + dy_ * 3,
+ rect.width(),
+ rect.height() / 2),
+ Qt::AlignBottom | Qt::AlignLeft, idStr);
+ }
+ }
+}
+
+QSize AccountItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
+{
+ QSize size = QItemDelegate::sizeHint(option, index);
+ size.setHeight(cellHeight_);
+ return size;
+}
diff --git a/smartlistdelegate.h b/accountitemdelegate.h
similarity index 78%
rename from smartlistdelegate.h
rename to accountitemdelegate.h
index 2b5e413..c3a798c 100644
--- a/smartlistdelegate.h
+++ b/accountitemdelegate.h
@@ -1,6 +1,6 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -15,29 +15,26 @@
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
-
#pragma once
-#include <QObject>
+#include <QPainter>
#include <QItemDelegate>
-class QPainter;
-
-class SmartListDelegate : public QItemDelegate
+class AccountItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
- explicit SmartListDelegate(QObject* parent = 0);
+ explicit AccountItemDelegate(QObject *parent = nullptr);
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
- constexpr static int sizeImage_ = 48;
- constexpr static int cellHeight_ = 60;
+ constexpr static int fontSize_ = 10;
+ const QFont font_ = QFont("Arial", fontSize_);
constexpr static int dy_ = 6;
constexpr static int dx_ = 12;
- constexpr static int fontSize_ = 10;
- constexpr static int effectiveComBarSize_ = 48;
+ constexpr static int avatarSize_ = 36;
+ constexpr static int cellHeight_ = 48;
};
diff --git a/accountlistmodel.cpp b/accountlistmodel.cpp
new file mode 100644
index 0000000..fb7b2da
--- /dev/null
+++ b/accountlistmodel.cpp
@@ -0,0 +1,105 @@
+/***************************************************************************
+* Copyright (C) 2018 by Savoir-faire Linux *
+* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+* *
+* 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/>. *
+***************************************************************************/
+
+#include "accountlistmodel.h"
+
+// Qt
+#include <QDateTime>
+
+// LRC
+#include "globalinstances.h"
+
+// Client
+#include "pixbufmanipulator.h"
+#include "lrcinstance.h"
+#include "utils.h"
+
+AccountListModel::AccountListModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+}
+
+int AccountListModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid()) {
+ return LRCInstance::accountModel().getAccountList().size(); // count
+ }
+ return 0; // A valid QModelIndex returns 0 as no entry has sub-elements
+}
+
+int AccountListModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 1;
+}
+
+QVariant AccountListModel::data(const QModelIndex &index, int role) const
+{
+ auto accountList = LRCInstance::accountModel().getAccountList();
+ if (!index.isValid() || accountList.size() == 0) {
+ return QVariant();
+ }
+
+ auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountList.at(index.row()));
+
+ switch (role) {
+ case Role::Alias:
+ case Qt::DisplayRole:
+ return QVariant(QString::fromStdString(accountInfo.profileInfo.alias));
+ case Role::Username:
+ return QVariant(QString::fromStdString(accountInfo.profileInfo.uri));
+ case Role::Type:
+ return QVariant(Utils::toUnderlyingValue<lrc::api::profile::Type>(accountInfo.profileInfo.type));
+ case Role::Status:
+ return QVariant(Utils::toUnderlyingValue<lrc::api::account::Status>(accountInfo.status));
+ case Role::Picture:
+ case Qt::DecorationRole:
+ return PixbufManipulator::accountPhoto(accountInfo);
+ case Role::ID:
+ return QVariant(QString::fromStdString(accountInfo.id));
+ }
+ return QVariant();
+}
+
+QModelIndex AccountListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ if (column != 0) {
+ return QModelIndex();
+ }
+
+ if (row >= 0 && row < rowCount()) {
+ return createIndex(row, column);
+ }
+ return QModelIndex();
+}
+
+QModelIndex AccountListModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child);
+ return QModelIndex();
+}
+
+Qt::ItemFlags AccountListModel::flags(const QModelIndex &index) const
+{
+ auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+ if (!index.isValid()) {
+ return QAbstractItemModel::flags(index);
+ }
+ return flags;
+}
diff --git a/accountlistmodel.h b/accountlistmodel.h
new file mode 100644
index 0000000..127cb88
--- /dev/null
+++ b/accountlistmodel.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+* Copyright (C) 2018 by Savoir-faire Linux *
+* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+* *
+* 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/>. *
+***************************************************************************/
+#pragma once
+
+// Qt include
+#include <QAbstractItemModel>
+
+// LRC
+#include "api/account.h"
+#include "api/conversation.h"
+#include "api/contact.h"
+
+class AccountListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ enum Role {
+ Alias = Qt::UserRole + 1,
+ Username,
+ Picture,
+ Type,
+ Status,
+ ID
+ };
+
+ explicit AccountListModel(QObject *parent = 0);
+
+ // QAbstractItemModel
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+};
diff --git a/callutilsdialog.cpp b/callutilsdialog.cpp
index db2453b..5e41620 100644
--- a/callutilsdialog.cpp
+++ b/callutilsdialog.cpp
@@ -34,7 +34,7 @@
QDialog(parent),
ui(new Ui::CallUtilsDialog),
confMode_(false),
- smartListDelegate_(nullptr),
+ conversationItemDelegate_(nullptr),
notCurrentProxyModel_(nullptr),
spikeMask_(new QPixmap(":/images/spikeMask.png"))
{
@@ -62,7 +62,7 @@
delete effect_;
delete spikeMask_;
delete fadeAnim_;
- delete smartListDelegate_;
+ delete conversationItemDelegate_;
delete notCurrentProxyModel_;
delete ui;
}
@@ -77,10 +77,10 @@
notCurrentProxyModel_ = new NotCurrentProxyModel(&RecentModel::instance());
}
ui->contactView->setModel(notCurrentProxyModel_);
- if (not smartListDelegate_) {
- smartListDelegate_ = new SmartListDelegate();
+ if (not conversationItemDelegate_) {
+ conversationItemDelegate_ = new ConversationItemDelegate();
}
- ui->contactView->setItemDelegate(smartListDelegate_);
+ ui->contactView->setItemDelegate(conversationItemDelegate_);
emit(isVisible(true));
diff --git a/callutilsdialog.h b/callutilsdialog.h
index 0ab4491..e4b9130 100644
--- a/callutilsdialog.h
+++ b/callutilsdialog.h
@@ -24,7 +24,7 @@
#include "callmodel.h"
#include "recentmodel.h"
-#include "smartlistdelegate.h"
+#include "conversationitemdelegate.h"
#include <ciso646>
@@ -79,7 +79,7 @@
private:
Ui::CallUtilsDialog* ui;
bool confMode_;
- SmartListDelegate* smartListDelegate_;
+ ConversationItemDelegate* conversationItemDelegate_;
NotCurrentProxyModel* notCurrentProxyModel_;
QPixmap* spikeMask_;
QPropertyAnimation* fadeAnim_;
diff --git a/callwidget.cpp b/callwidget.cpp
index e15cf7d..e41a38e 100644
--- a/callwidget.cpp
+++ b/callwidget.cpp
@@ -1,8 +1,9 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Copyright (C) 2015-2018 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -33,41 +34,22 @@
#undef ERROR
#undef interface
-//LRC
-#include "audio/settings.h"
-#include "accountmodel.h"
-#include "personmodel.h"
-#include "person.h"
-#include "fallbackpersoncollection.h"
-#include "categorizedcontactmodel.h"
-#include "localhistorycollection.h"
-#include "media/text.h"
-#include "media/recording.h"
-#include "media/recordingmodel.h"
-#include "recentmodel.h"
-#include "contactmethod.h"
+// lrc
#include "globalinstances.h"
-#include <availableaccountmodel.h>
-#include "pendingcontactrequestmodel.h"
#include "profilemodel.h"
-#include "profile.h"
-#include "peerprofilecollection.h"
#include "localprofilecollection.h"
-#include "callmodel.h"
-//Client
+// client
#include "wizarddialog.h"
#include "windowscontactbackend.h"
#include "contactpicker.h"
-#include "contactmethodpicker.h"
#include "globalsystemtray.h"
-#include "smartlistdelegate.h"
+#include "conversationitemdelegate.h"
#include "imdelegate.h"
#include "pixbufmanipulator.h"
#include "settingskey.h"
-#include "contactrequestitemdelegate.h"
-#include "deletecontactdialog.h"
-
+#include "lrcinstance.h"
+#include "messagemodel.h"
CallWidget::CallWidget(QWidget* parent) :
NavWidget(parent),
@@ -77,15 +59,9 @@
{
ui->setupUi(this);
- pageAnim_ = new QPropertyAnimation(ui->welcomePage, "pos", this);
+ using namespace lrc::api;
- setActualCall(nullptr);
- videoRenderer_ = nullptr;
-
- connect(ui->settingsButton, &QPushButton::clicked, this, &CallWidget::settingsButtonClicked);
-
- connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
- ui->instantMessagingWidget, SLOT(setVisible(bool)));
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
QPixmap logo(":/images/logo-ring-standard-coul.png");
ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
@@ -93,106 +69,92 @@
ui->qrLabel->hide();
- try {
- callModel_ = &CallModel::instance();
+ videoRenderer_ = nullptr;
- connect(callModel_, SIGNAL(incomingCall(Call*)),
- this, SLOT(callIncoming(Call*)));
- connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
- this, SLOT(callStateChanged(Call*, Call::State)));
+ // this line is not welcome here, and must be removed
+ ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
- RecentModel::instance().peopleProxy()->setFilterRole(static_cast<int>(Ring::Role::Name));
- RecentModel::instance().peopleProxy()->setFilterCaseSensitivity(Qt::CaseInsensitive);
- ui->smartList->setModel(RecentModel::instance().peopleProxy());
-
- PersonModel::instance().addCollection<PeerProfileCollection>(LoadOptions::FORCE_ENABLED);
- ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
-
- PersonModel::instance().
- addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
-
- connect(ui->smartList, &QTreeView::entered, this, &CallWidget::on_entered);
-
- smartListDelegate_ = new SmartListDelegate();
- ui->smartList->setSmartListItemDelegate(smartListDelegate_);
-
- ui->contactRequestList->setItemDelegate(new ContactRequestItemDelegate());
-
- ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
-
- connect(ui->smartList, &SmartList::btnVideoClicked, this, &CallWidget::btnComBarVideoClicked);
-
- connect(RecentModel::instance().selectionModel(),
- SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this,
- SLOT(smartListCurrentChanged(QModelIndex,QModelIndex)));
-
- //set most recent call to view
- connect(&RecentModel::instance(), &QAbstractItemModel::dataChanged, [=](const QModelIndex &topLeft, const QModelIndex &bottomRight,const QVector<int> &vec){
- Q_UNUSED(bottomRight)
- Q_UNUSED(vec)
-
- if (topLeft.isValid() && RecentModel::instance().hasActiveCall(topLeft)){
- ui->smartList->selectionModel()->setCurrentIndex(topLeft,QItemSelectionModel::ClearAndSelect);
+ // select last used account if stored in registry
+ auto accountList = LRCInstance::accountModel().getAccountList();
+ if (!accountList.empty()) {
+ std::string accountIdToStartWith;
+ QSettings settings;
+ if (settings.contains(SettingsKey::selectedAccount)) {
+ accountIdToStartWith = settings
+ .value(SettingsKey::selectedAccount, true)
+ .value<QString>()
+ .toStdString();
+ if (Utils::indexInVector(accountList, accountIdToStartWith) == -1) {
+ accountIdToStartWith = accountList.at(0);
}
- });
-
- connect(RecentModel::instance().selectionModel(), &QItemSelectionModel::selectionChanged, [=](const QItemSelection &selected, const QItemSelection &deselected) {
- // lambda used to focus on the correct smartList element when switching automatically between two calls
- Q_UNUSED(deselected)
- if (selected.size()) {
- auto idx = selected.indexes().first();
- auto realIdx = RecentModel::instance().peopleProxy()->mapFromSource(idx);
- ui->smartList->selectionModel()->setCurrentIndex(realIdx, QItemSelectionModel::ClearAndSelect);
- } else {
- RecentModel::instance().selectionModel()->clearCurrentIndex();
- ui->smartList->clearSelection();
- ui->smartList->selectionModel()->clearCurrentIndex();
- }
- });
-
- connect(&NameDirectory::instance(), SIGNAL(registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)),
- this, SLOT(contactLineEdit_registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)));
-
- connect(&AccountModel::instance(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- ui->currentAccountWidget, SLOT(update()));
-
- connect(ui->searchBtn, SIGNAL(clicked(bool)), this, SLOT(searchBtnClicked()));
-
- connect(ui->sendContactRequestWidget, &SendContactRequestWidget::sendCRclicked, [=]{Utils::slidePage(ui->stackedWidget, ui->messagingPage);});
-
- connect(ui->contactRequestWidget, &ContactRequestWidget::choiceMade, [this]() {
- if (getSelectedAccount()->pendingContactRequestModel()->rowCount() == 0)
- ui->mainTabMenu->setCurrentWidget(ui->mainTabMenuPage1);
- else
- ui->contactRequestList->selectionModel()->clear();
- });
-
- connect(AvailableAccountModel::instance().selectionModel(), &QItemSelectionModel::currentChanged,
- this, &CallWidget::selectedAccountChanged);
-
- // It needs to be called manually once to initialize the ui with the account selected at start.
- // The second argument (previous) is set to an invalid QModelIndex as it is the first selection.
- selectedAccountChanged(AvailableAccountModel::instance().selectionModel()->currentIndex(), QModelIndex());
-
- // This connect() is used to initialise and track changes of profile's picture
- connect(&ProfileModel::instance(), &ProfileModel::dataChanged,
- ui->currentAccountWidget, &CurrentAccountWidget::setPhoto);
-
- connect(ui->videoWidget, &VideoView::videoSettingsClicked, this, &CallWidget::settingsButtonClicked);
-
- connect(ui->smartList, &QListView::customContextMenuRequested, [=](const QPoint& pos){ setupSmartListMenu(pos);});
-
- // setup searchingfor mini spinner
- miniSpinner_ = new QMovie(":/images/waiting.gif");
- ui->spinnerLabel->setMovie(miniSpinner_);
- ui->spinnerLabel->hide();
-
- } catch (const std::exception& e) {
- qDebug() << "INIT ERROR" << e.what();
+ }
+ else {
+ accountIdToStartWith = accountList.at(0);
+ }
+ setSelectedAccount(accountIdToStartWith);
+ // get account index and set the currentAccountWidget selector
+ auto index = Utils::indexInVector(accountList, accountIdToStartWith);
+ if (index != -1) {
+ ui->currentAccountWidget->changeSelectedIndex(index);
+ }
}
+ // conversation list
+ conversationItemDelegate_ = new ConversationItemDelegate();
+ ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ // setup searchingfor mini spinner
+ miniSpinner_ = new QMovie(":/images/waiting.gif");
+ ui->spinnerLabel->setMovie(miniSpinner_);
+ ui->spinnerLabel->hide();
+
+ // set to welcome view
+ ui->stackedWidget->setCurrentWidget(ui->welcomePage);
setupOutOfCallIM();
+
+ // connections
+ connect(ui->settingsButton, &QPushButton::clicked,
+ this, &CallWidget::settingsButtonClicked);
+
+ connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
+ ui->instantMessagingWidget, SLOT(setVisible(bool)));
+
+ connect(ui->videoWidget, &VideoView::videoSettingsClicked,
+ this, &CallWidget::settingsButtonClicked);
+
+ connect(ui->buttonConversations, &QPushButton::clicked,
+ this, &CallWidget::conversationsButtonClicked);
+
+ connect(ui->buttonInvites, &QPushButton::clicked,
+ this, &CallWidget::invitationsButtonClicked);
+
+ connect(ui->currentAccountWidget, &CurrentAccountWidget::currentAccountChanged,
+ this, &CallWidget::currentAccountChanged);
+
+ // TODO(new lrc)
+ connect(&ProfileModel::instance(), &ProfileModel::dataChanged,
+ ui->currentAccountWidget, &CurrentAccountWidget::setPhoto);
+
+ connect(ui->smartList, &QListView::customContextMenuRequested,
+ this, &CallWidget::slotCustomContextMenuRequested);
+
+ connect(ui->smartList, &SmartListView::btnAcceptInviteClicked,
+ this, &CallWidget::slotAcceptInviteClicked);
+
+ connect(ui->smartList, &SmartListView::btnBlockInviteClicked,
+ this, &CallWidget::slotBlockInviteClicked);
+
+ connect(ui->smartList, &SmartListView::btnIgnoreInviteClicked,
+ this, &CallWidget::slotIgnoreInviteClicked);
+
+ connect(&LRCInstance::behaviorController(), &BehaviorController::showCallView,
+ this, &CallWidget::slotShowCallView);
+
+ connect(&LRCInstance::behaviorController(), &BehaviorController::showIncomingCallView,
+ this, &CallWidget::slotShowIncomingCallView);
+
+ connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView,
+ this, &CallWidget::slotShowChatView);
}
CallWidget::~CallWidget()
@@ -200,9 +162,7 @@
delete ui;
delete menu_;
delete imDelegate_;
- delete pageAnim_;
- delete smartListDelegate_;
- delete shareMenu_;
+ delete conversationItemDelegate_;
}
void
@@ -221,131 +181,108 @@
QApplication::clipboard()->setText(text.value<QString>());
}
});
-
- QSettings settings;
-
- auto displayDate = new QAction(tr("Display date"), this);
- displayDate->setCheckable(true);
- displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
- ui->listMessageView->addAction(displayDate);
-
- auto displayAuthor = new QAction(tr("Display author"), this);
- displayAuthor->setCheckable(true);
- displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
- ui->listMessageView->addAction(displayAuthor);
-
- auto lamdba = [=](){
- QSettings settings;
- settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
- settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
- emit imDelegate_->sizeHintChanged(QModelIndex());
- };
-
- connect(displayAuthor, &QAction::triggered, lamdba);
- connect(displayDate, &QAction::triggered, lamdba);
-
- connect(&::media::RecordingModel::instance(),
- SIGNAL(newTextMessage(::media::TextRecording*, ContactMethod*)),
- this,
- SLOT(onIncomingMessage(::media::TextRecording*, ContactMethod*)));
}
void
-CallWidget::onIncomingMessage(::media::TextRecording* t, ContactMethod* cm)
+CallWidget::onIncomingMessage(const std::string& convUid,
+ uint64_t interactionId,
+ const lrc::api::interaction::Info& interaction)
{
- Q_UNUSED(cm)
-
+ Q_UNUSED(interactionId);
if (!QApplication::focusWidget()) {
- auto idx = t->instantTextMessagingModel()->
- index(t->instantTextMessagingModel()->rowCount()-1, 0);
- GlobalSystemTray::instance()
- .showMessage("Ring",
- QString(tr("Message incoming from %1")).arg(
- idx.data((int)media::TextRecording::Role::AuthorDisplayname).toString()));
- QApplication::alert(this, 5000);
+ Utils::showSystemNotification(this,
+ QString(tr("Message incoming from %1"))
+ .arg(QString::fromStdString(interaction.body)));
}
+ updateConversationView(convUid);
+ ui->conversationsFilterWidget->update();
}
void
-CallWidget::triggerDeleteContactDialog(ContactMethod *cm, Account *ac)
+CallWidget::setupSmartListContextMenu(const QPoint& pos)
{
- auto dlg = new DeleteContactDialog(cm, ac);
- dlg->exec();
-}
-
-void
-CallWidget::setupSmartListMenu(const QPoint& pos)
-{
- auto idx = ui->smartList->currentIndex();
-
- if (not idx.isValid())
- return;
-
QPoint globalPos = ui->smartList->mapToGlobal(pos);
- QMenu menu;
- QVector<ContactMethod*> contactMethods = RecentModel::instance()
- .getContactMethods(RecentModel::instance().peopleProxy()->mapToSource(idx));
-
- if (contactMethods.isEmpty())
+ auto index = ui->smartList->indexAt(pos);
+ if (not index.isValid()) {
return;
-
- auto contactMethod = contactMethods.first();
-
- if (contactMethods.size() == 1){
- auto copyAction = new QAction(tr("Copy number"), this);
- menu.addAction(copyAction);
- connect(copyAction, &QAction::triggered, [contactMethod]() {
- QApplication::clipboard()->setText(contactMethod->uri());
- });
-
- auto copyNameAction = new QAction(tr("Copy name"), this);
- menu.addAction(copyNameAction);
- connect(copyNameAction, &QAction::triggered, [contactMethod]() {
- QApplication::clipboard()->setText(contactMethod->primaryName());
- });
- } else {
- auto callMenu = menu.addMenu(tr("Call Number"));
- auto copyMenu = menu.addMenu(tr("Copy Number"));
- for (auto cM : contactMethods) {
- auto uri = cM->bestId();
- auto copyAction = new QAction(tr("Copy %1").arg(uri), this);
- copyMenu->addAction(copyAction);
- connect(copyAction, &QAction::triggered, [uri]() {
- QApplication::clipboard()->setText(uri);
- });
- auto callAction = new QAction(tr("Call %1").arg(uri), this);
- callMenu->addAction(callAction);
- connect(callAction, &QAction::triggered, [cM]() {
- Call* c = CallModel::instance().dialingCall(cM);
- c->performAction(Call::Action::ACCEPT);
- });
- }
}
- auto ac = getSelectedAccount();
- if (ac && !ac->hasContact(contactMethod)) {
- auto addExisting = new QAction(tr("Add to contacts"), this);
- menu.addAction(addExisting);
- connect(addExisting, &QAction::triggered, [this, contactMethod, ac]() {
- /* uncomment and capture globalPos in lambda to reactivate popup
- ContactPicker contactPicker(contactMethod);
- contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
- contactPicker.exec();
- */
- ac->addContact(contactMethod);
- });
- } else if (ac) {
- auto removeExisting = new QAction(tr("Remove from contacts"), this);
- menu.addAction(removeExisting);
- connect(removeExisting, &QAction::triggered, [this, contactMethod, ac]() {
- triggerDeleteContactDialog(contactMethod, ac);
- });
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
+ .value<QString>()
+ .toStdString();
+ auto conversation = Utils::getConversationFromUid(convUid, *convModel);
+ auto contactUid = (*conversation).participants.at(0);
+ auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
+
+ if (!Utils::isContactValid(contactUid, *convModel)) {
+ return;
}
+ QMenu menu;
+
+ // video call
+ auto videoCallAction = new QAction(tr("Start video call"), this);
+ menu.addAction(videoCallAction);
+ connect(videoCallAction, &QAction::triggered,
+ [this, convUid, conversation, convModel]() {
+ convModel->placeCall(convUid);
+ ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
+ if (convUid != selectedConvUid()) {
+ selectConversation(*conversation, *convModel);
+ }
+ });
+ // audio call
+ auto audioCallAction = new QAction(tr("Start audio call"), this);
+ menu.addAction(audioCallAction);
+ connect(audioCallAction, &QAction::triggered,
+ [this, convUid, conversation, convModel]() {
+ convModel->placeAudioOnlyCall(convUid);
+ ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
+ if (convUid != selectedConvUid()) {
+ selectConversation(*conversation, *convModel);
+ }
+ });
+
+ if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
+ // separator
+ menu.addSeparator();
+
+ // clear conversation
+ auto clearConversationAction = new QAction(tr("Clear conversation"), this);
+ menu.addAction(clearConversationAction);
+ connect(clearConversationAction, &QAction::triggered,
+ [convUid]() {
+ LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
+ });
+ // block contact
+ auto blockContactAction = new QAction(tr("Block contact"), this);
+ menu.addAction(blockContactAction);
+ connect(blockContactAction, &QAction::triggered,
+ [convUid]() {
+ LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
+ });
+
+ // separator
+ menu.addSeparator();
+
+ // copy number(infohash)
+ auto copyNumberAction = new QAction(tr("Copy number"), this);
+ menu.addAction(copyNumberAction);
+ connect(copyNumberAction, &QAction::triggered,
+ [contact]() {
+ QApplication::clipboard()->setText(
+ QString::fromStdString(contact.profileInfo.uri)
+ );
+ });
+ }
+ smartListModel_->isContextMenuOpen_ = true;
menu.exec(globalPos);
+ smartListModel_->isContextMenuOpen_ = false;
}
-void CallWidget::setupQRCode(QString ringID)
+void
+CallWidget::setupQRCode(QString ringID)
{
auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
0, //Let the version be decided by libqrencode
@@ -379,24 +316,22 @@
}
painter.end();
QRcode_free(rcode);
- ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_), Qt::KeepAspectRatio)));
+ ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
+ Qt::KeepAspectRatio)));
}
bool
CallWidget::findRingAccount()
{
bool ringAccountFound = false;
- auto a_count = AccountModel::instance().rowCount();
- for (int i = 0; i < a_count; ++i) {
- auto idx = AccountModel::instance().index(i, 0);
- auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
- if (static_cast<Account::Protocol>(protocol.toUInt()) == Account::Protocol::RING) {
+ auto accountList = LRCInstance::accountModel().getAccountList();
+ for (int i = 0; i < accountList.size(); ++i) {
+ auto accountId = accountList.at(i);
+ auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
+ if (accountInfo.profileInfo.type == lrc::api::profile::Type::RING) {
ringAccountFound = true;
- auto account = AccountModel::instance().getAccountByModelIndex(idx);
- if (account->displayName().isEmpty())
- account->displayName() = account->alias();
- if (account->needsMigration()) {
- WizardDialog dlg(WizardDialog::MIGRATION, account);
+ if (accountInfo.status == lrc::api::account::Status::ERROR_NEED_MIGRATION) {
+ WizardDialog dlg(WizardDialog::MIGRATION);
dlg.exec();
}
}
@@ -416,151 +351,80 @@
}
void
-CallWidget::callChangedSlot()
+CallWidget::on_smartList_clicked(const QModelIndex& index)
{
- if (not actualCall_)
- return;
-
- ui->callerIdLabel->setText(QString("%1")
- .arg(actualCall_->formattedName()));
- ui->callerPhoto->setPixmap(
- QPixmap::fromImage(
- GlobalInstances::pixmapManipulator()
- .callPhoto(actualCall_, QSize(128, 128)).value<QImage>()));
- ui->callerBestIdLabel->setText(actualCall_->peerContactMethod()->bestId());
-
- if(actualCall_->state() == Call::State::OVER || actualCall_->state() == Call::State::FAILURE){
- ui->outboundCallLabel->setText(actualCall_->toHumanStateName(Call::State::INITIALIZATION));
- } else {
- ui->outboundCallLabel->setText(actualCall_->toHumanStateName());
- }
-}
-
-void
-CallWidget::callIncoming(Call* call)
-{
- if (!QApplication::focusWidget()) {
- GlobalSystemTray::instance()
- .showMessage("Ring",
- QString(tr("Call incoming from %1")).arg(call->formattedName()));
- QApplication::alert(this, 5000);
- }
-
- setActualCall(call);
+ Q_UNUSED(index);
}
void
CallWidget::on_acceptButton_clicked()
{
- if (actualCall_ != nullptr)
- actualCall_->performAction(Call::Action::ACCEPT);
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto callModel = LRCInstance::getCurrentCallModel();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
+ callModel->accept(conversation->callId);
}
void
CallWidget::on_refuseButton_clicked()
{
- if (actualCall_ == nullptr)
- return;
- actualCall_->performAction(Call::Action::REFUSE);
- ui->stackedWidget->setCurrentWidget(ui->welcomePage);
- setActualCall(nullptr);
-}
-
-void
-CallWidget::callStateChanged(Call* call, Call::State previousState)
-{
- Q_UNUSED(previousState)
- if (call == nullptr
- || call != actualCall_)
- return;
-
- callStateToView(call);
-
- if (call->state() == Call::State::OVER) {
- setActualCall(nullptr);
- ui->smartList->clearSelection();
- RecentModel::instance().selectionModel()->clear();
- }
-}
-
-void
-CallWidget::atExit()
-{
-}
-
-void
-CallWidget::callStateToView(Call* value)
-{
- if (value) {
- switch (value->state()) {
- case Call::State::INCOMING:
- if (not value->account()->isAutoAnswer())
- ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
- else
- ui->stackedWidget->setCurrentWidget(ui->videoPage);
- break;
- case Call::State::CURRENT:
- case Call::State::CONFERENCE:
- case Call::State::HOLD:
- ui->stackedWidget->setCurrentWidget(ui->videoPage);
- hideMiniSpinner();
- break;
- case Call::State::OVER:
- ui->stackedWidget->setCurrentWidget(ui->welcomePage);
- break;
- case Call::State::FAILURE:
- case Call::State::ERROR:
- on_cancelButton_clicked();
- hideMiniSpinner();
- break;
- case Call::State::INITIALIZATION:
- case Call::State::CONNECTED:
- case Call::State::RINGING:
- miniSpinner_->start();
- ui->spinnerLabel->show();
- ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
- break;
- default:
- qWarning() << "Call state not handled doing nothing : "
- << value->toHumanStateName();
- break;
- }
- }
-}
-
-void
-CallWidget::setActualCall(Call* value)
-{
- actualCall_ = value;
- CallModel::instance().selectCall(value);
- ui->videoWidget->pushRenderer(value);
- ui->instantMessagingWidget->setMediaText(actualCall_);
- callStateToView(value);
- if (actualCall_) {
- callChangedConnection_ = connect(actualCall_,
- SIGNAL(changed()),
- this,
- SLOT(callChangedSlot()));
- } else
- disconnect(callChangedConnection_);
-
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
+ LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
+ showConversationView();
}
void
CallWidget::on_cancelButton_clicked()
{
- if (actualCall_){
- actualCall_->performAction(Call::Action::REFUSE);
- ui->stackedWidget->setCurrentWidget(ui->welcomePage);
- }
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
+ LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
+ showConversationView();
}
void
-CallWidget::on_smartList_clicked(const QModelIndex& index)
+CallWidget::showConversationView()
{
- RecentModel::instance().selectionModel()->setCurrentIndex(
- RecentModel::instance().peopleProxy()->mapToSource(index),
- QItemSelectionModel::ClearAndSelect);
+ ui->stackedWidget->setCurrentWidget(ui->messagingPage);
+ ui->imMessageEdit->clear();
+ ui->imMessageEdit->setFocus();
+ disconnect(imClickedConnection_);
+ imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
+ auto urlList = index.data(static_cast<int>(media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
+ if (urlList.size() == 1) {
+ QDesktopServices::openUrl(urlList.at(0));
+ } else if (urlList.size()) {
+ //TODO Handle multiple url in one message
+ }
+ });
+}
+
+void
+CallWidget::selectSmartlistItem(const std::string & convUid)
+{
+ if (convUid.empty()) {
+ return;
+ }
+ ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversation = Utils::getConversationFromUid(convUid, *convModel);
+ if (conversation == convModel->allFilteredConversations().end()) {
+ return;
+ }
+ auto contactURI = QString::fromStdString((*conversation).participants[0]);
+ if (contactURI.isEmpty() ||
+ convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
+ return;
+ }
+ for (int row = 0; row < smartListModel_->rowCount(); row++) {
+ QModelIndex index = smartListModel_->index(row);
+ auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
+ if (indexContactURI == contactURI) {
+ ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
+ return;
+ }
+ }
}
void
@@ -569,62 +433,46 @@
if (!index.isValid())
return;
- auto realIndex = RecentModel::instance().peopleProxy()->mapToSource(index);
- if (RecentModel::instance().hasActiveCall(realIndex))
- return;
+ LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
- ContactMethod* m = nullptr;
- if (auto cm = realIndex.data((int)Call::Role::ContactMethod).value<ContactMethod*>()) {
- m = cm;
- } else {
- if (auto person = realIndex.data((int)Person::Role::Object).value<Person*>()) {
- m = person->phoneNumbers().first();
- }
- }
+ ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
+}
- if (m && !RecentModel::instance().index(0, 0, realIndex).isValid()) {
+QImage
+CallWidget::imageForConv(const std::string& convUid)
+{
+ return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
+}
- QPixmap map = QPixmap::fromImage(
- GlobalInstances::pixmapManipulator().callPhoto(m, QSize(130,130)).value<QImage>());
- ui->callingPhoto->setPixmap(map);
+const std::string&
+CallWidget::selectedAccountId()
+{
+ return LRCInstance::getSelectedAccountId();
+}
- Call* c = CallModel::instance().dialingCall(m);
- c->performAction(Call::Action::ACCEPT);
- setActualCall(c);
- }
+const std::string&
+CallWidget::selectedConvUid()
+{
+ return LRCInstance::getSelectedConvUid();
}
void
-CallWidget::smartListCurrentChanged(const QModelIndex ¤tIdx, const QModelIndex &previousIdx)
+CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
- Q_UNUSED(previousIdx);
- if (not currentIdx.isValid()) {
- auto widget = ui->stackedWidget->currentWidget();
- if (widget == ui->messagingPage || widget == ui->videoPage)
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
- if(actualCall_)
- setActualCall(nullptr);
+ Q_UNUSED(deselected);
+ QModelIndexList indices = selected.indexes();
+
+ if (indices.isEmpty()) {
return;
}
- //catch call of current index
- auto currentIdxCall = RecentModel::instance().getActiveCall(currentIdx);
+ auto selectedIndex = indices.at(0);
- if (currentIdxCall) {
- if (currentIdxCall != actualCall_) //if it is different from actual call, switch between the two
- setActualCall(currentIdxCall);
- } else { // if there is no call attached to this smartlist index (contact tab)
- setActualCall(nullptr);
- showIMOutOfCall(currentIdx); // change page to contact request of messaging page with correct behaviour
+ if (not selectedIndex.isValid()) {
+ return;
}
- /*
- else { // if non defined behaviour disconnect instant messaging and return to welcome page
- setActualCall(nullptr);
- if (imConnection_)
- disconnect(imConnection_);
- ui->stackedWidget->setCurrentWidget(ui->welcomePage);
- }
- */
+
+ selectConversation(selectedIndex);
}
void
@@ -638,7 +486,7 @@
} else {
ui->contactRequestWidget->setCurrentContactRequest(QModelIndex());
if (ui->stackedWidget->currentWidget() == ui->contactRequestPage)
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
}
}
@@ -657,144 +505,219 @@
}
void
+CallWidget::conversationsButtonClicked()
+{
+ setConversationFilter(lrc::api::profile::Type::RING);
+}
+
+void
+CallWidget::invitationsButtonClicked()
+{
+ setConversationFilter(lrc::api::profile::Type::PENDING);
+}
+
+void
CallWidget::settingsButtonClicked()
{
emit NavigationRequested(ScreenEnum::ConfScreen);
}
void
-CallWidget::searchContactLineEditEntry(const URI &uri)
-{
- auto cm = PhoneDirectoryModel::instance().getNumber(uri, getSelectedAccount());
- // if its a new CM, bring it to the top
- if (cm->lastUsed() == 0)
- cm->setLastUsed(QDateTime::currentDateTime().toTime_t());
-
- // select cm
- RecentModel::instance().selectionModel()->setCurrentIndex(RecentModel::instance().getIndex(cm),
- QItemSelectionModel::ClearAndSelect);
- ui->ringContactLineEdit->clear();
- cm->setAccount(AvailableAccountModel::instance().currentDefaultAccount(cm));
-}
-
-bool
-CallWidget::uriNeedNameLookup(const URI uri_passed)
-{
- if (uri_passed.protocolHint() == URI::ProtocolHint::RING_USERNAME ) {
- return TRUE;
- } else if (
- uri_passed.protocolHint() != URI::ProtocolHint::RING && // not a RingID
- uri_passed.schemeType() == URI::SchemeType::NONE // scheme type not specified
- ){
- // if no scheme type has been specified, determine ring vs sip by the current selected account
- auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
- if (idx.isValid()) {
- auto account = idx.data((int)Ring::Role::Object).value<Account *>();
- if (account && account->protocol() == Account::Protocol::RING)
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void
CallWidget::processContactLineEdit()
{
auto contactLineText = ui->ringContactLineEdit->text();
- URI uri_passed = URI(contactLineText);
- Account* ac = getSelectedAccount();
-
- if (!contactLineText.isNull() && !contactLineText.isEmpty()){
- if (uriNeedNameLookup(uri_passed)){
- NameDirectory::instance().lookupName(ac, QString(), uri_passed);
- } else {
- searchContactLineEditEntry(uri_passed);
- }
- }
+ setConversationFilter(contactLineText);
}
void
CallWidget::on_ringContactLineEdit_returnPressed()
{
- processContactLineEdit();
+ // select current temporary item and show conversation
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversations = convModel->allFilteredConversations();
+ auto contactIsValid = Utils::isContactValid(conversations.at(0).participants.at(0), *convModel);
+ if (!conversations.empty() && contactIsValid) {
+ selectConversation(smartListModel_->index(0));
+ }
}
-void
-CallWidget::searchBtnClicked()
+void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
{
- processContactLineEdit();
+ auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
+ LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
}
-void
-CallWidget::btnComBarVideoClicked()
+void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
{
- if (not highLightedIndex_.isValid())
+ auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
+ LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
+}
+
+void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
+{
+ auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
+ LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString());
+}
+
+void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
+{
+ setupSmartListContextMenu(pos);
+}
+
+void CallWidget::slotShowCallView(const std::string& accountId,
+ const lrc::api::conversation::Info& convInfo)
+{
+ Q_UNUSED(accountId);
+ Q_UNUSED(convInfo);
+ qDebug() << "BehaviorController::showCallView";
+ ui->stackedWidget->setCurrentWidget(ui->videoPage);
+ hideMiniSpinner();
+}
+
+void CallWidget::slotShowIncomingCallView(const std::string& accountId,
+ const lrc::api::conversation::Info& convInfo) {
+ Q_UNUSED(accountId);
+ qDebug() << "BehaviorController::showIncomingCallView";
+ auto callModel = LRCInstance::getCurrentCallModel();
+ auto call = callModel->getCall(convInfo.callId);
+ if (call.isOutgoing) {
+ miniSpinner_->start();
+ ui->spinnerLabel->show();
+ ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
+ }
+ else {
+ selectSmartlistItem(convInfo.uid);
+ auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
+ auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
+ if (!accountProperties.autoAnswer) {
+ ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
+ }
+ else {
+ ui->stackedWidget->setCurrentWidget(ui->videoPage);
+ }
+ if (!QApplication::focusWidget()) {
+ auto formattedName = Utils::bestNameForConversation(convInfo, *LRCInstance::getCurrentConversationModel());
+ Utils::showSystemNotification(this,
+ QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
+ }
+ }
+
+ if (!callModel->hasCall(convInfo.callId)) {
return;
+ }
- on_smartList_doubleClicked(highLightedIndex_);
+ ui->videoWidget->pushRenderer(convInfo.callId);
+ // TODO:(new lrc) in call chat
+ //ui->instantMessagingWidget->setMediaText(actualCall_);
+
+ disconnect(selectedCallChanged_);
+ selectedCallChanged_ = connect(
+ callModel,
+ &lrc::api::NewCallModel::callStatusChanged,
+ [this, callModel](const std::string& callUid) {
+ auto call = callModel->getCall(callUid);
+ qDebug() << "NewCallModel::callStatusChanged: " << static_cast<int>(call.status);
+ }
+ );
+
+ ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
+}
+
+void CallWidget::slotShowChatView(const std::string& accountId,
+ const lrc::api::conversation::Info& convInfo) {
+ Q_UNUSED(accountId);
+ Q_UNUSED(convInfo);
+ qDebug() << "BehaviorController::showChatView";
+ showConversationView();
}
void
-CallWidget::selectedAccountChanged(const QModelIndex ¤t, const QModelIndex &previous)
+CallWidget::currentAccountChanged(const QModelIndex ¤t)
{
- Q_UNUSED(previous)
-
- if (current.isValid()) {
- if (ui->selectBar->isHidden()){
- ui->selectBar->show();
- }
- auto ac = current.data(static_cast<int>(Account::Role::Object)).value<Account*>();
-
- // First, we get back to the welcome view (except if in call)
-
- if (ui->stackedWidget->currentWidget() != ui->videoPage &&
- ui->stackedWidget->currentWidget() != ui->welcomePage) {
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
- }
-
- // We setup the ringIdLabel and the QRCode
- auto protocol = ac->protocol();
- if (protocol == Account::Protocol::RING) {
- ui->ringIdLabel->setText((ac->registeredName().isEmpty())?ac->username():ac->registeredName());
- setupQRCode(ac->username());
- } else {
- ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
- }
-
- // Then, we update the pending CR list with those from the newly selected account
- if (disconnect(crListSelectionConnection_)) {
- ui->contactRequestList->selectionModel()->clear();
- // The selection model must be deleted by the application (see QT doc).
- QItemSelectionModel* sMod = ui->contactRequestList->selectionModel();
- delete sMod;
- RecentModel::instance().selectionModel()->clear();
- }
-
- ui->contactRequestList->setItemModel(ac->pendingContactRequestModel());
-
- // We modify the currentAccountWidget to reflect the new selected account
- // if the event wasn't triggered by this widget
- ui->currentAccountWidget->changeSelectedIndex(current.row());
-
- if (actualCall_){
- // keep call on foreground
- callStateToView(actualCall_);
- }
- } else {
+ if (!current.isValid()) {
ui->selectBar->hide();
ui->ringIdLabel->setText("");
+ return;
}
+ if (ui->selectBar->isHidden()){
+ ui->selectBar->show();
+ }
+
+ auto accountId = current.data(static_cast<int>(AccountListModel::Role::ID)).value<QString>().toStdString();
+
+ setSelectedAccount(accountId);
+}
+
+void
+CallWidget::setSelectedAccount(const std::string& accountId)
+{
+ LRCInstance::setSelectedAccountId(accountId);
+
+ // First, we get back to the welcome view (except if in call)
+ if (ui->stackedWidget->currentWidget() != ui->videoPage &&
+ ui->stackedWidget->currentWidget() != ui->welcomePage) {
+ Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
+ }
+
+ // We setup the ringIdLabel and the QRCode
+ auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
+ auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
+ auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
+ if (isRingAccount) {
+ ui->ringIdLabel->setText(QString::fromStdString(id));
+ setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
+ }
+
+ updateSmartList();
+ currentTypeFilter_ = accountInfo.profileInfo.type;
+ LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
+ updateConversationsFilterWidget();
+ connectConversationModel();
+}
+
+void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
+{
+ if (currentTypeFilter_ == filter) {
+ return;
+ }
+ currentTypeFilter_ = filter;
+ LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
+}
+
+void CallWidget::updateConversationsFilterWidget()
+{
+ auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
+ if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
+ currentTypeFilter_ = lrc::api::profile::Type::RING;
+ LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
+ }
+ ui->conversationsFilterWidget->setVisible(invites);
+ ui->verticalSpacer_3->changeSize(0, 10 * (1 - static_cast<bool>(invites)));
+}
+
+void CallWidget::setConversationFilter(const QString & filter)
+{
+ LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
}
void
CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
{
- ui->contactMethodComboBox->clear();
- QString name = nodeIdx.data(static_cast<int>(Ring::Role::Name)).toString();
- QString number = nodeIdx.data(static_cast<int>(Ring::Role::Number)).toString();
+ QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
+ QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
+ QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
- if (getSelectedAccount()->isIp2ip()){
+ bool isContact = false;
+ auto selectedAccountId = LRCInstance::getSelectedAccountId();
+ auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
+ bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
+ try {
+ accountInfo.contactModel->getContact(contactURI.toStdString());
+ isContact = true;
+ }
+ catch (...) {}
+
+ if (!isRINGAccount){
ui->imMessageEdit->setPlaceholderText("No messaging possible out of call (SIP) ");
ui->imMessageEdit->setEnabled(false);
ui->sendIMButton->hide();
@@ -805,58 +728,38 @@
}
ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
- .arg(name));
+ .arg(displayName));
- if ( !getSelectedAccount()->isIp2ip() && name != number ){
+ if (isRINGAccount && displayName != displayId){
ui->imIdLabel->show();
ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
- .arg(number));
+ .arg(displayId));
} else {
ui->imIdLabel->hide();
}
- auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
- ui->contactMethodComboBox->setVisible(cmVector.size() > 1);
- foreach (const ContactMethod* cm, cmVector) {
- ui->contactMethodComboBox->addItem(cm->bestId());
- }
+ bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
+ ui->sendContactRequestPageButton->setVisible(shouldShowSendContactRequestBtn);
- ui->sendContactRequestPageButton->setVisible(shouldDisplayInviteButton(*cmVector[0]));
+ showConversationView();
- ui->stackedWidget->setCurrentWidget(ui->messagingPage);
- ui->imMessageEdit->clear();
- ui->imMessageEdit->setFocus();
- disconnect(imClickedConnection_);
- imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
- auto urlList = index.data(static_cast<int>(media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
- if (urlList.size() == 1)
- QDesktopServices::openUrl(urlList.at(0));
- else if (urlList.size()) {
- //TODO Handle multiple url in one message
- }
- });
+ auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
+ *LRCInstance::getCurrentConversationModel());
+ messageModel_.reset(new MessageModel(*currentConversation, accountInfo, this->parent()));
+ ui->listMessageView->setModel(messageModel_.get());
+ ui->listMessageView->scrollToBottom();
}
void
CallWidget::on_sendIMButton_clicked()
{
- if (ui->imMessageEdit->text().trimmed().isEmpty())
- return;
-
- auto idx = RecentModel::instance().selectionModel()->currentIndex();
- auto cmVec = RecentModel::instance().getContactMethods(idx);
- if (cmVec.size() > 0) {
- auto cm = cmVec[0];
- if(!cm) {
- qWarning() << "Contact Method not found";
- return;
- }
- QMap<QString, QString> msg;
- msg["text/plain"] = ui->imMessageEdit->text();
- cm->sendOfflineTextMessage(msg);
- ui->imMessageEdit->clear();
- } else {
- qWarning() << "No contact method found for messaging";
+ auto msg = ui->imMessageEdit->text();
+ if (msg.trimmed().isEmpty()) return;
+ ui->imMessageEdit->clear();
+ try {
+ LRCInstance::getCurrentConversationModel()->sendMessage(selectedConvUid(), msg.toStdString());
+ } catch (...) {
+ qDebug() << "exception when sending message";
}
}
@@ -866,48 +769,6 @@
on_sendIMButton_clicked();
}
-void CallWidget::on_contactMethodComboBox_currentIndexChanged(int index)
-{
- auto idx = RecentModel::instance().selectionModel()->currentIndex();
- auto cmVec = RecentModel::instance().getContactMethods(idx);
- ContactMethod* cm {};
-
- if (index < cmVec.size() && index >= 0 ){
- cm = cmVec[index];
- }
-
- if (cm){
- ui->sendContactRequestPageButton->setVisible(shouldDisplayInviteButton(*cm));
- if (auto txtRecording = cm->textRecording()) {
- ui->listMessageView->setModel(txtRecording->instantMessagingModel());
- if (imConnection_)
- disconnect(imConnection_);
- imConnection_ = connect(txtRecording,
- SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,media::Media::Direction)),
- this,
- SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,media::Media::Direction)));
- auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
- if (messagesPresent) {
- ui->listMessageView->scrollToBottom();
- txtRecording->setAllRead();
- }
- ui->listMessageView->setVisible(messagesPresent);
- ui->noMessagesLabel->setVisible(!messagesPresent);
- if (not messagesPresent) {
- imVisibleConnection_ = connect(txtRecording->instantMessagingModel(),
- &QAbstractItemModel::rowsInserted,
- [this, txtRecording]() {
- if (imVisibleConnection_)
- disconnect(imVisibleConnection_);
- auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
- ui->listMessageView->setVisible(messagesPresent);
- ui->noMessagesLabel->setVisible(!messagesPresent);
- });
- }
- }
- }
-}
-
void
CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
ContactMethod* cm,
@@ -923,17 +784,19 @@
void
CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
{
- RecentModel::instance().peopleProxy()->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
+ Q_UNUSED(text);
+ processContactLineEdit();
}
void
CallWidget::backToWelcomePage()
{
- RecentModel::instance().selectionModel()->clear();
- disconnect(imConnection_);
+ deselectConversation();
+ ui->stackedWidget->setCurrentWidget(ui->welcomePage);
}
-void CallWidget::hideMiniSpinner()
+void
+CallWidget::hideMiniSpinner()
{
if(ui->spinnerLabel->isVisible()){
miniSpinner_->stop();
@@ -960,50 +823,9 @@
}
void
-CallWidget::contactLineEdit_registeredNameFound(Account* account,NameDirectory::LookupStatus status,
- const QString& address,const QString& name)
-{
- URI uri = URI(ui->ringContactLineEdit->text());
- QString username_to_lookup = uri.userinfo();
-
- if (username_to_lookup.compare(name) != 0){
- return;
- }
-
- switch (status)
- {
- case NameDirectory::LookupStatus::SUCCESS:
- {
- uri = URI("ring:" + address);
- qDebug() << "contactLineEdit username to search: " << username_to_lookup;
- qDebug() << uri;
- searchContactLineEditEntry(uri);
- auto cm = PhoneDirectoryModel::instance().getNumber(uri);
- cm->setAccount(account);
- break;
- }
- case NameDirectory::LookupStatus::INVALID_NAME:
- {
- qDebug() << "Invalid Ring username";
- break;
- }
- case NameDirectory::LookupStatus::ERROR:
- case NameDirectory::LookupStatus::NOT_FOUND:
- default:
- {
- qDebug() << "Could not resolve Ring username";
- break;
- }
- }
-}
-
-void
CallWidget::on_sendContactRequestPageButton_clicked()
{
- ui->sendContactRequestWidget->sendCR(RecentModel::instance().selectionModel()->currentIndex());
- // temporarly changed comportment waiting for message in payload implementation
- /*ui->sendContactRequestWidget->setup(RecentModel::instance().selectionModel()->currentIndex());
- slidePage(ui->sendContactRequestPage);*/
+ LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
}
void
@@ -1015,42 +837,223 @@
void
CallWidget::on_pendingCRBackButton_clicked()
{
- ui->contactRequestList->selectionModel()->clear();
ui->stackedWidget->setCurrentWidget(ui->welcomePage);
}
-Account*
-CallWidget::getSelectedAccount()
+bool
+CallWidget::connectConversationModel()
{
- auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
- if (idx.isValid()) {
- auto ac = idx.data(static_cast<int>(Ring::Role::Object)).value<Account*>();
- return ac;
+ auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
+
+ if (ui->smartList->selectionModel()) {
+ ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
}
- return nullptr;
+
+ QObject::disconnect(modelSortedConnection_);
+ QObject::disconnect(modelUpdatedConnection_);
+ QObject::disconnect(filterChangedConnection_);
+ QObject::disconnect(newConversationConnection_);
+ QObject::disconnect(conversationRemovedConnection_);
+ QObject::disconnect(conversationClearedConnection);
+ QObject::disconnect(interactionStatusUpdatedConnection_);
+ QObject::disconnect(newInteractionConnection_);
+
+ modelSortedConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::modelSorted,
+ [this]() {
+ updateConversationsFilterWidget();
+ selectSmartlistItem(selectedConvUid());
+ ui->smartList->update();
+ }
+ );
+ modelUpdatedConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
+ [this](const std::string& convUid) {
+ Q_UNUSED(convUid);
+ ui->smartList->update();
+ }
+ );
+ filterChangedConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::filterChanged,
+ [this]() {
+ updateSmartList();
+ updateConversationsFilterWidget();
+ ui->smartList->update();
+ }
+ );
+ newConversationConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::newConversation,
+ [this](const std::string& convUid) {
+ updateSmartList();
+ updateConversationForNewContact(convUid);
+ ui->conversationsFilterWidget->update();
+ }
+ );
+ conversationRemovedConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
+ [this]() {
+ backToWelcomePage();
+ }
+ );
+ conversationClearedConnection = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
+ [this](const std::string& convUid) {
+ updateConversationView(convUid);
+ // if currently selected,
+ // switch to welcome screen (deselecting current smartlist item )
+ if (convUid != selectedConvUid()) {
+ return;
+ }
+ backToWelcomePage();
+ }
+ );
+ interactionStatusUpdatedConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
+ [this](const std::string& convUid) {
+ if (convUid != selectedConvUid()) {
+ return;
+ }
+ updateConversationView(convUid);
+ }
+ );
+ newInteractionConnection_ = QObject::connect(
+ currentConversationModel, &lrc::api::ConversationModel::newInteraction,
+ [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
+ onIncomingMessage(convUid, interactionId, interaction);
+ }
+ );
+ currentConversationModel->setFilter("");
+ // clear search field
+ ui->ringContactLineEdit->setText("");
+ return true;
+}
+
+void
+CallWidget::updateConversationView(const std::string& convUid)
+{
+ if (convUid != selectedConvUid()) {
+ return;
+ }
+
+ auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
+ auto currentConversationModel = currentAccountInfo.conversationModel.get();
+ currentConversationModel->clearUnreadInteractions(convUid);
+ ui->conversationsFilterWidget->update();
+ auto currentConversation = Utils::getConversationFromUid(convUid,
+ *currentConversationModel);
+ if (currentConversation == currentConversationModel->allFilteredConversations().end()) {
+ return;
+ }
+ messageModel_.reset(new MessageModel(*currentConversation, currentAccountInfo, this->parent()));
+ ui->listMessageView->setModel(messageModel_.get());
+ ui->listMessageView->scrollToBottom();
+}
+
+void
+CallWidget::selectConversation(const QModelIndex& index)
+{
+ auto currentConversationModel = LRCInstance::getCurrentConversationModel();
+
+ if (currentConversationModel == nullptr || !index.isValid()) {
+ return;
+ }
+
+ const auto item = currentConversationModel->filteredConversation(index.row());
+
+ if (selectConversation(item, *currentConversationModel)) {
+ auto convUid = selectedConvUid();
+ if (!lastConvUid_.compare(convUid)) {
+ return;
+ }
+ lastConvUid_.assign(convUid);
+ auto currentConversationModel = LRCInstance::getCurrentConversationModel();
+ auto callModel = LRCInstance::getCurrentCallModel();
+ auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
+ const auto item = currentConversationModel->filteredConversation(index.row());
+ if (callModel->hasCall(conversation->callId)) {
+ ui->stackedWidget->setCurrentWidget(ui->videoPage);
+ }
+ else {
+ showIMOutOfCall(index);
+ }
+ }
}
bool
-CallWidget::shouldDisplayInviteButton(ContactMethod &cm)
+CallWidget::selectConversation( const lrc::api::conversation::Info& item,
+ lrc::api::ConversationModel& convModel)
{
- // Displaying the button for a SIP ContactMethod is a nonsense
- if (cm.protocolHint() == URI::ProtocolHint::RING) {
- // If we know that the other accepted us
- if (cm.isConfirmed())
- return false;
-
- // If not sure, we still check if the contact method is linked to a
- // Ring account or if the selected account is a RING one.
- if(auto linkedAccount = cm.account())
- return linkedAccount->protocol() == Account::Protocol::RING;
- else if (auto acc = getSelectedAccount())
- return acc->protocol() == Account::Protocol::RING;
+ if (selectedConvUid() == item.uid) {
+ return false;
+ } else if (item.participants.size() > 0) {
+ convModel.selectConversation(item.uid);
+ LRCInstance::setSelectedConvId(item.uid);
+ convModel.clearUnreadInteractions(item.uid);
+ ui->conversationsFilterWidget->update();
+ return true;
}
- return false;
}
-void CallWidget::on_contactRequestList_clicked(const QModelIndex &index)
+void
+CallWidget::deselectConversation()
{
- RecentModel::instance().selectionModel()->clear();
- contactReqListCurrentChanged(index, QModelIndex());
+ auto currentConversationModel = LRCInstance::getCurrentConversationModel();
+
+ if (currentConversationModel == nullptr) {
+ return;
+ }
+
+ currentConversationModel->selectConversation("");
+ LRCInstance::setSelectedConvId("");
+
+ ui->smartList->selectionModel()->clear();
+ disconnect(imConnection_);
}
+
+void
+CallWidget::updateConversationForNewContact(const std::string& convUid)
+{
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ if (convModel == nullptr) {
+ return;
+ }
+ ui->ringContactLineEdit->setText("");
+ auto selectedUid = selectedConvUid();
+ auto it = Utils::getConversationFromUid(convUid, *convModel);
+ if (it != convModel->allFilteredConversations().end()) {
+ try {
+ auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
+ if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
+ LRCInstance::setSelectedConvId(convUid);
+ convModel->selectConversation(convUid);
+ }
+ } catch (...) {
+ return;
+ }
+ }
+}
+
+void
+CallWidget::updateSmartList()
+{
+ auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
+ smartListModel_.reset(new SmartListModel(currentAccountInfo, this->parent()));
+ ui->smartList->setModel(smartListModel_.get());
+ ui->smartList->setItemDelegate(new ConversationItemDelegate());
+
+ // smartlist selection
+ QObject::disconnect(smartlistSelectionConnection_);
+ smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this,
+ SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
+}
+
+void
+CallWidget::update()
+{
+ ui->currentAccountWidget->update();
+ updateSmartList();
+ updateConversationsFilterWidget();
+ connectConversationModel();
+}
\ No newline at end of file
diff --git a/callwidget.h b/callwidget.h
index f77d82e..9fb6178 100644
--- a/callwidget.h
+++ b/callwidget.h
@@ -1,8 +1,9 @@
/**************************************************************************
-* Copyright (C) 2015-2017 by Savoir-faire Linux *
+* Copyright (C) 2015-2018 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -29,7 +30,9 @@
#include "navwidget.h"
#include "instantmessagingwidget.h"
+#include "smartlistmodel.h"
+// old LRC
#include "callmodel.h"
#include "video/renderer.h"
#include "video/previewmanager.h"
@@ -37,7 +40,16 @@
#include "categorizedhistorymodel.h"
#include "media/textrecording.h"
-class SmartListDelegate;
+// new LRC
+#include "globalinstances.h"
+#include "api/newaccountmodel.h"
+#include "api/conversationmodel.h"
+#include "api/account.h"
+#include "api/contact.h"
+#include "api/contactmodel.h"
+#include "api/newcallmodel.h"
+
+class ConversationItemDelegate;
class ImDelegate;
class QPropertyAnimation;
@@ -52,18 +64,22 @@
public:
explicit CallWidget(QWidget* parent = 0);
~CallWidget();
- void atExit();
bool findRingAccount();
public slots:
+ void on_ringContactLineEdit_returnPressed();
+
+public slots:
void settingsButtonClicked();
void showIMOutOfCall(const QModelIndex& nodeIdx);
- void btnComBarVideoClicked();
-
-//UI SLOTS
-public slots:
- void on_ringContactLineEdit_returnPressed();
- inline void on_entered(const QModelIndex& i){if (i.isValid()) highLightedIndex_ = i;}
+ void slotAcceptInviteClicked(const QModelIndex& index);
+ void slotBlockInviteClicked(const QModelIndex& index);
+ void slotIgnoreInviteClicked(const QModelIndex& index);
+ void slotCustomContextMenuRequested(const QPoint & pos);
+ void slotShowCallView(const std::string & accountId, const lrc::api::conversation::Info & convInfo);
+ void slotShowIncomingCallView(const std::string & accountId, const lrc::api::conversation::Info & convInfo);
+ void slotShowChatView(const std::string & accountId, const lrc::api::conversation::Info & convInfo);
+ void update();
private slots:
void on_acceptButton_clicked();
@@ -82,55 +98,75 @@
void on_pendingCRBackButton_clicked();
private slots:
- void callIncoming(Call* call);
- void callStateChanged(Call* call, Call::State previousState);
- void smartListCurrentChanged(const QModelIndex ¤tIdx, const QModelIndex &previousIdx);
+ void smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void contactReqListCurrentChanged(const QModelIndex ¤tIdx, const QModelIndex &previousIdx);
void slotAccountMessageReceived(const QMap<QString,QString> message,ContactMethod* cm, media::Media::Direction dir);
- void onIncomingMessage(::media::TextRecording* t, ContactMethod* cm);
- void callChangedSlot();
- void contactLineEdit_registeredNameFound(Account *account, NameDirectory::LookupStatus status, const QString& address, const QString& name);
- void searchBtnClicked();
- void selectedAccountChanged(const QModelIndex ¤t, const QModelIndex &previous);
- void on_contactMethodComboBox_currentIndexChanged(int index);
- void on_contactRequestList_clicked(const QModelIndex &index);
+ void onIncomingMessage(const std::string & convUid, uint64_t interactionId, const lrc::api::interaction::Info & interaction);
+ void currentAccountChanged(const QModelIndex ¤t);
private:
- Ui::CallWidget* ui;
- Call* actualCall_;
- Video::Renderer* videoRenderer_;
- CallModel* callModel_;
- int outputVolume_;
- int inputVolume_;
+ void placeCall();
+ void conversationsButtonClicked();
+ void invitationsButtonClicked();
+ void setupOutOfCallIM();
+ void setupSmartListContextMenu(const QPoint &pos);
+ void setupQRCode(QString ringID);
+ void backToWelcomePage();
+ void triggerDeleteContactDialog(ContactMethod *cm, Account *ac);
+
+ // lrc
+ void selectConversation(const QModelIndex& index);
+ bool selectConversation(const lrc::api::conversation::Info& item,
+ lrc::api::ConversationModel& convModel);
+ void deselectConversation();
+ bool connectConversationModel();
+ void updateConversationView(const std::string& convUid);
+ void showConversationView();
+ void selectSmartlistItem(const std::string& convUid);
+ QImage imageForConv(const std::string & convUid);
+ void processContactLineEdit();
+ void hideMiniSpinner();
+ void updateConversationForNewContact(const std::string& convUid);
+ void updateSmartList();
+ void setSelectedAccount(const std::string & accountId);
+ void setConversationFilter(const QString& filter);
+ void setConversationFilter(lrc::api::profile::Type filter);
+ void updateConversationsFilterWidget();
+ const std::string& selectedAccountId();
+ const std::string& selectedConvUid();
+
QMenu* menu_;
- SmartListDelegate* smartListDelegate_;
- QPersistentModelIndex highLightedIndex_;
+ ConversationItemDelegate* conversationItemDelegate_;
ImDelegate* imDelegate_;
+
QMetaObject::Connection imConnection_;
QMetaObject::Connection imVisibleConnection_;
QMetaObject::Connection callChangedConnection_;
QMetaObject::Connection imClickedConnection_;
QMetaObject::Connection crListSelectionConnection_;
- QPropertyAnimation* pageAnim_;
- QMenu* shareMenu_;
+
+ Ui::CallWidget* ui;
QMovie* miniSpinner_;
constexpr static int qrSize_ = 200;
-private:
- void setActualCall(Call* value);
- void placeCall();
- void setupOutOfCallIM();
- void setupSmartListMenu(const QPoint &pos);
- void slidePage(QWidget* widget, bool toRight = false);
- void callStateToView(Call* value);
- void setupQRCode(QString ringID);
- void searchContactLineEditEntry(const URI &uri);
- bool uriNeedNameLookup(const URI uri_passed);
- void processContactLineEdit();
- static Account* getSelectedAccount();
- static bool shouldDisplayInviteButton(ContactMethod& cm);
- void backToWelcomePage();
- void hideMiniSpinner();
- void triggerDeleteContactDialog(ContactMethod *cm, Account *ac);
+ // lrc
+ Video::Renderer* videoRenderer_;
+ std::string lastConvUid_ {};
+ lrc::api::profile::Type currentTypeFilter_{};
+
+ std::unique_ptr<SmartListModel> smartListModel_;
+ std::unique_ptr<MessageModel> messageModel_;
+ QMetaObject::Connection modelSortedConnection_;
+ QMetaObject::Connection modelUpdatedConnection_;
+ QMetaObject::Connection filterChangedConnection_;
+ QMetaObject::Connection newConversationConnection_;
+ QMetaObject::Connection conversationRemovedConnection_;
+ QMetaObject::Connection newInteractionConnection_;
+ QMetaObject::Connection interactionStatusUpdatedConnection_;
+ QMetaObject::Connection conversationClearedConnection;
+ QMetaObject::Connection selectedCallChanged_;
+ QMetaObject::Connection smartlistSelectionConnection_;
+
+
};
diff --git a/callwidget.ui b/callwidget.ui
index 7b7031a..1efddad 100644
--- a/callwidget.ui
+++ b/callwidget.ui
@@ -112,7 +112,7 @@
<number>0</number>
</property>
<item row="0" column="0">
- <layout class="QVBoxLayout" name="verticalLayout_2" stretch="3,1,18">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
<property name="spacing">
<number>0</number>
</property>
@@ -122,7 +122,7 @@
<item>
<widget class="CurrentAccountWidget" name="currentAccountWidget" native="true">
<property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -130,23 +130,32 @@
<property name="minimumSize">
<size>
<width>0</width>
- <height>100</height>
+ <height>60</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="selectBar" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="maximumSize">
<size>
- <width>324</width>
- <height>16777215</height>
+ <width>16777214</width>
+ <height>30</height>
</size>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <layout class="QHBoxLayout" name="selectBar_layout" stretch="0,0,0">
<property name="spacing">
<number>0</number>
</property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
<property name="leftMargin">
<number>0</number>
</property>
@@ -169,7 +178,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>16</width>
+ <width>10</width>
<height>38</height>
</size>
</property>
@@ -181,14 +190,14 @@
<bool>true</bool>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>244</width>
+ <width>266</width>
<height>30</height>
</size>
</property>
@@ -203,6 +212,9 @@
<pointsize>9</pointsize>
</font>
</property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="toolTip">
<string>Search contact text input</string>
</property>
@@ -221,42 +233,6 @@
</widget>
</item>
<item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="searchBtn">
- <property name="minimumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>search button</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_search_black_18dp_2x.png</normaloff>:/images/icons/ic_search_black_18dp_2x.png</iconset>
- </property>
- </widget>
- </item>
- <item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -266,8 +242,8 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
- <height>20</height>
+ <width>10</width>
+ <height>38</height>
</size>
</property>
</spacer>
@@ -276,150 +252,104 @@
</widget>
</item>
<item>
- <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QTabWidget" name="mainTabMenu">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="toolTip">
- <string/>
- </property>
- <property name="currentIndex">
- <number>0</number>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <widget class="QWidget" name="mainTabMenuPage1">
- <attribute name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_chat_black_24dp_2x.png</normaloff>:/images/icons/ic_chat_black_24dp_2x.png</iconset>
- </attribute>
- <attribute name="title">
- <string/>
- </attribute>
- <attribute name="toolTip">
- <string>Conversations</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_6">
+ <widget class="QWidget" name="smartListWidget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,0,0">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>1</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>1</number>
+ </property>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="ConversationsFilterWidget" name="conversationsFilterWidget" native="true">
+ <layout class="QHBoxLayout" name="conversationFilterLayout">
<property name="spacing">
- <number>0</number>
+ <number>10</number>
</property>
<property name="leftMargin">
- <number>0</number>
+ <number>10</number>
</property>
<property name="topMargin">
- <number>0</number>
+ <number>10</number>
</property>
<property name="rightMargin">
- <number>0</number>
+ <number>10</number>
</property>
<property name="bottomMargin">
- <number>0</number>
+ <number>10</number>
</property>
<item>
- <widget class="SmartList" name="smartList">
- <property name="minimumSize">
- <size>
- <width>324</width>
- <height>0</height>
- </size>
+ <widget class="QPushButton" name="buttonConversations">
+ <property name="toolTip">
+ <string>Show conversations</string>
</property>
- <property name="mouseTracking">
- <bool>true</bool>
+ <property name="text">
+ <string>Conversations</string>
</property>
- <property name="indentation">
- <number>0</number>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonInvites">
+ <property name="toolTip">
+ <string>Show invites</string>
</property>
- <property name="headerHidden">
- <bool>true</bool>
+ <property name="text">
+ <string>Invites</string>
</property>
- <attribute name="headerMinimumSectionSize">
- <number>0</number>
- </attribute>
</widget>
</item>
</layout>
</widget>
- <widget class="QWidget" name="mainTabMenuPage2">
- <attribute name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_person_add_black_24dp_2x.png</normaloff>:/images/icons/ic_person_add_black_24dp_2x.png</iconset>
+ </item>
+ <item>
+ <widget class="SmartListView" name="smartList">
+ <property name="autoScrollMargin">
+ <number>16</number>
+ </property>
+ <property name="indentation">
+ <number>0</number>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
</attribute>
- <attribute name="title">
- <string/>
- </attribute>
- <attribute name="toolTip">
- <string>Contact requests</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_7">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="ContactRequestListWidget" name="contactRequestList">
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="rootIsDecorated">
- <bool>false</bool>
- </property>
- <attribute name="headerVisible">
- <bool>false</bool>
- </attribute>
- <attribute name="headerMinimumSectionSize">
- <number>0</number>
- </attribute>
- </widget>
- </item>
- </layout>
</widget>
- </widget>
- </item>
- </layout>
+ </item>
+ </layout>
+ </widget>
</item>
</layout>
</item>
@@ -490,7 +420,7 @@
<string/>
</property>
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="welcomePage">
<layout class="QVBoxLayout" name="verticalLayout_15">
@@ -677,8 +607,10 @@
<string notr="true">color: #aeaeae</string>
</property>
<property name="text">
- <string>This is your RingID.
-Copy and share it with your friends!</string>
+ <string>
+ This is your RingID.
+ Copy and share it with your friends!
+ </string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
@@ -1033,7 +965,7 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_12" stretch="1,25,25,1">
+ <layout class="QVBoxLayout" name="verticalLayout_12" stretch="1,25,1">
<property name="leftMargin">
<number>5</number>
</property>
@@ -1178,19 +1110,6 @@
</spacer>
</item>
<item>
- <widget class="QComboBox" name="contactMethodComboBox">
- <property name="minimumSize">
- <size>
- <width>160</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Peer contact method selector</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="sendContactRequestPageButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -1221,23 +1140,6 @@
</item>
</layout>
</item>
- <item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
- <widget class="QLabel" name="noMessagesLabel">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Start the conversation !</string>
- </property>
- </widget>
- </item>
<item>
<widget class="QListView" name="listMessageView">
<property name="sizePolicy">
@@ -1918,9 +1820,9 @@
<header>idlabel.h</header>
</customwidget>
<customwidget>
- <class>SmartList</class>
+ <class>SmartListView</class>
<extends>QTreeView</extends>
- <header>smartlist.h</header>
+ <header>smartlistview.h</header>
</customwidget>
<customwidget>
<class>SendContactRequestWidget</class>
@@ -1941,9 +1843,10 @@
<container>1</container>
</customwidget>
<customwidget>
- <class>ContactRequestListWidget</class>
- <extends>QTreeView</extends>
- <header>contactrequestlistwidget.h</header>
+ <class>ConversationsFilterWidget</class>
+ <extends>QWidget</extends>
+ <header>conversationsfilterwidget.h</header>
+ <container>1</container>
</customwidget>
</customwidgets>
<resources>
diff --git a/combar.ui b/combar.ui
deleted file mode 100644
index 8b9e661..0000000
--- a/combar.ui
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ComBar</class>
- <widget class="QWidget" name="ComBar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>578</width>
- <height>112</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>5</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnComBarVideo">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Call button</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_videocam_white.png</normaloff>:/images/icons/ic_videocam_white.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>18</width>
- <height>18</height>
- </size>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources>
- <include location="ressources.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/configurationwidget.cpp b/configurationwidget.cpp
index 67e9388..81f9b55 100644
--- a/configurationwidget.cpp
+++ b/configurationwidget.cpp
@@ -77,9 +77,6 @@
}
accountModel_->save();
accountDetails_->save();
- });
-
- connect(ui->exitSettingsButton, &QPushButton::clicked, this, [=]() {
emit NavigationRequested(ScreenEnum::CallScreen);
});
diff --git a/contactmethodpicker.cpp b/contactmethodpicker.cpp
deleted file mode 100644
index 9d7d11a..0000000
--- a/contactmethodpicker.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
- * *
- * 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/>. *
- **************************************************************************/
-
-#include "contactmethodpicker.h"
-#include "ui_contactmethodpicker.h"
-
-#include "contactmethod.h"
-
-ContactMethodPicker::ContactMethodPicker(const Person::ContactMethods& cM, QWidget *parent) :
- QDialog(parent),
- ui(new Ui::ContactMethodPicker),
- contactMethods_(cM)
-{
- ui->setupUi(this);
-
- this->setWindowFlags(Qt::CustomizeWindowHint);
- this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
-
- for (auto contactMethod : cM) {
- auto item = new QListWidgetItem();
- item->setText(contactMethod->uri());
- ui->contactMethodListWidget->addItem(item);
- }
-}
-
-ContactMethodPicker::~ContactMethodPicker()
-{
- delete ui;
-}
-
-void
-ContactMethodPicker::on_contactMethodListWidget_clicked(const QModelIndex &index)
-{
- index_ = index.row();
- accept();
-}
-
-ContactMethod*
-ContactMethodPicker::getSelected() const
-{
- return contactMethods_.at(index_);
-}
diff --git a/contactmethodpicker.h b/contactmethodpicker.h
deleted file mode 100644
index 489ab98..0000000
--- a/contactmethodpicker.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
- * *
- * 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/>. *
- **************************************************************************/
-
-#pragma once
-
-#include <QDialog>
-
-#include "person.h"
-#include "personmodel.h"
-
-namespace Ui {
-class ContactMethodPicker;
-}
-
-class ContactMethodPicker final : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit ContactMethodPicker(const Person::ContactMethods &cM, QWidget *parent = 0);
- ~ContactMethodPicker();
-
- ContactMethod* getSelected() const;
-
-//UI SLOTS
-private slots:
- void on_contactMethodListWidget_clicked(const QModelIndex &index);
-
-private:
- Ui::ContactMethodPicker *ui;
- const Person::ContactMethods& contactMethods_;
- int index_;
-};
-
diff --git a/contactmethodpicker.ui b/contactmethodpicker.ui
deleted file mode 100644
index 338d2df..0000000
--- a/contactmethodpicker.ui
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ContactMethodPicker</class>
- <widget class="QDialog" name="ContactMethodPicker">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>93</width>
- <height>93</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QListWidget" name="contactMethodListWidget"/>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/contactrequestitemdelegate.cpp b/contactrequestitemdelegate.cpp
deleted file mode 100644
index 6e6d9f6..0000000
--- a/contactrequestitemdelegate.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2017 by Savoir-faire Linux *
- * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
- * *
- * 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/>. *
- ***************************************************************************/
-
-#include "contactrequestitemdelegate.h"
-#include "ringthemeutils.h"
-
-#include "accountmodel.h"
-#include "pendingcontactrequestmodel.h"
-#include "contactrequest.h"
-#include "globalinstances.h"
-#include "pixmapmanipulatordefault.h"
-
-#include <QPainter>
-#include <QApplication>
-
-#include <ciso646>
-
-ContactRequestItemDelegate::ContactRequestItemDelegate(QObject* parent) :
- QItemDelegate(parent)
-{}
-
-void
-ContactRequestItemDelegate::paint(QPainter* painter
- , const QStyleOptionViewItem& option
- , const QModelIndex& index
- ) const
-{
- painter->setRenderHint(QPainter::Antialiasing);
-
- QStyleOptionViewItem opt(option);
-
- // Not having focus removes dotted lines around the item
- if (opt.state & QStyle::State_HasFocus)
- opt.state ^= QStyle::State_HasFocus;
-
- // First, we draw the control itself
- QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
- style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
-
- bool selected = false;
- if (option.state & QStyle::State_Selected) {
- selected = true;
- opt.state ^= QStyle::State_Selected;
- painter->fillRect(option.rect, RingTheme::smartlistSelection_);
- }
- else if (option.state & QStyle::State_MouseOver) {
- painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
- }
-
- // Then, we print the text
- QFont font(painter->font());
- font.setPointSize(10);
- font.setBold(true);
- painter->setFont(font);
-
- QFontMetrics fontMetrics(font);
-
- QRect rectText(opt.rect);
- rectText.setLeft(opt.rect.left() + dxText_);
- rectText.setTop(opt.rect.top() + dyText_);
- rectText.setBottom(rectText.top() + fontMetrics.height());
-
- QString text(index.data().toString());
- text = fontMetrics.elidedText(text, Qt::ElideRight, rectText.width());
-
- QPen pen(painter->pen());
-
- pen.setColor(RingTheme::lightBlack_);
- painter->setPen(pen);
-
- painter->drawText(rectText,text);
-
- // Draw the picture from the vCard
- QRect rectPic(opt.rect.left() + dxImage_, opt.rect.top() + dyImage_, sizeImage_, sizeImage_);
- auto cr = index.data(static_cast<int>(Ring::Role::Object)).value<ContactRequest*>();
- auto photo = GlobalInstances::pixmapManipulator().contactPhoto(cr->peer(), QSize(sizeImage_, sizeImage_), false);
- drawDecoration(painter, opt, rectPic, QPixmap::fromImage(photo.value<QImage>()));
-}
-
-QSize
-ContactRequestItemDelegate::sizeHint(const QStyleOptionViewItem& option
- , const QModelIndex& index
- ) const
-{
- QSize size = QItemDelegate::sizeHint(option, index);
- size.setHeight(cellHeight_);
- return size;
-}
diff --git a/contactrequestitemdelegate.h b/contactrequestitemdelegate.h
deleted file mode 100644
index 2d059e3..0000000
--- a/contactrequestitemdelegate.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2017 by Savoir-faire Linux *
- * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
- * *
- * 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/>. *
- ***************************************************************************/
-
-#pragma once
-
-#include <QObject>
-#include <QItemDelegate>
-
-class ContactRequestItemDelegate : public QItemDelegate
-{
-public:
- ContactRequestItemDelegate(QObject* parent = 0);
-
-protected:
- void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
- QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
-
-private:
- constexpr static int cellHeight_ = 60;
- constexpr static int sizeImage_ = 48;
- constexpr static int dxImage_ = 16;
- constexpr static int dyImage_ = 6;
-
- constexpr static int dxText_ = dxImage_ + sizeImage_ + 12;
- constexpr static int dyText_ = 13;
-
- constexpr static int separatorYPadding_ = 20;
-};
diff --git a/contactrequestlistwidget.cpp b/contactrequestlistwidget.cpp
deleted file mode 100644
index 1e74d39..0000000
--- a/contactrequestlistwidget.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/**************************************************************************
-* Copyright (C) 2015-2017 by Savoir-faire Linux *
-* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
-* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
-* *
-* 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/>. *
-**************************************************************************/
-
-#include "contactrequestlistwidget.h"
-
-//LRC
-#include "contactrequest.h"
-#include "pendingcontactrequestmodel.h"
-#include "itemdataroles.h"
-
-//CLIENT
-#include "quickactcontactrequestwidget.h"
-#include <QScrollBar>
-#include <QAbstractItemView>
-#include <QEvent>
-
-#include <ciso646>
-
-ContactRequestListWidget::ContactRequestListWidget(QWidget *parent) :
- QTreeView(parent)
-{
- // for hover detection
- setMouseTracking(true);
-
- //connects the entered signal to the creation and display of hovering widget
- connect(this, &QAbstractItemView::entered, [this](const QModelIndex & index) {
- //get current hovered row quick action widget
- auto widget = indexWidget(index);
- //build and add hovering quick action widget to row and display, if already built just display
- if (!widget) {
- QuickActContactRequestWidget* quickBtns = new QuickActContactRequestWidget();
- setIndexWidget(index, quickBtns);
- connect(quickBtns, &QuickActContactRequestWidget::quickValidCRBtnClicked,
- this,
- [=](){ model()->data(index, static_cast<int>(Ring::Role::Object)).value<ContactRequest*>()->accept(); });
-
- connect(quickBtns, &QuickActContactRequestWidget::quickMuteCRBtnClicked,
- this,
- [=](){ model()->data(index, static_cast<int>(Ring::Role::Object)).value<ContactRequest*>()->discard(); });
-
- connect(quickBtns, &QuickActContactRequestWidget::quickBanCRBtnClicked,
- this,
- [=](){ model()->data(index, static_cast<int>(Ring::Role::Object)).value<ContactRequest*>()->block(); });
- }
- else if (index.isValid()){
- indexWidget(index)->setVisible(true);
- }
-
- //hide previously shown hover widget (if any)
- if(hoveredCRIndex_.isValid() and indexWidget(hoveredCRIndex_))
- indexWidget(hoveredCRIndex_)->setVisible(false);
-
- //update current hovered index
- hoveredCRIndex_ = index;
- });
-}
-
-ContactRequestListWidget::~ContactRequestListWidget()
-{
-}
-
-void
-ContactRequestListWidget::setItemModel(QAbstractItemModel *model)
-{
- setModel(model);
-
- // Hide unused columns
- for(int column = 1; column < model->columnCount(); column++){
- hideColumn(column);
- }
-}
-
-
-void
-ContactRequestListWidget::enterEvent(QEvent* event)
-{
- Q_UNUSED(event);
- verticalScrollBar()->show();
-}
-
-void
-ContactRequestListWidget::leaveEvent(QEvent* event)
-{
- Q_UNUSED(event);
-
- hoveredCRIndex_ = QModelIndex();
- verticalScrollBar()->hide();
-}
-
-bool
-ContactRequestListWidget::eventFilter(QObject* watched, QEvent* event)
-{
- if (qobject_cast<QScrollBar*>(watched) && event->type() == QEvent::Enter) {
- hoveredCRIndex_ = QModelIndex();
- return true;
- }
-
- return QObject::eventFilter(watched, event);
-}
-
-
-void
-ContactRequestListWidget::drawRow(QPainter* painter,
- const QStyleOptionViewItem& option, const QModelIndex& index) const
-{
- if(index == hoveredCRIndex_ && indexWidget(hoveredCRIndex_))
- indexWidget(index)->setVisible(true);
- else if(indexWidget(index))
- indexWidget(index)->setVisible(false);
-
- QTreeView::drawRow(painter, option, index);
-}
diff --git a/contactrequestlistwidget.h b/contactrequestlistwidget.h
deleted file mode 100644
index 4dc61e3..0000000
--- a/contactrequestlistwidget.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**************************************************************************
-* Copyright (C) 2015-2017 by Savoir-faire Linux *
-* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
-* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
-* *
-* 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 CONTACTREQUESTLISTWIDGET_H
-#define CONTACTREQUESTLISTWIDGET_H
-
-#include <QTreeView>
-
-class ContactRequestListWidget : public QTreeView
-{
- Q_OBJECT
-
-public:
- explicit ContactRequestListWidget(QWidget *parent = 0);
- ~ContactRequestListWidget();
- void setItemModel(QAbstractItemModel *model);
-
-private:
- QModelIndex hoveredCRIndex_;
-
-protected:
- void enterEvent(QEvent *event);
- void leaveEvent(QEvent *event);
- bool eventFilter(QObject *watched, QEvent *event);
- void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
-};
-
-#endif // CONTACTREQUESTLISTWIDGET_H
diff --git a/conversationitemdelegate.cpp b/conversationitemdelegate.cpp
new file mode 100644
index 0000000..f260519
--- /dev/null
+++ b/conversationitemdelegate.cpp
@@ -0,0 +1,307 @@
+/***************************************************************************
+ * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "conversationitemdelegate.h"
+
+#include <QApplication>
+#include <QPainter>
+#include <QPixmap>
+#include <QDebug>
+
+// Client
+#include "smartlistmodel.h"
+#include "ringthemeutils.h"
+#include "utils.h"
+
+#include <ciso646>
+
+ConversationItemDelegate::ConversationItemDelegate(QObject* parent) :
+ QItemDelegate(parent)
+{
+}
+
+void
+ConversationItemDelegate::paint(QPainter* painter
+ , const QStyleOptionViewItem& option
+ , const QModelIndex& index
+ ) const
+{
+ QStyleOptionViewItem opt(option);
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ // Not having focus removes dotted lines around the item
+ if (opt.state & QStyle::State_HasFocus)
+ opt.state ^= QStyle::State_HasFocus;
+
+ // First, we draw the control itself
+ QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
+
+ auto isContextMenuOpen = index.data(static_cast<int>(SmartListModel::Role::ContextMenuOpen)).value<bool>();
+ bool selected = false;
+ if (option.state & QStyle::State_Selected) {
+ selected = true;
+ opt.state ^= QStyle::State_Selected;
+ } else if (!isContextMenuOpen) {
+ if (option.state & QStyle::State_MouseOver) {
+ highlightMap_[index.row()] = true;
+ } else {
+ highlightMap_[index.row()] = false;
+ }
+ }
+
+ // One does not simply keep the highlighted state drawn when the context
+ // menu is openÂ…
+ auto rowHighlight = highlightMap_.find(index.row());
+ if (selected) {
+ painter->fillRect(option.rect, RingTheme::smartlistSelection_);
+ } else if (rowHighlight != highlightMap_.end() && (*rowHighlight).second) {
+ painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
+ }
+
+ QRect &rect = opt.rect;
+
+ // Avatar drawing
+ opt.decorationSize = QSize(sizeImage_, sizeImage_);
+ opt.decorationPosition = QStyleOptionViewItem::Left;
+ opt.decorationAlignment = Qt::AlignCenter;
+
+ QRect rectAvatar(dx_ + rect.left(), rect.top() + dy_, sizeImage_, sizeImage_);
+ drawDecoration(painter, opt, rectAvatar,
+ QPixmap::fromImage(index.data(Qt::DecorationRole).value<QImage>())
+ .scaled(sizeImage_, sizeImage_, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+
+ QFont font(painter->font());
+
+ // If there's unread messages, a message count is displayed
+ if (auto messageCount = index.data(static_cast<int>(SmartListModel::Role::UnreadMessagesCount)).toInt()) {
+ QString messageCountText = (messageCount > 9) ? "9+" : QString::number(messageCount);
+ qreal fontSize = messageCountText.count() > 1 ? 7 : 8;
+ font.setPointSize(fontSize);
+
+ // ellipse
+ QPainterPath ellipse;
+ qreal ellipseHeight = sizeImage_ / 6;
+ qreal ellipseWidth = ellipseHeight;
+ QPointF ellipseCenter(rectAvatar.right() - ellipseWidth, rectAvatar.top() + ellipseHeight + 1);
+ QRect ellipseRect(ellipseCenter.x() - ellipseWidth, ellipseCenter.y() - ellipseHeight,
+ ellipseWidth * 2, ellipseHeight * 2);
+ ellipse.addRoundedRect(ellipseRect, ellipseWidth, ellipseHeight);
+ painter->fillPath(ellipse, RingTheme::notificationRed_);
+
+ // text
+ painter->setPen(Qt::white);
+ painter->setOpacity(1);
+ painter->setFont(font);
+ ellipseRect.setTop(ellipseRect.top() - 2);
+ painter->drawText(ellipseRect, Qt::AlignCenter, messageCountText);
+ }
+
+ // Presence indicator
+ if (index.data(static_cast<int>(SmartListModel::Role::Presence)).value<bool>()) {
+ qreal radius = sizeImage_ / 6;
+ QPainterPath outerCircle, innerCircle;
+ QPointF center(rectAvatar.right() - radius, (rectAvatar.bottom() - radius) + 1);
+ qreal outerCRadius = radius;
+ qreal innerCRadius = outerCRadius * 0.75;
+ outerCircle.addEllipse(center, outerCRadius, outerCRadius);
+ innerCircle.addEllipse(center, innerCRadius, innerCRadius);
+ painter->fillPath(outerCircle, Qt::white);
+ painter->fillPath(innerCircle, RingTheme::presenceGreen_);
+ }
+
+ using namespace lrc::api;
+ auto type = Utils::toEnum<profile::Type>(
+ index.data(static_cast<int>(SmartListModel::Role::ContactType)).value<int>()
+ );
+ switch (type) {
+ case profile::Type::RING:
+ case profile::Type::TEMPORARY:
+ paintRingConversationItem(painter, option, rect, index);
+ break;
+ case profile::Type::PENDING:
+ paintRingInviteConversationItem(painter, option, rect, index);
+ break;
+ case profile::Type::SIP:
+ break;
+ default:
+ paintRingConversationItem(painter, option, rect, index);
+ break;
+ }
+}
+
+QSize
+ConversationItemDelegate::sizeHint(const QStyleOptionViewItem& option,
+ const QModelIndex& index) const
+{
+ return QSize(0, cellHeight_);
+}
+
+void
+ConversationItemDelegate::paintRingConversationItem(QPainter* painter,
+ const QStyleOptionViewItem& option,
+ const QRect& rect,
+ const QModelIndex& index) const
+{
+ QFont font(painter->font());
+ font.setPointSize(fontSize_);
+ QPen pen(painter->pen());
+ painter->setPen(pen);
+
+ auto leftMargin = dx_ + sizeImage_ + dx_ / 2;
+ auto rightMargin = dx_;
+ auto topMargin = 0;
+ auto bottomMargin = 12;
+
+ QRect rectName1(rect.left() + leftMargin,
+ rect.top() + topMargin,
+ rect.width() - leftMargin - infoTextWidth_,
+ rect.height() / 2);
+
+ QRect rectName2(rectName1.left(),
+ rectName1.top() + rectName1.height(),
+ rectName1.width(),
+ rectName1.height() - bottomMargin);
+
+ QRect rectInfo1(rectName1.left() + rectName1.width(),
+ rect.top() + topMargin,
+ infoTextWidth_ - rightMargin,
+ rect.height() / 2);
+
+ QRect rectInfo2(rectInfo1.left(),
+ rectInfo1.top() + rectInfo1.height(),
+ rectInfo1.width(),
+ rectInfo1.height() - bottomMargin);
+
+ QFontMetrics fontMetrics(font);
+
+ // The name is displayed at the avatar's right
+ QString nameStr = index.data(static_cast<int>(SmartListModel::Role::DisplayName)).value<QString>();;
+ if (!nameStr.isNull()) {
+ font.setItalic(false);
+ font.setBold(true);
+ pen.setColor(RingTheme::lightBlack_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ QString elidedNameStr = fontMetrics.elidedText(nameStr, Qt::ElideRight, rectName1.width());
+ painter->drawText(rectName1, Qt::AlignVCenter | Qt::AlignLeft, elidedNameStr);
+ }
+
+ // Display the ID under the name
+ QString idStr = index.data(static_cast<int>(SmartListModel::Role::DisplayID)).value<QString>();
+ if (idStr != nameStr && !idStr.isNull()) {
+ font.setItalic(false);
+ font.setBold(false);
+ pen.setColor(RingTheme::grey_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ idStr = fontMetrics.elidedText(idStr, Qt::ElideRight, rectName2.width());
+ painter->drawText(rectName2, Qt::AlignVCenter | Qt::AlignLeft, idStr);
+ }
+
+ // top-right: last interaction date/time
+ QString lastUsedStr = index.data(static_cast<int>(SmartListModel::Role::LastInteractionDate)).value<QString>();
+ if (!lastUsedStr.isNull()) {
+ font.setItalic(false);
+ font.setBold(false);
+ pen.setColor(RingTheme::grey_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ lastUsedStr = fontMetrics.elidedText(lastUsedStr, Qt::ElideRight, rectInfo1.width());
+ painter->drawText(rectInfo1, Qt::AlignVCenter | Qt::AlignRight, lastUsedStr);
+ }
+
+ // bottom-right: last interaction snippet
+ QString interactionStr = index.data(static_cast<int>(SmartListModel::Role::LastInteraction)).value<QString>();
+ if (!interactionStr.isNull()) {
+ // remove phone glyphs
+ interactionStr.replace(QChar(0xd83d), "");
+ interactionStr.replace(QChar(0xdd7d), "");
+ interactionStr.replace(QChar(0xdcde), "");
+
+ font.setItalic(false);
+ font.setBold(false);
+ pen.setColor(RingTheme::grey_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ interactionStr = fontMetrics.elidedText(interactionStr, Qt::ElideRight, rectInfo2.width());
+ painter->drawText(rectInfo2, Qt::AlignVCenter | Qt::AlignRight, interactionStr);
+ }
+}
+
+void
+ConversationItemDelegate::paintRingInviteConversationItem(QPainter* painter,
+ const QStyleOptionViewItem& option,
+ const QRect& rect,
+ const QModelIndex& index) const
+{
+ QFont font(painter->font());
+ font.setPointSize(fontSize_);
+ QPen pen(painter->pen());
+ painter->setPen(pen);
+
+ auto leftMargin = dx_ + sizeImage_ + dx_ / 2;
+ auto rightMargin = dx_;
+ if (option.state & QStyle::State_MouseOver) {
+ rightMargin = infoTextWidth_ - dx_ * 2;
+ }
+ auto topMargin = 0;
+ auto bottomMargin = 12;
+
+ QRect rectName1(rect.left() + leftMargin,
+ rect.top() + topMargin,
+ rect.width() - leftMargin - rightMargin,
+ rect.height() / 2);
+
+ QRect rectName2(rectName1.left(),
+ rectName1.top() + rectName1.height(),
+ rectName1.width(),
+ rectName1.height() - bottomMargin);
+
+ QFontMetrics fontMetrics(font);
+
+ // The name is displayed at the avatar's right
+ QString nameStr = index.data(static_cast<int>(SmartListModel::Role::DisplayName)).value<QString>();;
+ if (!nameStr.isNull()) {
+ font.setItalic(false);
+ font.setBold(true);
+ pen.setColor(RingTheme::lightBlack_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ QString elidedNameStr = fontMetrics.elidedText(nameStr, Qt::ElideRight, rectName1.width());
+ painter->drawText(rectName1, Qt::AlignVCenter | Qt::AlignLeft, elidedNameStr);
+ }
+
+ // Display the ID under the name
+ QString idStr = index.data(static_cast<int>(SmartListModel::Role::DisplayID)).value<QString>();
+ if (idStr != nameStr && !idStr.isNull()) {
+ font.setItalic(false);
+ font.setBold(false);
+ pen.setColor(RingTheme::grey_);
+ painter->setPen(pen);
+ painter->setFont(font);
+ idStr = fontMetrics.elidedText(idStr, Qt::ElideRight, rectName2.width());
+ painter->drawText(rectName2, Qt::AlignVCenter | Qt::AlignLeft, idStr);
+ }
+}
+
+void
+ConversationItemDelegate::paintSIPConversationItem(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
+{
+}
diff --git a/smartlistdelegate.h b/conversationitemdelegate.h
similarity index 74%
copy from smartlistdelegate.h
copy to conversationitemdelegate.h
index 2b5e413..249d77b 100644
--- a/smartlistdelegate.h
+++ b/conversationitemdelegate.h
@@ -23,21 +23,27 @@
class QPainter;
-class SmartListDelegate : public QItemDelegate
+class ConversationItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
- explicit SmartListDelegate(QObject* parent = 0);
+ explicit ConversationItemDelegate(QObject* parent = 0);
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
+ void paintRingConversationItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
+ void paintRingInviteConversationItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
+ void paintSIPConversationItem(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
+
constexpr static int sizeImage_ = 48;
constexpr static int cellHeight_ = 60;
constexpr static int dy_ = 6;
constexpr static int dx_ = 12;
constexpr static int fontSize_ = 10;
- constexpr static int effectiveComBarSize_ = 48;
+ constexpr static int infoTextWidth_ = 144;
+
+ mutable std::map<int, bool> highlightMap_;
};
diff --git a/conversationsfilterwidget.cpp b/conversationsfilterwidget.cpp
new file mode 100644
index 0000000..07abdf5
--- /dev/null
+++ b/conversationsfilterwidget.cpp
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "conversationsfilterwidget.h"
+
+#include "ringthemeutils.h"
+
+#include <QPainter>
+
+static inline const QRect
+getNotifierRect(const QRect& buttonRect)
+{
+ qreal radius = 8;
+ QPointF ellipseCenter(buttonRect.right() - radius * 2, buttonRect.top());
+ return QRect(ellipseCenter.x() - radius, ellipseCenter.y() - radius, radius * 2, radius * 2);
+}
+
+void
+ConversationsFilterWidget::handleNotifierOverlay(const QString& buttonName,
+ SmartlistSelectorButtonNotifier*& notifier,
+ lrc::api::profile::Type filter)
+{
+ auto button = this->findChild<QPushButton*>(buttonName);
+ if (!button) {
+ return;
+ }
+ if (!notifier) {
+ notifier = new SmartlistSelectorButtonNotifier(this);
+ button->stackUnder(notifier);
+ notifier->setTypeFilter(filter);
+ notifier->hide();
+ QObject::connect(notifier, SIGNAL(clicked()), button, SLOT(click()));
+ } else {
+ notifier->setGeometry(getNotifierRect(button->frameGeometry()));
+ notifier->show();
+ }
+}
+
+ConversationsFilterWidget::ConversationsFilterWidget(QWidget *parent)
+ : QWidget(parent)
+{
+}
+
+void ConversationsFilterWidget::paintEvent(QPaintEvent * event)
+{
+ QWidget::paintEvent(event);
+
+ using namespace lrc::api::profile;
+ handleNotifierOverlay("buttonConversations", unreadMessagesNotifier_, Type::RING);
+ handleNotifierOverlay("buttonInvites", pendingInvitesNotifier_, Type::PENDING);
+}
diff --git a/quickactcontactrequestwidget.h b/conversationsfilterwidget.h
similarity index 63%
rename from quickactcontactrequestwidget.h
rename to conversationsfilterwidget.h
index b74c292..1ce9eef 100644
--- a/quickactcontactrequestwidget.h
+++ b/conversationsfilterwidget.h
@@ -1,6 +1,6 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -15,32 +15,27 @@
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
+#pragma once
-#ifndef QUICKACTCONTACTREQUESTWIDGET_H
-#define QUICKACTCONTACTREQUESTWIDGET_H
+#include "api/profile.h"
+#include "smartlistselectorbuttonnotifier.h"
#include <QWidget>
-
-namespace Ui {
-class QuickActContactRequestWidget;
-}
-
-class QuickActContactRequestWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit QuickActContactRequestWidget(QWidget *parent = 0);
- ~QuickActContactRequestWidget();
-
-signals:
- void quickValidCRBtnClicked();
- void quickMuteCRBtnClicked();
- void quickBanCRBtnClicked();
-
-private:
- Ui::QuickActContactRequestWidget *ui;
-};
-
-#endif // QUICKACTCONTACTREQUESTWIDGET_H
+class ConversationsFilterWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ConversationsFilterWidget(QWidget *parent = 0);
+
+protected:
+ virtual void paintEvent(QPaintEvent *event);
+
+private:
+ void handleNotifierOverlay(const QString& buttonName,
+ SmartlistSelectorButtonNotifier*& notifier,
+ lrc::api::profile::Type filter);
+ SmartlistSelectorButtonNotifier* unreadMessagesNotifier_{ nullptr };
+ SmartlistSelectorButtonNotifier* pendingInvitesNotifier_{ nullptr };
+};
\ No newline at end of file
diff --git a/currentaccountwidget.cpp b/currentaccountwidget.cpp
index 9693217..a339061 100644
--- a/currentaccountwidget.cpp
+++ b/currentaccountwidget.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2015-2017 by Savoir-faire Linux *
* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -19,6 +20,7 @@
#include "currentaccountwidget.h"
#include "ui_currentaccountwidget.h"
+
#include "globalinstances.h"
#include "availableaccountmodel.h"
#include "account.h"
@@ -26,15 +28,36 @@
#include "profilemodel.h"
#include "profile.h"
#include "person.h"
+
#include "utils.h"
-#include "globalinstances.h"
+#include "lrcinstance.h"
+#include "pixbufmanipulator.h"
CurrentAccountWidget::CurrentAccountWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::CurrentAccountWidget)
{
ui->setupUi(this);
- setup();
+
+ accountListModel_ = std::make_unique<AccountListModel>();
+ ui->currentAccountSelector->setModel(accountListModel_.get());
+ accountItemDelegate_ = new AccountItemDelegate();
+ ui->currentAccountSelector->setItemDelegate(accountItemDelegate_);
+
+ connect(&LRCInstance::accountModel(),
+ &lrc::api::NewAccountModel::accountAdded,
+ [this](const std::string& accountId) {
+ auto accountList = LRCInstance::accountModel().getAccountList();
+ auto it = std::find(accountList.begin(), accountList.end(), accountId);
+ if (it != accountList.end()) {
+ auto index = std::distance(accountList.begin(), it);
+ // newly created account
+ // index should be 0
+ QModelIndex idx = ui->currentAccountSelector->model()->index(index, 0);
+ emit currentAccountChanged(idx);
+ update();
+ }
+ });
}
CurrentAccountWidget::~CurrentAccountWidget()
@@ -43,80 +66,41 @@
}
void
-CurrentAccountWidget::setup()
-{
- ui->accountsStatus->setText("No enabled account: impossible to communicate!");
- ui->accountsStatus->hide();
- ui->currentAccountSelector->setModel(&AvailableAccountModel::instance());
- updateAccounts();
- if (ui->currentAccountSelector->count() > 0) {
- ui->currentAccountSelector->setCurrentIndex(0);
- qDebug() << "CurrentAccount : setup over";
- } else {
- qDebug() << "CurrentAccount : No account available";
- }
-}
-
-void
CurrentAccountWidget::update()
{
- updateAccounts();
-
-}
-
-void
-CurrentAccountWidget::updateAccounts()
-{
- auto selector = ui->currentAccountSelector;
-
- if (selector->count() <= 1){
- selector->hide();
- if (selector->count() < 1) {
- ui->accountsStatus->show();
- setPhoto();
- } else {
- ui->accountsStatus->hide();
- }
+ if (ui->currentAccountSelector->count() <= 1) {
+ ui->currentAccountSelector->setEnabled(false);
+ ui->currentAccountSelector->setStyleSheet(
+ "QComboBox:disabled{color: black;}"
+ "QComboBox{border:0;}"
+ "QComboBox::down-arrow{image:url('none');}"
+ );
} else {
- selector->show();
- ui->accountsStatus->hide();
+ ui->currentAccountSelector->setEnabled(true);
+ ui->currentAccountSelector->setStyleSheet("");
}
+ setPhoto();
}
void
CurrentAccountWidget::setPhoto()
{
- auto selector = ui->currentAccountSelector;
- if (selector->count() > 0) {
- if (ProfileModel::instance().selectedProfile()) {
- if (auto p = ProfileModel::instance().selectedProfile()->person()) {
- QVariant avatarImage = ProfileModel::instance().selectedProfile()->person()->roleData(Qt::DecorationRole);
- QImage image = Utils::getCirclePhoto(avatarImage.value<QImage>(), ui->idDisplayLayout->contentsRect().height());
- ui->currentAccountPixmap->setPixmap(QPixmap::fromImage(image));
- qDebug() << "CurrentAccount : Photo set";
- } else
- qDebug() << "CurrentAccount : selected profile has no person";
- } else
- qDebug() << "CurrentAccount : Profilemodel: no selected profile";
- } else {
- qDebug() << "CurrentAccount : account not set";
- ui->currentAccountPixmap->setPixmap(QPixmap());
+ auto accountId = LRCInstance::getSelectedAccountId();
+ try {
+ auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
+ QVariant avatarImage = PixbufManipulator::accountPhoto(accountInfo);
+ QImage image = Utils::getCirclePhoto(avatarImage.value<QImage>(), ui->idDisplayLayout->contentsRect().height());
+ ui->currentAccountPixmap->setPixmap(QPixmap::fromImage(image));
}
+ catch (...) {}
}
void
CurrentAccountWidget::on_currentAccountSelector_currentIndexChanged(int index)
{
- QModelIndex idx = ui->currentAccountSelector->model()->index(index,0);
- Account* ac = AccountModel::instance().getAccountByModelIndex(idx);
-
- if (ac) {
- AvailableAccountModel::instance().selectionModel()->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
- setPhoto();
- } else {
- qDebug() << "CurrentAccount : account not referenced correctly";
- //null for now
- }
+ QModelIndex idx = ui->currentAccountSelector->model()->index(index, 0);
+ emit currentAccountChanged(idx);
+ setPhoto();
}
void
diff --git a/currentaccountwidget.h b/currentaccountwidget.h
index 10d01f6..20f5f46 100644
--- a/currentaccountwidget.h
+++ b/currentaccountwidget.h
@@ -22,6 +22,9 @@
#include <QWidget>
+#include "accountlistmodel.h"
+#include "accountitemdelegate.h"
+
namespace Ui {
class CurrentAccountWidget;
}
@@ -35,6 +38,9 @@
~CurrentAccountWidget();
void changeSelectedIndex(int index);
+signals:
+ void currentAccountChanged(const QModelIndex& current);
+
public slots:
void update();
void setPhoto();
@@ -43,9 +49,9 @@
void on_currentAccountSelector_currentIndexChanged(int index);
private:
+ AccountItemDelegate * accountItemDelegate_;
+ std::unique_ptr<AccountListModel> accountListModel_;
Ui::CurrentAccountWidget *ui;
- void setup();
- void updateAccounts();
};
#endif // CURRENTACCOUNTWIDGET_H
diff --git a/currentaccountwidget.ui b/currentaccountwidget.ui
index 51b5cee..c10708b 100644
--- a/currentaccountwidget.ui
+++ b/currentaccountwidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>294</width>
- <height>184</height>
+ <width>461</width>
+ <height>128</height>
</rect>
</property>
<property name="sizePolicy">
@@ -48,12 +48,12 @@
<number>0</number>
</property>
<item>
- <layout class="QVBoxLayout" name="fullLayout" stretch="4,0,0">
+ <layout class="QVBoxLayout" name="fullLayout" stretch="4">
<property name="spacing">
<number>0</number>
</property>
<item>
- <layout class="QHBoxLayout" name="idDisplayLayout" stretch="0,0,0">
+ <layout class="QHBoxLayout" name="idDisplayLayout" stretch="0,0,0,0">
<property name="leftMargin">
<number>10</number>
</property>
@@ -71,9 +71,12 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -82,15 +85,15 @@
<item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
<widget class="QLabel" name="currentAccountPixmap">
<property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>0</width>
- <height>60</height>
+ <width>48</width>
+ <height>48</height>
</size>
</property>
<property name="toolTip">
@@ -106,42 +109,32 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
+ <item>
+ <widget class="QComboBox" name="currentAccountSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>account selection combobox</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QLabel" name="accountsStatus">
- <property name="minimumSize">
- <size>
- <width>20</width>
- <height>10</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Account status</string>
- </property>
- <property name="styleSheet">
- <string notr="true">text: centered;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="currentAccountSelector">
- <property name="toolTip">
- <string>account selection combobox</string>
- </property>
- </widget>
- </item>
</layout>
</item>
</layout>
diff --git a/deletecontactdialog.cpp b/deletecontactdialog.cpp
deleted file mode 100644
index 85c15f0..0000000
--- a/deletecontactdialog.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
- * *
- * 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/>. *
- **************************************************************************/
-
-#include "deletecontactdialog.h"
-#include "ui_deletecontactdialog.h"
-
-// LRC
-#include "person.h"
-#include "account.h"
-#include "bannedcontactmodel.h"
-
-DeleteContactDialog::DeleteContactDialog(ContactMethod* cm, Account* ac, QWidget *parent) :
- QDialog(parent),
- ui(new Ui::DeleteContactDialog),
- contactMethod_(cm),
- account_(ac)
-{
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
- ui->setupUi(this);
- ui->contactNameLabel->setText(cm->bestName());
- if (cm->bestName() != cm->bestId())
- ui->contactIdLabel->setText(cm->bestId());
- else
- ui->contactIdLabel->hide();
-}
-
-DeleteContactDialog::~DeleteContactDialog()
-{
- delete ui;
-}
-
-void DeleteContactDialog::on_deleteCancelBtn_clicked()
-{
- close();
-}
-
-void DeleteContactDialog::on_deleteAcceptBtn_clicked()
-{
- account_->removeContact(contactMethod_);
- accept();
-}
-
-void DeleteContactDialog::on_deleteBanBtn_clicked()
-{
- account_->removeContact(contactMethod_);
- account_->bannedContactModel()->add(contactMethod_);
- accept();
-}
diff --git a/deletecontactdialog.h b/deletecontactdialog.h
deleted file mode 100644
index 792f654..0000000
--- a/deletecontactdialog.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
- * *
- * 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 DELETECONTACTDIALOG_H
-#define DELETECONTACTDIALOG_H
-
-#include <QDialog>
-
-// LRC
-#include "contactmethod.h"
-
-namespace Ui {
-class DeleteContactDialog;
-}
-
-class DeleteContactDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit DeleteContactDialog(ContactMethod* cm, Account *ac, QWidget *parent = 0);
- ~DeleteContactDialog();
-
-private slots:
- void on_deleteCancelBtn_clicked();
- void on_deleteAcceptBtn_clicked();
- void on_deleteBanBtn_clicked();
-
-private:
- Ui::DeleteContactDialog *ui;
- ContactMethod* contactMethod_;
- Account* account_;
-};
-
-#endif // DELETECONTACTDIALOG_H
diff --git a/deletecontactdialog.ui b/deletecontactdialog.ui
deleted file mode 100644
index fa97857..0000000
--- a/deletecontactdialog.ui
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>DeleteContactDialog</class>
- <widget class="QDialog" name="DeleteContactDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>200</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>10</height>
- </size>
- </property>
- </spacer>
- </item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QLabel" name="label">
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- </font>
- </property>
- <property name="text">
- <string>Do you want to delete this contact?</string>
- </property>
- </widget>
- </item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QLabel" name="contactNameLabel">
- <property name="minimumSize">
- <size>
- <width>10</width>
- <height>0</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QLabel" name="contactIdLabel">
- <property name="minimumSize">
- <size>
- <width>10</width>
- <height>0</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="buttonRow">
- <property name="spacing">
- <number>10</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QPushButton" name="deleteCancelBtn">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Cancel contact deletion button</string>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="deleteAcceptBtn">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Delete contact validation button</string>
- </property>
- <property name="text">
- <string>Delete</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="deleteBanBtn">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Delete and ban validation button</string>
- </property>
- <property name="text">
- <string>Delete and ban</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>10</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/images/icons/ic_block-24px.svg b/images/icons/ic_block-24px.svg
new file mode 100644
index 0000000..8032acf
--- /dev/null
+++ b/images/icons/ic_block-24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/></svg>
\ No newline at end of file
diff --git a/images/icons/ic_clear-24px.svg b/images/icons/ic_clear-24px.svg
new file mode 100644
index 0000000..dea8678
--- /dev/null
+++ b/images/icons/ic_clear-24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
\ No newline at end of file
diff --git a/imdelegate.cpp b/imdelegate.cpp
index 55f10d0..6c13048 100644
--- a/imdelegate.cpp
+++ b/imdelegate.cpp
@@ -1,6 +1,7 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Copyright (C) 2015-2018 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -19,7 +20,6 @@
#include "imdelegate.h"
#include <QApplication>
-#include <QTextDocument>
#include <QSettings>
#include <QDateTime>
@@ -28,6 +28,8 @@
#include "ringthemeutils.h"
#include "settingskey.h"
+#include "messagemodel.h"
+#include "utils.h"
ImDelegate::ImDelegate(QObject *parent)
: QStyledItemDelegate(parent)
@@ -35,25 +37,17 @@
}
void
-ImDelegate::formatMsg(const QModelIndex& index, QString& msg) const
+ImDelegate::formatMsg(const QModelIndex& index, QString& msgString) const
{
- QSettings settings;
- QStringList meta;
- if (settings.value(SettingsKey::imShowAuthor).toBool()) {
- meta << index.data(
- static_cast<int>(media::TextRecording::Role::AuthorDisplayname)).toString();
+ auto date = index.data(static_cast<int>(MessageModel::Role::InteractionDate)).value<QDateTime>();
+ auto now = QDateTime::currentDateTime();
+ QString dateString;
+ if (now.date() == date.date()) {
+ dateString = date.time().toString();
+ } else {
+ dateString = date.toString();
}
- if (settings.value(SettingsKey::imShowDate).toBool()) {
- auto timeStamp = index.data(
- static_cast<int>(media::TextRecording::Role::Timestamp)).value<uint>();
- auto date = QDateTime::fromTime_t(timeStamp);
- auto now = QDateTime::currentDateTime();
- if (now.date() == date.date())
- meta << date.time().toString();
- else
- meta << date.toString();
- }
- msg = QString("%2<footer><i>%1</i></footer>").arg(meta.join(" - "), msg);
+ msgString = QString("%1<br><footer><i>%2</i></footer>").arg(msgString, dateString);
}
void
@@ -61,6 +55,16 @@
const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
+ if (!index.isValid()) {
+ return;
+ }
+
+ auto msg = index.data(static_cast<int>(MessageModel::Role::Body)).toString();
+ auto type = static_cast<lrc::api::interaction::Type>(index.data(static_cast<int>(MessageModel::Role::Type)).value<int>());
+ auto isOutgoing = index.data(static_cast<int>(MessageModel::Role::Direction)).value<bool>();
+ auto isGenerated = Utils::isInteractionGenerated(type);
+ auto dir = isGenerated ? Qt::AlignHCenter : (isOutgoing ? Qt::AlignRight : Qt::AlignLeft);
+
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
painter->setRenderHint(QPainter::Antialiasing);
@@ -68,77 +72,69 @@
opt.font = fontMsg_;
painter->setFont(fontMsg_);
- if (index.isValid()) {
- auto msg = index.data(static_cast<int>(media::TextRecording::Role::FormattedHtml)).toString();
- opt.text.clear();
- QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
+ opt.text.clear();
+ QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
- auto dir = index.data(static_cast<int>(media::TextRecording::Role::Direction))
- .value<media::Media::Direction>() == media::Media::Direction::IN
- ? Qt::AlignLeft : Qt::AlignRight;
+ formatMsg(index, msg);
- formatMsg(index, msg);
+ QTextDocument document;
+ document.setDefaultStyleSheet(defaultStylesheet_);
+ document.setDefaultFont(fontMsg_);
+ document.setHtml(msg);
+ auto textOptions = QTextOption(Qt::AlignLeft);
+ textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
+ document.setDefaultTextOption(textOptions);
- QRect textRect = getBoundingRect(dir, msg, opt);
+ QRect textRect = getBoundingRect(dir, opt, document);
+ document.setTextWidth(textRect.width());
- if (dir == Qt::AlignLeft) {
- opt.decorationSize = iconSize_;
- opt.decorationPosition = (dir == Qt::AlignRight ?
- QStyleOptionViewItem::Right : QStyleOptionViewItem::Left);
- opt.decorationAlignment = Qt::AlignTop | Qt::AlignHCenter;
- } else
- opt.decorationSize = QSize();
+ if (dir == Qt::AlignLeft) {
+ opt.decorationSize = iconSize_;
+ opt.decorationPosition = QStyleOptionViewItem::Left;
+ opt.decorationAlignment = Qt::AlignTop | Qt::AlignHCenter;
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
-
- QPainterPath path;
- path.addRoundedRect(textRect, padding_, padding_);
-
- if (dir == Qt::AlignRight) {
- painter->fillPath(path, RingTheme::imBlue_);
- }
- else {
- painter->fillPath(path, RingTheme::imGrey_);
- }
-
- painter->save();
-
- QTextDocument document;
- document.setDefaultFont(fontMsg_);
-
- document.setDefaultStyleSheet("body { color : black; } i { opacity: 100; font-size : 11px; text-align : right; }");
-
- document.setHtml(msg);
-
- auto textOptions = QTextOption(Qt::AlignLeft);
- textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
- document.setDefaultTextOption(textOptions);
- document.setTextWidth(textRect.width());
-
- painter->translate(textRect.topLeft());
- document.drawContents(painter);
- painter->restore();
+ } else {
+ opt.decorationSize = QSize();
+ opt.decorationPosition = QStyleOptionViewItem::Right;
}
+
+ QPainterPath path;
+ path.addRoundedRect(textRect, bubbleRadius_, bubbleRadius_);
+
+ if (dir == Qt::AlignRight) {
+ painter->fillPath(path, RingTheme::imGrey_);
+ } else if (dir == Qt::AlignHCenter) {
+ painter->fillPath(path, Qt::transparent);
+ } else {
+ painter->fillPath(path, RingTheme::imBlue_);
+ }
+
+ painter->save();
+
+ painter->translate(textRect.topLeft());
+ document.drawContents(painter);
+ painter->restore();
}
QRect ImDelegate::getBoundingRect(const Qt::AlignmentFlag& dir,
- const QString& msg,
- const QStyleOptionViewItem &option) const
+ const QStyleOptionViewItem &option,
+ QTextDocument& txtDoc) const
{
QRect textRect;
- QTextDocument txtDoc;
- txtDoc.setDefaultFont(fontMsg_);
- txtDoc.setHtml(msg);
- auto textOptions = QTextOption(Qt::AlignLeft);
- textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
- txtDoc.setDefaultTextOption(textOptions);
-
if (dir == Qt::AlignLeft) {
txtDoc.setTextWidth(option.rect.width() - iconSize_.width() - padding_);
textRect.setRect(option.rect.left() + iconSize_.width() + padding_,
option.rect.top() + padding_,
txtDoc.idealWidth(),
txtDoc.size().height());
+ } else if (dir == Qt::AlignHCenter) {
+ txtDoc.setTextWidth(option.rect.width() - padding_);
+ auto optCenter = option.rect.left() + option.rect.width() / 2;
+ textRect.setRect(optCenter - txtDoc.idealWidth() / 2,
+ option.rect.top() + padding_,
+ txtDoc.idealWidth(),
+ txtDoc.size().height());
} else {
txtDoc.setTextWidth(option.rect.width() - padding_);
textRect.setRect(option.rect.right() - padding_ - txtDoc.idealWidth(),
@@ -158,22 +154,30 @@
QString msg = index.data(static_cast<int>(media::TextRecording::Role::FormattedHtml)).toString();
- auto dir = index.data(
- static_cast<int>(media::TextRecording::Role::Direction))
- .value<media::Media::Direction>() == media::Media::Direction::IN
- ? Qt::AlignLeft : Qt::AlignRight;
+ auto isOutgoing = index.data(static_cast<int>(MessageModel::Role::Direction)).value<bool>();
+ auto isGenerated = Utils::isInteractionGenerated(
+ static_cast<lrc::api::interaction::Type>(index.data(static_cast<int>(MessageModel::Role::Type)).value<int>())
+ );
+ auto dir = isGenerated ? Qt::AlignHCenter : (isOutgoing ? Qt::AlignRight : Qt::AlignLeft);
formatMsg(index, msg);
- QRect boundingRect = getBoundingRect(dir, msg, opt);
+ QTextDocument document;
+ document.setDefaultFont(fontMsg_);
+ document.setHtml(msg);
+ auto textOptions = QTextOption(Qt::AlignLeft);
+ textOptions.setWrapMode(QTextOption::WrapMode::WordWrap);
+ document.setDefaultTextOption(textOptions);
- QSize size(option.rect.width(), boundingRect.height());
+ QRect boundingRect = getBoundingRect(dir, opt, document);
+
+ QSize size(boundingRect.width() + 2 * margin_, boundingRect.height());
/* Keep the minimum height needed. */
if(size.height() < iconSize_.height())
size.setHeight(iconSize_.height());
- size.setHeight(size.height() + 2 * padding_);
+ size.setHeight(size.height() + 2 * margin_);
return size;
}
diff --git a/imdelegate.h b/imdelegate.h
index 5a6151a..c422610 100644
--- a/imdelegate.h
+++ b/imdelegate.h
@@ -19,6 +19,7 @@
#pragma once
#include <QPainter>
+#include <QTextDocument>
#include <QStyledItemDelegate>
class ImDelegate : public QStyledItemDelegate
@@ -26,21 +27,21 @@
Q_OBJECT
public:
explicit ImDelegate(QObject *parent = 0);
- enum DisplayOptions {
- AUTHOR = 1,
- DATE
- };
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
void formatMsg(const QModelIndex& index, QString& msg) const;
- QRect getBoundingRect(const Qt::AlignmentFlag& dir, const QString& msg, const QStyleOptionViewItem &option) const;
+ QRect getBoundingRect(const Qt::AlignmentFlag& dir, const QStyleOptionViewItem &option,
+ QTextDocument& txtDoc) const;
const QFont fontMsg_ = QFont("Arial", 10);
- const QSize iconSize_ {38,38};
+ const QString defaultStylesheet_ = QString("body { color : black; } i { opacity: 100; font-size : 10px; text-align : right; }");
+ const QSize iconSize_ {38, 38};
+ constexpr static int margin_ = 5;
constexpr static int padding_ = 5;
+ constexpr static int bubbleRadius_ = 12;
};
diff --git a/instantmessagingwidget.cpp b/instantmessagingwidget.cpp
index 95cce48..9473950 100644
--- a/instantmessagingwidget.cpp
+++ b/instantmessagingwidget.cpp
@@ -46,23 +46,6 @@
connect(copyAction, &QAction::triggered, [=]() {
copyToClipboard();
});
- QSettings settings;
- auto displayDate = new QAction(tr("Display date"), this);
- displayDate->setCheckable(true);
- displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
- ui->listMessageView->addAction(displayDate);
- auto displayAuthor = new QAction(tr("Display author"), this);
- displayAuthor->setCheckable(true);
- displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
- ui->listMessageView->addAction(displayAuthor);
- auto lamdba = [=](){
- QSettings settings;
- settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
- settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
- emit imDelegate_->sizeHintChanged(QModelIndex());
- };
- connect(displayAuthor, &QAction::triggered, lamdba);
- connect(displayDate, &QAction::triggered, lamdba);
}
InstantMessagingWidget::~InstantMessagingWidget()
@@ -86,12 +69,9 @@
textMedia = call->addOutgoingMedia<media::Text>();
}
if (textMedia) {
- ui->listMessageView->setModel(
- textMedia->recording()->
- instantMessagingModel());
+ ui->listMessageView->setModel(textMedia->recording()->instantMessagingModel());
ui->listMessageView->scrollToBottom();
- connect(ui->messageEdit, &QLineEdit::returnPressed, [=]()
- {
+ connect(ui->messageEdit, &QLineEdit::returnPressed, [=]() {
if (not ui->messageEdit->text().trimmed().isEmpty()) {
QMap<QString, QString> messages;
messages["text/plain"] = ui->messageEdit->text();
diff --git a/combar.cpp b/invitebuttonswidget.cpp
similarity index 62%
rename from combar.cpp
rename to invitebuttonswidget.cpp
index 757f319..ee18f90 100644
--- a/combar.cpp
+++ b/invitebuttonswidget.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -16,23 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
-#include "ui_combar.h"
+#include "ui_invitebuttonswidget.h"
-#include "combar.h"
+#include "invitebuttonswidget.h"
-ComBar::ComBar(QWidget* parent) :
+InviteButtonsWidget::InviteButtonsWidget(QWidget* parent) :
QWidget(parent),
- ui(new Ui::ComBar)
+ ui(new Ui::InviteButtonsWidget)
{
ui->setupUi(this);
- connect(ui->btnComBarVideo, &QPushButton::clicked , this , [=](){
- emit btnVideoClicked();
- });
+ connect(ui->btnAcceptInvite, &QPushButton::clicked, this,
+ [=]() {
+ emit btnAcceptInviteClicked();
+ });
+ connect(ui->btnIgnoreInvite, &QPushButton::clicked, this,
+ [=]() {
+ emit btnIgnoreInviteClicked();
+ });
+ connect(ui->btnBlockInvite, &QPushButton::clicked, this,
+ [=]() {
+ emit btnBlockInviteClicked();
+ });
}
-ComBar::~ComBar()
+InviteButtonsWidget::~InviteButtonsWidget()
{
disconnect(this);
delete ui;
-}
+}
\ No newline at end of file
diff --git a/combar.h b/invitebuttonswidget.h
similarity index 73%
rename from combar.h
rename to invitebuttonswidget.h
index ca01889..7e1919b 100644
--- a/combar.h
+++ b/invitebuttonswidget.h
@@ -1,6 +1,6 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -21,20 +21,22 @@
#include <QWidget>
namespace Ui {
-class ComBar;
+class InviteButtonsWidget;
}
-class ComBar : public QWidget
+class InviteButtonsWidget : public QWidget
{
Q_OBJECT
public:
- explicit ComBar(QWidget* parent = 0);
- ~ComBar();
+ explicit InviteButtonsWidget(QWidget* parent = 0);
+ ~InviteButtonsWidget();
private:
- Ui::ComBar* ui;
+ Ui::InviteButtonsWidget* ui;
signals:
- void btnVideoClicked() const;
+ void btnAcceptInviteClicked() const;
+ void btnIgnoreInviteClicked() const;
+ void btnBlockInviteClicked() const;
-};
+};
\ No newline at end of file
diff --git a/invitebuttonswidget.ui b/invitebuttonswidget.ui
new file mode 100644
index 0000000..e1f8bf2
--- /dev/null
+++ b/invitebuttonswidget.ui
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InviteButtonsWidget</class>
+ <widget class="QWidget" name="InviteButtonsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>323</width>
+ <height>114</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>5</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>209</width>
+ <height>17</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAcceptInvite">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Accept invite</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_person_add_black_24dp_2x.png</normaloff>:/images/icons/ic_person_add_black_24dp_2x.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>18</width>
+ <height>18</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnIgnoreInvite">
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Ignore invite</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_clear-24px.svg</normaloff>:/images/icons/ic_clear-24px.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>18</width>
+ <height>18</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnBlockInvite">
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Block person</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_block-24px.svg</normaloff>:/images/icons/ic_block-24px.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>18</width>
+ <height>18</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>17</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="ressources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/lrcinstance.h b/lrcinstance.h
index 573f7d3..e92dd34 100644
--- a/lrcinstance.h
+++ b/lrcinstance.h
@@ -21,6 +21,8 @@
#undef ERROR
#endif
+#include <QSettings>
+
#include "api/lrc.h"
#include "api/account.h"
#include "api/newaccountmodel.h"
@@ -31,6 +33,8 @@
#include "api/contact.h"
#include "api/datatransfermodel.h"
+#include <settingskey.h>
+
class LRCInstance {
public:
static void init() {
@@ -55,15 +59,51 @@
return instance().lrc_->isConnected();
};
+ static const lrc::api::account::Info&
+ getCurrentAccountInfo() {
+ return accountModel().getAccountInfo(instance().selectedAccountId);
+ };
+
+ static lrc::api::ConversationModel*
+ getCurrentConversationModel() {
+ return getCurrentAccountInfo().conversationModel.get();
+ };
+
+ static lrc::api::NewCallModel*
+ getCurrentCallModel() {
+ return getCurrentAccountInfo().callModel.get();
+ };
+
+ static const std::string& getSelectedAccountId() {
+ return instance().selectedAccountId;
+ };
+
+ static void setSelectedAccountId(const std::string& accountId) {
+ instance().selectedAccountId = accountId;
+ QSettings settings;
+ settings.setValue(SettingsKey::selectedAccount, QString::fromStdString(accountId));
+ };
+
+ static const std::string& getSelectedConvUid() {
+ return instance().selectedConvUid;
+ };
+
+ static void setSelectedConvId(const std::string& convUid) {
+ instance().selectedConvUid = convUid;
+ };
+
private:
std::unique_ptr<lrc::api::Lrc> lrc_;
static LRCInstance& instance() {
static LRCInstance instance_;
return instance_;
- }
+ };
LRCInstance() {
lrc_ = std::make_unique<lrc::api::Lrc>();
};
+
+ std::string selectedAccountId;
+ std::string selectedConvUid;
};
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
index 61dec93..a0284ab 100644
--- a/main.cpp
+++ b/main.cpp
@@ -29,7 +29,6 @@
#include "pixbufmanipulator.h"
#include "lrcinstance.h"
-#include <QThread>
#include <QTranslator>
#include <QLibraryInfo>
#include <QFontDatabase>
diff --git a/mainwindow.cpp b/mainwindow.cpp
index c3cd8f6..c6abaec 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -1,6 +1,7 @@
/***************************************************************************
* Copyright (C) 2015-2017 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -42,10 +43,19 @@
ui(new Ui::MainWindow)
{
ui->setupUi(this);
+
connect(ui->callwidget, &CallWidget::NavigationRequested,
- [this](ScreenEnum scr){Utils::slidePage(ui->navStack, ui->navStack->widget(scr));});
+ [this](ScreenEnum scr) {
+ Utils::setStackWidget(ui->navStack, ui->navStack->widget(scr));
+ });
+
connect(ui->configurationwidget, &ConfigurationWidget::NavigationRequested,
- [this](ScreenEnum scr){Utils::slidePage(ui->navStack, ui->navStack->widget(scr));});
+ [this](ScreenEnum scr) {
+ Utils::setStackWidget(ui->navStack, ui->navStack->widget(scr));
+ if (scr == ScreenEnum::CallScreen) {
+ ui->callwidget->update();
+ }
+ });
QIcon icon(":images/ring.png");
@@ -189,7 +199,7 @@
settings->setIcon(icon);
settings->setDismissOnClick(true);
connect(settings, &QWinThumbnailToolButton::clicked, [this]() {
- Utils::slidePage(ui->navStack, ui->configurationwidget);
+ Utils::setStackWidget(ui->navStack, ui->configurationwidget);
});
thumbbar->addButton(settings);
diff --git a/messagemodel.cpp b/messagemodel.cpp
new file mode 100644
index 0000000..998c97f
--- /dev/null
+++ b/messagemodel.cpp
@@ -0,0 +1,123 @@
+/***************************************************************************
+* Copyright (C) 2017 by Savoir-faire Linux *
+* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+* *
+* 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/>. *
+***************************************************************************/
+
+#include "messagemodel.h"
+
+// Qt
+#include <QDateTime>
+
+// LRC
+#include "globalinstances.h"
+#include "api/contactmodel.h"
+#include "api/conversationmodel.h"
+
+// Client
+#include "pixbufmanipulator.h"
+#include "utils.h"
+
+MessageModel::MessageModel(const ConversationInfo& conv, const AccountInfo& acc, QObject *parent)
+ : QAbstractItemModel(parent),
+ conv_(conv),
+ acc_(acc)
+{
+}
+
+int MessageModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid()) {
+ return conv_.interactions.size();
+ }
+ return 0; // A valid QModelIndex returns 0 as no entry has sub-elements
+}
+
+int MessageModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 1;
+}
+
+QVariant MessageModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || conv_.interactions.size() == 0) {
+ return QVariant();
+ }
+
+ auto it = conv_.interactions.begin();
+ std::advance(it, index.row());
+ const auto& item = (*it).second;
+ switch (role) {
+ case Role::Body:
+ return QVariant(QString::fromStdString(item.body));
+ case Role::Picture:
+ case Qt::DecorationRole:
+ return GlobalInstances::pixmapManipulator().decorationRole(conv_, acc_);
+ case Role::DisplayName:
+ case Qt::DisplayRole:
+ {
+ auto& contact = acc_.contactModel->getContact(conv_.participants[0]);
+ return QVariant(QString::fromStdString(Utils::bestNameForContact(contact)));
+ }
+ case Role::Presence:
+ {
+ auto& contact = acc_.contactModel->getContact(conv_.participants[0]);
+ return QVariant(contact.isPresent);
+ }
+ case Role::InteractionDate:
+ {
+ auto& date = item.timestamp;
+ return QVariant(QDateTime::fromTime_t(date));
+ }
+ case Role::Status:
+ return QVariant::fromValue(static_cast<int>(item.status));
+ case Role::Direction:
+ return QVariant::fromValue(lrc::api::interaction::isOutgoing(item));
+ case Role::Type:
+ return QVariant::fromValue(static_cast<int>(item.type));
+ }
+ return QVariant();
+}
+
+QModelIndex MessageModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ if (column != 0) {
+ return QModelIndex();
+ }
+
+ if (row >= 0 && row < rowCount()) {
+ return createIndex(row, column);
+ }
+ return QModelIndex();
+}
+
+QModelIndex MessageModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child);
+ return QModelIndex();
+}
+
+Qt::ItemFlags MessageModel::flags(const QModelIndex &index) const
+{
+ auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+ if (!index.isValid()) {
+ return QAbstractItemModel::flags(index);
+ } else {
+ flags &= ~(Qt::ItemIsSelectable);
+ }
+ return flags;
+}
diff --git a/messagemodel.h b/messagemodel.h
new file mode 100644
index 0000000..b8411c3
--- /dev/null
+++ b/messagemodel.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+* Copyright (C) 2017 by Savoir-faire Linux *
+* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+* *
+* 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/>. *
+***************************************************************************/
+#pragma once
+
+// Qt include
+#include <QAbstractItemModel>
+
+// LRC
+#include "api/account.h"
+#include "api/conversation.h"
+#include "api/contact.h"
+
+class MessageModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ using AccountInfo = lrc::api::account::Info;
+ using ConversationInfo = lrc::api::conversation::Info;
+ using ContactInfo = lrc::api::contact::Info;
+
+ enum Role {
+ Body = Qt::UserRole + 1,
+ DisplayName,
+ Picture,
+ Presence,
+ Status,
+ DataTransferStatus,
+ InteractionDate,
+ Direction,
+ Type
+ };
+
+ explicit MessageModel(const ConversationInfo& conv, const AccountInfo& acc, QObject *parent = 0);
+
+ // QAbstractItemModel
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+private:
+ ConversationInfo conv_;
+ const AccountInfo& acc_;
+};
diff --git a/photoboothwidget.cpp b/photoboothwidget.cpp
index 537f544..ded23f4 100644
--- a/photoboothwidget.cpp
+++ b/photoboothwidget.cpp
@@ -33,7 +33,6 @@
ui->setupUi(this);
ui->videoFeed->setIsFullPreview(true);
ui->videoFeed->setPhotoMode(true);
- startBooth();
}
PhotoboothWidget::~PhotoboothWidget()
@@ -44,12 +43,7 @@
void PhotoboothWidget::startBooth()
{
- // // // //
- // stop (or start before) to give Preview manager some time to start
- // TODO go modify the daemon to ensure starting upon calling videomanager::startCamera
Video::PreviewManager::instance().stopPreview();
- // // // //
-
Video::PreviewManager::instance().startPreview();
ui->videoFeed->show();
}
diff --git a/pixbufmanipulator.cpp b/pixbufmanipulator.cpp
index 3ca4956..f0fe02e 100644
--- a/pixbufmanipulator.cpp
+++ b/pixbufmanipulator.cpp
@@ -35,6 +35,13 @@
#include "contactmethod.h"
#include "profilemodel.h"
#include "profile.h"
+#include "globalinstances.h"
+
+ // new LRC
+#include <api/contactmodel.h>
+#include <api/conversation.h>
+#include <api/account.h>
+#include <api/contact.h>
#include "utils.h"
#include "ringthemeutils.h"
@@ -51,20 +58,13 @@
if (h.isEmpty() || h.isNull()) {
return RingTheme::defaultAvatarColor_;
}
- uint8_t colorsLength = sizeof(RingTheme::avatarColors_) / sizeof(QColor);
- bool ok;
- auto colorIndex = QString(h.at(0)).toUInt(&ok, colorsLength);
+ auto colorIndex = std::string("0123456789abcdef").find(h.at(0).toLatin1());
return RingTheme::avatarColors_[colorIndex];
}
-//
// Generate a QImage representing a dummy user avatar, when user doesn't provide it.
// Current rendering is a flat colored circle with a centered letter.
// The color of the letter is computed from the circle color to be visible whaterver be the circle color.
-//
-// \param color circle color
-// \param letter centerer letter
-//
static QImage
fallbackAvatar(const QSize size, const QString& canonicalUriStr, const QString& letterStr = QString())
{
@@ -84,6 +84,8 @@
// If a letter was passed, then we paint a letter in the circle,
// otherwise we draw the default avatar icon
+ QString letterStrCleaned(letterStr);
+ letterStrCleaned.remove(QRegExp("[\\n\\t\\r]"));
if (!letterStr.isEmpty()) {
auto letter = letterStr.at(0).toUpper().toLatin1();
QFont font("Arial", avatar.height() / 2.66667, QFont::Medium);
@@ -104,8 +106,7 @@
}
QImage
-fallbackAvatar
-(const QSize size, const ContactMethod* cm)
+fallbackAvatar(const QSize size, const ContactMethod* cm)
{
if (cm == nullptr) {
return QImage();
@@ -121,6 +122,14 @@
return image;
}
+QImage
+fallbackAvatar(const QSize size, const std::string& alias, const std::string& uri)
+{
+ return fallbackAvatar(size,
+ QString::fromStdString(uri),
+ QString::fromStdString(alias));
+}
+
/*Namespace Interfaces collide with QBuffer*/
QByteArray QImageToByteArray(QImage image)
{
@@ -174,11 +183,12 @@
QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& type)
{
QImage avatar;
- QByteArray ba = type.toLatin1();
- const char* c_str2 = ba.data();
- if (avatar.loadFromData(data.fromBase64(data), c_str2))
- return Utils::getCirclePhoto(avatar, avatar.size().width());
- return fallbackAvatar(IMAGE_SIZE, QString());
+ const bool ret = avatar.loadFromData(QByteArray::fromBase64(data), type.toLatin1());
+ if (!ret) {
+ qDebug() << "vCard image loading failed";
+ return QVariant();
+ }
+ return QPixmap::fromImage(Utils::getCirclePhoto(avatar, avatar.size().width()));
}
QVariant
@@ -287,3 +297,65 @@
selectedProfile()->person()->photo().value<QImage>(),
IMAGE_SIZE.width());
}
+
+QVariant
+PixbufManipulator::decorationRole(const lrc::api::conversation::Info & conversationInfo,
+ const lrc::api::account::Info & accountInfo)
+{
+ QImage photo;
+ auto contacts = conversationInfo.participants;
+ if (!contacts.empty()) {
+ try {
+ // Get first contact photo
+ auto contactUri = contacts.front();
+ auto contactInfo = accountInfo.contactModel->getContact(contactUri);
+ auto contactPhoto = contactInfo.profileInfo.avatar;
+ auto bestName = Utils::bestNameForContact(contactInfo);
+ auto bestId = Utils::bestIdForContact(contactInfo);
+ if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP &&
+ contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
+ photo = fallbackAvatar(IMAGE_SIZE, QString(), QString());
+ }
+ else if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP) {
+ photo = fallbackAvatar(IMAGE_SIZE,
+ QString::fromStdString("sip:" + bestId),
+ QString());
+ }
+ else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.empty()) {
+ photo = fallbackAvatar(IMAGE_SIZE, QString(), QString());
+ }
+ else if (!contactPhoto.empty()) {
+ QByteArray byteArray(contactPhoto.c_str(), contactPhoto.length());
+ photo = personPhoto(byteArray, nullptr).value<QImage>();
+ }
+ else {
+ auto avatarName = contactInfo.profileInfo.uri == bestName ?
+ QString() :
+ QString::fromStdString(bestName);
+ photo = fallbackAvatar(IMAGE_SIZE,
+ QString::fromStdString("ring:" + bestId),
+ avatarName);
+ }
+ }
+ catch (...) {}
+ }
+ return QVariant::fromValue(scaleAndFrame(photo, IMAGE_SIZE));
+}
+
+QVariant
+PixbufManipulator::accountPhoto(const lrc::api::account::Info& accountInfo)
+{
+ QImage photo;
+ if (!accountInfo.profileInfo.avatar.empty()) {
+ QByteArray ba = QByteArray::fromStdString(accountInfo.profileInfo.avatar);
+ photo = GlobalInstances::pixmapManipulator().personPhoto(ba, nullptr).value<QImage>();
+ }
+ else {
+ auto bestId = Utils::bestIdForAccount(accountInfo);
+ auto bestName = Utils::bestNameForAccount(accountInfo);
+ photo = fallbackAvatar( IMAGE_SIZE,
+ QString::fromStdString("ring:" + bestId),
+ QString::fromStdString(bestName));
+ }
+ return QVariant::fromValue(scaleAndFrame(photo, IMAGE_SIZE));
+}
diff --git a/pixbufmanipulator.h b/pixbufmanipulator.h
index 4155e5d..8bbe96a 100644
--- a/pixbufmanipulator.h
+++ b/pixbufmanipulator.h
@@ -52,7 +52,9 @@
QVariant decorationRole(const ContactMethod* cm) override;
QVariant decorationRole(const Person* p) override;
QVariant decorationRole(const Account* acc) override;
+ QVariant decorationRole(const lrc::api::conversation::Info& conversation,
+ const lrc::api::account::Info& accountInfo) override;
static QImage scaleAndFrame(const QImage photo, const QSize& size);
- static QImage scaleAndFrame(const QImage photo, const int& size);
+ static QVariant accountPhoto(const lrc::api::account::Info& accountInfo);
};
diff --git a/quickactcontactrequestwidget.cpp b/quickactcontactrequestwidget.cpp
deleted file mode 100644
index 020d9e6..0000000
--- a/quickactcontactrequestwidget.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
- * *
- * 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/>. *
- **************************************************************************/
-
-#include "quickactcontactrequestwidget.h"
-#include "ui_quickactcontactrequestwidget.h"
-
-#include <QFont>
-
-// CLIENT
-#include "contactrequestitemdelegate.h"
-
-QuickActContactRequestWidget::QuickActContactRequestWidget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::QuickActContactRequestWidget)
-{
- ui->setupUi(this);
-
- // set symbols in buttons using FontAwsome
- ui->quickValidCRBtn->setText(QChar(0xf00c));
- ui->quickMuteCRBtn->setText(QChar(0xf12d));
- ui->quickBanCRBtn->setText(QChar(0xf00d));
-
- connect(ui->quickValidCRBtn, &QPushButton::clicked, this, [=](){
- emit quickValidCRBtnClicked();
- });
-
- connect(ui->quickMuteCRBtn, &QPushButton::clicked, this, [=](){
- emit quickMuteCRBtnClicked();
- });
-
- connect(ui->quickBanCRBtn, &QPushButton::clicked, this, [=](){
- emit quickBanCRBtnClicked();
- });
-
-}
-
-QuickActContactRequestWidget::~QuickActContactRequestWidget()
-{
- disconnect(this);
- delete ui;
-}
diff --git a/ressources.qrc b/ressources.qrc
index e93b7c1..fa04106 100644
--- a/ressources.qrc
+++ b/ressources.qrc
@@ -44,5 +44,7 @@
<file>images/icons/ic_person_add_black_24dp_2x.png</file>
<file>images/waiting.gif</file>
<file>images/default-avatar-overlay.svg</file>
+ <file>images/icons/ic_clear-24px.svg</file>
+ <file>images/icons/ic_block-24px.svg</file>
</qresource>
</RCC>
diff --git a/ring-client-windows.pro b/ring-client-windows.pro
deleted file mode 100644
index 9ee5b41..0000000
--- a/ring-client-windows.pro
+++ /dev/null
@@ -1,287 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2018-06-28T15:11:54
-#
-#-------------------------------------------------
-
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets svg xml network winextras
-
-VERSION = 2.0.0
-GIT_VERSION = $$system(git --git-dir $$PWD/.git --work-tree $$PWD describe --always --tags)
-
-DEFINES += NIGHTLY_VERSION=$$system("echo %date:~10,4%%date:~4,2%%date:~7,2%")
-
-TARGET = Ring
-TEMPLATE = app
-
-contains(BUILD, Debug) {
- QMAKE_STRIP = echo
- CONFIG += console
-}
-
-isEmpty(QMAKE_LRELEASE) {
- QMAKE_LRELEASE = lrelease
-}
-
-SOURCES +=
- main.cpp\
- mainwindow.cpp \
- callwidget.cpp \
- configurationwidget.cpp \
- navwidget.cpp \
- accountdetails.cpp \
- aboutdialog.cpp \
- videowidget.cpp \
- utils.cpp \
- wizarddialog.cpp \
- windowscontactbackend.cpp \
- selectareadialog.cpp \
- accountserializationadapter.cpp \
- instantmessagingwidget.cpp \
- accountstatedelegate.cpp \
- videoview.cpp \
- videooverlay.cpp \
- imdelegate.cpp \
- contactpicker.cpp \
- contactmethodpicker.cpp \
- globalsystemtray.cpp \
- smartlistdelegate.cpp \
- callutilsdialog.cpp \
- combar.cpp \
- idlabel.cpp \
- smartlist.cpp \
- ringcontactlineedit.cpp \
- pixbufmanipulator.cpp \
- qualitydialog.cpp \
- ringbutton.cpp \
- photoboothdialog.cpp \
- sendcontactrequestwidget.cpp \
- currentaccountwidget.cpp \
- contactrequestwidget.cpp \
- contactrequestitemdelegate.cpp \
- quickactcontactrequestwidget.cpp \
- contactrequestlistwidget.cpp \
- deleteaccountdialog.cpp \
- bannedcontactswidget.cpp \
- photoboothwidget.cpp \
- deletecontactdialog.cpp
-
-HEADERS +=
- mainwindow.h \
- callwidget.h \
- configurationwidget.h \
- navwidget.h \
- accountdetails.h \
- aboutdialog.h \
- videowidget.h \
- utils.h \
- wizarddialog.h \
- windowscontactbackend.h \
- selectareadialog.h \
- accountserializationadapter.h \
- instantmessagingwidget.h \
- accountstatedelegate.h \
- videoview.h \
- videooverlay.h \
- imdelegate.h \
- contactpicker.h \
- contactmethodpicker.h \
- settingskey.h \
- globalsystemtray.h \
- smartlistdelegate.h \
- callutilsdialog.h \
- combar.h \
- idlabel.h \
- smartlist.h \
- ringcontactlineedit.h \
- pixbufmanipulator.h \
- qualitydialog.h \
- ringthemeutils.h \
- ringbutton.h \
- photoboothdialog.h \
- sendcontactrequestwidget.h \
- currentaccountwidget.h \
- contactrequestwidget.h \
- contactrequestitemdelegate.h \
- quickactcontactrequestwidget.h \
- contactrequestlistwidget.h \
- deleteaccountdialog.h \
- bannedcontactswidget.h \
- photoboothwidget.h \
- deletecontactdialog.h \
- lrcinstance.h
-
-contains(DEFINES, URI_PROTOCOL) {
- HEADERS += shmclient.h
- SOURCES += shmclient.cpp
-}
-
-FORMS +=
- mainwindow.ui \
- callwidget.ui \
- configurationwidget.ui \
- accountdetails.ui \
- aboutdialog.ui \
- wizarddialog.ui \
- instantmessagingwidget.ui \
- videoview.ui \
- videooverlay.ui \
- contactpicker.ui \
- contactmethodpicker.ui \
- callutilsdialog.ui \
- combar.ui \
- qualitydialog.ui \
- ringbutton.ui \
- photoboothdialog.ui \
- sendcontactrequestwidget.ui \
- currentaccountwidget.ui \
- contactrequestwidget.ui \
- quickactcontactrequestwidget.ui \
- deleteaccountdialog.ui \
- bannedcontactswidget.ui \
- photoboothwidget.ui \
- deletecontactdialog.ui
-
-INCLUDEPATH += $${RING}/lrc/src
-INCLUDEPATH += $${RING}/client-windows/winsparkle/include
-INCLUDEPATH += $${RING}/client-windows/qrencode-win32/qrencode-win32
-
-
-CONFIG( debug, debug|release ) {
- # debug
- # daemon lib
- LIBS += -L$$PWD/../daemon/contrib/msvc/lib/x64/
- LIBS += -L$$PWD/../daemon/MSVC/x64/DebugLib_win32/bin/ -ldring
-
- # lrc lib
- LIBS += -L$$PWD/../lrc/msvc/Debug/ -lringclient_s
-
- # winsparkle lib
- LIBS += -L$$PWD/winsparkle/x64/release/ -lWinSparkle
-
- # qrcode lib
- LIBS += -L$$PWD/qrencode-win32/qrencode-win32/vc8/qrcodelib/x64/Release-Lib/ -lqrcodelib
-} else {
- # release
- # debug
- # daemon lib
- LIBS += -L$$PWD/../daemon/contrib/msvc/lib/x64/
- LIBS += -L$$PWD/../daemon/MSVC/x64/ReleaseLib_win32/bin/ -ldring
-
- # lrc lib
- LIBS += -L$$PWD/../lrc/msvc/Release/ -lringclient_s
-
- # winsparkle lib
- LIBS += -L$$PWD/winsparkle/x64/release/ -lWinSparkle
-
- # qrcode lib
- LIBS += -L$$PWD/qrencode-win32/qrencode-win32/vc8/qrcodelib/x64/Release-Lib/ -lqrcodelib
-
- QMAKE_LFLAGS_RELEASE += /FORCE:MULTIPLE
-}
-
-LIBS += -lOle32 -lAdvapi32 -lShlwapi -lUser32 -lGdi32 -lCrypt32 -lStrmiids
-
-RESOURCES += \
- ressources.qrc
-
-RC_FILE = ico.rc
-
-TRANSLATIONS = \
- translations/ring_client_windows_nb.ts \
- translations/ring_client_windows_pa.ts \
- translations/ring_client_windows_pt_BR.ts \
- translations/ring_client_windows_pt.ts \
- translations/ring_client_windows_ms.ts \
- translations/ring_client_windows_de.ts \
- translations/ring_client_windows_uk.ts \
- translations/ring_client_windows_sq_AL.ts \
- translations/ring_client_windows_ca.ts \
- translations/ring_client_windows_es.ts \
- translations/ring_client_windows_da_DK.ts \
- translations/ring_client_windows_et_EE.ts \
- translations/ring_client_windows_de_DE.ts \
- translations/ring_client_windows_lt.ts \
- translations/ring_client_windows_fr_FR.ts \
- translations/ring_client_windows_nl_BE.ts \
- translations/ring_client_windows_he.ts \
- translations/ring_client_windows_sk_SK.ts \
- translations/ring_client_windows_pl.ts \
- translations/ring_client_windows_es_AR.ts \
- translations/ring_client_windows_nl.ts \
- translations/ring_client_windows_it_IT.ts \
- translations/ring_client_windows_bg.ts \
- translations/ring_client_windows_id.ts \
- translations/ring_client_windows_en_GB.ts \
- translations/ring_client_windows_pl_PL.ts \
- translations/ring_client_windows.ts \
- translations/ring_client_windows_eu.ts \
- translations/ring_client_windows_eo.ts \
- translations/ring_client_windows_nl_NL.ts \
- translations/ring_client_windows_ru_RU.ts \
- translations/ring_client_windows_hr.ts \
- translations/ring_client_windows_zh_CN.ts \
- translations/ring_client_windows_fr.ts \
- translations/ring_client_windows_tr.ts \
- translations/ring_client_windows_cs_CZ.ts \
- translations/ring_client_windows_zh_TW.ts \
- translations/ring_client_windows_fr_CA.ts \
- translations/ring_client_windows_ko_KR.ts \
- translations/ring_client_windows_zh.ts \
- translations/ring_client_windows_fa_IR.ts \
- translations/ring_client_windows_fi.ts \
- translations/ring_client_windows_sv.ts \
- translations/ring_client_windows_it.ts \
- translations/ring_client_windows_el.ts \
- translations/ring_client_windows_ja.ts \
- translations/ring_client_windows_hu.ts \
- translations/ring_client_windows_sl.ts \
- translations/ring_client_windows_hi_IN.ts \
- translations/ring_client_windows_ro.ts \
- translations/ring_client_windows_ru.ts \
- translations/ring_client_windows_ar.ts \
-
-RINGTONES.files = $${RING}/daemon/ringtones
-RINGTONES.path = $$OUT_PWD/release
-
-PACKAGING.files = ring.nsi images/ring.ico
-PACKAGING.path = $$OUT_PWD/release
-
-LICENSE.files = License.rtf
-LICENSE.path = $$OUT_PWD/release
-
-RUNTIMEDIR=$$[QT_INSTALL_BINS]
-
-RUNTIME.files = $${RING}/lrc/msvc/Release/ringclient.dll
-RUNTIME.path = $$OUT_PWD/release
-
-LRC_TRANSLATION.files = $${RING}/share/libringclient/translations
-LRC_TRANSLATION.path = $$OUT_PWD/release/share/libringclient/
-
-QTRUNTIME.files = $$RUNTIMEDIR/Qt5Core.dll $$RUNTIMEDIR/Qt5Widgets.dll \
- $$RUNTIMEDIR/Qt5Gui.dll $$RUNTIMEDIR/Qt5Svg.dll \
- $$RUNTIMEDIR/Qt5Xml.dll $$RUNTIMEDIR/Qt5WinExtras.dll \
- $$RUNTIMEDIR/Qt5Network.dll $$RUNTIMEDIR/Qt5Sql.dll
-QTRUNTIME.path = $$OUT_PWD/release
-
-QTDEPSRUNTIME.path = $$OUT_PWD/release
-
-QTPLATFORMS.files = $$[QT_INSTALL_PLUGINS]/platforms/qwindows.dll
-QTPLATFORMS.path = $$OUT_PWD/release/platforms
-
-QTPLUGINIMAGE.files = $$[QT_INSTALL_PLUGINS]/imageformats/
-QTPLUGINIMAGE.path = $$OUT_PWD/release
-
-QTSQLDRIVERS.files = $$[QT_INSTALL_PLUGINS]/sqldrivers/qsqlite.dll
-QTSQLDRIVERS.path = $$OUT_PWD/release/sqldrivers
-
-LIBSTD.files = $$RUNTIMEDIR/libgcc_s_sjlj-1.dll $$RUNTIMEDIR/libstdc++-6.dll \
- $$RUNTIMEDIR/libwinpthread-1.dll $$RUNTIMEDIR/libgcc_s_seh-1.dll
-LIBSTD.path = $$OUT_PWD/release
-
-INSTALLS += RINGTONES PACKAGING LICENSE RUNTIME LRC_TRANSLATION QTRUNTIME QTDEPSRUNTIME \
- QTPLUGINIMAGE QTPLATFORMS QTSQLDRIVERS LIBSTD
-
-DEFINES += ENABLE_AUTOUPDATE
diff --git a/ring-client-windows.sln b/ring-client-windows.sln
index f2e9245..222923c 100644
--- a/ring-client-windows.sln
+++ b/ring-client-windows.sln
@@ -37,15 +37,16 @@
RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x64.ActiveCfg = Debug|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x64.Build.0 = Debug|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x86.ActiveCfg = Debug|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x64.ActiveCfg = Debug|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x64.Build.0 = Debug|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x64.ActiveCfg = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x64.Build.0 = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x86.ActiveCfg = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.Debug|x86.Build.0 = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x64.ActiveCfg = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x64.Build.0 = Release|x64
{0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x86.ActiveCfg = Release|x64
{0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib_win32|x86.Build.0 = Release|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x64.ActiveCfg = Debug|x64
- {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x64.Build.0 = Debug|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x64.ActiveCfg = Release|x64
+ {0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x64.Build.0 = Release|x64
{0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x86.ActiveCfg = Release|x64
{0F6318E4-4C06-384E-BCA8-F344DA187957}.DebugLib|x86.Build.0 = Release|x64
{0F6318E4-4C06-384E-BCA8-F344DA187957}.MinSizeRel|x64.ActiveCfg = Release|x64
diff --git a/ring-client-windows.vcxproj b/ring-client-windows.vcxproj
index d092da0..cb7f54b 100644
--- a/ring-client-windows.vcxproj
+++ b/ring-client-windows.vcxproj
@@ -5,10 +5,6 @@
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0F6318E4-4C06-384E-BCA8-F344DA187957}</ProjectGuid>
@@ -26,15 +22,6 @@
<IntermediateDirectory>release\</IntermediateDirectory>
<PrimaryOutput>Ring</PrimaryOutput>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <PlatformToolset>v141</PlatformToolset>
- <OutputDirectory>debug\</OutputDirectory>
- <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
- <CharacterSet>NotSet</CharacterSet>
- <ConfigurationType>Application</ConfigurationType>
- <IntermediateDirectory>debug\</IntermediateDirectory>
- <PrimaryOutput>Ring</PrimaryOutput>
- </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')">
<QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
@@ -49,9 +36,6 @@
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
- </ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
@@ -59,19 +43,15 @@
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Ring</TargetName>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Ring</TargetName>
- <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
- <AdditionalIncludeDirectories>.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)../daemon/contrib/msvc/include;$(ProjectDir)../lrc/src;$(ProjectDir)../client-windows/winsparkle/include;$(ProjectDir)../client-windows/qrencode-win32/qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;release;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>release\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4068;4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4068;4099;4189;4267;4577;4467;4715;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>MaxSpeed</Optimization>
@@ -90,7 +70,7 @@
<Link>
<AdditionalDependencies>..\daemon\MSVC\x64\ReleaseLib_win32\bin\dring.lib;..\lrc\msvc\src\qtwrapper\Release\qtwrapper.lib;..\lrc\msvc\release\ringclient_static.lib;.\winsparkle\x64\release\WinSparkle.lib;.\qrencode-win32\qrencode-win32\vc8\qrcodelib\x64\Release-Lib\qrcodelib.lib;shell32.lib;Ole32.lib;Advapi32.lib;Shlwapi.lib;User32.lib;Gdi32.lib;Crypt32.lib;Strmiids.lib;$(QTDIR)\lib\qtmain.lib;$(QTDIR)\lib\Qt5Svg.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5WinExtras.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Xml.lib;$(QTDIR)\lib\Qt5Network.lib;$(QTDIR)\lib\Qt5Core.lib;$(QTDIR)\lib\Qt5Sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(QTDIR)\lib;..\daemon\contrib\msvc\lib\x64;..\daemon\MSVC\x64\ReleaseLib_win32\bin;..\lrc\msvc\release;.\winsparkle\x64\release;.\qrencode-win32\qrencode-win32\vc8\qrcodelib\x64\Release-Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /ignore:4006,4049,4078,4098 /LTCG /NODEFAULTLIB:LIBCMT %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
@@ -136,109 +116,53 @@
<QTDIR>$(QTDIR)</QTDIR>
</QtUic>
</ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)../lrc/src;$(ProjectDir)../client-windows/winsparkle/include;$(ProjectDir)../client-windows/qrencode-win32/qrencode-win32;$(QTDIR)\include;debug;$(QTDIR)\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
- <AssemblerListingLocation>debug\</AssemblerListingLocation>
- <BrowseInformation>false</BrowseInformation>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4068;4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
- <ExceptionHandling>Sync</ExceptionHandling>
- <ObjectFileName>$(IntDir)</ObjectFileName>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <PreprocessToFile>false</PreprocessToFile>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
- <WarningLevel>Level3</WarningLevel>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
- </ClCompile>
- <Link>
- <AdditionalDependencies>$(QTDIR)\lib\qtmaind.lib;shell32.lib;C:\Users\fner\Desktop\RINGVS2017\ring-project\daemon\MSVC\x64\DebugLib_win32\bin\dringd.lib;C:\Users\fner\Desktop\RINGVS2017\ring-project\lrc\msvc\debug\ringclient_s.lib;.\winsparkle\x64\release\WinSparkle.lib;.\qrencode-win32\qrencode-win32\vc8\qrcodelib\x64\Release-Lib\qrcodelib.lib;Ole32.lib;Advapi32.lib;Shlwapi.lib;User32.lib;Gdi32.lib;Crypt32.lib;Mmdevapi.lib;$(QTDIR)\lib\Qt5Svgd.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5WinExtrasd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Xmld.lib;$(QTDIR)\lib\Qt5Networkd.lib;$(QTDIR)\lib\Qt5Cored.lib;$(QTDIR)\lib\Qt5Sqld.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;$(QTDIR)\lib;C:\Users\fner\Desktop\RINGVS2017\ring-project\daemon\contrib\msvc\lib\x64;C:\Users\fner\Desktop\RINGVS2017\ring-project\daemon\MSVC\x64\ReleaseLib\bin;C:\Users\fner\Desktop\RINGVS2017\ring-project\lrc\msvc\release;.\winsparkle\x64\release;.\qrencode-win32\qrencode-win32\vc8\qrcodelib\x64\Release-Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
- <DataExecutionPrevention>true</DataExecutionPrevention>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <IgnoreImportLibrary>true</IgnoreImportLibrary>
- <OutputFile>$(OutDir)\Ring.exe</OutputFile>
- <RandomizedBaseAddress>true</RandomizedBaseAddress>
- <SubSystem>Windows</SubSystem>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <Version>2.0</Version>
- </Link>
- <Midl>
- <DefaultCharType>Unsigned</DefaultCharType>
- <EnableErrorChecks>None</EnableErrorChecks>
- <WarningLevel>0</WarningLevel>
- </Midl>
- <ResourceCompile>
- <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ResourceCompile>
- <QtRcc>
- <QTDIR>$(QTDIR)</QTDIR>
- <ExecutionDescription>Rcc'ing %(Identity)...</ExecutionDescription>
- <Compression>default</Compression>
- <InitFuncName>ressources</InitFuncName>
- <OutputFile>.\GeneratedFiles\qrc_%(Filename).cpp</OutputFile>
- <InputFile>%(FullPath)</InputFile>
- </QtRcc>
- <QtMoc>
- <QTDIR>$(QTDIR)</QTDIR>
- <OutputFile>.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</OutputFile>
- <Define>_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;%(PreprocessorDefinitions)</Define>
- <CompilerFlavor>msvc</CompilerFlavor>
- <Include>$(Configuration)/moc_predefs.h</Include>
- <ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription>
- <InputFile>%(FullPath)</InputFile>
- <DynamicSource>output</DynamicSource>
- <IncludePath>.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)../lrc/src;$(ProjectDir)../client-windows/winsparkle/include;$(ProjectDir)../client-windows/qrencode-win32/qrencode-win32;$(QTDIR)\include;debug;$(QTDIR)\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</IncludePath>
- </QtMoc>
- <QtUic>
- <InputFile>%(FullPath)</InputFile>
- <ExecutionDescription>Uic'ing %(Identity)...</ExecutionDescription>
- <OutputFile>.\GeneratedFiles\ui_%(Filename).h</OutputFile>
- <QTDIR>$(QTDIR)</QTDIR>
- </QtUic>
- </ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="aboutdialog.cpp" />
<ClCompile Include="accountdetails.cpp" />
+ <ClCompile Include="accountitemdelegate.cpp" />
<ClCompile Include="accountserializationadapter.cpp" />
+ <ClCompile Include="accountlistmodel.cpp" />
<ClCompile Include="accountstatedelegate.cpp" />
<ClCompile Include="bannedcontactswidget.cpp" />
<ClCompile Include="callutilsdialog.cpp" />
- <ClCompile Include="callwidget.cpp" />
- <ClCompile Include="combar.cpp" />
+ <ClCompile Include="callwidget.cpp">
+ <OutputFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\%(Filename).moc</OutputFile>
+ <DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
+ </ClCompile>
<ClCompile Include="configurationwidget.cpp" />
- <ClCompile Include="contactmethodpicker.cpp" />
<ClCompile Include="contactpicker.cpp" />
- <ClCompile Include="contactrequestitemdelegate.cpp" />
- <ClCompile Include="contactrequestlistwidget.cpp" />
<ClCompile Include="contactrequestwidget.cpp" />
<ClCompile Include="currentaccountwidget.cpp" />
<ClCompile Include="deleteaccountdialog.cpp" />
- <ClCompile Include="deletecontactdialog.cpp" />
<ClCompile Include="globalsystemtray.cpp" />
<ClCompile Include="idlabel.cpp" />
<ClCompile Include="imdelegate.cpp" />
<ClCompile Include="instantmessagingwidget.cpp" />
+ <ClCompile Include="invitebuttonswidget.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mainwindow.cpp" />
+ <ClCompile Include="messagemodel.cpp" />
<ClCompile Include="navwidget.cpp" />
<ClCompile Include="photoboothdialog.cpp" />
<ClCompile Include="photoboothwidget.cpp" />
<ClCompile Include="pixbufmanipulator.cpp" />
<ClCompile Include="qualitydialog.cpp" />
- <ClCompile Include="quickactcontactrequestwidget.cpp" />
<ClCompile Include="ringbutton.cpp" />
<ClCompile Include="ringcontactlineedit.cpp" />
<ClCompile Include="selectareadialog.cpp" />
<ClCompile Include="sendcontactrequestwidget.cpp" />
- <ClCompile Include="smartlist.cpp" />
- <ClCompile Include="smartlistdelegate.cpp" />
+ <ClCompile Include="conversationsfilterwidget.cpp">
+ <OutputFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\%(Filename).moc</OutputFile>
+ <DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
+ </ClCompile>
+ <ClCompile Include="smartlistselectorbuttonnotifier.cpp" />
+ <ClCompile Include="smartlistview.cpp" />
+ <ClCompile Include="conversationitemdelegate.cpp" />
+ <ClCompile Include="smartlistmodel.cpp" />
<ClCompile Include="utils.cpp" />
<ClCompile Include="videooverlay.cpp" />
<ClCompile Include="videoview.cpp" />
@@ -261,16 +185,17 @@
</QtMoc>
<QtMoc Include="callwidget.h">
</QtMoc>
- <QtMoc Include="combar.h">
- </QtMoc>
<QtMoc Include="configurationwidget.h">
</QtMoc>
- <QtMoc Include="contactmethodpicker.h">
- </QtMoc>
<QtMoc Include="contactpicker.h">
</QtMoc>
- <ClInclude Include="contactrequestitemdelegate.h" />
- <QtMoc Include="contactrequestlistwidget.h">
+ <QtMoc Include="accountlistmodel.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB</Define>
+ </QtMoc>
+ <QtMoc Include="accountitemdelegate.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB</Define>
</QtMoc>
<QtMoc Include="contactrequestwidget.h">
</QtMoc>
@@ -278,8 +203,6 @@
</QtMoc>
<QtMoc Include="deleteaccountdialog.h">
</QtMoc>
- <QtMoc Include="deletecontactdialog.h">
- </QtMoc>
<QtMoc Include="globalsystemtray.h">
</QtMoc>
<QtMoc Include="idlabel.h">
@@ -296,12 +219,18 @@
</QtMoc>
<QtMoc Include="photoboothwidget.h">
</QtMoc>
+ <QtMoc Include="invitebuttonswidget.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
+ </QtMoc>
<ClInclude Include="lrcinstance.h" />
+ <QtMoc Include="messagemodel.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB</Define>
+ </QtMoc>
<ClInclude Include="pixbufmanipulator.h" />
<QtMoc Include="qualitydialog.h">
</QtMoc>
- <QtMoc Include="quickactcontactrequestwidget.h">
- </QtMoc>
<QtMoc Include="ringbutton.h">
</QtMoc>
<QtMoc Include="ringcontactlineedit.h">
@@ -312,9 +241,25 @@
<QtMoc Include="sendcontactrequestwidget.h">
</QtMoc>
<ClInclude Include="settingskey.h" />
- <QtMoc Include="smartlist.h">
+ <QtMoc Include="smartlistview.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB</Define>
</QtMoc>
- <QtMoc Include="smartlistdelegate.h">
+ <QtMoc Include="conversationitemdelegate.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
+ </QtMoc>
+ <QtMoc Include="smartlistmodel.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_SVG_LIB;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_XML_LIB;QT_NETWORK_LIB;QT_CORE_LIB</Define>
+ </QtMoc>
+ <QtMoc Include="conversationsfilterwidget.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
+ </QtMoc>
+ <QtMoc Include="smartlistselectorbuttonnotifier.h">
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define>
</QtMoc>
<ClInclude Include="utils.h" />
<QtMoc Include="videooverlay.h">
@@ -331,10 +276,6 @@
<CustomBuild Include="debug\moc_predefs.h.cbt">
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h</Command>
- <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_predefs.h;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Include="release\moc_predefs.h.cbt">
<FileType>Document</FileType>
@@ -342,21 +283,17 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</CustomBuild>
<ClInclude Include="ui_aboutdialog.h" />
<ClInclude Include="ui_accountdetails.h" />
<ClInclude Include="ui_bannedcontactswidget.h" />
<ClInclude Include="ui_callutilsdialog.h" />
<ClInclude Include="ui_callwidget.h" />
- <ClInclude Include="ui_combar.h" />
<ClInclude Include="ui_configurationwidget.h" />
- <ClInclude Include="ui_contactmethodpicker.h" />
<ClInclude Include="ui_contactpicker.h" />
<ClInclude Include="ui_contactrequestwidget.h" />
<ClInclude Include="ui_currentaccountwidget.h" />
<ClInclude Include="ui_deleteaccountdialog.h" />
- <ClInclude Include="ui_deletecontactdialog.h" />
<ClInclude Include="ui_instantmessagingwidget.h" />
<ClInclude Include="ui_mainwindow.h" />
<ClInclude Include="ui_photoboothdialog.h" />
@@ -433,13 +370,10 @@
<QtUic Include="callutilsdialog.ui">
</QtUic>
<QtUic Include="callwidget.ui">
- </QtUic>
- <QtUic Include="combar.ui">
+ <SubType>Designer</SubType>
</QtUic>
<QtUic Include="configurationwidget.ui">
</QtUic>
- <QtUic Include="contactmethodpicker.ui">
- </QtUic>
<QtUic Include="contactpicker.ui">
</QtUic>
<QtUic Include="contactrequestwidget.ui">
@@ -448,10 +382,9 @@
</QtUic>
<QtUic Include="deleteaccountdialog.ui">
</QtUic>
- <QtUic Include="deletecontactdialog.ui">
- </QtUic>
<QtUic Include="instantmessagingwidget.ui">
</QtUic>
+ <QtUic Include="invitebuttonswidget.ui" />
<QtUic Include="mainwindow.ui">
</QtUic>
<QtUic Include="photoboothdialog.ui">
diff --git a/ring-client-windows.vcxproj.filters b/ring-client-windows.vcxproj.filters
index a777fab..276995b 100644
--- a/ring-client-windows.vcxproj.filters
+++ b/ring-client-windows.vcxproj.filters
@@ -75,27 +75,12 @@
<ClCompile Include="callutilsdialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="callwidget.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="combar.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="configurationwidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="contactmethodpicker.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="contactpicker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="contactrequestitemdelegate.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="contactrequestlistwidget.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="contactrequestwidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -105,9 +90,6 @@
<ClCompile Include="deleteaccountdialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="deletecontactdialog.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="globalsystemtray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -141,9 +123,6 @@
<ClCompile Include="qualitydialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="quickactcontactrequestwidget.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="ringbutton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -156,12 +135,6 @@
<ClCompile Include="sendcontactrequestwidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="smartlist.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="smartlistdelegate.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -180,6 +153,36 @@
<ClCompile Include="wizarddialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="smartlistview.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="smartlistmodel.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="messagemodel.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="accountlistmodel.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="accountitemdelegate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="callwidget.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="conversationitemdelegate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="conversationsfilterwidget.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="smartlistselectorbuttonnotifier.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="invitebuttonswidget.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="aboutdialog.h">
@@ -203,24 +206,12 @@
<QtMoc Include="callwidget.h">
<Filter>Header Files</Filter>
</QtMoc>
- <QtMoc Include="combar.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<QtMoc Include="configurationwidget.h">
<Filter>Header Files</Filter>
</QtMoc>
- <QtMoc Include="contactmethodpicker.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<QtMoc Include="contactpicker.h">
<Filter>Header Files</Filter>
</QtMoc>
- <ClInclude Include="contactrequestitemdelegate.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <QtMoc Include="contactrequestlistwidget.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<QtMoc Include="contactrequestwidget.h">
<Filter>Header Files</Filter>
</QtMoc>
@@ -230,9 +221,6 @@
<QtMoc Include="deleteaccountdialog.h">
<Filter>Header Files</Filter>
</QtMoc>
- <QtMoc Include="deletecontactdialog.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<QtMoc Include="globalsystemtray.h">
<Filter>Header Files</Filter>
</QtMoc>
@@ -263,9 +251,6 @@
<QtMoc Include="qualitydialog.h">
<Filter>Header Files</Filter>
</QtMoc>
- <QtMoc Include="quickactcontactrequestwidget.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<QtMoc Include="ringbutton.h">
<Filter>Header Files</Filter>
</QtMoc>
@@ -284,12 +269,6 @@
<ClInclude Include="settingskey.h">
<Filter>Header Files</Filter>
</ClInclude>
- <QtMoc Include="smartlist.h">
- <Filter>Header Files</Filter>
- </QtMoc>
- <QtMoc Include="smartlistdelegate.h">
- <Filter>Header Files</Filter>
- </QtMoc>
<ClInclude Include="utils.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -308,6 +287,33 @@
<QtMoc Include="wizarddialog.h">
<Filter>Header Files</Filter>
</QtMoc>
+ <QtMoc Include="smartlistmodel.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="smartlistview.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="messagemodel.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="accountlistmodel.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="accountitemdelegate.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="conversationitemdelegate.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="conversationsfilterwidget.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="smartlistselectorbuttonnotifier.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
+ <QtMoc Include="invitebuttonswidget.h">
+ <Filter>Header Files</Filter>
+ </QtMoc>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
@@ -331,15 +337,9 @@
<ClInclude Include="ui_callwidget.h">
<Filter>Generated Files</Filter>
</ClInclude>
- <ClInclude Include="ui_combar.h">
- <Filter>Generated Files</Filter>
- </ClInclude>
<ClInclude Include="ui_configurationwidget.h">
<Filter>Generated Files</Filter>
</ClInclude>
- <ClInclude Include="ui_contactmethodpicker.h">
- <Filter>Generated Files</Filter>
- </ClInclude>
<ClInclude Include="ui_contactpicker.h">
<Filter>Generated Files</Filter>
</ClInclude>
@@ -352,9 +352,6 @@
<ClInclude Include="ui_deleteaccountdialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
- <ClInclude Include="ui_deletecontactdialog.h">
- <Filter>Generated Files</Filter>
- </ClInclude>
<ClInclude Include="ui_instantmessagingwidget.h">
<Filter>Generated Files</Filter>
</ClInclude>
@@ -563,15 +560,9 @@
<QtUic Include="callwidget.ui">
<Filter>Form Files</Filter>
</QtUic>
- <QtUic Include="combar.ui">
- <Filter>Form Files</Filter>
- </QtUic>
<QtUic Include="configurationwidget.ui">
<Filter>Form Files</Filter>
</QtUic>
- <QtUic Include="contactmethodpicker.ui">
- <Filter>Form Files</Filter>
- </QtUic>
<QtUic Include="contactpicker.ui">
<Filter>Form Files</Filter>
</QtUic>
@@ -584,9 +575,6 @@
<QtUic Include="deleteaccountdialog.ui">
<Filter>Form Files</Filter>
</QtUic>
- <QtUic Include="deletecontactdialog.ui">
- <Filter>Form Files</Filter>
- </QtUic>
<QtUic Include="instantmessagingwidget.ui">
<Filter>Form Files</Filter>
</QtUic>
@@ -620,6 +608,9 @@
<QtUic Include="wizarddialog.ui">
<Filter>Form Files</Filter>
</QtUic>
+ <QtUic Include="invitebuttonswidget.ui">
+ <Filter>Form Files</Filter>
+ </QtUic>
</ItemGroup>
<ItemGroup>
<None Include="images\FontAwesome.otf">
diff --git a/ringthemeutils.h b/ringthemeutils.h
index da8e504..8b77e73 100644
--- a/ringthemeutils.h
+++ b/ringthemeutils.h
@@ -26,11 +26,13 @@
static const QColor imGrey_ {"#dedee0"};
static const QColor imBlue_ {"#cfebf5"};
static const QColor lightBlack_ {63, 63, 63};
-static const QColor grey_ {192, 192, 192};
+static const QColor grey_ {160, 160, 160 };
static const QColor red_ {251, 72, 71};
static const QColor lightRed_ {252, 91, 90};
static const QColor darkRed_ {219, 55, 54};
+static const QColor notificationRed_{ 255, 59, 48 };
static const QColor green_ {127, 255, 0};
+static const QColor presenceGreen_{ 76, 217, 100 };
static const QColor smartlistSelection_ { 237, 237, 237 };
static const QColor smartlistHighlight_ { 242, 242, 242 };
diff --git a/settingskey.h b/settingskey.h
index 9fd4234..8a2453a 100644
--- a/settingskey.h
+++ b/settingskey.h
@@ -24,9 +24,8 @@
constexpr static char autoAnswer[] = "autoAnswer";
constexpr static char geometry[] = "geometry";
constexpr static char windowState[] = "windowState";
-constexpr static char imShowAuthor[] = "imShowAuthor";
-constexpr static char imShowDate[] = "imShowDate";
constexpr static char enableNotifications[] = "enableNotifications";
+constexpr static char selectedAccount[] = "selectedAccount";
}
#define accountAutoAnswer(A) (A+SettingsKey::autoAnswer)
diff --git a/smartlist.cpp b/smartlist.cpp
deleted file mode 100644
index 21db00e..0000000
--- a/smartlist.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
- * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
- * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
- * *
- * 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/>. *
- **************************************************************************/
-
-#include <QStyledItemDelegate>
-#include <QEvent>
-#include <QTreeWidgetItem>
-#include <QScrollBar>
-
-#include "smartlistdelegate.h"
-#include "combar.h"
-#include "smartlist.h"
-
-#include <ciso646>
-
-SmartList::SmartList(QWidget *parent) :
- QTreeView(parent)
-{
- verticalScrollBar()->hide();
-
- connect(this, &QAbstractItemView::entered, [this](const QModelIndex & index) {
- auto widget = indexWidget(index);
- if (!widget) {
- ComBar* bar = new ComBar();
- setIndexWidget(index, bar);
- connect(bar, &ComBar::btnVideoClicked, this, [=](){ emit btnVideoClicked(); });
- }
- else if (index.isValid())
- indexWidget(index)->setVisible(true);
-
- if(hoveredRow_.isValid() and indexWidget(hoveredRow_))
- indexWidget(hoveredRow_)->setVisible(false);
-
- hoveredRow_ = index;
- });
-
- setVerticalScrollMode(ScrollPerPixel);
-}
-
-SmartList::~SmartList()
-{
- reset();
-}
-
-void
-SmartList::enterEvent(QEvent* event)
-{
- Q_UNUSED(event);
- verticalScrollBar()->show();
-}
-
-void
-SmartList::leaveEvent(QEvent* event)
-{
- Q_UNUSED(event);
-
- hoveredRow_ = QModelIndex();
- verticalScrollBar()->hide();
-}
-
-void
-SmartList::setSmartListItemDelegate(SmartListDelegate* delegate)
-{
- if (delegate) {
- setItemDelegate(delegate);
- smartListDelegate_ = delegate;
- }
-}
-
-bool
-SmartList::eventFilter(QObject* watched, QEvent* event)
-{
-
- if (qobject_cast<QScrollBar*>(watched) && event->type() == QEvent::Enter) {
- hoveredRow_ = QModelIndex();
- return true;
- }
-
- return QObject::eventFilter(watched, event);
-}
-
-
-void
-SmartList::drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
-{
- if(index == hoveredRow_ && indexWidget(hoveredRow_))
- indexWidget(index)->setVisible(true);
- else if(indexWidget(index))
- indexWidget(index)->setVisible(false);
-
- QTreeView::drawRow(painter, option, index);
-}
diff --git a/smartlistdelegate.cpp b/smartlistdelegate.cpp
deleted file mode 100644
index cb9d964..0000000
--- a/smartlistdelegate.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
- * *
- * 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/>. *
- **************************************************************************/
-
-#include "smartlistdelegate.h"
-
-#include <QApplication>
-#include <QSortFilterProxyModel>
-#include <QPainter>
-#include <QPixmap>
-#include <QDebug>
-
-// LRC
-#include "itemdataroles.h"
-#include "person.h"
-#include "recentmodel.h"
-#include "call.h"
-
-// Client
-#include "combar.h"
-#include "ringthemeutils.h"
-
-#include <ciso646>
-
-SmartListDelegate::SmartListDelegate(QObject* parent) :
- QItemDelegate(parent)
-{
-}
-
-void
-SmartListDelegate::paint(QPainter* painter
- , const QStyleOptionViewItem& option
- , const QModelIndex& index
- ) const
-{
- QStyleOptionViewItem opt(option);
- painter->setRenderHint(QPainter::Antialiasing);
-
- // Not having focus removes dotted lines around the item
- if (opt.state & QStyle::State_HasFocus)
- opt.state ^= QStyle::State_HasFocus;
-
- // First, we draw the control itself
- QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
- style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
-
- bool selected = false;
- if (option.state & QStyle::State_Selected) {
- selected = true;
- opt.state ^= QStyle::State_Selected;
- painter->fillRect(option.rect, RingTheme::smartlistSelection_);
- }
- else if (option.state & QStyle::State_MouseOver) {
- painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
- }
-
- QRect &rect = opt.rect;
-
- // Avatar drawing
- opt.decorationSize = QSize(sizeImage_, sizeImage_);
- opt.decorationPosition = QStyleOptionViewItem::Left;
- opt.decorationAlignment = Qt::AlignCenter;
-
- QRect rectAvatar(16 + rect.left(), rect.top() + dy_, sizeImage_, sizeImage_);
- drawDecoration(painter, opt, rectAvatar,
- QPixmap::fromImage(index.data(Qt::DecorationRole).value<QImage>())
- .scaled(sizeImage_, sizeImage_, Qt::KeepAspectRatio, Qt::SmoothTransformation));
-
- QFont font(painter->font());
-
- // If there's unread messages, a message count is displayed
- if (auto messageCount = index.data(static_cast<int>(Ring::Role::UnreadTextMessageCount)).toInt()) {
- font.setPointSize(8);
- QFontMetrics textFontMetrics(font);
-
- // If there is more than 10 unread messages, "10+" is displayed
- QString messageCountText = (messageCount >= 10)? "9+" : QString::number(messageCount);
-
- // This QRect is the bounding one containing the message count to be displayed
- QRect pastilleRect = textFontMetrics.boundingRect(QRect(rectAvatar.left() - (2 * sizeImage_)/9,
- rectAvatar.bottom() - sizeImage_/3 - textFontMetrics.height(), sizeImage_, textFontMetrics.height()),
- Qt::AlignVCenter | Qt::AlignLeft, messageCountText);
-
- // This one is larger than pastilleRect and is used to prepare the red background
- QRect bubbleRect(pastilleRect.left() - 3, pastilleRect.top(),
- pastilleRect.width() + 6, pastilleRect.height() + 1);
-
- // The background is displayed
- QPainterPath path;
- path.addRoundedRect(bubbleRect, 3, 3);
- QPen pen(RingTheme::red_, 5);
- painter->setOpacity(0.9);
- painter->setPen(pen);
- painter->fillPath(path, RingTheme::red_);
-
- // Then the message count
- painter->setPen(Qt::white);
- painter->setOpacity(1);
- painter->setFont(font);
- painter->drawText(pastilleRect, Qt::AlignCenter, messageCountText);
- }
-
- // Presence indicator
- QPainterPath outerCircle, innerCircle;
- QPointF center(rectAvatar.right() - sizeImage_/6, (rectAvatar.bottom() - sizeImage_/6) + 1);
- qreal outerCRadius = sizeImage_ / 6, innerCRadius = outerCRadius * 0.75;
- outerCircle.addEllipse(center, outerCRadius, outerCRadius);
- innerCircle.addEllipse(center, innerCRadius, innerCRadius);
- if (index.data(static_cast<int>(Ring::Role::IsPresent)).value<bool>()) {
- painter->fillPath(outerCircle, Qt::white);
- painter->fillPath(innerCircle, RingTheme::green_);
- }
- font.setPointSize(fontSize_);
- QPen pen(painter->pen());
-
- if (index.column() != 0) {
- if (selected) {
- opt.state ^= QStyle::State_Selected;
- }
- QItemDelegate::paint(painter, opt, index);
- return;
- }
-
- painter->setPen(pen);
-
- QRect rectTexts(16 + rect.left() + dx_ + sizeImage_,
- rect.top(),
- rect.width(),
- rect.height() / 2);
-
- // The name is displayed at the avatar's right
- QVariant name = index.data(static_cast<int>(Ring::Role::Name));
- if (name.isValid())
- {
- pen.setColor(RingTheme::lightBlack_);
- painter->setPen(pen);
- font.setBold(true);
- painter->setFont(font);
- QFontMetrics fontMetrics(font);
- QString nameStr = fontMetrics.elidedText(name.toString(), Qt::ElideRight
- , rectTexts.width()- sizeImage_ - effectiveComBarSize_ - dx_);
- painter->drawText(rectTexts, Qt::AlignVCenter | Qt::AlignLeft, nameStr);
- }
-
- // Display the ID under the name
- QString idStr = index.data(static_cast<int>(Ring::Role::Number)).value<QString>();
- if (idStr != name.toString()){
- pen.setColor(RingTheme::grey_);
- painter->setPen(pen);
- font.setItalic(true);
- font.setBold(false);
- painter->setFont(font);
- QFontMetrics fontMetrics(font);
- if (!idStr.isNull()){
- idStr = fontMetrics.elidedText(idStr, Qt::ElideRight, rectTexts.width()- sizeImage_ - effectiveComBarSize_ - dx_);
- painter->drawText(QRect(16 + rect.left() + dx_ + sizeImage_,
- rect.top() + rect.height()/7,
- rect.width(),
- rect.height()/2),
- Qt::AlignBottom | Qt::AlignLeft, idStr);
-
- } else {
- qDebug() << "This is not a Person";
- }
- }
-
- // Finally, either last interaction date or call state is displayed
- QVariant state = index.data(static_cast<int>(Ring::Role::FormattedState));
- pen.setColor(RingTheme::grey_);
- painter->setPen(pen);
- font.setItalic(false);
- font.setBold(false);
- painter->setFont(font);
- rectTexts.moveTop(cellHeight_/2);
- if (state.isValid() && RecentModel::instance().getActiveCall(RecentModel::instance().peopleProxy()->mapToSource(index)))
- {
- painter->drawText(QRect(16 + rect.left() + dx_ + sizeImage_,
- rect.top() + rect.height()/2,
- rect.width(),
- rect.height()/2),
- Qt::AlignLeft | Qt::AlignVCenter, state.toString());
- }
- else
- {
- QVariant lastUsed = index.data(static_cast<int>(Ring::Role::FormattedLastUsed));
- if (lastUsed.isValid())
- {
- painter->drawText(QRect(16 + rect.left() + dx_ + sizeImage_,
- rect.top() + rect.height()/2,
- rect.width(),
- rect.height()/2),
- Qt::AlignLeft | Qt::AlignVCenter, lastUsed.toString());
- }
- }
-}
-
-QSize
-SmartListDelegate::sizeHint(const QStyleOptionViewItem& option
- , const QModelIndex& index
- ) const
-{
- QSize size = QItemDelegate::sizeHint(option, index);
- size.setHeight(cellHeight_);
- return size;
-}
diff --git a/smartlistmodel.cpp b/smartlistmodel.cpp
new file mode 100644
index 0000000..d767a03
--- /dev/null
+++ b/smartlistmodel.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * Copyright (C) 2017 by Savoir-faire Linux *
+ * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "smartlistmodel.h"
+
+// Qt
+#include <QDateTime>
+
+// LRC
+#include "globalinstances.h"
+#include "api/contactmodel.h"
+#include "api/conversationmodel.h"
+
+// Client
+#include "pixbufmanipulator.h"
+#include "messagemodel.h"
+#include "utils.h"
+
+SmartListModel::SmartListModel(const lrc::api::account::Info &acc, QObject *parent)
+ : QAbstractItemModel(parent),
+ acc_(acc)
+{
+}
+
+int SmartListModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid()) {
+ return acc_.conversationModel->allFilteredConversations().size();
+ }
+ return 0; // A valid QModelIndex returns 0 as no entry has sub-elements
+}
+
+int SmartListModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 1;
+}
+
+QVariant SmartListModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ const auto& item = acc_.conversationModel->filteredConversation(index.row());
+ if (item.participants.size() > 0) {
+ try {
+ switch (role) {
+ case Role::Picture:
+ case Qt::DecorationRole:
+ return GlobalInstances::pixmapManipulator().decorationRole(item, acc_);
+ case Role::DisplayName:
+ case Qt::DisplayRole:
+ {
+ auto& contact = acc_.contactModel->getContact(item.participants[0]);
+ return QVariant(QString::fromStdString(Utils::bestNameForContact(contact)));
+ }
+ case Role::DisplayID:
+ {
+ auto& contact = acc_.contactModel->getContact(item.participants[0]);
+ return QVariant(QString::fromStdString(Utils::bestIdForContact(contact)));
+ }
+ case Role::Presence:
+ {
+ auto& contact = acc_.contactModel->getContact(item.participants[0]);
+ return QVariant(contact.isPresent);
+ }
+ case Role::URI:
+ {
+ auto& contact = acc_.contactModel->getContact(item.participants[0]);
+ return QVariant(QString::fromStdString(contact.profileInfo.uri));
+ }
+ case Role::UnreadMessagesCount:
+ return QVariant(item.unreadMessages);
+ case Role::LastInteractionDate:
+ {
+ auto& date = item.interactions.at(item.lastMessageUid).timestamp;
+ return QVariant(QString::fromStdString(Utils::formatTimeString(date)));
+ }
+ case Role::LastInteraction:
+ return QVariant(QString::fromStdString(item.interactions.at(item.lastMessageUid).body));
+ case Role::ContactType:
+ {
+ auto& contact = acc_.contactModel->getContact(item.participants[0]);
+ return QVariant(Utils::toUnderlyingValue(contact.profileInfo.type));
+ }
+ case Role::UID:
+ return QVariant(QString::fromStdString(item.uid));
+ case Role::ContextMenuOpen:
+ return QVariant(isContextMenuOpen_);
+ }
+ } catch (...) {}
+ }
+ return QVariant();
+}
+
+QModelIndex SmartListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ if (column != 0) {
+ return QModelIndex();
+ }
+
+ if (row >= 0 && row < rowCount()) {
+ return createIndex(row, column);
+ }
+ return QModelIndex();
+}
+
+QModelIndex SmartListModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child);
+ return QModelIndex();
+}
+
+Qt::ItemFlags SmartListModel::flags(const QModelIndex &index) const
+{
+ auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+ auto type = Utils::toEnum<lrc::api::profile::Type>(data(index, Role::ContactType).value<int>());
+ auto displayName = data(index, Role::DisplayName).value<QString>();
+ auto uid = data(index, Role::UID).value<QString>();
+ if (!index.isValid()) {
+ return QAbstractItemModel::flags(index);
+ } else if ( type == lrc::api::profile::Type::TEMPORARY &&
+ uid.isEmpty()) {
+ flags &= ~(Qt::ItemIsSelectable);
+ }
+ return flags;
+}
diff --git a/smartlistmodel.h b/smartlistmodel.h
new file mode 100644
index 0000000..9071599
--- /dev/null
+++ b/smartlistmodel.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+* Copyright (C) 2017 by Savoir-faire Linux *
+* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
+* *
+* 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/>. *
+**************************************************************************/
+#pragma once
+
+// Qt include
+#include <QAbstractItemModel>
+
+// LRC
+#include "api/account.h"
+#include "api/conversation.h"
+#include "api/contact.h"
+
+#include "messagemodel.h"
+
+namespace lrc { namespace api { class ConversationModel; } }
+
+class SmartListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ using AccountInfo = lrc::api::account::Info;
+ using ConversationInfo = lrc::api::conversation::Info;
+ using ContactInfo = lrc::api::contact::Info;
+
+
+ enum Role {
+ DisplayName = Qt::UserRole + 1,
+ DisplayID,
+ Picture,
+ Presence,
+ URI,
+ UnreadMessagesCount,
+ LastInteractionDate,
+ LastInteraction,
+ ContactType,
+ UID,
+ ContextMenuOpen
+ };
+
+ explicit SmartListModel(const lrc::api::account::Info& acc, QObject *parent = 0);
+
+ // QAbstractItemModel
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ bool isContextMenuOpen_{false};
+
+private:
+ const AccountInfo& acc_;
+
+};
diff --git a/smartlistselectorbuttonnotifier.cpp b/smartlistselectorbuttonnotifier.cpp
new file mode 100644
index 0000000..a7b3764
--- /dev/null
+++ b/smartlistselectorbuttonnotifier.cpp
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "smartlistselectorbuttonnotifier.h"
+
+#include "lrcinstance.h"
+#include "ringthemeutils.h"
+
+#include "api/conversationmodel.h"
+
+#include <QPainter>
+
+SmartlistSelectorButtonNotifier::SmartlistSelectorButtonNotifier(QWidget *parent)
+ : QPushButton(parent)
+{
+}
+
+void SmartlistSelectorButtonNotifier::setTypeFilter(lrc::api::profile::Type filter)
+{
+ typeFilter_ = filter;
+}
+
+void
+SmartlistSelectorButtonNotifier::paintEvent(QPaintEvent *event)
+{
+ // nb: don't paint the 'button' here!
+ // QPushButton::paintEvent(event);
+ Q_UNUSED(event);
+
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ QFont font(painter.font());
+
+ int totalUnreadMessages = 0;
+
+ using namespace lrc::api::profile;
+ switch (typeFilter_) {
+ case Type::RING:
+ {
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto ringConversations = convModel->getFilteredConversations(Type::RING);
+ std::for_each(ringConversations.begin(), ringConversations.end(),
+ [&totalUnreadMessages, convModel](const auto& conversation) {
+ totalUnreadMessages += convModel->getNumberOfUnreadMessagesFor(conversation.uid);
+ });
+ break;
+ }
+ case Type::PENDING:
+ {
+ auto& accountInfo = LRCInstance::getCurrentAccountInfo();
+ totalUnreadMessages = accountInfo.contactModel->pendingRequestCount();
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (totalUnreadMessages) {
+ QString messageCountText = (totalUnreadMessages > 9) ? "9+" : QString::number(totalUnreadMessages);
+ qreal fontSize = messageCountText.count() > 1 ? 7 : 8;
+ font.setPointSize(fontSize);
+
+ QRect buttonRect(this->rect());
+
+ // ellipse
+ QPainterPath ellipse;
+ qreal radius = buttonRect.width() / 2;
+ ellipse.addRoundedRect(buttonRect, radius, radius);
+ painter.fillPath(ellipse, RingTheme::notificationRed_);
+
+ // text
+ painter.setPen(Qt::white);
+ painter.setOpacity(1);
+ painter.setFont(font);
+ buttonRect.setTop(buttonRect.top() - 2);
+ painter.drawText(buttonRect, Qt::AlignCenter, messageCountText);
+ }
+}
\ No newline at end of file
diff --git a/combar.h b/smartlistselectorbuttonnotifier.h
similarity index 68%
copy from combar.h
copy to smartlistselectorbuttonnotifier.h
index ca01889..3a928c3 100644
--- a/combar.h
+++ b/smartlistselectorbuttonnotifier.h
@@ -1,6 +1,6 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
- * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
+ * Copyright (C) 2018 by Savoir-faire Linux *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -15,26 +15,23 @@
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
-
#pragma once
-#include <QWidget>
+#include "api/profile.h"
+#include "smartlistselectorbuttonnotifier.h"
-namespace Ui {
-class ComBar;
-}
+#include <QPushButton>
-class ComBar : public QWidget
+class SmartlistSelectorButtonNotifier : public QPushButton
{
Q_OBJECT
+
public:
- explicit ComBar(QWidget* parent = 0);
- ~ComBar();
+ SmartlistSelectorButtonNotifier(QWidget *parent = 0);
+ void setTypeFilter(lrc::api::profile::Type filter);
-private:
- Ui::ComBar* ui;
+protected:
+ virtual void paintEvent(QPaintEvent *event);
-signals:
- void btnVideoClicked() const;
-
-};
+ lrc::api::profile::Type typeFilter_{ lrc::api::profile::Type::INVALID };
+};
\ No newline at end of file
diff --git a/smartlistview.cpp b/smartlistview.cpp
new file mode 100644
index 0000000..ae44423
--- /dev/null
+++ b/smartlistview.cpp
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
+ * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
+ * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
+ * *
+ * 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/>. *
+ **************************************************************************/
+
+#include "smartlistview.h"
+
+#include "invitebuttonswidget.h"
+#include "smartlistmodel.h"
+#include "utils.h"
+
+#include <QScrollBar>
+#include <QMouseEvent>
+#include <QDebug>
+
+#include <ciso646>
+
+SmartListView::SmartListView(QWidget *parent) :
+ QTreeView(parent)
+{
+ verticalScrollBar()->setEnabled(true);
+ setVerticalScrollMode(ScrollPerPixel);
+ verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 0px; }");
+ setDragEnabled(true);
+ setAcceptDrops(true);
+ setDropIndicatorShown(true);
+ setSelectionMode(QAbstractItemView::SingleSelection);
+ setMouseTracking(true);
+ installEventFilter(this);
+
+ QObject::connect(this, &QAbstractItemView::entered,
+ [this](const QModelIndex & index) {
+ auto type = Utils::toEnum<lrc::api::profile::Type>(
+ index.data(static_cast<int>(SmartListModel::Role::ContactType)).value<int>()
+ );
+ if (type == lrc::api::profile::Type::PENDING) {
+ auto widget = indexWidget(index);
+ if (!widget) {
+ InviteButtonsWidget* buttons = new InviteButtonsWidget();
+ setIndexWidget(index, buttons);
+
+ QObject::connect(buttons, &InviteButtonsWidget::btnAcceptInviteClicked, this,
+ [this, index]() {
+ hoveredRow_ = QModelIndex();
+ emit btnAcceptInviteClicked(index);
+ });
+ QObject::connect(buttons, &InviteButtonsWidget::btnIgnoreInviteClicked, this,
+ [this, index]() {
+ hoveredRow_ = QModelIndex();
+ emit btnIgnoreInviteClicked(index);
+ });
+ QObject::connect(buttons, &InviteButtonsWidget::btnBlockInviteClicked, this,
+ [this, index]() {
+ hoveredRow_ = QModelIndex();
+ emit btnBlockInviteClicked(index);
+ });
+ }
+ else {
+ widget->show();
+ }
+
+ if (hoveredRow_.isValid() && indexWidget(hoveredRow_)) {
+ indexWidget(hoveredRow_)->hide();
+ }
+
+ hoveredRow_ = index;
+ }
+ });
+}
+
+SmartListView::~SmartListView()
+{
+ reset();
+}
+
+void
+SmartListView::enterEvent(QEvent* event)
+{
+ Q_UNUSED(event);
+}
+
+void
+SmartListView::leaveEvent(QEvent* event)
+{
+ Q_UNUSED(event);
+ hoveredRow_ = QModelIndex();
+}
+
+void
+SmartListView::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::RightButton) {
+ emit customContextMenuRequested(event->pos());
+ }
+ else {
+ QTreeView::mousePressEvent(event);
+ }
+}
+
+bool
+SmartListView::eventFilter(QObject* watched, QEvent* event)
+{
+ auto index = this->indexAt(static_cast<QMouseEvent*>(event)->pos());
+ if (!index.isValid()) {
+ hoveredRow_ = QModelIndex();
+ }
+ if (qobject_cast<QScrollBar*>(watched) && event->type() == QEvent::Enter) {
+ hoveredRow_ = QModelIndex();
+ return true;
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+void
+SmartListView::hideButtonsWidgets()
+{
+ auto model = this->model();
+ if (!model) {
+ return;
+ }
+ for (int i = 0; i < model->rowCount(); ++i) {
+ auto index = model->index(i, 0);
+ if (index.isValid() && indexWidget(index)) {
+ qDebug() << "hide a ButtonsWidgets";
+ indexWidget(index)->setVisible(false);
+ }
+ }
+}
+
+void
+SmartListView::drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ if (index == hoveredRow_ && indexWidget(hoveredRow_)) {
+ indexWidget(index)->setVisible(true);
+ }
+ else if (indexWidget(index)) {
+ indexWidget(index)->setVisible(false);
+ }
+ QTreeView::drawRow(painter, option, index);
+}
\ No newline at end of file
diff --git a/smartlist.h b/smartlistview.h
similarity index 75%
rename from smartlist.h
rename to smartlistview.h
index 1dfa915..a7e6d89 100644
--- a/smartlist.h
+++ b/smartlistview.h
@@ -1,6 +1,7 @@
/***************************************************************************
* Copyright (C) 2015-2017 by Savoir-faire Linux *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -20,27 +21,29 @@
#include <QTreeView>
-class SmartListDelegate;
+class ConversationItemDelegate;
-class SmartList : public QTreeView
+class SmartListView : public QTreeView
{
Q_OBJECT
public:
- explicit SmartList(QWidget* parent = 0);
- ~SmartList();
- void setSmartListItemDelegate(SmartListDelegate* delegate);
+ explicit SmartListView(QWidget* parent = 0);
+ ~SmartListView();
protected:
void enterEvent(QEvent* event);
void leaveEvent(QEvent* event);
+ void mousePressEvent(QMouseEvent *event);
bool eventFilter(QObject* watched, QEvent* event);
void drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
private:
- SmartListDelegate* smartListDelegate_;
- QPersistentModelIndex hoveredRow_;
- void removeCombar();
+ void hideButtonsWidgets();
+ QModelIndex hoveredRow_;
-signals:
- void btnVideoClicked() const;
+signals:
+ void btnAcceptInviteClicked(const QModelIndex& index) const;
+ void btnBlockInviteClicked(const QModelIndex& index) const;
+ void btnIgnoreInviteClicked(const QModelIndex& index) const;
+
};
diff --git a/stylesheet.css b/stylesheet.css
index b5d7c35..285d674 100644
--- a/stylesheet.css
+++ b/stylesheet.css
@@ -26,6 +26,40 @@
background-color: #db3c30;
}
+QPushButton#buttonConversations, QPushButton#buttonInvites {
+ background-color: rgb(242, 242, 242);
+ border-style: solid;
+ border-width: 0px;
+ border-radius: 5px;
+ padding: 8px;
+ color: rgb(32, 32, 32);
+}
+
+QPushButton#buttonConversations:hover, QPushButton#buttonInvites:hover {
+ background-color: rgb(237, 237, 237);
+}
+
+QPushButton#buttonConversations:pressed, QPushButton#buttonInvites:pressed {
+ background-color: rgb(212, 212, 212);
+}
+
+QPushButton#btnAcceptInvite, QPushButton#btnIgnoreInvite, QPushButton#btnBlockInvite {
+ background-color: transparent;
+ border-style: solid;
+ border-width: 0px;
+ border-radius: 9px;
+ padding: 8px;
+ color: rgb(32, 32, 32);
+}
+
+QPushButton#btnAcceptInvite:hover, QPushButton#btnIgnoreInvite:hover, QPushButton#btnBlockInvite:hover {
+ background-color: rgb(212, 212, 212);
+}
+
+QPushButton#btnAcceptInvite:pressed, QPushButton#btnIgnoreInvite:pressed, QPushButton#btnBlockInvite:pressed {
+ background-color: rgb(187, 187, 187);
+}
+
QWidget#callInvitePage, QWidget#outboundCallPage{
background-color : rgb(77, 77, 77);
background-image : url(:/images/background-dark.png);
@@ -54,7 +88,7 @@
background: rgb(255, 255, 255);
}
-SmartList, ContactRequestListWidget{
+SmartListView {
background-color: white;
border: none;
}
@@ -106,14 +140,14 @@
background-color: transparent;
}
-SmartList::item:selected, QListView#accountView::item:selected, QListView#contactView::item:selected,
-QTreeView#contactRequestList::item:selected, QListView#BannedList::item:selected{
+SmartListView::item:selected, QListView#accountView::item:selected, QListView#contactView::item:selected,
+QListView#contactRequestList::item:selected, QListView#BannedList::item:selected {
background-color: rgba(220, 220, 220, 255);
border: none;
}
-SmartList::item:hover, QListView#accountView::item:hover, QListView#contactView::item:hover,
-QTreeView#contactRequestList::item:hover, QListView#BannedList::item:hover{
+SmartListView::item:hover, QListView#accountView::item:hover, QListView#contactView::item:hover,
+QListView#contactRequestList::item:hover, QListView#BannedList::item:hover {
background-color: rgba(242, 242, 242, 255);
}
@@ -371,6 +405,7 @@
border-style: solid;
border-width: 2px;
border-color: #414141;
+ border-bottom: transparent;
border-top: transparent;
border-left: transparent;
border-right: transparent;
@@ -378,10 +413,6 @@
padding: 2px;
}
-QComboBox:focus{
- border-color: #3AC0D2;
-}
-
QComboBox::down-arrow{
border-radius: 0px;
border-style: solid;
diff --git a/utils.cpp b/utils.cpp
index 03864d8..5923946 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -1,6 +1,7 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Copyright (C) 2015-2018 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -27,13 +28,18 @@
#include <shlwapi.h>
#endif
-
//Qt
#include <QObject>
#include <QErrorMessage>
#include <QPainter>
#include <QStackedWidget>
#include <QPropertyAnimation>
+#include <QApplication>
+
+#include "globalinstances.h"
+#include "pixbufmanipulator.h"
+
+#include "globalsystemtray.h"
bool
Utils::CreateStartupLink()
@@ -212,17 +218,161 @@
}
void
-Utils::slidePage(QStackedWidget* stack, QWidget* widget, bool toRight)
+Utils::setStackWidget(QStackedWidget* stack, QWidget* widget)
{
- if (stack->indexOf(widget) != -1 && stack->currentWidget() != widget){
- QPropertyAnimation* pageAnim = new QPropertyAnimation();
- int dir = (toRight ? -1 : 1);
+ if (stack->indexOf(widget) != -1 && stack->currentWidget() != widget) {
stack->setCurrentWidget(widget);
- pageAnim->setTargetObject(widget);
- pageAnim->setDuration(animDuration_);
- pageAnim->setStartValue(QPoint(widget->width() * dir, widget->y()));
- pageAnim->setEndValue(QPoint(widget->x(), widget->y()));
- pageAnim->setEasingCurve(QEasingCurve::OutQuad);
- pageAnim->start();
}
}
+
+void Utils::showSystemNotification(QWidget* widget, const QString & message, long delay)
+{
+ GlobalSystemTray::instance().showMessage("Ring", message);
+ QApplication::alert(widget, delay);
+}
+
+// new lrc helpers
+
+inline std::string
+removeEndlines(const std::string& str)
+{
+ std::string trimmed(str);
+ trimmed.erase(std::remove(trimmed.begin(), trimmed.end(), '\n'), trimmed.end());
+ trimmed.erase(std::remove(trimmed.begin(), trimmed.end(), '\r'), trimmed.end());
+ return trimmed;
+}
+
+std::string
+Utils::bestIdForConversation(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
+{
+ auto contact = model.owner.contactModel->getContact(conv.participants[0]);
+ if (!contact.registeredName.empty()) {
+ return removeEndlines(contact.registeredName);
+ }
+ return removeEndlines(contact.profileInfo.uri);
+}
+
+std::string
+Utils::bestIdForAccount(const lrc::api::account::Info& account)
+{
+ if (!account.registeredName.empty()) {
+ return removeEndlines(account.registeredName);
+ }
+ return removeEndlines(account.profileInfo.uri);
+}
+
+std::string
+Utils::bestNameForAccount(const lrc::api::account::Info& account)
+{
+ if (account.profileInfo.alias.empty()) {
+ return bestIdForAccount(account);
+ }
+ return account.profileInfo.alias;
+}
+
+std::string
+Utils::bestIdForContact(const lrc::api::contact::Info& contact)
+{
+ if (!contact.registeredName.empty()) {
+ return removeEndlines(contact.registeredName);
+ }
+ return removeEndlines(contact.profileInfo.uri);
+}
+
+std::string
+Utils::bestNameForContact(const lrc::api::contact::Info& contact)
+{
+ auto alias = removeEndlines(contact.profileInfo.alias);
+ if (alias.length() == 0) {
+ return bestIdForContact(contact);
+ }
+ return alias;
+}
+
+std::string
+Utils::bestNameForConversation(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
+{
+ auto contact = model.owner.contactModel->getContact(conv.participants[0]);
+ auto alias = removeEndlines(contact.profileInfo.alias);
+ if (alias.length() == 0) {
+ return bestIdForConversation(conv, model);
+ }
+ return alias;
+}
+
+lrc::api::profile::Type
+Utils::profileType(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
+{
+ try {
+ auto contact = model.owner.contactModel->getContact(conv.participants[0]);
+ return contact.profileInfo.type;
+ }
+ catch (...) {
+ return lrc::api::profile::Type::INVALID;
+ }
+}
+
+std::string
+Utils::formatTimeString(const std::time_t& timestamp)
+{
+ std::time_t now = std::time(nullptr);
+ char interactionDay[64];
+ char nowDay[64];
+ std::strftime(interactionDay, sizeof(interactionDay), "%D", std::localtime(×tamp));
+ std::strftime(nowDay, sizeof(nowDay), "%D", std::localtime(&now));
+ if (std::string(interactionDay) == std::string(nowDay)) {
+ char interactionTime[64];
+ std::strftime(interactionTime, sizeof(interactionTime), "%R", std::localtime(×tamp));
+ return interactionTime;
+ }
+ else {
+ return interactionDay;
+ }
+}
+
+lrc::api::ConversationModel::ConversationQueue::const_iterator
+Utils::getConversationFromUid(const std::string& uid, const lrc::api::ConversationModel& model) {
+ return std::find_if(model.allFilteredConversations().begin(), model.allFilteredConversations().end(),
+ [&](const lrc::api::conversation::Info& conv) {
+ return uid == conv.uid;
+ });
+}
+
+lrc::api::ConversationModel::ConversationQueue::const_iterator
+Utils::getConversationFromUri(const std::string& uri, const lrc::api::ConversationModel& model) {
+ return std::find_if(model.allFilteredConversations().begin(), model.allFilteredConversations().end(),
+ [&](const lrc::api::conversation::Info& conv) {
+ return uri == conv.participants[0];
+ });
+}
+
+bool
+Utils::isInteractionGenerated(const lrc::api::interaction::Type& type)
+{
+ return type == lrc::api::interaction::Type::CALL ||
+ type == lrc::api::interaction::Type::CONTACT;
+}
+
+bool
+Utils::isContactValid(const std::string& contactUid, const lrc::api::ConversationModel& model)
+{
+ auto contact = model.owner.contactModel->getContact(contactUid);
+ return (contact.profileInfo.type == lrc::api::profile::Type::PENDING ||
+ contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY ||
+ contact.profileInfo.type == lrc::api::profile::Type::RING ||
+ contact.profileInfo.type == lrc::api::profile::Type::SIP) &&
+ !contact.profileInfo.uri.empty();
+}
+
+QImage
+Utils::conversationPhoto(const std::string & convUid, const lrc::api::account::Info& accountInfo)
+{
+ auto& convModel = accountInfo.conversationModel;
+ auto conversation = Utils::getConversationFromUid(convUid, *convModel);
+ if (conversation == (*convModel).allFilteredConversations().end()) {
+ return QImage();
+ }
+
+ QVariant var = GlobalInstances::pixmapManipulator().decorationRole(*conversation, accountInfo);
+ return var.value<QImage>();
+}
diff --git a/utils.h b/utils.h
index cd21780..f304b31 100644
--- a/utils.h
+++ b/utils.h
@@ -1,6 +1,7 @@
/***************************************************************************
- * Copyright (C) 2015-2017 by Savoir-faire Linux *
+ * Copyright (C) 2015-2018 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -24,6 +25,9 @@
#ifdef Q_OS_WIN
#include <windows.h>
#include <ciso646>
+#undef OUT
+#undef IN
+#undef ERROR
#else //LINUX
#define LPCWSTR char*
#endif
@@ -33,6 +37,11 @@
#include <QImage>
#include <QStackedWidget>
+#include "api/conversationmodel.h"
+#include "api/account.h"
+#include "api/contactmodel.h"
+#include "api/contact.h"
+
namespace Utils
{
constexpr int animDuration_ = 200; // animation duration for sliding page in ms
@@ -47,6 +56,50 @@
QString GetCurrentUserName();
void InvokeMailto(const QString& subject, const QString& body, const QString& attachement = QString());
QImage getCirclePhoto(const QImage original, int sizePhoto);
- void slidePage(QStackedWidget *stack, QWidget *widget, bool toRight = false);
-}
+ void setStackWidget(QStackedWidget *stack, QWidget *widget);
+ void showSystemNotification(QWidget* widget, const QString& message, long delay = 5000);
+ std::string bestIdForConversation(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model);
+ std::string bestIdForAccount(const lrc::api::account::Info & account);
+ std::string bestNameForAccount(const lrc::api::account::Info & account);
+ std::string bestIdForContact(const lrc::api::contact::Info & contact);
+ std::string bestNameForContact(const lrc::api::contact::Info & contact);
+ std::string bestNameForConversation(const lrc::api::conversation::Info & conv, const lrc::api::ConversationModel & model);
+ lrc::api::profile::Type profileType(const lrc::api::conversation::Info & conv, const lrc::api::ConversationModel & model);
+ std::string formatTimeString(const std::time_t& timestamp);
+ lrc::api::ConversationModel::ConversationQueue::const_iterator getConversationFromUid(const std::string& uid, const lrc::api::ConversationModel& model);
+ lrc::api::ConversationModel::ConversationQueue::const_iterator getConversationFromUri(const std::string& uri, const lrc::api::ConversationModel& model);
+ bool isInteractionGenerated(const lrc::api::interaction::Type& interaction);
+ bool isContactValid(const std::string& contactUid, const lrc::api::ConversationModel& model);
+ QImage conversationPhoto(const std::string& convUid, const lrc::api::account::Info& accountInfo);
+
+ // helpers
+ template<typename E>
+ constexpr inline typename std::enable_if< std::is_enum<E>::value,
+ typename std::underlying_type<E>::type
+ >::type
+ toUnderlyingValue(E e) noexcept
+ {
+ return static_cast<typename std::underlying_type<E>::type >(e);
+ }
+
+ template<typename E, typename T>
+ constexpr inline typename std::enable_if< std::is_enum<E>::value && std::is_integral<T>::value,
+ E
+ >::type
+ toEnum(T value) noexcept
+ {
+ return static_cast<E>(value);
+ }
+
+ template<typename T>
+ ptrdiff_t
+ indexInVector(const std::vector<T>& vec, const T& item)
+ {
+ auto it = std::find(vec.begin(), vec.end(), item);
+ if (it == vec.end()) {
+ return -1;
+ }
+ return std::distance(vec.begin(), it);
+ }
+}
diff --git a/videooverlay.cpp b/videooverlay.cpp
index 572fbcb..f0706fe 100644
--- a/videooverlay.cpp
+++ b/videooverlay.cpp
@@ -1,6 +1,7 @@
/***************************************************************************
* Copyright (C) 2015-2017 by Savoir-faire Linux *
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -28,7 +29,8 @@
#include "person.h"
#include "account.h"
-
+#include "lrcinstance.h"
+#include "utils.h"
VideoOverlay::VideoOverlay(QWidget* parent) :
QWidget(parent),
@@ -38,70 +40,15 @@
{
ui->setupUi(this);
+ ui->bottomButtons->setMouseTracking(true);
+
ui->chatButton->setCheckable(true);
- actionModel_ = CallModel::instance().userActionModel();
setAttribute(Qt::WA_NoSystemBackground);
ui->noMicButton->setCheckable(true);
- connect(actionModel_,&UserActionModel::dataChanged, [=](const QModelIndex& tl, const QModelIndex& br) {
- const int first(tl.row()),last(br.row());
- for(int i = first; i <= last;i++) {
- const QModelIndex& idx = actionModel_->index(i,0);
- switch (idx.data(UserActionModel::Role::ACTION).value<UserActionModel::Action>()) {
- case UserActionModel::Action::MUTE_AUDIO:
- ui->noMicButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
- ui->noMicButton->setEnabled(idx.flags() & Qt::ItemIsEnabled);
- break;
- case UserActionModel::Action::MUTE_VIDEO:
- ui->noVideoButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
- ui->noVideoButton->setEnabled(idx.flags() & Qt::ItemIsEnabled);
- break;
- case UserActionModel::Action::HOLD:
- ui->holdButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
- ui->holdButton->setEnabled(idx.flags() & Qt::ItemIsEnabled);
- ui->onHoldLabel->setVisible(idx.data(Qt::CheckStateRole).value<bool>());
- break;
- case UserActionModel::Action::RECORD:
- ui->recButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
- ui->recButton->setEnabled(idx.flags() & Qt::ItemIsEnabled);
- default:
- break;
- }
- }
- });
-
- connect(CallModel::instance().selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) {
- Q_UNUSED(previous)
- Call* c = current.data(static_cast<int>(Call::Role::Object)).value<Call*>();
- if (c) {
- if (c->hasParentCall()) {
- ui->holdButton->hide();
- ui->transferButton->hide();
- ui->addPersonButton->hide();
- ui->chatButton->hide();
-
- ui->joinButton->show();
- } else {
- ui->holdButton->show();
- ui->transferButton->show();
- ui->addPersonButton->show();
- ui->chatButton->show();
-
- ui->joinButton->hide();
- }
-
- if (auto* contactMethod = c->peerContactMethod())
- ui->addToContactButton->setVisible(not contactMethod->contact()
- || contactMethod->contact()->isPlaceHolder());
-
- if (auto* acc = c->account())
- ui->transferButton->setVisible(acc->isIp2ip());
- else
- ui->transferButton->setVisible(false); // Hide transferButton as fallback so it is not displayed for Ring calls
- }
- });
+ ui->onHoldLabel->setVisible(false);
transferDialog_->setAttribute(Qt::WA_TranslucentBackground);
connect(transferDialog_, &CallUtilsDialog::isVisible, [this] (bool visible) {
@@ -143,9 +90,28 @@
}
void
+VideoOverlay::setVideoMuteVisibility(bool visible)
+{
+ ui->noVideoButton->setVisible(visible);
+}
+
+bool
+VideoOverlay::shouldShowOverlay()
+{
+ return ui->bottomButtons->underMouse() || ui->topInfoBar->underMouse();
+}
+
+void
VideoOverlay::on_hangupButton_clicked()
{
- actionModel_->execute(UserActionModel::Action::HANGUP);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid,
+ *LRCInstance::getCurrentConversationModel());
+ auto& callId = conversation->callId;
+ auto callModel = LRCInstance::getCurrentCallModel();
+ if (callModel->hasCall(callId)) {
+ callModel->hangUp(callId);
+ }
ui->chatButton->setChecked(false);
}
@@ -182,25 +148,52 @@
void
VideoOverlay::on_holdButton_clicked()
{
- actionModel_->execute(UserActionModel::Action::HOLD);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid,
+ *LRCInstance::getCurrentConversationModel());
+ auto& callId = conversation->callId;
+ auto callModel = LRCInstance::getCurrentCallModel();
+ if (callModel->hasCall(callId)) {
+ auto onHold = callModel->getCall(callId).status == lrc::api::call::Status::PAUSED;
+ ui->holdButton->setChecked(!onHold);
+ ui->onHoldLabel->setVisible(!onHold);
+ callModel->togglePause(callId);
+ }
}
void
VideoOverlay::on_noMicButton_clicked()
{
- actionModel_->execute(UserActionModel::Action::MUTE_AUDIO);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid,
+ *LRCInstance::getCurrentConversationModel());
+ auto& callId = conversation->callId;
+ auto callModel = LRCInstance::getCurrentCallModel();
+ if (callModel->hasCall(callId)) {
+ ui->noMicButton->setChecked(callModel->getCall(callId).audioMuted);
+ callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::AUDIO);
+ }
}
void
VideoOverlay::on_noVideoButton_clicked()
{
- actionModel_->execute(UserActionModel::Action::MUTE_VIDEO);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid,
+ *LRCInstance::getCurrentConversationModel());
+ auto& callId = conversation->callId;
+ auto callModel = LRCInstance::getCurrentCallModel();
+ if (callModel->hasCall(callId)) {
+ ui->noVideoButton->setChecked(callModel->getCall(callId).videoMuted);
+ callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::VIDEO);
+ }
}
void VideoOverlay::on_joinButton_clicked()
{
- CallModel::instance().selectedCall()->joinToParent();
+ // TODO:(newlrc) conferences
+ //CallModel::instance().selectedCall()->joinToParent();
}
void
@@ -215,21 +208,16 @@
}
void
-VideoOverlay::on_addToContactButton_clicked()
-{
- QPoint globalPos = mapToGlobal(ui->addToContactButton->pos());
- if (auto contactMethod = CallModel::instance().selectedCall()->peerContactMethod()) {
- ContactPicker contactPicker(contactMethod);
- contactPicker.move(globalPos.x(),
- globalPos.y() + ui->addToContactButton->height());
- contactPicker.exec();
- }
-}
-
-void
VideoOverlay::on_recButton_clicked()
{
- actionModel_->execute(UserActionModel::Action::RECORD);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid,
+ *LRCInstance::getCurrentConversationModel());
+ auto& callId = conversation->callId;
+ auto callModel = LRCInstance::getCurrentCallModel();
+ if (callModel->hasCall(callId)) {
+ callModel->toggleAudioRecord(callId);
+ }
}
void VideoOverlay::on_videoCfgBtn_clicked()
diff --git a/videooverlay.h b/videooverlay.h
index 002a9aa..bf49b1f 100644
--- a/videooverlay.h
+++ b/videooverlay.h
@@ -43,6 +43,8 @@
void setTime(const QString& time);
inline bool isDialogVisible(){ return dialogVisible_; };
void toggleContextButtons(bool visible);
+ void setVideoMuteVisibility(bool visible);
+ bool shouldShowOverlay();
//UI SLOTS
private slots:
@@ -55,13 +57,11 @@
void on_noMicButton_clicked();
void on_noVideoButton_clicked();
void on_qualityButton_clicked();
- void on_addToContactButton_clicked();
void on_recButton_clicked();
void on_videoCfgBtn_clicked();
private:
Ui::VideoOverlay* ui;
- UserActionModel* actionModel_;
CallUtilsDialog* transferDialog_;
QualityDialog* qualityDialog_;
bool dialogVisible_ = false;
diff --git a/videooverlay.ui b/videooverlay.ui
index 9697ad0..956d5bb 100644
--- a/videooverlay.ui
+++ b/videooverlay.ui
@@ -23,8 +23,523 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,1,0" columnstretch="0,0,2,0,0">
- <item row="1" column="2">
+ <item row="2" column="0" colspan="5">
+ <widget class="QWidget" name="bottomButtons" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="hangupButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Hangup</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_close_white_24dp.png</normaloff>:/images/icons/ic_close_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="holdButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Hold / Unhold</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_pause_white_24dp.png</normaloff>:/images/icons/ic_pause_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="chatButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Chat</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_chat_white_24dp.png</normaloff>:/images/icons/ic_chat_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addPersonButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Add person to call</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_person_add_white_24dp.png</normaloff>:/images/icons/ic_person_add_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="transferButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Transfer call</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_call_transfer_white_24px.png</normaloff>:/images/icons/ic_call_transfer_white_24px.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="noMicButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Mute Mic</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_mic_off_white_24dp.png</normaloff>:/images/icons/ic_mic_off_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="noVideoButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Mute Video</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_videocam_off_white_24dp.png</normaloff>:/images/icons/ic_videocam_off_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="recButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Record call</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_voicemail_white_24dp_2x.png</normaloff>:/images/icons/ic_voicemail_white_24dp_2x.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="qualityButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Quality</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_high_quality_white_24dp.png</normaloff>:/images/icons/ic_high_quality_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="joinButton">
+ <property name="minimumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>36</width>
+ <height>36</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Join Calls</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_group_add_white_24dp.png</normaloff>:/images/icons/ic_group_add_white_24dp.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QWidget" name="topInfoBar" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLabel" name="nameLabel">
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>143</red>
+ <green>146</green>
+ <blue>147</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="toolTip">
+ <string>Name label</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="timerLabel">
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>143</red>
+ <green>146</green>
+ <blue>147</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="toolTip">
+ <string>Time elapsed</string>
+ </property>
+ <property name="text">
+ <string>00:00</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="videoCfgBtn">
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Configuration</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="ressources.qrc">
+ <normaloff>:/images/icons/ic_settings_white_48dp_2x.png</normaloff>:/images/icons/ic_settings_white_48dp_2x.png</iconset>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="5">
<layout class="QHBoxLayout" name="horizontalLayout_5">
+ <property name="spacing">
+ <number>7</number>
+ </property>
<item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
<widget class="QLabel" name="onHoldLabel">
<property name="minimumSize">
@@ -54,546 +569,6 @@
</item>
</layout>
</item>
- <item row="2" column="0" colspan="5">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="hangupButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Hangup</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_close_white_24dp.png</normaloff>:/images/icons/ic_close_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="holdButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Hold / Unhold</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_pause_white_24dp.png</normaloff>:/images/icons/ic_pause_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="chatButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Chat</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_chat_white_24dp.png</normaloff>:/images/icons/ic_chat_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addPersonButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Add person to call</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_person_add_white_24dp.png</normaloff>:/images/icons/ic_person_add_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="transferButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Transfer call</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_call_transfer_white_24px.png</normaloff>:/images/icons/ic_call_transfer_white_24px.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="noMicButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Mute Mic</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_mic_off_white_24dp.png</normaloff>:/images/icons/ic_mic_off_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="noVideoButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Mute Video</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_videocam_off_white_24dp.png</normaloff>:/images/icons/ic_videocam_off_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="recButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Record call</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_voicemail_white_24dp_2x.png</normaloff>:/images/icons/ic_voicemail_white_24dp_2x.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="qualityButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Quality</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_high_quality_white_24dp.png</normaloff>:/images/icons/ic_high_quality_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="joinButton">
- <property name="minimumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>36</width>
- <height>36</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Join Calls</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_group_add_white_24dp.png</normaloff>:/images/icons/ic_group_add_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="0" column="2">
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <item>
- <widget class="QLabel" name="nameLabel">
- <property name="palette">
- <palette>
- <active>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </brush>
- </colorrole>
- </active>
- <inactive>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </brush>
- </colorrole>
- </inactive>
- <disabled>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>143</red>
- <green>146</green>
- <blue>147</blue>
- </color>
- </brush>
- </colorrole>
- </disabled>
- </palette>
- </property>
- <property name="toolTip">
- <string>Name label</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addToContactButton">
- <property name="minimumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Add to contact</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_person_add_white_24dp.png</normaloff>:/images/icons/ic_person_add_white_24dp.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>18</width>
- <height>18</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="timerLabel">
- <property name="palette">
- <palette>
- <active>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </brush>
- </colorrole>
- </active>
- <inactive>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </brush>
- </colorrole>
- </inactive>
- <disabled>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>143</red>
- <green>146</green>
- <blue>147</blue>
- </color>
- </brush>
- </colorrole>
- </disabled>
- </palette>
- </property>
- <property name="toolTip">
- <string>Time elapsed</string>
- </property>
- <property name="text">
- <string>00:00</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="videoCfgBtn">
- <property name="minimumSize">
- <size>
- <width>30</width>
- <height>30</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Configuration</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="ressources.qrc">
- <normaloff>:/images/icons/ic_settings_white_48dp_2x.png</normaloff>:/images/icons/ic_settings_white_48dp_2x.png</iconset>
- </property>
- </widget>
- </item>
- </layout>
- </item>
</layout>
</widget>
<resources>
diff --git a/videoview.cpp b/videoview.cpp
index b88f82e..5a9c70a 100644
--- a/videoview.cpp
+++ b/videoview.cpp
@@ -19,6 +19,9 @@
#include "videoview.h"
#include "ui_videoview.h"
+#include "utils.h"
+#include "lrcinstance.h"
+
#include "video/devicemodel.h"
#include "video/sourcemodel.h"
#include "recentmodel.h"
@@ -46,7 +49,7 @@
connect(&CallModel::instance(), SIGNAL(callStateChanged(Call*, Call::State)),
this, SLOT(callStateChanged(Call*, Call::State)));
-
+
overlay_ = new VideoOverlay(this);
auto effect = new QGraphicsOpacityEffect(overlay_);
effect->setOpacity(maxOverlayOpacity_);
@@ -58,7 +61,7 @@
fadeAnim_->setStartValue(effect->opacity());
fadeAnim_->setEndValue(0);
fadeAnim_->setEasingCurve(QEasingCurve::OutQuad);
-
+
// Setup the timer to start the fade when the mouse stops moving
this->setMouseTracking(true);
overlay_->setMouseTracking(true);
@@ -145,8 +148,9 @@
void
VideoView::fadeOverlayOut()
{
- if (not overlay_->isDialogVisible())
+ if (!overlay_->isDialogVisible() && !overlay_->shouldShowOverlay()) {
fadeAnim_->start(QAbstractAnimation::KeepWhenStopped);
+ }
}
void
@@ -192,8 +196,19 @@
VideoView::dropEvent(QDropEvent* event)
{
auto urls = event->mimeData()->urls();
- if (auto call = CallModel::instance().selectedCall()) {
- if (auto outVideo = call->firstMedia<media::Video>(media::Media::Direction::OUT)) {
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid, *convModel);
+ auto callList = CallModel::instance().getActiveCalls();
+ Call* thisCall = nullptr;
+ for (auto call : callList) {
+ if (call->historyId() == QString::fromStdString(conversation->callId)) {
+ thisCall = call;
+ break;
+ }
+ }
+ if (thisCall) {
+ if (auto outVideo = thisCall->firstMedia<media::Video>(media::Media::Direction::OUT)) {
outVideo->sourceModel()->setFile(urls.at(0));
}
}
@@ -225,8 +240,19 @@
media::Video* outVideo = nullptr;
int activeIndex = -1;
- if (auto call = CallModel::instance().selectedCall()) {
- outVideo = call->firstMedia<media::Video>(media::Media::Direction::OUT);
+ auto selectedConvUid = LRCInstance::getSelectedConvUid();
+ auto convModel = LRCInstance::getCurrentConversationModel();
+ auto conversation = Utils::getConversationFromUid(selectedConvUid, *convModel);
+ auto callList = CallModel::instance().getActiveCalls();
+ Call* thisCall = nullptr;
+ for (auto call : callList) {
+ if (call->historyId() == QString::fromStdString(conversation->callId)) {
+ thisCall = call;
+ break;
+ }
+ }
+ if (thisCall) {
+ outVideo = thisCall->firstMedia<media::Video>(media::Media::Direction::OUT);
if (outVideo)
activeIndex = outVideo->sourceModel()->activeIndex();
}
@@ -316,6 +342,26 @@
}
void
+VideoView::pushRenderer(const std::string& callUid) {
+ auto callModel = LRCInstance::getCurrentCallModel();
+
+ QObject::disconnect(videoStartedConnection_);
+ if (!callModel->hasCall(callUid)) {
+ return;
+ }
+
+ auto call = callModel->getCall(callUid);
+
+ videoStartedConnection_ = QObject::connect(callModel, &lrc::api::NewCallModel::remotePreviewStarted,
+ [this](const std::string& callId, Video::Renderer* renderer) {
+ Q_UNUSED(callId);
+ slotVideoStarted(renderer);
+ this->overlay_->setVideoMuteVisibility(LRCInstance::getCurrentCallModel()->getCall(callId).isAudioOnly);
+ });
+ ui->videoWidget->setPreviewDisplay(call.type != lrc::api::call::Type::CONFERENCE);
+}
+
+void
VideoView::slotVideoStarted(Video::Renderer* renderer) {
ui->videoWidget->show();
ui->videoWidget->setDistantRenderer(renderer);
@@ -357,7 +403,7 @@
} else {
fadeTimer_.start(startfadeOverlayTime_);
}
-
+
QRect& previewRect = ui->videoWidget->getPreviewRect();
if (draggingPreview_) {
if (previewRect.left() > 0
diff --git a/videoview.h b/videoview.h
index 159c373..41f02f0 100644
--- a/videoview.h
+++ b/videoview.h
@@ -37,6 +37,7 @@
explicit VideoView(QWidget* parent = 0);
~VideoView();
void pushRenderer(Call* call);
+ void pushRenderer(const std::string& callUid);
protected:
void resizeEvent(QResizeEvent* event);
@@ -80,7 +81,7 @@
constexpr static int startfadeOverlayTime_ = 2000; //msec
// TODO: fix when changing Qt version
- // Full(1.0) opacity bug affecting many Qt version (macOS + win10)
+ // Full(1.0) opacity bug affecting many Qt versions (macOS + win10)
// causing the render to take a buggy code path which can be avoided
// by using opacity values other than precisely 1.0.
// https://bugreports.qt.io/browse/QTBUG-65981
diff --git a/wizarddialog.cpp b/wizarddialog.cpp
index 7fedb37..c315334 100644
--- a/wizarddialog.cpp
+++ b/wizarddialog.cpp
@@ -3,6 +3,7 @@
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* *
* 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 *
@@ -35,7 +36,7 @@
const QString DEFAULT_RING_ACCT_ALIAS = QObject::tr("Ring account", "Default alias for new Ring account");
-WizardDialog::WizardDialog(WizardMode wizardMode, Account* toBeMigrated, QWidget* parent) :
+WizardDialog::WizardDialog(WizardMode wizardMode, AccountInfo* toBeMigrated, QWidget* parent) :
QDialog(parent),
ui(new Ui::WizardDialog),
account_(toBeMigrated),
@@ -61,9 +62,9 @@
movie_->start();
if (wizardMode_ == MIGRATION) {
- Utils::slidePage(ui->stackedWidget, ui->profilePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->profilePage);
ui->usernameEdit->setEnabled(false);
- ui->usernameEdit->setText(toBeMigrated->displayName());
+ ui->usernameEdit->setText(QString::fromStdString(toBeMigrated->profileInfo.alias));
ui->previousButton->hide();
ui->photoBooth->hide();
ui->pinEdit->hide();
@@ -126,58 +127,10 @@
ui->pinEdit->clear();
}
- ui->navBarWidget->hide();
- Utils::slidePage(ui->stackedWidget, ui->spinnerPage);
- repaint();
Utils::CreateStartupLink();
}
void
-WizardDialog::endSetup(Account::RegistrationState state)
-{
-#pragma push_macro("ERROR")
-#undef ERROR
- switch (state) {
- case Account::RegistrationState::UNREGISTERED:
- case Account::RegistrationState::READY:
- if (ui->signUpCheckbox->isChecked()) { // If the user wants to register its name on the blockchain
- bool regSuccess = account_->registerName(ui->passwordEdit->text(), ui->usernameEdit->text());
- ui->usernameEdit->clear();
- if (!regSuccess) {
- usernameFailedRegistration();
- } else {
- connect(account_, SIGNAL(nameRegistrationEnded(NameDirectory::RegisterNameStatus,QString)),
- this, SLOT(handle_nameRegistrationEnded(NameDirectory::RegisterNameStatus,QString)));
- ui->progressLabel->setText(tr("Registering your public username, it may take a few minutes..."));
- }
- } else {
- account_->performAction(Account::EditAction::RELOAD);
- accept();
- }
-
- { //avoid scope crossing init
- auto profile = ProfileModel::instance().selectedProfile();
- if (profile && AccountModel::instance().size() == 1) {
- profile->setAccounts({account_});
- profile->save();
- }
- }
- break;
- case Account::RegistrationState::ERROR:
- ui->spinnerLabel->hide();
- ui->navBarWidget->show();
- ui->nextButton->hide();
- ui->progressLabel->setText(tr("An error has occured during your account creation"));
- AccountModel::instance().remove(account_);
- break;
- case Account::RegistrationState::TRYING:
- case Account::RegistrationState::COUNT__:
- break;
- }
-#pragma pop_macro("ERROR")
-}
-
-void
WizardDialog::closeEvent(QCloseEvent* event)
{
Q_UNUSED(event);
@@ -189,12 +142,6 @@
}
void
-WizardDialog::usernameFailedRegistration()
-{
- QMessageBox::warning(this, "Username not registered", "Your account has been created, but we could not register your username. Try again from the settings menu.");
-}
-
-void
WizardDialog::on_photoTaken(QString fileName)
{
auto image = QImage(fileName);
@@ -210,7 +157,7 @@
{
ui->navBarWidget->show();
ui->nextButton->hide();
- Utils::slidePage(ui->stackedWidget, ui->linkMethodPage);
+ Utils::setStackWidget(ui->stackedWidget, ui->linkMethodPage);
}
void
@@ -225,11 +172,11 @@
{
if (existingAccount) { // If user want to add a device
ui->accountLabel->setText(tr("Add a device"));
- Utils::slidePage(ui->stackedWidget, ui->explanationPage);
+ Utils::setStackWidget(ui->stackedWidget, ui->explanationPage);
ui->photoBooth->hide();
} else { // If user want to create a new account
ui->accountLabel->setText(tr("Create your account"));
- Utils::slidePage(ui->stackedWidget, ui->profilePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->profilePage);
ui->photoBooth->startBooth();
ui->photoBooth->show();
}
@@ -249,9 +196,11 @@
WizardDialog::on_nextButton_clicked()
{
const QWidget* curWidget = ui->stackedWidget->currentWidget();
-
+ if (curWidget == ui->profilePage) {
+ ui->photoBooth->stopBooth();
+ }
if (curWidget == ui->profilePage || curWidget == ui->explanationPage) {
- Utils::slidePage(ui->stackedWidget, ui->accountPage);
+ Utils::setStackWidget(ui->stackedWidget, ui->accountPage);
} else if (curWidget == ui->accountPage) {
processWizardInformations();
} else if (curWidget == ui->fileImportPage) {
@@ -266,17 +215,21 @@
if (curWidget == ui->profilePage) {
ui->navBarWidget->hide();
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
} else if (curWidget == ui->explanationPage || curWidget == ui->fileImportPage) {
ui->navBarWidget->show();
ui->nextButton->hide();
- Utils::slidePage(ui->stackedWidget, ui->linkMethodPage);
+ Utils::setStackWidget(ui->stackedWidget, ui->linkMethodPage);
} else if (curWidget == ui->accountPage) {
- if (ui->pinEdit->isVisible()) // If we are adding a device
- Utils::slidePage(ui->stackedWidget, ui->explanationPage);
- else // If we are creating a new account
- Utils::slidePage(ui->stackedWidget, ui->profilePage);
+ if (ui->pinEdit->isVisible()) {
+ // If we are adding a device
+ Utils::setStackWidget(ui->stackedWidget, ui->explanationPage);
+ } else {
+ ui->photoBooth->startBooth();
+ ui->photoBooth->show();
+ Utils::setStackWidget(ui->stackedWidget, ui->profilePage);
+ }
ui->passwordEdit->setStyleSheet("border-color: rgb(0, 192, 212);");
ui->confirmPasswordEdit->setStyleSheet("border-color: rgb(0, 192, 212);");
@@ -285,11 +238,11 @@
} else if (curWidget == ui->linkMethodPage) {
ui->navBarWidget->hide();
ui->nextButton->show();
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
} else if (curWidget == ui->spinnerPage) {
ui->nextButton->show();
ui->navBarWidget->hide();
- Utils::slidePage(ui->stackedWidget, ui->welcomePage);
+ Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
}
}
@@ -354,14 +307,8 @@
void
WizardDialog::handle_nameRegistrationEnded(NameDirectory::RegisterNameStatus status, const QString& name)
{
- Q_UNUSED(name)
-
- disconnect(account_, SIGNAL(nameRegistrationEnded(NameDirectory::RegisterNameStatus,QString)),
- this, SLOT(handle_nameRegistrationEnded(NameDirectory::RegisterNameStatus,QString)));
- if(status != NameDirectory::RegisterNameStatus::SUCCESS) {
- usernameFailedRegistration();
- }
- account_->performAction(Account::EditAction::RELOAD);
+ Q_UNUSED(name);
+ Q_UNUSED(status);
accept();
}
@@ -417,35 +364,30 @@
const QString &pin,
const QString &archivePath)
{
- QString alias = (displayName.isEmpty() || displayName.isNull()) ? DEFAULT_RING_ACCT_ALIAS :
- displayName;
- // set display name
- account_ = AccountModel::instance().add(alias, Account::Protocol::RING);
- account_->setDisplayName(alias);
+ QtConcurrent::run(
+ [=] {
+ LRCInstance::accountModel().createNewAccount(
+ lrc::api::profile::Type::RING,
+ displayName.toStdString(),
+ archivePath.toStdString(),
+ password.toStdString(),
+ pin.toStdString()
+ );
+ });
- // archive properties
- account_->setArchivePassword(password);
- // import from DHT
- if (!pin.isEmpty() && !pin.isNull())
- account_->setArchivePin(pin);
- // import from file
- if (!archivePath.isEmpty() && !archivePath.isNull())
- account_->setArchivePath(archivePath);
+ connect(&LRCInstance::accountModel(),
+ &lrc::api::NewAccountModel::accountAdded,
+ [this](const std::string& accountId) {
+ //set default ringtone
+ auto confProps = LRCInstance::accountModel().getAccountConfig(accountId);
+ confProps.Ringtone.ringtonePath = Utils::GetRingtonePath().toStdString();
+ LRCInstance::accountModel().setAccountConfig(accountId, confProps);
+ accept();
+ });
- // set default UPNP behavior
- account_->setUpnpEnabled(true);
-
- //set default ringtone
- account_->setRingtonePath(Utils::GetRingtonePath());
-
- connect(account_, &Account::stateChanged, this, &WizardDialog::endSetup);
-
- account_->performAction(Account::EditAction::SAVE);
- auto profile = ProfileModel::instance().selectedProfile();
- if (profile && AccountModel::instance().size() == 1) {
- profile->person()->setFormattedName(alias);
- }
-
+ ui->navBarWidget->hide();
+ Utils::setStackWidget(ui->stackedWidget, ui->spinnerPage);
+ repaint();
}
void
@@ -461,6 +403,6 @@
ui->navBarWidget->show();
ui->nextButton->show();
wizardMode_ = IMPORT;
- Utils::slidePage(ui->stackedWidget, ui->fileImportPage);
+ Utils::setStackWidget(ui->stackedWidget, ui->fileImportPage);
}
diff --git a/wizarddialog.h b/wizarddialog.h
index 097c1c1..6d4cfda 100644
--- a/wizarddialog.h
+++ b/wizarddialog.h
@@ -26,6 +26,9 @@
#include "account.h"
#include "person.h"
+// new lrc
+#include "lrcinstance.h"
+
namespace Ui {
class WizardDialog;
}
@@ -35,6 +38,8 @@
Q_OBJECT
public:
+ using AccountInfo = lrc::api::account::Info;
+
enum WizardMode {
WIZARD,
NEW_ACCOUNT,
@@ -43,7 +48,7 @@
};
public:
- explicit WizardDialog(WizardMode wizardMode = WIZARD, Account* toBeMigrated = nullptr, QWidget* parent = 0);
+ explicit WizardDialog(WizardMode wizardMode = WIZARD, AccountInfo* toBeMigrated = nullptr, QWidget* parent = 0);
~WizardDialog();
//UI Slots
@@ -55,7 +60,6 @@
void on_passwordEdit_textChanged(const QString& arg1);
private slots:
- void endSetup(Account::RegistrationState state);
void on_usernameEdit_textChanged(const QString& arg1);
void handle_registeredNameFound(Account *account, NameDirectory::LookupStatus status, const QString& address, const QString& name);
void handle_nameRegistrationEnded(NameDirectory::RegisterNameStatus status, const QString& name);
@@ -69,14 +73,13 @@
private:
Ui::WizardDialog* ui;
- Account* account_;
+ AccountInfo* account_;
WizardMode wizardMode_;
QMovie* movie_;
QTimer nameLookupTimer_;
void setup();
void changePage(bool existingAccount);
- void usernameFailedRegistration();
void validateFileImport();
void createRingAccount(const QString &displayName = QString(),
const QString &password = QString(),