libfm-qt-packaging/src/core/bookmarks.cpp
Alf Gaida b2567a5f34
Adding upstream version 0.12.0.
Signed-off-by: Alf Gaida <agaida@siduction.org>
2017-10-22 00:13:03 +02:00

163 lines
4.9 KiB
C++

#include "bookmarks.h"
#include "cstrptr.h"
#include <algorithm>
#include <QTimer>
namespace Fm {
std::weak_ptr<Bookmarks> Bookmarks::globalInstance_;
static inline CStrPtr get_legacy_bookmarks_file(void) {
return CStrPtr{g_build_filename(g_get_home_dir(), ".gtk-bookmarks", nullptr)};
}
static inline CStrPtr get_new_bookmarks_file(void) {
return CStrPtr{g_build_filename(g_get_user_config_dir(), "gtk-3.0", "bookmarks", nullptr)};
}
Bookmarks::Bookmarks(QObject* parent):
QObject(parent),
idle_handler{false} {
/* trying the gtk-3.0 first and use it if it exists */
auto fpath = get_new_bookmarks_file();
file = FilePath::fromLocalPath(fpath.get());
load();
if(items_.empty()) { /* not found, use legacy file */
fpath = get_legacy_bookmarks_file();
file = FilePath::fromLocalPath(fpath.get());
load();
}
mon = GObjectPtr<GFileMonitor>{g_file_monitor_file(file.gfile().get(), G_FILE_MONITOR_NONE, nullptr, nullptr), false};
if(mon) {
g_signal_connect(mon.get(), "changed", G_CALLBACK(_onFileChanged), this);
}
}
Bookmarks::~Bookmarks() {
if(mon) {
g_signal_handlers_disconnect_by_data(mon.get(), this);
}
}
const std::shared_ptr<const BookmarkItem>& Bookmarks::insert(const FilePath& path, const QString& name, int pos) {
const auto insert_pos = (pos < 0 || static_cast<size_t>(pos) > items_.size()) ? items_.cend() : items_.cbegin() + pos;
auto it = items_.insert(insert_pos, std::make_shared<const BookmarkItem>(path, name));
queueSave();
return *it;
}
void Bookmarks::remove(const std::shared_ptr<const BookmarkItem>& item) {
items_.erase(std::remove(items_.begin(), items_.end(), item), items_.end());
queueSave();
}
void Bookmarks::reorder(const std::shared_ptr<const BookmarkItem>& item, int pos) {
auto old_it = std::find(items_.cbegin(), items_.cend(), item);
if(old_it == items_.cend())
return;
std::shared_ptr<const BookmarkItem> newItem = item;
auto old_pos = old_it - items_.cbegin();
items_.erase(old_it);
if(old_pos < pos)
--pos;
auto new_it = items_.cbegin() + pos;
if(new_it > items_.cend())
new_it = items_.cend();
items_.insert(new_it, std::move(newItem));
queueSave();
}
void Bookmarks::rename(const std::shared_ptr<const BookmarkItem>& item, QString new_name) {
auto it = std::find_if(items_.cbegin(), items_.cend(), [item](const std::shared_ptr<const BookmarkItem>& elem) {
return elem->path() == item->path();
});
if(it != items_.cend()) {
// create a new item to replace the old one
// we do not modify the old item directly since this data structure is shared with others
it = items_.insert(it, std::make_shared<const BookmarkItem>(item->path(), new_name));
items_.erase(it + 1); // remove the old item
queueSave();
}
}
std::shared_ptr<Bookmarks> Bookmarks::globalInstance() {
auto bookmarks = globalInstance_.lock();
if(!bookmarks) {
bookmarks = std::make_shared<Bookmarks>();
globalInstance_ = bookmarks;
}
return bookmarks;
}
void Bookmarks::save() {
std::string buf;
// G_LOCK(bookmarks);
for(auto& item: items_) {
auto uri = item->path().uri();
buf += uri.get();
buf += ' ';
buf += item->name().toUtf8().constData();
buf += '\n';
}
idle_handler = false;
// G_UNLOCK(bookmarks);
GError* err = nullptr;
if(!g_file_replace_contents(file.gfile().get(), buf.c_str(), buf.length(), nullptr,
FALSE, G_FILE_CREATE_NONE, nullptr, nullptr, &err)) {
g_critical("%s", err->message);
g_error_free(err);
}
/* we changed bookmarks list, let inform who interested in that */
Q_EMIT changed();
}
void Bookmarks::load() {
auto fpath = file.localPath();
FILE* f;
char buf[1024];
/* load the file */
f = fopen(fpath.get(), "r");
if(f) {
while(fgets(buf, 1024, f)) {
// format of each line in the bookmark file:
// <URI> <name>\n
char* sep;
sep = strchr(buf, '\n');
if(sep) {
*sep = '\0';
}
QString name;
sep = strchr(buf, ' '); // find the separator between URI and name
if(sep) {
*sep = '\0';
name = sep + 1;
}
auto uri = buf;
if(uri[0] != '\0') {
items_.push_back(std::make_shared<BookmarkItem>(FilePath::fromUri(uri), name));
}
}
fclose(f);
}
}
void Bookmarks::onFileChanged(GFileMonitor* /*mon*/, GFile* /*gf*/, GFile* /*other*/, GFileMonitorEvent /*evt*/) {
// reload the bookmarks
items_.clear();
load();
Q_EMIT changed();
}
void Bookmarks::queueSave() {
if(!idle_handler) {
QTimer::singleShot(0, this, &Bookmarks::save);
idle_handler = true;
}
}
} // namespace Fm