commit d949986910300f3f2b83797194fc5c794ce8805a
parent 8ffc48ebca32236efd39bd0173a3a374e77f1fa6
Author: cfillion <cfillion@users.noreply.github.com>
Date: Thu, 17 Mar 2016 01:08:46 -0400
implement history, about and selection in the browser dialog
Diffstat:
10 files changed, 211 insertions(+), 59 deletions(-)
diff --git a/src/about.cpp b/src/about.cpp
@@ -24,12 +24,12 @@
#include "menu.hpp"
#include "reapack.hpp"
#include "registry.hpp"
+#include "report.hpp"
#include "resource.hpp"
#include "richedit.hpp"
#include "tabbar.hpp"
#include <boost/algorithm/string/replace.hpp>
-#include <boost/range/adaptor/reversed.hpp>
#include <sstream>
using namespace std;
@@ -283,22 +283,3 @@ void About::packageHistory()
const Package *pkg = m_packagesData->at(index);
Dialog::Show<History>(instance(), handle(), pkg);
}
-
-History::History(const Package *pkg)
- : ReportDialog(), m_package(pkg)
-{
-}
-
-void History::fillReport()
-{
- SetWindowText(handle(), AUTO_STR("Package History"));
- SetWindowText(getControl(IDC_LABEL),
- make_autostring(m_package->name()).c_str());
-
- for(const Version *ver : m_package->versions() | boost::adaptors::reversed) {
- if(stream().tellp())
- stream() << NL;
-
- printVersion(ver);
- }
-}
diff --git a/src/about.hpp b/src/about.hpp
@@ -23,12 +23,9 @@
#include <memory>
#include <vector>
-#include "report.hpp"
-
class Index;
class ListView;
class Package;
-class ReportBase;
class RichEdit;
class TabBar;
struct Link;
@@ -68,15 +65,4 @@ private:
const std::vector<const Package *> *m_packagesData;
};
-class History : public ReportDialog {
-public:
- History(const Package *);
-
-protected:
- void fillReport() override;
-
-private:
- const Package *m_package;
-};
-
#endif
diff --git a/src/browser.cpp b/src/browser.cpp
@@ -20,16 +20,22 @@
#include "encoding.hpp"
#include "errors.hpp"
#include "index.hpp"
+#include "menu.hpp"
#include "reapack.hpp"
+#include "report.hpp"
#include "resource.hpp"
#include <boost/algorithm/string.hpp>
+#include <boost/range/adaptor/reversed.hpp>
using namespace std;
+enum Action { ACTION_HISTORY = 300, ACTION_ABOUT };
+enum Display { All, Installed, OutOfDate, Uninstalled, Obsolete };
+
Browser::Browser(const vector<IndexPtr> &indexes, ReaPack *reapack)
: Dialog(IDD_BROWSER_DIALOG), m_indexes(indexes), m_reapack(reapack),
- m_checkFilter(false)
+ m_checkFilter(false), m_currentEntry(nullptr)
{
}
@@ -40,6 +46,7 @@ void Browser::onInit()
SendMessage(m_display, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("All"));
SendMessage(m_display, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("Installed"));
+ SendMessage(m_display, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("Out of date"));
SendMessage(m_display, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("Uninstalled"));
SendMessage(m_display, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("Obsolete"));
@@ -61,6 +68,8 @@ void Browser::onInit()
{AUTO_STR("Type"), 70},
});
+ m_list->onActivate([=] { history(entryAt(m_list->itemUnderMouse())); });
+
m_list->sortByColumn(1);
reload();
@@ -83,6 +92,20 @@ void Browser::onCommand(const int id)
SetWindowText(m_filterHandle, AUTO_STR(""));
checkFilter();
break;
+ case IDC_SELECT:
+ m_list->selectAll();
+ SetFocus(m_list->handle());
+ break;
+ case IDC_UNSELECT:
+ m_list->unselectAll();
+ SetFocus(m_list->handle());
+ break;
+ case ACTION_HISTORY:
+ history(m_currentEntry);
+ break;
+ case ACTION_ABOUT:
+ about(m_currentEntry);
+ break;
case IDOK:
case IDCANCEL:
close();
@@ -90,9 +113,78 @@ void Browser::onCommand(const int id)
}
}
-void Browser::onContextMenu(HWND, const int, const int)
+void Browser::onContextMenu(HWND target, const int x, const int y)
{
- (void)m_reapack;
+ if(target != m_list->handle())
+ return;
+
+ SetFocus(m_list->handle());
+
+ const Entry *entry = entryAt(m_list->itemUnderMouse());
+ m_currentEntry = entry;
+
+ if(!entry)
+ return;
+
+ Menu menu;
+
+ if(!entry->isInstalled ||
+ (entry->latest && entry->latest->code() > entry->regEntry.versionCode)) {
+ }
+
+ if(entry->isInstalled) {
+ if(entry->latest && entry->latest->code() > entry->regEntry.versionCode) {
+ auto_char installLabel[255] = {};
+ auto_snprintf(installLabel, sizeof(installLabel),
+ AUTO_STR("&Update to v%s"), make_autostring(entry->latest->name()).c_str());
+
+ menu.addAction(installLabel, 0);
+ }
+
+ auto_char reinstallLabel[255] = {};
+ auto_snprintf(reinstallLabel, sizeof(reinstallLabel),
+ AUTO_STR("&Reinstall v%s"),
+ make_autostring(entry->regEntry.versionName).c_str());
+
+ const UINT index = menu.addAction(reinstallLabel, 0);
+
+ if(!entry->package)
+ menu.disable(index);
+ }
+ else {
+ auto_char installLabel[255] = {};
+ auto_snprintf(installLabel, sizeof(installLabel),
+ AUTO_STR("&Install v%s"), make_autostring(entry->latest->name()).c_str());
+
+ menu.addAction(installLabel, 0);
+ }
+
+ Menu versions = menu.addMenu(AUTO_STR("Versions"));
+ const UINT versionIndex = menu.size() - 1;
+ const UINT uninstallIndex = menu.addAction(AUTO_STR("&Uninstall"), 0);
+ menu.addSeparator();
+ const UINT historyIndex =
+ menu.addAction(AUTO_STR("Package &History"), ACTION_HISTORY);
+
+ auto_char aboutLabel[255] = {};
+ const auto_string &name = make_autostring(getValue(RemoteColumn, *entry));
+ auto_snprintf(aboutLabel, sizeof(aboutLabel),
+ AUTO_STR("&About %s..."), name.c_str());
+ menu.addAction(aboutLabel, ACTION_ABOUT);
+
+ if(!entry->package) {
+ menu.disable(historyIndex);
+ menu.disable(versionIndex);
+ }
+ else {
+ for(const Version *ver : entry->package->versions() | boost::adaptors::reversed)
+ versions.addAction(make_autostring(ver->name()).c_str(), 0);
+ }
+
+ if(!entry->isInstalled)
+ menu.disable(uninstallIndex);
+
+ menu.show(x, y, handle());
}
void Browser::onTimer(const int id)
@@ -125,11 +217,14 @@ void Browser::reload()
try {
Registry reg(Path::prefixRoot(Path::REGISTRY));
+ m_currentEntry = nullptr;
m_entries.clear();
for(IndexPtr index : m_indexes) {
- for(const Package *pkg : index->packages())
- m_entries.push_back({pkg->lastVersion(), reg.getEntry(pkg)});
+ for(const Package *pkg : index->packages()) {
+ const Registry::Entry ®Entry = reg.getEntry(pkg);
+ m_entries.push_back({regEntry.id != 0, regEntry, pkg, pkg->lastVersion()});
+ }
// obsolete packages
for(const Registry::Entry &entry : reg.getEntries(index->name())) {
@@ -138,7 +233,7 @@ void Browser::reload()
if(cat && cat->package(entry.package))
continue;
- m_entries.push_back({nullptr, entry});
+ m_entries.push_back({true, entry});
}
}
@@ -161,10 +256,16 @@ void Browser::fillList()
InhibitControl freeze(m_list);
m_list->clear();
+ m_visibleEntries.clear();
- for(const Entry &entry : m_entries) {
- if(match(entry))
- m_list->addRow(makeRow(entry));
+ for(size_t i = 0; i < m_entries.size(); i++) {
+ const Entry &entry = m_entries[i];
+
+ if(!match(entry))
+ continue;
+
+ m_list->addRow(makeRow(entry));
+ m_visibleEntries.push_back(i);
}
m_list->sort();
@@ -187,15 +288,15 @@ ListView::Row Browser::makeRow(const Entry &entry) const
string Browser::getValue(const Column col, const Entry &entry) const
{
- const Version *ver = entry.version;
- const Package *pkg = ver ? ver->package() : nullptr;
+ const Package *pkg = entry.package;
+ const Version *ver = entry.latest;
const Registry::Entry ®Entry = entry.regEntry;
string display;
switch(col) {
case StateColumn:
- if(regEntry.id)
+ if(entry.isInstalled)
display += ver ? 'i' : 'o';
else
display += '\x20';
@@ -206,7 +307,7 @@ string Browser::getValue(const Column col, const Entry &entry) const
case CategoryColumn:
return pkg ? pkg->category()->name() : regEntry.category;
case VersionColumn:
- if(regEntry.id)
+ if(entry.isInstalled)
display = regEntry.versionName;
if(ver && ver->code() != regEntry.versionCode) {
@@ -221,6 +322,8 @@ string Browser::getValue(const Column col, const Entry &entry) const
return ver ? ver->displayAuthor() : "";
case TypeColumn:
return pkg ? pkg->displayType() : Package::displayType(regEntry.type);
+ case RemoteColumn:
+ return pkg ? pkg->category()->index()->name() : regEntry.remote;
}
}
@@ -228,24 +331,32 @@ bool Browser::match(const Entry &entry) const
{
using namespace boost;
- int display = SendMessage(m_display, CB_GETCURSEL, 0, 0);
+ Display display = (Display)SendMessage(m_display, CB_GETCURSEL, 0, 0);
+
switch(display) {
- case 1: // Installed
- if(!entry.regEntry.id)
+ case All:
+ break;
+ case Installed:
+ if(!entry.isInstalled)
+ return false;
+ break;
+ case OutOfDate:
+ if(!entry.latest || !entry.isInstalled ||
+ entry.regEntry.versionCode >= entry.latest->code())
return false;
break;
- case 2: // Uninstalled
- if(entry.regEntry.id)
+ case Uninstalled:
+ if(entry.isInstalled)
return false;
break;
- case 3: // Obsolete
- if(entry.version)
+ case Obsolete:
+ if(entry.latest)
return false;
break;
}
const Package::Type type =
- entry.version ? entry.version->package()->type() : entry.regEntry.type;
+ entry.latest ? entry.package->type() : entry.regEntry.type;
const auto typeIt = m_types.find(type);
@@ -260,3 +371,23 @@ bool Browser::match(const Entry &entry) const
return icontains(name, m_filter) || icontains(category, m_filter) ||
icontains(author, m_filter);
}
+
+auto Browser::entryAt(const int listIndex) const -> const Entry *
+{
+ if(listIndex < 0 || listIndex >= (int)m_visibleEntries.size())
+ return nullptr;
+
+ return &m_entries[m_visibleEntries[listIndex]];
+}
+
+void Browser::history(const Entry *entry) const
+{
+ if(entry && entry->package)
+ Dialog::Show<History>(instance(), handle(), entry->package);
+}
+
+void Browser::about(const Entry *entry) const
+{
+ if(entry)
+ m_reapack->about(getValue(RemoteColumn, *entry), handle());
+}
diff --git a/src/browser.hpp b/src/browser.hpp
@@ -47,7 +47,12 @@ protected:
void onTimer(int) override;
private:
- struct Entry { const Version *version; Registry::Entry regEntry; };
+ struct Entry {
+ bool isInstalled;
+ Registry::Entry regEntry;
+ const Package *package;
+ const Version *latest;
+ };
enum Column {
StateColumn,
@@ -56,6 +61,7 @@ private:
VersionColumn,
AuthorColumn,
TypeColumn,
+ RemoteColumn,
};
bool match(const Entry &) const;
@@ -63,13 +69,20 @@ private:
void fillList();
std::string getValue(Column, const Entry &entry) const;
ListView::Row makeRow(const Entry &) const;
+ const Entry *entryAt(int) const;
+
+ void history(const Entry *) const;
+ void about(const Entry *) const;
std::vector<IndexPtr> m_indexes;
ReaPack *m_reapack;
bool m_checkFilter;
+ const Entry *m_currentEntry;
+
int m_filterTimer;
std::string m_filter;
std::vector<Entry> m_entries;
+ std::vector<size_t> m_visibleEntries;
HWND m_filterHandle;
HWND m_display;
diff --git a/src/reapack.cpp b/src/reapack.cpp
@@ -289,7 +289,12 @@ void ReaPack::manageRemotes()
void ReaPack::aboutSelf()
{
- about(m_config->remotes()->get("ReaPack"), m_mainWindow);
+ about("ReaPack", m_mainWindow);
+}
+
+void ReaPack::about(const string &remoteName, HWND parent)
+{
+ about(m_config->remotes()->get(remoteName), parent);
}
void ReaPack::about(const Remote &remote, HWND parent)
diff --git a/src/reapack.hpp b/src/reapack.hpp
@@ -74,6 +74,7 @@ public:
void import(const Remote &);
void manageRemotes();
void aboutSelf();
+ void about(const std::string &, HWND parent);
void about(const Remote &, HWND parent);
void cleanupPackages();
void browsePackages();
diff --git a/src/report.cpp b/src/report.cpp
@@ -168,3 +168,22 @@ void Report::printRemovals()
for(const Path &path : m_receipt->removals())
stream() << path.join() << NL;
}
+
+History::History(const Package *pkg)
+ : ReportDialog(), m_package(pkg)
+{
+}
+
+void History::fillReport()
+{
+ SetWindowText(handle(), AUTO_STR("Package History"));
+ SetWindowText(getControl(IDC_LABEL),
+ make_autostring(m_package->name()).c_str());
+
+ for(const Version *ver : m_package->versions() | boost::adaptors::reversed) {
+ if(stream().tellp())
+ stream() << NL;
+
+ printVersion(ver);
+ }
+}
diff --git a/src/report.hpp b/src/report.hpp
@@ -22,6 +22,7 @@
#include <sstream>
+class Package;
class Receipt;
class Version;
@@ -61,4 +62,15 @@ private:
const Receipt *m_receipt;
};
+class History : public ReportDialog {
+public:
+ History(const Package *);
+
+protected:
+ void fillReport() override;
+
+private:
+ const Package *m_package;
+};
+
#endif
diff --git a/src/resource.hpp b/src/resource.hpp
@@ -64,5 +64,7 @@
#define IDC_FILTER 226
#define IDC_CLEAR 227
#define IDC_DISPLAY 228
+#define IDC_SELECT 229
+#define IDC_UNSELECT 230
#endif
diff --git a/src/resource.rc b/src/resource.rc
@@ -107,7 +107,9 @@ BEGIN
CHECKBOX "&Extensions", IDC_EXTENSIONS, 450, 4, 50, 14
CONTROL "", IDC_PACKAGES, WC_LISTVIEW, LVS_REPORT | LVS_SHOWSELALWAYS |
WS_BORDER | WS_TABSTOP, 5, 22, 490, 204
- PUSHBUTTON "&OK", IDCANCEL, 368, 230, 40, 14
+ PUSHBUTTON "&Select all", IDC_SELECT, 5, 230, 45, 14
+ PUSHBUTTON "&Unselect all", IDC_UNSELECT, 53, 230, 45, 14
+ DEFPUSHBUTTON "&OK", IDOK, 368, 230, 40, 14
PUSHBUTTON "&Close", IDCANCEL, 411, 230, 40, 14
- DEFPUSHBUTTON "&Apply", IDAPPLY, 454, 230, 40, 14
+ PUSHBUTTON "&Apply", IDAPPLY, 454, 230, 40, 14
END