summaryrefslogtreecommitdiff
path: root/src/gtk/packagestab.h
blob: ab9984e0d00595f1a79d69ae89b5af7c2716d775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// -*-c++-*-

// packagestab.h
//
//  Copyright 1999-2009 Daniel Burrows
//  Copyright 2008-2009 Obey Arthur Liu
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; see the file COPYING.  If not, write to
//  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
//  Boston, MA 02111-1307, USA.

#ifndef PACKAGESTAB_H_
#define PACKAGESTAB_H_

#undef OK
#include <gtkmm.h>

#include <apt-pkg/pkgcache.h>

#include <gtk/tab.h>

#include <cwidget/generic/util/ref_ptr.h>

#include <generic/apt/matching/pattern.h>
#include <generic/util/refcounted_base.h>

namespace gui
{
  class PkgView;
  class Entity;

  /** \brief A class that handles managing a collection of widgets
   *  where package searches are entered.
   *
   *  This sets up signals to provide user feedback about search
   *  syntax, and to perform a search when the user finishes entering
   *  it.  It isn't a GTK+ container to provide more flexibility to
   *  client code: the widgets can be arranged whatever way is
   *  convenient.
   */
  class PackageSearchEntry : public aptitude::util::refcounted_base_threadsafe
  {
    Gtk::Entry *search_entry;
    Gtk::Label *error_label;
    Gtk::Button *find_button;
    Gtk::ToggleButton *incremental_toggle_button;

    Glib::ustring last_delayed_search_term;

    // Parse the current entry and emit the activated() signal if it's
    // valid (otherwise show the error).
    void do_search();

    // Will compare the current search term with the stored value and fire if unchanged,
    // but will not fire if same as last_delayed_search_term.
    // This is used to trigger a search, say, 200ms in the future if the search term
    // hasn't changed since but has since the last delayed search.
    bool do_delayed_search(Glib::ustring search_term);

    // Affect the search button according to the incremental toggle button:
    // if toggled, then disable manual search.
    void toggled_incremental();

    // Invoked when the search entry's text changes.
    void search_entry_changed();

    PackageSearchEntry(Gtk::Entry *_search_entry,
		       Gtk::Label *_error_label,
                       Gtk::Button *_find_button,
                       Gtk::ToggleButton *_incremental_toggle_button);

  public:
    /** \brief Create a new PackageSearchEntry.
     *
     *  \param search_entry               The text entry to manage.
     *  \param error_label                The label in which to display error messages.
     *  \param find_button                A button that the user can use to perform a search.
     *  \param incremental_toggle_button  A togglebutton to toggle incremental search.
     *
     *  \return A reference-counting wrapper around the new package
     *  search entry.
     */
    static cwidget::util::ref_ptr<PackageSearchEntry>
    create(Gtk::Entry *search_entry,
	   Gtk::Label *error_label,
	   Gtk::Button *find_button,
           Gtk::ToggleButton *incremental_toggle_button = NULL)
    {
      return new PackageSearchEntry(search_entry, error_label, find_button, incremental_toggle_button);
    }

    Glib::ustring get_text() const
    {
      return search_entry->get_text();
    }

    /** \brief Set the text of the entry and act as if the user had
     *	pressed Enter.
     */
    void set_text(const Glib::ustring &text);

    /** \brief A signal emitted when the user searches for a package. */
    sigc::signal<void, cwidget::util::ref_ptr<aptitude::matching::pattern> > activated;
  };

  /** \brief A searchable list of packages. */
  class PackageSearchList : public aptitude::util::refcounted_base_threadsafe
  {
    /** \brief The columns used in the filter combobox. */
    class filter_combobox_columns : public Gtk::TreeModel::ColumnRecord
    {
    public:
      Gtk::TreeModelColumn<Glib::ustring> name;
      Gtk::TreeModelColumn<cwidget::util::ref_ptr<aptitude::matching::pattern> > pattern;

      filter_combobox_columns();
    };

    // The last search that was successfully entered into the search
    // entry.  This is combined with the filter to produce the actual
    // search.
    cwidget::util::ref_ptr<aptitude::matching::pattern> current_search;

    // The search-entry aggregate associated with this view.
    cwidget::util::ref_ptr<PackageSearchEntry> search_entry;

    // The drop-down menu used to pick a filter.
    Gtk::ComboBox *filter_combobox;

    filter_combobox_columns filter_columns;

    // The actual package list that we encapsulate.
    cwidget::util::ref_ptr<PkgView> package_list;

    // A hook invoked whenever the model is rebuilt for whatever
    // reason.
    sigc::slot<void> after_repopulate_hook;

    // Builds the search list from the current selections.
    void repopulate();

    // Invoked when the user edits the pattern in the search entry.
    void do_search_entry_activated(const cwidget::util::ref_ptr<aptitude::matching::pattern> &p);

    // Used to test whether a row in the filter combobox is a
    // separator.
    bool filter_row_is_separator(const Glib::RefPtr<Gtk::TreeModel> &model,
				 const Gtk::TreeModel::iterator &iterator);

    PackageSearchList(const cwidget::util::ref_ptr<PackageSearchEntry> &_search_entry,
		      Gtk::ComboBox *_filter_combobox,
		      const cwidget::util::ref_ptr<PkgView> &_package_list,
		      const sigc::slot<void> &_after_repopulate_hook);
  public:
    /** \brief Create a new PackageSearchlist.
     *
     *  \param search_entry       The search-entry-widget aggregate
     *                            used to enter searches for this package list.
     *  \param filter_combobox    The drop-down box for picking
     *                            a filter for the package list.
     *  \param package_list       The package list managed by the new
     *                            object.
     *  \param after_repopulate_hook   A slot to invoke every time the
     *                                 list is rebuilt.
     */
    static cwidget::util::ref_ptr<PackageSearchList>
    create(const cwidget::util::ref_ptr<PackageSearchEntry> &search_entry,
						     Gtk::ComboBox *filter_combobox,
						     const cwidget::util::ref_ptr<PkgView> &package_list,
						     const sigc::slot<void> &after_repopulate_hook)
    {
      return new PackageSearchList(search_entry,
				   filter_combobox,
				   package_list,
				   after_repopulate_hook);
    }

    const cwidget::util::ref_ptr<PackageSearchEntry> &get_search_entry() const
    {
      return search_entry;
    }

    const cwidget::util::ref_ptr<PkgView> &get_package_list() const
    {
      return package_list;
    }
  };

  class PackagesTab : public Tab
  {
    private:
      cwidget::util::ref_ptr<PackageSearchList> pSearchList;
      Gtk::TextView * pPackagesTextView;

      void after_repopulate_model();
    public:
      PackagesTab(const Glib::ustring &label);
      void activated_package_handler();
      void display_desc(const cwidget::util::ref_ptr<Entity> &ent);
      const cwidget::util::ref_ptr<PackageSearchList> &get_search_list() const { return pSearchList; }

      std::set<PackagesAction> get_package_menu_actions();
      void dispatch_package_menu_action(PackagesAction action);
      bool get_undo_available();
      void dispatch_undo();
      void set_limit(const std::string &limit);

      bool get_edit_columns_available();
      void dispatch_edit_columns();
  };
}


#endif /* PACKAGESTAB_H_ */