From 4feb5e9e8844bc68e13d5119f4749e39fdec0ccc Mon Sep 17 00:00:00 2001
From: Arnt Gulbrandsen <arnt@gulbrandsen.priv.no>
Date: Thu, 6 Jan 2011 15:53:07 +0100
Subject: Add keyboard accelerators for tabs (alt-s to switch to the swift
 room, etc).

Handle window titles that happen to contain the '&' character correctly.

Abbreviate the tab bars generated from some long JID localparts
(e.g. #foo%irc.ma.us.example.org@irc.spectrum.example.net).

License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php

My future patches are also BSD-licensed, unless I explicitly note
a different license in that patch.

diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp
index de3b6ed..3493ba7 100644
--- a/Swift/QtUI/QtChatTabs.cpp
+++ b/Swift/QtUI/QtChatTabs.cpp
@@ -168,22 +168,75 @@ void QtChatTabs::handleTabTitleUpdated(QWidget* widget) {
 	if (index < 0) {
 		return;
 	}
-	tabs_->setTabText(index, tabbable->getCount() > 0 ? QString("(%1) %2").arg(tabbable->getCount()).arg(tabbable->windowTitle()) : tabbable->windowTitle());
+
+	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++] = false;
+	int other = tabs_->tabBar()->count();
+	while (other >= 0) {
+		other--;
+		if ( other != index ) {
+			QString t = tabs_->tabBar()->tabText(other).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-� 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.
+
+	tabs_->setTabText(index, 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;
 	default : tabTextColor = QColor();
 	}
-	tabs_->tabBar()->setTabTextColor(index, tabTextColor); 
+	tabs_->tabBar()->setTabTextColor(index, tabTextColor);
 	int unread = 0;
 	for (int i = 0; i < tabs_->count(); i++) {
 		QtTabbable* tab = qobject_cast<QtTabbable*>(tabs_->widget(i));
 		if (tab) {
-			unread += tab->getCount(); 
+			unread += tab->getCount();
 		}
 	}
-	
+
 	QtTabbable* current = qobject_cast<QtTabbable*>(tabs_->currentWidget());
 	setWindowTitle(unread > 0 ? QString("(%1) %2").arg(unread).arg(current->windowTitle()) : current->windowTitle());
 }
@@ -199,7 +252,7 @@ void QtChatTabs::resizeEvent(QResizeEvent*) {
 }
 
 void QtChatTabs::moveEvent(QMoveEvent*) {
-	emit geometryChanged();	
+	emit geometryChanged();
 }
 
 void QtChatTabs::checkForFirstShow() {
-- 
cgit v0.10.2-6-g49f6