diff options
author | Your Name <you@example.com> | 2020-11-07 09:30:53 -0500 |
---|---|---|
committer | Your Name <you@example.com> | 2020-11-07 09:30:53 -0500 |
commit | 89a449c2ab9d736c1f03c78b745e814424e01360 (patch) | |
tree | 25c4d03bd39a5ddbe1b7f28713e82bf174a29216 /mods.cc | |
download | biblereader-89a449c2ab9d736c1f03c78b745e814424e01360.tar.gz biblereader-89a449c2ab9d736c1f03c78b745e814424e01360.tar.bz2 biblereader-89a449c2ab9d736c1f03c78b745e814424e01360.zip |
Initial commit
Diffstat (limited to 'mods.cc')
-rw-r--r-- | mods.cc | 208 |
1 files changed, 208 insertions, 0 deletions
@@ -0,0 +1,208 @@ +#include "mods.h" +#include "header.h" +#include "readerview.h" +#include <iostream> +#include <thread> +#include <sys/types.h> +#include <sys/stat.h> + +// We want: https://developer.gnome.org/gtkmm-tutorial/stable/sec-multithread-example.html.en +void Mods::update(unsigned long totalBytes, unsigned long completedBytes, std::string mess) +{ + std::lock_guard<std::mutex> lock(progressMutex); + if (!totalBytes) { + //printf("Received a 0 totalBytes\n"); + dispatcher.emit(); + return; + } + fracDone = (completedBytes / totalBytes); + message = mess; + //printf("Progress: %f\n", fracDone); + dispatcher.emit(); +} + +void Mods::getStatus(double *fractionDone, std::string *mess, bool *isComplete) const { + std::lock_guard<std::mutex> lock(progressMutex); + *fractionDone = fracDone; + *mess = message; + *isComplete = complete; +} + +void Mods::onNotify() { + double fractionDone; + std::string mess; + bool isComplete; + getStatus(&fractionDone, &mess, &isComplete); + if(isComplete) { + if(worker && worker->joinable()) { + worker->join(); + header->reader->modsUpdated(); + header->updateButtons(); + header->updateMenus(); + endProgress(); + } + delete worker; + worker = nullptr; + } else { + showProgress(mess); + if(fractionDone >= 0 && fractionDone <= 1) { + progressBar.set_fraction(fractionDone); + } else { + progressBar.pulse(); + } + } +} + +void Mods::showProgress(std::string message) { + progressDialog.set_message(message); + progressDialog.show(); + progressDialog.show_all_children(); +} + +void Mods::endProgress() { + progressDialog.hide(); + return; +} + +Mods::Mods(Header *header, Gtk::Window *window) : modsAvailable(), progressDialog("", false, Gtk::MessageType::MESSAGE_INFO, Gtk::ButtonsType::BUTTONS_CANCEL), progressBar(), dispatcher(), progressMutex(), worker(nullptr) { + this->header = header; + this->window = window; + dispatcher.connect(sigc::mem_fun(*this, &Mods::onNotify)); + progressDialog.signal_response().connect([this](int response) { + libbible::terminateDownload(); + }); + progressDialog.get_message_area()->add(progressBar); + progressBar.show(); + displayMain(); +} + +Mods::~Mods() {} + +void Mods::displayMain() { + remove(); + auto *scroll = Gtk::manage(new Gtk::ScrolledWindow); + add(*scroll); + auto *vbox = Gtk::manage(new Gtk::VBox); + scroll->add(*vbox); + auto *label = Gtk::manage(new Gtk::Label); + label->set_text("Install new mods"); + vbox->pack_start(*label, false, false); + auto *hbox = Gtk::manage(new Gtk::HBox); + vbox->pack_start(*hbox, false, false); + auto *network = Gtk::manage(new Gtk::VBox); + hbox->add(*network); + label = Gtk::manage(new Gtk::Label); + label->set_text("Download over the network"); + network->pack_start(*label, false, false); + auto *button = Gtk::manage(new Gtk::Button("Download")); + network->pack_start(*button, false, false); + button->signal_clicked().connect([this]() { + updateInstallable(); + displayDownload(); + }); + auto *local = Gtk::manage(new Gtk::VBox); + hbox->add(*local); + label = Gtk::manage(new Gtk::Label); + label->set_text("Install local .zip file"); + local->pack_start(*label, false, false); + Gtk::FileChooserButton *add = Gtk::manage(new Gtk::FileChooserButton("Install SWORD modules", Gtk::FILE_CHOOSER_ACTION_OPEN)); + local->pack_start(*add, false, false); + auto filter = Gtk::FileFilter::create(); + filter->add_mime_type("application/zip"); + add->set_filter(filter); + add->signal_file_set().connect([this, add]() { + installMods(add->get_filenames()); + auto newMods = this->header->reader->modsUpdated(); + if(! newMods.empty()) { + this->header->reader->setVersion(newMods[0]); + } + this->header->updateMenus(); + this->header->updateButtons(); + this->header->showText(); + }); + window->show_all_children(); +} + +void Mods::displayDownload() { + remove(); + auto *scroll = Gtk::manage(new Gtk::ScrolledWindow); + add(*scroll); + auto *vbox = Gtk::manage(new Gtk::VBox); + //vbox->set_homogeneous(false); + //vbox->set_hexpand(false); + scroll->add(*vbox); + auto *button = Gtk::manage(new Gtk::Button("Back")); + vbox->pack_start(*button, false, false); + button->signal_clicked().connect([this]() { + displayMain(); + }); + auto *label = Gtk::manage(new Gtk::Label); + label->set_text("Language Selection:"); + vbox->pack_start(*label, false, false); + auto *langMenuButton = Gtk::manage(new Gtk::MenuButton); + // Perhaps default to English? Or if translations for the app are added, default to the global language setting? + langMenuButton->set_label("Select Language"); + vbox->pack_start(*langMenuButton, false, false); + label = Gtk::manage(new Gtk::Label); + label->set_text("Mods Available:"); + vbox->pack_start(*label, false, false); + auto *modsSelection = Gtk::manage(new Gtk::VBox); + modsSelection->set_vexpand(true); + vbox->pack_end(*modsSelection); + auto *langMenu = Gtk::manage(new Gtk::PopoverMenu); + auto *sw = Gtk::manage(new Gtk::ScrolledWindow); + langMenu->add(*sw); + auto *langBox = Gtk::manage(new Gtk::VBox); + sw->add(*langBox); + sw->set_propagate_natural_width(true); + sw->set_min_content_height(300); + for(auto item : modsAvailable) { + string language = item.first; + auto *langButton = Gtk::manage(new Gtk::Button(language)); + langButton->set_relief(Gtk::ReliefStyle::RELIEF_NONE); + langButton->signal_clicked().connect([language, langMenuButton, langMenu, modsSelection, this]() { + langMenu->popdown(); + langMenuButton->set_label(language); + for(auto child : modsSelection->get_children()) { + modsSelection->remove(*child); + } + for(string name : modsAvailable[language]) { + auto *installButton = Gtk::manage(new Gtk::Button(name)); + installButton->signal_clicked().connect([language, name, this]() { + worker = new std::thread([language, name, this] { + complete = false; + libbible::installModFromInternet(language, name); + complete = true; + dispatcher.emit(); + header->showText(); + }); + }); + modsSelection->pack_start(*installButton, false, false); + } + modsSelection->show_all_children(); + }); + langBox->add(*langButton); + } + langMenuButton->set_popover(*langMenu); + langMenu->show_all_children(); + window->show_all_children(); +} + +void Mods::installMods(std::vector<std::string> filenames) { + for(auto filename : filenames) { + libbible::installModFromZip(filename); + } +} + +void Mods::uninstallMods(std::vector<std::string> modnames) { + for(auto mod : modnames) { + libbible::uninstallMod(mod); + } +} + +void Mods::updateInstallable() { + if(! modsAvailable.empty()) { + return; + } + modsAvailable = libbible::downloadModsAvailable(this); +} |