aseprite/src/app/recent_files.cpp

196 lines
4.5 KiB
C++

// Aseprite
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/recent_files.h"
#include "app/ini_file.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include <cstdio>
#include <cstring>
#include <set>
namespace {
const char* kSectionName[] = { "PinnedFiles",
"RecentFiles",
"PinnedPaths",
"RecentPaths" };
struct compare_path {
std::string a;
compare_path(const std::string& a) : a(a) { }
bool operator()(const std::string& b) const {
return base::compare_filenames(a, b) == 0;
}
};
}
namespace app {
RecentFiles::RecentFiles(const int limit)
: m_limit(limit)
{
load();
}
RecentFiles::~RecentFiles()
{
save();
}
void RecentFiles::addRecentFile(const std::string& filename)
{
std::string fn = normalizePath(filename);
// If the filename is already pinned, we don't add it in the
// collection of recent files collection.
auto it = std::find(m_paths[kPinnedFiles].begin(),
m_paths[kPinnedFiles].end(), fn);
if (it != m_paths[kPinnedFiles].end())
return;
addItem(m_paths[kRecentFiles], fn);
// Add recent folder
std::string path = base::get_file_path(fn);
it = std::find(m_paths[kPinnedFolders].begin(),
m_paths[kPinnedFolders].end(), path);
if (it == m_paths[kPinnedFolders].end()) {
addItem(m_paths[kRecentFolders], path);
}
Changed();
}
void RecentFiles::removeRecentFile(const std::string& filename)
{
std::string fn = normalizePath(filename);
removeItem(m_paths[kRecentFiles], fn);
std::string dir = base::get_file_path(fn);
if (!base::is_directory(dir))
removeRecentFolder(dir);
Changed();
}
void RecentFiles::removeRecentFolder(const std::string& dir)
{
std::string fn = normalizePath(dir);
removeItem(m_paths[kRecentFolders], fn);
Changed();
}
void RecentFiles::setLimit(const int newLimit)
{
ASSERT(newLimit >= 0);
for (auto& list : m_paths) {
if (newLimit < list.size()) {
auto it = list.begin();
std::advance(it, newLimit);
list.erase(it, list.end());
}
}
m_limit = newLimit;
Changed();
}
void RecentFiles::clear()
{
// Clear only recent items (not pinned items)
m_paths[kRecentFiles].clear();
m_paths[kRecentFolders].clear();
Changed();
}
void RecentFiles::setFiles(const base::paths& pinnedFiles,
const base::paths& recentFiles)
{
m_paths[kPinnedFiles] = pinnedFiles;
m_paths[kRecentFiles] = recentFiles;
}
void RecentFiles::setFolders(const base::paths& pinnedFolders,
const base::paths& recentFolders)
{
m_paths[kPinnedFolders] = pinnedFolders;
m_paths[kRecentFolders] = recentFolders;
}
std::string RecentFiles::normalizePath(const std::string& filename)
{
return base::normalize_path(filename);
}
void RecentFiles::addItem(base::paths& list, const std::string& fn)
{
auto it = std::find_if(list.begin(), list.end(), compare_path(fn));
// If the item already exist in the list...
if (it != list.end()) {
// Move it to the first position
list.erase(it);
list.insert(list.begin(), fn);
return;
}
if (m_limit > 0)
list.insert(list.begin(), fn);
while (list.size() > m_limit)
list.erase(--list.end());
}
void RecentFiles::removeItem(base::paths& list, const std::string& fn)
{
auto it = std::find_if(list.begin(), list.end(), compare_path(fn));
if (it != list.end())
list.erase(it);
}
void RecentFiles::load()
{
for (int i=0; i<kCollections; ++i) {
for (const auto& key : enum_config_keys(kSectionName[i])) {
const char* fn = get_config_string(kSectionName[i], key.c_str(), nullptr);
if (fn && *fn &&
((i < 2 && base::is_file(fn)) ||
(i >= 2 && base::is_directory(fn)))) {
std::string normalFn = normalizePath(fn);
m_paths[i].push_back(normalFn);
}
}
}
}
void RecentFiles::save()
{
for (int i=0; i<kCollections; ++i) {
for (const auto& key : enum_config_keys(kSectionName[i]))
del_config_value(kSectionName[i],
key.c_str());
for (int j=0; j<m_paths[i].size(); ++j) {
set_config_string(kSectionName[i],
base::convert_to<std::string>(j).c_str(),
m_paths[i][j].c_str());
}
}
}
} // namespace app