diff --git a/Makefile.am b/Makefile.am index e34b72df2..a66a8244f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,8 @@ libkpdfpart_la_SOURCES = dcop.skel error.cpp part.cpp libkpdfpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) libkpdfpart_la_LIBADD = xpdf/xpdf/libxpdf.la conf/libkpdfconf.la core/libkpdfcore.la \ ui/libkpdfui.la ui/painter_agg2/libagg2.la $(LIB_KPARTS) \ - $(LIB_KFILE) $(LIB_KDEPRINT) $(LIB_KUTILS) -lm + $(LIB_KFILE) $(LIB_KDEPRINT) $(LIB_KUTILS) $(LIB_KNEWSTUFF) \ + $(LIB_KHTML) -lm partdesktopdir = $(kde_servicesdir) partdesktop_DATA = kpdf_part.desktop diff --git a/part.cpp b/part.cpp index daa9f61ce..949b83d29 100644 --- a/part.cpp +++ b/part.cpp @@ -61,6 +61,7 @@ #include "ui/thumbnaillist.h" #include "ui/side_reviews.h" #include "ui/minibar.h" +#include "ui/newstuff.h" #include "ui/propertiesdialog.h" #include "ui/presentationwidget.h" #include "conf/preferencesdialog.h" @@ -232,12 +233,15 @@ Part::Part(QWidget *parentWidget, const char *widgetName, m_printPreview = KStdAction::printPreview( this, SLOT( slotPrintPreview() ), ac ); m_printPreview->setEnabled( false ); - m_showLeftPanel = new KToggleAction( i18n( "Show &left panel"), "show_side_panel", 0, this, SLOT( slotShowLeftPanel() ), ac, "show_leftpanel" ); + m_showLeftPanel = new KToggleAction( i18n( "Show &left panel"), "show_side_panel", 0, this, SLOT( slotShowLeftPanel() ), ac, "show_leftpanel" ); m_showLeftPanel->setShortcut( "CTRL+L" ); m_showLeftPanel->setCheckedState( i18n("Hide &left panel") ); m_showLeftPanel->setChecked( Settings::showLeftPanel() ); slotShowLeftPanel(); + KAction * ghns = new KAction(i18n("&Get new stuff"), "knewstuff", 0, this, SLOT(slotGetNewStuff()), ac, "get_new_stuff"); + ghns->setShortcut( "G" ); // TEMP, REMOVE ME! + m_showProperties = new KAction(i18n("&Properties"), "info", 0, this, SLOT(slotShowProperties()), ac, "properties"); m_showProperties->setEnabled( false ); @@ -565,6 +569,14 @@ void Part::slotSaveFileAs() } } +void Part::slotGetNewStuff() +{ + // show the modal dialog over pageview and execute it + NewStuffDialog * dialog = new NewStuffDialog( m_pageView ); + dialog->exec(); + delete dialog; +} + void Part::slotPreferences() { // an instance the dialog could be already created and could be cached, diff --git a/part.h b/part.h index da4adfa59..85b8ea9f8 100644 --- a/part.h +++ b/part.h @@ -96,6 +96,7 @@ protected slots: void slotFind(); void slotFindNext(); void slotSaveFileAs(); + void slotGetNewStuff(); void slotPreferences(); void slotNewConfig(); void slotPrintPreview(); diff --git a/part.rc b/part.rc index 2db92ac0f..95733bbfa 100644 --- a/part.rc +++ b/part.rc @@ -6,6 +6,8 @@ + + &Edit diff --git a/ui/Makefile.am b/ui/Makefile.am index 2a2e9a899..e0072343e 100644 --- a/ui/Makefile.am +++ b/ui/Makefile.am @@ -8,7 +8,7 @@ noinst_LTLIBRARIES = libkpdfui.la libkpdfui_la_SOURCES = pagepainter.cpp pageview.cpp pageviewutils.cpp \ pageviewannotator.cpp minibar.cpp thumbnaillist.cpp \ searchwidget.cpp toc.cpp propertiesdialog.cpp \ - presentationwidget.cpp side_reviews.cpp + presentationwidget.cpp side_reviews.cpp newstuff.cpp pageview.lo: ../conf/settings.h pageviewutils.lo: ../conf/settings.h diff --git a/ui/data/Makefile.am b/ui/data/Makefile.am index 07da4a779..cd4d4b03a 100644 --- a/ui/data/Makefile.am +++ b/ui/data/Makefile.am @@ -10,6 +10,10 @@ annpics_DATA = checkmark.png circle.png comment.png cross.png help.png \ rightarrow.png rightpointer.png star.png uparrow.png \ upleftarrow.png +# install misc images +miscpicsdir = $(kde_datadir)/kpdf/pics +miscpics_DATA = ghns.png ghns_star.png ghns_star_gray.png + # install annotator xml tools description xmldir = $(kde_datadir)/kpdf xml_DATA = tools.xml diff --git a/ui/data/ghns.png b/ui/data/ghns.png new file mode 100644 index 000000000..16b98e137 Binary files /dev/null and b/ui/data/ghns.png differ diff --git a/ui/data/ghns_star.png b/ui/data/ghns_star.png new file mode 100644 index 000000000..4bb01cd4e Binary files /dev/null and b/ui/data/ghns_star.png differ diff --git a/ui/data/ghns_star_gray.png b/ui/data/ghns_star_gray.png new file mode 100644 index 000000000..698d93e48 Binary files /dev/null and b/ui/data/ghns_star_gray.png differ diff --git a/ui/data/sources/ghns.svg b/ui/data/sources/ghns.svg new file mode 100644 index 000000000..d611f6b39 --- /dev/null +++ b/ui/data/sources/ghns.svg @@ -0,0 +1,3106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + New + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + New + Get + Get + Exciting + Exciting + Stuff + Stuff + + + + + + + + + + + + + + + diff --git a/ui/newstuff.cpp b/ui/newstuff.cpp new file mode 100644 index 000000000..8f122d519 --- /dev/null +++ b/ui/newstuff.cpp @@ -0,0 +1,686 @@ +/*************************************************************************** + * Copyright (C) 2005 by Enrico Ros * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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" + +/** GUI: Internal Widget that displays a ver-stretchable (only) image */ +class ExtendImageWidget : public QWidget +{ + public: + ExtendImageWidget( const QPixmap & pix, QWidget * parent ) + : QWidget( parent, "", WNoAutoErase ), m_pixmap( pix ) + { + // adjust size hint + setFixedWidth( pix.width() ); + setMinimumHeight( pix.height() ); + // paint all own pixels + setBackgroundMode( Qt::NoBackground ); + // create the tile image from last line of pixmap + m_tile.resize( pix.width(), 1 ); + copyBlt( &m_tile, 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 + QMemArray rects = paintRegion.subtract( pixmapRect ).rects(); + for ( unsigned 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 QValueList< AvailableItem * > List; + AvailableItem( const QDomElement & element, const QString & providerName ) + : Entry( element ) + { + QString remoteUrl = payload().url(); + QString fileName = remoteUrl.section( '/', -1, -1 ); + QString extension = fileName.lower().section( '.', -1, -1 ); + // place books on the desktop + if ( providerName.lower().contains( "book" ) ) + m_destinationFile = KGlobalSettings::desktopPath() + "/" + fileName; + // place kpdf data on the local share/apps/kpdf/stuff + else if ( providerName.lower().contains( "kpdf" ) ) + m_destinationFile = locateLocal( "data", "kpdf/stuff/" + fileName ); + // warn about unrecognized provider + else + kdDebug() << "NewStuffDialog: AvailableItem: unrecognized provider name." << endl; + } + + // 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 ); + } + + private: + QString m_destinationFile; +}; + + +/** GUI/CORE: HTML Widget to operate on AvailableItem::List */ +class ItemsView : public KHTMLPart +{ + public: + ItemsView( QWidget * parent ) + : KHTMLPart( parent, "newStuffHTMLView" ), 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(); + } + + private: + // generate the HTML contents to be displayed by the class itself + void buildContents() + { + // try to get informations in current locale + QString preferredLanguage = KGlobal::locale()->language(); + + // write the html code to be rendered + begin(); + setTheAaronnesqueStyle(); + write( "" ); + + 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 = "

"; + + // precalc the title string + QString titleString = item->name(); + if ( item->version().length() > 0 ) + titleString += " v." + item->version(); + + // precalc the string for displaying stars (normal+grayed) + int starPixels = 11 + 11 * (item->rating() / 10); + QString starsString = "
"; + int grayPixels = 22 + 22 * (item->rating() / 20); + starsString = "
" + starsString + "
"; + + // 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( ')' ).stripWhiteSpace(); + authorString = authorString.section( '(', 0, 0 ).stripWhiteSpace(); + authorString = "" + authorString + ""; + } + + // write the HTML code for the current item + write( QString( + "" + "" + "" + "
" + // image + + imageString + + // button + "
" + "" + "
" + "
" + // contents header: item name/score + "" + "" + "" + "
" + titleString + "" + starsString + "
" + // contents body: item description + "
" + + item->summary( preferredLanguage ) + + "
" + // contents footer: author's name/date + "
" + "" + authorString + ", " + + KGlobal::locale()->formatDate( item->releaseDate(), true ) + + "
" + "
" ) + ); + } + + write( "" ); + 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 = locate( "data", "kpdf/pics/ghns_star.png" ); + QString starBgIconPath = locate( "data", "kpdf/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 {}"; + style += ".contentsColumn { vertical-align: top; }"; + style += ".contentsHeader { width: 100%; font-size: 120%; font-weight: bold; border-bottom: 1px solid #c8c8c8; }"; + style += ".contentsBody {}"; + style += ".contentsFooter {}"; + style += ".star { width: 0px; height: 24px; background-image: url(" + starIconPath + "); background-repeat: repeat-x; }"; + style += ".starbg { width: 110px; height: 24px; background-image: url(" + starBgIconPath + "); background-repeat: repeat-x; }"; + setUserStyleSheet( style ); + } + + // handle clicks on page links/buttons + void urlSelected( const QString & link, int, int, const QString &, KParts::URLArgs ) + { + KURL url( link ); + QString urlProtocol = url.protocol(); + QString urlPath = url.path(); + + if ( urlProtocol == "mailto" ) + { + // clicked over a mail address + kapp->invokeMailer( url ); + } + else if ( urlProtocol == "item" ) + { + // clicked over an item + bool ok; + unsigned long itemPointer = urlPath.toULong( &ok ); + if ( !ok ) + { + kdWarning() << "ItemsView: error converting item pointer." << endl; + return; + } + // I love to cast pointers + AvailableItem * item = (AvailableItem *)itemPointer; + if ( !m_items.contains( item ) ) + { + kdWarning() << "ItemsView: error retrieving item pointer." << endl; + return; + } + // perform operations on the AvailableItem (maybe already installed) + bool itemInstalled = item->installed(); + kdDebug() << itemInstalled << endl; + } + } + + // delete all the classes we own + void clear() + { + // delete all items and empty local list + AvailableItem::List::iterator it = m_items.begin(), iEnd = m_items.end(); + for ( ; it != iEnd; ++it ) + delete *it; + m_items.clear(); + } + + private: + AvailableItem::List m_items; + int m_sorting; +}; + + +/** CORE/GUI: The main dialog that performs GHNS low level operations **/ +/* internal storage structures to be used by NewStuffDialog */ +struct ProviderJobInfo +{ + const Provider * provider; + QString receivedData; +}; +struct NewStuffDialogPrivate +{ + // network classes for providers/items/files + ProviderLoader * providerLoader; + Provider::List * providersList; + QMap< KIO::Job *, ProviderJobInfo > providerJobs; + QMap< KIO::Job *, QString > transferJobs; + + // gui related vars + QWidget * parentWidget; + QLineEdit * searchLine; + QComboBox * typeCombo; + QComboBox * sortCombo; + ItemsView * itemsView; + QLabel * messageLabel; + + // other classes + QTimer * messageTimer; + QTimer * networkTimer; +}; + +NewStuffDialog::NewStuffDialog( QWidget * parentWidget ) + : QDialog( parentWidget, "kpdfNewStuff" ), d( new NewStuffDialogPrivate ) +{ + // initialize the private classes + d->providerLoader = 0; + d->providersList = 0; + d->parentWidget = parentWidget; + + d->messageTimer = new QTimer( this ); + connect( d->messageTimer, SIGNAL( timeout() ), + this, SLOT( slotResetMessageColors() ) ); + + d->networkTimer = new QTimer( this ); + connect( d->networkTimer, SIGNAL( timeout() ), + this, SLOT( slotNetworkTimeout() ) ); + + // popuplate dialog with stuff + QBoxLayout * horLay = new QHBoxLayout( this, 11 ); + + // create left picture widget (if picture found) + QPixmap p( locate( "data", "kpdf/pics/ghns.png" ) ); + if ( !p.isNull() ) + horLay->addWidget( new ExtendImageWidget( p, this ) ); + + // create right 'main' widget + QVBox * rightLayouter = new QVBox( this ); + rightLayouter->setSpacing( 6 ); + horLay->addWidget( rightLayouter ); + + // create upper label + QLabel * mainLabel = new QLabel( i18n("All you ever wanted, in a click!"), rightLayouter); + QFont mainFont = mainLabel->font(); + mainFont.setBold( true ); + mainLabel->setFont( mainFont ); + + // create the control panel + QFrame * panelFrame = new QFrame( rightLayouter ); + panelFrame->setFrameStyle( QFrame::StyledPanel | QFrame::Raised ); + QGridLayout * panelLayout = new QGridLayout( panelFrame, 2, 4, 11, 6 ); + // add widgets to the control panel + QLabel * label1 = new QLabel( i18n("Show:"), panelFrame ); + panelLayout->addWidget( label1, 0, 0 ); + d->typeCombo = new QComboBox( false, panelFrame ); + panelLayout->addWidget( d->typeCombo, 0, 1 ); + d->typeCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ); + d->typeCombo->setMinimumWidth( 150 ); + d->typeCombo->setEnabled( false ); + connect( d->typeCombo, SIGNAL( activated(int) ), + this, SLOT( slotLoadProvider(int) ) ); + + QLabel * label2 = new QLabel( i18n("Order by:"), panelFrame ); + panelLayout->addWidget( label2, 0, 2 ); + d->sortCombo = new QComboBox( false, panelFrame ); + panelLayout->addWidget( d->sortCombo, 0, 3 ); + d->sortCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ); + d->sortCombo->setMinimumWidth( 100 ); + d->sortCombo->setEnabled( false ); + connect( d->sortCombo, SIGNAL( activated(int) ), + this, SLOT( slotSortingSelected(int) ) ); + + QLabel * label3 = new QLabel( i18n("Search:"), panelFrame ); + panelLayout->addWidget( label3, 1, 0 ); + d->searchLine = new QLineEdit( panelFrame ); + panelLayout->addMultiCellWidget( d->searchLine, 1, 1, 1, 3 ); + d->searchLine->setEnabled( false ); + + // create the ItemsView used to display available items + d->itemsView = new ItemsView( rightLayouter ); + + // create bottom buttons + QHBox * bottomLine = new QHBox( rightLayouter ); + // create info label + d->messageLabel = new QLabel( bottomLine ); + d->messageLabel->setFrameStyle( QFrame::StyledPanel | QFrame::Raised ); + d->messageLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); + // close button + QPushButton * closeButton = new QPushButton( i18n("Close"), bottomLine ); + //closeButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) + connect( closeButton, SIGNAL( clicked() ), this, SLOT( accept() ) ); + + // start with a nice size + resize( 700, 400 ); + slotResetMessageColors(); + + // start loading providers list + QTimer::singleShot( 100, this, SLOT( slotLoadProviders() ) ); +} + +NewStuffDialog::~NewStuffDialog() +{ + delete d->providerLoader; + delete d; +} + +void NewStuffDialog::displayMessage( const QString & msg, MessageType type, int timeOutMs ) +{ + // stop the pending timer if present + if ( d->messageTimer ) + d->messageTimer->stop(); + + // set background color based on message type + switch ( type ) + { + case Info: + d->messageLabel->setPaletteForegroundColor( palette().active().highlightedText() ); + d->messageLabel->setPaletteBackgroundColor( palette().active().highlight() ); + break; + case Error: + d->messageLabel->setPaletteForegroundColor( Qt::white ); + d->messageLabel->setPaletteBackgroundColor( Qt::red ); + break; + default: + slotResetMessageColors(); + break; + } + + // set text to messageLabel + d->messageLabel->setText( msg ); + + // single shot the resetColors timer (and create it if null) + d->messageTimer->start( timeOutMs, true ); +} + + +void NewStuffDialog::slotResetMessageColors() // SLOT +{ + d->messageLabel->setPaletteForegroundColor( palette().active().text() ); + d->messageLabel->setPaletteBackgroundColor( palette().active().background() ); +} + +void NewStuffDialog::slotNetworkTimeout() // SLOT +{ + displayMessage( i18n("Timeout. Check internet connection!"), Error ); +} + +void NewStuffDialog::slotSortingSelected( int sortType ) // SLOT +{ + d->itemsView->setSorting( sortType ); +} + + +//BEGIN Providers Loading +void NewStuffDialog::slotLoadProviders() +{ + // create the helpful loader class (may be done internally in future) + if ( !d->providerLoader ) + { + d->providerLoader = new ProviderLoader( d->parentWidget ); + connect( d->providerLoader, SIGNAL( providersLoaded( Provider::List* ) ), + this, SLOT( slotProvidersLoaded( Provider::List* ) ) ); + } + + // start loading + d->providersList = 0; + d->providerLoader->load( RES_TYPE, PROVIDERS_URL ); + + // start the 'network watchdog timer' + d->networkTimer->start( 20*1000, true /*single shot*/ ); + + // inform the user + displayMessage( i18n("Loading providers list...") ); +} + +void NewStuffDialog::slotProvidersLoaded( Provider::List * list ) +{ + // stop network watchdog + d->networkTimer->stop(); + + // safety check + d->providersList = list; + if ( !list || !list->count() ) + { + displayMessage( i18n("Problems loading providers. Please retry later."), Error ); + return; + } + + // update and PopUp the providers ComboBox + d->typeCombo->clear(); + int providersNumber = list->count(); + for ( int i = 0; i < providersNumber; i++ ) + { + const Provider * provider = list->at( i ); + // provider icon: using local KIconLoader, not loading from remote url + QPixmap icon = DesktopIcon( provider->icon().url(), 16 ); + QString name = provider->name(); + // insert provider in combo + d->typeCombo->insertItem( icon, name ); + } + + // inform the user + displayMessage( i18n("Loaded %1 providers").arg( providersNumber ), Info ); + + // automatically load the first provider + d->typeCombo->setEnabled( true ); + d->typeCombo->setCurrentItem( 0 ); + QTimer::singleShot( 500, this, SLOT( slotLoadProvider() ) ); +} +//END Providers Loading + +//BEGIN AvailableItem(s) Loading +void NewStuffDialog::slotLoadProvider( int pNumber ) +{ + // safety check + if ( !d->providersList || !d->typeCombo->isEnabled() || + pNumber < 0 || pNumber >= (int)d->providersList->count() ) + { + displayMessage( i18n("Error with this provider"), Error ); + return; + } + + // create a job that will feed provider data + const Provider * provider = d->providersList->at( pNumber ); + KIO::TransferJob * job = KIO::get( provider->downloadUrl(), false /*refetch*/, false /*progress*/ ); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), + this, SLOT( slotProviderInfoData( KIO::Job *, const QByteArray & ) ) ); + connect( job, SIGNAL( result( KIO::Job * ) ), + this, SLOT( slotProviderInfoResult( KIO::Job * ) ) ); + + // create a job description and data holder + ProviderJobInfo info; + info.provider = provider; + d->providerJobs[ job ] = info; + + // inform the user + displayMessage( i18n("Loading %1...").arg( provider->name() ) ); + + // start the 'network watchdog timer' + d->networkTimer->start( 30*1000, true /*single shot*/ ); + + // block any possible recourring calls while we're running + d->typeCombo->setEnabled( false ); +} + +void NewStuffDialog::slotProviderInfoData( KIO::Job * job, const QByteArray & data ) +{ + // safety check + if ( data.isEmpty() || !d->providerJobs.contains( job ) ) + return; + + // append the data buffer to the 'receivedData' string + QCString str( data, data.size() + 1 ); + d->providerJobs[ job ].receivedData.append( QString::fromUtf8( str ) ); +} + +void NewStuffDialog::slotProviderInfoResult( KIO::Job * job ) +{ + // stop network watchdog + d->networkTimer->stop(); + + // enable gui controls + d->typeCombo->setEnabled( true ); + d->sortCombo->setEnabled( true ); + + // safety check + if ( job->error() || !d->providerJobs.contains( job ) || + d->providerJobs[ job ].receivedData.isEmpty() || + d->providerJobs[ job ].receivedData.contains("404 Not Found") ) + { + displayMessage( i18n("Error loading provider description!"), Error ); + return; + } + + // build XML DOM from the received data + QDomDocument doc; + bool docOk = doc.setContent( d->providerJobs[ job ].receivedData ); + QString providerName = d->providerJobs[ job ].provider->name(); + d->providerJobs.remove( job ); + if ( !docOk ) + { + displayMessage( i18n("Problems parsing provider description."), Info ); + return; + } + + // create AvailableItem(s) based on the knewstuff.dtd + AvailableItem::List itemList; + QDomNode stuffNode = doc.documentElement().firstChild(); + while ( !stuffNode.isNull() ) + { + QDomElement elem = stuffNode.toElement(); + stuffNode = stuffNode.nextSibling(); + // WARNING: disabled the stuff type checking (use only in kate afaik) + if ( elem.tagName() == "stuff" /*&& elem.attribute( "type", RES_TYPE ) == RES_TYPE*/ ) + itemList.append( new AvailableItem( elem, providerName ) ); + } + + // update the control widget and inform user about the current operation + d->itemsView->setItems( itemList ); + if ( itemList.count() ) + displayMessage( i18n("You have %1 resources available.").arg( itemList.count() ) ); + else + displayMessage( i18n("No resources available on this provider." ) ); +} +//END AvailableItem(s) loading + +/* UNCOMPRESS (specify uncompression method) +KTar tar( fileName, "application/x-gzip" ); +tar.open( IO_ReadOnly ); +const KArchiveDirectory *dir = tar.directory(); +dir->copyTo( "somedir" ); +tar.close(); +QFile::remove( fileName ); +*/ + +/* EXECUTE (specify the 'cmd' command) +QStringList list = QStringList::split( " ", cmd ), + list2; +for ( QStringList::iterator it = list.begin(); it != list.end(); it++ ) + list2 << (*it).replace("%f", fileName); +KProcess proc; +proc << list2; +proc.start( KProcess::Block ); +*/ + +/* callbacks +emit something(); +*/ + +/* +QString target = item ? item->fullName() : "/"; +QString path = "/tmp"; //locateLocal( resourceString.utf8(), target) +QString file = path + "/" + target; + +if ( KStandardDirs::exists( file ) ) + if ( KMessageBox::questionYesNo( d->parentWidget, + i18n("The file '%1' already exists. Do you want to override it?") + .arg( file ), + QString::null, i18n("Overwrite") ) == KMessageBox::No ) + return QString(); +*/ + +//END of the NewStuffDialog + +#include "newstuff.moc" diff --git a/ui/newstuff.h b/ui/newstuff.h new file mode 100644 index 000000000..1823e3e0a --- /dev/null +++ b/ui/newstuff.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2005 by Enrico Ros * + * * + * 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. * + ***************************************************************************/ + +#ifndef _KPDF_NEWSTUFF_H_ +#define _KPDF_NEWSTUFF_H_ + +#include +#include +using namespace KNS; +namespace KIO { class JOB; } + +class AvailableItem; + +class NewStuffDialog : public QDialog +{ + Q_OBJECT + public: + NewStuffDialog( QWidget * parent ); + ~NewStuffDialog(); + + // show a message in the bottom bar + enum MessageType { Normal, Info, Error }; + void displayMessage( const QString & msg, MessageType type = Normal, + int timeOutMs = 3000 ); + + private: + // private storage class + class NewStuffDialogPrivate * d; + + private slots: + void slotResetMessageColors(); + void slotNetworkTimeout(); + void slotSortingSelected( int sortType ); + // providers loading related + void slotLoadProviders(); + void slotProvidersLoaded( Provider::List * list ); + // items loading related + void slotLoadProvider( int provider = 0 ); + void slotProviderInfoData( KIO::Job *, const QByteArray & ); + void slotProviderInfoResult( KIO::Job * ); + // files downloading related + //void slotDownloadItem( AvailableItem * ); + //void slotItemDownloaded( KIO::Job * ); +}; + +#endif