diff --git a/daemon/src/history/history.cpp b/daemon/src/history/history.cpp index 258123b87209a6e13d5db793185fd3ca78d6bb3f..1b5abac164e4fd5bfd8c6f829582c573845fbfd2 100644 --- a/daemon/src/history/history.cpp +++ b/daemon/src/history/history.cpp @@ -33,6 +33,7 @@ #include "history.h" #include <cerrno> #include <cc++/file.h> +#include <algorithm> #include <ctime> #include "global.h" #include "logger.h" @@ -54,8 +55,7 @@ namespace { History::History() : items_(), loaded_(false), path_("") -{ -} +{} void History::load(int limit) { @@ -72,9 +72,10 @@ void History::load(int limit) loaded_ = true; } -bool History::save() const +bool History::save() { DEBUG("History: Saving history in XDG directory: %s", path_.c_str()); + std::sort(items_.begin(), items_.end()); std::ofstream outfile(path_.c_str()); if (outfile.fail()) return false; diff --git a/daemon/src/history/history.h b/daemon/src/history/history.h index ada9fc6ebc2d28b5793b9b5bffdc45222b0c2a05..cf062a4df66f3655c9412d5f956b863c722422bf 100644 --- a/daemon/src/history/history.h +++ b/daemon/src/history/history.h @@ -52,7 +52,7 @@ class History { /** *@return bool True if the history has been successfully saved in the file */ - bool save() const; + bool save(); /** *@return bool True if the history file has been successfully read diff --git a/daemon/src/history/historyitem.cpp b/daemon/src/history/historyitem.cpp index 9713a7e04dd2fb501adf55157c3c842f238209f1..ee4eb3fd1334c78a452702599251e3daa684cf3d 100644 --- a/daemon/src/history/historyitem.cpp +++ b/daemon/src/history/historyitem.cpp @@ -31,8 +31,8 @@ */ #include "historyitem.h" -#include <sstream> #include <cstdlib> +#include <istream> const char * const HistoryItem::ACCOUNT_ID_KEY = "accountid"; const char * const HistoryItem::CALLID_KEY = "callid"; @@ -51,22 +51,24 @@ const char * const HistoryItem::OUTGOING_STRING = "outgoing"; using std::map; using std::string; -HistoryItem::HistoryItem(const map<string, string> &args) - : entryMap_(args) +HistoryItem::HistoryItem(const map<string, string> &args) : entryMap_(args), + timestampStart_(std::atol(entryMap_[TIMESTAMP_START_KEY].c_str())) {} -HistoryItem::HistoryItem(std::istream &entry) - : entryMap_() +HistoryItem::HistoryItem(std::istream &entry) : entryMap_(), timestampStart_(0) { std::string tmp; while (std::getline(entry, tmp, '\n')) { size_t pos = tmp.find('='); if (pos == std::string::npos) - return; - std::string key(tmp.substr(0, pos)); - std::string val(tmp.substr(pos + 1, tmp.length() - pos - 1)); - entryMap_[key] = val; + break; + else if (pos < tmp.length() - 1) { + std::string key(tmp.substr(0, pos)); + std::string val(tmp.substr(pos + 1, tmp.length() - pos - 1)); + entryMap_[key] = val; + } } + timestampStart_ = std::atol(entryMap_[TIMESTAMP_START_KEY].c_str()); } map<string, string> HistoryItem::toMap() const @@ -74,9 +76,9 @@ map<string, string> HistoryItem::toMap() const return entryMap_; } -bool HistoryItem::youngerThan(int otherTime) const +bool HistoryItem::youngerThan(unsigned long otherTime) const { - return std::atol(getTimestampStart().c_str()) > otherTime; + return timestampStart_ > otherTime; } bool HistoryItem::hasPeerNumber() const @@ -84,15 +86,6 @@ bool HistoryItem::hasPeerNumber() const return entryMap_.find(PEER_NUMBER_KEY) != entryMap_.end(); } -string HistoryItem::getTimestampStart() const -{ - map<string, string>::const_iterator iter(entryMap_.find(TIMESTAMP_START_KEY)); - if (iter != entryMap_.end()) - return iter->second; - else - return ""; -} - void HistoryItem::print(std::ostream &o) const { // every entry starts with "[" + random integer = "]" diff --git a/daemon/src/history/historyitem.h b/daemon/src/history/historyitem.h index 2a8734792951d2f0addfc7ee3ed0bb6c58de4bba..7aa71085dc0b79cbebcaf1bc4e1c113f61a855cb 100644 --- a/daemon/src/history/historyitem.h +++ b/daemon/src/history/historyitem.h @@ -56,14 +56,17 @@ class HistoryItem { bool hasPeerNumber() const; - bool youngerThan(int otherTime) const; + bool youngerThan(unsigned long otherTime) const; std::map<std::string, std::string> toMap() const; void print(std::ostream &o) const; + bool operator< (const HistoryItem &other) const { + return timestampStart_ > other.timestampStart_; + } private: - std::string getTimestampStart() const; std::map<std::string, std::string> entryMap_; + unsigned long timestampStart_; // cached as we use this a lot, avoids string ops }; std::ostream& operator << (std::ostream& o, const HistoryItem& item); diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 0d1168de48c3f24938bb2fbf82948c3e1f0efdfc..4c34fc676148bf17d676c32b023688a63b799d14 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -76,7 +76,7 @@ ManagerImpl::ManagerImpl() : audiolayerMutex_(), waitingCall_(), waitingCallMutex_(), nbIncomingWaitingCall_(0), path_(), callAccountMap_(), callAccountMapMutex_(), callConfigMap_(), accountMap_(), - mainBuffer_(), conferenceMap_(), history_(), + mainBuffer_(), conferenceMap_(), history_(new History), imModule_(new sfl::InstantMessaging) { // initialize random generator for call id @@ -87,6 +87,7 @@ ManagerImpl::ManagerImpl() : ManagerImpl::~ManagerImpl() { delete imModule_; + delete history_; delete audiofile_; } @@ -128,7 +129,7 @@ void ManagerImpl::init(std::string config_file) audioLayerMutexUnlock(); - history_.load(preferences.getHistoryLimit()); + history_->load(preferences.getHistoryLimit()); registerAccounts(); } @@ -2956,13 +2957,13 @@ std::map<std::string, std::string> ManagerImpl::getCallDetails(const std::string std::vector<std::map<std::string, std::string> > ManagerImpl::getHistory() const { - return history_.getSerialized(); + return history_->getSerialized(); } void ManagerImpl::setHistorySerialized(const std::vector<std::map<std::string, std::string> > &history) { - history_.setSerialized(history, preferences.getHistoryLimit()); - history_.save(); + history_->setSerialized(history, preferences.getHistoryLimit()); + history_->save(); } namespace { diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index b142bfdca3d3b7277e39123da1546347af51fdae..e6b9823837f056e59281367a35e1c11cfaf8be2a 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -51,7 +51,6 @@ #include "audio/codecs/audiocodecfactory.h" #include "audio/mainbuffer.h" -#include "history/history.h" #include "preferences.h" #include "noncopyable.h" @@ -67,6 +66,7 @@ class YamlEmitter; class DTMF; class AudioFile; class AudioLayer; +class History; class TelephoneTone; class VoIPLink; @@ -1198,7 +1198,7 @@ class ManagerImpl { * To handle the persistent history * TODO: move this to ConfigurationManager */ - History history_; + History *history_; /** * Instant messaging module, resposible to initiate, format, parse, diff --git a/gnome/src/actions.c b/gnome/src/actions.c index 160ea13e568b1d7c5323f421d5d91dae10473d43..d19abd2dcd4651ad1e0f3b224f7ee675e477e861 100644 --- a/gnome/src/actions.c +++ b/gnome/src/actions.c @@ -1057,33 +1057,11 @@ void sflphone_fill_history(void) fill_treeview_with_calls(); } -/* Ordered from highest timestamp (most recent) to lowest (oldest) */ -static gint -history_compare_func(gconstpointer a, gconstpointer b) -{ - gconstpointer first_value = g_hash_table_lookup(* (GHashTable **) a, TIMESTAMP_START_KEY); - gconstpointer second_value = g_hash_table_lookup(* (GHashTable **) b, TIMESTAMP_START_KEY); - /* treat NULL values as less than non-NULL values, like g_strcmp0 does */ - if (!first_value) - return -(first_value != second_value); - else if (!second_value) - return first_value != second_value; - - long f = atol(first_value); - long s = atol(second_value); - if (f > s) - return -1; - else if (f == s) - return 0; - else - return 1; -} - void sflphone_save_history(void) { gint size = calllist_get_size(history_tab); - GPtrArray *sorted_history = g_ptr_array_new(); + GPtrArray *history_array = g_ptr_array_new(); /* For each entry in our call history */ for (gint i = 0; i < size; ++i) { QueueElement *current = calllist_get_nth(history_tab, i); @@ -1095,15 +1073,14 @@ void sflphone_save_history(void) if (current->type == HIST_CALL) { GHashTable *value = create_hashtable_from_history_entry(current->elem.call); - g_ptr_array_add(sorted_history, (gpointer) value); + g_ptr_array_add(history_array, (gpointer) value); } else ERROR("SFLphone: Error: Unknown type for serialization"); } - g_ptr_array_sort(sorted_history, history_compare_func); - dbus_set_history(sorted_history); - g_ptr_array_free(sorted_history, TRUE); + dbus_set_history(history_array); + g_ptr_array_free(history_array, TRUE); } void diff --git a/gnome/src/callable_obj.c b/gnome/src/callable_obj.c index ba1d0ba65c1527b58b5d0377421e779dc793a32a..8b4f4aac62344d244b36ddb0afdca2b415e2b6d8 100644 --- a/gnome/src/callable_obj.c +++ b/gnome/src/callable_obj.c @@ -256,14 +256,12 @@ GHashTable* create_hashtable_from_history_entry(callable_obj_t *entry) const gchar *recording_path = entry->_recordfile ? entry->_recordfile : ""; GHashTable *result = g_hash_table_new(NULL, g_str_equal); + add_to_hashtable(result, ACCOUNT_ID_KEY, account_id); add_to_hashtable(result, CALLID_KEY, call_id); add_to_hashtable(result, CONFID_KEY, conf_id); - add_to_hashtable(result, PEER_NUMBER_KEY, peer_number); add_to_hashtable(result, PEER_NAME_KEY, peer_name); + add_to_hashtable(result, PEER_NUMBER_KEY, peer_number); add_to_hashtable(result, RECORDING_PATH_KEY, recording_path); - add_to_hashtable(result, ACCOUNT_ID_KEY, account_id); - add_to_hashtable(result, TIMESTAMP_START_KEY, time_start); - add_to_hashtable(result, TIMESTAMP_STOP_KEY, time_stop); add_to_hashtable(result, STATE_KEY, history_state); /* These values were already allocated dynamically */ g_hash_table_insert(result, g_strdup(TIMESTAMP_START_KEY), time_start);