summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/QtUI/QtChatWindow.cpp24
-rw-r--r--Swift/QtUI/QtChatWindow.h3
-rw-r--r--Swift/QtUI/QtTextEdit.cpp22
-rw-r--r--Swift/QtUI/QtTextEdit.h16
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.cpp60
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.h3
6 files changed, 95 insertions, 33 deletions
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 0b9b1af..ffcbf15 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -143,6 +143,8 @@ QtChatWindow::QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventSt
inputBarLayout->addWidget(correctingLabel_);
correctingLabel_->hide();
+ connect(input_, SIGNAL(receivedFocus()), this, SLOT(handleTextInputReceivedFocus()));
+ connect(input_, SIGNAL(lostFocus()), this, SLOT(handleTextInputLostFocus()));
QPushButton* emoticonsButton_ = new QPushButton(this);
emoticonsButton_->setIcon(QIcon(":/emoticons/smile.png"));
connect(emoticonsButton_, SIGNAL(clicked()), this, SLOT(handleEmoticonsButtonClicked()));
@@ -171,7 +173,6 @@ QtChatWindow::QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventSt
logRosterSplitter_->setFocusProxy(input_);
midBar_->setFocusProxy(input_);
messageLog_->setFocusProxy(input_);
- connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(qAppFocusChanged(QWidget*, QWidget*)));
connect(messageLog_, SIGNAL(gotFocus()), input_, SLOT(setFocus()));
resize(400,300);
connect(messageLog_, SIGNAL(fontResized(int)), this, SIGNAL(fontResized(int)));
@@ -458,17 +459,6 @@ void QtChatWindow::convertToMUC(MUCType mucType) {
subject_->setVisible(!impromptu_);
}
-void QtChatWindow::qAppFocusChanged(QWidget* /*old*/, QWidget* now) {
- if (now && isWidgetSelected()) {
- lastLineTracker_.setHasFocus(true);
- input_->setFocus();
- onAllMessagesRead();
- }
- else {
- lastLineTracker_.setHasFocus(false);
- }
-}
-
void QtChatWindow::setOnline(bool online) {
isOnline_ = online;
if (!online) {
@@ -657,6 +647,16 @@ void QtChatWindow::handleEmoticonClicked(QString emoticonAsText) {
input_->textCursor().insertText(emoticonAsText);
}
+void QtChatWindow::handleTextInputReceivedFocus() {
+ lastLineTracker_.setHasFocus(true);
+ input_->setFocus();
+ onAllMessagesRead();
+}
+
+void QtChatWindow::handleTextInputLostFocus() {
+ lastLineTracker_.setHasFocus(false);
+}
+
void QtChatWindow::handleActionButtonClicked() {
QMenu contextMenu;
QAction* changeSubject = NULL;
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 06c6064..19046c9 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -149,7 +149,6 @@ namespace Swift {
void fontResized(int);
protected slots:
- void qAppFocusChanged(QWidget* old, QWidget* now);
void closeEvent(QCloseEvent* event);
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
@@ -173,6 +172,8 @@ namespace Swift {
void handleCurrentLabelChanged(int);
void handleEmoticonsButtonClicked();
void handleEmoticonClicked(QString emoticonAsText);
+ void handleTextInputReceivedFocus();
+ void handleTextInputLostFocus();
private:
void updateTitleWithUnreadCount();
diff --git a/Swift/QtUI/QtTextEdit.cpp b/Swift/QtUI/QtTextEdit.cpp
index a381cbe..fed8819 100644
--- a/Swift/QtUI/QtTextEdit.cpp
+++ b/Swift/QtUI/QtTextEdit.cpp
@@ -1,28 +1,28 @@
/*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swift/QtUI/QtTextEdit.h>
-#include <boost/tuple/tuple.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
#include <QApplication>
#include <QFontMetrics>
#include <QKeyEvent>
-#include <QDebug>
#include <QMenu>
+#include <QTime>
#include <Swiften/Base/foreach.h>
-#include <SwifTools/SpellCheckerFactory.h>
-#include <SwifTools/SpellChecker.h>
-
#include <Swift/Controllers/SettingConstants.h>
+#include <SwifTools/SpellChecker.h>
+#include <SwifTools/SpellCheckerFactory.h>
+
#include <Swift/QtUI/QtSpellCheckerWindow.h>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtUtilities.h>
@@ -75,6 +75,16 @@ void QtTextEdit::keyPressEvent(QKeyEvent* event) {
}
}
+void QtTextEdit::focusInEvent(QFocusEvent* event) {
+ receivedFocus();
+ QTextEdit::focusInEvent(event);
+}
+
+void QtTextEdit::focusOutEvent(QFocusEvent* event) {
+ lostFocus();
+ QTextEdit::focusOutEvent(event);
+}
+
void QtTextEdit::handleTextChanged() {
QSize previous(maximumSize());
setMaximumSize(QSize(maximumWidth(), sizeHint().height()));
diff --git a/Swift/QtUI/QtTextEdit.h b/Swift/QtUI/QtTextEdit.h
index 5b645ba..67826ba 100644
--- a/Swift/QtUI/QtTextEdit.h
+++ b/Swift/QtUI/QtTextEdit.h
@@ -1,20 +1,20 @@
/*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
-#include <SwifTools/SpellParser.h>
+#include <QPointer>
+#include <QTextEdit>
-#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <Swift/Controllers/SettingConstants.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
-#include <Swift/QtUI/QtSpellCheckHighlighter.h>
+#include <SwifTools/SpellParser.h>
-#include <QTextEdit>
-#include <QPointer>
+#include <Swift/QtUI/QtSpellCheckHighlighter.h>
namespace Swift {
class SpellChecker;
@@ -31,12 +31,16 @@ namespace Swift {
void wordCorrected(QString& word);
void returnPressed();
void unhandledKeyPressEvent(QKeyEvent* event);
+ void receivedFocus();
+ void lostFocus();
public slots:
void handleSettingChanged(const std::string& settings);
protected:
virtual void keyPressEvent(QKeyEvent* event);
+ virtual void focusInEvent(QFocusEvent* event);
+ virtual void focusOutEvent(QFocusEvent* event);
virtual void contextMenuEvent(QContextMenuEvent* event);
private slots:
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
index cc3208b..e2b6e27 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
@@ -10,18 +10,20 @@
#include <QApplication>
#include <QEvent>
-#include <QLayoutItem>
#include <QGridLayout>
+#include <QLayoutItem>
#include <QtDebug>
+#include <Swiften/Base/Log.h>
+
#include <Swift/QtUI/QtSwiftUtil.h>
-#include <Swift/QtUI/QtTabbable.h>
#include <Swift/QtUI/QtTabWidget.h>
+#include <Swift/QtUI/QtTabbable.h>
#include <Swift/QtUI/Trellis/QtDNDTabBar.h>
namespace Swift {
-QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND) {
+QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(NULL) {
gridLayout_ = new QGridLayout(this);
setContentsMargins(0,0,0,0);
setDimensions(QSize(1,1));
@@ -107,6 +109,10 @@ int QtDynamicGridLayout::indexOf(const QWidget* widget) const {
}
void QtDynamicGridLayout::handleApplicationFocusChanged(QWidget*, QWidget* newFocus) {
+ if (movingTab_) {
+ return;
+ }
+
if (newFocus) {
if (isAncestorOf(newFocus)) {
QtTabbable *newTab = dynamic_cast<QtTabbable*>(newFocus->parentWidget());
@@ -142,6 +148,29 @@ void QtDynamicGridLayout::removeTab(int index) {
}
}
+/**
+ * This event filter serves the purpose of filtering out all QEvent::Show events targeted at
+ * all widgets excepts the currently moving widget.
+ * It is required because of the way Qt internally implements the QTabBar::moveTab method.
+ * It does not move the actual tab in the underlying structure, but instead removes it from
+ * a stacked layout and later adds it again.
+ * Both the remove and insert produce a lot signal emission and focus changes. Most of which
+ * the application MUST NOT react on because of the QTabBar and the corresponding QTabWidget
+ * being out of sync in an inconsistent state.
+ */
+bool QtDynamicGridLayout::eventFilter(QObject* object, QEvent* event) {
+ QtTabbable* tab = qobject_cast<QtTabbable*>(object);
+ if (!tab) {
+ return false;
+ }
+ if (tab && (tab != movingTab_)) {
+ if (event->type() == QEvent::Show) {
+ return true;
+ }
+ }
+ return false;
+}
+
QWidget* QtDynamicGridLayout::currentWidget() const {
QWidget* current = NULL;
current = focusWidget();
@@ -394,6 +423,10 @@ void QtDynamicGridLayout::handleTabCloseRequested(int index) {
}
void QtDynamicGridLayout::handleTabCurrentChanged(int index) {
+ if (movingTab_) {
+ return;
+ }
+
if (index >= 0) {
QTabWidget* sendingTabWidget = dynamic_cast<QTabWidget*>(sender());
assert(sendingTabWidget);
@@ -417,14 +450,25 @@ void QtDynamicGridLayout::updateTabPositions() {
}
void QtDynamicGridLayout::moveTab(QtTabWidget* tabWidget, int oldIndex, int newIndex) {
- tabWidget->widget(oldIndex)->blockSignals(true);
- tabWidget->widget(newIndex)->blockSignals(true);
#if QT_VERSION >= 0x040500
- tabWidget->tabBar()->moveTab(oldIndex, newIndex);
+ SWIFT_LOG_ASSERT(movingTab_ == NULL, error) << std::endl;
+ movingTab_ = qobject_cast<QtTabbable*>(tabWidget->widget(oldIndex));
+ SWIFT_LOG_ASSERT(movingTab_ != NULL, error) << std::endl;
+
+ if (movingTab_) {
+ // Install event filter that filters out events issued during the internal movement of the
+ // tab but not targeted at the moving tab.
+ qApp->installEventFilter(this);
+
+ tabWidget->tabBar()->moveTab(oldIndex, newIndex);
+
+ qApp->removeEventFilter(this);
+ SWIFT_LOG_ASSERT(movingTab_ == tabWidget->widget(newIndex), error) << std::endl;
+ }
+ movingTab_ = NULL;
+ tabWidget->widget(newIndex)->setFocus();
#else
#warning Qt 4.5 or later is needed. Trying anyway, some things will be disabled.
- tabWidget->widget(oldIndex)->blockSignals(false);
- tabWidget->widget(newIndex)->blockSignals(false);
#endif
}
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.h b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
index 616ee5e..ed8a9fc 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.h
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
@@ -45,6 +45,8 @@ namespace Swift {
QHash<QString, QPoint> getTabPositions() const;
void setTabPositions(const QHash<QString, QPoint> positions);
+ bool eventFilter(QObject* object, QEvent* event);
+
signals:
void tabCloseRequested(int index);
void onCurrentIndexChanged(int newIndex);
@@ -73,5 +75,6 @@ namespace Swift {
QGridLayout *gridLayout_;
bool dndEnabled_;
QHash<QString, QPoint> tabPositions_;
+ QtTabbable* movingTab_;
};
}