/* $Id: gtk-makeimage.cc,v 1.19 2005/04/10 16:36:31 atterer Exp $ -*- C++ -*- __ _ |_) /| Copyright (C) 2003 | richard@ | \/¯| Richard Atterer | atterer.net ¯ '` ¯ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2. See the file COPYING for details. Download and processing of .jigdo files - GTK+ frontend */ #include #include #include #include //______________________________________________________________________ DEBUG_UNIT("gtk-makeimage") GtkMakeImage::GtkMakeImage(const string& uriStr, const string& destDir) : progress(), status(), treeViewStatus(), dest(), imageInfo(_("\nDownloading .jigdo data - please wait...")), imageShortInfo(), mid(uriStr, destDir) { mid.io.addListener(*this); // Remove all trailing '/' from dest dir, even if result empty unsigned destLen = destDir.length(); while (destLen > 0 && destDir[destLen - 1] == DIRSEP) --destLen; dest.assign(destDir, 0, destLen); } GtkMakeImage::~GtkMakeImage() { mid.killAllChildren(); /* Delete all children. A simpler frontend would always delete them immediately when makeImageDl_finished() is called, but with GTK+, we leave them instantiated a few seconds (if child was successful) or until now (if error). */ GtkTreeIter x; GtkTreeModel* model = GTK_TREE_MODEL(jobList()->store()); // if (gtk_tree_model_iter_children(model, &x, row()) == TRUE) { // do { // JobLine* child = jobList()->get(&x); // debug("~GtkMakeImage: Deleting child %1", child); // delete child; // } while (gtk_tree_model_iter_next(model, &x) == TRUE); // } while (gtk_tree_model_iter_children(model, &x, row()) == TRUE) { JobLine* child = jobList()->get(&x); debug("~GtkMakeImage: Deleting child %1", child); delete child; } } //______________________________________________________________________ bool GtkMakeImage::run() { // Show URL as object name unsigned lastSlash = mid.jigdoUri().rfind('/'); const char* object = ""; if (lastSlash != string::npos) object = mid.jigdoUri().c_str() + lastSlash + 1; treeViewStatus = _("Waiting"); gtk_tree_store_set(jobList()->store(), row(), JobList::COLUMN_STATUS, treeViewStatus.c_str(), JobList::COLUMN_OBJECT, object, -1); mid.run(); // By default, children of this object are visible GtkTreePath* path = gtk_tree_model_get_path( GTK_TREE_MODEL(jobList()->store()), row() ); gtk_tree_view_expand_row(jobList()->view(), path, TRUE); gtk_tree_path_free(path); return SUCCESS; } //______________________________________________________________________ /* User clicked on our line in the display of jobs. If the window is not already displaying our info, switch to it. Otherwise, cycle through the sub-notebook tabs of our info. */ void GtkMakeImage::selectRow() { if (jobList()->isWindowOwner(this)) { // Cycle through tabs GtkNotebook* notebook = GTK_NOTEBOOK(GUI::window.pageJigdo); int page = gtk_notebook_get_current_page(notebook); int npages = gtk_notebook_get_n_pages(notebook); // For convenience, some unused tabs are set to invisible; skip them! while (true) { ++page; if (page >= npages) page = 0; GtkWidget* entry = gtk_notebook_get_nth_page(notebook, page); if (GTK_WIDGET_VISIBLE(entry)) break; } //msg("selrowcallback %1 of %2", page, npages); gtk_notebook_set_current_page(notebook, page); } else { // Don't cycle through tabs, just switch to jigdo info in main window setNotebookPage(GUI::window.pageJigdo); jobList()->setWindowOwner(this); } updateWindow(); } //______________________________________________________________________ bool GtkMakeImage::paused() const { return false; } void GtkMakeImage::pause() { } void GtkMakeImage::cont() { } void GtkMakeImage::stop() { } void GtkMakeImage::percentDone(uint64* cur, uint64* total) { *cur = 0; *total = 0; } //______________________________________________________________________ void GtkMakeImage::updateWindow() { if (!jobList()->isWindowOwner(this)) return; // Image description gtk_label_set_markup(GTK_LABEL(GUI::window.jigdo_ShortInfo), imageShortInfo.c_str()); gtk_label_set_markup(GTK_LABEL(GUI::window.jigdo_Info), imageInfo.c_str()); // URL and destination lines gtk_label_set_text(GTK_LABEL(GUI::window.jigdo_URL), mid.jigdoUri().c_str()); gtk_label_set_text(GTK_LABEL(GUI::window.jigdo_dest), dest.c_str()); // Progress and status lines // if (!mid.paused() && !mid.failed()) { // progress.erase(); // job->progress()->appendProgress(&progress); // } gtk_label_set_text(GTK_LABEL(GUI::window.jigdo_progress), progress.c_str()); gtk_label_set_text(GTK_LABEL(GUI::window.jigdo_status), status.c_str()); # if 0 // Buttons (in)sensitive gtk_widget_set_sensitive(GUI::window.jigdo_startButton, (job != 0 && (paused() || job->succeeded() || job->failed() && job->resumePossible()) ? TRUE : FALSE)); gtk_widget_set_sensitive(GUI::window.jigdo_pauseButton, (job != 0 && !job->failed() && !job->succeeded() && !paused() ? TRUE : FALSE)); gtk_widget_set_sensitive(GUI::window.jigdo_stopButton, (job != 0 && !job->failed() && !job->succeeded() ? TRUE : FALSE)); # endif } //______________________________________________________________________ void GtkMakeImage::job_deleted() { } void GtkMakeImage::job_succeeded() { } void GtkMakeImage::job_failed(const string& message) { debug("job_failed: %1", message); treeViewStatus = subst(_("%E1"), message); status = message; progress = _("Failed:"); updateWindow(); gtk_tree_store_set(jobList()->store(), row(), JobList::COLUMN_STATUS, treeViewStatus.c_str(), -1); } void GtkMakeImage::job_message(const string& message) { debug("job_message: %1", message); treeViewStatus = message; status = message; gtk_tree_store_set(jobList()->store(), row(), JobList::COLUMN_STATUS, treeViewStatus.c_str(), -1); } void GtkMakeImage::makeImageDl_new( Job::DataSource* childDownload, const string& uri, const string& destDesc) { debug("makeImageDl_new: %1", uri); GtkSingleUrl* child = new GtkSingleUrl(uri, destDesc, childDownload); GUI::jobList.prepend(child, this); // New child of "this" is "child" bool status = child->run(); /* NB run() cannot result in "delete child;" for child mode, so we always return a valid pointer here. */ Assert(status == SUCCESS); childDownload->io.addListener(*child); } void GtkMakeImage::makeImageDl_finished(Job::DataSource* src) { // mid.io.listeners() for (IList::iterator i = src->io.listeners().begin(), e = src->io.listeners().end(); i != e; ++i) { GtkSingleUrl* child = dynamic_cast(&*i); if (child != 0) { debug("makeImageDl_finished: %1", src->location()); child->childIsFinished(); } } } void GtkMakeImage::makeImageDl_haveImageSection() { dest += DIRSEP; dest += mid.imageName(); gtk_tree_store_set(jobList()->store(), row(), JobList::COLUMN_OBJECT, mid.imageName().c_str(), -1); imageInfo.erase(); const char* gtk[] = { "", "", // , "", "", // , "", "", // , "", "", // , "", "", // , "", "", // , "\n" //
}; mid.imageInfo(&imageInfo, true, gtk); /* Problem: GtkLabels have a certain default width which cannot be influenced AFAICT. The only way to make them wider is to include a word whose length exceeds the default width */ // imageInfo += "\n\xa0\x62"; const char* format = (mid.imageShortInfo().empty() ? "%EF2" : _("%EF1 (%EF2)")); imageShortInfo = subst(format, mid.imageShortInfo(), mid.imageName()); updateWindow(); } //______________________________________________________________________ void GtkMakeImage::on_startButton_clicked() { debug("unimplemented"); } void GtkMakeImage::on_pauseButton_clicked() { debug("unimplemented"); } void GtkMakeImage::on_stopButton_clicked() { debug("unimplemented"); } void GtkMakeImage::on_restartButton_clicked() { debug("unimplemented"); } void GtkMakeImage::on_closeButton_clicked() { if (jobList()->isWindowOwner(this)) setNotebookPage(GUI::window.pageOpen); delete this; }