Add the basic emoji dictionary class (responsible for loading them from disk and providing helpful lookup functions)
parent
d95571cf7c
commit
ec23b4bc63
|
|
@ -53,6 +53,7 @@ set(llui_SOURCE_FILES
|
|||
lldockcontrol.cpp
|
||||
lldraghandle.cpp
|
||||
lleditmenuhandler.cpp
|
||||
llemojidictionary.cpp
|
||||
llf32uictrl.cpp
|
||||
llfiltereditor.cpp
|
||||
llflashtimer.cpp
|
||||
|
|
@ -163,6 +164,7 @@ set(llui_HEADER_FILES
|
|||
lldockablefloater.h
|
||||
lldockcontrol.h
|
||||
lleditmenuhandler.h
|
||||
llemojidictionary.h
|
||||
llf32uictrl.h
|
||||
llfiltereditor.h
|
||||
llflashtimer.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @file llemojidictionary.cpp
|
||||
* @brief Implementation of LLEmojiDictionary
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "lldir.h"
|
||||
#include "llemojidictionary.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
// ============================================================================
|
||||
// Constants
|
||||
//
|
||||
|
||||
constexpr char SKINNED_EMOJI_FILENAME[] = "emoji_characters.xml";
|
||||
|
||||
// ============================================================================
|
||||
// Helper functions
|
||||
//
|
||||
|
||||
template<class T>
|
||||
std::list<T> llsd_array_to_list(const LLSD& sd, std::function<void(T&)> mutator = {});
|
||||
|
||||
template<>
|
||||
std::list<std::string> llsd_array_to_list(const LLSD& sd, std::function<void(std::string&)> mutator)
|
||||
{
|
||||
std::list<std::string> result;
|
||||
for (LLSD::array_const_iterator it = sd.beginArray(), end = sd.endArray(); it != end; ++it)
|
||||
{
|
||||
const LLSD& entry = *it;
|
||||
if (!entry.isString())
|
||||
continue;
|
||||
|
||||
result.push_back(entry.asStringRef());
|
||||
if (mutator)
|
||||
{
|
||||
mutator(result.back());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LLEmojiDescriptor::LLEmojiDescriptor(const LLSD& descriptor_sd)
|
||||
{
|
||||
Name = descriptor_sd["Name"].asStringRef();
|
||||
|
||||
const LLWString emoji_string = utf8str_to_wstring(descriptor_sd["Character"].asString());
|
||||
Character = (1 == emoji_string.size()) ? emoji_string[0] : L'\0'; // We don't currently support character composition
|
||||
|
||||
auto toLower = [](std::string& str) { LLStringUtil::toLower(str); };
|
||||
ShortCodes = llsd_array_to_list<std::string>(descriptor_sd["ShortCodes"], toLower);
|
||||
Categories = llsd_array_to_list<std::string>(descriptor_sd["Categories"], toLower);
|
||||
|
||||
if (Name.empty())
|
||||
{
|
||||
Name = ShortCodes.front();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLEmojiDescriptor::isValid() const
|
||||
{
|
||||
return
|
||||
Character &&
|
||||
!ShortCodes.empty() &&
|
||||
!Categories.empty();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LLEmojiDictionary class
|
||||
//
|
||||
|
||||
LLEmojiDictionary::LLEmojiDictionary()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
void LLEmojiDictionary::initClass()
|
||||
{
|
||||
LLEmojiDictionary* pThis = &LLEmojiDictionary::initParamSingleton();
|
||||
|
||||
LLSD data;
|
||||
|
||||
const std::string filename = gDirUtilp->findSkinnedFilenames(LLDir::XUI, SKINNED_EMOJI_FILENAME, LLDir::CURRENT_SKIN).front();
|
||||
llifstream file(filename.c_str());
|
||||
if (file.is_open())
|
||||
{
|
||||
LL_DEBUGS() << "Loading emoji characters file at " << filename << LL_ENDL;
|
||||
LLSDSerialize::fromXML(data, file);
|
||||
}
|
||||
|
||||
if (data.isUndefined())
|
||||
{
|
||||
LL_WARNS() << "Emoji file characters missing or ill-formed" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (LLSD::array_const_iterator descriptor_it = data.beginArray(), descriptor_end = data.endArray(); descriptor_it != descriptor_end; ++descriptor_it)
|
||||
{
|
||||
LLEmojiDescriptor descriptor(*descriptor_it);
|
||||
if (!descriptor.isValid())
|
||||
{
|
||||
LL_WARNS() << "Skipping invalid emoji descriptor " << descriptor.Character << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
pThis->addEmoji(std::move(descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
LLWString LLEmojiDictionary::findMatchingEmojis(std::string needle)
|
||||
{
|
||||
// Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category
|
||||
LLStringUtil::toLower(needle);
|
||||
const auto kitty_needle = boost::make_iterator_range((boost::starts_with(needle, ":")) ? needle.begin() + 1 : needle.begin(), needle.end());
|
||||
|
||||
LLWString wstr;
|
||||
for (const auto& descr : mEmojis)
|
||||
{
|
||||
for (const auto& short_code : descr.ShortCodes)
|
||||
{
|
||||
if (boost::icontains(short_code, kitty_needle))
|
||||
{
|
||||
wstr.push_back(descr.Character);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& category : descr.Categories)
|
||||
{
|
||||
if (boost::icontains(category, kitty_needle))
|
||||
{
|
||||
wstr.push_back(descr.Character);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wstr;
|
||||
}
|
||||
|
||||
std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch)
|
||||
{
|
||||
const auto it = mEmoji2Descr.find(ch);
|
||||
return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null;
|
||||
}
|
||||
|
||||
void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr)
|
||||
{
|
||||
mEmojis.push_back(descr);
|
||||
const LLEmojiDescriptor& back = mEmojis.back();
|
||||
mEmoji2Descr.insert(std::make_pair(descr.Character, &back));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* @file llemojidictionary.h
|
||||
* @brief Header file for LLEmojiDictionary
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lldictionary.h"
|
||||
#include "llinitdestroyclass.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
// ============================================================================
|
||||
// LLEmojiDescriptor class
|
||||
//
|
||||
|
||||
struct LLEmojiDescriptor
|
||||
{
|
||||
LLEmojiDescriptor(const LLSD& descriptor_sd);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
std::string Name;
|
||||
llwchar Character;
|
||||
std::list<std::string> ShortCodes;
|
||||
std::list<std::string> Categories;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// LLEmojiDictionary class
|
||||
//
|
||||
|
||||
class LLEmojiDictionary : public LLParamSingleton<LLEmojiDictionary>, public LLInitClass<LLEmojiDictionary>
|
||||
{
|
||||
LLSINGLETON(LLEmojiDictionary);
|
||||
~LLEmojiDictionary() override {};
|
||||
|
||||
public:
|
||||
static void initClass();
|
||||
LLWString findMatchingEmojis(std::string needle);
|
||||
std::string getNameFromEmoji(llwchar ch);
|
||||
|
||||
private:
|
||||
void addEmoji(LLEmojiDescriptor&& descr);
|
||||
|
||||
private:
|
||||
std::list<LLEmojiDescriptor> mEmojis;
|
||||
std::map<llwchar, const LLEmojiDescriptor*> mEmoji2Descr;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
Loading…
Reference in New Issue