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