diff options
Diffstat (limited to 'Swift/QtUI/QtChatTabs.cpp')
-rw-r--r-- | Swift/QtUI/QtChatTabs.cpp | 644 |
1 files changed, 322 insertions, 322 deletions
diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp index 9ecf093..3241858 100644 --- a/Swift/QtUI/QtChatTabs.cpp +++ b/Swift/QtUI/QtChatTabs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,17 +9,6 @@ #include <algorithm> #include <vector> -#include <Swiften/Base/Log.h> - -#include <Swift/Controllers/ChatMessageSummarizer.h> -#include <Swift/Controllers/SettingConstants.h> -#include <Swift/Controllers/Settings/SettingsProvider.h> -#include <Swift/QtUI/QtSwiftUtil.h> -#include <Swift/QtUI/QtTabWidget.h> -#include <Swift/QtUI/QtTabbable.h> -#include <Swift/QtUI/Trellis/QtDynamicGridLayout.h> -#include <Swift/QtUI/Trellis/QtGridSelectionDialog.h> - #include <QAction> #include <QApplication> #include <QCloseEvent> @@ -31,392 +20,403 @@ #include <QTabWidget> #include <QtGlobal> +#include <Swiften/Base/Log.h> + +#include <Swift/Controllers/ChatMessageSummarizer.h> + +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swift/QtUI/QtTabWidget.h> +#include <Swift/QtUI/QtTabbable.h> +#include <Swift/QtUI/QtUISettingConstants.h> +#include <Swift/QtUI/Trellis/QtDynamicGridLayout.h> +#include <Swift/QtUI/Trellis/QtGridSelectionDialog.h> + namespace Swift { -QtChatTabs::QtChatTabs(bool singleWindow, SettingsProvider* settingsProvider, bool trellisMode) : QWidget(), singleWindow_(singleWindow), settingsProvider_(settingsProvider), trellisMode_(trellisMode), dynamicGrid_(NULL), gridSelectionDialog_(NULL) { +QtChatTabs::QtChatTabs(bool singleWindow, SettingsProvider* settingsProvider, bool trellisMode) : QWidget(), singleWindow_(singleWindow), settingsProvider_(settingsProvider), trellisMode_(trellisMode), dynamicGrid_(nullptr), gridSelectionDialog_(nullptr) { #ifndef Q_OS_MAC - setWindowIcon(QIcon(":/logo-chat-16.png")); + setWindowIcon(QIcon(":/logo-chat-16.png")); #else - setAttribute(Qt::WA_ShowWithoutActivating); + setAttribute(Qt::WA_ShowWithoutActivating); #endif - dynamicGrid_ = new QtDynamicGridLayout(this, trellisMode); - connect(dynamicGrid_, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabCloseRequested(int))); - connect(dynamicGrid_, SIGNAL(onCurrentIndexChanged(int)), this, SLOT(handleCurrentTabIndexChanged(int))); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(dynamicGrid_); - setLayout(layout); - - if (trellisMode) { - // restore size - std::string gridSizeString = settingsProvider->getSetting(SettingConstants::TRELLIS_GRID_SIZE); - if (!gridSizeString.empty()) { - QByteArray gridSizeData = QByteArray::fromBase64(P2QSTRING(gridSizeString).toUtf8()); - QDataStream dataStreamGridSize(&gridSizeData, QIODevice::ReadWrite); - QSize gridSize(1,1); - dataStreamGridSize >> gridSize; - dynamicGrid_->setDimensions(gridSize); - } - - // restore positions - std::string tabPositionsString = settingsProvider->getSetting(SettingConstants::TRELLIS_GRID_POSITIONS); - if (!tabPositionsString.empty()) { - QByteArray tabPositionsData = QByteArray::fromBase64(P2QSTRING(tabPositionsString).toUtf8()); - QDataStream inTabPositions(&tabPositionsData, QIODevice::ReadWrite); - QHash<QString, QPoint> tabPositions; - inTabPositions >> tabPositions; - dynamicGrid_->setTabPositions(tabPositions); - } - } - - gridSelectionDialog_ = new QtGridSelectionDialog(); - - // setup shortcuts - shortcuts_ << new QShortcut(QKeySequence(tr("CTRL+W", "Close chat tab.")), window(), SLOT(handleCloseTabShortcut())); - shortcuts_ << new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageUp), window(), SLOT(handleRequestedPreviousTab())); - shortcuts_ << new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageDown), window(), SLOT(handleRequestedNextTab())); - shortcuts_ << new QShortcut(QKeySequence(Qt::ALT + Qt::Key_A), window(), SLOT(handleRequestedActiveTab())); + dynamicGrid_ = new QtDynamicGridLayout(this, trellisMode); + connect(dynamicGrid_, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabCloseRequested(int))); + connect(dynamicGrid_, SIGNAL(onCurrentIndexChanged(int)), this, SLOT(handleCurrentTabIndexChanged(int))); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(dynamicGrid_); + setLayout(layout); + + if (trellisMode) { + // restore size + std::string gridSizeString = settingsProvider->getSetting(QtUISettingConstants::TRELLIS_GRID_SIZE); + if (!gridSizeString.empty()) { + QByteArray gridSizeData = QByteArray::fromBase64(P2QSTRING(gridSizeString).toUtf8()); + QDataStream dataStreamGridSize(&gridSizeData, QIODevice::ReadWrite); + QSize gridSize(1,1); + dataStreamGridSize >> gridSize; + dynamicGrid_->setDimensions(gridSize); + } + + // restore positions + std::string tabPositionsString = settingsProvider->getSetting(QtUISettingConstants::TRELLIS_GRID_POSITIONS); + if (!tabPositionsString.empty()) { + QByteArray tabPositionsData = QByteArray::fromBase64(P2QSTRING(tabPositionsString).toUtf8()); + QDataStream inTabPositions(&tabPositionsData, QIODevice::ReadWrite); + QHash<QString, QPoint> tabPositions; + inTabPositions >> tabPositions; + dynamicGrid_->setTabPositions(tabPositions); + } + } + + gridSelectionDialog_ = new QtGridSelectionDialog(); + + // setup shortcuts + shortcuts_ << new QShortcut(QKeySequence(tr("CTRL+W", "Close chat tab.")), window(), SLOT(handleCloseTabShortcut())); + shortcuts_ << new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageUp), window(), SLOT(handleRequestedPreviousTab())); + shortcuts_ << new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageDown), window(), SLOT(handleRequestedNextTab())); + shortcuts_ << new QShortcut(QKeySequence(Qt::ALT + Qt::Key_A), window(), SLOT(handleRequestedActiveTab())); } QtChatTabs::~QtChatTabs() { - foreach (QShortcut* shortcut, shortcuts_) { - delete shortcut; - } - - if (trellisMode_) { - storeTabPositions(); - } - delete gridSelectionDialog_; + for (auto shortcut : shortcuts_) { + delete shortcut; + } + + if (trellisMode_) { + storeTabPositions(); + } + delete gridSelectionDialog_; } void QtChatTabs::closeEvent(QCloseEvent* event) { - //Hide first to prevent flickering as each tab is removed. - hide(); - if (trellisMode_) { - storeTabPositions(); - } - - for (int i = dynamicGrid_->count() - 1; i >= 0; i--) { - dynamicGrid_->widget(i)->close(); - } - event->accept(); + //Hide first to prevent flickering as each tab is removed. + hide(); + if (trellisMode_) { + storeTabPositions(); + } + + for (int i = dynamicGrid_->count() - 1; i >= 0; i--) { + dynamicGrid_->widget(i)->close(); + } + event->accept(); } QtTabbable* QtChatTabs::getCurrentTab() { - return qobject_cast<QtTabbable*>(dynamicGrid_->currentWidget()); + return qobject_cast<QtTabbable*>(dynamicGrid_->currentWidget()); } void QtChatTabs::setViewMenu(QMenu* viewMenu) { - if (trellisMode_) { - viewMenu->addSeparator(); - QAction* action = new QAction(tr("Change &layout"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Alt+L"))); - connect(action, SIGNAL(triggered()), this, SLOT(handleOpenLayoutChangeDialog())); - viewMenu->addAction(action); - - action = new QAction(tr("Move Tab right"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Shift+PgDown"))); - connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabRight())); - viewMenu->addAction(action); - - action = new QAction(tr("Move Tab left"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Shift+PgUp"))); - connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabLeft())); - viewMenu->addAction(action); - - action = new QAction(tr("Move Tab to next group"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Alt+PgDown"))); - connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabToNextGroup())); - viewMenu->addAction(action); - - action = new QAction(tr("Move Tab to previous group"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Alt+PgUp"))); - connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabToPreviousGroup())); - viewMenu->addAction(action); - } + if (trellisMode_) { + viewMenu->addSeparator(); + QAction* action = new QAction(tr("Change &layout"), this); + action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(QKeySequence(tr("Ctrl+Alt+L"))); + connect(action, SIGNAL(triggered()), this, SLOT(handleOpenLayoutChangeDialog())); + viewMenu->addAction(action); + + action = new QAction(tr("Move Tab right"), this); + action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(QKeySequence(tr("Ctrl+Shift+PgDown"))); + connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabRight())); + viewMenu->addAction(action); + + action = new QAction(tr("Move Tab left"), this); + action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(QKeySequence(tr("Ctrl+Shift+PgUp"))); + connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabLeft())); + viewMenu->addAction(action); + + action = new QAction(tr("Move Tab to next group"), this); + action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(QKeySequence(tr("Ctrl+Alt+PgDown"))); + connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabToNextGroup())); + viewMenu->addAction(action); + + action = new QAction(tr("Move Tab to previous group"), this); + action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(QKeySequence(tr("Ctrl+Alt+PgUp"))); + connect(action, SIGNAL(triggered()), dynamicGrid_, SLOT(moveCurrentTabToPreviousGroup())); + viewMenu->addAction(action); + } } void QtChatTabs::addTab(QtTabbable* tab) { - QSizePolicy policy = sizePolicy(); - /* Chat windows like to grow - don't let them */ - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - dynamicGrid_->addTab(tab, tab->windowTitle()); - connect(tab, SIGNAL(titleUpdated()), this, SLOT(handleTabTitleUpdated()), Qt::UniqueConnection); - connect(tab, SIGNAL(countUpdated()), this, SLOT(handleTabTitleUpdated()), Qt::UniqueConnection); - connect(tab, SIGNAL(windowClosing()), this, SLOT(handleTabClosing()), Qt::UniqueConnection); - connect(tab, SIGNAL(windowOpening()), this, SLOT(handleWidgetShown()), Qt::UniqueConnection); - connect(tab, SIGNAL(wantsToActivate()), this, SLOT(handleWantsToActivate()), Qt::UniqueConnection); - connect(tab, SIGNAL(requestNextTab()), this, SLOT(handleRequestedNextTab()), Qt::UniqueConnection); - connect(tab, SIGNAL(requestActiveTab()), this, SLOT(handleRequestedActiveTab()), Qt::UniqueConnection); - connect(tab, SIGNAL(requestPreviousTab()), this, SLOT(handleRequestedPreviousTab()), Qt::UniqueConnection); - connect(tab, SIGNAL(requestFlash()), this, SLOT(flash()), Qt::UniqueConnection); - setSizePolicy(policy); + QSizePolicy policy = sizePolicy(); + /* Chat windows like to grow - don't let them */ + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + dynamicGrid_->addTab(tab, tab->windowTitle()); + connect(tab, SIGNAL(titleUpdated()), this, SLOT(handleTabTitleUpdated()), Qt::UniqueConnection); + connect(tab, SIGNAL(countUpdated()), this, SLOT(handleTabTitleUpdated()), Qt::UniqueConnection); + connect(tab, SIGNAL(windowClosing()), this, SLOT(handleTabClosing()), Qt::UniqueConnection); + connect(tab, SIGNAL(windowOpening()), this, SLOT(handleWidgetShown()), Qt::UniqueConnection); + connect(tab, SIGNAL(wantsToActivate()), this, SLOT(handleWantsToActivate()), Qt::UniqueConnection); + connect(tab, SIGNAL(requestNextTab()), this, SLOT(handleRequestedNextTab()), Qt::UniqueConnection); + connect(tab, SIGNAL(requestActiveTab()), this, SLOT(handleRequestedActiveTab()), Qt::UniqueConnection); + connect(tab, SIGNAL(requestPreviousTab()), this, SLOT(handleRequestedPreviousTab()), Qt::UniqueConnection); + connect(tab, SIGNAL(requestFlash()), this, SLOT(flash()), Qt::UniqueConnection); + setSizePolicy(policy); } void QtChatTabs::handleWidgetShown() { - QtTabbable* widget = qobject_cast<QtTabbable*>(sender()); - if (!widget) { - return; - } - checkForFirstShow(); - if (dynamicGrid_->indexOf(widget) >= 0) { - handleTabTitleUpdated(widget); - return; - } - widget->blockSignals(true); - addTab(widget); - widget->blockSignals(false); - show(); + QtTabbable* widget = qobject_cast<QtTabbable*>(sender()); + if (!widget) { + return; + } + checkForFirstShow(); + if (dynamicGrid_->indexOf(widget) >= 0) { + handleTabTitleUpdated(widget); + return; + } + widget->blockSignals(true); + addTab(widget); + widget->blockSignals(false); + show(); } void QtChatTabs::handleCurrentTabIndexChanged(int newIndex) { - handleTabTitleUpdated(dynamicGrid_->widget(newIndex)); + handleTabTitleUpdated(dynamicGrid_->widget(newIndex)); } void QtChatTabs::handleWantsToActivate() { - QtTabbable* widget = qobject_cast<QtTabbable*>(sender()); - Q_ASSERT(widget); - //Un-minimize and bring to front. - setWindowState(windowState() & ~Qt::WindowMinimized); - setWindowState(windowState() | Qt::WindowActive); - show(); - widget->show(); - dynamicGrid_->setCurrentWidget(widget); - handleTabTitleUpdated(widget); - widget->setFocus(); - raise(); - activateWindow(); + QtTabbable* widget = qobject_cast<QtTabbable*>(sender()); + Q_ASSERT(widget); + //Un-minimize and bring to front. + setWindowState(windowState() & ~Qt::WindowMinimized); + setWindowState(windowState() | Qt::WindowActive); + show(); + widget->show(); + dynamicGrid_->setCurrentWidget(widget); + handleTabTitleUpdated(widget); + widget->setFocus(); + raise(); + activateWindow(); } void QtChatTabs::handleTabClosing() { - QWidget* widget = qobject_cast<QWidget*>(sender()); - int index; - if (widget && ((index = dynamicGrid_->indexOf(widget)) >= 0)) { - dynamicGrid_->removeTab(index); - if (dynamicGrid_->count() == 0) { - if (!singleWindow_) { - hide(); - } - else { - setWindowTitle(""); - onTitleChanged(""); - } - } - else { - handleTabTitleUpdated(dynamicGrid_->currentWidget()); - } - } + QWidget* widget = qobject_cast<QWidget*>(sender()); + int index; + if (widget && ((index = dynamicGrid_->indexOf(widget)) >= 0)) { + dynamicGrid_->removeTab(index); + if (dynamicGrid_->count() == 0) { + if (!singleWindow_) { + hide(); + } + else { + setWindowTitle(""); + onTitleChanged(""); + } + } + else { + handleTabTitleUpdated(dynamicGrid_->currentWidget()); + } + } } void QtChatTabs::handleRequestedPreviousTab() { - int newIndex = dynamicGrid_->currentIndex() - 1; - dynamicGrid_->setCurrentIndex(newIndex >= 0 ? newIndex : dynamicGrid_->count() - 1); + int newIndex = dynamicGrid_->currentIndex() - 1; + dynamicGrid_->setCurrentIndex(newIndex >= 0 ? newIndex : dynamicGrid_->count() - 1); } void QtChatTabs::handleRequestedNextTab() { - int newIndex = dynamicGrid_->currentIndex() + 1; - dynamicGrid_->setCurrentIndex(newIndex < dynamicGrid_->count() ? newIndex : 0); + int newIndex = dynamicGrid_->currentIndex() + 1; + dynamicGrid_->setCurrentIndex(newIndex < dynamicGrid_->count() ? newIndex : 0); } void QtChatTabs::handleRequestedActiveTab() { - QtTabbable::AlertType types[] = {QtTabbable::WaitingActivity, QtTabbable::ImpendingActivity}; - bool finished = false; - for (int j = 0; j < 2; j++) { - bool looped = false; - for (int i = dynamicGrid_->currentIndex() + 1; !finished && i != dynamicGrid_->currentIndex(); i++) { - if (i >= dynamicGrid_->count()) { - if (looped) { - break; - } - looped = true; - i = 0; - } - if (qobject_cast<QtTabbable*>(dynamicGrid_->widget(i))->getWidgetAlertState() == types[j]) { - dynamicGrid_->setCurrentIndex(i); - finished = true; - break; - } - } - } + QtTabbable::AlertType types[] = {QtTabbable::WaitingActivity, QtTabbable::ImpendingActivity}; + bool finished = false; + for (auto& type : types) { + bool looped = false; + for (int i = dynamicGrid_->currentIndex() + 1; !finished && i != dynamicGrid_->currentIndex(); i++) { + if (i >= dynamicGrid_->count()) { + if (looped) { + break; + } + looped = true; + i = 0; + } + if (qobject_cast<QtTabbable*>(dynamicGrid_->widget(i))->getWidgetAlertState() == type) { + dynamicGrid_->setCurrentIndex(i); + finished = true; + break; + } + } + } } void QtChatTabs::handleCloseTabShortcut() { - QWidget* currentWidget = dynamicGrid_->currentWidget(); - if (currentWidget) { - currentWidget->close(); - } + QWidget* currentWidget = dynamicGrid_->currentWidget(); + if (currentWidget) { + currentWidget->close(); + } } void QtChatTabs::handleTabCloseRequested(int index) { - if (trellisMode_) { - storeTabPositions(); - } - - assert(index < dynamicGrid_->count()); - QWidget* widget = dynamicGrid_->widget(index); - assert(widget); - widget->close(); + if (trellisMode_) { + storeTabPositions(); + } + + assert(index < dynamicGrid_->count()); + QWidget* widget = dynamicGrid_->widget(index); + assert(widget); + widget->close(); } void QtChatTabs::handleTabTitleUpdated() { - QWidget* widget = qobject_cast<QWidget*>(sender()); - handleTabTitleUpdated(widget); + QWidget* widget = qobject_cast<QWidget*>(sender()); + handleTabTitleUpdated(widget); } void QtChatTabs::handleTabTitleUpdated(QWidget* widget) { - if (!widget) { - return; - } - QtTabbable* tabbable = qobject_cast<QtTabbable*>(widget); - int index = dynamicGrid_->indexOf(widget); - if (index < 0) { - return; - } - - QString tabText = tabbable->windowTitle().simplified(); - // look for spectrum-generated and other long JID localparts, and - // try to abbreviate the resulting long tab texts - QRegExp hasTrailingGarbage("^(.[-\\w\\s,&]+)([^\\s\\,w].*)$"); - if (hasTrailingGarbage.exactMatch(tabText) && - hasTrailingGarbage.cap(1).simplified().length() >= 2 && - hasTrailingGarbage.cap(2).length() >= 7) { - // there may be some trailing garbage, and it's long - // enough to be worth removing, and we'd leave at - // least a couple of characters. - tabText = hasTrailingGarbage.cap(1).simplified(); - } - // QTabBar interprets &, so escape that - tabText.replace("&", "&&"); - // see which alt[a-z] keys other tabs use - bool accelsTaken[26]; - int i = 0; - while (i < 26) { - accelsTaken[i] = (i == 0); //A is used for 'switch to active tab' - i++; - } - - int other = dynamicGrid_->count(); - while (other >= 0) { - other--; - if (other != index) { - int tabIndex = -1; - QtTabWidget* tabWidget = dynamicGrid_->indexToTabWidget(other, tabIndex); - QString t = tabWidget->tabBar()->tabText(tabIndex).toLower(); - int r = t.indexOf('&'); - if (r >= 0 && t[r+1] >= 'a' && t[r+1] <= 'z') { - accelsTaken[t[r+1].unicode()-'a'] = true; - } - } - } - // then look to see which letters in tabText may be used - i = 0; - int accelPos = -1; - while (i < tabText.length() && accelPos < 0) { - if (tabText[i] >= 'A' && tabText[i] <= 'Z' && - !accelsTaken[tabText[i].unicode()-'A']) { - accelPos = i; - } - if (tabText[i] >= 'a' && tabText[i] <= 'z' && - !accelsTaken[tabText[i].unicode()-'a']) { - accelPos = i; - } - ++i; - } - if (accelPos >= 0) { - tabText = tabText.mid(0, accelPos) + "&" + tabText.mid(accelPos); - } - // this could be improved on some european keyboards, such as - // the German one (where alt-Sz-Ligature is available) and basically - // doesn't work on Arabic/Indic keyboards (where Latin letters - // aren't available), but I don't care to deal with those. - - int tabIndex = -1; - QtTabWidget* tabWidget = dynamicGrid_->indexToTabWidget(index, tabIndex); - tabWidget->setTabText(tabIndex, tabbable->getCount() > 0 ? QString("(%1) %2").arg(tabbable->getCount()).arg(tabText) : tabText); - QColor tabTextColor; - switch (tabbable->getWidgetAlertState()) { - case QtTabbable::WaitingActivity : tabTextColor = QColor(217, 20, 43); break; - case QtTabbable::ImpendingActivity : tabTextColor = QColor(27, 171, 32); break; - case QtTabbable::NoActivity : tabTextColor = QColor(); break; - } - tabWidget->tabBar()->setTabTextColor(tabIndex, tabTextColor); - - std::vector<std::pair<std::string, int> > unreads; - for (int i = 0; i < dynamicGrid_->count(); i++) { - QtTabbable* tab = qobject_cast<QtTabbable*>(dynamicGrid_->widget(i)); - if (tab) { - unreads.push_back(std::pair<std::string, int>(Q2PSTRING(tab->windowTitle()), tab->getCount())); - } - } - - std::string current(Q2PSTRING(qobject_cast<QtTabbable*>(dynamicGrid_->currentWidget())->windowTitle())); - ChatMessageSummarizer summary; - QString title = summary.getSummary(current, unreads).c_str(); - setWindowTitle(title); - emit onTitleChanged(title); + if (!widget) { + return; + } + QtTabbable* tabbable = qobject_cast<QtTabbable*>(widget); + int index = dynamicGrid_->indexOf(widget); + if (index < 0) { + return; + } + + QString tabText = tabbable->windowTitle().simplified(); + // look for spectrum-generated and other long JID localparts, and + // try to abbreviate the resulting long tab texts + QRegExp hasTrailingGarbage("^(.[-\\w\\s,&]+)([^\\s\\,w].*)$"); + if (hasTrailingGarbage.exactMatch(tabText) && + hasTrailingGarbage.cap(1).simplified().length() >= 2 && + hasTrailingGarbage.cap(2).length() >= 7) { + // there may be some trailing garbage, and it's long + // enough to be worth removing, and we'd leave at + // least a couple of characters. + tabText = hasTrailingGarbage.cap(1).simplified(); + } + // QTabBar interprets &, so escape that + tabText.replace("&", "&&"); + // see which alt[a-z] keys other tabs use + bool accelsTaken[26]; + int i = 0; + while (i < 26) { + accelsTaken[i] = (i == 0); //A is used for 'switch to active tab' + i++; + } + + int other = dynamicGrid_->count(); + while (other >= 0) { + other--; + if (other != index) { + int tabIndex = -1; + QtTabWidget* tabWidget = dynamicGrid_->indexToTabWidget(other, tabIndex); + QString t = tabWidget->tabBar()->tabText(tabIndex).toLower(); + int r = t.indexOf('&'); + if (r >= 0 && t[r+1] >= 'a' && t[r+1] <= 'z') { + accelsTaken[t[r+1].unicode()-'a'] = true; + } + } + } + // then look to see which letters in tabText may be used + i = 0; + int accelPos = -1; + while (i < tabText.length() && accelPos < 0) { + if (tabText[i] >= 'A' && tabText[i] <= 'Z' && + !accelsTaken[tabText[i].unicode()-'A']) { + accelPos = i; + } + if (tabText[i] >= 'a' && tabText[i] <= 'z' && + !accelsTaken[tabText[i].unicode()-'a']) { + accelPos = i; + } + ++i; + } + if (accelPos >= 0) { + tabText = tabText.mid(0, accelPos) + "&" + tabText.mid(accelPos); + } + // this could be improved on some european keyboards, such as + // the German one (where alt-Sz-Ligature is available) and basically + // doesn't work on Arabic/Indic keyboards (where Latin letters + // aren't available), but I don't care to deal with those. + + int tabIndex = -1; + QtTabWidget* tabWidget = dynamicGrid_->indexToTabWidget(index, tabIndex); + tabWidget->setTabText(tabIndex, tabbable->getCount() > 0 ? QString("(%1) %2").arg(tabbable->getCount()).arg(tabText) : tabText); + QColor tabTextColor; + switch (tabbable->getWidgetAlertState()) { + case QtTabbable::WaitingActivity : tabTextColor = QColor(217, 20, 43); break; + case QtTabbable::ImpendingActivity : tabTextColor = QColor(27, 171, 32); break; + case QtTabbable::NoActivity : tabTextColor = QColor(); break; + } + tabWidget->tabBar()->setTabTextColor(tabIndex, tabTextColor); + + std::vector<std::pair<std::string, int> > unreads; + for (int i = 0; i < dynamicGrid_->count(); i++) { + QtTabbable* tab = qobject_cast<QtTabbable*>(dynamicGrid_->widget(i)); + if (tab) { + unreads.push_back(std::pair<std::string, int>(Q2PSTRING(tab->windowTitle()), tab->getCount())); + } + } + + std::string current(Q2PSTRING(qobject_cast<QtTabbable*>(dynamicGrid_->currentWidget())->windowTitle())); + ChatMessageSummarizer summary; + QString title = summary.getSummary(current, unreads).c_str(); + setWindowTitle(title); + emit onTitleChanged(title); } void QtChatTabs::flash() { #ifndef SWIFTEN_PLATFORM_MACOSX - QApplication::alert(this, 0); + QApplication::alert(this, 0); #endif } void QtChatTabs::handleOpenLayoutChangeDialog() { - disconnect(gridSelectionDialog_, SIGNAL(currentGridSizeChanged(QSize)), dynamicGrid_, SLOT(setDimensions(QSize))); - gridSelectionDialog_->setCurrentGridSize(dynamicGrid_->getDimension()); - gridSelectionDialog_->move(QCursor::pos()); - connect(gridSelectionDialog_, SIGNAL(currentGridSizeChanged(QSize)), dynamicGrid_, SLOT(setDimensions(QSize))); - gridSelectionDialog_->show(); + disconnect(gridSelectionDialog_, SIGNAL(currentGridSizeChanged(QSize)), dynamicGrid_, SLOT(setDimensions(QSize))); + gridSelectionDialog_->setCurrentGridSize(dynamicGrid_->getDimension()); + gridSelectionDialog_->move(QCursor::pos()); + connect(gridSelectionDialog_, SIGNAL(currentGridSizeChanged(QSize)), dynamicGrid_, SLOT(setDimensions(QSize))); + gridSelectionDialog_->show(); } void QtChatTabs::storeTabPositions() { - // save size - QByteArray gridSizeData; - QDataStream dataStreamGridSize(&gridSizeData, QIODevice::ReadWrite); - dataStreamGridSize << dynamicGrid_->getDimension(); - settingsProvider_->storeSetting(SettingConstants::TRELLIS_GRID_SIZE, Q2PSTRING(QString(gridSizeData.toBase64()))); - - // save positions - QByteArray tabPositionsData; - QDataStream dataStreamTabPositions(&tabPositionsData, QIODevice::ReadWrite); - dynamicGrid_->updateTabPositions(); - dataStreamTabPositions << dynamicGrid_->getTabPositions(); - settingsProvider_->storeSetting(SettingConstants::TRELLIS_GRID_POSITIONS, Q2PSTRING(QString(tabPositionsData.toBase64()))); + // save size + QByteArray gridSizeData; + QDataStream dataStreamGridSize(&gridSizeData, QIODevice::ReadWrite); + dataStreamGridSize << dynamicGrid_->getDimension(); + settingsProvider_->storeSetting(QtUISettingConstants::TRELLIS_GRID_SIZE, Q2PSTRING(QString(gridSizeData.toBase64()))); + + // save positions + QByteArray tabPositionsData; + QDataStream dataStreamTabPositions(&tabPositionsData, QIODevice::ReadWrite); + dynamicGrid_->updateTabPositions(); + dataStreamTabPositions << dynamicGrid_->getTabPositions(); + settingsProvider_->storeSetting(QtUISettingConstants::TRELLIS_GRID_POSITIONS, Q2PSTRING(QString(tabPositionsData.toBase64()))); } void QtChatTabs::resizeEvent(QResizeEvent*) { - emit geometryChanged(); + emit geometryChanged(); } void QtChatTabs::moveEvent(QMoveEvent*) { - emit geometryChanged(); + emit geometryChanged(); } void QtChatTabs::checkForFirstShow() { - if (!isVisible()) { + if (!isVisible()) { #ifndef Q_OS_MAC - showMinimized(); + showMinimized(); #else - /* https://bugreports.qt-project.org/browse/QTBUG-19194 - * ^ When the above is fixed we can swap the below for just show(); - * WA_ShowWithoutActivating seems to helpfully not work, so... */ - - QWidget* currentWindow = QApplication::activeWindow(); /* Remember who had focus if we're the current application*/ - show(); - QCoreApplication::processEvents(); /* Run through the eventloop to clear the show() */ - if (currentWindow) { - currentWindow->activateWindow(); /* Set focus back */ - } + /* https://bugreports.qt-project.org/browse/QTBUG-19194 + * ^ When the above is fixed we can swap the below for just show(); + * WA_ShowWithoutActivating seems to helpfully not work, so... */ + + QWidget* currentWindow = QApplication::activeWindow(); /* Remember who had focus if we're the current application*/ + show(); + QCoreApplication::processEvents(); /* Run through the eventloop to clear the show() */ + if (currentWindow) { + currentWindow->activateWindow(); /* Set focus back */ + } #endif - } + } } } |