📄 newstuff.cpp.svn-base
字号:
/*************************************************************************** * Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/// qt/kde includes#include <qfile.h>#include <qwidget.h>#include <qtimer.h>#include <qlayout.h>#include <khbox.h>#include <kvbox.h>#include <qpixmap.h>#include <qfont.h>#include <qlabel.h>#include <qlineedit.h>#include <qcombobox.h>#include <qrect.h>#include <qpainter.h>#include <qapplication.h>#include <ktoolinvocation.h>#include <kglobalsettings.h>#include <klocale.h>#include <kconfig.h>#include <kpushbutton.h>#include <kstandarddirs.h>#include <kstdguiitem.h>#include <kmessagebox.h>#include <kdebug.h>#include <kiconloader.h>#include <khtml_part.h>#include <kio/job.h>#include <kio/netaccess.h>#include <knewstuff/provider.h>#include <knewstuff/entry.h>// local includes#include "newstuff.h"// define the providers.xml location#define PROVIDERS_URL "http://kpdf.kde.org/newstuff/providers.xml"// define the type of the stuff returned by providers (unused)#define RES_TYPE "kpdf/stuff"/* How the whole thing works: - phase 1: fetch the ProvidersList from the PROVIDERS_URL - phase 2: every Provider in it contains some AvailableItem(s) - phase 3: every AvailableItem can be downloaded (aka installed) or deleted*//** GUI: Internal Widget that displays a ver-stretchable (only) image */class ExtendImageWidget : public QWidget{ public: ExtendImageWidget( const QPixmap & pix, QWidget * parent ) : QWidget( parent ), m_pixmap( pix ) { // adjust size hint setFixedWidth( pix.width() ); setMinimumHeight( pix.height() ); // paint all own pixels setAttribute( Qt::WA_OpaquePaintEvent, true ); // create the tile image from last line of pixmap m_tile = QPixmap( pix.width(), 1 ); QPainter p(&m_tile); p.drawPixmap(0, 0, pix, 0,pix.height()-2, pix.width(),1 ); } // internal paint function void paintEvent( QPaintEvent * e ) { // extend the bottom line of the image when painting QRegion paintRegion = e->region(); QRect pixmapRect = e->rect().intersect( m_pixmap.rect() ); // paint the pixmap rect QPainter p( this ); p.drawPixmap( pixmapRect.topLeft(), m_pixmap, pixmapRect ); // paint the tiled bottom part QVector<QRect> rects = paintRegion.subtract( pixmapRect ).rects(); for ( int i = 0; i < rects.count(); i++ ) { const QRect & tileRect = rects[ i ]; p.drawTiledPixmap( tileRect, m_tile, QPoint(tileRect.left(), 0) ); } } private: QPixmap m_pixmap; QPixmap m_tile;};/** CORE: extend KNS::Entry adding convenience methods */class AvailableItem : public Entry{ public: typedef QList< AvailableItem * > List; enum State { Normal = 0, Installing = 1, Uninstalling = 2 }; AvailableItem( const QDomElement & element ) : Entry( element ), m_state( Normal ), m_progress( 0 ) { QString remoteUrl = payload().url(); QString fileName = remoteUrl.section( '/', -1, -1 ); QString extension = fileName.toLower().section( '.', -1, -1 ); QString typeString = category(); // place books on the desktop if ( typeString == "kpdf/book" ) m_destinationFile = KGlobalSettings::desktopPath() + '/' + fileName; // place kpdf data on the local share/apps/kpdf/stuff else if ( typeString == "kpdf/tool" ) m_destinationFile = KStandardDirs::locateLocal( "data", "okular/stuff/" + fileName ); // warn about unrecognized type else kDebug() << "NewStuffDialog: AvailableItem: unrecognized provider name: '" << typeString << "'." << endl; } // returns the source url QString url() const { return payload().url(); } // returns local destination path for the item const QString & destinationPath() { return m_destinationFile; } // checks if the item is already installed bool installed() { return QFile::exists( m_destinationFile ); } // state void setState( State s ) { m_state = s; } State state() { return m_state; } // progress (state dependant) void setProgress( float p ) { m_progress = p; } float progress() { return m_progress; } private: QString m_destinationFile; State m_state; float m_progress;};/** GUI/CORE: HTML Widget to operate on AvailableItem::List */class ItemsView : public KHTMLPart{ public: ItemsView( NewStuffDialog * newStuffDialog, QWidget * parentWidget ) : KHTMLPart( parentWidget ), m_newStuffDialog( newStuffDialog ), m_sorting( 0 ) { // customize functionality setJScriptEnabled( true ); setJavaEnabled( false ); setMetaRefreshEnabled( false ); setPluginsEnabled( false ); setStandardFont( QApplication::font().family() ); // 100% is too large! less is better setZoomFactor( 70 ); } ~ItemsView() { clear(); } void setItems( const AvailableItem::List & itemList ) { clear(); m_items = itemList; buildContents(); } void setSorting( int sortType ) { m_sorting = sortType; buildContents(); } void updateItem( AvailableItem * item ) { // get item id string and iformations QString idString = QString::number( (unsigned long)item ); AvailableItem::State state = item->state(); bool showProgress = state != AvailableItem::Normal; int pixelProgress = showProgress ? (int)(item->progress() * 80.0) : 0; // perform internal scripting operations over the element executeScript( "document.getElementById('" + idString + "').style.color='red'" ); executeScript( "document.getElementById('bar" + idString + "').style.width='" + QString::number( pixelProgress ) + "px'" ); executeScript( "document.getElementById('bc" + idString + "').style.backgroundColor='" + (showProgress ? "gray" : "transparent") + '\'' ); executeScript( "document.getElementById('btn" + idString + "').value='" + (item->installed() ? i18n( "Uninstall" ) : i18n( "Install" )) + '\'' ); } private: // generate the HTML contents to be displayed by the class itself void buildContents() { // try to get information in current locale QString preferredLanguage = KGlobal::locale()->language(); begin(); setTheAaronnesqueStyle(); // write the html header and contents manipulation scripts write( "<html><body>" ); write( "<div style='font-size:2em; border-bottom: 1px solid blue; background-color: #808080;'>Updated</div>" ); AvailableItem::List::iterator it = m_items.begin(), iEnd = m_items.end(); for ( ; it != iEnd; ++it ) { AvailableItem * item = *it; // precalc the image string QString imageString = item->preview( preferredLanguage ).url(); if ( imageString.length() > 1 ) imageString = "<div class='leftImage'><img src='" + imageString + "' border='0'></div>"; // precalc the title string QString titleString = item->name(); if ( item->version().length() > 0 ) titleString += " v." + item->version(); // precalc button's text QString buttonText = item->installed() ? i18n( "Uninstall" ) : i18n( "Install" ); // precalc item's dynamic strings QString idString = QString::number( (unsigned long)item ); QString clickString = "window.location.href=\"item:" + idString + "\";"; // precalc the string for displaying stars (normal+grayed) int starPixels = 11 + 11 * (item->rating() / 10); QString starsString = "<div class='star' style='width: " + QString::number( starPixels ) + "px;'></div>"; int grayPixels = 22 + 22 * (item->rating() / 20); starsString = "<div class='starbg' style='width: " + QString::number( grayPixels ) + "px;'>" + starsString + "</div>"; // precalc the string for displaying author (parsing email) QString authorString = item->author(); QString emailString = authorString.section( '(', 1, 1 ); if ( emailString.contains( '@' ) && emailString.contains( ')' ) ) { emailString = emailString.remove( ')' ).trimmed(); authorString = authorString.section( '(', 0, 0 ).trimmed(); authorString = "<a href='mailto:" + emailString + "'>" + authorString + "</a>"; } // write the HTML code for the current item write( QString( "<table class='itemBox' id='" + idString + "'><tr>" "<td class='leftColumn'>" // image + imageString + // progress bar (initially transparent) "<div class='leftProgressContainer' id='bc" + idString + "'>" "<div id='bar" + idString + "' class='leftProgressBar'></div>" "</div>" // button "<div class='leftButton'>" "<input type='button' id='btn" + idString + "' onClick='" + clickString + "' value='" + buttonText + "'>" "</div>" "</td>" "<td class='contentsColumn'>" // contents header: item name/score "<table class='contentsHeader' cellspacing='2' cellpadding='0'><tr>" "<td>" + titleString + "</td>" "<td align='right'>" + starsString + "</td>" "</tr></table>" // contents body: item description "<div class='contentsBody'>" + item->summary( preferredLanguage ) + "</div>" // contents footer: author's name/date "<div class='contentsFooter'>" "<em>" + authorString + "</em>, " + KGlobal::locale()->formatDate( item->releaseDate(), true ) + "</div>" "</td>" "</tr></table>" ) ); } write( "</body></html>" ); end(); } // this is the stylesheet we use void setTheAaronnesqueStyle() { QString hoverColor = "#000000"; //QApplication::palette().active().highlightedText().name(); QString hoverBackground = "#f8f8f8"; //QApplication::palette().active().highlight().name(); QString starIconPath = KStandardDirs::locate( "data", "okular/pics/ghns_star.png" ); QString starBgIconPath = KStandardDirs::locate( "data", "okular/pics/ghns_star_gray.png" ); // default elements style QString style; style += "body { background-color: white; color: black; padding: 0; margin: 0; }"; style += "table, td, th { padding: 0; margin: 0; text-align: left; }"; style += "input { color: #000080; font-size:120%; }"; // the main item container (custom element) style += ".itemBox { background-color: white; color: black; width: 100%; border-bottom: 1px solid gray; margin: 0px 0px; }"; style += ".itemBox:hover { background-color: " + hoverBackground + "; color: " + hoverColor + "; }"; // style of the item elements (4 cells with multiple containers) style += ".leftColumn { width: 100px; height:100%; text-align: center; }"; style += ".leftImage {}"; style += ".leftButton {}";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -