summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI')
-rw-r--r--Swift/QtUI/ChattablesModel.cpp52
-rw-r--r--Swift/QtUI/ChattablesModel.h28
-rw-r--r--Swift/QtUI/QtChatOverview.cpp66
-rw-r--r--Swift/QtUI/QtChatOverview.h28
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.cpp145
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.h57
-rw-r--r--Swift/QtUI/QtChatOverviewDelegate.cpp88
-rw-r--r--Swift/QtUI/QtChatOverviewDelegate.h23
-rw-r--r--Swift/QtUI/QtChatTabs.cpp3
-rw-r--r--Swift/QtUI/QtMainWindow.cpp23
-rw-r--r--Swift/QtUI/QtMainWindow.h46
-rw-r--r--Swift/QtUI/QtUIFactory.cpp4
-rw-r--r--Swift/QtUI/QtUIFactory.h3
-rw-r--r--Swift/QtUI/SConscript192
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.cpp23
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.h4
16 files changed, 657 insertions, 128 deletions
diff --git a/Swift/QtUI/ChattablesModel.cpp b/Swift/QtUI/ChattablesModel.cpp
new file mode 100644
index 0000000..d1257b9
--- /dev/null
+++ b/Swift/QtUI/ChattablesModel.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/ChattablesModel.h>
+
+#include <QDebug>
+
+#include <Swift/Controllers/Chat/Chattables.h>
+
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+
+ChattablesModel::ChattablesModel(Chattables& chattables, QObject* parent) : QAbstractListModel(parent), chattables_(chattables) {
+ //FIXME: scoped connections, do it properly not reset.
+ chattables_.onAdded.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+ chattables_.onRemoved.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+ chattables_.onChanged.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+}
+
+int ChattablesModel::rowCount(const QModelIndex& /*parent*/) const {
+ return chattables_.get().size();
+}
+
+QVariant ChattablesModel::data(const QModelIndex& index, int role) const {
+ //FIXME: Check validity
+ auto state = chattables_.getState(chattables_.get()[index.row()]);
+ if (role == Qt::DisplayRole) {
+ return P2QSTRING((state.name.empty() ? state.jid.toString() : state.name));
+ }
+ if (role == UnreadCountRole) {
+ return QString::number(state.unreadCount);
+ }
+ if (role == TypeRole) {
+ switch (state.type) {
+ case Chattables::State::Type::Room: return "ROOM";
+ case Chattables::State::Type::Person: return "PERSON";
+ }
+ }
+ if (role == StatusRole) {
+ return QVariant(static_cast<int>(state.status));
+ }
+ if (role == JIDRole) {
+ return P2QSTRING(state.jid.toString());
+ }
+ return QVariant();
+}
+
+}
diff --git a/Swift/QtUI/ChattablesModel.h b/Swift/QtUI/ChattablesModel.h
new file mode 100644
index 0000000..57073aa
--- /dev/null
+++ b/Swift/QtUI/ChattablesModel.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QAbstractListModel>
+
+namespace Swift {
+class Chattables;
+class ChattablesModel : public QAbstractListModel {
+ public:
+ enum ChattablesRoles {
+ UnreadCountRole = Qt::UserRole,
+ TypeRole = Qt::UserRole + 1,
+ StatusRole = Qt::UserRole + 2,
+ JIDRole = Qt::UserRole + 3
+ };
+ ChattablesModel(Chattables& chattables, QObject* parent);
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ private:
+ Chattables& chattables_;
+};
+
+}
diff --git a/Swift/QtUI/QtChatOverview.cpp b/Swift/QtUI/QtChatOverview.cpp
new file mode 100644
index 0000000..76943e9
--- /dev/null
+++ b/Swift/QtUI/QtChatOverview.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverview.h>
+
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QPalette>
+#include <QVBoxLayout>
+
+#include <Swift/Controllers/Chat/Chattables.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/QtChatOverviewBundle.h>
+
+namespace Swift {
+
+QtChatOverview::QtChatOverview(Chattables& chattables, QWidget* parent) : QWidget(parent), chattables_(chattables) {
+ QPalette newPalette = palette();
+ newPalette.setColor(QPalette::Background, {38, 81, 112});
+ setAutoFillBackground(true);
+ newPalette.setColor(QPalette::Foreground, {255, 255, 255});
+ setPalette(newPalette);
+
+ auto mainLayout = new QVBoxLayout();
+ setLayout(mainLayout);
+
+ auto headerLayout = new QHBoxLayout();
+ mainLayout->addLayout(headerLayout);
+ auto allLabel = new QLabel(tr("All"), this);
+ allLabel->setStyleSheet("color: white;");
+ auto peopleLabel = new QLabel(tr("People"), this);
+ peopleLabel->setStyleSheet("color: white;");
+ auto roomsLabel = new QLabel(tr("Rooms"), this);
+ roomsLabel->setStyleSheet("color: white;");
+ headerLayout->addWidget(allLabel);
+ headerLayout->addWidget(peopleLabel);
+ headerLayout->addWidget(roomsLabel);
+
+ rootModel_ = new ChattablesModel(chattables_, this);
+
+ auto unreadBundle = new QtChatOverviewBundle(rootModel_, "UNREAD", true, this);
+ connect(unreadBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(unreadBundle);
+
+ auto peopleBundle = new QtChatOverviewBundle(rootModel_, "PEOPLE", false, this);
+ connect(peopleBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(peopleBundle);
+
+ auto roomsBundle = new QtChatOverviewBundle(rootModel_, "ROOMS", false, this);
+ connect(roomsBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(roomsBundle);
+
+ mainLayout->addStretch();
+}
+
+QtChatOverview::~QtChatOverview() {}
+
+void QtChatOverview::handleItemClicked(JID jid) {
+ chattables_.onActivated(jid);
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverview.h b/Swift/QtUI/QtChatOverview.h
new file mode 100644
index 0000000..8cd7762
--- /dev/null
+++ b/Swift/QtUI/QtChatOverview.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+#include <Swiften/JID/JID.h>
+
+namespace Swift {
+ class Chattables;
+ class ChattablesModel;
+ class QtChatOverview : public QWidget {
+ Q_OBJECT
+ public:
+ QtChatOverview(Chattables&, QWidget* parent);
+ ~QtChatOverview() override;
+
+ private slots:
+ void handleItemClicked(JID jid);
+ private:
+ Chattables& chattables_;
+ ChattablesModel* rootModel_;
+ };
+}
diff --git a/Swift/QtUI/QtChatOverviewBundle.cpp b/Swift/QtUI/QtChatOverviewBundle.cpp
new file mode 100644
index 0000000..4e7c023
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewBundle.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverviewBundle.h>
+
+#include <QDebug>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QListView>
+#include <QPalette>
+#include <QSortFilterProxyModel>
+#include <QVBoxLayout>
+
+#include <Swiften/Elements/StatusShow.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/QtChatOverviewDelegate.h>
+#include <Swift/QtUI/QtClickableLabel.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+
+BundleFilter::BundleFilter(QObject* parent) : QSortFilterProxyModel(parent) {
+ sort(0, Qt::AscendingOrder);
+ setDynamicSortFilter(true);
+}
+
+void BundleFilter::addFilter(Filter filter) {
+ filters_.emplace(filter);
+ invalidateFilter();
+}
+
+bool BundleFilter::hasFilter(Filter filter) {
+ return filters_.count(filter) > 0;
+}
+
+void BundleFilter::removeFilter(Filter filter) {
+ filters_.erase(filter);
+ invalidateFilter();
+}
+
+bool BundleFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
+ auto row = sourceModel()->index(sourceRow, 0, sourceParent);
+ if (filters_.count(Filter::Unread)) {
+ if (row.data(ChattablesModel::UnreadCountRole).toInt() == 0) {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::People)) {
+ if (row.data(ChattablesModel::TypeRole).toString() != "PERSON") {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::Rooms)) {
+ if (row.data(ChattablesModel::TypeRole).toString() != "ROOM") {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::Online)) {
+ if (static_cast<StatusShow::Type>(row.data(ChattablesModel::StatusRole).toInt()) == StatusShow::None) {
+ return false;
+ }
+ }
+ return true;
+}
+
+QtChatOverviewBundle::QtChatOverviewBundle(ChattablesModel* rootModel, QString name, bool hideWhenEmpty, QWidget* parent) : QWidget(parent), rootModel_(rootModel), hideWhenEmpty_(hideWhenEmpty) {
+ proxyModel_ = new BundleFilter(this);
+ if (name == "UNREAD") { // FIXME: Obviously needs a better approach
+ proxyModel_->addFilter(BundleFilter::Filter::Unread);
+ }
+ if (name == "PEOPLE") {
+ proxyModel_->addFilter(BundleFilter::Filter::People);
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ }
+ if (name == "ROOMS") {
+ proxyModel_->addFilter(BundleFilter::Filter::Rooms);
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ }
+ proxyModel_->setSourceModel(rootModel);
+
+
+ auto mainLayout = new QVBoxLayout();
+ setLayout(mainLayout);
+
+ auto headerLayout = new QHBoxLayout();
+ mainLayout->addLayout(headerLayout);
+ auto nameLabel = new QLabel(name, this);
+ nameLabel->setStyleSheet("color: white;");
+ headerLayout->addWidget(nameLabel);
+ headerLayout->addStretch();
+ if (!hideWhenEmpty) {
+ filterLabel_ = new QtClickableLabel(this);
+ filterLabel_->setText(tr("Online"));
+ filterLabel_->setStyleSheet("color: white;");
+ headerLayout->addWidget(filterLabel_);
+ connect(filterLabel_, SIGNAL(clicked()), this, SLOT(handleFilterClicked()));
+ }
+ listView_ = new QListView(this);
+ listView_->setModel(proxyModel_);
+ listView_->setFrameStyle(QFrame::NoFrame);
+ listView_->setItemDelegate(new QtChatOverviewDelegate(this));
+ connect(listView_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleItemClicked(const QModelIndex&)));
+ recalculateSize();
+ mainLayout->addWidget(listView_);
+ connect(proxyModel_, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
+ connect(proxyModel_, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
+ connect(proxyModel_, SIGNAL(modelReset()), this, SLOT(recalculateSize()));
+}
+
+QtChatOverviewBundle::~QtChatOverviewBundle() {}
+
+void QtChatOverviewBundle::recalculateSize() {
+ int totalHeight = 0;
+ for (int i = 0; i < proxyModel_->rowCount(); i++) {
+ totalHeight += listView_->sizeHintForRow(i);
+ }
+ listView_->setFixedHeight(totalHeight);
+ if (hideWhenEmpty_ && totalHeight == 0) {
+ hide();
+ }
+ else {
+ show();
+ }
+}
+
+void QtChatOverviewBundle::handleFilterClicked() {
+ if (proxyModel_->hasFilter(BundleFilter::Filter::Online)) {
+ proxyModel_->removeFilter(BundleFilter::Filter::Online);
+ filterLabel_->setText(tr("All"));
+ }
+ else {
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ filterLabel_->setText(tr("Online"));
+ }
+}
+
+void QtChatOverviewBundle::handleItemClicked(const QModelIndex& index) {
+ clicked(JID(Q2PSTRING(index.data(ChattablesModel::JIDRole).toString())));
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverviewBundle.h b/Swift/QtUI/QtChatOverviewBundle.h
new file mode 100644
index 0000000..f469fea
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewBundle.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <set>
+
+#include <QSortFilterProxyModel>
+#include <QString>
+#include <QWidget>
+
+#include <Swiften/JID/JID.h>
+
+class QListView;
+
+namespace Swift {
+ class ChattablesModel;
+ class QtClickableLabel;
+
+ class BundleFilter : public QSortFilterProxyModel {
+ Q_OBJECT
+ public:
+ enum class Filter {Unread, People, Rooms, Online};
+ BundleFilter(QObject* parent);
+ void addFilter(Filter);
+ bool hasFilter(Filter);
+ void removeFilter(Filter);
+ protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const;
+ private:
+ std::set<Filter> filters_;
+ };
+
+ class QtChatOverviewBundle : public QWidget {
+ Q_OBJECT
+ public:
+ QtChatOverviewBundle(ChattablesModel*, QString name, bool hideWhenEmpty, QWidget* parent);
+ ~QtChatOverviewBundle() override;
+
+ signals:
+ void clicked(JID jid);
+
+ private slots:
+ void recalculateSize();
+ void handleFilterClicked();
+ void handleItemClicked(const QModelIndex&);
+ private:
+ ChattablesModel* rootModel_;
+ QListView* listView_;
+ BundleFilter* proxyModel_;
+ bool hideWhenEmpty_;
+ QtClickableLabel* filterLabel_ = nullptr;
+ };
+}
diff --git a/Swift/QtUI/QtChatOverviewDelegate.cpp b/Swift/QtUI/QtChatOverviewDelegate.cpp
new file mode 100644
index 0000000..919c23d
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewDelegate.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverviewDelegate.h>
+
+#include <Swiften/Elements/StatusShow.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/Roster/DelegateCommons.h>
+
+namespace Swift {
+
+QtChatOverviewDelegate::QtChatOverviewDelegate(QObject* parent) : QItemDelegate(parent), nameFont(QApplication::font()) {
+
+}
+
+QtChatOverviewDelegate::~QtChatOverviewDelegate() {}
+
+QSize QtChatOverviewDelegate::sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const {
+ int heightByAvatar = DelegateCommons::avatarSize + DelegateCommons::verticalMargin * 2;
+ QFontMetrics nameMetrics(nameFont);
+ int sizeByText = 2 * DelegateCommons::verticalMargin + nameMetrics.height();
+ return QSize(150, sizeByText > heightByAvatar ? sizeByText : heightByAvatar);
+}
+
+void QtChatOverviewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
+ painter->save();
+ QRect fullRegion(option.rect);
+ const int statusCircleRadius = 3;
+ const int horizontalMargin = 4;
+
+ QColor bgColor(38, 81, 112);
+ QPen fontPen("white"); // FIXME
+
+ if (option.state & QStyle::State_Selected) {
+ //FIXME
+ }
+ painter->fillRect(fullRegion, bgColor);
+ painter->setPen(fontPen);
+
+ QFontMetrics nameMetrics(nameFont);
+ painter->setFont(nameFont);
+ QRect nameRegion(fullRegion.adjusted((horizontalMargin + statusCircleRadius) * 2, DelegateCommons::verticalMargin, 0, 0));
+ DelegateCommons::drawElidedText(painter, nameRegion, index.data(Qt::DisplayRole).toString());
+
+ const auto green = QColor(124, 243, 145);
+ const auto yellow = QColor(124, 243, 145); // FIXME: Yellow isn't green
+ const auto red = QColor(255,45,71);
+ const auto grey = QColor(159,159,159);
+ auto circleColour = grey;
+ auto status = static_cast<StatusShow::Type>(index.data(ChattablesModel::StatusRole).toInt());
+ switch (status) {
+ case StatusShow::Online: circleColour = green;break;
+ case StatusShow::FFC: circleColour = green;break;
+ case StatusShow::Away: circleColour = yellow;break;
+ case StatusShow::XA: circleColour = yellow;break;
+ case StatusShow::DND: circleColour = red;break;
+ case StatusShow::None: circleColour = grey;break;
+ }
+
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ int unreadCount = index.data(ChattablesModel::UnreadCountRole).toInt();
+ if (unreadCount > 0) {
+ int unreadCountSize = 16;
+ QRect unreadRect(fullRegion.right() - unreadCountSize - horizontalMargin, fullRegion.top() + (fullRegion.height() - unreadCountSize) / 2, unreadCountSize, unreadCountSize);
+ QPen pen(QColor("white"));
+ pen.setWidth(1);
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ painter->setPen(pen);
+ painter->drawEllipse(unreadRect);
+ painter->setBackgroundMode(Qt::TransparentMode);
+ painter->setPen(QColor("white"));
+ DelegateCommons::drawElidedText(painter, unreadRect, QString("%1").arg(unreadCount), Qt::AlignCenter);
+ }
+
+ painter->setPen(circleColour);
+ painter->setBrush(circleColour);
+ painter->drawEllipse(fullRegion.topLeft() + QPointF(horizontalMargin + 4, fullRegion.height() / 2), statusCircleRadius, statusCircleRadius);
+
+
+ painter->restore();
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverviewDelegate.h b/Swift/QtUI/QtChatOverviewDelegate.h
new file mode 100644
index 0000000..b00337d
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewDelegate.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QItemDelegate>
+#include <QFont>
+
+namespace Swift {
+ class QtChatOverviewDelegate : public QItemDelegate {
+ Q_OBJECT
+ public:
+ QtChatOverviewDelegate(QObject* parent);
+ ~QtChatOverviewDelegate() override;
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ private:
+ QFont nameFont;
+ };
+}
diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp
index f4d0d46..7b81567 100644
--- a/Swift/QtUI/QtChatTabs.cpp
+++ b/Swift/QtUI/QtChatTabs.cpp
@@ -24,6 +24,7 @@
#include <Swiften/Base/Log.h>
#include <Swift/Controllers/ChatMessageSummarizer.h>
+#include <Swift/Controllers/SettingConstants.h>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtTabWidget.h>
@@ -39,7 +40,7 @@ QtChatTabs::QtChatTabs(bool singleWindow, SettingsProvider* settingsProvider, bo
#else
setAttribute(Qt::WA_ShowWithoutActivating);
#endif
- dynamicGrid_ = new QtDynamicGridLayout(this, trellisMode);
+ dynamicGrid_ = new QtDynamicGridLayout(settingsProvider->getSetting(SettingConstants::FUTURE), this, trellisMode);
connect(dynamicGrid_, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabCloseRequested(int)));
connect(dynamicGrid_, SIGNAL(onCurrentIndexChanged(int)), this, SLOT(handleCurrentTabIndexChanged(int)));
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 0c1dd97..cd38259 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -19,6 +19,7 @@
#include <QListWidgetItem>
#include <QMenuBar>
#include <QPushButton>
+#include <QScrollArea>
#include <QTabWidget>
#include <QToolBar>
@@ -35,6 +36,7 @@
#include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h>
#include <Swift/QtUI/QtAdHocCommandWithJIDWindow.h>
+#include <Swift/QtUI/QtChatOverview.h>
#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtSettingsProvider.h>
#include <Swift/QtUI/QtSwiftUtil.h>
@@ -52,7 +54,7 @@
namespace Swift {
-QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
+QtMainWindow::QtMainWindow(Chattables& chattables, SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID) : QWidget(), MainWindow(false), chattables_(chattables), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
settings_ = settings;
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
@@ -66,11 +68,18 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
connect(meView_, SIGNAL(onShowCertificateInfo()), this, SLOT(handleShowCertificateInfo()));
tabs_ = new QtTabWidget(this);
-#if QT_VERSION >= 0x040500
tabs_->setDocumentMode(true);
-#endif
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
+
+ if (settings->getSetting(SettingConstants::FUTURE)) {
+ chatOverview_ = new QtChatOverview(chattables, this);
+ auto overviewScroll = new QScrollArea(this);
+ overviewScroll->setWidgetResizable(true);
+ overviewScroll->setWidget(chatOverview_);
+ tabs_->addTab(overviewScroll, tr("&All"));
+ }
+
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_);
@@ -82,9 +91,7 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
contactTabLayout->addWidget(treeWidget_);
new QtFilterWidget(this, treeWidget_, uiEventStream_, contactTabLayout);
-
tabs_->addTab(contactsTabWidget_, tr("&Contacts"));
-
eventWindow_ = new QtEventWindow(uiEventStream_);
connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int)));
@@ -103,8 +110,11 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
tabs_->tabBar()->hide();
tabBarCombo_ = new QComboBox(this);
tabBarCombo_->setAccessibleName("Current View");
+ tabBarCombo_->addItem(tr("All"));
+#ifndef NOT_YET
tabBarCombo_->addItem(tr("Contacts"));
tabBarCombo_->addItem(tr("Chats"));
+#endif
tabBarCombo_->addItem(tr("Notices"));
tabBarCombo_->setCurrentIndex(tabs_->currentIndex());
mainLayout->addWidget(tabBarCombo_);
@@ -424,4 +434,3 @@ void QtMainWindow::setBlockingCommandAvailable(bool isAvailable) {
}
}
-
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index c46fdfc..0e7f290 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -12,6 +12,7 @@
#include <QMenu>
#include <QWidget>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/UIInterfaces/MainWindow.h>
#include <Swift/QtUI/ChatList/QtChatListWindow.h>
@@ -19,44 +20,45 @@
#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtRosterHeader.h>
+class QAction;
class QComboBox;
class QLineEdit;
-class QPushButton;
-class QToolBar;
-class QAction;
class QMenu;
+class QPushButton;
class QTabWidget;
+class QToolBar;
namespace Swift {
+ class QtChatOverview;
class QtRosterWidget;
- class TreeWidget;
- class UIEventStream;
class QtTabWidget;
- class SettingsProvider;
class QtUIPreferences;
+ class SettingsProvider;
class StatusCache;
+ class TreeWidget;
+ class UIEventStream;
class QtMainWindow : public QWidget, public MainWindow {
Q_OBJECT
public:
- QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID);
- virtual ~QtMainWindow();
+ QtMainWindow(Chattables&, SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID);
+ virtual ~QtMainWindow() override;
std::vector<QMenu*> getMenus() {return menus_;}
- void setMyNick(const std::string& name);
- void setMyJID(const JID& jid);
- void setMyAvatarPath(const std::string& path);
- void setMyStatusText(const std::string& status);
- void setMyStatusType(StatusShow::Type type);
- void setMyContactRosterItem(std::shared_ptr<ContactRosterItem> contact);
- void setConnecting();
- void setStreamEncryptionStatus(bool tlsInPlaceAndValid);
- void openCertificateDialog(const std::vector<Certificate::ref>& chain);
+ void setMyNick(const std::string& name) override;
+ void setMyJID(const JID& jid) override;
+ void setMyAvatarPath(const std::string& path) override;
+ void setMyStatusText(const std::string& status) override;
+ void setMyStatusType(StatusShow::Type type) override;
+ void setMyContactRosterItem(std::shared_ptr<ContactRosterItem> contact) override;
+ void setConnecting() override;
+ void setStreamEncryptionStatus(bool tlsInPlaceAndValid) override;
+ void openCertificateDialog(const std::vector<Certificate::ref>& chain) override;
static void openCertificateDialog(const std::vector<Certificate::ref>& chain, QWidget* parent);
QtEventWindow* getEventWindow();
QtChatListWindow* getChatListWindow();
- void setRosterModel(Roster* roster);
- void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands);
- void setBlockingCommandAvailable(bool isAvailable);
+ void setRosterModel(Roster* roster) override;
+ void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands) override;
+ void setBlockingCommandAvailable(bool isAvailable) override;
private slots:
void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage);
void handleSettingChanged(const std::string& settingPath);
@@ -81,6 +83,7 @@ namespace Swift {
void handleSomethingSelectedChanged(bool itemSelected);
private:
+ Chattables& chattables_;
SettingsProvider* settings_;
QtLoginWindow::QtMenus loginMenus_;
std::vector<QMenu*> menus_;
@@ -98,6 +101,7 @@ namespace Swift {
QMenu* serverAdHocMenu_;
QtTabWidget* tabs_;
QComboBox* tabBarCombo_;
+ QtChatOverview* chatOverview_;
QWidget* contactsTabWidget_;
QWidget* eventsTabWidget_;
QtEventWindow* eventWindow_;
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index 583c477..7840b1b 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -86,8 +86,8 @@ FileTransferListWidget* QtUIFactory::createFileTransferListWidget() {
return widget;
}
-MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) {
- lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_);
+MainWindow* QtUIFactory::createMainWindow(Chattables& chattables, UIEventStream* eventStream) {
+ lastMainWindow = new QtMainWindow(chattables, settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_);
if (tabs) {
tabs->setViewMenu(lastMainWindow->getMenus()[0]);
}
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index 9989101..9eeaa68 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -17,6 +17,7 @@ class QSplitter;
namespace Swift {
class AutoUpdater;
+ class Chattables;
class QtChatTabs;
class QtChatTabsBase;
class QtChatTheme;
@@ -39,7 +40,7 @@ namespace Swift {
~QtUIFactory();
virtual XMLConsoleWidget* createXMLConsoleWidget();
virtual HistoryWindow* createHistoryWindow(UIEventStream*);
- virtual MainWindow* createMainWindow(UIEventStream* eventStream);
+ virtual MainWindow* createMainWindow(Chattables& chattables, UIEventStream* eventStream);
virtual LoginWindow* createLoginWindow(UIEventStream* eventStream);
virtual EventWindow* createEventWindow();
virtual ChatListWindow* createChatListWindow(UIEventStream*);
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 3755187..4ff2d81 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -110,131 +110,135 @@ myenv.WriteVal("DefaultTheme.qrc", myenv.Value(generateQRCTheme(myenv.Dir("#/Swi
sources = [
"main.cpp",
+ "ChatList/ChatListDelegate.cpp",
+ "ChatList/ChatListModel.cpp",
+ "ChatList/ChatListMUCItem.cpp",
+ "ChatList/ChatListRecentItem.cpp",
+ "ChatList/ChatListWhiteboardItem.cpp",
+ "ChatList/QtChatListWindow.cpp",
+ "ChattablesModel.cpp",
+ "ChatSnippet.cpp",
+ "EventViewer/EventDelegate.cpp",
+ "EventViewer/EventModel.cpp",
+ "EventViewer/QtEvent.cpp",
+ "EventViewer/QtEventWindow.cpp",
+ "EventViewer/TwoLineDelegate.cpp",
"FlowLayout.cpp",
+ "MessageSnippet.cpp",
+ "MUCSearch/MUCSearchDelegate.cpp",
+ "MUCSearch/MUCSearchEmptyItem.cpp",
+ "MUCSearch/MUCSearchModel.cpp",
+ "MUCSearch/MUCSearchRoomItem.cpp",
+ "MUCSearch/MUCSearchServiceItem.cpp",
+ "MUCSearch/QtLeafSortFilterProxyModel.cpp",
+ "MUCSearch/QtMUCSearchWindow.cpp",
+ "qrc_DefaultTheme.cc",
+ "qrc_Swift.cc",
"QtAboutWidget.cpp",
- "QtSpellCheckerWindow.cpp",
+ "QtAddBookmarkWindow.cpp",
+ "QtAdHocCommandWindow.cpp",
+ "QtAdHocCommandWithJIDWindow.cpp",
+ "QtAffiliationEditor.cpp",
"QtAvatarWidget.cpp",
- "QtUIFactory.cpp",
+ "QtBlockListEditorWindow.cpp",
+ "QtBookmarkDetailWindow.cpp",
+ "QtCachedImageScaler.cpp",
+ "QtChatOverview.cpp",
+ "QtChatOverviewBundle.cpp",
+ "QtChatOverviewDelegate.cpp",
+ "QtChatTabs.cpp",
+ "QtChatTabsBase.cpp",
+ "QtChatTabsShortcutOnlySubstitute.cpp",
+ "QtChatTheme.cpp",
+ "QtChatView.cpp",
+ "QtChatWindow.cpp",
"QtChatWindowFactory.cpp",
+ "QtChatWindowJSBridge.cpp",
+ "QtCheckBoxStyledItemDelegate.cpp",
"QtClickableLabel.cpp",
+ "QtClosableLineEdit.cpp",
+ "QtColorSelectionStyledItemDelegate.cpp",
+ "QtColorToolButton.cpp",
+ "QtConnectionSettingsWindow.cpp",
+ "QtContactEditWidget.cpp",
+ "QtContactEditWindow.cpp",
+ "QtEditBookmarkWindow.cpp",
+ "QtElidingLabel.cpp",
+ "QtEmojiCell.cpp",
+ "QtEmojisGrid.cpp",
+ "QtEmojisScroll.cpp",
+ "QtEmojisSelector.cpp",
+ "QtEmoticonsGrid.cpp",
+ "QtFileTransferListItemModel.cpp",
+ "QtFileTransferListWidget.cpp",
+ "QtFormResultItemModel.cpp",
+ "QtFormWidget.cpp",
+ "QtHighlightNotificationConfigDialog.cpp",
+ "QtHistoryWindow.cpp",
+ "QtJoinMUCWindow.cpp",
+ "QtLineEdit.cpp",
"QtLoginWindow.cpp",
"QtMainWindow.cpp",
- "QtProfileWindow.cpp",
- "QtBlockListEditorWindow.cpp",
+ "QtMUCConfigurationWindow.cpp",
"QtNameWidget.cpp",
+ "QtPlainChatView.cpp",
+ "QtProfileWindow.cpp",
+ "QtRecentEmojisGrid.cpp",
+ "QtResourceHelper.cpp",
+ "QtRosterHeader.cpp",
+ "QtScaledAvatarCache.cpp",
"QtSettingsProvider.cpp",
+ "QtSingleWindow.cpp",
+ "QtSoundPlayer.cpp",
+ "QtSoundSelectionStyledItemDelegate.cpp",
+ "QtSpellCheckerWindow.cpp",
+ "QtSpellCheckHighlighter.cpp",
"QtStatusWidget.cpp",
- "QtScaledAvatarCache.cpp",
+ "QtSubscriptionRequestWindow.cpp",
"QtSwift.cpp",
- "QtURIHandler.cpp",
- "QtChatWindow.cpp",
- "QtChatView.cpp",
- "QtWebKitChatView.cpp",
- "QtPlainChatView.cpp",
- "QtChatTheme.cpp",
- "QtChatTabs.cpp",
- "QtChatTabsBase.cpp",
- "QtChatTabsShortcutOnlySubstitute.cpp",
- "QtSoundPlayer.cpp",
"QtSystemTray.cpp",
- "QtCachedImageScaler.cpp",
"QtTabbable.cpp",
"QtTabWidget.cpp",
"QtTextEdit.cpp",
- "QtXMLConsoleWidget.cpp",
- "QtHistoryWindow.cpp",
- "QtFileTransferListWidget.cpp",
- "QtFileTransferListItemModel.cpp",
- "QtAdHocCommandWindow.cpp",
- "QtAdHocCommandWithJIDWindow.cpp",
+ "QtUIFactory.cpp",
+ "QtUISettingConstants.cpp",
+ "QtUpdateFeedSelectionDialog.cpp",
+ "QtURIHandler.cpp",
+ "QtURLValidator.cpp",
"QtUtilities.cpp",
- "QtBookmarkDetailWindow.cpp",
- "QtAddBookmarkWindow.cpp",
- "QtEditBookmarkWindow.cpp",
- "QtEmojisGrid.cpp",
- "QtEmojiCell.cpp",
- "QtEmojisScroll.cpp",
- "QtEmojisSelector.cpp",
- "QtRecentEmojisGrid.cpp",
- "QtEmoticonsGrid.cpp",
- "QtContactEditWindow.cpp",
- "QtContactEditWidget.cpp",
- "QtSingleWindow.cpp",
- "QtColorToolButton.cpp",
- "QtClosableLineEdit.cpp",
- "QtHighlightNotificationConfigDialog.cpp",
- "ChatSnippet.cpp",
- "MessageSnippet.cpp",
- "SystemMessageSnippet.cpp",
- "QtElidingLabel.cpp",
- "QtFormWidget.cpp",
- "QtFormResultItemModel.cpp",
- "QtLineEdit.cpp",
- "QtJoinMUCWindow.cpp",
- "QtConnectionSettingsWindow.cpp",
- "Roster/RosterModel.cpp",
- "Roster/QtTreeWidget.cpp",
- "Roster/RosterDelegate.cpp",
- "Roster/GroupItemDelegate.cpp",
+ "QtWebKitChatView.cpp",
+ "QtWebView.cpp",
+ "QtXMLConsoleWidget.cpp",
"Roster/DelegateCommons.cpp",
+ "Roster/GroupItemDelegate.cpp",
"Roster/QtFilterWidget.cpp",
- "Roster/QtRosterWidget.cpp",
"Roster/QtOccupantListWidget.cpp",
+ "Roster/QtRosterWidget.cpp",
+ "Roster/QtTreeWidget.cpp",
+ "Roster/RosterDelegate.cpp",
+ "Roster/RosterModel.cpp",
"Roster/RosterTooltip.cpp",
- "EventViewer/EventModel.cpp",
- "EventViewer/EventDelegate.cpp",
- "EventViewer/TwoLineDelegate.cpp",
- "EventViewer/QtEventWindow.cpp",
- "EventViewer/QtEvent.cpp",
- "ChatList/QtChatListWindow.cpp",
- "ChatList/ChatListModel.cpp",
- "ChatList/ChatListDelegate.cpp",
- "ChatList/ChatListMUCItem.cpp",
- "ChatList/ChatListRecentItem.cpp",
- "ChatList/ChatListWhiteboardItem.cpp",
- "MUCSearch/MUCSearchDelegate.cpp",
- "MUCSearch/MUCSearchEmptyItem.cpp",
- "MUCSearch/MUCSearchModel.cpp",
- "MUCSearch/MUCSearchRoomItem.cpp",
- "MUCSearch/MUCSearchServiceItem.cpp",
- "MUCSearch/QtLeafSortFilterProxyModel.cpp",
- "MUCSearch/QtMUCSearchWindow.cpp",
+ "SystemMessageSnippet.cpp",
+ "Trellis/QtDNDTabBar.cpp",
+ "Trellis/QtDynamicGridLayout.cpp",
+ "Trellis/QtGridSelectionDialog.cpp",
"UserSearch/ContactListDelegate.cpp",
"UserSearch/ContactListModel.cpp",
"UserSearch/QtContactListWidget.cpp",
"UserSearch/QtSuggestingJIDInput.cpp",
- "UserSearch/QtUserSearchFirstPage.cpp",
- "UserSearch/QtUserSearchFirstMultiJIDPage.cpp",
+ "UserSearch/QtUserSearchDetailsPage.cpp",
"UserSearch/QtUserSearchFieldsPage.cpp",
+ "UserSearch/QtUserSearchFirstMultiJIDPage.cpp",
+ "UserSearch/QtUserSearchFirstPage.cpp",
"UserSearch/QtUserSearchResultsPage.cpp",
- "UserSearch/QtUserSearchDetailsPage.cpp",
"UserSearch/QtUserSearchWindow.cpp",
- "UserSearch/UserSearchModel.cpp",
"UserSearch/UserSearchDelegate.cpp",
+ "UserSearch/UserSearchModel.cpp",
+ "Whiteboard/ColorWidget.cpp",
"Whiteboard/FreehandLineItem.cpp",
"Whiteboard/GView.cpp",
- "Whiteboard/TextDialog.cpp",
"Whiteboard/QtWhiteboardWindow.cpp",
- "Whiteboard/ColorWidget.cpp",
- "QtSubscriptionRequestWindow.cpp",
- "QtRosterHeader.cpp",
- "QtWebView.cpp",
- "qrc_DefaultTheme.cc",
- "qrc_Swift.cc",
- "QtChatWindowJSBridge.cpp",
- "QtMUCConfigurationWindow.cpp",
- "QtAffiliationEditor.cpp",
- "QtUISettingConstants.cpp",
- "QtURLValidator.cpp",
- "QtResourceHelper.cpp",
- "QtSpellCheckHighlighter.cpp",
- "QtUpdateFeedSelectionDialog.cpp",
- "Trellis/QtDynamicGridLayout.cpp",
- "Trellis/QtDNDTabBar.cpp",
- "Trellis/QtGridSelectionDialog.cpp",
- "QtCheckBoxStyledItemDelegate.cpp",
- "QtColorSelectionStyledItemDelegate.cpp",
- "QtSoundSelectionStyledItemDelegate.cpp"
+ "Whiteboard/TextDialog.cpp"
]
if env["PLATFORM"] == "win32" :
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
index 2509b3f..2402529 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
@@ -23,7 +23,7 @@
namespace Swift {
-QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(nullptr) {
+QtDynamicGridLayout::QtDynamicGridLayout(bool future, QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(nullptr), future_(future) {
gridLayout_ = new QGridLayout(this);
setContentsMargins(0,0,0,0);
setDimensions(QSize(1,1));
@@ -49,6 +49,9 @@ int QtDynamicGridLayout::addTab(QtTabbable* tab, const QString& title) {
tabWidget->addTab(tab, title);
}
tab->setEmphasiseFocus(getDimension().width() > 1 || getDimension().height() > 1);
+ if (future_) {
+ showHideFirstTabs(); // FIXME: Putting it here as a workaround until I work out why it doesn't work initially
+ }
return tabWidget ? indexOf(tab) : -1;
}
@@ -328,6 +331,24 @@ void QtDynamicGridLayout::setDimensions(const QSize& dim) {
setCurrentWidget(restoredWidget);
updateEmphasiseFocusOnTabs();
+
+ if (future_) {
+ showHideFirstTabs();
+ }
+}
+
+void QtDynamicGridLayout::showHideFirstTabs() {
+ int tmp;
+ auto firstTabs = indexToTabWidget(0, tmp);
+
+ if (firstTabs) {
+ if (gridLayout_->columnCount() == 1 && gridLayout_->rowCount() == 1) {
+ firstTabs->tabBar()->hide();
+ }
+ else {
+ firstTabs->tabBar()->show();
+ }
+ }
}
void QtDynamicGridLayout::updateEmphasiseFocusOnTabs() {
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.h b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
index 682ae41..f3a2e96 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.h
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
@@ -20,7 +20,7 @@ namespace Swift {
class QtDynamicGridLayout : public QWidget {
Q_OBJECT
public:
- explicit QtDynamicGridLayout(QWidget* parent = nullptr, bool enableDND = false);
+ explicit QtDynamicGridLayout(bool future, QWidget* parent = nullptr, bool enableDND = false);
virtual ~QtDynamicGridLayout();
QSize getDimension() const;
@@ -71,6 +71,7 @@ namespace Swift {
void moveTab(QtTabWidget* tabWidget, int oldIndex, int newIndex);
QtTabWidget* createDNDTabWidget(QWidget* parent);
void updateEmphasiseFocusOnTabs();
+ void showHideFirstTabs();
private:
QGridLayout *gridLayout_;
@@ -78,5 +79,6 @@ namespace Swift {
QHash<QString, QPoint> tabPositions_;
QtTabbable* movingTab_;
bool resizing_ = false;
+ bool future_ = false;
};
}