libyui-qt-pkg  2.42.5
 All Classes Functions Variables Enumerations
YQPkgPatternList.cc
1 /**************************************************************************
2 Copyright (C) 2000 - 2010 Novell, Inc.
3 All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (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
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19 **************************************************************************/
20 
21 
22 /*---------------------------------------------------------------------\
23 | |
24 | __ __ ____ _____ ____ |
25 | \ \ / /_ _/ ___|_ _|___ \ |
26 | \ V / _` \___ \ | | __) | |
27 | | | (_| |___) || | / __/ |
28 | |_|\__,_|____/ |_| |_____| |
29 | |
30 | core system |
31 | (C) SuSE GmbH |
32 \----------------------------------------------------------------------/
33 
34  File: YQPkgPatternList.cc
35 
36  Author: Stefan Hundhammer <sh@suse.de>
37 
38  Textdomain "qt-pkg"
39 
40 /-*/
41 
42 #define YUILogComponent "qt-pkg"
43 #include "YUILog.h"
44 #include <QRegExp>
45 #include <zypp/ZYppFactory.h>
46 #include <zypp/Resolver.h>
47 #include <QPainter>
48 #include <QHeaderView>
49 #include <QLabel>
50 #include <QLayout>
51 #include <QItemDelegate>
52 
53 #include "YQi18n.h"
54 #include "utf8.h"
55 #include "YQPackageSelector.h"
56 #include "YQPkgPatternList.h"
57 #include "YQIconPool.h"
58 #include "YQApplication.h"
59 #include "YQUI.h"
60 
61 using std::string;
62 using std::set;
63 
64 class YQPkgPatternItemDelegate : public QItemDelegate
65 {
66  YQPkgPatternList *_view;
67 public:
68  YQPkgPatternItemDelegate( YQPkgPatternList *parent ) : QItemDelegate( parent ), _view( parent ) {
69  }
70 
71  virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
72  {
73  painter->save();
74  //QColor background = option.palette.color(QPalette::Window);
75 
76  YQPkgPatternCategoryItem *citem = dynamic_cast<YQPkgPatternCategoryItem *>(_view->itemFromIndex(index));
77  // special painting for category items
78  if ( citem )
79  {
80  //std::cout << "printing category: " << index.column() << std::endl;
81  QFont f = painter->font();
82  f.setWeight(QFont::Bold);
83  QFontMetrics fm(f);
84  f.setPixelSize( (int) ( fm.height() * 1.1 ) );
85  citem->setFont(_view->summaryCol(), f);
86 
87  painter->fillRect(option.rect, option.palette.color(QPalette::AlternateBase));
88  QItemDelegate::paint(painter, option, index);
89  painter->restore();
90  return;
91  }
92 
93 
94  YQPkgPatternListItem *item = dynamic_cast<YQPkgPatternListItem *>(_view->itemFromIndex(index));
95  if ( item )
96  {
97  //if ( index.column() == _view->howmanyCol() )
98  if ( false )
99  {
100  //std::cout << "printing percentage: " << index.column() << std::endl;
101 
102  QColor background = option.palette.color(QPalette::Window);
103  painter->setBackground( background );
104 
105  float percent = (item->totalPackages() > 0)
106  ? (((float)item->installedPackages()*100) / (float)item->totalPackages())
107  : 0;
108 
109  QColor fillColor = option.palette.color(QPalette::Mid);
110 
111  if ( percent > 100.0 ) percent = 100.0;
112  if ( percent < 0.0 ) percent = 0.0;
113  int x = option.rect.left() + 1;
114  int y = option.rect.top() + 1;
115  int w = option.rect.width() - 2;
116  int h = (int) ( ( (float) option.rect.height() )/2 );
117  int fillWidth = 0;
118  if ( w > 0 )
119  {
120  fillWidth = (int) ( w * percent / 100.0 );
121  //std::cout << "percent: " << percent << " fillw: " << fillWidth << " x: " << x << " y: " << y << "w: " << w << " h: " << h << std::endl;
122 
123  // Fill the desired percentage.
124 
125  painter->fillRect( x, y, fillWidth, h,
126  fillColor );
127 
128  QString percentageText;
129  percentageText.sprintf("%d/%d", item->installedPackages(), item->totalPackages());
130 
131  painter->setPen( _view->palette().color( QPalette::Base ) );
132  painter->drawText( QRect( x, y,
133  w, h ),
134  Qt::AlignHCenter, percentageText );
135  painter->restore();
136  }
137  painter->restore();
138  return;
139 
140  }
141  else
142  {
143  //std::cout << "printing other: " << index.column() << std::endl;
144  painter->restore();
145  QItemDelegate::paint(painter, option, index);
146  }
147 
148  }
149  }
150 };
151 
152 
153 YQPkgPatternList::YQPkgPatternList( QWidget * parent, bool autoFill, bool autoFilter )
154  : YQPkgObjList( parent )
155  , _howmanyCol(0)
156 {
157  yuiDebug() << "Creating pattern list" << std::endl;
158 
159  int numCol = 0;
160  QStringList headers;
161  //headers << "";
162  headers << ""; _statusCol = numCol++;
163 
164  // Translators: "Pattern" refers to so-called "installation patterns",
165  // i.e., specific task-oriented groups of packages, like "everything that
166  // is needed to run a web server". The idea of patterns is that they also
167  // include the configuration workflow needed for that task, such of
168  // configuring the web server. For the scope of the package selector, this
169  // is only of little relevance, though.
170 
171  headers << ""; _iconCol = numCol++;
172  headers << _( "Pattern" ); _summaryCol = numCol++;
173 
174  //headers << ""; _howmanyCol = numCol++;
175 
176  setColumnCount( numCol );
177  setHeaderLabels(headers);
178 
179  setIndentation(0);
180 
181  setItemDelegateForColumn( _iconCol, new YQPkgPatternItemDelegate( this ) );
182  setItemDelegateForColumn( _statusCol, new YQPkgPatternItemDelegate( this ) );
183  setItemDelegateForColumn( _summaryCol, new YQPkgPatternItemDelegate( this ) );
184  //setItemDelegateForColumn( _howmanyCol, new YQPkgPatternItemDelegate(this) );
185 
186  // Can use the same colum for "broken" and "satisfied":
187  // Both states are mutually exclusive
188 
189  _satisfiedIconCol = -42;
190  _brokenIconCol = -42;
191 
192 // header()->setStretchEnabled( _statusCol , false );
193 // header()->setStretchEnabled( _summaryCol, true );
194 
195  setSortingEnabled( true );
196  sortByColumn( summaryCol(), Qt::AscendingOrder );
197 
198  setAllColumnsShowFocus( true );
199 
200  header()->setResizeMode( statusCol(), QHeaderView::Fixed );
201  header()->setResizeMode( summaryCol(), QHeaderView::Stretch );
202  header()->setResizeMode( howmanyCol(), QHeaderView::Fixed );
203 
204  header()->resizeSection( statusCol(), 25 );
205  setColumnWidth( statusCol(), 25 );
206  setColumnWidth( summaryCol(), 100 );
207  setColumnWidth( howmanyCol(), 15 );
208 
209  //header()->resizeSection( 0, 0 );
210 
211  //header()->setMinimumSectionSize( 25 );
212 
213  if ( autoFilter )
214  {
215  connect( this, SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ),
216  this, SLOT ( filter() ) );
217  }
218 
219  setIconSize(QSize(32,32));
220  header()->resizeSection( iconCol(), 34 );
221  //header()->resizeSection( howmanyCol(), 15 );
222 
223  if ( autoFill )
224  {
225  fillList();
226  selectSomething();
227  }
228  yuiDebug() << "Creating pattern list done" << std::endl;
229 }
230 
231 
233 {
234  // NOP
235 }
236 
237 
238 void
240 {
241  _categories.clear();
242 
243  clear();
244  yuiDebug() << "Filling pattern list" << std::endl;
245 
246  for ( ZyppPoolIterator it = zyppPatternsBegin();
247  it != zyppPatternsEnd();
248  ++it )
249  {
250  ZyppPattern zyppPattern = tryCastToZyppPattern( (*it)->theObj() );
251 
252  if ( zyppPattern )
253  {
254  if ( zyppPattern->userVisible() )
255  {
256  addPatternItem( *it, zyppPattern );
257  }
258  else
259  yuiDebug() << "Pattern " << zyppPattern->name()
260  << " is not user-visible" << std::endl;
261  }
262  else
263  {
264  yuiError() << "Found non-Pattern selectable" << std::endl;
265  }
266  }
267 
268  yuiDebug() << "Pattern list filled" << std::endl;
269  resizeColumnToContents(_iconCol);
270  resizeColumnToContents(_statusCol);
271  resizeColumnToContents(_howmanyCol);
272 }
273 
274 
276 YQPkgPatternList::category( const QString & categoryName )
277 {
278  if ( categoryName.isEmpty() )
279  return 0;
280 
281  YQPkgPatternCategoryItem * cat = _categories[ categoryName ];
282 
283  if ( ! cat )
284  {
285  yuiDebug() << "New pattern category \""<< categoryName << "\"" << std::endl;
286 
287  cat = new YQPkgPatternCategoryItem( this, categoryName );
288  Q_CHECK_PTR( cat );
289  _categories.insert( categoryName, cat );
290  }
291 
292  return cat;
293 }
294 
295 
296 
297 void
299 {
300  if ( isVisible() )
301  filter();
302 }
303 
304 
305 void
307 {
308  emit filterStart();
309 
310  if ( selection() ) // The seleted QListViewItem
311  {
312  ZyppPattern zyppPattern = selection()->zyppPattern();
313 
314  if ( zyppPattern )
315  {
316  int total = 0;
317  int installed = 0;
318 
319  zypp::Pattern::Contents c(zyppPattern->contents());
320  for ( zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
321  it != c.selectableEnd();
322  ++it )
323  {
324  ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
325  if ( zyppPkg )
326  {
327  if ( (*it)->installedSize() > 0 )
328  ++installed;
329  ++total;
330 
331  emit filterMatch( *it, zyppPkg );
332  }
333  }
334  selection()->setInstalledPackages(installed);
335  selection()->setTotalPackages(total);
336  selection()->resetToolTip();
337  }
338  }
339 
340  emit filterFinished();
341  resizeColumnToContents(_howmanyCol);
342 }
343 
344 
345 void
347  ZyppPattern zyppPattern )
348 {
349  if ( ! selectable )
350  {
351  yuiError() << "NULL ZyppSelectable!" << std::endl;
352  return;
353  }
354 
355  YQPkgPatternCategoryItem * cat = category( fromUTF8( zyppPattern->category() ) );
356  YQPkgPatternListItem * item = 0;
357 
358  if ( cat )
359  {
360  item = new YQPkgPatternListItem( this, cat, selectable, zyppPattern );
361  }
362  else
363  {
364  item = new YQPkgPatternListItem( this, selectable, zyppPattern );
365  }
366 
367  resizeColumnToContents(_howmanyCol);
368  resizeColumnToContents(_summaryCol);
369 
370  addTopLevelItem(item);
371  applyExcludeRules( item );
372 }
373 
374 
377 {
378  QTreeWidgetItem * item = currentItem();
379 
380  if ( ! item )
381  return 0;
382 
383  return dynamic_cast<YQPkgPatternListItem *> (item);
384 }
385 
386 
387 void
389  QTreeWidgetItem * listViewItem,
390  int col,
391  const QPoint & pos )
392 {
393  YQPkgPatternCategoryItem * categoryItem
394  = dynamic_cast<YQPkgPatternCategoryItem *> (listViewItem);
395 
396  if ( categoryItem )
397  {
398  if ( button == Qt::LeftButton )
399  {
400  if ( col == 0 )
401  {
402  categoryItem->setExpanded( ! categoryItem->isExpanded() );
403  }
404  }
405  }
406  else
407  {
408 
409  YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
410  }
411 }
412 
413 
414 void
416 {
417 #if FIXME
418  QTreeWidgetItemIterator it( this );
419 
420  while ( *it )
421  {
422  QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
423  YQPkgPatternCategoryItem * categoryItem =
424  dynamic_cast<YQPkgPatternCategoryItem *> (*it);
425 
426  if ( item && item->isSelectable() && ! categoryItem )
427  {
428  setSelected( item, true ); // emits signal, too
429  return;
430  }
431 
432  ++it;
433  }
434 #endif
435 }
436 
438  ZyppSel selectable,
439  ZyppPattern zyppPattern )
440  : YQPkgObjListItem( patternList, selectable, zyppPattern )
441  , _patternList( patternList )
442  , _zyppPattern( zyppPattern )
443  , _total(0), _installed(0)
444 {
445  init();
446 }
447 
448 
450  YQPkgPatternCategoryItem * parentCategory,
451  ZyppSel selectable,
452  ZyppPattern zyppPattern )
453  : YQPkgObjListItem( patternList, parentCategory, selectable, zyppPattern )
454  , _patternList( patternList )
455  , _zyppPattern( zyppPattern )
456  , _total(0), _installed(0)
457 {
458  init();
459  parentCategory->addPattern( _zyppPattern );
460 }
461 
462 
463 void
465 {
466  if ( ! _zyppPattern )
467  _zyppPattern = tryCastToZyppPattern( selectable()->theObj() );
468 
469  if (_zyppPattern)
470  {
471  string icon = _zyppPattern->icon().asString();
472  // HACK most patterns have wrong default icon
473  if ( (icon == zypp::Pathname("yast-system").asString()) ||
474  icon.empty() )
475  icon = "pattern-generic";
476 
477  std::string iconpath = YQPackageSelector::iconPath(icon, 32);
478  //std::cout << icon << " | "<< iconpath << std::endl;
479 
480  setIcon(_patternList->iconCol(), QIcon(QString(iconpath.c_str())));
481 
482  }
483 
484  setStatusIcon();
485  resetToolTip();
486  setFirstColumnSpanned ( false );
487 }
488 
489 
490 
492 {
493  // NOP
494 }
495 
496 
497 void
499 {
500  if ( ! _editable || ! _pkgObjList->editable() )
501  return;
502 
503  ZyppStatus oldStatus = status();
504  ZyppStatus newStatus = oldStatus;
505 
506  switch ( oldStatus )
507  {
508  case S_Install:
509  newStatus = S_NoInst;
510  break;
511 
512 // see: bnc 476965
513 // case S_KeepInstalled:
514 // newStatus = S_Install;
515 // break;
516 
517  case S_NoInst:
518  newStatus = S_Install;
519  break;
520 
521  case S_AutoInstall:
522  newStatus = S_NoInst;
523  break;
524 
525  default:
526  break;
527  }
528 
529  if ( oldStatus != newStatus )
530  {
531  setStatus( newStatus );
532 
533  if ( showLicenseAgreement() )
534  {
535  showNotifyTexts( newStatus );
536  }
537  else // License not confirmed?
538  {
539  // Status is now S_Taboo or S_Del - update status icon
540  setStatusIcon();
541  }
542 
543  _patternList->sendStatusChanged();
544  }
545 }
546 
547 
548 void
550 {
551  std::string infoToolTip;
552  infoToolTip += ("<p>" + zyppPattern()->description() + "</p>");
553 
554  if ( totalPackages() > 0 )
555  {
556  infoToolTip += ("<p>" + zypp::str::form("%d / %d", installedPackages(), totalPackages() ) + "</p>");
557  }
558 
559  setToolTip(_patternList->summaryCol(), fromUTF8(infoToolTip));
560 }
561 
562 void
564 {
566 }
567 
568 
569 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
570 {
571  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
572 
573  //std::cout << _zyppPattern->order()<< " | " << otherPatternListitem->zyppPattern()->order() << std::endl;
574 
575 
576  if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
577  {
578  if ( _zyppPattern->order() != otherPatternListitem->zyppPattern()->order() )
579  return _zyppPattern->order() < otherPatternListitem->zyppPattern()->order();
580  else
581  return _zyppPattern->name() < otherPatternListitem->zyppPattern()->name();
582  }
583 
584  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
585 
586  if ( otherCategoryItem ) // Patterns without category should always be sorted
587  return true; // before any category
588 
589  return QTreeWidgetItem::operator<( otherListViewItem );
590 }
591 
593  const QString & category )
594  : QY2ListViewItem( patternList )
595  , _patternList( patternList )
596 {
597  setText( _patternList->summaryCol(), category );
598 
599  setExpanded( true );
600  setTreeIcon();
601 }
602 
603 
605 {
606  // NOP
607 }
608 
609 void
611 {
612  if ( ! _firstPattern )
613  {
614  _firstPattern = pattern;
615  }
616  else
617  {
618  if ( _firstPattern->order().compare( pattern->order() ) < 0 )
619  _firstPattern = pattern;
620  }
621 }
622 
623 
624 void
625 YQPkgPatternCategoryItem::setExpanded( bool open )
626 {
627  QTreeWidgetItem::setExpanded( open );
628  setTreeIcon();
629 }
630 
631 
632 void
634 {
635  setIcon( 0,
636  isExpanded() ?
637  YQIconPool::treeMinus() :
638  YQIconPool::treePlus() );
639 
640 }
641 
642 
643 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
644 {
645  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
646 
647  if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
648  return _firstPattern->order() < otherCategoryItem->firstPattern()->order();
649 
650 
651  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
652 
653  if ( otherPatternListitem ) // Patterns without category should always be sorted
654  return false; // before any category
655 
656  return QTreeWidgetItem::operator<( otherListViewItem );
657 }
658 
659 
660 
661 #include "YQPkgPatternList.moc"