picking up branches/tmp/sh/qt4-port/, merging it with trunk
[duncan/yast2-qt4.git] / src / pkg / YQPkgRepoList.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgRepoList.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21
22 #include <algorithm>
23 #include <qdatetime.h>
24
25 #define y2log_component "qt-pkg"
26 #include <ycp/y2log.h>
27 #include <zypp/RepoManager.h>
28
29 #include "YQPkgRepoList.h"
30 #include "YQi18n.h"
31 #include "utf8.h"
32
33 using std::list;
34 using std::set;
35 using std::vector;
36
37
38
39 YQPkgRepoList::YQPkgRepoList( QWidget * parent )
40     : QY2ListView( parent )
41 {
42     y2debug( "Creating repository list" );
43
44     _nameCol    = -1;
45     _urlCol     = -1;
46
47     int numCol = 0;
48
49     // Column headers for repository list
50     addColumn( _( "Name"        ) );    _nameCol        = numCol++;
51     addColumn( _( "URL"         ) );    _urlCol         = numCol++;
52
53     setAllColumnsShowFocus( true );
54     setSelectionMode( Q3ListView::Extended );   // allow multi-selection with Ctrl-mouse
55
56     connect( this,      SIGNAL( selectionChanged() ),
57              this,      SLOT  ( filterIfVisible()) );
58
59     fillList();
60     selectSomething();
61
62     y2debug( "Creating repository list done" );
63 }
64
65
66 YQPkgRepoList::~YQPkgRepoList()
67 {
68     // NOP
69 }
70
71
72 void
73 YQPkgRepoList::fillList()
74 {
75     clear();
76     y2debug( "Filling repository list" );
77
78     for ( ZyppRepositoryIterator it = ZyppRepositoriesBegin();
79           it != ZyppRepositoriesEnd();
80           ++it )
81     {
82         addRepo( *it );
83     }
84
85     y2debug( "Inst repository filled" );
86 }
87
88
89 int
90 YQPkgRepoList::countEnabledRepositories()
91 {
92     return zyppPool().knownRepositoriesSize();
93 }
94
95
96 void
97 YQPkgRepoList::filterIfVisible()
98 {
99     if ( isVisible() )
100         filter();
101 }
102
103
104 void
105 YQPkgRepoList::filter()
106 {
107     emit filterStart();
108
109     y2milestone( "Collecting packages in selected repositories..." );
110     QTime stopWatch;
111     stopWatch.start();
112
113
114     //
115     // Collect all packages on this repository
116     //
117
118     set<ZyppSel> exactMatches;
119     set<ZyppSel> nearMatches;
120
121     Q3ListViewItem * item = firstChild();       // take multi selection into account
122
123     while ( item )
124     {
125         if ( item->isSelected() )
126         {
127             YQPkgRepoListItem * repoItem = dynamic_cast<YQPkgRepoListItem *> (item);
128
129             if ( repoItem )
130             {
131                 ZyppRepo currentRepo = repoItem->zyppRepo();
132
133                 for ( ZyppPoolIterator sel_it = zyppPkgBegin();
134                       sel_it != zyppPkgEnd();
135                       ++sel_it )
136                 {
137                     if ( (*sel_it)->candidateObj() &&
138                          (*sel_it)->candidateObj()->repository() == currentRepo )
139                     {
140                         exactMatches.insert( *sel_it );
141                     }
142                     else
143                     {
144                         zypp::ui::Selectable::available_iterator pkg_it = (*sel_it)->availableBegin();
145
146                         while ( pkg_it != (*sel_it)->availableEnd() )
147                         {
148                             if ( (*pkg_it)->repository() == currentRepo )
149                                 nearMatches.insert( *sel_it );
150
151                             ++pkg_it;
152                         }
153                     }
154                 }
155
156             }
157         }
158
159         item = item->nextSibling();
160     }
161
162
163     //
164     // Send all exact matches to the list
165     // (emit a filterMatch signal for each one)
166     //
167
168     set<ZyppSel>::const_iterator sel_it = exactMatches.begin();
169
170     while ( sel_it != exactMatches.end() )
171     {
172         emit filterMatch( (*sel_it), tryCastToZyppPkg( (*sel_it)->theObj() ) );
173         nearMatches.erase( *sel_it );
174         ++sel_it;
175     }
176
177
178     //
179     // Send all near matches to the list
180     // (emit a filterNearMatch signal for each one)
181     //
182
183     sel_it = nearMatches.begin();
184
185     while ( sel_it != nearMatches.end() )
186     {
187         emit filterNearMatch( *sel_it, tryCastToZyppPkg( (*sel_it)->theObj() ) );
188         ++sel_it;
189     }
190
191     y2debug( "Packages sent to package list. Elapsed time: %f sec", stopWatch.elapsed() / 1000.0 );
192
193     emit filterFinished();
194 }
195
196
197 void
198 YQPkgRepoList::addRepo( ZyppRepo repo )
199 {
200     new YQPkgRepoListItem( this, repo );
201 }
202
203
204 YQPkgRepoListItem *
205 YQPkgRepoList::selection() const
206 {
207     Q3ListViewItem * item = selectedItem();
208
209     if ( ! item )
210         return 0;
211
212     return dynamic_cast<YQPkgRepoListItem *> (item);
213 }
214
215
216
217
218
219
220 YQPkgRepoListItem::YQPkgRepoListItem( YQPkgRepoList *   repoList,
221                                       ZyppRepo          repo    )
222     : QY2ListViewItem( repoList )
223     , _repoList( repoList )
224     , _zyppRepo( repo )
225 {
226     if ( nameCol() >= 0 )
227     {
228         string name = repo.info().name();
229
230 #if SHOW_SINGLE_PRODUCT
231         ZyppProduct product = singleProduct( _zyppRepo );
232
233         if ( product )  // only if the repository provides exactly one product
234         {               // (which is the most common case)
235             name = product->summary();
236         }
237 #endif
238
239         if ( ! name.empty() )
240             setText( nameCol(), fromUTF8( name ));
241     }
242
243     if ( urlCol() >= 0 )
244     {
245         zypp::Url repoUrl;
246         
247         if ( ! repo.info().baseUrlsEmpty() )
248             repoUrl = *repo.info().baseUrlsBegin();
249
250         setText( urlCol(), repoUrl.asString().c_str() );
251     }
252 }
253
254
255
256 YQPkgRepoListItem::~YQPkgRepoListItem()
257 {
258     // NOP
259 }
260
261
262 ZyppProduct
263 YQPkgRepoListItem::singleProduct( ZyppRepo zyppRepo )
264 {
265     ZyppProduct product;
266
267     zypp::ResStore::iterator it = zyppRepo.resolvables().begin();
268
269     //
270     // Find the first product on this repository
271     //
272
273     while ( it != zyppRepo.resolvables().end() && ! product )
274     {
275         product = zypp::dynamic_pointer_cast<zypp::Product>( *it );
276         ++it;
277     }
278
279     //
280     // Check if there is another product on this repository
281     //
282
283     while ( it != zyppRepo.resolvables().end() )
284     {
285         if ( zypp::dynamic_pointer_cast<zypp::Product>( *it ) )
286         {
287             y2milestone( "Multiple products in repository %s",
288                          zyppRepo.info().alias().c_str() );
289             ZyppProduct null;
290             return null;
291         }
292
293         ++it;
294     }
295
296     if ( ! product )
297         y2milestone( "No product in repository %s",
298                      zyppRepo.info().alias().c_str() );
299
300     return product;
301 }
302
303
304
305 #include "YQPkgRepoList.moc"