root/src/apt_options.cc

Revision 1936:ee8248f2fa39, 22.2 kB (checked in by Obey Arthur Liu <arthur@…>, 2 years ago)

Added the ::UI::Flat-View-As-First-View option to display the flat view as first view while keeping the default view settings. English documentation updated.

Line 
1// apt_options.cc
2//
3//   Copyright (C) 2000, 2007-2008 Daniel Burrows
4//
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.
9//
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.
14//
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.
19
20#include "apt_options.h"
21#include "apt_config_treeitems.h"
22#include "apt_config_widgets.h"
23#include "pkg_columnizer.h"
24#include "ui.h"
25
26#include "aptitude.h"
27
28#include <cwidget/fragment.h>
29#include <cwidget/widgets/button.h>
30#include <cwidget/widgets/center.h>
31#include <cwidget/widgets/frame.h>
32#include <cwidget/widgets/label.h>
33#include <cwidget/widgets/scrollbar.h>
34#include <cwidget/widgets/subtree.h>
35#include <cwidget/widgets/table.h>
36#include <cwidget/widgets/text_layout.h>
37
38#include <cwidget/config/keybindings.h>
39#include <cwidget/config/colors.h>
40
41#include <generic/apt/apt.h>
42#include <generic/apt/config_signal.h>
43
44#include <sigc++/adaptors/bind.h>
45#include <sigc++/functors/mem_fun.h>
46
47#include <string>
48#include <vector>
49
50using namespace std;
51
52namespace cw = cwidget;
53namespace cwidget { using namespace widgets; }
54
55namespace aptitude
56{
57  namespace ui
58  {
59    namespace config
60    {
61      namespace
62      {
63struct option_item
64{
65  enum {OPTION_BOOL, OPTION_STRING, OPTION_RADIO, OPTION_END} type;
66  const char *untranslated_description;
67  const char *untranslated_long_description;
68  const char *option_name;
69
70  union
71  {
72    bool b_default;
73    const char *s_default;
74  };
75
76  /** Used by radio options to store the list of valid values for
77   *  the option.
78   */
79  vector<radio_choice> choices;
80
81  option_item()
82    :type(OPTION_END), untranslated_description(NULL), option_name(NULL)
83  {
84  }
85
86  option_item(const char *_untranslated_description,
87              const char *_untranslated_long_description,
88              const char *_option_name, bool def)
89    :type(OPTION_BOOL),
90     untranslated_description(_untranslated_description),
91     untranslated_long_description(_untranslated_long_description),
92     option_name(_option_name),
93     b_default(def)
94  {
95  }
96
97  option_item(const char *_untranslated_description,
98              const char *_untranslated_long_description,
99              const char *_option_name,
100              const char *def)
101    :type(OPTION_STRING),
102     untranslated_description(_untranslated_description),
103     untranslated_long_description(_untranslated_long_description),
104     option_name(_option_name),
105     s_default(def)
106  {
107  }
108
109  /** \brief Construct a radio item from a list of choices,
110   *  destroying each choice after it's inserted into the list.
111   */
112  static option_item radio(const char *untranslated_description,
113                           const char *untranslated_long_description,
114                           const char *option_name,
115                           const char *def,
116                           const radio_choice *choice_1,
117                           ...)
118  {
119    option_item rval;
120
121    va_list args;
122    va_start(args, choice_1);
123
124    rval.type=OPTION_RADIO;
125    rval.untranslated_description = untranslated_description;
126    rval.untranslated_long_description = untranslated_long_description;
127    rval.option_name = option_name;
128    rval.s_default=def;
129
130    rval.choices.push_back(*choice_1);
131    delete choice_1;
132
133    while(1)
134      {
135        radio_choice *choice=va_arg(args, radio_choice *);
136
137        if(choice == NULL)
138          break;
139
140        rval.choices.push_back(*choice);
141        delete choice;
142      }
143
144    va_end(args);
145
146    return rval;
147  }
148};
149
150        radio_choice *choice(const char *value,
151                             const char *untranslated_description,
152                             const char *untranslated_long_description)
153        {
154          return new radio_choice(value,
155                                  untranslated_description,
156                                  untranslated_long_description);
157        }
158
159option_item ui_options[]={
160  option_item(N_("Display some available commands at the top of the screen"),
161              N_("If this option is enabled, a brief summary of some "
162                 "of the most important aptitude commands will appear "
163                 "beneath the menu bar."),
164              PACKAGE "::UI::HelpBar", true),
165  option_item(N_("Hide the menu bar when it is not being used"),
166              N_("If this option is enabled, the menu bar will "
167                 "only appear when it has been activated by pressing "
168                 "the menu key."),
169              PACKAGE "::UI::Menubar-Autohide", false),
170  option_item(N_("Use a minibuffer-style prompt when possible"),
171              N_("If this option is enabled, prompts will be "
172                 "displayed in a single line at the bottom of "
173                 "the screen.  If not, prompts will be displayed "
174                 "as pop-up dialog boxes."),
175              PACKAGE "::UI::Minibuf-Prompts", false),
176  option_item(N_("Show partial search results (incremental search)"),
177              N_("If this option is enabled, aptitude will "
178                 "perform searches within the package list as "
179                 "you type them.  This is convenient, but may "
180                 "slow the program down, particularly on older "
181                 "computers."),
182              PACKAGE "::UI::Incremental-Search", true),
183  option_item(N_("Closing the last view exits the program"),
184              N_("If this option is enabled, aptitude will stop "
185                 "running when all views (package lists, package "
186                 "details, etc) have been closed.  Otherwise, "
187                 "aptitude will continue running until you select "
188                 "'Quit' from the Actions menu."),
189              PACKAGE "::UI::Exit-On-Last-Close", true),
190  option_item(N_("Prompt for confirmation at exit"),
191              N_("If this option is enabled, aptitude will "
192                 "not terminate until you confirm that you "
193                 "really want to quit."),
194              PACKAGE "::UI::Prompt-On-Exit", true),
195  option_item::radio(N_("Pause after downloading files"),
196                     N_("This option controls whether aptitude will wait for confirmation after a download before it goes ahead and installs packages."),
197                     PACKAGE "::UI::Pause-After-Download",
198                     "OnlyIfError",
199                     choice("No", N_("Never"),
200                            N_("Never wait for the user after downloading packages: always begin the installation immediately.")),
201                     choice("OnlyIfError", N_("When an error occurs"),
202                            N_("Wait for confirmation if an error occurred during the download.  If there were no errors, begin installing packages immediately.")),
203                     choice("Yes", N_("Always"),
204                            N_("Always wait for the user to confirm the download before proceeding with the installation.")),
205                     NULL),
206  option_item(N_("Use a 'status-line' download indicator for all downloads"),
207              N_("If this option is enabled, aptitude will display "
208                 "the status of ongoing downloads at the bottom of "
209                 "the screen, rather than opening a new view."),
210              PACKAGE "::UI::Minibuf-Download-Bar", false),
211  option_item(N_("Display the information area by default"),
212              N_("If this option is enabled, the information "
213                 "area (the pane at the bottom of the screen) in the "
214                 "package list will be visible when the program "
215                 "starts; otherwise, it will be initially hidden."),
216              PACKAGE "::UI::Description-Visible-By-Default", true),
217  option_item(N_("Display tabs for the available views"),
218              N_("If this option is enabled, tabs will appear at the top "
219                 "of the screen listing the currently opened views."),
220              PACKAGE "::UI::ViewTabs", true),
221  option_item(N_("Display tabs for the information area"),
222              N_("If this option is enabled, tabs will appear at the top of "
223                 "the information area (the pane at the bottom of the screen) "
224                 "listing the different displays of information that can be "
225                 "viewed there."),
226              PACKAGE "::UI::InfoAreaTabs", false),
227  option_item(N_("Advance to the next item after changing the state of a package"),
228              N_("If this option is enabled, then performing an "
229                 "action on a package (for instance, installing or "
230                 "removing it) will move the selection to the next "
231                 "package in the list."),
232              PACKAGE "::UI::Advance-On-Action", false),
233  option_item(N_("Automatically show why packages are broken"),
234              N_("If this option is enabled, then highlighting a "
235                 "package that has broken dependencies will "
236                 "automatically display the dependencies that "
237                 "are unfulfilled in the lower pane of the "
238                 "display."),
239              PACKAGE "::UI::Auto-Show-Reasons", true),
240  option_item(N_("Display flat view instead of default view on startup"),
241              N_("If this option is enabled, then the first view "
242                 "displayed on startup will be a flat view instead "
243                 "of the default view."),
244              PACKAGE "::UI::Flat-View-As-First-View", false),
245  option_item(N_("The default grouping method for package views"),
246              N_("This option controls how aptitude organizes the "
247                 "package list.  See the aptitude user's manual for "
248                 "information on how to specify a grouping method."),
249              PACKAGE "::UI::Default-Grouping", default_grpstr),
250  option_item(N_("The default display-limit for package views"),
251              N_("By default, the limit of each package view will "
252                 "be set to the value specified by this option.  "
253                 "See the aptitude user's manual for detailed "
254                 "information about searches."),
255              PACKAGE "::Pkg-Display-Limit", ""),
256  option_item(N_("The display format for package views"),
257              N_("This option controls how aptitude formats lines "
258                 "of the package list.  See the aptitude user's "
259                 "manual for information on how to specify a "
260                 "display format."),
261              PACKAGE "::UI::Package-Display-Format",
262              pkg_item::pkg_columnizer::default_pkgdisplay),
263  option_item(N_("The display format for the status line"),
264              N_("This option controls how aptitude formats the "
265                 "status line (the line between the package list "
266                 "and the lower pane).  See the aptitude user's "
267                 "manual for information on how to specify a "
268                 "display format."),
269              PACKAGE "::UI::Package-Status-Format",
270              default_pkgstatusdisplay),
271  option_item(N_("The display format for the header line"),
272              N_("This option controls how aptitude formats the "
273                 "header line (the line above the package list).  "
274                 "See the aptitude user's manual for information on "
275                 "how to specify a display format."),
276              PACKAGE "::UI::Package-Header-Format",
277              default_pkgheaderdisplay),
278  option_item()
279};
280
281option_item misc_options[]={
282  option_item(N_("Automatically upgrade installed packages"),
283              N_("If this option is enabled, then on startup, "
284                 "aptitude will select all upgradable packages for "
285                 "upgrade."),
286              PACKAGE "::Auto-Upgrade", false),
287  option_item(N_("Remove obsolete package files after downloading new package lists"),
288              N_("If this option is enabled, then after every "
289                 "install run, aptitude will delete from the package "
290                 "cache any package files that can no longer be "
291                 "downloaded from any archive in sources.list."),
292              PACKAGE "::AutoClean-After-Update", false),
293  option_item(N_("URL to use to download changelogs"),
294              N_("This option controls the template that's used to "
295                 "download changelogs from the Debian Web site.  You "
296                 "should only need to change this if the changelogs move "
297                 "to a different URL."),
298              PACKAGE "::Changelog-URL-Template",
299              "http://cgi.debian.org/cgi-bin/get-changelog?package=%s"),
300  option_item(N_("Display a preview of what will be done before doing it"),
301              N_("If this option is enabled, then when you ask "
302                 "aptitude to perform an install run, it will "
303                 "first display a summary of the actions it is "
304                 "going to perform."),
305              PACKAGE "::Display-Planned-Action",
306              true),
307  option_item(N_("Forget which packages are \"new\" whenever the package lists are updated"),
308              N_("If this option is enabled, then aptitude will "
309                 "clear the list of new packages after you update "
310                 "the package lists (e.g., by pressing 'u')."),
311              PACKAGE "::Forget-New-On-Update",
312              false),
313  option_item(N_("Forget which packages are \"new\" whenever packages are installed or removed"),
314              N_("If this option is enabled, then aptitude will "
315                 "clear the list of new packages after you perform "
316                 "an install run or install or remove packages from "
317                 "the command-line."),
318              PACKAGE "::Forget-New-On-Install",
319              false),
320  option_item(N_("Do not display a warning when the first change is made in read-only mode"),
321              N_("If this option is %Bnot%b enabled, aptitude will "
322                 "display a warning when you modify the state of a "
323                 "package if you do not have permissions to apply "
324                 "the change to the system."),
325              PACKAGE "::Suppress-Read-Only-Warning",
326              false),
327  option_item(N_("Warn when attempting to perform a privileged action as a non-root user"),
328              N_("If this option is enabled, aptitude will "
329                 "warn you when you attempt to perform an action "
330                 "which you do not have permission to do: for "
331                 "instance, installing packages as a non-root user.  "
332                 "You will be given the option to log in as root "
333                 "and perform the action with root privileges."),
334              PACKAGE "::Warn-Not-Root",
335              true),
336  // TODO: support multiple log destinations.
337  option_item(N_("File to log actions into"),
338              N_("When you install or remove packages, a summary of "
339                 "what aptitude does will be written to this file.  "
340                 "If the first character of the file name is a pipe "
341                 "character ('%B|%b'), the remainder of the name will "
342                 "be interpreted as a shell command that is to "
343                 "receive the log on standard input."),
344              PACKAGE "::Log",
345              "/var/log/aptitude"),
346  option_item()
347};
348
349option_item dependency_options[]={
350  option_item(N_("Automatically resolve dependencies of a package when it is selected"),
351              N_("If this option is enabled, aptitude will "
352                 "use a simple heuristic to immediately resolve "
353                 "the dependencies of each package you flag for "
354                 "installation.  This is much faster than the "
355                 "built-in dependency resolver, but may produce "
356                 "suboptimal results or fail entirely in some "
357                 "scenarios."),
358              PACKAGE "::Auto-Install", true),
359  option_item(N_("Automatically fix broken packages before installing or removing"),
360              N_("If this option is enabled, and you perform an "
361                 "install run while some packages are broken, "
362                 "aptitude will automatically apply the current "
363                 "suggestion of the problem resolver.  Otherwise, "
364                 "aptitude will prompt you for a solution to the "
365                 "broken dependencies."),
366              PACKAGE "::Auto-Fix-Broken", true),
367  option_item(N_("Install recommended packages automatically"),
368              N_("If this option is enabled and \"automatically "
369                 "resolve dependencies\" is also enabled, aptitude "
370                 "will attempt to install the recommendations of "
371                 "newly installed packages in addition to their "
372                 "outright dependencies.  Suggestions will not "
373                 "be automatically installed."
374                 "\n"
375                 "If this option is enabled and \"Remove unused "
376                 "packages automatically\" is enabled, packages "
377                 "that are recommended by an installed package "
378                 "will not be automatically removed."),
379              "Apt::Install-Recommends", true),
380  option_item(N_("Remove unused packages automatically"),
381              N_("If this option is enabled, packages that are "
382                 "automatically installed and that no manually "
383                 "installed package depends on will be removed "
384                 "from the system.  Cancelling the removal will "
385                 "flag the package as manually installed."
386                 "\n"
387                 "If this option is enabled and \"Install recommended "
388                 "packages automatically\" is enabled, "
389                 "automatically installed packages will not be "
390                 "removed if any installed package recommends them."),
391              PACKAGE "::Delete-Unused", true),
392  option_item(N_("Packages that should never be automatically removed"),
393              N_("Packages matching this search pattern will "
394                 "always be treated as if an installed package "
395                 "depends on them: they will never be targeted "
396                 "for removal as unused packages."),
397              PACKAGE "::Keep-Unused-Pattern", ""),
398  option_item(N_("Allow dependency resolutions that break holds or forbids"),
399              N_("If this option is enabled, then whenever aptitude "
400                 "solves a dependency problem, it will consider "
401                 "modifying held packages, or installing forbidden "
402                 "package versions.  With this option disabled, these "
403                 "solutions will be rejected by default."
404                 "\n"
405                 "NOTE: At present, this restriction only applies to situations "
406                 "in which aptitude's dependency resolver (the red bar "
407                 "at the bottom of the screen) is activated.  aptitude "
408                 "will still break holds when automatically installing "
409                 "the dependencies of a package that has just been "
410                 "selected for installation or upgrade, due to apt bug "
411                 "#470035."),
412              PACKAGE "::ProblemResolver::Allow-Break-Holds", false),
413  option_item()
414};
415
416        class dummy_subtree : public cw::subtree<cw::treeitem>
417        {
418          std::wstring text;
419        public:
420          dummy_subtree(const std::wstring &_text)
421            : cw::subtree<cw::treeitem>(true),
422              text(_text)
423          {
424          }
425
426          void paint(cw::tree *win, int y,
427                     bool hierarchical, const cw::style &)
428          {
429            cw::subtree<cw::treeitem>::paint(win, y, hierarchical, text);
430          }
431
432          const wchar_t *tag()
433          {
434            return L"";
435          }
436
437          const wchar_t *label()
438          {
439            return L"";
440          }
441        };
442
443        /** \brief Instantiate a widget for the given option description.
444         *
445         *  Any untranslated strings in the structure are translated
446         *  by calls to gettext().
447         */
448        cw::treeitem *parse_option(const option_item &option)
449        {
450          eassert(option.type != option_item::OPTION_END);
451          switch(option.type)
452            {
453            case option_item::OPTION_BOOL:
454              return make_boolean_item(W_(option.untranslated_description),
455                                       _(option.untranslated_long_description),
456                                       option.option_name,
457                                       option.b_default);
458            case option_item::OPTION_STRING:
459              return make_string_item(W_(option.untranslated_description),
460                                      _(option.untranslated_long_description),
461                                      option.option_name,
462                                      option.s_default);
463            case option_item::OPTION_RADIO:
464              return make_radio_item(W_(option.untranslated_description),
465                                     _(option.untranslated_long_description),
466                                     option.option_name,
467                                     option.choices,
468                                     option.s_default);
469            default:
470              eassert(!"This should never happen.");
471              return NULL;
472            }
473        }
474
475        class apt_options_view : public cw::table
476        {
477          cw::text_layout_ref desc_area;
478          cw::tree_ref tree;
479
480          sigc::connection last_connection;
481
482          void handle_selection_changed(cw::treeitem *selected)
483          {
484            last_connection.disconnect();
485
486            config_treeitem *configitem = dynamic_cast<config_treeitem *>(selected);
487            if(configitem == NULL)
488              desc_area->set_fragment(cw::newline_fragment());
489            else
490              {
491                last_connection = configitem->description_changed.connect(sigc::mem_fun(this, &apt_options_view::handle_description_changed));
492                desc_area->set_fragment(configitem->get_long_description());
493              }
494          }
495
496          void handle_description_changed()
497          {
498            cw::treeiterator selected = tree->get_selection();
499            config_treeitem *configitem;
500
501            if(selected == tree->get_end())
502              configitem = NULL;
503            else
504              configitem = dynamic_cast<config_treeitem *>(&*selected);
505
506            if(configitem == NULL)
507              desc_area->set_fragment(cw::newline_fragment());
508            else
509              desc_area->set_fragment(configitem->get_long_description());
510          }
511
512          void make_children(dummy_subtree *parent, option_item *children)
513          {
514            for(option_item *it = children;
515                it->type != option_item::OPTION_END;
516                ++it)
517              parent->add_child(parse_option(*it));
518          }
519
520          apt_options_view()
521          {
522            dummy_subtree *root = new dummy_subtree(L"");
523
524            dummy_subtree *ui_tree =
525              new dummy_subtree(W_("UI options"));
526            dummy_subtree *dep_tree =
527              new dummy_subtree(W_("Dependency handling"));
528            dummy_subtree *misc_tree =
529              new dummy_subtree(W_("Miscellaneous"));
530
531            root->add_child(ui_tree);
532            root->add_child(dep_tree);
533            root->add_child(misc_tree);
534
535            make_children(ui_tree,   ui_options);
536            make_children(dep_tree,  dependency_options);
537            make_children(misc_tree, misc_options);
538
539            tree = cw::tree::create(root);
540
541            // Use an empty label to produce a "bar" dividing the two
542            // halves of the screen.
543
544            // These declarations are workarounds for strange behavior
545            // in g++ 4.3.
546            std::string empty_label;
547            cw::style status_style(cw::get_style("Status"));
548            cw::label_ref middle_label = cw::label::create(empty_label, status_style);
549            desc_area = cw::text_layout::create();
550
551            cw::scrollbar_ref desc_area_scrollbar = cw::scrollbar::create(cw::scrollbar::VERTICAL);
552
553            tree->selection_changed.connect(sigc::mem_fun(this, &apt_options_view::handle_selection_changed));
554            tree->highlight_current();
555
556            add_widget_opts(tree, 0, 0, 1, 2,
557                            cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK | cw::table::IGNORE_SIZE_REQUEST,
558                            cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK | cw::table::IGNORE_SIZE_REQUEST);
559
560            add_widget_opts(middle_label, 1, 0, 1, 2,
561                            cw::table::ALIGN_CENTER | cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK,
562                            cw::table::ALIGN_CENTER);
563
564            add_widget_opts(desc_area, 2, 0, 1, 1,
565                            cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK | cw::table::IGNORE_SIZE_REQUEST,
566                            cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK | cw::table::IGNORE_SIZE_REQUEST);
567            add_widget_opts(desc_area_scrollbar, 2, 1, 1, 1,
568                            cw::table::FILL | cw::table::SHRINK,
569                            cw::table::EXPAND | cw::table::FILL | cw::table::SHRINK);
570
571            desc_area->location_changed.connect(sigc::mem_fun(*desc_area_scrollbar.unsafe_get_ref(), &cw::scrollbar::set_slider));
572
573            tree->connect_key("DescriptionUp", &cw::config::global_bindings,
574                              sigc::mem_fun(*desc_area.unsafe_get_ref(),
575                                            &cw::text_layout::line_up));
576            tree->connect_key("DescriptionDown", &cw::config::global_bindings,
577                              sigc::mem_fun(*desc_area.unsafe_get_ref(),
578                                            &cw::text_layout::line_down));
579          }
580
581        public:
582          static cw::util::ref_ptr<apt_options_view> create()
583          {
584            return cw::util::ref_ptr<apt_options_view>(new apt_options_view);
585          }
586        };
587        typedef cw::util::ref_ptr<apt_options_view> apt_options_view_ref;
588      }
589
590      cw::widget_ref make_options_tree()
591      {
592        return apt_options_view::create();
593      }
594    }
595  }
596}
Note: See TracBrowser for help on using the browser.