3
// Copyright 2000-2009 Daniel Burrows <dburrows@debian.org>
5
// This program is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU General Public License as
7
// published by the Free Software Foundation; either version 2 of
8
// the License, or (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; see the file COPYING. If not, write to
17
// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
// Boston, MA 02111-1307, USA.
20
// Various UI glue-code and routines.
24
#include <sigc++/adaptors/bind.h>
25
#include <sigc++/adaptors/retype_return.h>
26
#include <sigc++/functors/ptr_fun.h>
27
#include <sigc++/functors/mem_fun.h>
29
#include <boost/make_shared.hpp>
30
#include <boost/shared_ptr.hpp>
31
#include <boost/weak_ptr.hpp>
33
#include <apt-pkg/acquire.h>
34
#include <apt-pkg/clean.h>
35
#include <apt-pkg/configuration.h>
36
#include <apt-pkg/error.h>
37
#include <apt-pkg/packagemanager.h>
43
#include <sys/types.h>
55
#include "apt_config_widgets.h"
56
#include "apt_options.h"
57
#include "broken_indicator.h"
59
#include "load_config.h"
60
#include "load_grouppolicy.h"
61
#include "load_pkgview.h"
62
#include "solution_dialog.h"
63
#include "solution_fragment.h"
64
#include "solution_screen.h"
66
#include <cwidget/curses++.h>
67
#include <cwidget/dialogs.h>
68
#include <cwidget/fragment.h>
69
#include <cwidget/toplevel.h>
70
#include <cwidget/widgets/button.h>
71
#include <cwidget/widgets/center.h>
72
#include <cwidget/widgets/editline.h>
73
#include <cwidget/widgets/frame.h>
74
#include <cwidget/widgets/label.h>
75
#include <cwidget/widgets/menu.h>
76
#include <cwidget/widgets/menubar.h>
77
#include <cwidget/widgets/multiplex.h>
78
#include <cwidget/widgets/pager.h>
79
#include <cwidget/widgets/scrollbar.h>
80
#include <cwidget/widgets/stacked.h>
81
#include <cwidget/widgets/statuschoice.h>
82
#include <cwidget/widgets/table.h>
83
#include <cwidget/widgets/text_layout.h>
84
#include <cwidget/widgets/togglebutton.h>
85
#include <cwidget/widgets/transient.h>
86
#include <cwidget/widgets/tree.h>
88
#include <mine/cmine.h>
90
#include <generic/apt/apt.h>
91
#include <generic/apt/apt_undo_group.h>
92
#include <generic/apt/aptitude_resolver_universe.h>
93
#include <generic/apt/config_signal.h>
94
#include <generic/apt/download_install_manager.h>
95
#include <generic/apt/download_update_manager.h>
96
#include <generic/apt/download_signal_log.h>
97
#include <generic/apt/resolver_manager.h>
99
#include <generic/problemresolver/exceptions.h>
100
#include <generic/problemresolver/solution.h>
102
#include <generic/util/temp.h>
103
#include <generic/util/util.h>
105
#include "dep_item.h"
106
#include "download_list.h"
107
#include "menu_tree.h"
108
#include "pkg_columnizer.h"
109
#include "pkg_grouppolicy.h"
110
#include "pkg_info_screen.h"
111
#include "pkg_tree.h"
112
#include "pkg_ver_item.h"
113
#include "pkg_view.h"
114
#include "safe_slot_event.h"
115
#include "ui_download_manager.h"
116
#include "progress.h"
119
namespace cw = cwidget;
122
using namespace widgets;
125
typedef generic_solution<aptitude_universe> aptitude_solution;
127
static cw::menubar_ref main_menu;
128
static cw::menu_ref views_menu;
130
static cw::stacked_ref main_stacked;
132
// Hmm, is this table the best idea?..
133
static cw::table_ref main_table;
135
static cw::multiplex_ref main_multiplex;
136
static cw::multiplex_ref main_status_multiplex;
138
// I think it's better to only have a single preview screen at once. (note to
139
// self: data-segment stuff initializes to 0 already..)
140
static pkg_tree_ref active_preview_tree;
141
static cw::widget_ref active_preview;
143
// True if a download or package-list update is proceeding. This hopefully will
144
// avoid the nasty possibility of collisions between them.
145
// FIXME: uses implicit locking -- if multithreading happens, should use a mutex
147
static bool active_download;
149
// While a status-widget download progress thingy is active, this will be
151
cw::widget_ref active_status_download;
153
sigc::signal0<void> file_quit;
155
sigc::signal0<bool, cw::util::accumulate_or> undo_undo;
156
sigc::signal0<bool, cw::util::accumulate_or> undo_undo_enabled;
158
sigc::signal0<void> package_states_changed;
160
sigc::signal0<bool, cw::util::accumulate_or> package_menu_enabled;
161
sigc::signal0<bool, cw::util::accumulate_or> package_forbid_enabled;
162
sigc::signal0<bool, cw::util::accumulate_or> package_information_enabled;
163
sigc::signal0<bool, cw::util::accumulate_or> package_cycle_information_enabled;
164
sigc::signal0<bool, cw::util::accumulate_or> package_changelog_enabled;
166
sigc::signal0<bool, cw::util::accumulate_or> find_search_enabled;
167
sigc::signal0<bool, cw::util::accumulate_or> find_search_back_enabled;
168
sigc::signal0<bool, cw::util::accumulate_or> find_research_enabled;
169
sigc::signal0<bool, cw::util::accumulate_or> find_repeat_search_back_enabled;
170
sigc::signal0<bool, cw::util::accumulate_or> find_limit_enabled;
171
sigc::signal0<bool, cw::util::accumulate_or> find_cancel_limit_enabled;
172
sigc::signal0<bool, cw::util::accumulate_or> find_broken_enabled;
174
sigc::signal0<bool, cw::util::accumulate_or> package_install;
175
sigc::signal0<bool, cw::util::accumulate_or> package_remove;
176
sigc::signal0<bool, cw::util::accumulate_or> package_purge;
177
sigc::signal0<bool, cw::util::accumulate_or> package_hold;
178
sigc::signal0<bool, cw::util::accumulate_or> package_keep;
179
sigc::signal0<bool, cw::util::accumulate_or> package_mark_auto;
180
sigc::signal0<bool, cw::util::accumulate_or> package_unmark_auto;
181
sigc::signal0<bool, cw::util::accumulate_or> package_forbid;
182
sigc::signal0<bool, cw::util::accumulate_or> package_information;
183
sigc::signal0<bool, cw::util::accumulate_or> package_cycle_information;
184
sigc::signal0<bool, cw::util::accumulate_or> package_changelog;
186
sigc::signal0<bool, cw::util::accumulate_or> resolver_toggle_rejected;
187
sigc::signal0<bool, cw::util::accumulate_or> resolver_toggle_rejected_enabled;
188
sigc::signal0<bool, cw::util::accumulate_or> resolver_toggle_approved;
189
sigc::signal0<bool, cw::util::accumulate_or> resolver_toggle_approved_enabled;
190
sigc::signal0<bool, cw::util::accumulate_or> resolver_view_target;
191
sigc::signal0<bool, cw::util::accumulate_or> resolver_view_target_enabled;
193
sigc::signal0<bool, cw::util::accumulate_or> find_search;
194
sigc::signal0<bool, cw::util::accumulate_or> find_search_back;
195
sigc::signal0<bool, cw::util::accumulate_or> find_research;
196
sigc::signal0<bool, cw::util::accumulate_or> find_repeat_search_back;
197
sigc::signal0<bool, cw::util::accumulate_or> find_limit;
198
sigc::signal0<bool, cw::util::accumulate_or> find_cancel_limit;
199
sigc::signal0<bool, cw::util::accumulate_or> find_broken;
201
sigc::signal1<void, bool> install_finished;
202
sigc::signal1<void, bool> update_finished;
204
const char *default_pkgstatusdisplay="%d";
205
const char *default_pkgheaderdisplay="%N %n #%B %u %o";
206
const char *default_grpstr="task,status,section(subdirs,passthrough),section(topdir)";
207
const char *confirm_delete_essential_str=N_("Yes, I am aware this is a very bad idea");
210
void ui_start_download(bool hide_preview)
212
active_download = true;
214
if(apt_cache_file != NULL)
215
(*apt_cache_file)->set_read_only(true);
217
if(hide_preview && active_preview.valid())
218
active_preview->destroy();
221
void ui_stop_download()
223
active_download = false;
225
if(apt_cache_file != NULL)
226
(*apt_cache_file)->set_read_only(false);
229
static cw::fragment *apt_error_fragment()
231
vector<cw::fragment *> frags;
234
frags.push_back(cw::text_fragment(_("Er, there aren't any errors, this shouldn't have happened..")));
235
else while(!_error->empty())
238
bool iserr=_error->PopMessage(currerr);
244
frags.push_back(indentbox(0, 3,
245
wrapbox(cw::fragf("%B%s%b %s",
250
return cw::sequence_fragment(frags);
253
// Handles "search" dialogs for pagers
254
static void pager_search(cw::pager &p)
256
prompt_string(W_("Search for:"),
258
cw::util::arg(sigc::mem_fun(p, &cw::pager::search_for)),
265
static void pager_repeat_search(cw::pager &p)
270
static void pager_repeat_search_back(cw::pager &p)
272
p.search_back_for(L"");
275
static cw::widget_ref make_error_dialog(const cw::text_layout_ref &layout)
277
cw::table_ref t=cw::table::create();
279
cw::scrollbar_ref s=cw::scrollbar::create(cw::scrollbar::VERTICAL);
281
t->add_widget(layout, 0, 0, 1, 1, true, true);
282
t->add_widget_opts(s, 0, 1, 1, 1,
283
cw::table::ALIGN_RIGHT,
284
cw::table::ALIGN_CENTER | cw::table::FILL);
286
layout->location_changed.connect(sigc::mem_fun(s.unsafe_get_ref(), &cw::scrollbar::set_slider));
287
s->scrollbar_interaction.connect(sigc::mem_fun(layout.unsafe_get_ref(), &cw::text_layout::scroll));
289
return cw::dialogs::ok(t, NULL, W_("Ok"), cw::get_style("Error"));
293
static void do_null_ptr(cw::text_layout_ref *p)
298
void check_apt_errors()
303
static cw::text_layout_ref error_dialog_layout = NULL;
305
if(!error_dialog_layout.valid())
307
error_dialog_layout = cw::text_layout::create(apt_error_fragment());
308
error_dialog_layout->destroyed.connect(sigc::bind(sigc::ptr_fun(do_null_ptr), &error_dialog_layout));
310
main_stacked->add_visible_widget(make_error_dialog(error_dialog_layout),
314
error_dialog_layout->append_fragment(apt_error_fragment());
317
static void read_only_permissions_table_destroyed(apt_config_widget &w)
320
apt_dumpcfg(PACKAGE);
325
static bool do_read_only_permission()
331
(*apt_cache_file)->set_read_only(false);
334
if(!aptcfg->FindB(PACKAGE "::Suppress-Read-Only-Warning", false))
336
cw::table_ref t(cw::table::create());
338
cw::fragment *f = wrapbox(cw::text_fragment(_("WARNING: the package cache is opened in read-only mode! This change and all subsequent changes will not be saved unless you stop all other running apt-based programs and select \"Become root\" from the Actions menu.")));
340
t->add_widget_opts(cw::text_layout::create(f),
341
0, 0, 1, 1, cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
342
cw::table::EXPAND | cw::table::FILL);
344
apt_bool_widget *w = new apt_bool_widget(_("Never display this message again."),
345
PACKAGE "::Suppress-Read-Only-Warning", false);
348
t->add_widget_opts(cw::label::create(""), 1, 0, 1, 1,
349
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
352
t->add_widget_opts(w->cb, 2, 0, 1, 1,
353
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
354
cw::table::EXPAND | cw::table::FILL);
357
t->add_widget_opts(cw::label::create(""), 3, 0, 1, 1,
358
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
361
cw::button_ref ok(cw::button::create(_("Ok")));
363
t->add_widget_opts(ok, 4, 0, 1, 1,
364
cw::table::EXPAND | cw::table::SHRINK,
371
cw::frame_ref frame = cw::frame::create(t);
372
frame->set_bg_style(cw::style_attrs_flip(A_REVERSE));
374
cw::center_ref c = cw::center::create(frame);
376
ok->pressed.connect(sigc::mem_fun(c.unsafe_get_ref(), &cw::widget::destroy));
377
c->destroyed.connect(sigc::bind(sigc::ptr_fun(&read_only_permissions_table_destroyed), sigc::ref(*w)));
386
static void do_read_only_fail()
388
eassert(active_download);
390
show_message(_("You may not modify the state of any package while a download is underway."));
393
static void do_connect_read_only_callbacks()
395
if(apt_cache_file != NULL)
397
(*apt_cache_file)->read_only_permission.connect(sigc::ptr_fun(&do_read_only_permission));
398
(*apt_cache_file)->read_only_fail.connect(sigc::ptr_fun(&do_read_only_fail));
402
// Runs a sub-aptitude with the same selections that the user
403
// has currently made, but as root.
405
// Because tagfiles don't work on FIFOs, and su closes all open fds,
406
// this is a lot hairier than it should be.
408
// This writes the current status to a file in a designated temporary
409
// directory, then loads it in a su'd instance. A FIFO is used to
410
// make the reader block until the writer is done writing. Not
411
// foolproof but the user would have to go to a lot of pointless
412
// trouble to screw it up.
414
// Note that the deletion of the temporary files is safe, since this
415
// routine blocks until the sub-process exits.
417
static void do_su_to_root(string args)
421
show_message(_("You already are root!"));
425
std::string root_command = aptcfg->Find(PACKAGE "::Get-Root-Command",
428
if(root_command == "su")
429
root_command = "su:/bin/su";
430
else if(root_command == "sudo")
431
root_command = "sudo:/usr/bin/sudo";
433
std::string::size_type splitloc = root_command.find(':');
434
if(splitloc == std::string::npos)
436
_error->Error(_("Invalid Get-Root-Command; it should start with su: or sudo:"));
440
std::string protocol(root_command, 0, splitloc);
441
if(protocol != "su" && protocol != "sudo")
443
_error->Error(_("Invalid Get-Root-Command; it should start with su: or sudo:, not %s:"), protocol.c_str());
446
std::string root_program(root_command, splitloc + 1);
448
temp::name statusname("pkgstates");
449
temp::name fifoname("control");
451
if(mkfifo(fifoname.get_name().c_str(), 0600) != 0)
453
_error->Errno("do_su_to_root",
454
"Couldn't create temporary FIFO");
458
// Shut curses down. This is done before we fork because otherwise
459
// we'll end up with curses apparently being initialized in the
460
// child and with mutexes locked (despite the fact that no thread
461
// holds them), and get horribly confused, especially if we try to
464
// An alternative is to invoke _exit(2) instead, but it seems
465
// cleaner to suspend curses right here.
466
cw::toplevel::suspend();
472
_error->Error(_("Unable to fork: %s"), strerror(errno));
473
cw::toplevel::resume();
475
else if(pid==0) // I'm a child!
477
// Read one byte from the FIFO for synchronization
479
int fd = open(fifoname.get_name().c_str(), O_RDONLY);
480
read(fd, &tmp, 1); // Will block until the other process writes.
483
// It's ok to use argv0 to generate the command,
484
// since the user has to authenticate themselves as root (ie, if
485
// they're going to do something evil that way they'd have su'd
488
// What happens if tmpdir has spaces in it? Can I get more
489
// control over how the su-to-root function is called?
492
std::ostringstream cmdbuf;
493
cmdbuf << argv0 << " --no-gui -S "
494
<< statusname.get_name() << " "
496
execl(root_program.c_str(), root_program.c_str(), "-c", cmdbuf.str().c_str(), NULL);
500
else if(protocol == "sudo")
502
std::vector<std::string> cmdlist;
503
// Split whitespace in the input command.
504
std::string command = root_program + " " + argv0 + " --no-gui -S " + statusname.get_name() + " " + args;
505
std::string::const_iterator it = command.begin();
506
while(it != command.end() && isspace(*it))
509
while(it != command.end())
512
while(it != command.end() && !isspace(*it))
518
cmdlist.push_back(tmp);
520
while(it != command.end() && isspace(*it))
524
const char **real_cmd = new const char*[cmdlist.size() + 1];
525
for(std::string::size_type i = 0; i < cmdlist.size(); ++i)
526
real_cmd[i] = cmdlist[i].c_str();
527
real_cmd[cmdlist.size()] = NULL;
529
execv(real_cmd[0], const_cast<char* const*>(real_cmd));
531
std::string errmsg = ssprintf("aptitude: do_su_to_root: exec \"%s\" failed", root_program.c_str());
532
perror(errmsg.c_str());
536
// Eek, something bad happened.
540
exit(1); // Should never happen -- see the test above.
545
OpProgress foo; // Need a generic non-outputting progress bar
547
// Save the selection list. Check first if it's NULL to handle the
548
// case of a closed cache.
549
if(apt_cache_file != NULL)
550
(*apt_cache_file)->save_selection_list(foo, statusname.get_name().c_str());
552
// Ok, wake the other process up.
554
int fd=open(fifoname.get_name().c_str(), O_WRONLY);
558
// Wait for a while so we don't accidentally daemonize ourselves.
559
while(waitpid(pid, &status, 0)!=pid)
562
if(!WIFEXITED(status) || WEXITSTATUS(status))
565
_("Subprocess exited with an error -- did you type your password correctly?"));
566
cw::toplevel::resume();
568
// We have to clear these out or the cache won't reload properly (?)
570
progress_ref p = gen_progress_bar();
571
apt_reload_cache(p->get_progress().unsafe_get_ref(), true, statusname.get_name().c_str());
576
// Clear out our references to these objects so they get
577
// removed, although the shutdown routine should also do
579
statusname = temp::name();
580
fifoname = temp::name();
587
static bool su_to_root_enabled()
592
static void update_menubar_autohide()
594
main_menu->set_always_visible(main_multiplex->num_children()==0 ||
595
!aptcfg->FindB(PACKAGE "::UI::Menubar-Autohide",
599
cw::widget_ref reload_message;
600
static void do_show_reload_message()
602
if(!reload_message.valid())
604
cw::widget_ref w = cw::frame::create(cw::label::create(_("Loading cache")));
605
reload_message = cw::center::create(w);
606
reload_message->show_all();
607
popup_widget(reload_message);
609
cw::toplevel::tryupdate();
613
static void do_hide_reload_message()
615
if(reload_message.valid())
617
reload_message->destroy();
618
reload_message = NULL;
619
cw::toplevel::tryupdate();
623
/** \brief If this is \b true, there's a "really quit aptitude?"
626
* The sole purpose of this variable is to prevent the dialog
627
* box that asks about quitting from showing up multiple times.
629
static bool really_quit_active = false;
631
static void do_really_quit_answer(bool should_i_quit)
633
really_quit_active = false;
639
static void do_quit()
641
if(aptcfg->FindB(PACKAGE "::UI::Prompt-On-Exit", true))
643
if(!really_quit_active)
645
really_quit_active = true;
646
prompt_yesno(_("Really quit Aptitude?"), false,
647
cw::util::arg(sigc::bind(ptr_fun(do_really_quit_answer), true)),
648
cw::util::arg(sigc::bind(ptr_fun(do_really_quit_answer), false)));
655
static void do_destroy_visible()
657
if(aptcfg->FindB(PACKAGE "::UI::Exit-On-Last-Close", true) &&
658
main_multiplex->num_children()<=1)
662
cw::widget_ref w=main_multiplex->visible_widget();
666
// If all the screens are destroyed, we make the menu visible (so the
667
// user knows that something is still alive :) )
668
update_menubar_autohide();
672
static bool view_next_prev_enabled()
674
return main_multiplex->num_visible()>1;
677
static bool any_view_visible()
679
return main_multiplex->visible_widget().valid();
682
// These are necessary because main_multiplex isn't created until after
683
// the slot in the static initializer..
684
// (creating the menu info at a later point would solve this problem)
685
static void do_view_next()
687
main_multiplex->cycle_forward();
690
static void do_view_prev()
692
main_multiplex->cycle_backward();
695
static void do_show_options_tree()
697
cw::widget_ref w = aptitude::ui::config::make_options_tree();
700
_("Change the behavior of aptitude"),
706
static void do_show_ui_options_dlg()
708
cw::widget_ref w = make_ui_options_dialog();
709
main_stacked->add_visible_widget(w, true);
713
static void do_show_misc_options_dlg()
715
cw::widget_ref w=make_misc_options_dialog();
716
main_stacked->add_visible_widget(w, true);
720
static void do_show_dependency_options_dlg()
722
cw::widget_ref w=make_dependency_options_dialog();
723
main_stacked->add_visible_widget(w, true);
728
static void really_do_revert_options()
731
apt_dumpcfg(PACKAGE);
734
static void do_revert_options()
736
prompt_yesno(_("Really discard your personal settings and reload the defaults?"),
738
cw::util::arg(sigc::ptr_fun(really_do_revert_options)),
742
static cw::widget_ref make_default_view(const menu_tree_ref &mainwidget,
744
desc_signal *desc_sig,
745
bool allow_visible_desc=true,
746
bool show_reason_first=false)
748
if(aptcfg->Exists(PACKAGE "::UI::Default-Package-View"))
750
list<package_view_item> *format=load_pkgview(PACKAGE "::UI::Default-Package-View");
754
// The unsafe_get_ref is to convert mainwidget to be a
755
// menu_redirect pointer.
756
cw::widget_ref rval=make_package_view(*format, mainwidget,
757
mainwidget.unsafe_get_ref(), sig,
758
desc_sig, show_reason_first);
766
list<package_view_item> basic_format;
768
// FIXME: do the config lookup inside the package-view code?
769
basic_format.push_back(package_view_item("static1",
770
parse_columns(cw::util::transcode(aptcfg->Find(PACKAGE "::UI::Package-Header-Format", default_pkgheaderdisplay)),
771
pkg_item::pkg_columnizer::parse_column_type,
772
pkg_item::pkg_columnizer::defaults),
773
PACKAGE "::UI::Package-Header-Format",
775
cw::table::ALIGN_CENTER | cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
776
cw::table::ALIGN_CENTER,
777
cw::get_style("Header"),
782
basic_format.push_back(package_view_item("main", 1, 0, 1, 1,
783
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
784
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
788
basic_format.push_back(package_view_item("static2",
789
parse_columns(cw::util::transcode(aptcfg->Find(PACKAGE "::UI::Package-Status-Format", default_pkgstatusdisplay)),
790
pkg_item::pkg_columnizer::parse_column_type,
791
pkg_item::pkg_columnizer::defaults),
792
PACKAGE "::UI::Package-Status-Format",
794
cw::table::ALIGN_CENTER | cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
795
cw::table::ALIGN_CENTER,
796
cw::get_style("Status"),
800
basic_format.push_back(package_view_item("desc", 3, 0, 1, 1,
801
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
802
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
804
"ShowHideDescription", "",
805
allow_visible_desc && aptcfg->FindB(PACKAGE "::UI::Description-Visible-By-Default", true)));
807
return make_package_view(basic_format, mainwidget,
808
mainwidget.unsafe_get_ref(),
813
void do_new_package_view(OpProgress &progress)
815
pkg_grouppolicy_factory *grp=NULL;
816
std::string grpstr="";
818
if(aptcfg->Exists(PACKAGE "::UI::Default-Grouping"))
820
grpstr=aptcfg->Find(PACKAGE "::UI::Default-Grouping");
821
grp=parse_grouppolicy(grpstr);
826
grpstr=default_grpstr;
827
grp=parse_grouppolicy(grpstr);
830
// Eek! The default grouping failed to parse. Fall all the
832
grp=new pkg_grouppolicy_task_factory(new pkg_grouppolicy_status_factory(new pkg_grouppolicy_section_factory(pkg_grouppolicy_section_factory::split_subdirs,true,new pkg_grouppolicy_section_factory(pkg_grouppolicy_section_factory::split_topdir,false,new pkg_grouppolicy_end_factory()))));
835
pkg_tree_ref tree=pkg_tree::create(grpstr.c_str(), grp);
837
add_main_widget(make_default_view(tree,
838
&tree->selected_signal,
839
&tree->selected_desc_signal),
841
_("View available packages and choose actions to perform"),
844
tree->build_tree(progress);
847
// For signal connections.
848
static void do_new_package_view_with_new_bar()
850
progress_ref p = gen_progress_bar();
851
do_new_package_view(*p->get_progress().unsafe_get_ref());
855
static void do_new_recommendations_view()
857
progress_ref p = gen_progress_bar();
859
pkg_grouppolicy_factory *grp = new pkg_grouppolicy_end_factory();
860
std::string grpstr="section(subdirs, passthrough)";
862
pkg_tree_ref tree=pkg_tree::create(grpstr.c_str(), grp,
863
L"!~v!~i~RBrecommends:~i");
865
add_main_widget(make_default_view(tree,
866
&tree->selected_signal,
867
&tree->selected_desc_signal,
870
_("Recommended Packages"),
871
_("View packages that it is recommended that you install"),
872
_("Recommendations"));
874
tree->build_tree(*p->get_progress().unsafe_get_ref());
878
void do_new_flat_view(OpProgress &progress)
880
pkg_grouppolicy_factory *grp = new pkg_grouppolicy_end_factory;
881
pkg_tree_ref tree = pkg_tree::create("", grp);
882
tree->set_limit(cw::util::transcode("!~v"));
884
add_main_widget(make_default_view(tree,
885
&tree->selected_signal,
886
&tree->selected_desc_signal),
888
_("View available packages and choose actions to perform"),
891
tree->build_tree(progress);
894
// For signal connections.
895
static void do_new_flat_view_with_new_bar()
897
progress_ref p = gen_progress_bar();
898
do_new_flat_view(*p->get_progress().unsafe_get_ref());
902
static void do_new_tag_view_with_new_bar()
904
progress_ref p = gen_progress_bar();
906
pkg_grouppolicy_factory *grp = NULL;
907
string grpstr = "tag";
908
grp = parse_grouppolicy(grpstr);
910
pkg_tree_ref tree = pkg_tree::create(grpstr.c_str(), grp);
912
add_main_widget(make_default_view(tree,
913
&tree->selected_signal,
914
&tree->selected_desc_signal),
916
_("View available packages and choose actions to perform"),
919
tree->build_tree(*p->get_progress().unsafe_get_ref());
923
void do_new_hier_view(OpProgress &progress)
925
pkg_grouppolicy_factory *grp=NULL;
926
std::string grpstr="";
929
grp=parse_grouppolicy(grpstr);
931
pkg_tree_ref tree=pkg_tree::create(grpstr.c_str(), grp);
932
tree->set_limit(cw::util::transcode("!~v"));
933
//tree->set_hierarchical(false);
935
add_main_widget(make_default_view(tree,
936
&tree->selected_signal,
937
&tree->selected_desc_signal),
939
_("View available packages and choose actions to perform"),
941
tree->build_tree(progress);
944
// For signal connections.
945
static void do_new_hier_view_with_new_bar()
947
progress_ref p=gen_progress_bar();
948
do_new_hier_view(*p->get_progress().unsafe_get_ref());
952
cw::widget_ref make_info_screen(const pkgCache::PkgIterator &pkg,
953
const pkgCache::VerIterator &ver)
955
pkg_info_screen_ref w = pkg_info_screen::create(pkg, ver);
956
cw::widget_ref rval = make_default_view(w, w->get_sig(), w->get_desc_sig(), false);
957
w->repeat_signal(); // force the status line in the view to update
961
cw::widget_ref make_dep_screen(const pkgCache::PkgIterator &pkg,
962
const pkgCache::VerIterator &ver,
965
pkg_dep_screen_ref w = pkg_dep_screen::create(pkg, ver, reverse);
966
cw::widget_ref rval = make_default_view(w, w->get_sig(), w->get_desc_sig(), true);
967
w->repeat_signal(); // force the status line in the view to update
971
cw::widget_ref make_ver_screen(const pkgCache::PkgIterator &pkg)
973
pkg_ver_screen_ref w = pkg_ver_screen::create(pkg);
974
cw::widget_ref rval = make_default_view(w, w->get_sig(), w->get_desc_sig(), true);
979
static void do_help_about()
981
cw::fragment *f = cw::fragf(_("Aptitude %s%n%nCopyright 2000-2008 Daniel Burrows.%n"
983
"aptitude comes with %BABSOLUTELY NO WARRANTY%b; for details see 'license' in the Help menu. This is free software, and you are welcome to redistribute it under certain conditions; see 'license' for details."), VERSION);
985
cw::widget_ref w=cw::dialogs::ok(wrapbox(f));
991
/** Set up a new top-level file-viewing widget with a scrollbar. */
992
static cw::widget_ref setup_fileview(const std::string &filename,
993
const char *encoding,
994
const std::string &menudesc,
995
const std::string &longmenudesc,
996
const std::string &tabdesc)
999
cw::table_ref t = cw::table::create();
1000
cw::scrollbar_ref s = cw::scrollbar::create(cw::scrollbar::VERTICAL);
1001
cw::file_pager_ref p = cw::file_pager::create(filename, encoding);
1003
p->line_changed.connect(sigc::mem_fun(s.unsafe_get_ref(), &cw::scrollbar::set_slider));
1004
s->scrollbar_interaction.connect(sigc::mem_fun(p.unsafe_get_ref(), &cw::pager::scroll_page));
1005
p->scroll_top(); // Force a scrollbar update.
1007
p->connect_key("Search", &cw::config::global_bindings,
1008
sigc::bind(sigc::ptr_fun(&pager_search), p.weak_ref()));
1009
p->connect_key("ReSearch", &cw::config::global_bindings,
1010
sigc::bind(sigc::ptr_fun(&pager_repeat_search), p.weak_ref()));
1011
p->connect_key("RepeatSearchBack", &cw::config::global_bindings,
1012
sigc::bind(sigc::ptr_fun(&pager_repeat_search_back), p.weak_ref()));
1014
t->add_widget_opts(p, 0, 0, 1, 1,
1015
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
1016
cw::table::EXPAND | cw::table::FILL);
1017
t->add_widget_opts(s, 0, 1, 1, 1,
1018
0, cw::table::EXPAND | cw::table::FILL);
1023
add_main_widget(t, menudesc, longmenudesc, tabdesc);
1027
static void do_help_license()
1029
setup_fileview(HELPDIR "/COPYING",
1032
_("View the terms under which you may copy and distribute aptitude"),
1036
static void do_help_help()
1038
static cw::widget_ref fileview_widget;
1040
if(fileview_widget.valid())
1042
fileview_widget->show();
1046
std::string filename = ssprintf(HELPDIR "/%s", _("help.txt"));
1048
const char *encoding = P_("Encoding of help.txt|UTF-8");
1050
// Deal with missing localized docs.
1051
if(access(filename.c_str(), R_OK) != 0)
1053
filename = HELPDIR "/help.txt";
1057
fileview_widget = setup_fileview(filename,
1060
_("View a brief introduction to aptitude"),
1062
fileview_widget->destroyed.connect(sigc::mem_fun(fileview_widget,
1063
&cw::widget_ref::clear));
1066
static void do_help_readme()
1068
// Look up the translation of README.
1069
std::string readme_file = ssprintf(HELPDIR "/%s", _("README"));
1070
const char *encoding = P_("Encoding of README|ISO_8859-1");
1072
// Deal with missing localized docs.
1073
if(access(readme_file.c_str(), R_OK)!=0)
1075
readme_file = HELPDIR "/README";
1076
encoding = "ISO_8859-1";
1079
setup_fileview(readme_file,
1082
_("Read the full user's manual of aptitude"),
1086
static void do_help_faq()
1088
setup_fileview(HELPDIR "/FAQ",
1091
_("View a list of frequently asked questions"),
1095
// news isn't translated since it's just a changelog.
1096
static void do_help_news()
1098
setup_fileview(HELPDIR "/NEWS",
1101
ssprintf(_("View the important changes made in each version of %s"), PACKAGE),
1105
static void do_kill_old_tmp(const std::string old_tmpdir)
1107
if(!aptitude::util::recursive_remdir(old_tmpdir))
1108
show_message(ssprintf(_("Unable to remove the old temporary directory; you should remove %s by hand."), old_tmpdir.c_str()));
1111
static void cancel_kill_old_tmp(const std::string old_tmpdir)
1113
show_message(ssprintf(_("Will not remove %s; you should examine the files in it and remove them by hand."), old_tmpdir.c_str()));
1114
aptcfg->Set(PACKAGE "::Ignore-Old-Tmp", "true");
1115
apt_dumpcfg(PACKAGE);
1118
static void maybe_show_old_tmpdir_message()
1120
std::string tmpdir_path = get_homedir() + "/.aptitude/.tmp";
1122
if(aptcfg->FindB(PACKAGE "::Ignore-Old-Tmp", false))
1124
// Watch for the reappearance of this directory.
1125
if(access(tmpdir_path.c_str(), F_OK) != 0)
1127
aptcfg->Set(PACKAGE "::Ignore-Old-Tmp", "false");
1128
apt_dumpcfg(PACKAGE);
1134
// Remove it silently if it's empty.
1135
if(rmdir(tmpdir_path.c_str()) == 0)
1138
if(access(tmpdir_path.c_str(), F_OK) == 0)
1139
prompt_yesno_popup(wrapbox(cw::fragf(_("It appears that a previous version of aptitude left files behind in %s. These files are probably useless and safe to delete.%n%nDo you want to remove this directory and all its contents? If you select \"No\", you will not see this message again."), tmpdir_path.c_str())),
1141
cw::util::arg(sigc::bind(sigc::ptr_fun(do_kill_old_tmp), tmpdir_path)),
1142
cw::util::arg(sigc::bind(sigc::ptr_fun(cancel_kill_old_tmp), tmpdir_path)));
1145
// There are some circular references because of the code to test
1146
// for consistency before doing a package run; the last routine called before
1147
// the program starts downloading will verify that the selections are
1148
// consistent and call its predecessors if they are not.
1150
// (er, can I disentangle this by rearranging the routines? I think maybe I
1151
// can to some degree)
1155
void run_dpkg_with_cwidget_suspended(sigc::slot1<pkgPackageManager::OrderResult, int> f,
1156
sigc::slot1<void, pkgPackageManager::OrderResult> k)
1158
cw::toplevel::suspend();
1159
pkgPackageManager::OrderResult rval = f(-1);
1161
if(rval != pkgPackageManager::Incomplete)
1163
cerr << _("Press return to continue.\n");
1166
while(c != '\n' && c != EOF)
1170
// libapt-pkg likes to stomp on SIGINT and SIGQUIT. Restore them
1171
// here in the simplest possible way.
1172
cw::toplevel::install_sighandlers();
1174
cw::toplevel::resume();
1183
// Note that this is only safe if it's OK to copy the thunk in a
1184
// background thread (i.e., it won't be invalidated by an object being
1185
// destroyed in another thread). In the special cases where we use
1186
// this it should be all right.
1187
void do_post_thunk(const safe_slot0<void> &thunk)
1189
cw::toplevel::post_event(new aptitude::safe_slot_event(thunk));
1192
progress_with_destructor make_progress_bar()
1194
progress_ref rval = gen_progress_bar();
1195
return std::make_pair(rval->get_progress(),
1196
sigc::mem_fun(*rval.unsafe_get_ref(),
1197
&progress::destroy));
1201
void install_or_remove_packages()
1203
boost::shared_ptr<download_install_manager> m =
1204
boost::make_shared<download_install_manager>(false, sigc::ptr_fun(&run_dpkg_with_cwidget_suspended));
1206
m->post_forget_new_hook.connect(package_states_changed.make_slot());
1208
std::pair<download_signal_log *, download_list_ref>
1209
download_log_pair = gen_download_progress(false, false,
1210
_("Downloading packages"),
1211
_("View the progress of the package download"),
1212
_("Package Download"));
1214
ui_download_manager *uim = new ui_download_manager(m,
1215
download_log_pair.first,
1216
download_log_pair.second,
1217
sigc::ptr_fun(&make_progress_bar),
1220
download_log_pair.second->cancelled.connect(sigc::mem_fun(*uim, &ui_download_manager::aborted));
1222
uim->download_starts.connect(sigc::bind(sigc::ptr_fun(&ui_start_download), true));
1223
uim->download_stops.connect(sigc::ptr_fun(&ui_stop_download));
1225
uim->download_complete.connect(install_finished.make_slot());
1229
/** Make sure that no trust violations are about to be committed. If
1230
* any are, warn the user and give them a chance to fix the
1233
* Should this warning be displayed when a package is selected instead?
1235
static void check_package_trust()
1237
vector<pkgCache::VerIterator> untrusted;
1239
for(pkgCache::PkgIterator pkg=(*apt_cache_file)->PkgBegin();
1242
pkgDepCache::StateCache &state=(*apt_cache_file)[pkg];
1246
pkgCache::VerIterator curr=pkg.CurrentVer();
1247
pkgCache::VerIterator cand=state.InstVerIter(*apt_cache_file);
1249
if((curr.end() || package_trusted(curr)) &&
1250
!package_trusted(cand))
1251
untrusted.push_back(cand);
1255
if(!untrusted.empty())
1257
vector<cw::fragment *> frags;
1259
frags.push_back(wrapbox(cw::fragf(_("%BWARNING%b: untrusted versions of the following packages will be installed!%n%n"
1260
"Untrusted packages could %Bcompromise your system's security%b. "
1261
"You should only proceed with the installation if you are certain that this is what you want to do.%n%n"), "Error")));
1263
for(vector<pkgCache::VerIterator>::const_iterator i=untrusted.begin();
1264
i!=untrusted.end(); ++i)
1265
frags.push_back(clipbox(cw::fragf(_(" %S*%N %s [version %s]%n"),
1267
i->ParentPkg().Name(), i->VerStr())));
1269
main_stacked->add_visible_widget(cw::dialogs::yesno(cw::sequence_fragment(frags),
1270
cw::util::arg(sigc::ptr_fun(install_or_remove_packages)),
1271
W_("Really Continue"),
1273
W_("Abort Installation"),
1274
cw::get_style("TrustWarning"),
1280
install_or_remove_packages();
1285
void actually_do_package_run();
1288
static void reset_preview()
1290
active_preview=NULL;
1291
active_preview_tree=NULL;
1294
// One word: ewwwwwwww. I REALLY need to get my act together on the
1295
// view-customization stuff.
1296
static void do_show_preview()
1298
if(!active_preview_tree.valid())
1300
eassert(!active_preview.valid());
1302
pkg_grouppolicy_factory *grp=NULL;
1305
if(aptcfg->Exists(PACKAGE "::UI::Default-Preview-Grouping"))
1307
grpstr=aptcfg->Find(PACKAGE "::UI::Default-Preview-Grouping");
1308
grp=parse_grouppolicy(grpstr);
1311
//if(!grp && aptcfg->Exists(PACKAGE "::UI::Default-Grouping"))
1313
// grpstr=aptcfg->Find(PACKAGE "::UI::Default-Grouping");
1314
// grp=parse_grouppolicy(grpstr);
1320
grp=new pkg_grouppolicy_mode_factory(new pkg_grouppolicy_end_factory);
1323
if(aptcfg->Exists(PACKAGE "::UI::Preview-Limit"))
1324
active_preview_tree=pkg_tree::create(grpstr.c_str(), grp, cw::util::transcode(aptcfg->Find(PACKAGE "::UI::Preview-Limit").c_str()));
1326
active_preview_tree=pkg_tree::create(grpstr.c_str(), grp);
1328
active_preview=make_default_view(active_preview_tree,
1329
&active_preview_tree->selected_signal,
1330
&active_preview_tree->selected_desc_signal,
1334
active_preview->destroyed.connect(sigc::ptr_fun(reset_preview));
1335
active_preview->connect_key("DoInstallRun",
1336
&cw::config::global_bindings,
1337
sigc::ptr_fun(actually_do_package_run));
1338
add_main_widget(active_preview, _("Preview of package installation"),
1339
_("View and/or adjust the actions that will be performed"),
1342
progress_ref p=gen_progress_bar();
1343
active_preview_tree->build_tree(*p->get_progress().unsafe_get_ref());
1348
eassert(active_preview.valid());
1349
active_preview->show();
1353
static void do_keep_all()
1355
auto_ptr<undo_group> undo(new apt_undo_group);
1357
aptitudeDepCache::action_group group(*apt_cache_file, undo.get());
1359
for(pkgCache::PkgIterator i=(*apt_cache_file)->PkgBegin();
1361
(*apt_cache_file)->mark_keep(i, false, false, undo.get());
1363
if(!undo.get()->empty())
1364
apt_undos->add_item(undo.release());
1367
static void fixer_dialog_done()
1369
if(active_preview_tree.valid())
1370
active_preview_tree->build_tree();
1371
do_package_run_or_show_preview();
1374
static void install_fixer_dialog()
1376
cw::widget_ref w=make_solution_dialog();
1377
w->destroyed.connect(sigc::ptr_fun(fixer_dialog_done));
1378
popup_widget(w, true);
1382
static void auto_fix_broken()
1384
undo_group *undo=new apt_undo_group;
1388
eassert(resman != NULL);
1389
eassert(resman->resolver_exists());
1391
aptitude_solution sol = resman->get_solution(resman->get_selected_solution(), 0);
1393
(*apt_cache_file)->apply_solution(sol, undo);
1395
cw::widget_ref d = cw::dialogs::ok(cw::fragf("%s%n%n%F",
1396
_("Some packages were broken and have been fixed:"),
1397
solution_fragment(sol)),
1400
popup_widget(d, true);
1402
catch(NoMoreSolutions)
1404
show_message(_("No solution to these dependency problems exists!"),
1406
cw::get_style("Error"));
1410
show_message(cw::fragf(_("Ran out of time while trying to resolve dependencies (press \"%s\" to try harder)"),
1411
cw::config::global_bindings.readable_keyname("NextSolution").c_str()),
1413
cw::get_style("Error"));
1417
apt_undos->add_item(undo);
1421
if(active_preview_tree.valid())
1422
active_preview_tree->build_tree();
1426
// Huge FIXME: the preview interacts badly with the menu. This can be solved
1427
// in a couple ways, including having the preview be a popup dialog -- the best
1428
// thing IMO, though, would be to somehow allow particular widgets to override
1429
// the meaning of global commands. This needs a little thought, though. (fake
1431
static void actually_do_package_run_post_essential_check()
1435
if(!active_download)
1437
// whatever we call will chain to the next appropriate
1439
if((*apt_cache_file)->BrokenCount()>0)
1441
if(_config->FindB(PACKAGE "::Auto-Fix-Broken", true))
1447
install_fixer_dialog();
1452
if(getuid()==0 || !aptcfg->FindB(PACKAGE "::Warn-Not-Root", true))
1453
check_package_trust();
1456
popup_widget(cw::dialogs::yesno(wrapbox(cw::text_fragment(_("Installing/removing packages requires administrative privileges, which you currently do not have. Would you like to change to the root account?"))),
1457
cw::util::arg(sigc::bind(sigc::ptr_fun(&do_su_to_root),
1460
cw::util::arg(sigc::ptr_fun(&check_package_trust)),
1461
W_("Don't become root"),
1462
cw::get_style("Error")));
1466
show_message(_("A package-list update or install run is already taking place."), NULL, cw::get_style("Error"));
1472
void actually_do_package_run_finish_delete_essential(const std::wstring &response)
1474
if(response == cw::util::transcode(_(confirm_delete_essential_str)) ||
1475
response == cw::util::transcode(confirm_delete_essential_str))
1476
actually_do_package_run_post_essential_check();
1479
void actually_do_package_run()
1483
// Failsafe check to ensure that we aren't deleting any
1484
// Essential packages.
1486
// \todo We should remember which ones the user already
1487
// confirmed and not ask twice.
1488
std::vector<pkgCache::PkgIterator> deleted_essential, broken_essential;
1490
for(pkgCache::PkgIterator pkg = (*apt_cache_file)->PkgBegin();
1493
pkgDepCache::StateCache &state = (*apt_cache_file)[pkg];
1495
if((pkg->Flags & pkgCache::Flag::Essential) &&
1499
deleted_essential.push_back(pkg);
1500
if(state.InstBroken())
1501
broken_essential.push_back(pkg);
1505
if(deleted_essential.empty() && broken_essential.empty())
1506
actually_do_package_run_post_essential_check();
1509
// We reuse the command line's strings here so that
1510
// translators don't need to add new translations.
1511
std::vector<cw::fragment *> fragments;
1512
if(!deleted_essential.empty())
1514
fragments.push_back(wrapbox(cw::text_fragment(_("The following ESSENTIAL packages will be REMOVED!\n"))));
1516
for(std::vector<pkgCache::PkgIterator>::const_iterator it =
1517
deleted_essential.begin(); it != deleted_essential.end(); ++it)
1519
fragments.push_back(cw::fragf(" %S*%N %s%n",
1524
fragments.push_back(cw::newline_fragment());
1527
if(!broken_essential.empty())
1529
fragments.push_back(cw::text_fragment(_("The following ESSENTIAL packages will be BROKEN by this action:\n")));
1531
for(std::vector<pkgCache::PkgIterator>::const_iterator it =
1532
broken_essential.begin(); it != broken_essential.end(); ++it)
1534
fragments.push_back(cw::fragf(" %S*%N %s%n",
1539
fragments.push_back(cw::newline_fragment());
1542
fragments.push_back(wrapbox(cw::text_fragment(_("WARNING: Performing this action will probably cause your system to break!\n Do NOT continue unless you know EXACTLY what you are doing!\n"))));
1543
fragments.push_back(wrapbox(cw::fragf(_("To continue, type the phrase \"%s\":\n"), confirm_delete_essential_str)));
1545
cw::widget_ref w = cw::dialogs::string(cw::sequence_fragment(fragments),
1547
cw::util::arg(sigc::ptr_fun(&actually_do_package_run_finish_delete_essential)),
1551
cw::style_attrs_flip(A_REVERSE));
1559
void do_package_run_or_show_preview()
1561
// UI: check that something will actually be done first.
1562
bool some_action_happening=false;
1563
bool some_non_simple_keep_happening=false;
1564
for(pkgCache::PkgIterator i=(*apt_cache_file)->PkgBegin(); !i.end(); ++i)
1566
pkg_action_state state = find_pkg_state(i, *apt_cache_file);
1568
if(state!=pkg_unchanged)
1570
some_action_happening=true;
1572
if(!(state==pkg_hold && !(*apt_cache_file)->is_held(i)))
1573
some_non_simple_keep_happening=true;
1576
if(some_action_happening && some_non_simple_keep_happening)
1580
if(!some_action_happening)
1582
show_message(_("No packages are scheduled to be installed, removed, or upgraded."));
1585
else if(!some_non_simple_keep_happening &&
1586
!aptcfg->FindB(PACKAGE "::Allow-Null-Upgrade", false))
1588
show_message(_("No packages will be installed, removed or upgraded. "
1589
"Some packages could be upgraded, but you have not chosen to upgrade them. "
1590
"Type \"U\" to prepare an upgrade."));
1596
if(!active_preview.valid() || !active_preview->get_visible())
1598
if(aptcfg->FindB(PACKAGE "::Display-Planned-Action", true))
1601
actually_do_package_run();
1605
active_preview_tree->build_tree();
1606
// We need to rebuild the tree since this is called after a
1607
// broken-fixing operation. This feels like a hack, though..
1608
active_preview->show();
1613
static bool can_start_download()
1615
return !active_download;
1618
static bool can_start_download_and_install()
1620
return !active_download && apt_cache_file != NULL;
1623
void do_package_run()
1627
if(active_preview_tree.valid() && active_preview_tree->get_visible())
1628
actually_do_package_run();
1629
else if((*apt_cache_file)->BrokenCount()>0)
1631
if(aptcfg->FindB(PACKAGE "::Auto-Fix-Broken", true))
1634
do_package_run_or_show_preview();
1637
install_fixer_dialog();
1640
do_package_run_or_show_preview();
1644
static void lists_autoclean_msg(boost::weak_ptr<download_update_manager> m_weak)
1646
boost::shared_ptr<download_update_manager> m(m_weak);
1651
cw::widget_ref msg = cw::center::create(cw::frame::create(cw::label::create(_("Deleting obsolete downloaded files"))));
1652
m->post_autoclean_hook.connect(sigc::mem_fun(msg.unsafe_get_ref(),
1653
&cw::widget::destroy));
1656
cw::toplevel::tryupdate();
1659
void really_do_update_lists()
1661
boost::shared_ptr<download_update_manager> m = boost::make_shared<download_update_manager>();
1662
m->pre_autoclean_hook.connect(sigc::bind(sigc::ptr_fun(lists_autoclean_msg),
1663
boost::weak_ptr<download_update_manager>(m)));
1664
m->post_forget_new_hook.connect(package_states_changed.make_slot());
1666
std::pair<download_signal_log *, download_list_ref>
1667
download_log_pair = gen_download_progress(false, true,
1668
_("Updating package lists"),
1669
_("View the progress of the package list update"),
1672
ui_download_manager *uim = new ui_download_manager(m,
1673
download_log_pair.first,
1674
download_log_pair.second,
1675
sigc::ptr_fun(&make_progress_bar),
1678
download_log_pair.second->cancelled.connect(sigc::mem_fun(*uim, &ui_download_manager::aborted));
1680
uim->download_starts.connect(sigc::bind(sigc::ptr_fun(&ui_start_download), false));
1681
uim->download_stops.connect(sigc::ptr_fun(&ui_stop_download));
1683
uim->download_complete.connect(update_finished.make_slot());
1687
void do_update_lists()
1689
if(!active_download)
1691
if(getuid()==0 || !aptcfg->FindB(PACKAGE "::Warn-Not-Root", true))
1692
really_do_update_lists();
1695
popup_widget(cw::dialogs::yesno(wrapbox(cw::text_fragment(_("Updating the package lists requires administrative privileges, which you currently do not have. Would you like to change to the root account?"))),
1696
cw::util::arg(sigc::bind(sigc::ptr_fun(&do_su_to_root),
1699
cw::util::arg(sigc::ptr_fun(&really_do_update_lists)),
1700
W_("Don't become root"),
1701
cw::get_style("Error")));
1705
show_message(_("A package-list update or install run is already taking place."), NULL, cw::get_style("Error"));
1708
static void do_sweep()
1710
add_main_widget(cmine::create(), _("Minesweeper"), _("Waste time trying to find mines"), _("Minesweeper"));
1713
static void really_do_clean()
1716
// Erk! That's weird!
1717
_error->Error(_("Cleaning while a download is in progress is not allowed"));
1720
cw::widget_ref msg=cw::center::create(cw::frame::create(cw::label::create(_("Deleting downloaded files"))));
1723
cw::toplevel::tryupdate();
1728
fetcher.Clean(aptcfg->FindDir("Dir::Cache::archives"));
1729
fetcher.Clean(aptcfg->FindDir("Dir::Cache::archives")+"partial/");
1734
show_message(_("Downloaded package files have been deleted"));
1740
if(getuid()==0 || !aptcfg->FindB(PACKAGE "::Warn-Not-Root", true))
1744
popup_widget(cw::dialogs::yesno(wrapbox(cw::text_fragment(_("Cleaning the package cache requires administrative privileges, which you currently do not have. Would you like to change to the root account?"))),
1745
cw::util::arg(sigc::bind(sigc::ptr_fun(&do_su_to_root),
1746
"--clean-on-startup")),
1748
cw::util::arg(sigc::ptr_fun(&really_do_update_lists)),
1749
W_("Don't become root"),
1750
cw::get_style("Error")));
1754
// Ok, this is, uh, weird. Erase has to be overridden to at least
1757
// Should I list what I'm doing like apt-get does?
1758
class my_cleaner:public pkgArchiveCleaner
1762
virtual void Erase(const char *file,
1768
total_size+=stat.st_size;
1772
long get_total_size() {return total_size;}
1775
// g++ bug? If I include this implementation above in the class
1776
// def'n, it never gets called!
1777
my_cleaner::my_cleaner()
1782
static bool do_autoclean_enabled()
1784
return apt_cache_file != NULL;
1787
static void really_do_autoclean()
1789
if(apt_cache_file == NULL)
1790
_error->Error(_("The apt cache file is not available; cannot auto-clean."));
1791
else if(active_download)
1792
// Erk! That's weird!
1793
_error->Error(_("Cleaning while a download is in progress is not allowed"));
1796
cw::widget_ref msg=cw::center::create(cw::frame::create(cw::label::create(_("Deleting obsolete downloaded files"))));
1799
cw::toplevel::tryupdate();
1801
long cleaned_size=0;
1807
cleaner.Go(aptcfg->FindDir("Dir::Cache::archives"), *apt_cache_file);
1808
cleaner.Go(aptcfg->FindDir("Dir::Cache::archives")+"partial/",
1811
cleaned_size=cleaner.get_total_size();
1816
show_message(ssprintf(_("Obsolete downloaded package files have been deleted, freeing %sB of disk space."),
1817
SizeToStr(cleaned_size).c_str()));
1823
if(getuid()==0 || !aptcfg->FindB(PACKAGE "::Warn-Not-Root", true))
1824
really_do_autoclean();
1827
popup_widget(cw::dialogs::yesno(wrapbox(cw::text_fragment(_("Deleting obsolete files requires administrative privileges, which you currently do not have. Would you like to change to the root account?"))),
1828
cw::util::arg(sigc::bind(sigc::ptr_fun(&do_su_to_root),
1829
"--autoclean-on-startup")),
1831
cw::util::arg(sigc::ptr_fun(&really_do_update_lists)),
1832
W_("Don't become root"),
1833
cw::get_style("Error")));
1837
static bool do_mark_upgradable_enabled()
1839
return apt_cache_file != NULL;
1842
static void do_mark_upgradable()
1846
undo_group *undo=new apt_undo_group;
1848
(*apt_cache_file)->mark_all_upgradable(true, true, undo);
1851
apt_undos->add_item(undo);
1855
package_states_changed();
1859
static bool forget_new_enabled()
1864
return (*apt_cache_file)->get_new_package_count()>0;
1867
void do_forget_new()
1871
undoable *undo=NULL;
1872
(*apt_cache_file)->forget_new(&undo);
1874
apt_undos->add_item(undo);
1876
package_states_changed();
1880
#ifdef WITH_RELOAD_CACHE
1881
static void do_reload_cache()
1883
progress_ref p = gen_progress_bar();
1884
apt_reload_cache(p->get_progress().unsafe_get_ref(), true);
1889
static void start_solution_calculation();
1891
class interactive_continuation : public resolver_manager::background_continuation
1893
/** The manager associated with this continuation; usually resman. */
1894
resolver_manager *manager;
1896
/** Indicate that a new solution is available by invoking the
1897
* selection_changed signal.
1899
class success_event : public cw::toplevel::event
1901
resolver_manager *manager;
1903
success_event(resolver_manager *_manager)
1910
manager->state_changed();
1914
class no_more_solutions_event : public cw::toplevel::event
1916
resolver_manager *manager;
1918
no_more_solutions_event(resolver_manager *_manager)
1925
resolver_manager::state st = manager->state_snapshot();
1927
if(st.selected_solution == st.generated_solutions)
1928
manager->select_previous_solution();
1929
show_message(_("No more solutions."));
1931
manager->state_changed();
1935
class solution_search_aborted_event : public cw::toplevel::event
1937
resolver_manager *manager;
1940
solution_search_aborted_event(resolver_manager *_manager,
1942
: manager(_manager), msg(_msg)
1948
resolver_manager::state st = manager->state_snapshot();
1950
if(st.selected_solution == st.generated_solutions)
1951
manager->select_previous_solution();
1952
show_message(ssprintf("Fatal error in dependency resolver. You can continue searching, but some solutions might be impossible to generate.\n\n%s",
1955
manager->state_changed();
1959
interactive_continuation(resolver_manager *_manager)
1964
void success(const aptitude_solution &sol)
1966
cw::toplevel::post_event(new success_event(manager));
1969
void no_more_solutions()
1971
cw::toplevel::post_event(new no_more_solutions_event(manager));
1976
start_solution_calculation();
1983
void aborted(const std::string &errmsg)
1985
cw::toplevel::post_event(new solution_search_aborted_event(manager, errmsg));
1989
void cwidget_resolver_trampoline(const sigc::slot<void> &f)
1994
// If the current solution pointer is past the end of the solution
1995
// list, queue up a calculation for it in the background thread.
1996
static void start_solution_calculation()
1998
resman->maybe_start_solution_calculation(boost::make_shared<interactive_continuation>(resman),
1999
&cwidget_resolver_trampoline);
2002
static void do_connect_resolver_callback()
2004
resman->state_changed.connect(sigc::ptr_fun(&start_solution_calculation));
2005
// We may have missed a signal before making the connection:
2006
start_solution_calculation();
2007
resman->state_changed.connect(sigc::ptr_fun(&cw::toplevel::update));
2010
static bool do_next_solution_enabled()
2015
resolver_manager::state state = resman->state_snapshot();
2018
state.selected_solution < state.generated_solutions &&
2019
!(state.selected_solution + 1 == state.generated_solutions &&
2020
state.solutions_exhausted);
2023
void do_next_solution()
2025
if(!do_next_solution_enabled())
2029
// If an error was encountered, pressing "next solution"
2031
resman->discard_error_information();
2032
resman->select_next_solution();
2036
static bool do_previous_solution_enabled()
2041
resolver_manager::state state = resman->state_snapshot();
2043
return state.selected_solution > 0;
2046
void do_previous_solution()
2048
if(!do_previous_solution_enabled())
2051
resman->select_previous_solution();
2054
static bool do_first_solution_enabled()
2059
resolver_manager::state state = resman->state_snapshot();
2061
return state.resolver_exists && state.selected_solution > 0;
2064
static void do_first_solution()
2066
if(!do_first_solution_enabled())
2069
resman->select_solution(0);
2072
static bool do_last_solution_enabled()
2077
resolver_manager::state state = resman->state_snapshot();
2079
return state.resolver_exists && state.selected_solution + 1 < state.generated_solutions;
2082
static void do_last_solution()
2090
resolver_manager::state state = resman->state_snapshot();
2092
if(!(state.resolver_exists && state.selected_solution + 1 < state.generated_solutions))
2095
resman->select_solution(state.generated_solutions - 1);
2098
static bool do_apply_solution_enabled_from_state(const resolver_manager::state &state)
2101
state.resolver_exists &&
2102
state.selected_solution >= 0 &&
2103
state.selected_solution < state.generated_solutions;
2106
static bool do_apply_solution_enabled()
2111
resolver_manager::state state = resman->state_snapshot();
2112
return do_apply_solution_enabled_from_state(state);
2115
void do_apply_solution()
2120
resolver_manager::state state = resman->state_snapshot();
2122
if(!do_apply_solution_enabled_from_state(state))
2129
undo_group *undo=new apt_undo_group;
2132
(*apt_cache_file)->apply_solution(resman->get_solution(state.selected_solution, aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000)),
2135
catch(NoMoreSolutions)
2137
show_message(_("Unable to find a solution to apply."),
2139
cw::get_style("Error"));
2143
show_message(_("Ran out of time while trying to find a solution."),
2145
cw::get_style("Error"));
2150
apt_undos->add_item(undo);
2151
package_states_changed();
2160
bool do_reject_break_holds_enabled()
2162
return resman != NULL && resman->resolver_exists();
2165
void do_reject_break_holds()
2167
if(!do_reject_break_holds_enabled())
2170
resman->reject_break_holds();
2174
static void do_nullify_solver(cw::widget_ref *solver)
2179
static bool do_examine_solution_enabled()
2181
return resman != NULL && resman->resolver_exists() &&
2182
aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000) > 0;
2185
void do_examine_solution()
2187
if(!do_examine_solution_enabled())
2193
static cw::widget_ref solver;
2199
solver = make_solution_screen();
2200
solver->destroyed.connect(sigc::bind(sigc::ptr_fun(&do_nullify_solver),
2203
add_main_widget(solver, _("Resolve Dependencies"),
2204
_("Search for solutions to unsatisfied dependencies"),
2205
_("Resolve Dependencies"));
2209
static void handle_dump_resolver_response(const wstring &s)
2211
if(resman != NULL && resman->resolver_exists())
2213
ofstream out(cw::util::transcode(s).c_str());
2216
_error->Errno("dump_resolver", _("Unable to open %ls"), s.c_str());
2222
_error->Errno("dump_resolver", _("Error while dumping resolver state"));
2227
static void do_dump_resolver()
2229
static cw::editline::history_list history;
2231
if(resman != NULL && resman->resolver_exists())
2232
prompt_string(_("File to which the resolver state should be dumped:"),
2234
cw::util::arg(sigc::ptr_fun(handle_dump_resolver_response)),
2240
// NOTE ON TRANSLATIONS!
2242
// Implicitly translating stuff in the widget set would be ugly. Everything
2243
// would need to make sure its input to the widget set was able to survive
2246
// Using N_ here and translating when we need to display the description
2247
// would be ugly. Everything would need to make sure its input to the UI would
2248
// be able to handle translation.
2250
// What I do is ugly, but it doesn't force other bits of the program to handle
2251
// input to us with velvet gloves, or otherwise break stuff. So these structures
2252
// just contain a char *. I can modify the char *. In particular, I can mark
2253
// these for translation, then walk through them and munge the pointers to point
2254
// to the translated version. "EWWWWW!" I hear you say, and you're right, but
2255
// the alternatives are worse.
2257
cw::menu_info actions_menu[]={
2258
//{cw::menu_info::MENU_ITEM, N_("Test ^Errors"), NULL,
2259
//N_("Generate an APT error for testing purposes"),
2260
//SigC::bind(SigC::slot(&silly_test_error), "This is a test error item.")},
2262
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Install/remove packages"), "DoInstallRun",
2263
N_("Perform all pending installs and removals"), sigc::ptr_fun(do_package_run), sigc::ptr_fun(can_start_download_and_install)),
2265
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Update package list"), "UpdatePackageList",
2266
N_("Check for new versions of packages"), sigc::ptr_fun(do_update_lists), sigc::ptr_fun(can_start_download)),
2268
cw::menu_info::MENU_SEPARATOR,
2270
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Mark Up^gradable"), "MarkUpgradable",
2271
N_("Mark all upgradable packages which are not held for upgrade"),
2272
sigc::ptr_fun(do_mark_upgradable), sigc::ptr_fun(do_mark_upgradable_enabled)),
2274
// FIXME: this is a bad name for the menu item.
2275
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Forget new packages"), "ForgetNewPackages",
2276
N_("Forget which packages are \"new\""),
2277
sigc::ptr_fun(do_forget_new), sigc::ptr_fun(forget_new_enabled)),
2279
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Canc^el pending actions"), NULL,
2280
N_("Cancel all pending installations, removals, holds, and upgrades."),
2281
sigc::ptr_fun(do_keep_all)),
2283
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Clean package cache"), NULL,
2284
N_("Delete package files which were previously downloaded"),
2285
sigc::ptr_fun(do_clean)),
2287
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Clean ^obsolete files"), NULL,
2288
N_("Delete package files which can no longer be downloaded"),
2289
sigc::ptr_fun(do_autoclean), sigc::ptr_fun(do_autoclean_enabled)),
2291
cw::menu_info::MENU_SEPARATOR,
2293
#ifdef WITH_RELOAD_CACHE
2294
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Reload package cache"), NULL,
2295
N_("Reload the package cache"),
2296
sigc::ptr_fun(do_reload_cache)),
2299
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Play Minesweeper"), NULL,
2300
N_("Waste time trying to find mines"), sigc::ptr_fun(do_sweep)),
2302
cw::menu_info::MENU_SEPARATOR,
2304
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Become root"), NULL,
2305
N_("Run 'su' to become root; this will restart the program, but your settings will be preserved"), sigc::bind(sigc::ptr_fun(do_su_to_root), ""), sigc::ptr_fun(su_to_root_enabled)),
2307
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Quit"), "QuitProgram",
2308
N_("Exit the program"), sigc::ptr_fun(do_quit)),
2310
cw::menu_info::MENU_END
2313
cw::menu_info undo_menu[]={
2314
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Undo"), "Undo",
2315
N_("Undo the last package operation or group of operations"),
2316
sigc::hide_return(undo_undo.make_slot()),
2317
undo_undo_enabled.make_slot()),
2319
cw::menu_info::MENU_END
2322
cw::menu_info package_menu[]={
2323
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Install"), "Install",
2324
N_("Flag the currently selected package for installation or upgrade"),
2325
sigc::hide_return(package_install.make_slot()),
2326
package_menu_enabled.make_slot()),
2327
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Remove"), "Remove",
2328
N_("Flag the currently selected package for removal"),
2329
sigc::hide_return(package_remove.make_slot()),
2330
package_menu_enabled.make_slot()),
2331
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Purge"), "Purge",
2332
N_("Flag the currently selected package and its configuration files for removal"),
2333
sigc::hide_return(package_purge.make_slot()),
2334
package_menu_enabled.make_slot()),
2335
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Keep"), "Keep",
2336
N_("Cancel any action on the selected package"),
2337
sigc::hide_return(package_keep.make_slot()),
2338
package_menu_enabled.make_slot()),
2339
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Hold"), "Hold",
2340
N_("Cancel any action on the selected package, and protect it from future upgrades"),
2341
sigc::hide_return(package_hold.make_slot()),
2342
package_menu_enabled.make_slot()),
2343
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Mark ^Auto"), "SetAuto",
2344
N_("Mark the selected package as having been automatically installed; it will automatically be removed if no other packages depend on it"),
2345
sigc::hide_return(package_mark_auto.make_slot()),
2346
package_menu_enabled.make_slot()),
2347
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Mark ^Manual"), "ClearAuto",
2348
N_("Mark the selected package as having been manually installed; it will not be removed unless you manually remove it"),
2349
sigc::hide_return(package_unmark_auto.make_slot()),
2350
package_menu_enabled.make_slot()),
2351
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Forbid Version"), "ForbidUpgrade",
2352
N_("Forbid the candidate version of the selected package from being installed; newer versions of the package will be installed as usual"),
2353
sigc::hide_return(package_forbid.make_slot()),
2354
package_forbid_enabled.make_slot()),
2355
cw::menu_info::MENU_SEPARATOR,
2356
cw::menu_info(cw::menu_info::MENU_ITEM, N_("I^nformation"), "InfoScreen",
2357
N_("Display more information about the selected package"),
2358
sigc::hide_return(package_information.make_slot()),
2359
package_information_enabled.make_slot()),
2360
cw::menu_info(cw::menu_info::MENU_ITEM, N_("C^ycle Package Information"), "DescriptionCycle",
2361
N_("Cycle through the modes of the package information area: it can show the package's long description, a summary of its dependency status, or an analysis of why the package is required."),
2362
sigc::hide_return(package_cycle_information.make_slot()),
2363
package_cycle_information_enabled.make_slot()),
2364
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Changelog"), "Changelog",
2365
N_("Display the Debian changelog of the selected package"),
2366
sigc::hide_return(package_changelog.make_slot()),
2367
package_changelog_enabled.make_slot()),
2368
cw::menu_info::MENU_END
2371
cw::menu_info resolver_menu[] = {
2372
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Examine Solution"),
2373
"ExamineSolution", N_("Examine the currently selected solution to the dependency problems."),
2374
sigc::ptr_fun(do_examine_solution),
2375
sigc::ptr_fun(do_examine_solution_enabled)),
2376
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Apply ^Solution"),
2377
"ApplySolution", N_("Perform the actions contained in the currently selected solution."),
2378
sigc::ptr_fun(do_apply_solution),
2379
sigc::ptr_fun(do_apply_solution_enabled)),
2380
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Next Solution"),
2381
"NextSolution", N_("Select the next solution to the dependency problems."),
2382
sigc::ptr_fun(do_next_solution),
2383
sigc::ptr_fun(do_next_solution_enabled)),
2384
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Previous Solution"),
2385
"PrevSolution", N_("Select the previous solution to the dependency problems."),
2386
sigc::ptr_fun(do_previous_solution),
2387
sigc::ptr_fun(do_previous_solution_enabled)),
2388
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^First Solution"),
2389
"FirstSolution", N_("Select the first solution to the dependency problems."),
2390
sigc::ptr_fun(do_first_solution),
2391
sigc::ptr_fun(do_first_solution_enabled)),
2392
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Last Solution"),
2393
"LastSolution", N_("Select the last solution to the dependency problems that has been generated so far."),
2394
sigc::ptr_fun(do_last_solution),
2395
sigc::ptr_fun(do_last_solution_enabled)),
2397
cw::menu_info::MENU_SEPARATOR,
2399
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Toggle ^Rejected"),
2400
"SolutionActionReject", N_("Toggle whether the currently selected action is rejected."),
2401
sigc::hide_return(resolver_toggle_rejected.make_slot()),
2402
resolver_toggle_rejected_enabled.make_slot()),
2404
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Toggle ^Approved"),
2405
"SolutionActionApprove", N_("Toggle whether the currently selected action is approved."),
2406
sigc::hide_return(resolver_toggle_approved.make_slot()),
2407
resolver_toggle_approved_enabled.make_slot()),
2409
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^View Target"),
2410
"InfoScreen", N_("View the package which will be affected by the selected action"),
2411
sigc::hide_return(resolver_view_target.make_slot()),
2412
resolver_view_target_enabled.make_slot()),
2414
cw::menu_info::MENU_SEPARATOR,
2416
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Reject Breaking ^Holds"),
2418
N_("Reject all actions that would change the state of held packages or install forbidden versions"),
2419
sigc::ptr_fun(&do_reject_break_holds),
2420
sigc::ptr_fun(&do_reject_break_holds_enabled)),
2422
cw::menu_info::MENU_END
2425
cw::menu_info search_menu[]={
2426
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Find"), "Search",
2427
N_("Search forwards"),
2428
sigc::hide_return(find_search.make_slot()),
2429
find_search_enabled.make_slot()),
2430
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Find Backwards"), "SearchBack",
2431
N_("Search backwards"),
2432
sigc::hide_return(find_search_back.make_slot()),
2433
find_search_back_enabled.make_slot()),
2434
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Find ^Again"), "ReSearch",
2435
N_("Repeat the last search"),
2436
sigc::hide_return(find_research.make_slot()),
2437
find_research_enabled.make_slot()),
2438
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Find Again ^Backwards"), "RepeatSearchBack",
2439
N_("Repeat the last search in the opposite direction"),
2440
sigc::hide_return(find_repeat_search_back.make_slot()),
2441
find_repeat_search_back_enabled.make_slot()),
2442
cw::menu_info::MENU_SEPARATOR,
2443
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Limit Display"),
2444
"ChangePkgTreeLimit", N_("Apply a filter to the package list"),
2445
sigc::hide_return(find_limit.make_slot()),
2446
find_limit_enabled.make_slot()),
2447
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Un-Limit Display"),
2448
NULL, N_("Remove the filter from the package list"),
2449
sigc::hide_return(find_cancel_limit.make_slot()),
2450
find_cancel_limit_enabled.make_slot()),
2451
cw::menu_info::MENU_SEPARATOR,
2452
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Find ^Broken"),
2453
"SearchBroken", N_("Find the next package with unsatisfied dependencies"),
2454
sigc::hide_return(find_broken.make_slot()),
2455
find_broken_enabled.make_slot()),
2456
cw::menu_info::MENU_END
2459
cw::menu_info options_menu[]={
2460
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Preferences"), NULL,
2461
N_("Change the behavior of aptitude"),
2462
sigc::ptr_fun(do_show_options_tree)),
2465
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^UI options"), NULL,
2466
N_("Change the settings which affect the user interface"),
2467
sigc::ptr_fun(do_show_ui_options_dlg)),
2469
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Dependency handling"), NULL,
2470
N_("Change the settings which affect how package dependencies are handled"),
2471
sigc::ptr_fun(do_show_dependency_options_dlg)),
2473
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Miscellaneous"), NULL,
2474
N_("Change miscellaneous program settings"),
2475
sigc::ptr_fun(do_show_misc_options_dlg)),
2478
cw::menu_info::MENU_SEPARATOR,
2480
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Revert options"), NULL,
2481
N_("Reset all settings to the system defaults"),
2482
sigc::ptr_fun(do_revert_options)),
2484
//{cw::menu_info::MENU_ITEM, N_("^Save options"), NULL,
2485
// N_("Save current settings for future sessions"), cw::util::arg(bind(sigc::ptr_fun(apt_dumpcfg)),
2488
cw::menu_info::MENU_END
2491
cw::menu_info views_menu_info[]={
2492
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Next"), "CycleNext",
2493
N_("View next display"), sigc::ptr_fun(do_view_next),
2494
sigc::ptr_fun(view_next_prev_enabled)),
2496
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Prev"), "CyclePrev",
2497
N_("View previous display"), sigc::ptr_fun(do_view_prev),
2498
sigc::ptr_fun(view_next_prev_enabled)),
2500
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Close"), "Quit",
2501
N_("Close this display"), sigc::ptr_fun(do_destroy_visible),
2502
sigc::ptr_fun(any_view_visible)),
2504
cw::menu_info::MENU_SEPARATOR,
2506
cw::menu_info(cw::menu_info::MENU_ITEM, N_("New Package ^View"), NULL,
2507
N_("Create a new default package view"),
2508
sigc::ptr_fun(do_new_package_view_with_new_bar)),
2510
cw::menu_info(cw::menu_info::MENU_ITEM, N_("Audit ^Recommendations"), NULL,
2511
N_("View packages which it is recommended that you install, but which are not currently installed."),
2512
sigc::ptr_fun(do_new_recommendations_view)),
2514
cw::menu_info(cw::menu_info::MENU_ITEM, N_("New ^Flat Package List"), NULL,
2515
N_("View all the packages on the system in a single uncategorized list"),
2516
sigc::ptr_fun(do_new_flat_view_with_new_bar)),
2518
cw::menu_info(cw::menu_info::MENU_ITEM, N_("New ^Debtags Browser"),
2520
N_("Browse packages using Debtags data"),
2521
sigc::ptr_fun(do_new_tag_view_with_new_bar)),
2523
cw::menu_info(cw::menu_info::MENU_ITEM, N_("New Categorical ^Browser"),
2525
N_("Browse packages by category"),
2526
sigc::ptr_fun(do_new_hier_view_with_new_bar)),
2528
cw::menu_info::MENU_SEPARATOR,
2529
cw::menu_info::MENU_END
2532
cw::menu_info help_menu_info[]={
2533
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^About"), NULL,
2534
N_("View information about this program"),
2535
sigc::ptr_fun(do_help_about)),
2537
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^Help"), "Help",
2538
N_("View the on-line help"), sigc::ptr_fun(do_help_help)),
2540
cw::menu_info(cw::menu_info::MENU_ITEM, N_("User's ^Manual"), NULL,
2541
N_("View the detailed program manual"),
2542
sigc::ptr_fun(do_help_readme)),
2544
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^FAQ"), NULL,
2545
N_("View a list of frequently asked questions"),
2546
sigc::ptr_fun(do_help_faq)),
2548
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^News"), NULL,
2549
N_("View the important changes made in each version of " PACKAGE),
2550
sigc::ptr_fun(do_help_news)),
2552
cw::menu_info(cw::menu_info::MENU_ITEM, N_("^License"), NULL,
2553
N_("View the terms under which you may copy and distribute aptitude"),
2554
sigc::ptr_fun(do_help_license)),
2556
cw::menu_info::MENU_END
2559
// This is responsible for converting a particular menu-info thingy.
2560
static void munge_menu(cw::menu_info *menu)
2562
while(menu->item_type!=cw::menu_info::MENU_END)
2564
if(menu->item_description)
2565
menu->item_description=_(menu->item_description);
2567
menu->item_name=_(menu->item_name);
2573
static void do_show_menu_description(cw::menu_item *item, cw::label &label)
2575
if(item && item->get_description().size()>0)
2578
label.set_text(wrapbox(cw::text_fragment(item->get_description())));
2587
// I want discardable signal arguments!
2588
static void do_setup_columns()
2590
pkg_item::pkg_columnizer::setup_columns(true);
2593
static void load_options(string base, bool usetheme)
2595
load_styles(base+"::Styles", usetheme);
2596
load_bindings(base+"::Keybindings", &cw::config::global_bindings, usetheme);
2597
load_bindings(base+"::Keybindings::EditLine", cw::editline::bindings, usetheme);
2598
load_bindings(base+"::Keybindings::Menu", cw::menu::bindings, usetheme);
2599
load_bindings(base+"::Keybindings::Menubar", cw::menubar::bindings, usetheme);
2600
load_bindings(base+"::Keybindings::Minesweeper", cmine::bindings, usetheme);
2601
load_bindings(base+"::Keybindings::MinibufChoice", cw::statuschoice::bindings, usetheme);
2602
load_bindings(base+"::Keybindings::Pager", cw::pager::bindings, usetheme);
2603
load_bindings(base+"::KeyBindings::PkgNode", pkg_tree_node::bindings, usetheme);
2604
load_bindings(base+"::Keybindings::PkgTree", pkg_tree::bindings, usetheme);
2605
load_bindings(base+"::Keybindings::Table", cw::table::bindings, usetheme);
2606
load_bindings(base+"::Keybindings::TextLayout", cw::text_layout::bindings, usetheme);
2607
load_bindings(base+"::Keybindings::Tree", cw::tree::bindings, usetheme);
2610
static cw::menu_ref add_menu(cw::menu_info *info, const std::string &name,
2611
const cw::label_ref &menu_description)
2615
cw::menu_ref menu=cw::menu::create(0, 0, 0, info);
2617
main_menu->append_item(cw::util::transcode(name), menu);
2619
menu->item_highlighted.connect(sigc::bind(sigc::ptr_fun(do_show_menu_description),
2620
menu_description.weak_ref()));
2625
static void do_update_show_tabs(cw::multiplex &mp)
2627
mp.set_show_tabs(aptcfg->FindB(PACKAGE "::UI::ViewTabs", true));
2631
class help_bar:public cw::label
2634
help_bar(const wstring &txt, const cw::style &st):cw::label(txt, st)
2640
cw::util::ref_ptr<help_bar> create(const wstring &txt, const cw::style &st)
2642
cw::util::ref_ptr<help_bar> rval(new help_bar(txt, st));
2647
inline void set_visibility()
2649
set_visible(aptcfg->FindB(PACKAGE "::UI::HelpBar", true));
2652
typedef cw::util::ref_ptr<help_bar> help_bar_ref;
2654
/** \brief A list of global connections that must be disconnected when the UI exits. */
2655
std::deque<sigc::connection> global_connections;
2659
cw::toplevel::init();
2662
// The basic behavior of the package state signal is to update the
2664
global_connections.push_back(package_states_changed.connect(sigc::ptr_fun(cw::toplevel::update)));
2666
global_connections.push_back(consume_errors.connect(sigc::ptr_fun(check_apt_errors)));
2668
if(aptcfg->Exists(PACKAGE "::Theme"))
2669
load_options(PACKAGE "::Themes::"+string(aptcfg->Find(PACKAGE "::Theme"))+"::"+PACKAGE "::UI", true);
2671
load_options(PACKAGE "::UI", false);
2673
cw::label_ref menu_description=cw::label::create("");
2675
main_menu=cw::menubar::create(!aptcfg->FindB(PACKAGE "::UI::Menubar-Autohide", false));
2677
aptcfg->connect(string(PACKAGE "::UI::Menubar-Autohide"),
2678
sigc::ptr_fun(update_menubar_autohide));
2679
aptcfg->connect(string(PACKAGE "::UI::Package-Display-Format"),
2680
sigc::ptr_fun(do_setup_columns));
2682
global_connections.push_back(cache_closed.connect(sigc::ptr_fun(do_show_reload_message)));
2683
global_connections.push_back(cache_reloaded.connect(sigc::ptr_fun(do_hide_reload_message)));
2684
global_connections.push_back(cache_reloaded.connect(sigc::ptr_fun(do_connect_resolver_callback)));
2687
do_connect_resolver_callback();
2688
start_solution_calculation();
2690
global_connections.push_back(cache_reload_failed.connect(sigc::ptr_fun(do_hide_reload_message)));
2692
global_connections.push_back(cache_reloaded.connect(sigc::ptr_fun(do_connect_read_only_callbacks)));
2694
do_connect_read_only_callbacks();
2696
add_menu(actions_menu, _("Actions"), menu_description);
2697
add_menu(undo_menu, _("Undo"), menu_description);
2698
add_menu(package_menu, _("Package"), menu_description);
2699
add_menu(resolver_menu, _("Resolver"), menu_description);
2700
add_menu(search_menu, _("Search"), menu_description);
2701
add_menu(options_menu, _("Options"), menu_description);
2702
views_menu=add_menu(views_menu_info, _("Views"), menu_description);
2703
add_menu(help_menu_info, _("Help"), menu_description);
2705
main_stacked=cw::stacked::create();
2706
main_menu->set_subwidget(main_stacked);
2707
main_stacked->show();
2709
main_stacked->connect_key_post("QuitProgram", &cw::config::global_bindings, sigc::ptr_fun(do_quit));
2710
main_stacked->connect_key_post("Quit", &cw::config::global_bindings, sigc::ptr_fun(do_destroy_visible));
2711
main_stacked->connect_key_post("CycleNext",
2712
&cw::config::global_bindings,
2713
sigc::ptr_fun(do_view_next));
2714
main_stacked->connect_key_post("CyclePrev",
2715
&cw::config::global_bindings,
2716
sigc::ptr_fun(do_view_prev));
2717
main_stacked->connect_key_post("DoInstallRun",
2718
&cw::config::global_bindings,
2719
sigc::ptr_fun(do_package_run));
2720
main_stacked->connect_key_post("UpdatePackageList",
2721
&cw::config::global_bindings,
2722
sigc::ptr_fun(do_update_lists));
2723
main_stacked->connect_key_post("MarkUpgradable",
2724
&cw::config::global_bindings,
2725
sigc::ptr_fun(do_mark_upgradable));
2726
main_stacked->connect_key_post("ForgetNewPackages",
2727
&cw::config::global_bindings,
2728
sigc::ptr_fun(do_forget_new));
2729
main_stacked->connect_key_post("Help",
2730
&cw::config::global_bindings,
2731
sigc::ptr_fun(do_help_help));
2732
main_stacked->connect_key_post("Undo",
2733
&cw::config::global_bindings,
2734
sigc::hide_return(undo_undo.make_slot()));
2735
main_stacked->connect_key_post("NextSolution",
2736
&cw::config::global_bindings,
2737
sigc::ptr_fun(do_next_solution));
2738
main_stacked->connect_key_post("PrevSolution",
2739
&cw::config::global_bindings,
2740
sigc::ptr_fun(do_previous_solution));
2741
main_stacked->connect_key_post("FirstSolution",
2742
&cw::config::global_bindings,
2743
sigc::ptr_fun(do_first_solution));
2744
main_stacked->connect_key_post("LastSolution",
2745
&cw::config::global_bindings,
2746
sigc::ptr_fun(do_last_solution));
2747
main_stacked->connect_key_post("ApplySolution",
2748
&cw::config::global_bindings,
2749
sigc::ptr_fun(do_apply_solution));
2750
main_stacked->connect_key_post("ExamineSolution",
2751
&cw::config::global_bindings,
2752
sigc::ptr_fun(do_examine_solution));
2753
main_stacked->connect_key_post("DumpResolver",
2754
&cw::config::global_bindings,
2755
sigc::ptr_fun(do_dump_resolver));
2757
main_table=cw::table::create();
2758
main_stacked->add_widget(main_table);
2761
// FIXME: highlight the keys.
2762
wstring menu_key=cw::config::global_bindings.readable_keyname("ToggleMenuActive"),
2763
help_key=cw::config::global_bindings.readable_keyname("Help"),
2764
quit_key=cw::config::global_bindings.readable_keyname("Quit"),
2765
update_key=cw::config::global_bindings.readable_keyname("UpdatePackageList"),
2766
install_key=cw::config::global_bindings.readable_keyname("DoInstallRun");
2768
wstring helptext = swsprintf(W_("%ls: Menu %ls: Help %ls: Quit %ls: Update %ls: Download/Install/Remove Pkgs").c_str(),
2773
install_key.c_str());
2775
help_bar_ref help_label(help_bar::create(helptext, cw::get_style("Header")));
2776
main_table->add_widget_opts(help_label, 0, 0, 1, 1,
2777
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
2778
cw::table::ALIGN_CENTER);
2779
aptcfg->connect(string(PACKAGE "::UI::HelpBar"),
2780
sigc::mem_fun(help_label.unsafe_get_ref(), &help_bar::set_visibility));
2782
main_multiplex=cw::multiplex::create(aptcfg->FindB(PACKAGE "::UI::ViewTabs", true));
2783
aptcfg->connect(string(PACKAGE "::UI::ViewTabs"),
2784
sigc::bind(sigc::ptr_fun(&do_update_show_tabs), main_multiplex.weak_ref()));
2785
main_table->add_widget_opts(main_multiplex, 1, 0, 1, 1,
2786
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
2787
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK);
2788
main_multiplex->show();
2790
cw::widget_ref b=make_broken_indicator();
2791
main_table->add_widget_opts(b, 2, 0, 1, 1,
2792
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
2793
cw::table::ALIGN_CENTER);
2795
main_status_multiplex=cw::multiplex::create();
2796
main_status_multiplex->set_bg_style(cw::get_style("Status"));
2797
main_table->add_widget_opts(main_status_multiplex, 3, 0, 1, 1,
2798
cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
2799
cw::table::ALIGN_CENTER);
2800
main_status_multiplex->show();
2802
main_status_multiplex->add_widget(menu_description);
2806
cw::toplevel::settoplevel(main_menu);
2809
cw::toplevel::main_hook.connect(sigc::ptr_fun(check_apt_errors));
2811
help_label->set_visibility();
2813
update_menubar_autohide();
2815
// Force parsing of the column stuff.
2816
// FIXME: put this in load_options() and kill all other references
2817
// to setup_columns?
2818
pkg_item::pkg_columnizer::setup_columns();
2820
// Make sure the broken indicator doesn't annoyingly pop up for a
2823
// Note that it *should* be visible if we enter this code from the
2824
// command-line (i.e., with the cache already loaded). More hack?
2825
if(resman != NULL && resman->resolver_exists())
2830
maybe_show_old_tmpdir_message();
2833
struct clear_global_connections_on_exit
2835
clear_global_connections_on_exit()
2839
~clear_global_connections_on_exit()
2841
for(std::deque<sigc::connection>::iterator it = global_connections.begin();
2842
it != global_connections.end(); ++it)
2844
global_connections.clear();
2850
clear_global_connections_on_exit clearer;
2852
cw::toplevel::mainloop();
2854
if(apt_cache_file &&
2855
(aptitudeDepCache *) (*apt_cache_file) &&
2856
apt_cache_file->is_locked())
2858
progress_ref p=gen_progress_bar();
2859
(*apt_cache_file)->save_selection_list(*p->get_progress().unsafe_get_ref());
2863
cw::toplevel::shutdown();
2866
void popup_widget(const cw::widget_ref &w, bool do_show_all)
2868
main_stacked->add_widget(w);
2876
static void setup_main_widget(const cw::widget_ref &w, const std::wstring &menuref,
2877
const std::wstring &menudesc)
2879
cw::menu_item *menuentry=new cw::menu_item(menuref, "", menudesc);
2881
// FIXME: if w is removed from the multiplexer but not destroyed, this may
2882
// break. Fix for now: Don't Do That Then!
2883
w->destroyed.connect(sigc::bind(sigc::mem_fun(views_menu.unsafe_get_ref(), &cw::menu::remove_item), menuentry));
2884
menuentry->selected.connect(sigc::mem_fun(w.unsafe_get_ref(), &cw::widget::show));
2886
views_menu->append_item(menuentry);
2889
// Handles the case where the last view is destroyed directly (other than
2890
// through do_destroy_visible); for instance, when a download completes.
2891
static void main_widget_destroyed()
2893
if(aptcfg->FindB(PACKAGE "::UI::Exit-On-Last-Close", true) &&
2894
main_multiplex->num_children()==0)
2895
// Don't prompt -- if the last view is destroyed, assume it was by
2896
// the user's request.
2900
void add_main_widget(const cw::widget_ref &w, const std::wstring &menuref,
2901
const std::wstring &menudesc,
2902
const std::wstring &tabdesc)
2904
setup_main_widget(w, menuref, menudesc);
2905
main_multiplex->add_widget(w, tabdesc);
2907
w->destroyed.connect(sigc::ptr_fun(main_widget_destroyed));
2909
update_menubar_autohide();
2912
void add_main_widget(const cw::widget_ref &w, const std::string &menuref,
2913
const std::string &menudesc,
2914
const std::string &tabdesc)
2916
add_main_widget(w, cw::util::transcode(menuref), cw::util::transcode(menudesc),
2917
cw::util::transcode(tabdesc));
2920
void insert_main_widget(const cw::widget_ref &w, const std::wstring &menuref,
2921
const std::wstring &menudesc,
2922
const std::wstring &tabdesc)
2924
setup_main_widget(w, menuref, menudesc);
2925
main_multiplex->add_widget_after(w, main_multiplex->visible_widget(), tabdesc);
2928
update_menubar_autohide();
2931
void insert_main_widget(const cw::widget_ref &w, const std::string &menuref,
2932
const std::string &menudesc,
2933
const std::string &tabdesc)
2935
insert_main_widget(w, cw::util::transcode(menuref),
2936
cw::util::transcode(menudesc), cw::util::transcode(tabdesc));
2939
cw::widget_ref active_main_widget()
2941
return main_multiplex->visible_widget();
2944
progress_ref gen_progress_bar()
2946
progress_ref rval = progress::create();
2948
main_status_multiplex->add_visible_widget(rval, true);
2953
cw::fragment *wrapbox(cw::fragment *contents)
2955
if(aptcfg->FindB(PACKAGE "::UI::Fill-Text", false))
2956
return fillbox(contents);
2958
return flowbox(contents);
2961
static void reset_status_download()
2963
active_status_download=NULL;
2966
std::pair<download_signal_log *,
2968
gen_download_progress(bool force_noninvasive,
2970
const wstring &title,
2971
const wstring &longtitle,
2972
const wstring &tablabel)
2974
download_signal_log *m=new download_signal_log;
2975
download_list_ref w=NULL;
2977
if(force_noninvasive ||
2978
aptcfg->FindB(PACKAGE "::UI::Minibuf-Download-Bar", false))
2980
w = download_list::create(false, !list_update);
2981
main_status_multiplex->add_visible_widget(w, true);
2982
active_status_download=w;
2983
w->destroyed.connect(sigc::ptr_fun(&reset_status_download));
2987
w = download_list::create(true, !list_update);
2988
add_main_widget(w, title, longtitle, tablabel);
2991
m->MediaChange_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
2992
&download_list::MediaChange));
2993
m->IMSHit_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
2994
&download_list::IMSHit));
2996
m->Fetch_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
2997
&download_list::Fetch));
2999
m->Done_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3000
&download_list::Done));
3002
m->Fail_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3003
&download_list::Fail));
3005
m->Pulse_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3006
&download_list::Pulse));
3008
m->Start_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3009
&download_list::Start));
3011
m->Stop_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3012
&download_list::Stop));
3014
m->Complete_sig.connect(sigc::mem_fun(w.unsafe_get_ref(),
3015
&download_list::Complete));
3017
return std::make_pair(m, w);
3020
static void do_prompt_string(const wstring &s,
3022
sigc::slot0<void> realslot)
3024
e.add_to_history(s);
3028
std::pair<download_signal_log *, download_list_ref>
3029
gen_download_progress(bool force_noninvasive,
3031
const string &title,
3032
const string &longtitle,
3033
const string &tablabel)
3035
return gen_download_progress(force_noninvasive,
3037
cw::util::transcode(title),
3038
cw::util::transcode(longtitle),
3039
cw::util::transcode(tablabel));
3042
void prompt_string(const std::wstring &prompt,
3043
const std::wstring &text,
3044
cw::util::slotarg<sigc::slot1<void, wstring> > slot,
3045
cw::util::slotarg<sigc::slot0<void> > cancel_slot,
3046
cw::util::slotarg<sigc::slot1<void, wstring> > changed_slot,
3047
cw::editline::history_list *history)
3049
if(aptcfg->FindB(PACKAGE "::UI::Minibuf-Prompts"))
3051
cw::editline_ref e=cw::editline::create(prompt, text, history);
3052
e->set_allow_wrap(true);
3053
e->set_clear_on_first_edit(true);
3055
e->entered.connect(*slot);
3057
e->entered.connect(sigc::bind(sigc::ptr_fun(do_prompt_string),
3059
sigc::mem_fun(e.unsafe_get_ref(), &cw::widget::destroy)));
3061
e->text_changed.connect(*changed_slot);
3063
e->connect_key("Cancel",
3064
&cw::config::global_bindings,
3065
sigc::mem_fun(e.unsafe_get_ref(), &cw::widget::destroy));
3068
e->connect_key("Cancel",
3069
&cw::config::global_bindings,
3072
main_status_multiplex->add_visible_widget(e, true);
3073
main_table->focus_widget(main_status_multiplex);
3076
main_stacked->add_visible_widget(cw::dialogs::string(prompt, text,
3083
void prompt_string(const std::string &prompt,
3084
const std::string &text,
3085
cw::util::slotarg<sigc::slot1<void, wstring> > slot,
3086
cw::util::slotarg<sigc::slot0<void> > cancel_slot,
3087
cw::util::slotarg<sigc::slot1<void, wstring> > changed_slot,
3088
cw::editline::history_list *history)
3090
prompt_string(cw::util::transcode(prompt), cw::util::transcode(text),
3091
slot, cancel_slot, changed_slot, history);
3094
static void do_prompt_yesno(int cval,
3096
cw::util::slot0arg yesslot,
3097
cw::util::slot0arg noslot)
3118
void prompt_yesno(const std::wstring &prompt,
3120
cw::util::slot0arg yesslot,
3121
cw::util::slot0arg noslot)
3123
if(aptcfg->FindB(PACKAGE "::UI::Minibuf-Prompts"))
3125
string yesstring, nostring;
3127
yesstring+=_("yes_key")[0];
3128
nostring+=_("no_key")[0];
3129
string yesnostring=deflt?yesstring+nostring:nostring+yesstring;
3131
cw::statuschoice_ref c=cw::statuschoice::create(prompt, cw::util::transcode(yesnostring));
3132
c->chosen.connect(sigc::bind(sigc::ptr_fun(&do_prompt_yesno),
3137
main_status_multiplex->add_visible_widget(c, true);
3138
main_table->focus_widget(main_status_multiplex);
3141
main_stacked->add_visible_widget(cw::dialogs::yesno(prompt,
3148
void prompt_yesno_popup(cw::fragment *prompt,
3150
cw::util::slot0arg yesslot,
3151
cw::util::slot0arg noslot)
3153
main_stacked->add_visible_widget(cw::dialogs::yesno(prompt,
3161
void prompt_yesno(const std::string &prompt,
3163
cw::util::slot0arg yesslot,
3164
cw::util::slot0arg noslot)
3166
return prompt_yesno(cw::util::transcode(prompt), deflt, yesslot, noslot);
3169
class self_destructing_layout : public cw::text_layout
3172
self_destructing_layout() : cw::text_layout()
3176
self_destructing_layout(cw::fragment *f) : cw::text_layout(f)
3181
bool handle_key(const cw::config::key &k)
3183
if(!cw::text_layout::focus_me() ||
3184
!cw::text_layout::handle_key(k))
3190
/** \brief Unlike cw::text_layouts, self-destructing widgets
3191
* can always grab the focus.
3198
static cw::util::ref_ptr<self_destructing_layout> create()
3200
cw::util::ref_ptr<self_destructing_layout> rval(new self_destructing_layout());
3205
static cw::util::ref_ptr<self_destructing_layout> create(cw::fragment *f)
3207
cw::util::ref_ptr<self_destructing_layout> rval(new self_destructing_layout(f));
3213
void show_message(cw::fragment *msg,
3214
cw::util::slot0arg okslot,
3215
const cw::style &st)
3218
if(aptcfg->FindB(PACKAGE "::UI::Minibuf-Prompts"))
3220
cw::text_layout_ref l = self_destructing_layout::create(msg);
3221
l->set_bg_style(cw::get_style("Status")+st);
3223
l->destroyed.connect(*okslot);
3225
main_status_multiplex->add_visible_widget(cw::transient::create(l), true);
3226
main_table->focus_widget(main_status_multiplex);
3229
main_stacked->add_visible_widget(cw::dialogs::ok(msg, okslot, st), true);
3232
void show_message(const std::string &msg,
3233
cw::util::slot0arg okslot,
3234
const cw::style &st)
3236
show_message(cw::text_fragment(msg), okslot, st);
3239
void show_message(const std::wstring &msg,
3240
cw::util::slot0arg okslot,
3241
const cw::style &st)
3243
show_message(cw::text_fragment(msg), okslot, st);