summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.project.vimrc2
-rw-r--r--Swift/ChangeLog.md1
-rw-r--r--Swift/Controllers/SConscript3
-rw-r--r--Swift/Controllers/StatusCache.cpp99
-rw-r--r--Swift/Controllers/StatusCache.h40
-rw-r--r--Swift/QtUI/QtMainWindow.cpp4
-rw-r--r--Swift/QtUI/QtMainWindow.h3
-rw-r--r--Swift/QtUI/QtRosterHeader.cpp4
-rw-r--r--Swift/QtUI/QtRosterHeader.h3
-rw-r--r--Swift/QtUI/QtStatusWidget.cpp26
-rw-r--r--Swift/QtUI/QtStatusWidget.h6
-rw-r--r--Swift/QtUI/QtSwift.cpp6
-rw-r--r--Swift/QtUI/QtSwift.h2
-rw-r--r--Swift/QtUI/QtUIFactory.cpp4
-rw-r--r--Swift/QtUI/QtUIFactory.h4
15 files changed, 193 insertions, 14 deletions
diff --git a/.project.vimrc b/.project.vimrc
index 771522b..cf0bd43 100644
--- a/.project.vimrc
+++ b/.project.vimrc
@@ -15,3 +15,5 @@ set errorformat+=%E%.%#\ test:\ %.%#line:\ %l\ %f,%Z%m
set makeprg=python\ 3rdParty/SCons/scons.py\ check=1
set noexpandtab
+
+let g:syntastic_c_include_dirs = [ '.', 'Swift/QtUI', '3rdParty/Boost/src' ]
diff --git a/Swift/ChangeLog.md b/Swift/ChangeLog.md
index 6046ba1..2fd9bf3 100644
--- a/Swift/ChangeLog.md
+++ b/Swift/ChangeLog.md
@@ -1,6 +1,7 @@
3.0-beta1
---------
- Allow toggling of a more compact roster display.
+- Remember status settings and provide quick access to them with searching of recent selections in the status setter.
2.0-beta2
---------
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index 7cd017b..a54c6a2 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -74,7 +74,8 @@ if env["SCONS_STAGE"] == "build" :
"XMPPURIController.cpp",
"ChatMessageSummarizer.cpp",
"SettingConstants.cpp",
- "WhiteboardManager.cpp"
+ "WhiteboardManager.cpp",
+ "StatusCache.cpp"
])
env.Append(UNITTEST_SOURCES = [
diff --git a/Swift/Controllers/StatusCache.cpp b/Swift/Controllers/StatusCache.cpp
new file mode 100644
index 0000000..0e8c34d
--- /dev/null
+++ b/Swift/Controllers/StatusCache.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/Controllers/StatusCache.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/ByteArray.h>
+#include <SwifTools/Application/ApplicationPathProvider.h>
+
+namespace Swift {
+
+static const size_t MAX_ENTRIES = 200;
+
+StatusCache::StatusCache(ApplicationPathProvider* paths) {
+ paths_ = paths;
+ path_ = paths_->getDataDir() / "StatusCache";
+ loadRecents();
+}
+
+StatusCache::~StatusCache() {
+
+}
+
+std::vector<StatusCache::PreviousStatus> StatusCache::getMatches(const std::string& substring, size_t maxCount) const {
+ std::vector<PreviousStatus> matches;
+ foreach (const PreviousStatus& status, previousStatuses_) {
+ if (substring.empty() || boost::algorithm::ifind_first(status.first, substring)) {
+ matches.push_back(status);
+ if (matches.size() == maxCount) {
+ break;
+ }
+ }
+ }
+ return matches;
+}
+
+void StatusCache::addRecent(const std::string& text, StatusShow::Type type) {
+ previousStatuses_.push_back(PreviousStatus(text, type));
+ for (size_t i = previousStatuses_.size(); i > MAX_ENTRIES; i--) {
+ previousStatuses_.pop_front();
+ }
+ saveRecents();
+}
+
+void StatusCache::loadRecents() {
+ try {
+ if (boost::filesystem::exists(path_)) {
+ ByteArray data;
+ readByteArrayFromFile(data, path_.string());
+ std::string stringData = byteArrayToString(data);
+ std::vector<std::string> lines;
+ boost::split(lines, stringData, boost::is_any_of("\n"));
+ foreach (const std::string& line, lines) {
+ std::vector<std::string> bits;
+ boost::split(bits, line, boost::is_any_of("\t"));
+ if (bits.size() < 2) {
+ continue;
+ }
+ StatusShow::Type type;
+ type = static_cast<StatusShow::Type>(boost::lexical_cast<size_t>(bits[0]));
+ previousStatuses_.push_back(PreviousStatus(bits[1], type));
+ }
+ }
+ }
+ catch (const boost::filesystem::filesystem_error& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ }
+}
+
+void StatusCache::saveRecents() {
+ try {
+ if (!boost::filesystem::exists(path_.parent_path())) {
+ boost::filesystem::create_directories(path_.parent_path());
+ }
+ boost::filesystem::ofstream file(path_);
+ foreach (const PreviousStatus& recent, previousStatuses_) {
+ std::string message = recent.first;
+ boost::replace_all(message, "\t", " ");
+ file << recent.second << "\t" << message << std::endl;
+ }
+ file.close();
+ }
+ catch (const boost::filesystem::filesystem_error& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ }
+}
+
+}
+
+
+
+
diff --git a/Swift/Controllers/StatusCache.h b/Swift/Controllers/StatusCache.h
new file mode 100644
index 0000000..35b3674
--- /dev/null
+++ b/Swift/Controllers/StatusCache.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <utility>
+#include <vector>
+#include <list>
+#include <iostream>
+
+#include <boost/filesystem/path.hpp>
+
+#include <Swiften/Elements/StatusShow.h>
+
+namespace Swift {
+ class ApplicationPathProvider;
+ class StatusCache {
+ public:
+ typedef std::pair<std::string, StatusShow::Type> PreviousStatus;
+ public:
+ StatusCache(ApplicationPathProvider* paths);
+ ~StatusCache();
+
+ std::vector<PreviousStatus> getMatches(const std::string& substring, size_t maxCount) const;
+ void addRecent(const std::string& text, StatusShow::Type type);
+ private:
+ void saveRecents();
+ void loadRecents();
+ private:
+ boost::filesystem::path path_;
+ std::list<PreviousStatus> previousStatuses_;
+ ApplicationPathProvider* paths_;
+ };
+}
+
+
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 8f74a8d..9749397 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -47,14 +47,14 @@
namespace Swift {
-QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, bool emoticonsExist) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
+QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
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);
+ meView_ = new QtRosterHeader(settings, statusCache, 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()));
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index f91610a..99bc675 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -32,11 +32,12 @@ namespace Swift {
class QtTabWidget;
class SettingsProvider;
class QtUIPreferences;
+ class StatusCache;
class QtMainWindow : public QWidget, public MainWindow {
Q_OBJECT
public:
- QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, bool emoticonsExist);
+ QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist);
virtual ~QtMainWindow();
std::vector<QMenu*> getMenus() {return menus_;}
void setMyNick(const std::string& name);
diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp
index d32a12e..44459d5 100644
--- a/Swift/QtUI/QtRosterHeader.cpp
+++ b/Swift/QtUI/QtRosterHeader.cpp
@@ -23,7 +23,7 @@
#include "QtScaledAvatarCache.h"
namespace Swift {
-QtRosterHeader::QtRosterHeader(SettingsProvider* settings, QWidget* parent) : QWidget(parent) {
+QtRosterHeader::QtRosterHeader(SettingsProvider* settings, StatusCache* statusCache, QWidget* parent) : QWidget(parent) {
QHBoxLayout* topLayout = new QHBoxLayout();
topLayout->setSpacing(3);
topLayout->setContentsMargins(4,4,4,4);
@@ -62,7 +62,7 @@ QtRosterHeader::QtRosterHeader(SettingsProvider* settings, QWidget* parent) : QW
rightLayout->addLayout(nameAndSecurityLayout);
- statusWidget_ = new QtStatusWidget(this);
+ statusWidget_ = new QtStatusWidget(statusCache, this);
connect(statusWidget_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleChangeStatusRequest(StatusShow::Type, const QString&)));
rightLayout->addWidget(statusWidget_);
diff --git a/Swift/QtUI/QtRosterHeader.h b/Swift/QtUI/QtRosterHeader.h
index 9527cf4..ad19178 100644
--- a/Swift/QtUI/QtRosterHeader.h
+++ b/Swift/QtUI/QtRosterHeader.h
@@ -24,11 +24,12 @@ namespace Swift {
class QtStatusWidget;
class QtNameWidget;
class SettingsProvider;
+ class StatusCache;
class QtRosterHeader : public QWidget {
Q_OBJECT
public:
- QtRosterHeader(SettingsProvider* settings, QWidget* parent = NULL);
+ QtRosterHeader(SettingsProvider* settings, StatusCache* statusCache, QWidget* parent = NULL);
void setAvatar(const QString& path);
void setJID(const QString& jid);
diff --git a/Swift/QtUI/QtStatusWidget.cpp b/Swift/QtUI/QtStatusWidget.cpp
index 0e2731a..fc1e764 100644
--- a/Swift/QtUI/QtStatusWidget.cpp
+++ b/Swift/QtUI/QtStatusWidget.cpp
@@ -23,10 +23,11 @@
#include "Swift/QtUI/QtLineEdit.h"
#include "Swift/QtUI/QtSwiftUtil.h"
#include <Swift/Controllers/StatusUtil.h>
+#include <Swift/Controllers/StatusCache.h>
namespace Swift {
-QtStatusWidget::QtStatusWidget(QWidget *parent) : QWidget(parent), editCursor_(Qt::IBeamCursor), viewCursor_(Qt::PointingHandCursor) {
+QtStatusWidget::QtStatusWidget(StatusCache* statusCache, QWidget *parent) : QWidget(parent), statusCache_(statusCache), editCursor_(Qt::IBeamCursor), viewCursor_(Qt::PointingHandCursor) {
isClicking_ = false;
connecting_ = false;
setMaximumHeight(24);
@@ -134,6 +135,14 @@ void QtStatusWidget::generateList() {
item->setStatusTip(item->toolTip());
item->setData(Qt::UserRole, QVariant(type));
}
+ std::vector<StatusCache::PreviousStatus> previousStatuses = statusCache_->getMatches(Q2PSTRING(text), 8);
+ foreach (StatusCache::PreviousStatus savedStatus, previousStatuses) {
+ QListWidgetItem* item = new QListWidgetItem(P2QSTRING(savedStatus.first), menu_);
+ item->setIcon(icons_[savedStatus.second]);
+ item->setToolTip(item->text());
+ item->setStatusTip(item->toolTip());
+ item->setData(Qt::UserRole, QVariant(savedStatus.second));
+ }
foreach (StatusShow::Type type, icons_.keys()) {
QListWidgetItem* item = new QListWidgetItem(P2QSTRING(statusShowTypeToFriendlyName(type)), menu_);
item->setIcon(icons_[type]);
@@ -141,8 +150,20 @@ void QtStatusWidget::generateList() {
item->setStatusTip(item->toolTip());
item->setData(Qt::UserRole, QVariant(type));
}
+ resizeMenu();
}
+void QtStatusWidget::resizeMenu() {
+ int height = menu_->sizeHintForRow(0) * menu_->count();
+ int marginLeft;
+ int marginTop;
+ int marginRight;
+ int marginBottom;
+ menu_->getContentsMargins(&marginLeft, &marginTop, &marginRight, &marginBottom);
+ height += marginTop + marginBottom;
+
+ menu_->setGeometry(menu_->x(), menu_->y(), menu_->width(), height);
+}
void QtStatusWidget::handleClicked() {
editing_ = true;
@@ -197,7 +218,7 @@ void QtStatusWidget::viewMode() {
disconnect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(handleApplicationFocusChanged(QWidget*, QWidget*)));
editing_ = false;
menu_->hide();
- stack_->setCurrentIndex(0);
+ stack_->setCurrentIndex(0);
}
void QtStatusWidget::handleEditComplete() {
@@ -205,6 +226,7 @@ void QtStatusWidget::handleEditComplete() {
statusText_ = newStatusText_;
viewMode();
emit onChangeStatusRequest(selectedStatusType_, statusText_);
+ statusCache_->addRecent(Q2PSTRING(statusText_), selectedStatusType_);
}
void QtStatusWidget::handleEditCancelled() {
diff --git a/Swift/QtUI/QtStatusWidget.h b/Swift/QtUI/QtStatusWidget.h
index 75bcf52..57f52c6 100644
--- a/Swift/QtUI/QtStatusWidget.h
+++ b/Swift/QtUI/QtStatusWidget.h
@@ -22,10 +22,12 @@ class QMovie;
namespace Swift {
class QtLineEdit;
class QtElidingLabel;
+ class StatusCache;
+
class QtStatusWidget : public QWidget {
Q_OBJECT
public:
- QtStatusWidget(QWidget *parent);
+ QtStatusWidget(StatusCache* statusCache, QWidget *parent);
~QtStatusWidget();
StatusShow::Type getSelectedStatusShow();
void setStatusType(StatusShow::Type type);
@@ -45,9 +47,11 @@ namespace Swift {
void handleItemClicked(QListWidgetItem* item);
static QString getNoMessage();
private:
+ void resizeMenu();
void viewMode();
void setNewToolTip();
//QComboBox *types_;
+ StatusCache* statusCache_;
QStackedWidget* stack_;
QLabel* statusIcon_;
QtElidingLabel* statusTextLabel_;
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 223f3ae..e2f2f8d 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -38,6 +38,7 @@
#include <SwifTools/AutoUpdater/AutoUpdater.h>
#include <SwifTools/AutoUpdater/PlatformAutoUpdaterFactory.h>
#include "Swiften/Base/Paths.h"
+#include <Swift/Controllers/StatusCache.h>
#if defined(SWIFTEN_PLATFORM_WINDOWS)
#include "WindowsNotifier.h"
@@ -190,6 +191,8 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
uriHandler_ = new QtDBUSURIHandler();
#endif
+ statusCache_ = new StatusCache(applicationPathProvider_);
+
if (splitter_) {
splitter_->show();
}
@@ -199,7 +202,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
// Don't add the first tray (see note above)
systemTrays_.push_back(new QtSystemTray());
}
- QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), startMinimized, !emoticons.empty());
+ QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), statusCache_, startMinimized, !emoticons.empty());
uiFactories_.push_back(uiFactory);
MainController* mainController = new MainController(
&clientMainThreadCaller_,
@@ -243,6 +246,7 @@ QtSwift::~QtSwift() {
}
delete tabs_;
delete splitter_;
+ delete statusCache_;
delete uriHandler_;
delete dock_;
delete soundPlayer_;
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index 42fb50f..99393d4 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -50,6 +50,7 @@ namespace Swift {
class URIHandler;
class SettingsProviderHierachy;
class XMLSettingsProvider;
+ class StatusCache;
class QtSwift : public QObject {
Q_OBJECT
@@ -81,6 +82,7 @@ namespace Swift {
CertificateStorageFactory* certificateStorageFactory_;
AutoUpdater* autoUpdater_;
Notifier* notifier_;
+ StatusCache* statusCache_;
PlatformIdleQuerier idleQuerier_;
ActualIdleDetector idleDetector_;
#if defined(SWIFTEN_PLATFORM_MACOSX)
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index a154fb0..4c6b328 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -33,7 +33,7 @@
namespace Swift {
-QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, bool startMinimized, bool emoticonsExist) : settings(settings), qtOnlySettings(qtOnlySettings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized), emoticonsExist_(emoticonsExist) {
+QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist) : settings(settings), qtOnlySettings(qtOnlySettings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(NULL), loginWindow(NULL), statusCache(statusCache), startMinimized(startMinimized), emoticonsExist_(emoticonsExist) {
chatFontSize = settings->getSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE);
historyFontSize_ = settings->getSetting(QtUISettingConstants::HISTORYWINDOW_FONT_SIZE);
}
@@ -78,7 +78,7 @@ FileTransferListWidget* QtUIFactory::createFileTransferListWidget() {
}
MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) {
- lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), emoticonsExist_);
+ lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_);
return lastMainWindow;
}
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index 30f0101..eb39cc6 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -26,11 +26,12 @@ namespace Swift {
class TimerFactory;
class historyWindow_;
class WhiteboardSession;
+ class StatusCache;
class QtUIFactory : public QObject, public UIFactory {
Q_OBJECT
public:
- QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, bool startMinimized, bool emoticonsExist);
+ QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist);
virtual XMLConsoleWidget* createXMLConsoleWidget();
virtual HistoryWindow* createHistoryWindow(UIEventStream*);
@@ -63,6 +64,7 @@ namespace Swift {
TimerFactory* timerFactory_;
QtMainWindow* lastMainWindow;
QtLoginWindow* loginWindow;
+ StatusCache* statusCache;
std::vector<QPointer<QtChatWindow> > chatWindows;
bool startMinimized;
int chatFontSize;