commit 62dfea006210ce32f3ee687f9c40d56eb26adcbd
parent 7b521042c393c183abc37408bff1159e4be2353c
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sat, 9 Jul 2016 20:31:44 -0400
merge Package Contents and Packages Histry in a single dialog
Diffstat:
13 files changed, 470 insertions(+), 384 deletions(-)
diff --git a/src/about.cpp b/src/about.cpp
@@ -22,6 +22,7 @@
#include "index.hpp"
#include "listview.hpp"
#include "menu.hpp"
+#include "ostream.hpp"
#include "reapack.hpp"
#include "registry.hpp"
#include "report.hpp"
@@ -30,119 +31,168 @@
#include "tabbar.hpp"
#include <boost/algorithm/string/replace.hpp>
-#include <sstream>
using namespace std;
-enum { ACTION_HISTORY = 300, ACTION_CONTENTS };
+enum { ACTION_ABOUT_PKG = 300 };
-About::About(IndexPtr index)
- : Dialog(IDD_ABOUT_DIALOG), m_index(index),
- m_currentCat(-255)
+AboutDialog::AboutDialog()
+ : Dialog(IDD_ABOUT_DIALOG), m_currentIndex(-255)
{
RichEdit::Init();
}
-void About::onInit()
+void AboutDialog::onInit()
{
Dialog::onInit();
- m_about = createControl<RichEdit>(IDC_ABOUT);
-
- m_cats = createControl<ListView>(IDC_CATEGORIES, ListView::Columns{
- {AUTO_STR("Category"), 142}
- });
+ auto_char title[255] = {};
+ const auto_string &name = make_autostring(what());
+ auto_snprintf(title, auto_size(title), AUTO_STR("About %s"), name.c_str());
+ SetWindowText(handle(), title);
- m_cats->onSelect(bind(&About::updatePackages, this));
+ m_tabs = createControl<TabBar>(IDC_TABS, TabBar::Tabs{});
- m_packages = createControl<ListView>(IDC_PACKAGES, ListView::Columns{
- {AUTO_STR("Name"), 382},
- {AUTO_STR("Version"), 80},
- {AUTO_STR("Author"), 90},
- });
+ m_menu = createMenu();
+ m_menu->sortByColumn(0);
+ m_menu->onSelect(bind(&AboutDialog::callUpdateList, this));
- m_packages->sortByColumn(0);
- m_packages->onActivate(bind(&About::packageHistory, this));
- m_packages->onContextMenu(bind(&About::fillContextMenu,
- this, placeholders::_1, placeholders::_2));
+ m_list = createList();
+ m_list->sortByColumn(0);
- m_installedFiles = getControl(IDC_LIST);
-
- m_tabs = createControl<TabBar>(IDC_TABS, TabBar::Tabs{
- {AUTO_STR("Description"), {m_about->handle()}},
- {AUTO_STR("Packages"), {m_cats->handle(), m_packages->handle()}},
- {AUTO_STR("Installed Files"), {m_installedFiles}},
- });
+ m_report = getControl(IDC_REPORT);
populate();
+ m_menu->sort();
+ callUpdateList();
#ifdef LVSCW_AUTOSIZE_USEHEADER
- m_cats->resizeColumn(m_cats->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
- m_packages->resizeColumn(m_packages->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
+ m_menu->resizeColumn(m_menu->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
+ m_list->resizeColumn(m_list->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
#endif
}
-void About::onCommand(const int id, int)
+void AboutDialog::onCommand(const int id, int)
{
switch(id) {
- case IDC_WEBSITE:
- selectLink(id, m_websiteLinks);
- break;
- case IDC_DONATE:
- selectLink(id, m_donationLinks);
- break;
- case IDC_INSTALL:
- close(InstallResult);
- break;
- case ACTION_CONTENTS:
- packageContents();
- break;
- case ACTION_HISTORY:
- packageHistory();
- break;
case IDOK:
case IDCANCEL:
close();
break;
default:
- if(id >> 8 == IDC_WEBSITE)
- openLink(m_websiteLinks[id & 0xff]);
- else if(id >> 8 == IDC_DONATE)
- openLink(m_donationLinks[id & 0xff]);
+ if(m_links.count(id))
+ selectLink(id);
+ else if(m_links.count(id >> 8))
+ openLink(m_links[id >> 8][id & 0xff]);
break;
}
}
-bool About::fillContextMenu(Menu &menu, const int) const
+void AboutDialog::callUpdateList()
{
- if(m_packages->currentIndex() < 0)
- return false;
+ const int index = m_menu->currentIndex();
- menu.addAction(AUTO_STR("Package &Contents"), ACTION_CONTENTS);
- menu.addAction(AUTO_STR("Package &History"), ACTION_HISTORY);
+ // do nothing when the selection is cleared, except for the initial execution
+ if((index < 0 && m_currentIndex >= -1) || index == m_currentIndex)
+ return;
- return true;
+ InhibitControl lock(m_list);
+ m_list->clear();
+
+ updateList(index);
+ m_currentIndex = index;
+
+ m_list->sort();
}
-void About::populate()
+void AboutDialog::addLinks(const int ctrl, const vector<const Link *> &links)
{
- auto_char title[32] = {};
- const auto_string &name = make_autostring(m_index->name());
- auto_snprintf(title, auto_size(title), AUTO_STR("About %s"), name.c_str());
- SetWindowText(handle(), title);
+ if(links.empty())
+ return;
- auto_char btnLabel[32] = {};
- auto_snprintf(btnLabel, auto_size(btnLabel),
- AUTO_STR("Install/update %s"), name.c_str());
- SetWindowText(getControl(IDC_INSTALL), btnLabel);
+ m_links[ctrl] = links;
+ show(getControl(ctrl));
+}
+
+void AboutDialog::selectLink(const int ctrl)
+{
+ const auto &links = m_links[ctrl];
+ const int count = (int)links.size();
+
+ m_tabs->setFocus();
+
+ if(count == 1) {
+ openLink(links.front());
+ return;
+ }
+
+ Menu menu;
+
+ for(int i = 0; i < count; i++) {
+ const string &name = boost::replace_all_copy(links[i]->name, "&", "&&");
+ menu.addAction(make_autostring(name).c_str(), i | (ctrl << 8));
+ }
+
+ RECT rect;
+ GetWindowRect(getControl(ctrl), &rect);
+ menu.show(rect.left, rect.bottom - 1, handle());
+}
+
+void AboutDialog::openLink(const Link *link)
+{
+ const auto_string &url = make_autostring(link->url);
+ ShellExecute(nullptr, AUTO_STR("open"), url.c_str(), nullptr, nullptr, SW_SHOW);
+}
+
+AboutRemote::AboutRemote(IndexPtr index)
+ : AboutDialog(), m_index(index)
+{
+}
+
+const string &AboutRemote::what() const
+{
+ return m_index->name();
+}
+
+ListView *AboutRemote::createMenu()
+{
+ return createControl<ListView>(IDC_MENU, ListView::Columns{
+ {AUTO_STR("Category"), 142}
+ });
+}
+
+ListView *AboutRemote::createList()
+{
+ return createControl<ListView>(IDC_LIST, ListView::Columns{
+ {AUTO_STR("Name"), 382},
+ {AUTO_STR("Version"), 80},
+ {AUTO_STR("Author"), 90},
+ });
+}
- m_websiteLinks = m_index->links(Index::WebsiteLink);
- if(m_websiteLinks.empty())
- hide(getControl(IDC_WEBSITE));
+void AboutRemote::onCommand(const int id, const int event)
+{
+ switch(id) {
+ case IDC_INSTALL:
+ close(InstallResult);
+ break;
+ case ACTION_ABOUT_PKG:
+ aboutPackage();
+ break;
+ default:
+ AboutDialog::onCommand(id, event);
+ break;
+ }
+}
- m_donationLinks = m_index->links(Index::DonationLink);
- if(m_donationLinks.empty())
- hide(getControl(IDC_DONATE));
+void AboutRemote::populate()
+{
+ HWND installBtn = getControl(IDC_INSTALL);
+ auto_char btnLabel[32] = {};
+ auto_snprintf(btnLabel, auto_size(btnLabel),
+ AUTO_STR("Install/update %s"), make_autostring(what()).c_str());
+ SetWindowText(installBtn, btnLabel);
+ show(installBtn);
string aboutText = m_index->aboutText();
@@ -151,59 +201,50 @@ void About::populate()
boost::replace_all(aboutText, "[[REAPACK_BUILDTIME]]", ReaPack::BUILDTIME);
}
- if(!m_about->setRichText(aboutText)) {
- // if description is invalid or empty, don't display it
- m_tabs->removeTab(0);
- m_tabs->setCurrentIndex(0);
- }
+ RichEdit *desc = createControl<RichEdit>(IDC_ABOUT);
+ if(desc->setRichText(aboutText))
+ tabs()->addTab({AUTO_STR("Description"), {desc->handle()}});
- m_cats->addRow({AUTO_STR("<All Packages>")});
+ tabs()->addTab({AUTO_STR("Packages"), {menu()->handle(), list()->handle()}});
+ tabs()->addTab({AUTO_STR("Installed Files"), {report()}});
- for(const Category *cat : m_index->categories())
- m_cats->addRow({make_autostring(cat->name())});
+ list()->onActivate(bind(&AboutRemote::aboutPackage, this));
- m_cats->sortByColumn(0);
+ addLinks(IDC_WEBSITE, m_index->links(Index::WebsiteLink));
+ addLinks(IDC_DONATE, m_index->links(Index::DonationLink));
- updatePackages();
+ menu()->addRow({AUTO_STR("<All Packages>")});
+
+ for(const Category *cat : m_index->categories())
+ menu()->addRow({make_autostring(cat->name())});
updateInstalledFiles();
+
+ list()->onContextMenu(bind(&AboutRemote::fillContextMenu,
+ this, placeholders::_1, placeholders::_2));
}
-void About::updatePackages()
+void AboutRemote::updateList(const int index)
{
- const int index = m_cats->currentIndex();
-
- // do nothing when the selection is cleared, except for the initial execution
- if(index == -1 && m_currentCat >= -1)
- return;
-
// -1: all packages, >0 selected category
const int catIndex = max(-1, index - 1);
- if(catIndex == m_currentCat)
- return;
- else if(catIndex < 0)
+ if(catIndex < 0)
m_packagesData = &m_index->packages();
else
m_packagesData = &m_index->category(catIndex)->packages();
- InhibitControl lock(m_packages);
- m_packages->clear();
-
for(const Package *pkg : *m_packagesData) {
const Version *lastVer = pkg->lastVersion();
const auto_string &name = make_autostring(pkg->name());
const auto_string &version = make_autostring(lastVer->name());
const auto_string &author = make_autostring(lastVer->displayAuthor());
- m_packages->addRow({name, version, author});
+ list()->addRow({name, version, author});
}
-
- m_currentCat = catIndex;
- m_packages->sort();
}
-void About::updateInstalledFiles()
+void AboutRemote::updateInstalledFiles()
{
set<Registry::File> allFiles;
@@ -222,12 +263,12 @@ void About::updateInstalledFiles()
AUTO_STR("Retry later when all installation task are completed.\r\n")
AUTO_STR("\r\nError description: %s"),
desc.c_str());
- SetWindowText(m_installedFiles, msg);
+ SetWindowText(report(), msg);
return;
}
if(allFiles.empty()) {
- SetWindowText(m_installedFiles,
+ SetWindowText(report(),
AUTO_STR(
"This repository does not own any file on your computer at this time.\r\n")
@@ -244,57 +285,105 @@ void About::updateInstalledFiles()
stream << "\r\n";
}
- SetWindowText(m_installedFiles, make_autostring(stream.str()).c_str());
+ SetWindowText(report(), make_autostring(stream.str()).c_str());
}
}
-void About::selectLink(const int ctrl, const vector<const Link *> &links)
+bool AboutRemote::fillContextMenu(Menu &menu, const int) const
{
- const int count = (int)links.size();
+ if(list()->currentIndex() < 0)
+ return false;
- m_tabs->setFocus();
+ menu.addAction(AUTO_STR("Package &Overview"), ACTION_ABOUT_PKG);
- if(count == 1) {
- openLink(links.front());
- return;
- }
+ return true;
+}
- Menu menu;
+void AboutRemote::aboutPackage()
+{
+ const int index = list()->currentIndex();
- for(int i = 0; i < count; i++) {
- const string &name = boost::replace_all_copy(links[i]->name, "&", "&&");
- menu.addAction(make_autostring(name).c_str(), i | (ctrl << 8));
- }
+ if(index < 0)
+ return;
- RECT rect;
- GetWindowRect(getControl(ctrl), &rect);
- menu.show(rect.left, rect.bottom - 1, handle());
+ const Package *pkg = m_packagesData->at(index);
+ Dialog::Show<AboutPackage>(instance(), handle(), pkg);
}
-void About::openLink(const Link *link)
+AboutPackage::AboutPackage(const Package *pkg)
+ : AboutDialog(), m_package(pkg)
{
- const auto_string &url = make_autostring(link->url);
- ShellExecute(nullptr, AUTO_STR("open"), url.c_str(), nullptr, nullptr, SW_SHOW);
}
-void About::packageHistory()
+const string &AboutPackage::what() const
{
- const int index = m_packages->currentIndex();
+ return m_package->name();
+}
- if(index < 0)
- return;
+ListView *AboutPackage::createMenu()
+{
+ return createControl<ListView>(IDC_MENU, ListView::Columns{
+ {AUTO_STR("Version"), 142}
+ });
+}
- const Package *pkg = m_packagesData->at(index);
- Dialog::Show<History>(instance(), handle(), pkg);
+ListView *AboutPackage::createList()
+{
+ return createControl<ListView>(IDC_LIST, ListView::Columns{
+ {AUTO_STR("File"), 251},
+ {AUTO_STR("Source"), 251},
+ {AUTO_STR("Main"), 50},
+ });
}
-void About::packageContents()
+void AboutPackage::populate()
{
- const int index = m_packages->currentIndex();
+ // RichEdit *desc = createControl<RichEdit>(IDC_ABOUT);
+ // if(desc->setRichText(aboutText))
+ // tabs()->addTab({AUTO_STR("Documentation"), {desc->handle()}});
+
+ tabs()->addTab({AUTO_STR("History"), {menu()->handle(),
+ report()}});
+ tabs()->addTab({AUTO_STR("Contents"), {menu()->handle(),
+ list()->handle()}});
+
+ RECT rect;
+ GetWindowRect(list()->handle(), &rect);
+ ScreenToClient(handle(), (LPPOINT)&rect);
+ ScreenToClient(handle(), ((LPPOINT)&rect)+1);
+
+ SetWindowPos(report(), nullptr, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ for(const Version *ver : m_package->versions())
+ menu()->addRow({make_autostring(ver->name())});
+ menu()->setSortCallback(0, [&] (const int a, const int b) {
+ return m_package->version(a)->compare(*m_package->version(b));
+ });
+ menu()->sortByColumn(0, ListView::DescendingOrder);
+ menu()->setSelected(menu()->rowCount() - 1, true);
+}
+
+void AboutPackage::updateList(const int index)
+{
if(index < 0)
return;
- const Package *pkg = m_packagesData->at(index);
- Dialog::Show<Contents>(instance(), handle(), pkg);
+ const Version *ver = m_package->version(index);
+ OutputStream stream;
+ stream << *ver;
+ SetWindowText(report(), make_autostring(stream.str()).c_str());
+
+ const auto &sources = ver->sources();
+ for(auto it = sources.begin(); it != sources.end();) {
+ const Path &path = it->first;
+ const Source *src = it->second;
+
+ list()->addRow({make_autostring(path.join()), make_autostring(src->url()),
+ make_autostring(src->isMain() ? "Yes" : "No")});
+
+ // skip duplicate files
+ do { it++; } while(it != sources.end() && path == it->first);
+ }
}
diff --git a/src/about.hpp b/src/about.hpp
@@ -20,6 +20,7 @@
#include "dialog.hpp"
+#include <map>
#include <memory>
#include <vector>
@@ -33,38 +34,80 @@ struct Link;
typedef std::shared_ptr<const Index> IndexPtr;
-class About : public Dialog {
+class AboutDialog : public Dialog {
+public:
+ AboutDialog();
+
+protected:
+ void onInit() override;
+ void onCommand(int, int) override;
+
+ virtual const std::string &what() const = 0;
+ virtual ListView *createMenu() = 0;
+ virtual ListView *createList() = 0;
+
+ virtual void populate() = 0;
+ virtual void updateList(int) = 0;
+
+ TabBar *tabs() const { return m_tabs; }
+ ListView *menu() const { return m_menu; }
+ ListView *list() const { return m_list; }
+ HWND report() const { return m_report; }
+
+ void addLinks(int control, const std::vector<const Link *> &);
+
+private:
+ void selectLink(int control);
+ void openLink(const Link *);
+ void callUpdateList();
+
+ int m_currentIndex;
+ TabBar *m_tabs;
+ ListView *m_menu;
+ ListView *m_list;
+ HWND m_report;
+
+ std::map<int, std::vector<const Link *> > m_links;
+};
+
+class AboutRemote : public AboutDialog {
public:
enum { InstallResult = 100 };
- About(IndexPtr);
+ AboutRemote(IndexPtr);
protected:
- void onInit() override;
+ const std::string &what() const override;
+ ListView *createMenu() override;
+ ListView *createList() override;
+
void onCommand(int, int) override;
+ void populate() override;
+ void updateList(int) override;
private:
bool fillContextMenu(Menu &, int index) const;
- void populate();
- void updatePackages();
void updateInstalledFiles();
- void selectLink(int control, const std::vector<const Link *> &);
- void openLink(const Link *);
- void packageHistory();
- void packageContents();
+ void aboutPackage();
IndexPtr m_index;
- int m_currentCat;
+ const std::vector<const Package *> *m_packagesData;
+};
- TabBar *m_tabs;
- RichEdit *m_about;
- ListView *m_cats;
- ListView *m_packages;
- HWND m_installedFiles;
+class AboutPackage : public AboutDialog {
+public:
+ AboutPackage(const Package *);
- std::vector<const Link *> m_websiteLinks;
- std::vector<const Link *> m_donationLinks;
- const std::vector<const Package *> *m_packagesData;
+protected:
+ const std::string &what() const override;
+ ListView *createMenu() override;
+ ListView *createList() override;
+
+ void populate() override;
+ void updateList(int) override;
+
+private:
+ const Package *m_package;
};
#endif
diff --git a/src/browser.cpp b/src/browser.cpp
@@ -44,9 +44,8 @@ enum Action {
ACTION_UNINSTALL,
ACTION_UNINSTALL_ALL,
ACTION_PIN,
- ACTION_CONTENTS,
- ACTION_HISTORY,
- ACTION_ABOUT,
+ ACTION_ABOUT_PKG,
+ ACTION_ABOUT_REMOTE,
ACTION_RESET_ALL,
ACTION_SHOWDESCS,
ACTION_REFRESH,
@@ -79,7 +78,7 @@ void Browser::onInit()
SendMessage(m_view, CB_ADDSTRING, 0, (LPARAM)AUTO_STR("Uninstalled"));
SendMessage(m_view, CB_SETCURSEL, 0, 0);
- m_list = createControl<ListView>(IDC_PACKAGES, ListView::Columns{
+ m_list = createControl<ListView>(IDC_LIST, ListView::Columns{
{AUTO_STR("Status"), 23, ListView::NoLabelFlag},
{AUTO_STR("Package"), 380},
{AUTO_STR("Category"), 150},
@@ -90,7 +89,7 @@ void Browser::onInit()
{AUTO_STR("Last Update"), 120, ListView::CollapseFlag},
});
- m_list->onActivate([=] { history(m_list->itemUnderMouse()); });
+ m_list->onActivate([=] { aboutPackage(m_list->itemUnderMouse()); });
m_list->onSelect([=] { setEnabled(m_list->hasSelection(), m_actionsBtn); });
m_list->onContextMenu(bind(&Browser::fillContextMenu,
this, placeholders::_1, placeholders::_2));
@@ -183,14 +182,11 @@ void Browser::onCommand(const int id, const int event)
case ACTION_PIN:
togglePin(m_currentIndex);
break;
- case ACTION_CONTENTS:
- contents(m_currentIndex);
+ case ACTION_ABOUT_PKG:
+ aboutPackage(m_currentIndex);
break;
- case ACTION_HISTORY:
- history(m_currentIndex);
- break;
- case ACTION_ABOUT:
- about(m_currentIndex);
+ case ACTION_ABOUT_REMOTE:
+ aboutRemote(m_currentIndex);
break;
case ACTION_RESET_ALL:
selectionDo(bind(&Browser::resetActions, this, placeholders::_1));
@@ -361,16 +357,13 @@ void Browser::fillMenu(Menu &menu)
menu.addSeparator();
menu.setEnabled(!entry->test(ObsoleteFlag),
- menu.addAction(AUTO_STR("Package &Contents"), ACTION_CONTENTS));
-
- menu.setEnabled(!entry->test(ObsoleteFlag),
- menu.addAction(AUTO_STR("Package &History"), ACTION_HISTORY));
+ menu.addAction(AUTO_STR("Package &Overview..."), ACTION_ABOUT_PKG));
auto_char aboutLabel[32] = {};
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);
+ menu.addAction(aboutLabel, ACTION_ABOUT_REMOTE);
}
void Browser::updateDisplayLabel()
@@ -800,23 +793,13 @@ auto Browser::getEntry(const int listIndex) -> Entry *
return &m_entries[m_visibleEntries[listIndex]];
}
-void Browser::history(const int index)
+void Browser::aboutPackage(const int index)
{
- const Entry *entry = getEntry(index);
-
- if(entry && entry->package)
- Dialog::Show<History>(instance(), handle(), entry->package);
-}
-
-void Browser::contents(const int index)
-{
- const Entry *entry = getEntry(index);
-
- if(entry)
- Dialog::Show<Contents>(instance(), handle(), entry->package);
+ if(const Entry *entry = getEntry(index))
+ m_reapack->about(entry->package, handle());
}
-void Browser::about(const int index)
+void Browser::aboutRemote(const int index)
{
if(const Entry *entry = getEntry(index))
m_reapack->about(getRemote(*entry), handle());
diff --git a/src/browser.hpp b/src/browser.hpp
@@ -131,9 +131,8 @@ private:
void installVersion(int index, size_t verIndex);
void uninstall(int index, bool toggle = true);
void togglePin(int index);
- void history(int index);
- void contents(int index);
- void about(int index);
+ void aboutRemote(int index);
+ void aboutPackage(int index);
std::vector<IndexPtr> m_indexes;
ReaPack *m_reapack;
diff --git a/src/ostream.cpp b/src/ostream.cpp
@@ -0,0 +1,59 @@
+/* ReaPack: Package manager for REAPER
+ * Copyright (C) 2015-2016 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 "ostream.hpp"
+
+#include "version.hpp"
+
+#include <locale>
+
+using namespace std;
+
+OutputStream::OutputStream()
+{
+ // enable number formatting (ie. "1,234" instead of "1234")
+ m_stream.imbue(locale(""));
+}
+
+void OutputStream::indented(const string &text)
+{
+ istringstream stream(text);
+ string line;
+
+ while(getline(stream, line, '\n'))
+ m_stream << "\x20\x20" << line.substr(line.find_first_not_of('\x20')) << "\r\n";
+}
+
+OutputStream &OutputStream::operator<<(const Version &ver)
+{
+ m_stream << 'v' << ver.name();
+
+ if(!ver.author().empty())
+ m_stream << " by " << ver.author();
+
+ const string &date = ver.time().toString();
+ if(!date.empty())
+ m_stream << " – " << date;
+
+ m_stream << "\r\n";
+
+ const string &changelog = ver.changelog();
+ indented(changelog.empty() ? "No changelog" : changelog);
+
+ return *this;
+}
+
diff --git a/src/ostream.hpp b/src/ostream.hpp
@@ -0,0 +1,42 @@
+/* ReaPack: Package manager for REAPER
+ * Copyright (C) 2015-2016 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_OSTREAM_HPP
+#define REAPACK_OSTREAM_HPP
+
+#include <sstream>
+
+class Version;
+
+class OutputStream {
+public:
+ OutputStream();
+
+ std::ostringstream::pos_type tellp() { return m_stream.tellp(); }
+ std::string str() const { return m_stream.str(); }
+
+ void indented(const std::string &);
+
+ template<typename T>
+ OutputStream &operator<<(T t) { m_stream << t; return *this; }
+ OutputStream &operator<<(const Version &);
+
+private:
+ std::ostringstream m_stream;
+};
+
+#endif
diff --git a/src/reapack.cpp b/src/reapack.cpp
@@ -238,9 +238,9 @@ void ReaPack::about(const Remote &remote, HWND parent)
if(!index)
return;
- const auto ret = Dialog::Show<About>(m_instance, parent, index);
+ const auto ret = Dialog::Show<AboutRemote>(m_instance, parent, index);
- if(ret == About::InstallResult) {
+ if(ret == AboutRemote::InstallResult) {
Transaction *tx = setupTransaction();
if(!tx)
@@ -254,6 +254,14 @@ void ReaPack::about(const Remote &remote, HWND parent)
}, parent);
}
+void ReaPack::about(const Package *pkg, HWND parent)
+{
+ const auto ret = Dialog::Show<AboutPackage>(m_instance, parent, pkg);
+
+ switch(ret) {
+ }
+}
+
void ReaPack::browsePackages()
{
if(m_browser) {
diff --git a/src/reapack.hpp b/src/reapack.hpp
@@ -71,8 +71,8 @@ public:
void importRemote();
void manageRemotes();
void aboutSelf();
- void about(const std::string &, HWND parent);
void about(const Remote &, HWND parent);
+ void about(const Package *, HWND parent);
void browsePackages();
void refreshManager();
void refreshBrowser();
diff --git a/src/report.cpp b/src/report.cpp
@@ -24,21 +24,15 @@
#include "transaction.hpp"
#include <boost/range/adaptor/reversed.hpp>
-#include <locale>
using namespace std;
-static const string SEP(10, '=');
-const char * const ReportDialog::NL = "\r\n";
-
-ReportDialog::ReportDialog()
- : Dialog(IDD_REPORT_DIALOG)
+Report::Report(const Receipt &receipt)
+ : Dialog(IDD_REPORT_DIALOG), m_receipt(receipt)
{
- // enable number formatting (ie. "1,234" instead of "1234")
- m_stream.imbue(locale(""));
}
-void ReportDialog::onInit()
+void Report::onInit()
{
Dialog::onInit();
@@ -48,46 +42,13 @@ void ReportDialog::onInit()
SetDlgItemText(handle(), IDC_REPORT, str.c_str());
}
-void ReportDialog::printHeader(const char *title)
+void Report::printHeader(const char *title)
{
if(m_stream.tellp())
- m_stream << NL;
-
- m_stream << SEP << ' ' << title << ": " << SEP << NL << NL;
-}
-
-void ReportDialog::printVersion(const Version *ver)
-{
- stream() << 'v' << ver->name();
+ m_stream << "\r\n";
- if(!ver->author().empty())
- stream() << " by " << ver->author();
-
- const string &date = ver->time().toString();
- if(!date.empty())
- stream() << " – " << date;
-
- stream() << NL;
-}
-
-void ReportDialog::printChangelog(const Version *ver)
-{
- const string &changelog = ver->changelog();
- printIndented(changelog.empty() ? "No changelog" : changelog);
-}
-
-void ReportDialog::printIndented(const string &text)
-{
- istringstream stream(text);
- string line;
-
- while(getline(stream, line, '\n'))
- m_stream << "\x20\x20" << line.substr(line.find_first_not_of('\x20')) << NL;
-}
-
-Report::Report(const Receipt &receipt)
- : ReportDialog(), m_receipt(receipt)
-{
+ const string sep(10, '=');
+ m_stream << sep << ' ' << title << ": " << sep << "\r\n\r\n";
}
void Report::fillReport()
@@ -97,20 +58,20 @@ void Report::fillReport()
const size_t removals = m_receipt.removals().size();
const size_t errors = m_receipt.errors().size();
- stream()
+ m_stream
<< installs << " installed packages, "
<< updates << " updates, "
<< removals << " removed files and "
<< errors << " errors"
- << NL
+ << "\r\n"
;
if(m_receipt.isRestartNeeded()) {
- stream()
- << NL
- << "Notice: One or more native REAPER extensions were installed." << NL
+ m_stream
+ << "\r\n"
+ << "Notice: One or more native REAPER extensions were installed.\r\n"
<< "The newly installed files won't be loaded until REAPER is restarted."
- << NL;
+ << "\r\n";
}
if(errors)
@@ -131,31 +92,30 @@ void Report::printInstalls()
printHeader("Installed packages");
for(const InstallTicket &ticket : m_receipt.installs())
- stream() << ticket.version->fullName() << NL;
+ m_stream << ticket.version->fullName() << "\r\n";
}
void Report::printUpdates()
{
printHeader("Updates");
- const auto start = stream().tellp();
+ const auto start = m_stream.tellp();
for(const InstallTicket &ticket : m_receipt.updates()) {
const Package *pkg = ticket.version->package();
const Registry::Entry ®Entry = ticket.regEntry;
const VersionSet &versions = pkg->versions();
- if(stream().tellp() != start)
- stream() << NL;
+ if(m_stream.tellp() != start)
+ m_stream << "\r\n";
- stream() << pkg->fullName() << ':' << NL;
+ m_stream << pkg->fullName() << ":\r\n";
for(const Version *ver : versions | boost::adaptors::reversed) {
if(*ver <= regEntry.version)
break;
- printVersion(ver);
- printChangelog(ver);
+ m_stream << *ver;
}
}
}
@@ -164,14 +124,14 @@ void Report::printErrors()
{
printHeader("Errors");
- const auto start = stream().tellp();
+ const auto start = m_stream.tellp();
for(const Receipt::Error &err : m_receipt.errors()) {
- if(stream().tellp() != start)
- stream() << NL;
+ if(m_stream.tellp() != start)
+ m_stream << "\r\n";
- stream() << err.title << ':' << NL;
- printIndented(err.message);
+ m_stream << err.title << ":\r\n";
+ m_stream.indented(err.message);
}
}
@@ -180,57 +140,5 @@ void Report::printRemovals()
printHeader("Removed files");
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);
- printChangelog(ver);
- }
-}
-
-Contents::Contents(const Package *pkg)
- : ReportDialog(), m_package(pkg)
-{
-}
-
-void Contents::fillReport()
-{
- SetWindowText(handle(), AUTO_STR("Package Contents"));
- 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);
-
- const auto &sources = ver->sources();
- for(auto it = sources.begin(); it != sources.end();) {
- const Path &path = it->first;
- const string &file = path.join();
- const Source *src = it->second;
-
- printIndented(src->isMain() ? file + '*' : file);
- printIndented("Source: " + src->url());
-
- // skip duplicate files
- do { it++; } while(it != sources.end() && path == it->first);
- }
- }
+ m_stream << path.join() << "\r\n";
}
diff --git a/src/report.hpp b/src/report.hpp
@@ -20,71 +20,32 @@
#include "dialog.hpp"
+#include "ostream.hpp"
#include "receipt.hpp"
#include "registry.hpp"
-#include <sstream>
-
class Package;
class Version;
-class ReportDialog : public Dialog {
+class Report : public Dialog {
public:
- ReportDialog();
+ Report(const Receipt &);
protected:
void onInit() override;
- virtual void fillReport() = 0;
-
- static const char * const NL;
- std::ostringstream &stream() { return m_stream; }
+ virtual void fillReport();
void printHeader(const char *);
- void printVersion(const Version *);
- void printChangelog(const Version *);
- void printIndented(const std::string &);
-
-private:
- std::ostringstream m_stream;
-};
-
-class Report : public ReportDialog {
-public:
- Report(const Receipt &);
-
-protected:
- void fillReport() override;
-private:
void printInstalls();
void printUpdates();
void printErrors();
void printRemovals();
- Receipt m_receipt;
-};
-
-class History : public ReportDialog {
-public:
- History(const Package *);
-
-protected:
- void fillReport() override;
-
private:
- const Package *m_package;
-};
-
-class Contents : public ReportDialog {
-public:
- Contents(const Package *);
-
-protected:
- void fillReport() override;
-
-private:
- const Package *m_package;
+ Receipt m_receipt;
+ OutputStream m_stream;
};
#endif
diff --git a/src/resource.hpp b/src/resource.hpp
@@ -54,19 +54,18 @@
#define IDC_WEBSITE 216
#define IDC_DONATE 217
#define IDC_ABOUT 218
-#define IDC_CATEGORIES 219
-#define IDC_PACKAGES 220
-#define IDC_GROUPBOX 221
-#define IDC_URL 222
-#define IDC_FILTER 223
-#define IDC_CLEAR 224
-#define IDC_DISPLAY 225
-#define IDC_SELECT 226
-#define IDC_UNSELECT 227
-#define IDC_OPTIONS 228
-#define IDC_ACTIONS 229
-#define IDC_BROWSE 230
-#define IDC_PROXY 231
-#define IDC_VERIFYPEER 232
+#define IDC_MENU 219
+#define IDC_GROUPBOX 220
+#define IDC_URL 221
+#define IDC_FILTER 222
+#define IDC_CLEAR 223
+#define IDC_DISPLAY 224
+#define IDC_SELECT 225
+#define IDC_UNSELECT 226
+#define IDC_OPTIONS 227
+#define IDC_ACTIONS 228
+#define IDC_BROWSE 228
+#define IDC_PROXY 229
+#define IDC_VERIFYPEER 230
#endif
diff --git a/src/resource.rc b/src/resource.rc
@@ -41,28 +41,28 @@ BEGIN
PUSHBUTTON "&Apply", IDAPPLY, 284, 161, 40, 14
END
-IDD_ABOUT_DIALOG DIALOGEX 0, 0, 460, 270
+IDD_ABOUT_DIALOG DIALOGEX 0, 0, 460, 267
STYLE DIALOG_STYLE
FONT DIALOG_FONT
BEGIN
CONTROL "", IDC_TABS, WC_TABCONTROL, 0, 0, 2, 460, 243
#ifdef _WIN32
CONTROL "", IDC_ABOUT, MSFTEDIT_CLASS, WS_VSCROLL | ES_MULTILINE |
- ES_READONLY | NOT WS_TABSTOP, 10, 20, 440, 220
+ ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE, 10, 20, 440, 220
#else
EDITTEXT IDC_ABOUT, 10, 20, 440, 220,
- WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP
+ WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE
#endif
- CONTROL "", IDC_CATEGORIES, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL |
- LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 10, 20, 96, 220
- CONTROL "", IDC_PACKAGES, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL |
- LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 110, 20, 340, 220
- EDITTEXT IDC_LIST, 10, 20, 440, 220,
- WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP
- PUSHBUTTON "&Website", IDC_WEBSITE, 5, 250, 45, 14
- PUSHBUTTON "&Donate...", IDC_DONATE, 53, 250, 45, 14
- PUSHBUTTON "", IDC_INSTALL, 286, 250, 120, 14
- DEFPUSHBUTTON "&Close", IDOK, 409, 250, 45, 14
+ CONTROL "", IDC_MENU, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL |
+ LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE, 10, 20, 96, 220
+ CONTROL "", IDC_LIST, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL |
+ LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE, 110, 20, 340, 220
+ EDITTEXT IDC_REPORT, 10, 20, 440, 220,
+ WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE
+ PUSHBUTTON "&Website", IDC_WEBSITE, 5, 248, 45, 14, NOT WS_VISIBLE
+ PUSHBUTTON "&Donate...", IDC_DONATE, 53, 248, 45, 14, NOT WS_VISIBLE
+ PUSHBUTTON "", IDC_INSTALL, 286, 248, 120, 14, NOT WS_VISIBLE
+ DEFPUSHBUTTON "&Close", IDOK, 409, 248, 45, 14
END
IDD_IMPORT_DIALOG DIALOGEX 0, 0, 290, 69
@@ -90,7 +90,7 @@ BEGIN
LTEXT "Display:", IDC_LABEL2, 286, 7, 30, 10
COMBOBOX IDC_TABS, 314, 5, 65, 54, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "", IDC_DISPLAY, 385, 4, 110, 14
- CONTROL "", IDC_PACKAGES, WC_LISTVIEW, LVS_REPORT | LVS_SHOWSELALWAYS |
+ CONTROL "", IDC_LIST, WC_LISTVIEW, LVS_REPORT | LVS_SHOWSELALWAYS |
WS_BORDER | WS_TABSTOP, 5, 22, 490, 205
PUSHBUTTON "&Select all", IDC_SELECT, 5, 231, 50, 14
PUSHBUTTON "&Unselect all", IDC_UNSELECT, 58, 231, 50, 14
diff --git a/src/tabbar.cpp b/src/tabbar.cpp
@@ -32,9 +32,6 @@ int TabBar::addTab(const Tab &tab)
{
int index = m_size++;
- for(HWND control : tab.page)
- ShowWindow(control, SW_HIDE);
-
m_pages.push_back(tab.page);
TCITEM item{};
@@ -62,13 +59,11 @@ void TabBar::setCurrentIndex(const int index)
void TabBar::removeTab(const int index)
{
- if(!TabCtrl_DeleteItem(handle(), index))
- return;
-
- for(HWND control : m_pages[index])
- ShowWindow(control, SW_HIDE);
+ if(currentIndex() == index)
+ setCurrentIndex(index == 0 ? index + 1 : index - 1);
- m_pages.erase(m_pages.begin() + index);
+ if(TabCtrl_DeleteItem(handle(), index))
+ m_pages.erase(m_pages.begin() + index);
}
void TabBar::setFocus()