libyui-qt-pkg  2.42.5
 All Classes Functions Variables Enumerations
YQPkgVersionsView.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: YQPkgVersionsView.cc
35 
36  Author: Stefan Hundhammer <sh@suse.de>
37 
38  Textdomain "qt-pkg"
39 
40 /-*/
41 
42 #define YUILogComponent "qt-pkg"
43 
44 #include <YQZypp.h>
45 #include <zypp/Repository.h>
46 #include "YUILog.h"
47 #include <QTabWidget>
48 #include <QRegExp>
49 #include <QHeaderView>
50 #include <QStylePainter>
51 #include <QStyleOptionButton>
52 #include <QApplication>
53 
54 
55 #include "YQPkgVersionsView.h"
56 #include "YQPkgRepoList.h"
57 #include "YQIconPool.h"
58 #include "YQi18n.h"
59 #include "utf8.h"
60 
61 #define ICONOFFSET 3 // the status icons have an asymmetrical transparent border
62 
63 using std::endl;
64 
65 YQPkgVersionsView::YQPkgVersionsView( QWidget * parent, bool userCanSwitch )
66  : QScrollArea( parent )
67  , _content(0)
68  , _layout(0)
69 {
70  _selectable = 0;
71  _parentTab = dynamic_cast<QTabWidget *> (parent);
72  _userCanSwitch = userCanSwitch;
73 
74  _buttons = new QButtonGroup(this);
75 
76  if ( _parentTab )
77  {
78  connect( parent, SIGNAL( currentChanged(QWidget *) ),
79  this, SLOT ( reload (QWidget *) ) );
80  }
81 }
82 
83 
85 {
86  // NOP
87 }
88 
89 
90 void
91 YQPkgVersionsView::reload( QWidget * newCurrent )
92 {
93  if ( newCurrent == this )
94  showDetailsIfVisible( _selectable );
95 }
96 
97 
98 void
99 YQPkgVersionsView::slotRefreshDetails( )
100 {
101  emit multiversionSelectionChanged( );
102 }
103 
104 
105 void
107 {
108  _selectable = selectable;
109 
110  yuiMilestone() << "showDetailsIfVis" << endl;
111 
112  if ( _parentTab ) // Is this view embedded into a tab widget?
113  {
114  if ( _parentTab->currentWidget() == this ) // Is this page the topmost?
115  showDetails( selectable );
116  }
117  else // No tab parent - simply show data unconditionally.
118  {
119  showDetails( selectable );
120  }
121 }
122 
123 
124 void
125 YQPkgVersionsView::showDetails( ZyppSel selectable )
126 {
127  yuiMilestone() << "showDetails" << endl;
128 
129  _selectable = selectable;
130 
131  if ( ! selectable )
132  {
133  // Delete all installed items
134  qDeleteAll( _installed );
135  _installed.clear();
136 
137  _content = new QWidget( this );
138  setWidget( _content );
139  _content->show();
140  return;
141  }
142 
143  // old widget is autodestroyed by setWidget later
144  _content = new QWidget( this );
145  _layout = new QVBoxLayout( _content );
146  _content->setLayout( _layout );
147 
148  // also paint the scrollarea background
149  setPalette( QApplication::palette().color( QPalette::Active, QPalette::Base ) );
150  setAutoFillBackground( true );
151 
152  _content->setPalette( QApplication::palette().color( QPalette::Active, QPalette::Base ) );
153  _content->setAutoFillBackground( true );
154 
155  QLabel * pkgNameLabel = new QLabel( this );
156 
157  if ( ! selectable->theObj() )
158  return;
159 
160  _layout->addWidget( pkgNameLabel );
161 
162  QFont font = pkgNameLabel->font();
163  font.setBold( true );
164 
165  QFontMetrics fm( font) ;
166  font.setPixelSize( (int) ( fm.height() * 1.1 ) );
167 
168  pkgNameLabel->setFont( font );
169  pkgNameLabel->setText( fromUTF8(selectable->theObj()->name().c_str()) );
170 
171  // New scope
172  {
173  QListIterator<QAbstractButton*> it( _buttons->buttons() );
174 
175  while ( it.hasNext() )
176  {
177  delete it.next();
178  }
179  }
180 
181  // Delete all installed items
182  qDeleteAll( _installed );
183  _installed.clear();
184 
185  if ( selectable->multiversionInstall() )
186  {
187  //
188  // Find installed and available objects ( for multiversion view )
189  //
190  {
191  zypp::ui::Selectable::picklist_iterator it = selectable->picklistBegin();
192 
193 
194  while ( it != selectable->picklistEnd() )
195  {
196  YQPkgMultiVersion * version = new YQPkgMultiVersion( this, selectable, *it, _userCanSwitch );
197 
198  _installed.push_back( version );
199  _layout->addWidget( version );
200 
201  connect (version, SIGNAL(statusChanged()), this, SLOT(slotRefreshDetails()));
202  connect (this, SIGNAL(multiversionSelectionChanged()), version, SLOT(update()));
203 
204  ++it;
205  }
206  }
207  }
208  else
209  {
210  //
211  // Fill installed objects
212  //
213  {
214  zypp::ui::Selectable::installed_iterator it = selectable->installedBegin();
215 
216  while ( it != selectable->installedEnd() )
217  {
218  QString text = _( "%1-%2 from vendor %3 (installed)" )
219  .arg( fromUTF8( (*it)->edition().asString().c_str() ) )
220  .arg( fromUTF8( (*it)->arch().asString().c_str() ) )
221  .arg( fromUTF8( (*it)->vendor().c_str() ) ) ;
222 
223  QWidget * installedVersion = new QWidget( this );
224  QHBoxLayout * instLayout = new QHBoxLayout( installedVersion );
225  instLayout->setContentsMargins( 0, 0, 0, 0 );
226 
227  QLabel * icon = new QLabel( installedVersion );
228  icon->setPixmap( YQIconPool::pkgSatisfied() );
229  instLayout->addWidget( icon );
230 
231  QLabel * textLabel = new QLabel( text, installedVersion );
232  instLayout->addWidget( textLabel );
233  instLayout->addStretch();
234 
235  _installed.push_back( installedVersion );
236  _layout->addWidget( installedVersion );
237 
238  ++it;
239  }
240  }
241 
242 
243  //
244  // Fill available objects
245  //
246 
247  {
248  zypp::ui::Selectable::available_iterator it = selectable->availableBegin();
249 
250  while ( it != selectable->availableEnd() )
251  {
252  QRadioButton *radioButton = new YQPkgVersion( this, selectable, *it, _userCanSwitch );
253  connect( radioButton, SIGNAL( clicked( bool ) ), SLOT( checkForChangedCandidate() ) );
254 
255  _buttons->addButton( radioButton );
256  _layout->addWidget( radioButton );
257 
258 
259  if ( selectable->hasCandidateObj() &&
260  selectable->candidateObj()->edition() == (*it)->edition() &&
261  selectable->candidateObj()->arch() == (*it)->arch() )
262  {
263  radioButton->setChecked(true);
264  }
265 
266  ++it;
267  }
268  }
269  }
270 
271  _layout->addStretch();
272  setWidget( _content );
273  _content->show();
274 }
275 
276 
277 void
279 {
280  QListIterator<QAbstractButton*> it( _buttons->buttons() );
281 
282  while ( it.hasNext() )
283  {
284  YQPkgVersion * versionItem = dynamic_cast<YQPkgVersion *> (it.next());
285 
286  if ( versionItem && versionItem->isChecked() )
287  {
288  ZyppObj newCandidate = versionItem->zyppObj();
289 
290  if ( _selectable && newCandidate != _selectable->candidateObj() )
291  {
292  yuiMilestone() << "Candidate changed" << endl;
293 
294  // Change status of selectable
295 
296  ZyppStatus status = _selectable->status();
297 
298  if ( !_selectable->installedEmpty() &&
299  _selectable->installedObj()->arch() == newCandidate->arch() &&
300  _selectable->installedObj()->edition() == newCandidate->edition() )
301  {
302  // Switch back to the original instance -
303  // the version that was previously installed
304  status = S_KeepInstalled;
305  }
306  else
307  {
308  switch ( status )
309  {
310  case S_KeepInstalled:
311  case S_Protected:
312  case S_AutoDel:
313  case S_AutoUpdate:
314  case S_Del:
315  case S_Update:
316 
317  status = S_Update;
318  break;
319 
320  case S_NoInst:
321  case S_Taboo:
322  case S_Install:
323  case S_AutoInstall:
324  status = S_Install;
325  break;
326  }
327  }
328 
329  _selectable->setStatus( status );
330 
331 
332  // Set candidate
333 
334  _selectable->setCandidate( newCandidate );
335  emit candidateChanged( newCandidate );
336  return;
337  }
338  }
339 
340  }
341 }
342 
343 
344 QSize
346 {
347  return QSize( 0, 0 );
348 }
349 
350 
351 
352 
353 
354 
355 YQPkgVersion::YQPkgVersion( QWidget * parent,
356  ZyppSel selectable,
357  ZyppObj zyppObj,
358  bool enabled )
359  : QRadioButton( parent )
360  , _selectable( selectable )
361  , _zyppObj( zyppObj )
362 {
363  // Translators: %1 is a package version, %2 the package architecture,
364  // %3 describes the repository where it comes from,
365  // %4 is the repository's priority
366  // %5 is the vendor of the package
367  // Examples:
368  // 2.5.23-i568 from Packman with priority 100 and vendor openSUSE
369  // 3.17.4-i386 from openSUSE-11.1 update repository with priority 20 and vendor openSUSE
370  // ^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^
371  // %1 %2 %3 %4 %5
372  setText( _( "%1-%2 from %3 with priority %4 and vendor %5" )
373  .arg( fromUTF8( zyppObj->edition().asString().c_str() ) )
374  .arg( fromUTF8( zyppObj->arch().asString().c_str() ) )
375  .arg( fromUTF8( zyppObj->repository().info().name().c_str() ) )
376  .arg( zyppObj->repository().info().priority() )
377  .arg( fromUTF8( zyppObj->vendor().c_str() ) ) );
378 }
379 
380 
382 {
383  // NOP
384 }
385 
386 
387 QString
389 {
390  QString tip;
391 
392  if ( zyppObj() == selectable()->installedObj() )
393  tip = _( "This version is installed in your system." );
394 
395  return tip;
396 }
397 
398 
399 
400 
402  ZyppSel selectable,
403  ZyppPoolItem zyppPoolItem,
404  bool enabled )
405  : QCheckBox( parent )
406  , _selectable( selectable )
407  , _zyppPoolItem( zyppPoolItem )
408 {
409  setText (_( "%1-%2 from %3 with priority %4 and vendor %5" )
410  .arg( fromUTF8( zyppPoolItem->edition().asString().c_str() ) )
411  .arg( fromUTF8( zyppPoolItem->arch().asString().c_str() ) )
412  .arg( fromUTF8( zyppPoolItem->repository().info().name().c_str() ) )
413  .arg( zyppPoolItem->repository().info().priority() )
414  .arg( fromUTF8( zyppPoolItem->vendor().c_str() ) ));
415 
416 
417  connect( this, SIGNAL (toggled(bool)), this, SLOT( slotIconClicked()));
418 }
419 
420 
422 {
423  // NOP
424 }
425 
426 
427 void YQPkgMultiVersion::slotIconClicked()
428 {
429  // prevent checkmark, we draw the status icons ourselves
430  bool oldBlock = blockSignals( true );
431  setChecked( false );
432  blockSignals( oldBlock );
433  cycleStatus();
434 }
435 
436 
438 {
439 
440  ZyppStatus oldStatus = _selectable->pickStatus( _zyppPoolItem );
441  ZyppStatus newStatus = oldStatus;
442 
443  switch ( oldStatus )
444  {
445  case S_Install:
446  newStatus = S_NoInst;
447  break;
448 
449  case S_Protected:
450  newStatus = _selectable->identicalAvailable( _zyppPoolItem ) ?
451  S_KeepInstalled: S_NoInst;
452  break;
453 
454  case S_Taboo:
455  newStatus = _selectable->identicalInstalled( _zyppPoolItem ) ?
456  S_KeepInstalled : S_NoInst;
457  break;
458 
459  case S_KeepInstalled:
460  newStatus = _selectable->identicalAvailable( _zyppPoolItem ) ?
461  S_Update : S_Del;
462  break;
463 
464  case S_Update:
465  newStatus = S_Del;
466  break;
467 
468  case S_AutoUpdate:
469  newStatus = S_KeepInstalled;
470  break;
471 
472  case S_Del:
473  case S_AutoDel:
474  newStatus = S_KeepInstalled;
475  break;
476 
477  case S_NoInst:
478  if ( _selectable->identicalAvailable( _zyppPoolItem ) )
479  {
480  newStatus = S_Install;
481  }
482  else
483  {
484  yuiWarning() << "No candidate for " << _selectable->theObj()->name() << endl;
485  newStatus = S_NoInst;
486  }
487  break;
488 
489  case S_AutoInstall:
490  // this used to be taboo before, but now ZYpp supports
491  // saving weak locks (unselected packages)
492  newStatus = S_NoInst;
493  break;
494  }
495 
496 
497  setStatus( newStatus );
498  yuiMilestone() << "oldStatus:" << oldStatus << endl;
499  yuiMilestone() << "newStatus:" << newStatus << endl;
500 
501 }
502 
503 
504 void YQPkgMultiVersion::setStatus( ZyppStatus newStatus )
505 {
506  _selectable->setPickStatus( _zyppPoolItem, newStatus );
507 
508  emit statusChanged();
509  update();
510 }
511 
512 
513 void YQPkgMultiVersion::paintEvent(QPaintEvent *)
514 {
515  // draw the usual checkbox
516  QStylePainter p(this);
517  QStyleOptionButton opt;
518  initStyleOption(&opt);
519  p.drawControl(QStyle::CE_CheckBox, opt);
520 
521 
522  // calculate position and draw the status icon
523  QRect elementRect = style()->subElementRect ( QStyle::SE_CheckBoxIndicator, &opt);
524  QPixmap icon = statusIcon( _selectable->pickStatus(_zyppPoolItem) );
525 
526  QPoint start = elementRect.center() - icon.rect().center();
527  QRect rect = QRect(start.x() - ICONOFFSET, start.y(), icon.width(), icon.height());
528 
529  p.drawItemPixmap( rect, 0, icon );
530 }
531 
532 
533 QPixmap YQPkgMultiVersion::statusIcon( ZyppStatus status )
534 {
535  QPixmap icon = YQIconPool::pkgNoInst();
536 
537  switch ( status )
538  {
539  case S_Del: icon = YQIconPool::pkgDel(); break;
540  case S_Install: icon = YQIconPool::pkgInstall(); break;
541  case S_KeepInstalled: icon = YQIconPool::pkgKeepInstalled(); break;
542  case S_NoInst: icon = QPixmap(); break;
543  case S_Protected: icon = YQIconPool::pkgProtected(); break;
544  case S_Taboo: icon = YQIconPool::pkgTaboo(); break;
545  case S_Update: icon = YQIconPool::pkgUpdate(); break;
546 
547  case S_AutoDel: icon = YQIconPool::pkgAutoDel(); break;
548  case S_AutoInstall: icon = YQIconPool::pkgAutoInstall(); break;
549  case S_AutoUpdate: icon = YQIconPool::pkgAutoUpdate(); break;
550 
551  // Intentionally omitting 'default' branch so the compiler can
552  // catch unhandled enum states
553  }
554  return icon;
555 }
556 
557 
558 
559 #include "YQPkgVersionsView.moc"