libyui-qt-pkg  2.48.4
YQPkgDescriptionView.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: YQPkgDescriptionView.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 <QFile>
46 #include <QFileInfo>
47 #include <QList>
48 #include <QSettings>
49 #include "zypp/VendorSupportOptions.h"
50 #include "YQPkgDescriptionView.h"
51 #include "YQPkgDescriptionDialog.h"
52 #include "YQi18n.h"
53 #include "utf8.h"
54 #include "YQUI.h"
55 #include <qbuffer.h>
56 
57 #if (QT_VERSION < QT_VERSION_CHECK( 5, 15, 0 ))
58 # define QT_KEEP_EMPTY_PARTS QString::KeepEmptyParts
59 #else
60 # define QT_KEEP_EMPTY_PARTS Qt::KeepEmptyParts
61 #endif
62 
63 #define DESKTOP_TRANSLATIONS "desktop_translations"
64 #define DESKTOPFILEDIR "\\/share\\/applications\\/.*\\.desktop$" // RegExp
65 
66 
67 using std::list;
68 using std::endl;
69 using std::string;
70 using namespace zypp;
71 
72 
73 
74 YQPkgDescriptionView::YQPkgDescriptionView( QWidget * parent, bool showSupportability )
75  : YQPkgGenericDetailsView( parent )
76  , _showSupportability ( showSupportability )
77 {
78  //FIXME setMimeSourceFactory( 0 );
79  initLang();
80 }
81 
82 
84 {
85  // NOP
86 }
87 
88 
89 void
90 YQPkgDescriptionView::showDetails( ZyppSel selectable )
91 {
92  _selectable = selectable;
93 
94  if ( ! selectable )
95  {
96  clear();
97  return;
98  }
99 
100  QString html_text = htmlStart();
101 
102  html_text += htmlHeading( selectable );
103 
104  QString description = fromUTF8( selectable->theObj()->description() );
105 
106  if ( ! description.contains( "<!-- DT:Rich -->" ) )
107  description = simpleHtmlParagraphs( description );
108 
109  html_text += ( "<p>" + description + "</p>");
110 
111  // if the object is a patch, show the problem references too
112  Patch::constPtr patch = asKind<Patch>(selectable->theObj());
113  if ( patch )
114  {
115  html_text += "<p>";
116  html_text += _("References:");
117  html_text += "</p>";
118  html_text += "<ul>";
119 
120  for ( Patch::ReferenceIterator rit = patch->referencesBegin();
121  rit != patch->referencesEnd();
122  ++rit )
123  {
124  html_text += QString( "<li>%1 (%2) : %3</li>" )
125  .arg( rit.id().c_str() )
126  .arg( rit.type().c_str() )
127  .arg( rit.title().c_str() );
128  }
129  html_text += "</ul>";
130  }
131 
132  // if it is a package, show the support information
133  Package::constPtr package = asKind<Package>(selectable->theObj());
134  if ( _showSupportability && package )
135  {
136  html_text += "<p>";
137  // Translators: %1 contains the support level like "Level 3", "unsupported" or "unknown"
138  html_text += _("Supportability: %1").arg( fromUTF8(asUserString(package->vendorSupport()).c_str() ));
139  html_text += "</p>";
140  }
141 
142  // show application names and icons from desktop files if available
143  ZyppPkg installed = tryCastToZyppPkg( selectable->installedObj() );
144  if ( installed )
145  {
146  // ma@: It might be worth passing Package::FileList directly
147  // instead of copying _all_ filenames into a list first.
148  // Package::FileList is a query, so it does not eat much memory.
149  zypp::Package::FileList f( installed->filelist() );
150  std::list<std::string> tmp( f.begin(), f.end() );
151  html_text += applicationIconList( tmp );
152  }
153 
154  html_text += htmlEnd();
155  setHtml( html_text );
156  //FIXME ensureVisible( 0, 0 ); // Otherwise hyperlinks will be centered
157 }
158 
159 
160 
162 {
163  bool foundAuthorsList = false;
164  QString html_text = "<p>";
165 
166  QStringList lines = text.trimmed().split( '\n', QT_KEEP_EMPTY_PARTS );
167  QStringList::const_iterator it = lines.begin();
168 
169  while ( it != lines.end() )
170  {
171  QString line = htmlEscape( *it ).trimmed();
172 
173  if ( line.startsWith("* ") || line.startsWith("- ") || line.startsWith("# ") )
174  {
175  line = "<li>" + line + "</li>";
176  }
177 
178  if ( line.startsWith( "Authors:" ) )
179  {
180  line = "<p><b>" + line + "</b><ul>";
181  foundAuthorsList = true;
182  }
183 
184  if ( foundAuthorsList )
185  {
186  if ( ! line.startsWith( "-----" ) && ! line.isEmpty() )
187  html_text += "<li>" + line + "</li>";
188  }
189  else
190  {
191  if ( line.isEmpty() )
192  html_text += "</p><p>";
193  else
194  html_text += " " + line;
195  }
196 
197 
198 
199 
200  ++it;
201  }
202 
203  if ( foundAuthorsList )
204  html_text += "</ul>";
205 
206  html_text += "</p>";
207 
208  return html_text;
209 }
210 
211 
212 void
214 {
215  if ( url.scheme() == "pkg" )
216  {
217  QString pkgName = url.authority();
218  yuiMilestone() << "Hyperlinking to package \"" << pkgName << "\"" << endl;
220  }
221  else
222  {
223  yuiError() << "Protocol not supported - can't follow hyperlink \""
224  << url.toString() << "\"" << endl;
225  }
226 }
227 
228 
229 void
231 {
232  showLink( url );
233 }
234 
235 
236 QString
237 YQPkgDescriptionView::applicationIconList( const list<string> & fileList ) const
238 {
239  QString html = "";
240  QMap<QString, QString> desktopEntries;
241 
242  QStringList desktopFiles = findDesktopFiles( fileList );
243 
244  if ( desktopFiles.size() == 0 )
245  return QString();
246 
247  // headline for a list of application icons that belong to a selected package
248 
249  for ( int i = 0; i < desktopFiles.size(); ++i )
250  {
251  desktopEntries = readDesktopFile( desktopFiles[i] );
252 
253  QIcon icon = YQUI::ui()->loadIcon( desktopEntries["Icon"].toStdString() );
254 
255  if ( ! icon.isNull() )
256  {
257  QPixmap pixmap = icon.pixmap(32);
258  QByteArray byteArray;
259  QBuffer buffer(&byteArray);
260  pixmap.save(&buffer, "PNG");
261  html += "<tr><td valign='middle' align='center'>";
262  html += QString("<td><img src=\"data:image/png;base64,") + byteArray.toBase64() + QString( "\">" );
263  html += "</td><td valign='middle' align='left'>";
264  html += "<b>" + desktopEntries["Name"] + "</b>";
265  html += "</td></tr>";
266  }
267  }
268 
269  if ( ! html.isEmpty() )
270  {
271  html = _("This package contains: ")
272  + "<table border='0'>"
273  + html
274  + "</table>";
275  }
276 
277  return "<p>" + html + "</p>";
278 }
279 
280 
281 QMap<QString, QString>
282 YQPkgDescriptionView::readDesktopFile( const QString & fileName ) const
283 {
284  QMap<QString, QString> desktopEntries;
285  QString name, genericName;
286 
287  QSettings file( fileName, QSettings::IniFormat );
288  file.setIniCodec( "UTF-8");
289  file.beginGroup( "Desktop Entry" );
290  desktopEntries["Icon"] = file.value( "Icon" ).toString();
291  desktopEntries["Exec"] = file.value( "Exec" ).toString();
292 
293  // translate Name
294  name = file.value( QString( "Name[%1]" ).arg( langWithCountry ) ).toString();
295 
296  if ( name.isEmpty() )
297  name= file.value( QString( "Name[%1]" ).arg( lang ) ).toString() ;
298 
299  if ( name.isEmpty() )
300  {
301  QFileInfo fileInfo (fileName);
302  QString msgid = QString( "Name(%1)" ).arg( fileInfo.fileName() );
303  msgid += ": ";
304  msgid += file.value( QString( "Name" )).toString();
305  name = QString::fromUtf8( dgettext( DESKTOP_TRANSLATIONS, msgid.toLatin1() ) );
306 
307  if ( name == msgid )
308  name = "";
309  }
310  if ( name.isEmpty() )
311  name= file.value( QString( "Name" ) ).toString() ;
312  desktopEntries["Name"] = name;
313 
314  file.endGroup();
315 
316  return desktopEntries;
317 }
318 
319 
320 QStringList
321 YQPkgDescriptionView::findDesktopFiles( const list<string> & fileList ) const
322 {
323  QStringList desktopFiles;
324 
325  for ( list<string>::const_iterator it = fileList.begin();
326  it != fileList.end(); ++it )
327  {
328  QString line = fromUTF8( *it );
329 
330  if ( line.contains( QRegExp( DESKTOPFILEDIR ) ) )
331  desktopFiles << line;
332  }
333 
334  return desktopFiles;
335 }
336 
337 
339 {
340  const char *lang_cstr = getenv( "LANG" );
341 
342  if ( lang_cstr )
343  {
344  langWithCountry = lang_cstr;
345  langWithCountry.replace( QRegExp( "[@\\.].*$" ), "" ); // remove .utf8 / @euro etc.
346 
347  lang = langWithCountry;
348  lang.replace( QRegExp( "_.*$" ), "" ); // remove _DE etc.
349  }
350 }
351 
352 
YQPkgGenericDetailsView::htmlHeading
static QString htmlHeading(ZyppSel selectable, bool showVersion=false)
Returns a uniform heading in HTML format for the specified selectable: name and summary or name,...
Definition: YQPkgGenericDetailsView.cc:157
YQPkgGenericDetailsView::htmlStart
static QString htmlStart()
starts the html tag and set the style
Definition: YQPkgGenericDetailsView.cc:142
YQPkgDescriptionView::setSource
virtual void setSource(const QUrl &name)
Get the document pointed to by a hyperlink.
Definition: YQPkgDescriptionView.cc:230
YQPkgDescriptionView::YQPkgDescriptionView
YQPkgDescriptionView(QWidget *parent, bool showSupportability=true)
Constructor.
Definition: YQPkgDescriptionView.cc:74
YQPkgGenericDetailsView
Abstract base class for details views.
Definition: YQPkgGenericDetailsView.h:59
YQPkgDescriptionView::showLink
void showLink(const QUrl &url)
Show information for a hyperlinked object, e.g., a "pkg:somepkg" link to another package.
Definition: YQPkgDescriptionView.cc:213
YQPkgDescriptionView::readDesktopFile
QMap< QString, QString > readDesktopFile(const QString &fileName) const
Extract name, icon and exec attributes from a desktop file.
Definition: YQPkgDescriptionView.cc:282
YQPkgDescriptionView::applicationIconList
QString applicationIconList(const list< string > &fileList) const
Return html text that contains a list of application icons.
Definition: YQPkgDescriptionView.cc:237
YQPkgDescriptionView::findDesktopFiles
QStringList findDesktopFiles(const list< string > &fileList) const
Search for all desktop files in a file list.
Definition: YQPkgDescriptionView.cc:321
YQPkgGenericDetailsView::htmlEscape
static QString htmlEscape(const QString &plainText)
Escapes characters special to HTML in a ( plain text ) string, such as: '<' -> '<' '>' -> '>' '&' -> ...
Definition: YQPkgGenericDetailsView.cc:192
YQPkgDescriptionView::initLang
void initLang()
Initialize the language code (lang).
Definition: YQPkgDescriptionView.cc:338
YQPkgDescriptionView::simpleHtmlParagraphs
QString simpleHtmlParagraphs(QString text)
Format a multi-line text into paragraphs.
Definition: YQPkgDescriptionView.cc:161
YQPkgDescriptionView::~YQPkgDescriptionView
virtual ~YQPkgDescriptionView()
Destructor.
Definition: YQPkgDescriptionView.cc:83
YQPkgDescriptionDialog::showDescriptionDialog
static void showDescriptionDialog(const QString &pkgName)
Static convenience method: Post a description dialog for pkg 'pkgName'.
Definition: YQPkgDescriptionDialog.cc:193
YQPkgDescriptionView::showDetails
virtual void showDetails(ZyppSel selectable)
Show details for the specified package: In this case the package description.
Definition: YQPkgDescriptionView.cc:90