1 //
2 // Copyright RIME Developers
3 // Distributed under the BSD License
4 //
5 // 2012-02-18 GONG Chen <chen.sst@gmail.com>
6 //
7 #include <utility>
8 #include <boost/algorithm/string.hpp>
9 #include <boost/filesystem.hpp>
10 #include <rime/config.h>
11 #include <rime/deployer.h>
12 #include <rime/lever/switcher_settings.h>
13 
14 namespace fs = boost::filesystem;
15 
16 namespace rime {
17 
SwitcherSettings(Deployer * deployer)18 SwitcherSettings::SwitcherSettings(Deployer* deployer)
19     : CustomSettings(deployer, "default", "Rime::SwitcherSettings") {
20 }
21 
Load()22 bool SwitcherSettings::Load() {
23   if (!CustomSettings::Load())
24     return false;
25   available_.clear();
26   selection_.clear();
27   hotkeys_.clear();
28   GetAvailableSchemasFromDirectory(deployer_->shared_data_dir);
29   GetAvailableSchemasFromDirectory(deployer_->user_data_dir);
30   GetSelectedSchemasFromConfig();
31   GetHotkeysFromConfig();
32   return true;
33 }
34 
Select(Selection selection)35 bool SwitcherSettings::Select(Selection selection) {
36   selection_ = std::move(selection);
37   auto schema_list = New<ConfigList>();
38   for (const string& schema_id : selection_) {
39     auto item = New<ConfigMap>();
40     item->Set("schema", New<ConfigValue>(schema_id));
41     schema_list->Append(item);
42   }
43   return Customize("schema_list", schema_list);
44 }
45 
SetHotkeys(const string & hotkeys)46 bool SwitcherSettings::SetHotkeys(const string& hotkeys) {
47   // TODO: not implemented; validation required
48   return false;
49 }
50 
GetAvailableSchemasFromDirectory(const fs::path & dir)51 void SwitcherSettings::GetAvailableSchemasFromDirectory(const fs::path& dir) {
52   if (!fs::exists(dir) || !fs::is_directory(dir)) {
53     LOG(INFO) << "directory '" << dir.string() << "' does not exist.";
54     return;
55   }
56   for (fs::directory_iterator it(dir), end;
57        it != end; ++it) {
58     string file_path(it->path().string());
59     if (boost::ends_with(file_path, ".schema.yaml")) {
60       Config config;
61       if (config.LoadFromFile(file_path)) {
62         SchemaInfo info;
63         // required properties
64         if (!config.GetString("schema/schema_id", &info.schema_id))
65           continue;
66         if (!config.GetString("schema/name", &info.name))
67           continue;
68         // check for duplicates
69         bool duplicated = false;
70         for (const SchemaInfo& other : available_) {
71           if (other.schema_id == info.schema_id) {
72             duplicated = true;
73             break;
74           }
75         }
76         if (duplicated)
77           continue;
78         // details
79         config.GetString("schema/version", &info.version);
80         if (auto authors = config.GetList("schema/author")) {
81           for (size_t i = 0; i < authors->size(); ++i) {
82             auto author = authors->GetValueAt(i);
83             if (author && !author->str().empty()) {
84               if (!info.author.empty())
85                 info.author += "\n";
86               info.author += author->str();
87             }
88           }
89         }
90         config.GetString("schema/description", &info.description);
91         info.file_path = file_path;
92         available_.push_back(info);
93       }
94     }
95   }
96 }
97 
GetSelectedSchemasFromConfig()98 void SwitcherSettings::GetSelectedSchemasFromConfig() {
99   auto schema_list = config_.GetList("schema_list");
100   if (!schema_list) {
101     LOG(WARNING) << "schema list not defined.";
102     return;
103   }
104   for (auto it = schema_list->begin(); it != schema_list->end(); ++it) {
105     auto item = As<ConfigMap>(*it);
106     if (!item)
107       continue;
108     auto schema_property = item->GetValue("schema");
109     if (!schema_property)
110       continue;
111     const string& schema_id(schema_property->str());
112     selection_.push_back(schema_id);
113   }
114 }
115 
GetHotkeysFromConfig()116 void SwitcherSettings::GetHotkeysFromConfig() {
117   auto hotkeys = config_.GetList("switcher/hotkeys");
118   if (!hotkeys) {
119     LOG(WARNING) << "hotkeys not defined.";
120     return;
121   }
122   for (auto it = hotkeys->begin(); it != hotkeys->end(); ++it) {
123     auto item = As<ConfigValue>(*it);
124     if (!item)
125       continue;
126     const string& hotkey(item->str());
127     if (hotkey.empty())
128       continue;
129     if (!hotkeys_.empty())
130       hotkeys_ += ", ";
131     hotkeys_ += hotkey;
132   }
133 }
134 
135 }  // namespace rime
136