diff options
27 files changed, 183 insertions, 65 deletions
diff --git a/Swift/QtUI/ChatList/ChatListDelegate.cpp b/Swift/QtUI/ChatList/ChatListDelegate.cpp index 29dba62..bcd1585 100644 --- a/Swift/QtUI/ChatList/ChatListDelegate.cpp +++ b/Swift/QtUI/ChatList/ChatListDelegate.cpp @@ -1,68 +1,72 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <QPen> #include <QPainter> #include "Swift/QtUI/ChatList/ChatListDelegate.h" #include "Swift/QtUI/Roster/GroupItemDelegate.h" #include "Swift/QtUI/ChatList/ChatListItem.h" #include "Swift/QtUI/ChatList/ChatListMUCItem.h" #include "Swift/QtUI/ChatList/ChatListRecentItem.h" #include "Swift/QtUI/ChatList/ChatListGroupItem.h" namespace Swift { -ChatListDelegate::ChatListDelegate() { +ChatListDelegate::ChatListDelegate(bool compact) : compact_(compact) { groupDelegate_ = new GroupItemDelegate(); } ChatListDelegate::~ChatListDelegate() { delete groupDelegate_; } +void ChatListDelegate::setCompact(bool compact) { + compact_ = compact; +} + QSize ChatListDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { ChatListItem* item = static_cast<ChatListItem*>(index.internalPointer()); if (item && dynamic_cast<ChatListMUCItem*>(item)) { return mucSizeHint(option, index); } else if (item && dynamic_cast<ChatListRecentItem*>(item)) { - return common_.contactSizeHint(option, index); + return common_.contactSizeHint(option, index, compact_); } else if (item && dynamic_cast<ChatListGroupItem*>(item)) { return groupDelegate_->sizeHint(option, index); } return QStyledItemDelegate::sizeHint(option, index); } QSize ChatListDelegate::mucSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const { QFontMetrics nameMetrics(common_.nameFont); QFontMetrics statusMetrics(common_.detailFont); int sizeByText = 2 * common_.verticalMargin + nameMetrics.height() + statusMetrics.height(); return QSize(150, sizeByText); } QSize ChatListDelegate::recentSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { return mucSizeHint(option, index); } void ChatListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { ChatListItem* item = static_cast<ChatListItem*>(index.internalPointer()); if (item && dynamic_cast<ChatListMUCItem*>(item)) { paintMUC(painter, option, dynamic_cast<ChatListMUCItem*>(item)); } else if (item && dynamic_cast<ChatListRecentItem*>(item)) { paintRecent(painter, option, dynamic_cast<ChatListRecentItem*>(item)); } else if (item && dynamic_cast<ChatListGroupItem*>(item)) { ChatListGroupItem* group = dynamic_cast<ChatListGroupItem*>(item); groupDelegate_->paint(painter, option, group->data(Qt::DisplayRole).toString(), group->rowCount(), option.state & QStyle::State_Open); } else { QStyledItemDelegate::paint(painter, option, index); } } @@ -77,39 +81,39 @@ void ChatListDelegate::paintMUC(QPainter* painter, const QStyleOptionViewItem& o painter->setPen(QPen(nameColor)); } QFontMetrics nameMetrics(common_.nameFont); painter->setFont(common_.nameFont); int extraFontWidth = nameMetrics.width("H"); int leftOffset = common_.horizontalMargin * 2 + extraFontWidth / 2; QRect textRegion(fullRegion.adjusted(leftOffset, 0, 0, 0)); int nameHeight = nameMetrics.height() + common_.verticalMargin; QRect nameRegion(textRegion.adjusted(0, common_.verticalMargin, 0, 0)); DelegateCommons::drawElidedText(painter, nameRegion, item->data(Qt::DisplayRole).toString()); painter->setFont(common_.detailFont); painter->setPen(QPen(QColor(160,160,160))); QRect detailRegion(textRegion.adjusted(0, nameHeight, 0, 0)); DelegateCommons::drawElidedText(painter, detailRegion, item->data(ChatListMUCItem::DetailTextRole).toString()); painter->restore(); } void ChatListDelegate::paintRecent(QPainter* painter, const QStyleOptionViewItem& option, ChatListRecentItem* item) const { QColor nameColor = item->data(Qt::TextColorRole).value<QColor>(); QString avatarPath; if (item->data(ChatListRecentItem::AvatarRole).isValid() && !item->data(ChatListRecentItem::AvatarRole).value<QString>().isNull()) { avatarPath = item->data(ChatListRecentItem::AvatarRole).value<QString>(); } QIcon presenceIcon = item->data(ChatListRecentItem::PresenceIconRole).isValid() && !item->data(ChatListRecentItem::PresenceIconRole).value<QIcon>().isNull() ? item->data(ChatListRecentItem::PresenceIconRole).value<QIcon>() : QIcon(":/icons/offline.png"); QString name = item->data(Qt::DisplayRole).toString(); //qDebug() << "Avatar for " << name << " = " << avatarPath; QString statusText = item->data(ChatListRecentItem::DetailTextRole).toString(); - common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, item->getChat().unreadCount); + common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, item->getChat().unreadCount, compact_); } } diff --git a/Swift/QtUI/ChatList/ChatListDelegate.h b/Swift/QtUI/ChatList/ChatListDelegate.h index a898df4..5ac45ce 100644 --- a/Swift/QtUI/ChatList/ChatListDelegate.h +++ b/Swift/QtUI/ChatList/ChatListDelegate.h @@ -1,33 +1,36 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QStyledItemDelegate> #include "Swift/QtUI/Roster/GroupItemDelegate.h" namespace Swift { class ChatListMUCItem; class ChatListRecentItem; class ChatListDelegate : public QStyledItemDelegate { public: - ChatListDelegate(); + ChatListDelegate(bool compact); ~ChatListDelegate(); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + public slots: + void setCompact(bool compact); private: void paintMUC(QPainter* painter, const QStyleOptionViewItem& option, ChatListMUCItem* item) const; void paintRecent(QPainter* painter, const QStyleOptionViewItem& option, ChatListRecentItem* item) const; QSize mucSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const; QSize recentSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const; + bool compact_; DelegateCommons common_; GroupItemDelegate* groupDelegate_; }; } diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp index e5c63f6..8de5720 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.cpp +++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp @@ -1,85 +1,93 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Swift/QtUI/ChatList/QtChatListWindow.h" #include <QMenu> #include <QContextMenuEvent> -#include "Swift/QtUI/ChatList/ChatListMUCItem.h" -#include "Swift/QtUI/ChatList/ChatListRecentItem.h" -#include "Swift/QtUI/QtAddBookmarkWindow.h" -#include "Swift/QtUI/QtEditBookmarkWindow.h" -#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" -#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" -#include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h" -#include "Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h" -#include "Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h" +#include <Swift/QtUI/ChatList/ChatListMUCItem.h> +#include <Swift/QtUI/ChatList/ChatListRecentItem.h> +#include <Swift/QtUI/QtAddBookmarkWindow.h> +#include <Swift/QtUI/QtEditBookmarkWindow.h> +#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> +#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> +#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h> +#include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h> +#include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h> +#include <Swift/QtUI/QtUIPreferences.h> namespace Swift { -QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, QWidget* parent) : QTreeView(parent) { +QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QTreeView(parent) { eventStream_ = uiEventStream; + uiPreferences_ = uiPreferences; bookmarksEnabled_ = false; model_ = new ChatListModel(); setModel(model_); - delegate_ = new ChatListDelegate(); + delegate_ = new ChatListDelegate(uiPreferences_->getCompactRosters()); setItemDelegate(delegate_); setHeaderHidden(true); #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif expandAll(); setAnimated(true); setIndentation(0); setRootIsDecorated(true); setupContextMenus(); connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&))); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&))); + connect(uiPreferences_, SIGNAL(onCompactRostersChanged(bool)), this, SLOT(handleCompactRostersToggled(bool))); } QtChatListWindow::~QtChatListWindow() { delete model_; delete delegate_; delete mucMenu_; delete emptyMenu_; } +void QtChatListWindow::handleCompactRostersToggled(bool compact) { + delegate_->setCompact(compact); + repaint(); +} + void QtChatListWindow::setBookmarksEnabled(bool enabled) { bookmarksEnabled_ = enabled; } void QtChatListWindow::handleClicked(const QModelIndex& index) { ChatListGroupItem* item = dynamic_cast<ChatListGroupItem*>(static_cast<ChatListItem*>(index.internalPointer())); if (item) { setExpanded(index, !isExpanded(index)); } } void QtChatListWindow::setupContextMenus() { mucMenu_ = new QMenu(); mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark())); mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark())); mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark())); emptyMenu_ = new QMenu(); emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark())); } void QtChatListWindow::handleItemActivated(const QModelIndex& index) { ChatListItem* item = model_->getItemForIndex(index); if (ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(item)) { if (bookmarksEnabled_) { onMUCBookmarkActivated(mucItem->getBookmark()); } } else if (ChatListRecentItem* recentItem = dynamic_cast<ChatListRecentItem*>(item)) { if (!recentItem->getChat().isMUC || bookmarksEnabled_) { onRecentActivated(recentItem->getChat()); } } } diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h index 8775c3e..af37015 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.h +++ b/Swift/QtUI/ChatList/QtChatListWindow.h @@ -1,53 +1,55 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QTreeView> #include "Swift/Controllers/UIInterfaces/ChatListWindow.h" #include "Swift/Controllers/UIEvents/UIEventStream.h" #include "Swift/QtUI/ChatList/ChatListModel.h" #include "Swift/QtUI/ChatList/ChatListDelegate.h" namespace Swift { - + class QtUIPreferences; class QtChatListWindow : public QTreeView, public ChatListWindow { Q_OBJECT public: - QtChatListWindow(UIEventStream *uiEventStream, QWidget* parent = NULL); + QtChatListWindow(UIEventStream *uiEventStream, QtUIPreferences* uiPreferences, QWidget* parent = NULL); virtual ~QtChatListWindow(); void addMUCBookmark(const MUCBookmark& bookmark); void removeMUCBookmark(const MUCBookmark& bookmark); void setBookmarksEnabled(bool enabled); void setRecents(const std::list<ChatListWindow::Chat>& recents); void setUnreadCount(int unread); void clearBookmarks(); signals: void onCountUpdated(int count); private slots: void handleItemActivated(const QModelIndex&); void handleAddBookmark(); void handleEditBookmark(); void handleRemoveBookmark(); void handleClicked(const QModelIndex& index); + void handleCompactRostersToggled(bool); protected: void contextMenuEvent(QContextMenuEvent* event); private: void setupContextMenus(); bool bookmarksEnabled_; UIEventStream* eventStream_; ChatListModel* model_; ChatListDelegate* delegate_; QMenu* mucMenu_; QMenu* emptyMenu_; ChatListItem* contextMenuItem_; + QtUIPreferences* uiPreferences_; }; } diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 8270175..f0f268d 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -13,134 +13,136 @@ #include "SwifTools/Linkify.h" #include "QtChatView.h" #include "MessageSnippet.h" #include "SystemMessageSnippet.h" #include "QtTextEdit.h" #include "QtSettingsProvider.h" #include "QtScaledAvatarCache.h" #include "SwifTools/TabComplete.h" #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include "QtFileTransferJSBridge.h" #include <boost/cstdint.hpp> #include <boost/format.hpp> #include <boost/lexical_cast.hpp> #include <QLabel> #include <QMessageBox> #include <QInputDialog> #include <QApplication> #include <QBoxLayout> #include <QCloseEvent> #include <QComboBox> #include <QFileInfo> #include <QLineEdit> #include <QSplitter> #include <QString> #include <QTextEdit> #include <QTime> #include <QUrl> #include <QPushButton> #include <QFileDialog> #include <QMenu> +#include <Swift/QtUI/QtUIPreferences.h> #include <QDebug> namespace Swift { -QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), previousMessageWasFileTransfer_(false), eventStream_(eventStream) { +QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, QtUIPreferences* uiPreferences) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), previousMessageWasFileTransfer_(false), eventStream_(eventStream) { + uiPreferences_ = uiPreferences; unreadCount_ = 0; idCounter_ = 0; inputEnabled_ = true; completer_ = NULL; affiliationEditor_ = NULL; theme_ = theme; isCorrection_ = false; correctionEnabled_ = Maybe; updateTitleWithUnreadCount(); QtSettingsProvider settings; #ifdef SWIFT_EXPERIMENTAL_FT setAcceptDrops(true); #endif alertStyleSheet_ = "background: rgb(255, 255, 153); color: black"; QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this); layout->setContentsMargins(0,0,0,0); layout->setSpacing(2); alertWidget_ = new QWidget(this); QHBoxLayout* alertLayout = new QHBoxLayout(alertWidget_); layout->addWidget(alertWidget_); alertLabel_ = new QLabel(this); alertLayout->addWidget(alertLabel_); alertButton_ = new QPushButton(this); connect (alertButton_, SIGNAL(clicked()), this, SLOT(handleAlertButtonClicked())); alertLayout->addWidget(alertButton_); QPalette palette = alertWidget_->palette(); palette.setColor(QPalette::Window, QColor(Qt::yellow)); palette.setColor(QPalette::WindowText, QColor(Qt::black)); alertWidget_->setStyleSheet(alertStyleSheet_); alertLabel_->setStyleSheet(alertStyleSheet_); alertWidget_->hide(); QBoxLayout* subjectLayout = new QBoxLayout(QBoxLayout::LeftToRight); subject_ = new QLineEdit(this); subjectLayout->addWidget(subject_); setSubject(""); subject_->setReadOnly(true); actionButton_ = new QPushButton(this); actionButton_->setIcon(QIcon(":/icons/actions.png")); connect(actionButton_, SIGNAL(clicked()), this, SLOT(handleActionButtonClicked())); subjectLayout->addWidget(actionButton_); subject_->hide(); actionButton_->hide(); layout->addLayout(subjectLayout); logRosterSplitter_ = new QSplitter(this); logRosterSplitter_->setAutoFillBackground(true); layout->addWidget(logRosterSplitter_); messageLog_ = new QtChatView(theme, this); logRosterSplitter_->addWidget(messageLog_); - treeWidget_ = new QtOccupantListWidget(eventStream_, this); + treeWidget_ = new QtOccupantListWidget(eventStream_, uiPreferences_, this); treeWidget_->hide(); logRosterSplitter_->addWidget(treeWidget_); logRosterSplitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(logRosterSplitter_, SIGNAL(splitterMoved(int, int)), this, SLOT(handleSplitterMoved(int, int))); QWidget* midBar = new QWidget(this); layout->addWidget(midBar); midBar->setAutoFillBackground(true); QHBoxLayout *midBarLayout = new QHBoxLayout(midBar); midBarLayout->setContentsMargins(0,0,0,0); midBarLayout->setSpacing(2); midBarLayout->addStretch(); labelsWidget_ = new QComboBox(this); labelsWidget_->setFocusPolicy(Qt::NoFocus); labelsWidget_->hide(); labelsWidget_->setSizeAdjustPolicy(QComboBox::AdjustToContents); midBarLayout->addWidget(labelsWidget_,0); QHBoxLayout* inputBarLayout = new QHBoxLayout(); inputBarLayout->setContentsMargins(0,0,0,0); inputBarLayout->setSpacing(2); input_ = new QtTextEdit(this); input_->setAcceptRichText(false); inputBarLayout->addWidget(input_); correctingLabel_ = new QLabel(tr("Correcting"), this); inputBarLayout->addWidget(correctingLabel_); correctingLabel_->hide(); layout->addLayout(inputBarLayout); inputClearing_ = false; contactIsTyping_ = false; connect(input_, SIGNAL(unhandledKeyPressEvent(QKeyEvent*)), this, SLOT(handleKeyPressEvent(QKeyEvent*))); connect(input_, SIGNAL(returnPressed()), this, SLOT(returnPressed())); diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 0c64f02..233f2bc 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -1,73 +1,75 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <Swift/Controllers/UIInterfaces/ChatWindow.h> #include <Swift/QtUI/QtMUCConfigurationWindow.h> #include <Swift/QtUI/QtAffiliationEditor.h> #include <QtTabbable.h> #include <SwifTools/LastLineTracker.h> #include <map> #include <QPointer> class QTextEdit; class QLineEdit; class QComboBox; class QLabel; class QSplitter; class QPushButton; namespace Swift { class QtChatView; class QtOccupantListWidget; class QtChatTheme; class TreeWidget; class QtTextEdit; class UIEventStream; class QtFileTransferJSBridge; + class QtUIPreferences; + class QtChatWindow : public QtTabbable, public ChatWindow { Q_OBJECT public: - QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream); + QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, QtUIPreferences* uiPreferences); ~QtChatWindow(); std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time); std::string addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time); void addSystemMessage(const std::string& message); void addPresenceMessage(const std::string& message); void addErrorMessage(const std::string& errorMessage); void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time); // File transfer related stuff std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes); void setFileTransferProgress(std::string id, const int percentageDone); void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg); void show(); void activate(); void setUnreadMessageCount(int count); void convertToMUC(); // TreeWidget *getTreeWidget(); void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels); void setSecurityLabelsEnabled(bool enabled); void setSecurityLabelsError(); SecurityLabelsCatalog::Item getSelectedSecurityLabel(); void setName(const std::string& name); void setInputEnabled(bool enabled); QtTabbable::AlertType getWidgetAlertState(); void setContactChatState(ChatState::ChatStateType state); void setRosterModel(Roster* roster); void setTabComplete(TabComplete* completer); int getCount(); void replaceLastMessage(const std::string& message); void setAckState(const std::string& id, AckState state); void flash(); QByteArray getSplitterState(); virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions); void setSubject(const std::string& subject); void showRoomConfigurationForm(Form::ref); @@ -124,37 +126,38 @@ namespace Swift { int unreadCount_; bool contactIsTyping_; LastLineTracker lastLineTracker_; QString contact_; QString lastSentMessage_; QtChatView* messageLog_; QtChatTheme* theme_; QtTextEdit* input_; QComboBox* labelsWidget_; QtOccupantListWidget* treeWidget_; QLabel* correctingLabel_; QLabel* alertLabel_; QWidget* alertWidget_; QPushButton* alertButton_; TabComplete* completer_; QLineEdit* subject_; QPushButton* actionButton_; std::vector<SecurityLabelsCatalog::Item> availableLabels_; bool isCorrection_; bool previousMessageWasSelf_; bool previousMessageWasSystem_; bool previousMessageWasPresence_; bool previousMessageWasFileTransfer_; QString previousSenderName_; bool inputClearing_; UIEventStream* eventStream_; bool inputEnabled_; QSplitter *logRosterSplitter_; Tristate correctionEnabled_; QString alertStyleSheet_; std::map<QString, QString> descriptions; QtFileTransferJSBridge* fileTransferJS; QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_; QPointer<QtAffiliationEditor> affiliationEditor_; int idCounter_; + QtUIPreferences* uiPreferences_; }; } diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp index 4943c0e..b860dae 100644 --- a/Swift/QtUI/QtChatWindowFactory.cpp +++ b/Swift/QtUI/QtChatWindowFactory.cpp @@ -1,82 +1,83 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "QtChatWindowFactory.h" #include <QDesktopWidget> #include "QtChatTabs.h" #include "QtChatWindow.h" #include "QtSwiftUtil.h" #include "QtChatTheme.h" #include <qdebug.h> namespace Swift { static const QString SPLITTER_STATE = "mucSplitterState"; static const QString CHAT_TABS_GEOMETRY = "chatTabsGeometry"; -QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath) : themePath_(themePath) { +QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath, QtUIPreferences* uiPreferences) : themePath_(themePath) { settings_ = settings; tabs_ = tabs; + uiPreferences_ = uiPreferences; theme_ = NULL; if (splitter) { splitter->addWidget(tabs_); } else if (tabs_) { QVariant chatTabsGeometryVariant = settings_->getQSettings()->value(CHAT_TABS_GEOMETRY); if (chatTabsGeometryVariant.isValid()) { tabs_->restoreGeometry(chatTabsGeometryVariant.toByteArray()); } connect(tabs_, SIGNAL(geometryChanged()), this, SLOT(handleWindowGeometryChanged())); } } QtChatWindowFactory::~QtChatWindowFactory() { delete theme_; } ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStream* eventStream) { if (!theme_) { theme_ = new QtChatTheme(themePath_); if (theme_->getIncomingContent().isEmpty()) { delete theme_; theme_ = new QtChatTheme(""); /* Use the inbuilt theme */ } } - QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream); + QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, uiPreferences_); connect(chatWindow, SIGNAL(splitterMoved()), this, SLOT(handleSplitterMoved())); connect(this, SIGNAL(changeSplitterState(QByteArray)), chatWindow, SLOT(handleChangeSplitterState(QByteArray))); QVariant splitterState = settings_->getQSettings()->value(SPLITTER_STATE); if(splitterState.isValid()) { chatWindow->handleChangeSplitterState(splitterState.toByteArray()); } if (tabs_) { tabs_->addTab(chatWindow); } else { QVariant chatGeometryVariant = settings_->getQSettings()->value(CHAT_TABS_GEOMETRY); if (chatGeometryVariant.isValid()) { chatWindow->restoreGeometry(chatGeometryVariant.toByteArray()); } connect(chatWindow, SIGNAL(geometryChanged()), this, SLOT(handleWindowGeometryChanged())); } return chatWindow; } void QtChatWindowFactory::handleWindowGeometryChanged() { settings_->getQSettings()->setValue(CHAT_TABS_GEOMETRY, qobject_cast<QWidget*>(sender())->saveGeometry()); } void QtChatWindowFactory::handleSplitterMoved() { QByteArray splitterState = qobject_cast<QtChatWindow*>(sender())->getSplitterState(); settings_->getQSettings()->setValue(SPLITTER_STATE, QVariant(splitterState)); emit changeSplitterState(splitterState); } } diff --git a/Swift/QtUI/QtChatWindowFactory.h b/Swift/QtUI/QtChatWindowFactory.h index f3e8956..f664c43 100644 --- a/Swift/QtUI/QtChatWindowFactory.h +++ b/Swift/QtUI/QtChatWindowFactory.h @@ -1,37 +1,39 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swiften/JID/JID.h" #include "QtSettingsProvider.h" #include <QObject> #include <QSplitter> namespace Swift { class QtChatTabs; class QtChatTheme; class UIEventStream; + class QtUIPreferences; class QtChatWindowFactory : public QObject, public ChatWindowFactory { Q_OBJECT public: - QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath); + QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath, QtUIPreferences* uiPreferences); ~QtChatWindowFactory(); ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); signals: void changeSplitterState(QByteArray); private slots: void handleWindowGeometryChanged(); void handleSplitterMoved(); private: QString themePath_; QtSettingsProvider* settings_; QtChatTabs* tabs_; QtChatTheme* theme_; + QtUIPreferences* uiPreferences_; }; } diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 9d35435..a4ce98e 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -1,127 +1,135 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "QtMainWindow.h" #include <boost/optional.hpp> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <QBoxLayout> #include <QComboBox> #include <QLineEdit> #include <QListWidget> #include <QListWidgetItem> #include <QPushButton> #include <QMenuBar> #include <QToolBar> #include <QAction> #include <QTabWidget> #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtTabWidget.h> #include <Swift/QtUI/QtSettingsProvider.h> +#include <Swift/QtUI/QtUIPreferences.h> #include <Roster/QtRosterWidget.h> #include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h> namespace Swift { #define CURRENT_ROSTER_TAB "current_roster_tab" -QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventStream) : QWidget(), MainWindow(false) { +QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventStream, QtUIPreferences* uiPreferences) : QWidget(), MainWindow(false) { uiEventStream_ = uiEventStream; + uiPreferences_ = uiPreferences; settings_ = settings; setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); mainLayout->setContentsMargins(0,0,0,0); mainLayout->setSpacing(0); meView_ = new QtRosterHeader(settings, this); mainLayout->addWidget(meView_); connect(meView_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleStatusChanged(StatusShow::Type, const QString&))); connect(meView_, SIGNAL(onEditProfileRequest()), this, SLOT(handleEditProfileRequest())); tabs_ = new QtTabWidget(this); #if QT_VERSION >= 0x040500 tabs_->setDocumentMode(true); #endif tabs_->setTabPosition(QTabWidget::South); mainLayout->addWidget(tabs_); contactsTabWidget_ = new QWidget(this); contactsTabWidget_->setContentsMargins(0, 0, 0, 0); QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_); contactsTabWidget_->setLayout(contactTabLayout); contactTabLayout->setSpacing(0); contactTabLayout->setContentsMargins(0, 0, 0, 0); - treeWidget_ = new QtRosterWidget(uiEventStream_, this); + treeWidget_ = new QtRosterWidget(uiEventStream_, uiPreferences_, this); contactTabLayout->addWidget(treeWidget_); tabs_->addTab(contactsTabWidget_, tr("&Contacts")); eventWindow_ = new QtEventWindow(uiEventStream_); connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int))); - chatListWindow_ = new QtChatListWindow(uiEventStream_); + chatListWindow_ = new QtChatListWindow(uiEventStream_, uiPreferences_); connect(chatListWindow_, SIGNAL(onCountUpdated(int)), this, SLOT(handleChatCountUpdated(int))); tabs_->addTab(chatListWindow_, tr("C&hats")); tabs_->addTab(eventWindow_, tr("&Notices")); tabs_->setCurrentIndex(settings_->getIntSetting(CURRENT_ROSTER_TAB, 0)); connect(tabs_, SIGNAL(currentChanged(int)), this, SLOT(handleTabChanged(int))); this->setLayout(mainLayout); QMenu* viewMenu = new QMenu(tr("&View"), this); menus_.push_back(viewMenu); showOfflineAction_ = new QAction(tr("&Show offline contacts"), this); showOfflineAction_->setCheckable(true); showOfflineAction_->setChecked(false); connect(showOfflineAction_, SIGNAL(toggled(bool)), SLOT(handleShowOfflineToggled(bool))); viewMenu->addAction(showOfflineAction_); + //QAction* compactRosterAction_ = new QAction(tr("&Compact Roster"), this); + //compactRosterAction_->setCheckable(true); + //compactRosterAction_->setChecked(false); + //connect(compactRosterAction_, SIGNAL(toggled(bool)), uiPreferences_, SLOT(setCompactRosters(bool))); + //viewMenu->addAction(compactRosterAction_); + QMenu* actionsMenu = new QMenu(tr("&Actions"), this); menus_.push_back(actionsMenu); QAction* editProfileAction = new QAction(tr("Edit &Profile"), this); connect(editProfileAction, SIGNAL(triggered()), SLOT(handleEditProfileAction())); actionsMenu->addAction(editProfileAction); QAction* joinMUCAction = new QAction(tr("Enter &Room"), this); connect(joinMUCAction, SIGNAL(triggered()), SLOT(handleJoinMUCAction())); actionsMenu->addAction(joinMUCAction); addUserAction_ = new QAction(tr("&Add Contact"), this); connect(addUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleAddUserActionTriggered(bool))); actionsMenu->addAction(addUserAction_); editUserAction_ = new QAction(tr("&Edit Selected Contact"), this); connect(editUserAction_, SIGNAL(triggered(bool)), treeWidget_, SLOT(handleEditUserActionTriggered(bool))); actionsMenu->addAction(editUserAction_); editUserAction_->setEnabled(false); chatUserAction_ = new QAction(tr("Start &Chat"), this); connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool))); actionsMenu->addAction(chatUserAction_); serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this); actionsMenu->addMenu(serverAdHocMenu_); actionsMenu->addSeparator(); QAction* signOutAction = new QAction(tr("&Sign Out"), this); connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction())); actionsMenu->addAction(signOutAction); treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QAction::setEnabled, editUserAction_, _1)); setAvailableAdHocCommands(std::vector<DiscoItems::Item>()); QAction* adHocAction = new QAction(tr("Collecting commands..."), this); adHocAction->setEnabled(false); serverAdHocMenu_->addAction(adHocAction); serverAdHocCommandActions_.append(adHocAction); lastOfflineState_ = false; uiEventStream_->onUIEvent.connect(boost::bind(&QtMainWindow::handleUIEvent, this, _1)); diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index 321fa2d..afcb57c 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -1,85 +1,87 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QWidget> #include <QMenu> #include <QList> #include "Swift/Controllers/UIInterfaces/MainWindow.h" #include "Swift/QtUI/QtRosterHeader.h" #include "Swift/QtUI/EventViewer/QtEventWindow.h" #include "Swift/QtUI/ChatList/QtChatListWindow.h" #include <vector> class QComboBox; class QLineEdit; class QPushButton; class QToolBar; class QAction; class QMenu; class QTabWidget; namespace Swift { class QtRosterWidget; class TreeWidget; class UIEventStream; class QtTabWidget; class QtSettingsProvider; + class QtUIPreferences; class QtMainWindow : public QWidget, public MainWindow { Q_OBJECT public: - QtMainWindow(QtSettingsProvider*, UIEventStream* eventStream); + QtMainWindow(QtSettingsProvider*, UIEventStream* eventStream, QtUIPreferences* uiPreferences); virtual ~QtMainWindow(); 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 setConnecting(); QtEventWindow* getEventWindow(); QtChatListWindow* getChatListWindow(); void setRosterModel(Roster* roster); void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands); private slots: void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage); void handleUIEvent(boost::shared_ptr<UIEvent> event); void handleShowOfflineToggled(bool); void handleJoinMUCAction(); void handleSignOutAction(); void handleEditProfileAction(); void handleAddUserActionTriggered(bool checked); void handleChatUserActionTriggered(bool checked); void handleAdHocActionTriggered(bool checked); void handleEventCountUpdated(int count); void handleChatCountUpdated(int count); void handleEditProfileRequest(); void handleTabChanged(int index); private: QtSettingsProvider* settings_; std::vector<QMenu*> menus_; QtRosterWidget* treeWidget_; QtRosterHeader* meView_; QAction* addUserAction_; QAction* editUserAction_; QAction* chatUserAction_; QAction* showOfflineAction_; QMenu* serverAdHocMenu_; QtTabWidget* tabs_; QWidget* contactsTabWidget_; QWidget* eventsTabWidget_; QtEventWindow* eventWindow_; QtChatListWindow* chatListWindow_; UIEventStream* uiEventStream_; bool lastOfflineState_; std::vector<DiscoItems::Item> serverAdHocCommands_; QList<QAction*> serverAdHocCommandActions_; + QtUIPreferences* uiPreferences_; }; } diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 7f11b5c..f706deb 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -81,112 +81,112 @@ po::options_description QtSwift::getOptionsDescription() { ; return result; } QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMainThreadCaller_), autoUpdater_(NULL), idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 1000) { if (options.count("netbook-mode")) { splitter_ = new QSplitter(); } else { splitter_ = NULL; } QCoreApplication::setApplicationName(SWIFT_APPLICATION_NAME); QCoreApplication::setOrganizationName(SWIFT_ORGANIZATION_NAME); QCoreApplication::setOrganizationDomain(SWIFT_ORGANIZATION_DOMAIN); QCoreApplication::setApplicationVersion(buildVersion); int numberOfAccounts = 1; try { numberOfAccounts = options["multi-account"].as<int>(); } catch (...) { /* This seems to fail on a Mac when the .app is launched directly (the usual path).*/ numberOfAccounts = 1; } if (options.count("debug")) { Swift::logging = true; } tabs_ = options.count("no-tabs") && !(splitter_ > 0) ? NULL : new QtChatTabs(); bool startMinimized = options.count("start-minimized") > 0; bool eagleMode = options.count("eagle-mode") > 0; settings_ = new QtSettingsProvider(); applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME); storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir()); certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory()); - chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_, ""); + chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_, "", &uiPreferences_); soundPlayer_ = new QtSoundPlayer(applicationPathProvider_); // Ugly, because the dock depends on the tray, but the temporary // multi-account hack creates one tray per account. QtSystemTray* systemTray = new QtSystemTray(); systemTrays_.push_back(systemTray); #if defined(HAVE_GROWL) notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME); #elif defined(SWIFTEN_PLATFORM_WINDOWS) notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon()); #elif defined(SWIFTEN_PLATFORM_LINUX) notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME); #else notifier_ = new NullNotifier(); #endif #if defined(SWIFTEN_PLATFORM_MACOSX) dock_ = new MacOSXDock(&cocoaApplication_); #else dock_ = new NullDock(); #endif #if defined(SWIFTEN_PLATFORM_MACOSX) uriHandler_ = new QtURIHandler(); #elif defined(SWIFTEN_PLATFORM_WIN32) uriHandler_ = new NullURIHandler(); #else uriHandler_ = new QtDBUSURIHandler(); #endif if (splitter_) { splitter_->show(); } for (int i = 0; i < numberOfAccounts; i++) { if (i > 0) { // Don't add the first tray (see note above) systemTrays_.push_back(new QtSystemTray()); } - QtUIFactory* uiFactory = new QtUIFactory(settings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, startMinimized, eagleMode); + QtUIFactory* uiFactory = new QtUIFactory(settings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, startMinimized, eagleMode, &uiPreferences_); uiFactories_.push_back(uiFactory); MainController* mainController = new MainController( &clientMainThreadCaller_, &networkFactories_, uiFactory, settings_, systemTrays_[i], soundPlayer_, storagesFactory_, certificateStorageFactory_, dock_, notifier_, uriHandler_, &idleDetector_, options.count("latency-debug") > 0, eagleMode); mainControllers_.push_back(mainController); } // PlatformAutoUpdaterFactory autoUpdaterFactory; // if (autoUpdaterFactory.isSupported()) { // autoUpdater_ = autoUpdaterFactory.createAutoUpdater(SWIFT_APPCAST_URL); // autoUpdater_->checkForUpdates(); // } } QtSwift::~QtSwift() { delete notifier_; delete autoUpdater_; foreach (QtUIFactory* factory, uiFactories_) { delete factory; } foreach (MainController* controller, mainControllers_) { delete controller; diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h index 7f33475..c808fa0 100644 --- a/Swift/QtUI/QtSwift.h +++ b/Swift/QtUI/QtSwift.h @@ -1,82 +1,84 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <boost/program_options/variables_map.hpp> #include <boost/program_options/options_description.hpp> #include <Swiften/TLS/PlatformTLSFactories.h> #include <Swiften/Network/BoostNetworkFactories.h> #include <string> #include "Swiften/Base/Platform.h" #include "Swiften/EventLoop/Qt/QtEventLoop.h" #include "QtSettingsProvider.h" #if defined(SWIFTEN_PLATFORM_MACOSX) #include "SwifTools/Application/CocoaApplication.h" #endif #if defined(SWIFTEN_PLATFORM_WINDOWS) #include "WindowsNotifier.h" #endif #include "SwifTools/Idle/PlatformIdleQuerier.h" #include "SwifTools/Idle/ActualIdleDetector.h" +#include <Swift/QtUI/QtUIPreferences.h> namespace po = boost::program_options; class QSplitter; namespace Swift { class QtUIFactory; class CertificateStorageFactory; class Dock; class Notifier; class StoragesFactory; class AutoUpdater; class ApplicationPathProvider; class AvatarStorage; class CapsStorage; class MainController; class QtSystemTray; class QtChatTabs; class QtChatWindowFactory; class QtSoundPlayer; class QtMUCSearchWindowFactory; class QtUserSearchWindowFactory; class EventLoop; class URIHandler; class QtSwift : public QObject { Q_OBJECT public: QtSwift(const po::variables_map& options); static po::options_description getOptionsDescription(); ~QtSwift(); private: QtEventLoop clientMainThreadCaller_; PlatformTLSFactories tlsFactories_; BoostNetworkFactories networkFactories_; QtChatWindowFactory* chatWindowFactory_; std::vector<MainController*> mainControllers_; std::vector<QtSystemTray*> systemTrays_; std::vector<QtUIFactory*> uiFactories_; QtSettingsProvider *settings_; QSplitter* splitter_; QtSoundPlayer* soundPlayer_; Dock* dock_; URIHandler* uriHandler_; QtChatTabs* tabs_; ApplicationPathProvider* applicationPathProvider_; StoragesFactory* storagesFactory_; CertificateStorageFactory* certificateStorageFactory_; AutoUpdater* autoUpdater_; Notifier* notifier_; PlatformIdleQuerier idleQuerier_; ActualIdleDetector idleDetector_; + QtUIPreferences uiPreferences_; #if defined(SWIFTEN_PLATFORM_MACOSX) CocoaApplication cocoaApplication_; #endif }; } diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 5f55795..8a026f2 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -1,93 +1,93 @@ /* * Copyright (c) 2010 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "QtUIFactory.h" #include <QSplitter> #include "QtXMLConsoleWidget.h" #include "QtChatTabs.h" #include "QtMainWindow.h" #include "QtLoginWindow.h" #include "QtSystemTray.h" #include "QtSettingsProvider.h" #include "QtMainWindow.h" #include "QtChatWindow.h" #include "QtJoinMUCWindow.h" #include "QtChatWindowFactory.h" #include "QtSwiftUtil.h" #include "MUCSearch/QtMUCSearchWindow.h" #include "UserSearch/QtUserSearchWindow.h" #include "QtProfileWindow.h" #include "QtContactEditWindow.h" #include "QtAdHocCommandWindow.h" #include "QtFileTransferListWidget.h" #define CHATWINDOW_FONT_SIZE "chatWindowFontSize" namespace Swift { -QtUIFactory::QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode) : settings(settings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized), eagleMode(eagleMode) { +QtUIFactory::QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode, QtUIPreferences* uiPreferences) : settings(settings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized), eagleMode(eagleMode), uiPreferences(uiPreferences) { chatFontSize = settings->getIntSetting(CHATWINDOW_FONT_SIZE, 0); } XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() { QtXMLConsoleWidget* widget = new QtXMLConsoleWidget(); tabs->addTab(widget); if (!tabs->isVisible()) { tabs->show(); } widget->show(); return widget; } FileTransferListWidget* QtUIFactory::createFileTransferListWidget() { QtFileTransferListWidget* widget = new QtFileTransferListWidget(); tabs->addTab(widget); if (!tabs->isVisible()) { tabs->show(); } widget->show(); return widget; } MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) { - lastMainWindow = new QtMainWindow(settings, eventStream); + lastMainWindow = new QtMainWindow(settings, eventStream, uiPreferences); return lastMainWindow; } LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) { loginWindow = new QtLoginWindow(eventStream, eagleMode); if (netbookSplitter) { netbookSplitter->insertWidget(0, loginWindow); } connect(systemTray, SIGNAL(clicked()), loginWindow, SLOT(bringToFront())); #ifndef SWIFT_MOBILE QVariant loginWindowGeometryVariant = settings->getQSettings()->value("loginWindowGeometry"); if (loginWindowGeometryVariant.isValid()) { loginWindow->restoreGeometry(loginWindowGeometryVariant.toByteArray()); } connect(loginWindow, SIGNAL(geometryChanged()), this, SLOT(handleLoginWindowGeometryChanged())); if (startMinimized) loginWindow->hide(); #endif return loginWindow; } void QtUIFactory::handleLoginWindowGeometryChanged() { settings->getQSettings()->setValue("loginWindowGeometry", loginWindow->saveGeometry()); } EventWindow* QtUIFactory::createEventWindow() { return lastMainWindow->getEventWindow(); } ChatListWindow* QtUIFactory::createChatListWindow(UIEventStream*) { return lastMainWindow->getChatListWindow(); } MUCSearchWindow* QtUIFactory::createMUCSearchWindow() { return new QtMUCSearchWindow(); diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 319613d..db33365 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -1,62 +1,64 @@ /* * Copyright (c) 2010 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QObject> #include <QPointer> #include <Swift/Controllers/UIInterfaces/UIFactory.h> +#include <Swift/QtUI/QtUIPreferences.h> class QSplitter; namespace Swift { class QtSettingsProvider; class QtChatTabs; class QtSystemTray; class QtLoginWindow; class QtMainWindow; class QtChatTheme; class QtChatWindowFactory; class QtChatWindow; class QtUIFactory : public QObject, public UIFactory { Q_OBJECT public: - QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode); + QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode, QtUIPreferences* uiPreferences); virtual XMLConsoleWidget* createXMLConsoleWidget(); virtual MainWindow* createMainWindow(UIEventStream* eventStream); virtual LoginWindow* createLoginWindow(UIEventStream* eventStream); virtual EventWindow* createEventWindow(); virtual ChatListWindow* createChatListWindow(UIEventStream*); virtual MUCSearchWindow* createMUCSearchWindow(); virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups); virtual JoinMUCWindow* createJoinMUCWindow(UIEventStream* uiEventStream); virtual ProfileWindow* createProfileWindow(); virtual ContactEditWindow* createContactEditWindow(); virtual FileTransferListWidget* createFileTransferListWidget(); virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command); private slots: void handleLoginWindowGeometryChanged(); void handleChatWindowFontResized(int); private: QtSettingsProvider* settings; QtChatTabs* tabs; QSplitter* netbookSplitter; QtSystemTray* systemTray; QtChatWindowFactory* chatWindowFactory; QtMainWindow* lastMainWindow; QtLoginWindow* loginWindow; std::vector<QPointer<QtChatWindow> > chatWindows; bool startMinimized; int chatFontSize; bool eagleMode; + QtUIPreferences* uiPreferences; }; } diff --git a/Swift/QtUI/QtUIPreferences.cpp b/Swift/QtUI/QtUIPreferences.cpp new file mode 100644 index 0000000..3118178 --- /dev/null +++ b/Swift/QtUI/QtUIPreferences.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/QtUI/QtUIPreferences.h> + +namespace Swift { +QtUIPreferences::QtUIPreferences() : compactRosters_(false) { + +} + +QtUIPreferences::~QtUIPreferences() { + +} + +void QtUIPreferences::setCompactRosters(bool compact) { + compactRosters_ = compact; + emit onCompactRostersChanged(compact); +} + +bool QtUIPreferences::getCompactRosters() { + return compactRosters_; +} + +} diff --git a/Swift/QtUI/QtUIPreferences.h b/Swift/QtUI/QtUIPreferences.h new file mode 100644 index 0000000..e537e80 --- /dev/null +++ b/Swift/QtUI/QtUIPreferences.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <QObject> + +namespace Swift { + class QtUIPreferences : public QObject { + Q_OBJECT + public: + QtUIPreferences(); + ~QtUIPreferences(); + bool getCompactRosters(); + public slots: + void setCompactRosters(bool compact); + signals: + void onCompactRostersChanged(bool /*now*/); + private: + bool compactRosters_; + }; +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/DelegateCommons.cpp b/Swift/QtUI/Roster/DelegateCommons.cpp index 290794d..0dc8a52 100644 --- a/Swift/QtUI/Roster/DelegateCommons.cpp +++ b/Swift/QtUI/Roster/DelegateCommons.cpp @@ -1,108 +1,111 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "DelegateCommons.h" #include <QtScaledAvatarCache.h> #include <QFileInfo> namespace Swift { void DelegateCommons::drawElidedText(QPainter* painter, const QRect& region, const QString& text, int flags) { QString adjustedText(painter->fontMetrics().elidedText(text, Qt::ElideRight, region.width(), Qt::TextShowMnemonic)); painter->drawText(region, flags, adjustedText); } -void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount) const { +void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount, bool compact) const { painter->save(); QRect fullRegion(option.rect); if ( option.state & QStyle::State_Selected ) { painter->fillRect(fullRegion, option.palette.highlight()); painter->setPen(option.palette.highlightedText().color()); } else { painter->setPen(QPen(nameColor)); } QRect presenceIconRegion(QPoint(farLeftMargin, fullRegion.top()), QSize(presenceIconWidth, fullRegion.height() - verticalMargin)); int calculatedAvatarSize = presenceIconRegion.height(); //This overlaps the presenceIcon, so must be painted first QRect avatarRegion(QPoint(presenceIconRegion.right() - presenceIconWidth / 2, presenceIconRegion.top()), QSize(calculatedAvatarSize, calculatedAvatarSize)); QPixmap avatarPixmap; - if (!avatarPath.isEmpty()) { + if (!compact && !avatarPath.isEmpty()) { QString scaledAvatarPath = QtScaledAvatarCache(avatarRegion.height()).getScaledAvatarPath(avatarPath); if (QFileInfo(scaledAvatarPath).exists()) { avatarPixmap.load(scaledAvatarPath); } } - if (avatarPixmap.isNull()) { + if (!compact && avatarPixmap.isNull()) { avatarPixmap = QPixmap(":/icons/avatar.png").scaled(avatarRegion.height(), avatarRegion.width(), Qt::KeepAspectRatio, Qt::SmoothTransformation); } - painter->drawPixmap(avatarRegion.topLeft() + QPoint(((avatarRegion.width() - avatarPixmap.width()) / 2), (avatarRegion.height() - avatarPixmap.height()) / 2), avatarPixmap); + if (!compact) { + painter->drawPixmap(avatarRegion.topLeft() + QPoint(((avatarRegion.width() - avatarPixmap.width()) / 2), (avatarRegion.height() - avatarPixmap.height()) / 2), avatarPixmap); + } //Paint the presence icon over the top of the avatar presenceIcon.paint(painter, presenceIconRegion, Qt::AlignBottom | Qt::AlignHCenter); QFontMetrics nameMetrics(nameFont); painter->setFont(nameFont); int extraFontWidth = nameMetrics.width("H"); - int leftOffset = avatarRegion.right() + horizontalMargin * 2 + extraFontWidth / 2; + int leftOffset = (compact ? presenceIconRegion : avatarRegion).right() + horizontalMargin * 2 + extraFontWidth / 2; QRect textRegion(fullRegion.adjusted(leftOffset, 0, 0/*-leftOffset*/, 0)); int nameHeight = nameMetrics.height() + verticalMargin; QRect nameRegion(textRegion.adjusted(0, verticalMargin, 0, 0)); DelegateCommons::drawElidedText(painter, nameRegion, name); + if (!compact) { + painter->setFont(detailFont); + painter->setPen(QPen(QColor(160,160,160))); - painter->setFont(detailFont); - painter->setPen(QPen(QColor(160,160,160))); - - QRect statusTextRegion(textRegion.adjusted(0, nameHeight, 0, 0)); - DelegateCommons::drawElidedText(painter, statusTextRegion, statusText); + QRect statusTextRegion(textRegion.adjusted(0, nameHeight, 0, 0)); + DelegateCommons::drawElidedText(painter, statusTextRegion, statusText); + } if (unreadCount > 0) { QRect unreadRect(fullRegion.right() - unreadCountSize - horizontalMargin, fullRegion.top() + (fullRegion.height() - unreadCountSize) / 2, unreadCountSize, unreadCountSize); QPen pen(QColor("black")); pen.setWidth(1); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(pen); painter->setBrush(QBrush(QColor("red"), Qt::SolidPattern)); //painter->setBackgroundMode(Qt::OpaqueMode); painter->drawEllipse(unreadRect); painter->setBackgroundMode(Qt::TransparentMode); painter->setPen(QColor("white")); drawElidedText(painter, unreadRect, QString("%1").arg(unreadCount), Qt::AlignCenter); } painter->restore(); } -QSize DelegateCommons::contactSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const { - int heightByAvatar = avatarSize + verticalMargin * 2; +QSize DelegateCommons::contactSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/, bool compact ) const { + int heightByAvatar = (compact ? presenceIconHeight : avatarSize) + verticalMargin * 2; QFontMetrics nameMetrics(nameFont); QFontMetrics statusMetrics(detailFont); - int sizeByText = 2 * verticalMargin + nameMetrics.height() + statusMetrics.height(); + int sizeByText = 2 * verticalMargin + nameMetrics.height() + (compact ? 0 : statusMetrics.height()); //Doesn't work, yay! FIXME: why? //QSize size = (option.state & QStyle::State_Selected) ? QSize(150, 80) : QSize(150, avatarSize_ + margin_ * 2); //qDebug() << "Returning size" << size; return QSize(150, sizeByText > heightByAvatar ? sizeByText : heightByAvatar); } const int DelegateCommons::horizontalMargin = 2; const int DelegateCommons::verticalMargin = 2; const int DelegateCommons::farLeftMargin = 2; const int DelegateCommons::avatarSize = 20; const int DelegateCommons::presenceIconHeight = 16; const int DelegateCommons::presenceIconWidth = 16; const int DelegateCommons::unreadCountSize = 16; } diff --git a/Swift/QtUI/Roster/DelegateCommons.h b/Swift/QtUI/Roster/DelegateCommons.h index e5e4ff9..8732598 100644 --- a/Swift/QtUI/Roster/DelegateCommons.h +++ b/Swift/QtUI/Roster/DelegateCommons.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QApplication> #include <QFont> #include <QPainter> #include <QRect> #include <QString> #include <QIcon> #include <QStyleOptionViewItem> namespace Swift { class DelegateCommons { public: DelegateCommons() : nameFont(QApplication::font()), detailFont(QApplication::font()) { detailFontSizeDrop = nameFont.pointSize() >= 10 ? 2 : 0; detailFont.setStyle(QFont::StyleItalic); detailFont.setPointSize(nameFont.pointSize() - detailFontSizeDrop); } static void drawElidedText(QPainter* painter, const QRect& region, const QString& text, int flags = Qt::AlignTop); - QSize contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; - void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount) const; + QSize contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index, bool compact) const; + void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount, bool compact) const; int detailFontSizeDrop; QFont nameFont; QFont detailFont; static const int horizontalMargin; static const int verticalMargin; static const int farLeftMargin; static const int avatarSize; static const int presenceIconHeight; static const int presenceIconWidth; static const int unreadCountSize; }; } diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp index d7bb875..f864919 100644 --- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp +++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp @@ -1,57 +1,57 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Roster/QtOccupantListWidget.h" #include <QContextMenuEvent> #include <QMenu> #include <QAction> #include <QInputDialog> #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" #include "Swift/Controllers/UIEvents/UIEventStream.h" #include "QtSwiftUtil.h" namespace Swift { -QtOccupantListWidget::QtOccupantListWidget(UIEventStream* eventStream, QWidget* parent) : QtTreeWidget(eventStream, parent) { +QtOccupantListWidget::QtOccupantListWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QtTreeWidget(eventStream, uiPreferences, parent) { } QtOccupantListWidget::~QtOccupantListWidget() { } void QtOccupantListWidget::setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions) { availableOccupantActions_ = actions; } void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) { QModelIndex index = indexAt(event->pos()); if (!index.isValid()) { return; } RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); if (contact) { onSomethingSelectedChanged(contact); QMenu contextMenu; if (availableOccupantActions_.empty()) { QAction* noAction = contextMenu.addAction(tr("No actions for this user")); noAction->setEnabled(false); contextMenu.exec(event->globalPos()); } else { std::map<QAction*, ChatWindow::OccupantAction> actions; foreach (ChatWindow::OccupantAction availableAction, availableOccupantActions_) { QString text = "Error: missing string"; switch (availableAction) { case ChatWindow::Kick: text = tr("Kick user"); break; case ChatWindow::Ban: text = tr("Kick and ban user"); break; case ChatWindow::MakeModerator: text = tr("Make moderator"); break; diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.h b/Swift/QtUI/Roster/QtOccupantListWidget.h index ef29c00..da7c463 100644 --- a/Swift/QtUI/Roster/QtOccupantListWidget.h +++ b/Swift/QtUI/Roster/QtOccupantListWidget.h @@ -1,30 +1,31 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include "Swift/QtUI/Roster/QtTreeWidget.h" #include "Swiften/Base/boost_bsignals.h" #include "Swift/Controllers/UIInterfaces/ChatWindow.h" namespace Swift { +class QtUIPreferences; class QtOccupantListWidget : public QtTreeWidget { Q_OBJECT public: - QtOccupantListWidget(UIEventStream* eventStream, QWidget* parent = 0); + QtOccupantListWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0); virtual ~QtOccupantListWidget(); void setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions); boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected; protected: void contextMenuEvent(QContextMenuEvent* event); private: std::vector<ChatWindow::OccupantAction> availableOccupantActions_; }; } diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp index 4c96695..ac4b500 100644 --- a/Swift/QtUI/Roster/QtRosterWidget.cpp +++ b/Swift/QtUI/Roster/QtRosterWidget.cpp @@ -1,61 +1,61 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Roster/QtRosterWidget.h" #include <QContextMenuEvent> #include <QMenu> #include <QInputDialog> #include <QFileDialog> #include "Swift/Controllers/UIEvents/RequestContactEditorUIEvent.h" #include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h" #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/SendFileUIEvent.h" #include "QtContactEditWindow.h" #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" #include "Swift/Controllers/UIEvents/UIEventStream.h" #include "QtSwiftUtil.h" namespace Swift { -QtRosterWidget::QtRosterWidget(UIEventStream* eventStream, QWidget* parent) : QtTreeWidget(eventStream, parent) { +QtRosterWidget::QtRosterWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QtTreeWidget(eventStream, uiPreferences, parent) { } QtRosterWidget::~QtRosterWidget() { } void QtRosterWidget::handleEditUserActionTriggered(bool /*checked*/) { QModelIndexList selectedIndexList = getSelectedIndexes(); if (selectedIndexList.empty()) { return; } QModelIndex index = selectedIndexList[0]; if (!index.isValid()) { return; } RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) { eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID())); } } void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { QModelIndex index = indexAt(event->pos()); if (!index.isValid()) { return; } RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); QMenu contextMenu; if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) { QAction* editContact = contextMenu.addAction(tr("Edit")); QAction* removeContact = contextMenu.addAction(tr("Remove")); #ifdef SWIFT_EXPERIMENTAL_FT QAction* sendFile = NULL; if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) { diff --git a/Swift/QtUI/Roster/QtRosterWidget.h b/Swift/QtUI/Roster/QtRosterWidget.h index f870237..01f4726 100644 --- a/Swift/QtUI/Roster/QtRosterWidget.h +++ b/Swift/QtUI/Roster/QtRosterWidget.h @@ -1,25 +1,27 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include "Swift/QtUI/Roster/QtTreeWidget.h" namespace Swift { +class QtUIPreferences; + class QtRosterWidget : public QtTreeWidget { Q_OBJECT public: - QtRosterWidget(UIEventStream* eventStream, QWidget* parent = 0); + QtRosterWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0); virtual ~QtRosterWidget(); public slots: void handleEditUserActionTriggered(bool checked); protected: void contextMenuEvent(QContextMenuEvent* event); private: void renameGroup(GroupRosterItem* group); }; } diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp index 690515d..4382125 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.cpp +++ b/Swift/QtUI/Roster/QtTreeWidget.cpp @@ -1,87 +1,95 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Roster/QtTreeWidget.h" #include <boost/smart_ptr/make_shared.hpp> #include <QUrl> -#include "Swiften/Base/Platform.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include "Swift/Controllers/UIEvents/UIEventStream.h" -#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" -#include "Swift/Controllers/UIEvents/SendFileUIEvent.h" -#include "QtSwiftUtil.h" +#include <Swiften/Base/Platform.h> +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> +#include <Swift/Controllers/UIEvents/UIEventStream.h> +#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> +#include <Swift/Controllers/UIEvents/SendFileUIEvent.h> +#include <QtSwiftUtil.h> +#include <Swift/QtUI/QtUIPreferences.h> namespace Swift { -QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QWidget* parent) : QTreeView(parent) { +QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QTreeView(parent) { eventStream_ = eventStream; + uiPreferences_ = uiPreferences; model_ = new RosterModel(this); setModel(model_); - delegate_ = new RosterDelegate(this); + delegate_ = new RosterDelegate(this, uiPreferences_->getCompactRosters()); setItemDelegate(delegate_); setHeaderHidden(true); #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); expandAll(); setAnimated(true); setIndentation(0); #ifdef SWIFT_EXPERIMENTAL_FT setAcceptDrops(true); #endif setRootIsDecorated(true); connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&))); connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool))); connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&))); + connect(uiPreferences_, SIGNAL(onCompactRostersChanged(bool)), this, SLOT(handleCompactRostersToggled(bool))); } QtTreeWidget::~QtTreeWidget() { delete model_; delete delegate_; } +void QtTreeWidget::handleCompactRostersToggled(bool compact) { + delegate_->setCompact(compact); + repaint(); +} + void QtTreeWidget::setRosterModel(Roster* roster) { roster_ = roster; model_->setRoster(roster); expandAll(); } QtTreeWidgetItem* QtTreeWidget::getRoot() { return treeRoot_; } void QtTreeWidget::handleClicked(const QModelIndex& index) { GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer())); if (item) { setExpanded(index, !isExpanded(index)); } currentChanged(index, QModelIndex()); } QModelIndexList QtTreeWidget::getSelectedIndexes() const { // Not using selectedIndexes(), because this seems to cause a crash in Qt (4.7.0) in the // QModelIndexList destructor. // This is a workaround posted in http://www.qtcentre.org/threads/16933 (although this case // was resolved by linking against the debug libs, ours isn't, and we're not alone) QItemSelection ranges = selectionModel()->selection(); QModelIndexList selectedIndexList; for (int i = 0; i < ranges.count(); ++i) { QModelIndex parent = ranges.at(i).parent(); int right = ranges.at(i).model()->columnCount(parent) - 1; if (ranges.at(i).left() == 0 && ranges.at(i).right() == right) { for (int r = ranges.at(i).top(); r <= ranges.at(i).bottom(); ++r) { selectedIndexList.append(ranges.at(i).model()->index(r, 0, parent)); } } } return selectedIndexList; diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h index 271fbd5..705c039 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.h +++ b/Swift/QtUI/Roster/QtTreeWidget.h @@ -1,58 +1,61 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QTreeView> #include <QModelIndex> #include <QDragEnterEvent> #include <QDropEvent> #include <QDragMoveEvent> #include "Swift/QtUI/Roster/RosterModel.h" #include "Swift/QtUI/Roster/RosterDelegate.h" namespace Swift { class UIEventStream; +class QtUIPreferences; class QtTreeWidget : public QTreeView{ Q_OBJECT public: - QtTreeWidget(UIEventStream* eventStream, QWidget* parent = 0); + QtTreeWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0); ~QtTreeWidget(); void show(); QtTreeWidgetItem* getRoot(); void setRosterModel(Roster* roster); Roster* getRoster() {return roster_;} boost::signal<void (RosterItem*)> onSomethingSelectedChanged; private slots: void handleItemActivated(const QModelIndex&); void handleModelItemExpanded(const QModelIndex&, bool expanded); void handleExpanded(const QModelIndex&); void handleCollapsed(const QModelIndex&); void handleClicked(const QModelIndex&); + void handleCompactRostersToggled(bool compact); protected: void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); void dragMoveEvent(QDragMoveEvent* event); protected: QModelIndexList getSelectedIndexes() const; private: void drawBranches(QPainter*, const QRect&, const QModelIndex&) const; protected slots: virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous); protected: UIEventStream* eventStream_; private: RosterModel* model_; Roster* roster_; RosterDelegate* delegate_; QtTreeWidgetItem* treeRoot_; + QtUIPreferences* uiPreferences_; }; } diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp index e40907a..7e6428b 100644 --- a/Swift/QtUI/Roster/RosterDelegate.cpp +++ b/Swift/QtUI/Roster/RosterDelegate.cpp @@ -1,78 +1,82 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "RosterDelegate.h" #include <QApplication> #include <QPainter> #include <QColor> #include <QBrush> #include <QFontMetrics> #include <QPainterPath> #include <QPolygon> #include <qdebug.h> #include <QBitmap> #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" #include "QtTreeWidget.h" #include "RosterModel.h" namespace Swift { -RosterDelegate::RosterDelegate(QtTreeWidget* tree) { +RosterDelegate::RosterDelegate(QtTreeWidget* tree, bool compact) : compact_(compact) { tree_ = tree; groupDelegate_ = new GroupItemDelegate(); } RosterDelegate::~RosterDelegate() { delete groupDelegate_; } + +void RosterDelegate::setCompact(bool compact) { + compact_ = compact; +} QSize RosterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); if (dynamic_cast<GroupRosterItem*>(item)) { return groupDelegate_->sizeHint(option, index); } return contactSizeHint(option, index); } QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { - return common_.contactSizeHint(option, index); + return common_.contactSizeHint(option, index, compact_); } void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); if (dynamic_cast<GroupRosterItem*>(item)) { paintGroup(painter, option, index); } else { paintContact(painter, option, index); } } void RosterDelegate::paintGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { if (index.isValid()) { groupDelegate_->paint(painter, option, index.data(Qt::DisplayRole).toString(), index.data(ChildCountRole).toInt(), tree_->isExpanded(index)); } } void RosterDelegate::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QColor nameColor = index.data(Qt::TextColorRole).value<QColor>(); QString avatarPath; if (index.data(AvatarRole).isValid() && !index.data(AvatarRole).value<QString>().isNull()) { avatarPath = index.data(AvatarRole).value<QString>(); } QIcon presenceIcon = index.data(PresenceIconRole).isValid() && !index.data(PresenceIconRole).value<QIcon>().isNull() ? index.data(PresenceIconRole).value<QIcon>() : QIcon(":/icons/offline.png"); QString name = index.data(Qt::DisplayRole).toString(); QString statusText = index.data(StatusTextRole).toString(); - common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, 0); + common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, 0, compact_); } } diff --git a/Swift/QtUI/Roster/RosterDelegate.h b/Swift/QtUI/Roster/RosterDelegate.h index 253c11a..c5db7ef 100644 --- a/Swift/QtUI/Roster/RosterDelegate.h +++ b/Swift/QtUI/Roster/RosterDelegate.h @@ -1,32 +1,35 @@ /* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QStyledItemDelegate> #include <QColor> #include <QFont> #include "GroupItemDelegate.h" #include "DelegateCommons.h" namespace Swift { class QtTreeWidget; class RosterDelegate : public QStyledItemDelegate { public: - RosterDelegate(QtTreeWidget* tree); + RosterDelegate(QtTreeWidget* tree, bool compact); ~RosterDelegate(); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + public slots: + void setCompact(bool compact); private: QSize contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; void paintGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + bool compact_; DelegateCommons common_; GroupItemDelegate* groupDelegate_; QtTreeWidget* tree_; }; } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 9417f63..932a1fa 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -106,70 +106,71 @@ sources = [ "Roster/RosterDelegate.cpp", "Roster/GroupItemDelegate.cpp", "Roster/DelegateCommons.cpp", "Roster/QtRosterWidget.cpp", "Roster/QtOccupantListWidget.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", "MUCSearch/QtMUCSearchWindow.cpp", "MUCSearch/MUCSearchModel.cpp", "MUCSearch/MUCSearchRoomItem.cpp", "MUCSearch/MUCSearchEmptyItem.cpp", "MUCSearch/MUCSearchDelegate.cpp", "UserSearch/QtUserSearchFirstPage.cpp", "UserSearch/QtUserSearchFieldsPage.cpp", "UserSearch/QtUserSearchResultsPage.cpp", "UserSearch/QtUserSearchDetailsPage.cpp", "UserSearch/QtUserSearchWindow.cpp", "UserSearch/UserSearchModel.cpp", "UserSearch/UserSearchDelegate.cpp", "QtSubscriptionRequestWindow.cpp", "QtRosterHeader.cpp", "QtWebView.cpp", "qrc_DefaultTheme.cc", "qrc_Swift.cc", "QtFileTransferJSBridge.cpp", "QtMUCConfigurationWindow.cpp", "QtAffiliationEditor.cpp", + "QtUIPreferences.cpp" ] myenv["SWIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") if env["PLATFORM"] == "win32" : res = myenv.RES("#/Swift/resources/Windows/Swift.rc") # For some reason, SCons isn't picking up the dependency correctly # Adding it explicitly until i figure out why myenv.Depends(res, "../Controllers/BuildVersion.h") sources += [ "WindowsNotifier.cpp", "#/Swift/resources/Windows/Swift.res" ] if env["PLATFORM"] == "posix" : sources += [ "FreeDesktopNotifier.cpp", "QtDBUSURIHandler.cpp", ] if env["PLATFORM"] == "darwin" or env["PLATFORM"] == "win32" : swiftProgram = myenv.Program("Swift", sources) else : swiftProgram = myenv.Program("swift", sources) if env["PLATFORM"] != "darwin" and env["PLATFORM"] != "win32" : openURIProgram = myenv.Program("swift-open-uri", "swift-open-uri.cpp") else : openURIProgram = [] myenv.Uic4("MUCSearch/QtMUCSearchWindow.ui") myenv.Uic4("UserSearch/QtUserSearchWizard.ui") myenv.Uic4("UserSearch/QtUserSearchFirstPage.ui") myenv.Uic4("UserSearch/QtUserSearchFieldsPage.ui") myenv.Uic4("UserSearch/QtUserSearchResultsPage.ui") |
Swift