commit 36391c18a123db9b867d038a937f5fceb202bb5b
parent 43c2732e960d23e4d1c7107f8254de74bc16d919
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sat, 26 Aug 2017 17:10:12 -0400
browser: split Browser::Entry (big refactoring)
Diffstat:
M | src/browser.cpp | | | 278 | +++++-------------------------------------------------------------------------- |
M | src/browser.hpp | | | 66 | +++++++++++++++++++----------------------------------------------- |
A | src/browser_entry.cpp | | | 260 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/browser_entry.hpp | | | 80 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 376 insertions(+), 308 deletions(-)
diff --git a/src/browser.cpp b/src/browser.cpp
@@ -18,36 +18,19 @@
#include "browser.hpp"
#include "about.hpp"
+#include "browser_entry.hpp"
#include "config.hpp"
#include "encoding.hpp"
#include "errors.hpp"
#include "index.hpp"
+#include "listview.hpp"
#include "menu.hpp"
#include "reapack.hpp"
#include "resource.hpp"
#include "transaction.hpp"
-#include <boost/range/adaptor/reversed.hpp>
-
using namespace std;
-enum Action {
- ACTION_VERSION = 80,
- ACTION_FILTERTYPE,
- ACTION_LATEST = 300,
- ACTION_LATEST_ALL,
- ACTION_REINSTALL,
- ACTION_REINSTALL_ALL,
- ACTION_UNINSTALL,
- ACTION_UNINSTALL_ALL,
- ACTION_PIN,
- ACTION_ABOUT_PKG,
- ACTION_ABOUT_REMOTE,
- ACTION_RESET_ALL,
- ACTION_REFRESH,
- ACTION_MANAGE,
-};
-
enum Timers { TIMER_FILTER = 1, TIMER_ABOUT };
Browser::Browser()
@@ -228,7 +211,7 @@ bool Browser::onKeyDown(const int key, const int mods)
vector<string> values;
for(const int index : m_list->selection(false))
- values.push_back(getValue(NameColumn, *getEntry(index)));
+ values.push_back(getEntry(index)->displayName());
setClipboard(values);
}
@@ -285,94 +268,11 @@ void Browser::fillMenu(Menu &menu)
if(entry) {
Menu pkgMenu = menu.addMenu(AUTO_STR("Package under cursor"));
- fillPackageMenu(entry, pkgMenu);
+ entry->fillMenu(pkgMenu);
}
}
else if(entry)
- fillPackageMenu(entry, menu);
-}
-
-void Browser::fillPackageMenu(const Entry *entry, Menu &menu)
-{
- if(entry->test(InstalledFlag)) {
- if(entry->test(OutOfDateFlag)) {
- auto_char installLabel[32];
- auto_snprintf(installLabel, auto_size(installLabel),
- AUTO_STR("U&pdate to v%s"),
- make_autostring(entry->latest->name().toString()).c_str());
-
- const UINT actionIndex = menu.addAction(installLabel, ACTION_LATEST);
- if(entry->target && *entry->target == entry->latest)
- menu.check(actionIndex);
- }
-
- auto_char reinstallLabel[32];
- auto_snprintf(reinstallLabel, auto_size(reinstallLabel),
- AUTO_STR("&Reinstall v%s"),
- make_autostring(entry->regEntry.version.toString()).c_str());
-
- const UINT actionIndex = menu.addAction(reinstallLabel, ACTION_REINSTALL);
- if(!entry->current || entry->test(ObsoleteFlag))
- menu.disable(actionIndex);
- else if(entry->target && *entry->target == entry->current)
- menu.check(actionIndex);
- }
- else {
- auto_char installLabel[32];
- auto_snprintf(installLabel, auto_size(installLabel),
- AUTO_STR("&Install v%s"),
- make_autostring(entry->latest->name().toString()).c_str());
-
- const UINT actionIndex = menu.addAction(installLabel, ACTION_LATEST);
- if(entry->target && *entry->target == entry->latest)
- menu.check(actionIndex);
- }
-
- Menu versionMenu = menu.addMenu(AUTO_STR("Versions"));
- const UINT versionMenuIndex = menu.size() - 1;
- if(entry->test(ObsoleteFlag))
- menu.disable(versionMenuIndex);
- else {
- const auto &versions = entry->package->versions();
- int verIndex = (int)versions.size();
- for(const Version *ver : versions | boost::adaptors::reversed) {
- const UINT actionIndex = versionMenu.addAction(
- make_autostring(ver->name().toString()).c_str(),
- --verIndex | (ACTION_VERSION << 8));
-
- if(entry->target ? *entry->target == ver : ver == entry->current) {
- if(entry->target && ver != entry->latest)
- menu.check(versionMenuIndex);
-
- versionMenu.checkRadio(actionIndex);
- }
- }
- }
-
- const UINT pinIndex = menu.addAction(
- AUTO_STR("&Pin current version"), ACTION_PIN);
- if(!entry->canPin())
- menu.disable(pinIndex);
- if(entry->pin.value_or(entry->regEntry.pinned))
- menu.check(pinIndex);
-
- const UINT uninstallIndex =
- menu.addAction(AUTO_STR("&Uninstall"), ACTION_UNINSTALL);
- if(!entry->test(InstalledFlag) || getRemote(*entry).isProtected())
- menu.disable(uninstallIndex);
- else if(entry->target && *entry->target == nullptr)
- menu.check(uninstallIndex);
-
- menu.addSeparator();
-
- menu.setEnabled(!entry->test(ObsoleteFlag),
- menu.addAction(AUTO_STR("About this &package"), ACTION_ABOUT_PKG));
-
- auto_char aboutLabel[64];
- const auto_string &name = make_autostring(getValue(RemoteColumn, *entry));
- auto_snprintf(aboutLabel, auto_size(aboutLabel),
- AUTO_STR("&About %s..."), name.c_str());
- menu.addAction(aboutLabel, ACTION_ABOUT_REMOTE);
+ entry->fillMenu(menu);
}
void Browser::updateDisplayLabel()
@@ -552,12 +452,12 @@ void Browser::populate(const vector<IndexPtr> &indexes)
for(const IndexPtr &index : indexes) {
for(const Package *pkg : index->packages())
- m_entries.push_back(makeEntry(pkg, reg.getEntry(pkg), index));
+ m_entries.push_back({pkg, reg.getEntry(pkg), index});
// obsolete packages
for(const Registry::Entry ®Entry : reg.getEntries(index->name())) {
if(!index->find(regEntry.category, regEntry.package))
- m_entries.push_back({InstalledFlag | ObsoleteFlag, regEntry, index});
+ m_entries.push_back({regEntry, index});
}
}
@@ -611,35 +511,6 @@ void Browser::transferActions()
disable(m_applyBtn);
}
-auto Browser::makeEntry(const Package *pkg,
- const Registry::Entry ®Entry, const IndexPtr &index)
- const -> Entry
-{
- const auto &instOpts = g_reapack->config()->install;
- const Version *latest = pkg->lastVersion(instOpts.bleedingEdge, regEntry.version);
- const Version *current = nullptr;
-
- int flags = 0;
-
- if(regEntry) {
- flags |= InstalledFlag;
-
- if(latest && regEntry.version < latest->name())
- flags |= OutOfDateFlag;
-
- current = pkg->findVersion(regEntry.version);
- }
- else
- flags |= UninstalledFlag;
-
- // Show latest pre-release if no stable version is available,
- // or the newest available version if older than current installed version.
- if(!latest)
- latest = pkg->lastVersion(true);
-
- return {flags, regEntry, index, pkg, latest, current};
-}
-
void Browser::fillList()
{
InhibitControl freeze(m_list);
@@ -660,7 +531,7 @@ void Browser::fillList()
const auto &matchingEntryIt = find_if(oldSelection.begin(), oldSelection.end(),
[&entry] (const Entry *oldEntry) { return *oldEntry == entry; });
- const int index = m_list->addRow(makeRow(entry));
+ const int index = m_list->addRow(entry.makeRow());
if(matchingEntryIt != oldSelection.end())
m_list->select(index);
@@ -672,93 +543,6 @@ void Browser::fillList()
updateDisplayLabel();
}
-ListView::Row Browser::makeRow(const Entry &entry) const
-{
- const string &state = getValue(StateColumn, entry);
- const string &name = getValue(NameColumn, entry);
- const string &category = getValue(CategoryColumn, entry);
- const string &version = getValue(VersionColumn, entry);
- const string &author = getValue(AuthorColumn, entry);
- const string &type = getValue(TypeColumn, entry);
- const string &remote = getValue(RemoteColumn, entry);
- const string &date = getValue(TimeColumn, entry);
-
- ListView::Row row{
- make_autostring(state), make_autostring(name), make_autostring(category),
- make_autostring(version), make_autostring(author), make_autostring(type),
- make_autostring(remote), make_autostring(date),
- };
- row.userData = (void *)&entry;
- return row;
-}
-
-string Browser::getValue(const Column col, const Entry &entry) const
-{
- const Package *pkg = entry.package;
- const Version *ver = entry.latest;
- const Registry::Entry ®Entry = entry.regEntry;
-
- string display;
-
- switch(col) {
- case StateColumn: {
- if(entry.test(ObsoleteFlag))
- display += 'o';
- else if(entry.test(OutOfDateFlag))
- display += 'u';
- else if(entry.test(InstalledFlag))
- display += 'i';
- else
- display += '\x20';
-
- if(entry.regEntry.pinned)
- display += 'p';
-
- if(entry.target)
- display += *entry.target == nullptr ? 'R' : 'I';
- if(entry.pin && entry.canPin())
- display += 'P';
-
- return display;
- }
- case NameColumn: {
- if(pkg)
- return pkg->displayName();
- else
- return Package::displayName(regEntry.package, regEntry.description);
- }
- case CategoryColumn:
- return entry.categoryName();
- case VersionColumn:
- if(entry.test(InstalledFlag))
- display = regEntry.version.toString();
-
- if(ver && (!regEntry || ver->name() > regEntry.version)) {
- if(!display.empty())
- display += '\x20';
-
- display += '(' + ver->name().toString() + ')';
- }
-
- return display;
- case AuthorColumn:
- return ver ? ver->displayAuthor() : Version::displayAuthor(regEntry.author);
- case TypeColumn:
- return pkg ? pkg->displayType() : Package::displayType(regEntry.type);
- case RemoteColumn:
- return entry.indexName();
- case TimeColumn:
- return ver ? ver->time().toString() : string();
- }
-
- return {}; // for MSVC
-}
-
-Remote Browser::getRemote(const Entry &entry) const
-{
- return g_reapack->remote(getValue(RemoteColumn, entry));
-}
-
bool Browser::match(const Entry &entry) const
{
switch(currentView()) {
@@ -769,35 +553,28 @@ bool Browser::match(const Entry &entry) const
return false;
break;
case InstalledView:
- if(!entry.test(InstalledFlag))
+ if(!entry.test(Entry::InstalledFlag))
return false;
break;
case OutOfDateView:
- if(!entry.test(OutOfDateFlag))
+ if(!entry.test(Entry::OutOfDateFlag))
return false;
break;
case UninstalledView:
- if(!entry.test(UninstalledFlag))
+ if(!entry.test(Entry::UninstalledFlag))
return false;
break;
case ObsoleteView:
- if(!entry.test(ObsoleteFlag))
+ if(!entry.test(Entry::ObsoleteFlag))
return false;
break;
}
- const Package::Type type =
- entry.latest ? entry.package->type() : entry.regEntry.type;
-
- if(isFiltered(type))
+ if(isFiltered(entry.type()))
return false;
- const string &name = getValue(NameColumn, entry);
- const string &category = getValue(CategoryColumn, entry);
- const string &author = getValue(AuthorColumn, entry);
- const string &remote = getValue(RemoteColumn, entry);
-
- return m_filter.match({name, category, author, remote});
+ return m_filter.match({entry.displayName(), entry.categoryName(),
+ entry.displayAuthor(), entry.indexName()});
}
auto Browser::getEntry(const int index) -> Entry *
@@ -890,7 +667,7 @@ void Browser::uninstall(const int index, const bool toggle)
{
const Entry *entry = getEntry(index);
- if(entry && entry->test(InstalledFlag) && !getRemote(*entry).isProtected())
+ if(entry && entry->test(Entry::InstalledFlag) && !entry->remote().isProtected())
setTarget(index, nullptr, toggle);
}
@@ -968,7 +745,7 @@ void Browser::updateAction(const int index)
updateDisplayLabel();
}
else {
- m_list->replaceRow(index, makeRow(*entry));
+ m_list->replaceRow(index, entry->makeRow());
m_list->sort(); // TODO: only re-sort if sorted by status column
}
@@ -1059,24 +836,3 @@ bool Browser::apply()
return true;
}
-
-const string &Browser::Entry::indexName() const
-{
- return package ? package->category()->index()->name() : regEntry.remote;
-}
-
-const string &Browser::Entry::categoryName() const
-{
- return package ? package->category()->name() : regEntry.category;
-}
-
-const string &Browser::Entry::packageName() const
-{
- return package ? package->name() : regEntry.package;
-}
-
-bool Browser::Entry::operator==(const Entry &o) const
-{
- return indexName() == o.indexName() && categoryName() == o.categoryName() &&
- packageName() == o.packageName();
-}
diff --git a/src/browser.hpp b/src/browser.hpp
@@ -21,13 +21,11 @@
#include "dialog.hpp"
#include "filter.hpp"
-#include "listview.hpp"
-#include "registry.hpp"
+#include "package.hpp"
#include <boost/optional.hpp>
#include <functional>
#include <list>
-#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -35,13 +33,29 @@
class Index;
class ListView;
class Menu;
-class Remote;
class Version;
typedef std::shared_ptr<const Index> IndexPtr;
class Browser : public Dialog {
public:
+ enum Action {
+ ACTION_VERSION = 80,
+ ACTION_FILTERTYPE,
+ ACTION_LATEST = 300,
+ ACTION_LATEST_ALL,
+ ACTION_REINSTALL,
+ ACTION_REINSTALL_ALL,
+ ACTION_UNINSTALL,
+ ACTION_UNINSTALL_ALL,
+ ACTION_PIN,
+ ACTION_ABOUT_PKG,
+ ACTION_ABOUT_REMOTE,
+ ACTION_RESET_ALL,
+ ACTION_REFRESH,
+ ACTION_MANAGE,
+ };
+
Browser();
void refresh(bool stale = false);
void setFilter(const std::string &);
@@ -54,43 +68,7 @@ protected:
void onClose() override;
private:
- enum Flag {
- UninstalledFlag = 1<<0,
- InstalledFlag = 1<<1,
- OutOfDateFlag = 1<<2,
- ObsoleteFlag = 1<<3,
- };
-
- struct Entry {
- int flags;
- Registry::Entry regEntry;
- IndexPtr index;
- const Package *package;
- const Version *latest;
- const Version *current;
-
- const std::string &indexName() const;
- const std::string &categoryName() const;
- const std::string &packageName() const;
-
- boost::optional<const Version *> target;
- boost::optional<bool> pin;
-
- bool test(Flag f) const { return (flags & f) != 0; }
- bool canPin() const { return target ? *target != nullptr : test(InstalledFlag); }
- bool operator==(const Entry &o) const;
- };
-
- enum Column {
- StateColumn,
- NameColumn,
- CategoryColumn,
- VersionColumn,
- AuthorColumn,
- TypeColumn,
- RemoteColumn,
- TimeColumn,
- };
+ class Entry; // browser_entry.hpp
enum View {
AllView,
@@ -108,8 +86,6 @@ private:
Done,
};
- Entry makeEntry(const Package *, const Registry::Entry &, const IndexPtr &) const;
-
void onSelection();
bool fillContextMenu(Menu &, int index);
void populate(const std::vector<IndexPtr> &);
@@ -118,15 +94,11 @@ private:
void updateFilter();
void updateAbout();
void fillList();
- std::string getValue(Column, const Entry &entry) const;
- ListView::Row makeRow(const Entry &) const;
Entry *getEntry(int);
- Remote getRemote(const Entry &) const;
void updateDisplayLabel();
void displayButton();
void actionsButton();
void fillMenu(Menu &);
- void fillPackageMenu(const Entry *, Menu &);
bool isFiltered(Package::Type) const;
bool hasAction(const Entry *) const;
void setTarget(const int index, const Version *, bool toggle = true);
diff --git a/src/browser_entry.cpp b/src/browser_entry.cpp
@@ -0,0 +1,260 @@
+/* ReaPack: Package manager for REAPER
+ * Copyright (C) 2015-2017 Christian Fillion
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "browser_entry.hpp"
+
+#include "config.hpp"
+#include "index.hpp"
+#include "menu.hpp"
+#include "reapack.hpp"
+
+#include <boost/range/adaptor/reversed.hpp>
+
+using namespace std;
+
+Browser::Entry::Entry(const Package *pkg, const Registry::Entry &re, const IndexPtr &i)
+ : m_flags(0), regEntry(re), package(pkg), index(i), current(nullptr)
+{
+ const auto &instOpts = g_reapack->config()->install;
+ latest = pkg->lastVersion(instOpts.bleedingEdge, regEntry.version);
+
+ if(regEntry) {
+ m_flags |= InstalledFlag;
+
+ if(latest && regEntry.version < latest->name())
+ m_flags |= OutOfDateFlag;
+
+ current = pkg->findVersion(regEntry.version);
+ }
+ else
+ m_flags |= UninstalledFlag;
+
+ // Show latest pre-release if no stable version is available,
+ // or the newest available version if older than current installed version.
+ if(!latest)
+ latest = pkg->lastVersion(true);
+}
+
+Browser::Entry::Entry(const Registry::Entry &re, const IndexPtr &i)
+ : m_flags(InstalledFlag | ObsoleteFlag), regEntry(re), package(nullptr),
+ index(i), current(nullptr), latest(nullptr)
+{}
+
+string Browser::Entry::displayState() const
+{
+ string state;
+
+ if(test(ObsoleteFlag))
+ state += 'o';
+ else if(test(OutOfDateFlag))
+ state += 'u';
+ else if(test(InstalledFlag))
+ state += 'i';
+ else
+ state += '\x20';
+
+ if(regEntry.pinned)
+ state += 'p';
+
+ if(target)
+ state += *target == nullptr ? 'R' : 'I';
+ if(pin && canPin())
+ state += 'P';
+
+ return state;
+}
+
+const string &Browser::Entry::indexName() const
+{
+ return package ? package->category()->index()->name() : regEntry.remote;
+}
+
+const string &Browser::Entry::categoryName() const
+{
+ return package ? package->category()->name() : regEntry.category;
+}
+
+const string &Browser::Entry::packageName() const
+{
+ return package ? package->name() : regEntry.package;
+}
+
+string Browser::Entry::displayName() const
+{
+ if(package)
+ return package->displayName();
+ else
+ return Package::displayName(regEntry.package, regEntry.description);
+}
+
+Package::Type Browser::Entry::type() const
+{
+ return latest ? package->type() : regEntry.type;
+}
+
+string Browser::Entry::displayType() const
+{
+ return package ? package->displayType() : Package::displayType(regEntry.type);
+}
+
+string Browser::Entry::displayVersion() const
+{
+ string display;
+
+ if(test(InstalledFlag))
+ display = regEntry.version.toString();
+
+ if(latest && (!regEntry || latest->name() > regEntry.version)) {
+ if(!display.empty())
+ display += '\x20';
+
+ display += '(' + latest->name().toString() + ')';
+ }
+
+ return display;
+}
+
+const VersionName *Browser::Entry::sortVersion() const
+{
+ if(test(InstalledFlag))
+ return ®Entry.version;
+ else
+ return &latest->name();
+}
+
+string Browser::Entry::displayAuthor() const
+{
+ return latest ? latest->displayAuthor() : Version::displayAuthor(regEntry.author);
+}
+
+const Time *Browser::Entry::lastUpdate() const
+{
+ return latest ? &latest->time() : nullptr;
+}
+
+Remote Browser::Entry::remote() const
+{
+ return g_reapack->remote(indexName());
+}
+
+ListView::Row Browser::Entry::makeRow() const
+{
+ const Time *time = lastUpdate();
+
+ ListView::Row row;
+ row.userData = (void *)this;
+ row.push_back(make_autostring(displayState()));
+ row.push_back(make_autostring(displayName()));
+ row.push_back(make_autostring(categoryName()));
+ row.push_back({make_autostring(displayVersion()), (void *)sortVersion()});
+ row.push_back(make_autostring(displayAuthor()));
+ row.push_back(make_autostring(displayType()));
+ row.push_back(make_autostring(indexName()));
+ row.push_back({time ? make_autostring(time->toString()) : auto_string(),
+ (void *)time});
+
+ return row;
+}
+
+void Browser::Entry::fillMenu(Menu &menu) const
+{
+ if(test(InstalledFlag)) {
+ if(test(OutOfDateFlag)) {
+ auto_char installLabel[32];
+ auto_snprintf(installLabel, auto_size(installLabel),
+ AUTO_STR("U&pdate to v%s"),
+ make_autostring(latest->name().toString()).c_str());
+
+ const UINT actionIndex = menu.addAction(installLabel, ACTION_LATEST);
+ if(target && *target == latest)
+ menu.check(actionIndex);
+ }
+
+ auto_char reinstallLabel[32];
+ auto_snprintf(reinstallLabel, auto_size(reinstallLabel),
+ AUTO_STR("&Reinstall v%s"),
+ make_autostring(regEntry.version.toString()).c_str());
+
+ const UINT actionIndex = menu.addAction(reinstallLabel, ACTION_REINSTALL);
+ if(!current || test(ObsoleteFlag))
+ menu.disable(actionIndex);
+ else if(target && *target == current)
+ menu.check(actionIndex);
+ }
+ else {
+ auto_char installLabel[32];
+ auto_snprintf(installLabel, auto_size(installLabel),
+ AUTO_STR("&Install v%s"),
+ make_autostring(latest->name().toString()).c_str());
+
+ const UINT actionIndex = menu.addAction(installLabel, ACTION_LATEST);
+ if(target && *target == latest)
+ menu.check(actionIndex);
+ }
+
+ Menu versionMenu = menu.addMenu(AUTO_STR("Versions"));
+ const UINT versionMenuIndex = menu.size() - 1;
+ if(test(ObsoleteFlag))
+ menu.disable(versionMenuIndex);
+ else {
+ const auto &versions = package->versions();
+ int verIndex = (int)versions.size();
+ for(const Version *ver : versions | boost::adaptors::reversed) {
+ const UINT actionIndex = versionMenu.addAction(
+ make_autostring(ver->name().toString()).c_str(),
+ --verIndex | (ACTION_VERSION << 8));
+
+ if(target ? *target == ver : ver == current) {
+ if(target && ver != latest)
+ menu.check(versionMenuIndex);
+
+ versionMenu.checkRadio(actionIndex);
+ }
+ }
+ }
+
+ const UINT pinIndex = menu.addAction(
+ AUTO_STR("&Pin current version"), ACTION_PIN);
+ if(!canPin())
+ menu.disable(pinIndex);
+ if(pin.value_or(regEntry.pinned))
+ menu.check(pinIndex);
+
+ const UINT uninstallIndex =
+ menu.addAction(AUTO_STR("&Uninstall"), ACTION_UNINSTALL);
+ if(!test(InstalledFlag) || remote().isProtected())
+ menu.disable(uninstallIndex);
+ else if(target && *target == nullptr)
+ menu.check(uninstallIndex);
+
+ menu.addSeparator();
+
+ menu.setEnabled(!test(ObsoleteFlag),
+ menu.addAction(AUTO_STR("About this &package"), ACTION_ABOUT_PKG));
+
+ auto_char aboutLabel[64];
+ const auto_string &name = make_autostring(indexName());
+ auto_snprintf(aboutLabel, auto_size(aboutLabel),
+ AUTO_STR("&About %s..."), name.c_str());
+ menu.addAction(aboutLabel, ACTION_ABOUT_REMOTE);
+}
+
+bool Browser::Entry::operator==(const Entry &o) const
+{
+ return indexName() == o.indexName() && categoryName() == o.categoryName() &&
+ packageName() == o.packageName();
+}
diff --git a/src/browser_entry.hpp b/src/browser_entry.hpp
@@ -0,0 +1,80 @@
+/* ReaPack: Package manager for REAPER
+ * Copyright (C) 2015-2017 Christian Fillion
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef REAPACK_BROWSER_ENTRY_HPP
+#define REAPACK_BROWSER_ENTRY_HPP
+
+#include "browser.hpp"
+#include "listview.hpp"
+#include "registry.hpp"
+
+#include <boost/optional.hpp>
+#include <memory>
+
+class Index;
+class Menu;
+class Remote;
+
+typedef std::shared_ptr<const Index> IndexPtr;
+
+class Browser::Entry {
+public:
+ enum Flag {
+ UninstalledFlag = 1<<0,
+ InstalledFlag = 1<<1,
+ OutOfDateFlag = 1<<2,
+ ObsoleteFlag = 1<<3,
+ };
+
+ Entry(const Package *, const Registry::Entry &, const IndexPtr &);
+ Entry(const Registry::Entry &, const IndexPtr &);
+
+ boost::optional<const Version *> target;
+ boost::optional<bool> pin;
+
+ std::string displayState() const;
+ const std::string &indexName() const;
+ const std::string &categoryName() const;
+ const std::string &packageName() const;
+ std::string displayName() const;
+ Package::Type type() const;
+ std::string displayType() const;
+ std::string displayVersion() const;
+ const VersionName *sortVersion() const;
+ std::string displayAuthor() const;
+ const Time *lastUpdate() const;
+
+ Remote remote() const;
+ ListView::Row makeRow() const;
+ void fillMenu(Menu &) const;
+
+ bool test(Flag f) const { return (m_flags & f) != 0; }
+ bool canPin() const { return target ? *target != nullptr : test(InstalledFlag); }
+ bool operator==(const Entry &o) const;
+
+private:
+ int m_flags;
+
+public:
+ Registry::Entry regEntry;
+ const Package *package;
+ IndexPtr index;
+ const Version *current;
+ const Version *latest;
+};
+
+#endif