From f6d69d45cf25180a8285b2dd5c146a0481fd09ce Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 21 Sep 2014 18:30:01 -0500 Subject: Finish renaming knewstuff This relates to Bug 2093 --- tdenewstuff/CMakeLists.txt | 75 +++ tdenewstuff/Mainpage.dox | 35 ++ tdenewstuff/Makefile.am | 41 ++ tdenewstuff/README.knewstuff | 50 ++ tdenewstuff/cr16-action-knewstuff.png | Bin 0 -> 710 bytes tdenewstuff/cr32-action-knewstuff.png | Bin 0 -> 1459 bytes tdenewstuff/cr64-action-knewstuff.png | Bin 0 -> 3144 bytes tdenewstuff/downloaddialog.cpp | 959 ++++++++++++++++++++++++++++++++++ tdenewstuff/downloaddialog.h | 261 +++++++++ tdenewstuff/engine.cpp | 429 +++++++++++++++ tdenewstuff/engine.h | 189 +++++++ tdenewstuff/entry.cpp | 392 ++++++++++++++ tdenewstuff/entry.h | 282 ++++++++++ tdenewstuff/ghns.cpp | 93 ++++ tdenewstuff/ghns.h | 47 ++ tdenewstuff/knewstuff.cpp | 86 +++ tdenewstuff/knewstuff.h | 161 ++++++ tdenewstuff/knewstuffbutton.cpp | 90 ++++ tdenewstuff/knewstuffbutton.h | 115 ++++ tdenewstuff/knewstuffgeneric.cpp | 146 ++++++ tdenewstuff/knewstuffgeneric.h | 86 +++ tdenewstuff/knewstuffsecure.cpp | 240 +++++++++ tdenewstuff/knewstuffsecure.h | 101 ++++ tdenewstuff/provider.cpp | 428 +++++++++++++++ tdenewstuff/provider.h | 235 +++++++++ tdenewstuff/providerdialog.cpp | 95 ++++ tdenewstuff/providerdialog.h | 76 +++ tdenewstuff/security.cpp | 344 ++++++++++++ tdenewstuff/security.h | 141 +++++ tdenewstuff/tdehotnewstuff.cpp | 55 ++ tdenewstuff/tdehotnewstuffrc | 3 + tdenewstuff/testnewstuff.cpp | 120 +++++ tdenewstuff/testnewstuff.h | 58 ++ tdenewstuff/types | 7 + tdenewstuff/uploaddialog.cpp | 206 ++++++++ tdenewstuff/uploaddialog.h | 103 ++++ 36 files changed, 5749 insertions(+) create mode 100644 tdenewstuff/CMakeLists.txt create mode 100644 tdenewstuff/Mainpage.dox create mode 100644 tdenewstuff/Makefile.am create mode 100644 tdenewstuff/README.knewstuff create mode 100644 tdenewstuff/cr16-action-knewstuff.png create mode 100644 tdenewstuff/cr32-action-knewstuff.png create mode 100644 tdenewstuff/cr64-action-knewstuff.png create mode 100644 tdenewstuff/downloaddialog.cpp create mode 100644 tdenewstuff/downloaddialog.h create mode 100644 tdenewstuff/engine.cpp create mode 100644 tdenewstuff/engine.h create mode 100644 tdenewstuff/entry.cpp create mode 100644 tdenewstuff/entry.h create mode 100644 tdenewstuff/ghns.cpp create mode 100644 tdenewstuff/ghns.h create mode 100644 tdenewstuff/knewstuff.cpp create mode 100644 tdenewstuff/knewstuff.h create mode 100644 tdenewstuff/knewstuffbutton.cpp create mode 100644 tdenewstuff/knewstuffbutton.h create mode 100644 tdenewstuff/knewstuffgeneric.cpp create mode 100644 tdenewstuff/knewstuffgeneric.h create mode 100644 tdenewstuff/knewstuffsecure.cpp create mode 100644 tdenewstuff/knewstuffsecure.h create mode 100644 tdenewstuff/provider.cpp create mode 100644 tdenewstuff/provider.h create mode 100644 tdenewstuff/providerdialog.cpp create mode 100644 tdenewstuff/providerdialog.h create mode 100644 tdenewstuff/security.cpp create mode 100644 tdenewstuff/security.h create mode 100644 tdenewstuff/tdehotnewstuff.cpp create mode 100644 tdenewstuff/tdehotnewstuffrc create mode 100644 tdenewstuff/testnewstuff.cpp create mode 100644 tdenewstuff/testnewstuff.h create mode 100644 tdenewstuff/types create mode 100644 tdenewstuff/uploaddialog.cpp create mode 100644 tdenewstuff/uploaddialog.h (limited to 'tdenewstuff') diff --git a/tdenewstuff/CMakeLists.txt b/tdenewstuff/CMakeLists.txt new file mode 100644 index 000000000..0633603f8 --- /dev/null +++ b/tdenewstuff/CMakeLists.txt @@ -0,0 +1,75 @@ +################################################# +# +# (C) 2010 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${TQT_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/tdecore + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/tdecore + ${CMAKE_SOURCE_DIR}/tdeui + ${CMAKE_SOURCE_DIR}/tdeio + ${CMAKE_SOURCE_DIR}/tdeio/tdeio + ${CMAKE_SOURCE_DIR}/tdeio/tdefile +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### headers ################################### + +install( FILES + downloaddialog.h engine.h entry.h knewstuffgeneric.h + knewstuff.h providerdialog.h provider.h uploaddialog.h + knewstuffbutton.h knewstuffsecure.h + DESTINATION ${INCLUDE_INSTALL_DIR}/tdenewstuff ) + + +##### other data ################################ + +install( FILES types DESTINATION ${DATA_INSTALL_DIR}/tdenewstuff ) +install( FILES tdehotnewstuffrc DESTINATION ${CONFIG_INSTALL_DIR} ) +tde_install_icons( ) + + +##### tdenewstuff ############################### + +set( target tdenewstuff ) + +set( ${target}_SRCS + engine.cpp entry.cpp downloaddialog.cpp uploaddialog.cpp + providerdialog.cpp provider.cpp knewstuff.cpp security.cpp + knewstuffgeneric.cpp knewstuffbutton.cpp knewstuffsecure.cpp +) + +tde_add_library( ${target} SHARED AUTOMOC + SOURCES ${${target}_SRCS} + VERSION 1.0.0 + LINK tdeio-shared + DESTINATION ${LIB_INSTALL_DIR} +) + + +##### tdehotnewstuff ############################## + +set( target tdehotnewstuff ) + +set( ${target}_SRCS + tdehotnewstuff.cpp +) + +tde_add_executable( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK tdenewstuff-shared + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/tdenewstuff/Mainpage.dox b/tdenewstuff/Mainpage.dox new file mode 100644 index 000000000..d7f1c4da5 --- /dev/null +++ b/tdenewstuff/Mainpage.dox @@ -0,0 +1,35 @@ +/** \mainpage Collaborative Data Sharing in Trinity Applications + +The \b TDENewStuff2 library adds data sharing capabilities to %Trinity +applications. Technically, it implements the +GHNS and +DXS specifications. The library consists of three parts: the data management core +and GHNS protocol implementation, the DXS web service handler, and the user interface +classes like dialogs and buttons. + +Application authors should not use all of the classes directly, which are installed +only for the purpose of implementing functionality on top of \b TDENewStuff2; instead, +the high-level KNS::Engine class provides everything an application needs. +Both upload and download scenarios are handled by the engine. There are only two +preparation steps necessary before this class can be used: the setup of a GHNS repository, +and the creation of a *.knsrc file which will determine all aspects of the +application's \b TDENewStuff2 usage. + +All of the related information such as *.knsrc files, repositories and security +can be found in the TDENewStuff2 tutorial. + +@authors +Josef Spillner \ +Jeremy Whiting \ + +@maintainers +Jeremy Whiting \ + +@licenses +@lgpl + +*/ + +// DOXYGEN_REFERENCES = tdecore tdeui tdeio +// DOXYGEN_SET_PROJECT_NAME = TDENewStuff +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/tdenewstuff/Makefile.am b/tdenewstuff/Makefile.am new file mode 100644 index 000000000..b8532a234 --- /dev/null +++ b/tdenewstuff/Makefile.am @@ -0,0 +1,41 @@ +INCLUDES = $(all_includes) + +METASOURCES = AUTO + +lib_LTLIBRARIES = libknewstuff.la + +libknewstuff_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -version-info 1:0 +libknewstuff_la_LIBADD = $(LIB_TDEIO) $(LIB_QT) $(LIB_TDECORE) $(LIB_TDEUI) +libknewstuff_la_SOURCES = engine.cpp entry.cpp downloaddialog.cpp \ + uploaddialog.cpp providerdialog.cpp provider.cpp knewstuff.cpp \ + knewstuffgeneric.cpp knewstuffbutton.cpp knewstuffsecure.cpp security.cpp + +bin_PROGRAMS = tdehotnewstuff + +tdehotnewstuff_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor +tdehotnewstuff_LDADD = libknewstuff.la +tdehotnewstuff_SOURCES = tdehotnewstuff.cpp + +EXTRA_PROGRAMS = testnewstuff ghns + +testnewstuff_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor +testnewstuff_LDADD = libknewstuff.la +testnewstuff_SOURCES = testnewstuff.cpp + +ghns_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor +ghns_LDADD = libknewstuff.la +ghns_SOURCES = ghns.cpp + +knewstuffdir = $(kde_datadir)/knewstuff +knewstuff_DATA = types + +kde_conf_DATA = tdehotnewstuffrc + +knsdir = $(includedir)/knewstuff +kns_HEADERS = downloaddialog.h engine.h entry.h knewstuffgeneric.h knewstuff.h providerdialog.h provider.h uploaddialog.h knewstuffbutton.h knewstuffsecure.h +noinst_HEADERS = testnewstuff.h ghns.h security.h + +KDE_ICON=AUTO + +include ../admin/Doxyfile.am + diff --git a/tdenewstuff/README.knewstuff b/tdenewstuff/README.knewstuff new file mode 100644 index 000000000..fabefa988 --- /dev/null +++ b/tdenewstuff/README.knewstuff @@ -0,0 +1,50 @@ +TDENewStuff library - application data sharing framework for KDE + +TDENewStuff implements the "Get Hot New Stuff" (GHNS) architecture and +provides KDE applications with easy-to-use upload and download mechanisms, +with optional popularity counters, ratings, digital signatures, uncompression +and post-installation DCOP/scripting hooks. + +* GHNS Standard and related software + http://ghns.berlios.de/ + +* Documentation +- API docs + http://developer.kde.org/documentation/library/cvs-api/knewstuff/html/ +- TDENewStuff tutorial + http://www.kstuff.org/docs/tutorial/ +- TDENewStuffSecure tutorial + http://developer.kde.org/documentation/tutorials/knewstuffsecure/ + +* Repositories +Currently, about 7 repositories exist for a variety of KDE applications using +TDENewStuff for either download or upload or both. +Please have a look at the repository browser: +-> http://www.kstuff.org/hotstuff/index.php?p=browser +If you want automatic upload processing, download counting and administration +capabilities, as well as a web frontend, check out the Hotstuff scripts: +-> http://www.kstuff.org/source/index.php?p=cvs +For testing, feel free to use the kstuff.org infrastructure, as it is up and +running 24x7. + +* Future +Immediate plans: +- merge download dialog engine functionality into the engine class +- incremental updates of directories, + including cache +- after installation, return QStringList of installed items so no scanning + will be necessary anymore +- how to "fake" installations? (suggestions from TSDgeos) + knewstuff should know about already installed items +Future plans: +- kick-ass web interface with history and contributions +- integration with KDE SOAP messaging framework and KWSDL to access DXS +- hm.... :-) + +Josef Spillner, 01.04.2004, last updated 07.06.2005 + +Add d pointers to ALL public classes for KDE 4 or maintaining binary +compatibility is a nightmare. 12/3/05. + +Rich. + diff --git a/tdenewstuff/cr16-action-knewstuff.png b/tdenewstuff/cr16-action-knewstuff.png new file mode 100644 index 000000000..ef5ea45e2 Binary files /dev/null and b/tdenewstuff/cr16-action-knewstuff.png differ diff --git a/tdenewstuff/cr32-action-knewstuff.png b/tdenewstuff/cr32-action-knewstuff.png new file mode 100644 index 000000000..757e92668 Binary files /dev/null and b/tdenewstuff/cr32-action-knewstuff.png differ diff --git a/tdenewstuff/cr64-action-knewstuff.png b/tdenewstuff/cr64-action-knewstuff.png new file mode 100644 index 000000000..ad6d5e566 Binary files /dev/null and b/tdenewstuff/cr64-action-knewstuff.png differ diff --git a/tdenewstuff/downloaddialog.cpp b/tdenewstuff/downloaddialog.cpp new file mode 100644 index 000000000..586fb76b7 --- /dev/null +++ b/tdenewstuff/downloaddialog.cpp @@ -0,0 +1,959 @@ +/* + This file is part of TDENewStuff. + Copyright (c) 2003 Josef Spillner + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "downloaddialog.h" +#include "downloaddialog.moc" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include // hack + +#define OPENDESKTOP_REDIRECT_URL "opendesktop.org/content/download.php?content=" + +using namespace KNS; + +struct DownloadDialog::Private +{ + TQString m_providerlist; + TQWidget *m_page; + TDEListView *m_lvtmp_r, *m_lvtmp_d, *m_lvtmp_l; + TQPtrList m_installlist; + TQMap m_variantjobs; + TQMap m_variants; + TQMap m_newproviders; +}; + +class NumSortListViewItem : public TDEListViewItem +{ + public: + NumSortListViewItem( TQListView * parent, TQString label1, TQString label2 = TQString::null, TQString label3 = TQString::null, TQString label4 = TQString::null, TQString label5 = TQString::null, TQString label6 = TQString::null, TQString label7 = TQString::null, TQString label8 = TQString::null ) : + TDEListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8 ) + { + } + + TQString key(int col, bool asc) const { + if (col == 2) + { + TQString s; + s.sprintf("%08d", text(col).toInt()); + return s; + } + return TDEListViewItem::key( col, asc ); + } +}; + +class DateSortListViewItem : public TDEListViewItem +{ + public: + DateSortListViewItem( TQListView * parent, TQString label1, TQString label2 = TQString::null, TQString label3 = TQString::null, TQString label4 = TQString::null, TQString label5 = TQString::null, TQString label6 = TQString::null, TQString label7 = TQString::null, TQString label8 = TQString::null ) : + TDEListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8 ) + { + } + + TQString key(int col, bool asc) const { + if (col == 2) + { + TQString s; + TQDate date = TDEGlobal::locale()->readDate(text(col)); + s.sprintf("%08d", date.year() * 366 + date.dayOfYear()); + return s; + } + return TDEListViewItem::key( col, asc ); + } +}; + +// BEGIN deprecated for KDE 4 +DownloadDialog::DownloadDialog(Engine *engine, TQWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(TQWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::open(TQString type) +{ + DownloadDialog d; + d.setType(type); + d.load(); + d.exec(); +} +// END deprecated for KDE 4 + +DownloadDialog::DownloadDialog(Engine *engine, TQWidget *, const TQString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(TQWidget *, const TQString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::init(Engine *engine) +{ + resize(700, 400); + d = new Private(); + + m_engine = engine; + d->m_page = NULL; + + connect(this, TQT_SIGNAL(aboutToShowPage(TQWidget*)), TQT_SLOT(slotPage(TQWidget*))); + + if(!engine) + { + m_loader = new ProviderLoader(this); + connect(m_loader, TQT_SIGNAL(providersLoaded(Provider::List*)), TQT_SLOT(slotProviders(Provider::List*))); + } + + m_entries.setAutoDelete(true); +} + +DownloadDialog::~DownloadDialog() +{ + for (TQMap* >::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + delete it.data(); + for (TQMap* >::const_iterator it = m_map.constBegin(); it != m_map.constEnd(); ++it) + delete it.data(); + delete d; +} + +void DownloadDialog::load() +{ + m_loader->load(m_filter, d->m_providerlist); +} + +void DownloadDialog::load(TQString providerList) +{ + m_loader->load(m_filter, providerList); +} + +void DownloadDialog::clear() +{ + TQMap* >::Iterator it; + TQMap* >::Iterator end(m_map.end()); + for(it = m_map.begin(); it != end; ++it) + { + TQValueList *v = it.data(); + kdDebug() << "clear listviews in " << v << endl; + if(v) + { + (*(v->at(0)))->clear(); + (*(v->at(1)))->clear(); + (*(v->at(2)))->clear(); + + //delete (*it); + } + + delete it.key(); + } + m_map.clear(); +} + +void DownloadDialog::slotProviders(Provider::List *list) +{ + Provider *p; + /*TQFrame *frame;*/ + + for(p = list->first(); p; p = list->next()) + { + kdDebug() << "++ provider ++ " << p->name() << endl; + + if(!m_filter.isEmpty()) + loadProvider(p); + else + addProvider(p); + /*if(p == list->getFirst()) + slotPage(m_frame);*/ // only if !qtbug + } +} + +void DownloadDialog::addProvider(Provider *p) +{ + TQFrame *frame; + TQTabWidget *ctl; + TQWidget *w_d, *w_r, *w_l; + TQTextBrowser *rt; + TQString tmp; + int ret; + TQPixmap pix; + + if(m_map.count() == 0) + { + frame = addPage(i18n("Welcome"), i18n("Welcome"), TQPixmap(TQString(""))); + delete frame; + } + + kdDebug() << "addProvider()/begin" << endl; + + ret = true; + if(p->icon().path().isEmpty()) ret = false; + else + { + if(!p->icon().protocol().isEmpty()) + { + ret = TDEIO::NetAccess::download(p->icon(), tmp, this); + if(ret) pix = TQPixmap(tmp); + } + else + { + pix = TDEGlobal::iconLoader()->loadIcon(p->icon().path(), TDEIcon::Panel); + ret = true; + } + } + if(!ret) pix = TDEGlobal::iconLoader()->loadIcon("knewstuff", TDEIcon::Panel); + frame = addPage(p->name(), p->name(), pix); + m_frame = frame; + + w_d = new TQWidget(frame); + w_r = new TQWidget(frame); + w_l = new TQWidget(frame); + + ctl = new TQTabWidget(frame); + ctl->addTab(w_r, i18n("Highest Rated")); + ctl->addTab(w_d, i18n("Most Downloads")); + ctl->addTab(w_l, i18n("Latest")); + + m_curtab = 0; + connect(ctl, TQT_SIGNAL(currentChanged(TQWidget *)), TQT_SLOT(slotTab())); + + TQHBoxLayout *box = new TQHBoxLayout(frame); + box->add(ctl); + + d->m_lvtmp_r = new TDEListView(w_r); + d->m_lvtmp_r->addColumn(i18n("Name")); + d->m_lvtmp_r->addColumn(i18n("Version")); + d->m_lvtmp_r->addColumn(i18n("Rating")); + d->m_lvtmp_r->setSorting(2, false); + + d->m_lvtmp_d = new TDEListView(w_d); + d->m_lvtmp_d->addColumn(i18n("Name")); + d->m_lvtmp_d->addColumn(i18n("Version")); + d->m_lvtmp_d->addColumn(i18n("Downloads")); + d->m_lvtmp_d->setSorting(2, false); + + d->m_lvtmp_l = new TDEListView(w_l); + d->m_lvtmp_l->addColumn(i18n("Name")); + d->m_lvtmp_l->addColumn(i18n("Version")); + d->m_lvtmp_l->addColumn(i18n("Release Date")); + d->m_lvtmp_l->setSorting(2, false); + + connect(d->m_lvtmp_r, TQT_SIGNAL(clicked(TQListViewItem*)), TQT_SLOT(slotSelected())); + connect(d->m_lvtmp_d, TQT_SIGNAL(clicked(TQListViewItem*)), TQT_SLOT(slotSelected())); + connect(d->m_lvtmp_l, TQT_SIGNAL(clicked(TQListViewItem*)), TQT_SLOT(slotSelected())); + + rt = new TQTextBrowser(frame); + rt->setMinimumWidth(150); + + TQPushButton *in = new TQPushButton(i18n("Install"), frame); + TQPushButton *de = new TQPushButton(i18n("Details"), frame); + in->setEnabled(false); + de->setEnabled(false); + + box->addSpacing(spacingHint()); + TQVBoxLayout *vbox = new TQVBoxLayout(box); + vbox->add(rt); + vbox->addSpacing(spacingHint()); + vbox->add(de); + vbox->add(in); + + connect(rt, TQT_SIGNAL(linkClicked(const TQString&)), TQT_SLOT(slotEmail(const TQString&))); + + connect(in, TQT_SIGNAL(clicked()), TQT_SLOT(slotInstall())); + connect(de, TQT_SIGNAL(clicked()), TQT_SLOT(slotDetails())); + + TQVBoxLayout *box2 = new TQVBoxLayout(w_r); + box2->add(d->m_lvtmp_r); + TQVBoxLayout *box3 = new TQVBoxLayout(w_d); + box3->add(d->m_lvtmp_d); + TQVBoxLayout *box4 = new TQVBoxLayout(w_l); + box4->add(d->m_lvtmp_l); + + TQValueList *v = new TQValueList; + *v << d->m_lvtmp_r << d->m_lvtmp_d << d->m_lvtmp_l; + m_map[frame] = v; + m_rts[frame] = rt; + TQValueList *vb = new TQValueList; + *vb << in << de; + m_buttons[frame] = vb; + m_providers[frame] = p; + + kdDebug() << "addProvider()/end; d->m_lvtmp_r = " << d->m_lvtmp_r << endl; + + if(m_engine) slotPage(frame); + + TQTimer::singleShot(100, this, TQT_SLOT(slotFinish())); +} + +void DownloadDialog::slotResult(TDEIO::Job *job) +{ + TQDomDocument dom; + TQDomElement knewstuff; + TQDomElement content; + + kdDebug() << "got data: " << m_data[job] << endl; + + kapp->config()->setGroup("TDENewStuffStatus"); + + dom.setContent(m_data[job]); + knewstuff = dom.documentElement(); + + for(TQDomNode pn = knewstuff.firstChild(); !pn.isNull(); pn = pn.nextSibling()) + { + TQDomElement stuff = pn.toElement(); + + if(stuff.tagName() == "data") + { + content = pn.toElement(); + } + } + + for(TQDomNode pn = content.firstChild(); !pn.isNull(); pn = pn.nextSibling()) + { + TQDomElement stuff = pn.toElement(); + + kdDebug() << "element: " << stuff.tagName() << endl; + + if(stuff.tagName() == "content") + { + Entry *entry = new Entry(stuff); + kdDebug() << "TYPE::" << entry->type() << " FILTER::" << m_filter << endl; + if(!entry->type().isEmpty()) + { + if((!m_filter.isEmpty()) && (entry->type() != m_filter)) continue; + } + + /*if((!m_filter.isEmpty()) && (m_jobs[job])) + { + Provider *p = m_jobs[job]; + if(d->m_newproviders[p]) + { + addProvider(p); + slotPage(m_frame); + d->m_newproviders[p] = 0; + } + }*/ + if((!m_filter.isEmpty()) && (d->m_variantjobs[job])) + { + Provider *p = d->m_variantjobs[job]; + if(d->m_newproviders[p]) + { + addProvider(p); + slotPage(m_frame); + d->m_newproviders[p] = 0; + } + } + + /*if(m_jobs[job]) addEntry(entry); + else*/ + if(d->m_variantjobs[job]) addEntry(entry, d->m_variants[job]); + } + } +} + +int DownloadDialog::installStatus(Entry *entry) +{ + TQDate date; + TQString datestring; + int installed; + + TQString lang = TDEGlobal::locale()->language(); + + kapp->config()->setGroup("TDENewStuffStatus"); + datestring = kapp->config()->readEntry(entry->name(lang)); + if(datestring.isNull()) installed = 0; + else + { + date = TQT_TQDATE_OBJECT(TQDate::fromString(datestring, Qt::ISODate)); + if(!date.isValid()) installed = 0; + else if(date < entry->releaseDate()) installed = -1; + else installed = 1; + } + + return installed; +} + +void DownloadDialog::addEntry(Entry *entry, const TQStringList& variants) +{ + TQPixmap pix; + int installed; + + installed = installStatus(entry); + + if(installed > 0) pix = TDEGlobal::iconLoader()->loadIcon("ok", TDEIcon::Small); + else if(installed < 0) pix = TDEGlobal::iconLoader()->loadIcon("history", TDEIcon::Small); + else pix = TQPixmap(); + + TQString lang = TDEGlobal::locale()->language(); + + if(variants.contains("score")) + { + TDEListViewItem *tmp_r = new NumSortListViewItem(lv_r, + entry->name(lang), entry->version(), TQString("%1").arg(entry->rating())); + tmp_r->setPixmap(0, pix); + } + if(variants.contains("downloads")) + { + TDEListViewItem *tmp_d = new NumSortListViewItem(lv_d, + entry->name(lang), entry->version(), TQString("%1").arg(entry->downloads())); + tmp_d->setPixmap(0, pix); + } + if(variants.contains("latest")) + { + TDEListViewItem *tmp_l = new DateSortListViewItem(lv_l, + entry->name(lang), entry->version(), TDEGlobal::locale()->formatDate(entry->releaseDate())); + tmp_l->setPixmap(0, pix); + } + + m_entries.append(entry); + + kdDebug() << "added entry " << entry->name() << " for variants " << variants << endl; +} + +void DownloadDialog::addEntry(Entry *entry) +{ + TQStringList variants; + + variants << "score"; + variants << "downloads"; + variants << "latest"; + + addEntry(entry, variants); + + // not used anymore due to variants (but still used by engine) + kdDebug() << "added entry " << entry->name() << endl; +} + +void DownloadDialog::slotData(TDEIO::Job *job, const TQByteArray &a) +{ + TQCString tmp(a, a.size() + 1); + m_data[job].append(TQString::fromUtf8(tmp)); +} + +void DownloadDialog::slotDetails() +{ + Entry *e = getEntry(); + if(!e) return; + + TQString lang = TDEGlobal::locale()->language(); + + TQString info = i18n + ( + "Name: %1\n" + "Author: %2\n" + "License: %3\n" + "Version: %4\n" + "Release: %5\n" + "Rating: %6\n" + "Downloads: %7\n" + "Release date: %8\n" + "Summary: %9\n" + ).arg(e->name(lang) + ).arg(e->author() + ).arg(e->license() + ).arg(e->version() + ).arg(e->release() + ).arg(e->rating() + ).arg(e->downloads() + ).arg(TDEGlobal::locale()->formatDate(e->releaseDate()) + ).arg(e->summary(lang) + ); + + info.append(i18n + ( + "Preview: %1\n" + "Payload: %2\n" + ).arg(e->preview().url() + ).arg(e->payload().url() + )); + + KMessageBox::information(this, info, i18n("Details")); +} + +TQListViewItem *DownloadDialog::currentEntryItem() +{ + if((m_curtab == 0) && (lv_r->selectedItem())) return lv_r->selectedItem(); + if((m_curtab == 1) && (lv_d->selectedItem())) return lv_d->selectedItem(); + if((m_curtab == 2) && (lv_l->selectedItem())) return lv_l->selectedItem(); + + return 0; +} + +void DownloadDialog::slotInstall() +{ + Entry *e = getEntry(); + if(!e) return; + + TQPushButton *de, *in; + in = *(m_buttons[d->m_page]->at(0)); + de = *(m_buttons[d->m_page]->at(1)); + + if(in) in->setEnabled(false); + if(de) de->setEnabled(false); + + d->m_lvtmp_r->setEnabled( false ); + d->m_lvtmp_l->setEnabled( false ); + d->m_lvtmp_d->setEnabled( false ); + + kdDebug() << "download entry now" << endl; + + // OpenDesktop.org broke the basic functionality of TDEHNS by forcing + // downloads though an advertising display page. This in turn forces + // the user to download and manually install the wallpaper, which + // is relatively complex and negates much of the benefit of TDEHNS. + // Therefore, if the download URL contains OPENDESKTOP_REDIRECT_URL + // then download the raw HTML page and extract the real download URL for use below. + // In the future we may want to figure out how to display unobtrusive ads + // during the download process, but OpenDesktop.org would need to add back + // in the direct download ability for this to even be considered. + if (e->payload().url().contains(OPENDESKTOP_REDIRECT_URL)) { + TDEIO::TransferJob *job = TDEIO::get( KURL( e->payload() ), false, false ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotJobResult( TDEIO::Job * ) ) ); + connect( job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), + TQT_SLOT( slotJobData( TDEIO::Job *, const TQByteArray & ) ) ); + } + else { + slotInstallPhase2(); + } +} + +void DownloadDialog::slotInstallPhase2() +{ + Entry *e = getEntry(); + if(!e) return; + + m_entryitem = currentEntryItem(); + m_entryname = m_entryitem->text(0); + + kdDebug() << "download entry now (phase 2)" << endl; + + if(m_engine) + { + m_engine->download(e); + install(e); + } + else + { + m_s = new TDENewStuffGeneric(e->type(), this); + m_entry = e; + KURL source = e->payload(); + KURL dest = KURL(m_s->downloadDestination(e)); + + TDEIO::FileCopyJob *job = TDEIO::file_copy(source, dest, -1, true); + connect(job, TQT_SIGNAL(result(TDEIO::Job*)), TQT_SLOT(slotInstalled(TDEIO::Job*))); + } +} + +void DownloadDialog::slotJobData( TDEIO::Job *, const TQByteArray &data ) +{ + kdDebug() << "DownloadDialog::slotJobData()" << endl; + + if ( data.size() == 0 ) return; + + TQCString str( data, data.size() + 1 ); + + mJobData.append( TQString::fromUtf8( str ) ); +} + +void DownloadDialog::slotJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + job->showErrorDialog( this ); + return; + } + + Entry *e = getEntry(); + if(!e) return; + + // See previous note regarding OpenDesktop.org + if (e->payload().url().contains(OPENDESKTOP_REDIRECT_URL)) { + TQString realURL = mJobData.mid(mJobData.find("")-2); + realURL = realURL.mid(realURL.find("/CONTENT/content-files")); + realURL = e->payload().protocol() + "://opendesktop.org" + realURL; + e->setPayload(realURL); + } + + slotInstallPhase2(); +} + +void DownloadDialog::install(Entry *e) +{ + kapp->config()->setGroup("TDENewStuffStatus"); + kapp->config()->writeEntry(m_entryname, TQString(e->releaseDate().toString(Qt::ISODate))); + kapp->config()->sync(); + + TQPixmap pix = TDEGlobal::iconLoader()->loadIcon("ok", TDEIcon::Small); + + TQString lang = TDEGlobal::locale()->language(); + + if(m_entryitem) + { + m_entryitem->setPixmap(0, pix); + + TQListViewItem *item; + item = lv_r->findItem(e->name(lang), 0); + if(item) item->setPixmap(0, pix); + item = lv_d->findItem(e->name(lang), 0); + if(item) item->setPixmap(0, pix); + item = lv_l->findItem(e->name(lang), 0); + if(item) item->setPixmap(0, pix); + } + + if(currentEntryItem() == m_entryitem) + { + TQPushButton *in; + in = *(m_buttons[d->m_page]->at(0)); + if(in) in->setEnabled(false); + } + + d->m_installlist.append(e); + d->m_lvtmp_r->setEnabled( true ); + d->m_lvtmp_l->setEnabled( true ); + d->m_lvtmp_d->setEnabled( true ); +} + +void DownloadDialog::slotInstalled(TDEIO::Job *job) +{ + bool ret = job && (job->error() == 0); + if(ret) + { + TDEIO::FileCopyJob *cjob = ::tqqt_cast(job); + if(cjob) + { + ret = m_s->install(cjob->destURL().path()); + } + else ret = false; + } + + if(ret) + { + install(m_entry); + + KMessageBox::information(this, i18n("Installation successful."), i18n("Installation")); + } + else KMessageBox::error(this, i18n("Installation failed."), i18n("Installation")); + d->m_lvtmp_r->setEnabled( true ); + d->m_lvtmp_l->setEnabled( true ); + d->m_lvtmp_d->setEnabled( true ); + + delete m_s; +} + +void DownloadDialog::slotTab() +{ + int tab = static_cast(sender())->currentPageIndex(); + kdDebug() << "switch tab to: " << tab << endl; + + Entry *eold = getEntry(); + m_curtab = tab; + Entry *e = getEntry(); + + if(e == eold) return; + + if(e) + { + slotSelected(); + } + else + { + TQPushButton *de, *in; + in = *(m_buttons[d->m_page]->at(0)); + de = *(m_buttons[d->m_page]->at(1)); + + if(in) in->setEnabled(false); + if(de) de->setEnabled(false); + + m_rt->clear(); + } +} + +void DownloadDialog::slotSelected() +{ + TQString tmp; + bool enabled; + Entry *e = getEntry(); + TQString lang = TDEGlobal::locale()->language(); + bool ret; + + if(e) + { + TQString lang = TDEGlobal::locale()->language(); + + TQListViewItem *item; + if(m_curtab != 0) + { + lv_r->clearSelection(); + item = lv_r->findItem(e->name(lang), 0); + if(item) lv_r->setSelected(item, true); + } + if(m_curtab != 1) + { + lv_d->clearSelection(); + item = lv_d->findItem(e->name(lang), 0); + if(item) lv_d->setSelected(item, true); + } + if(m_curtab != 2) + { + lv_l->clearSelection(); + item = lv_l->findItem(e->name(lang), 0); + if(item) lv_l->setSelected(item, true); + } + + if(!e->preview(lang).isValid()) + { + ret = 0; + } + else + { + ret = TDEIO::NetAccess::download(e->preview(lang), tmp, this); + } + + TQString desc = TQString("%1
").arg(e->name(lang)); + if(!e->authorEmail().isNull()) + { + desc += TQString("
" + e->author() + ""); + } + else + { + desc += TQString("%1").arg(e->author()); + } + desc += TQString("
%1").arg(TDEGlobal::locale()->formatDate(e->releaseDate())); + desc += TQString("

"); + if(ret) + { + desc += TQString("").arg(tmp); + } + else + { + desc += i18n("Preview not available."); + } + desc += TQString("
%1").arg(e->summary(lang)); + desc += TQString("
(%1)").arg(e->license()); + + m_rt->clear(); + m_rt->setText(desc); + + if(installStatus(e) == 1) enabled = false; + else enabled = true; + + TQPushButton *de, *in; + in = *(m_buttons[d->m_page]->at(0)); + de = *(m_buttons[d->m_page]->at(1)); + if(in) in->setEnabled(enabled); + if(de) de->setEnabled(true); + } +} + +void DownloadDialog::slotEmail(const TQString& link) +{ + kdDebug() << "EMAIL: " << link << endl; + kapp->invokeMailer(link); + slotSelected(); // TQTextBrowser oddity workaround as it cannot handle mailto: URLs +} + +Entry *DownloadDialog::getEntry() +{ + TQListViewItem *entryItem = currentEntryItem(); + + if(!entryItem) + return 0; + + TQString entryName = entryItem->text(0); + + TQString lang = TDEGlobal::locale()->language(); + + for(Entry *e = m_entries.first(); e; e = m_entries.next()) + if(e->name(lang) == entryName) + return e; + + return 0; +} + +void DownloadDialog::slotPage(TQWidget *w) +{ + Provider *p; + + kdDebug() << "changed widget!!!" << endl; + + if(m_map.find(w) == m_map.end()) return; + + d->m_page = w; + + lv_r = *(m_map[w]->at(0)); + lv_d = *(m_map[w]->at(1)); + lv_l = *(m_map[w]->at(2)); + p = m_providers[w]; + m_rt = m_rts[w]; + + kdDebug() << "valid change!!!; lv_r = " << lv_r << endl; + + if(m_engine) return; + + if(!m_filter.isEmpty()) return; + + lv_r->clear(); + lv_d->clear(); + lv_l->clear(); + + kdDebug() << "-- fetch -- " << p->downloadUrl() << endl; + + loadProvider(p); +} + +void DownloadDialog::loadProvider(Provider *p) +{ + TQMap::Iterator it; + + for(it = d->m_variantjobs.begin(); it != d->m_variantjobs.end(); it++) + { + if(it.data() == p) + { + kdDebug() << "-- found provider data in cache" << endl; + slotResult(it.key()); + return; + } + } + + TQStringList variants; + variants << "score"; + variants << "downloads"; + variants << "latest"; + + // Optimise URLs so each unique URL only gets fetched once + + TQMap urls; + + for(TQStringList::Iterator it = variants.begin(); it != variants.end(); it++) + { + TQString url = p->downloadUrlVariant((*it)).url(); + if(!urls.contains(url)) + { + urls[url] = TQStringList(); + } + urls[url] << (*it); + + it = variants.remove(it); + } + + // Now fetch the URLs while keeping the variant list for each attached + + for(TQMap::Iterator it = urls.begin(); it != urls.end(); it++) + { + TQString url = it.key(); + TQStringList urlvariants = it.data(); + + TDEIO::TransferJob *variantjob = TDEIO::get(url); + d->m_newproviders[p] = p; + d->m_variantjobs[variantjob] = p; + d->m_variants[variantjob] = urlvariants; + m_data[variantjob] = ""; + + connect(variantjob, TQT_SIGNAL(result(TDEIO::Job*)), TQT_SLOT(slotResult(TDEIO::Job*))); + connect(variantjob, TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)), + TQT_SLOT(slotData(TDEIO::Job*, const TQByteArray&))); + } + + if(variants.count() == 0) return; + + // If not all variants are given, use default URL for those + + kdDebug() << "-- reached old downloadurl section; variants left: " << variants.count() << endl; + + TDEIO::TransferJob *job = TDEIO::get(p->downloadUrl()); + + d->m_newproviders[p] = p; + d->m_variantjobs[job] = p; + d->m_variants[job] = variants; + //m_jobs[job] = p; // not used anymore due to variants + m_data[job] = ""; + + connect(job, TQT_SIGNAL(result(TDEIO::Job*)), TQT_SLOT(slotResult(TDEIO::Job*))); + connect(job, TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)), + TQT_SLOT(slotData(TDEIO::Job*, const TQByteArray&))); +} + +void DownloadDialog::setType(TQString type) +{ + m_filter = type; +} + +void DownloadDialog::setProviderList(const TQString& providerList) +{ + d->m_providerlist = providerList; +} + +void DownloadDialog::slotOk() +{ +} + +void DownloadDialog::slotApply() +{ +} + +void DownloadDialog::open(const TQString& type, const TQString& caption) +{ + DownloadDialog d(0, caption); + d.setType(type); + d.load(); + d.exec(); +} + +void DownloadDialog::slotFinish() +{ + showPage(1); + //updateBackground(); +} + +TQPtrList DownloadDialog::installedEntries() +{ + return d->m_installlist; +} diff --git a/tdenewstuff/downloaddialog.h b/tdenewstuff/downloaddialog.h new file mode 100644 index 000000000..5756a4e6e --- /dev/null +++ b/tdenewstuff/downloaddialog.h @@ -0,0 +1,261 @@ +/* + This file is part of TDENewStuff. + Copyright (c) 2003 Josef Spillner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_DOWNLOADDIALOG_H +#define KNEWSTUFF_DOWNLOADDIALOG_H + +#include +#include + +namespace TDEIO +{ + class Job; +} + +class TDEListView; +class TQTextBrowser; +class TQFrame; +class TDENewStuffGeneric; + +namespace KNS +{ + +class ProviderLoader; +class Entry; +class Provider; +class Engine; + +/** + * @short Common download dialog for data browsing and installation. + * + * It provides an easy-to-use convenience method named open() which does all + * the work, unless a more complex operation is needed. + * \code + * TDENewStuff::DownloadDialog::open("kdesktop/wallpapers"); + * \endcode + * + * @author Josef Spillner (spillner@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT DownloadDialog : public KDialogBase +{ + Q_OBJECT + struct Private; + public: + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(Engine *engine, TQWidget *parent, const TQString& caption); + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(TQWidget *parent, const TQString& caption); + + /** + Destructor. + */ + ~DownloadDialog(); + + /** + Restricts the display of available data to a certain data type. + + @param type a Hotstuff data type such as "korganizer/calendar" + */ + void setType(TQString type); + // ### KDE 4.0: use const TQString& + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + */ + void load(); + + /** + Explicitly uses this provider list instead of the one read from + the application configuration. + + @param providerList the URL of the provider list + + @since 3.4 + */ + void setProviderList(const TQString& providerList); + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + + @param providerList the URl to the list of providers; if empty + we first try the ProvidersUrl from TDEGlobal::config, then we + fall back to a hardcoded value. + */ + void load(TQString providerList); // KDE4: merge with load() above + + /** + Adds another provider to the download dialog. + This is normally done internally. + + @param p the Hotstuff provider to be added + */ + void addProvider(Provider *p); + + /** + Adds an additional entry to the current provider. + This is normally done internally. + + @param entry a Hotstuff data entry to be added + */ + void addEntry(Entry *entry); + + /** + Adds an additional entry to the current provider. + This is normally done internal. + This version takes into accounts the download variant. + + @param entry a Hotstuff data entry to be added + @param variants all variants this entry is intended for + */ + void addEntry(Entry *entry, const TQStringList& variants); + + /** + Clears the entry list of the current provider. + This is normally done internally. + */ + void clear(); + + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + */ + DownloadDialog(Engine *engine, TQWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + */ + DownloadDialog(TQWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + @param caption the dialog caption + */ + static void open(const TQString& type, const TQString& caption); + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + @deprecated use open( const TQString& type, const TQString& caption ); + */ + static void open(TQString type) KDE_DEPRECATED; // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Returns the list of installed data entries. + + @return list of data entries which have been installed + */ + TQPtrList installedEntries(); + // ### KDE 4.0: the open() method should return this + + public slots: + /** + Availability of the provider list. + + @param list list of Hotstuff providers + */ + void slotProviders(Provider::List *list); + + protected slots: + void slotApply(); + void slotOk(); + + private slots: + void slotResult(TDEIO::Job *job); + void slotData(TDEIO::Job *job, const TQByteArray &a); + void slotJobData( TDEIO::Job *, const TQByteArray & ); + void slotJobResult( TDEIO::Job * ); + void slotInstall(); + void slotInstallPhase2(); + void slotDetails(); + void slotInstalled(TDEIO::Job *job); + void slotTab(); + void slotSelected(); + void slotPage(TQWidget *w); + void slotFinish(); + void slotEmail(const TQString& link); + + private: + void init(Engine *e); + Entry *getEntry(); + void loadProvider(Provider *p); + void install(Entry *e); + int installStatus(Entry *e); + TQListViewItem *currentEntryItem(); + + ProviderLoader *m_loader; + TQString m_entryname; + TDEListView *lv_r, *lv_d, *lv_l; + TQTextBrowser *m_rt; + TQFrame *m_frame; + TQListViewItem *m_entryitem; + TQPtrList m_entries; + Entry *m_entry; + TDENewStuffGeneric *m_s; + int m_curtab; + TQMap* > m_map; + TQMap m_providers; + TQMap m_rts; + TQMap* > m_buttons; + TQMap m_jobs; + TQMap m_data; + TQString m_filter; + TQString mJobData; + Engine *m_engine; + Private *d; +}; + +} + +#endif + diff --git a/tdenewstuff/engine.cpp b/tdenewstuff/engine.cpp new file mode 100644 index 000000000..f8e7163a9 --- /dev/null +++ b/tdenewstuff/engine.cpp @@ -0,0 +1,429 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "knewstuff.h" +#include "downloaddialog.h" +#include "uploaddialog.h" +#include "providerdialog.h" + +#include "engine.h" +#include "engine.moc" + +using namespace KNS; + +struct Engine::Private +{ + bool mIgnoreInstallResult; + TDENewStuff *mNewStuff; +}; + +Engine::Engine( TDENewStuff *newStuff, const TQString &type, + TQWidget *parentWidget ) : + mParentWidget( parentWidget ), mDownloadDialog( 0 ), + mUploadDialog( 0 ), mProviderDialog( 0 ), mUploadProvider( 0 ), + d(new Private), mType( type ) +{ + d->mNewStuff = newStuff; + d->mIgnoreInstallResult = false; + mProviderLoader = new ProviderLoader( mParentWidget ); +} + +Engine::Engine( TDENewStuff *newStuff, const TQString &type, + const TQString &providerList, TQWidget *parentWidget ) : + mParentWidget( parentWidget ), + mDownloadDialog( 0 ), mUploadDialog( 0 ), + mProviderDialog( 0 ), mUploadProvider( 0 ), + mProviderList( providerList ), d(new Private), + mType( type ) +{ + d->mNewStuff = newStuff; + d->mIgnoreInstallResult = false; + mProviderLoader = new ProviderLoader( mParentWidget ); +} + +Engine::~Engine() +{ + delete d; + delete mProviderLoader; + + delete mUploadDialog; + delete mDownloadDialog; +} + +void Engine::download() +{ + kdDebug() << "Engine::download()" << endl; + + connect( mProviderLoader, + TQT_SIGNAL( providersLoaded( Provider::List * ) ), + TQT_SLOT( getMetaInformation( Provider::List * ) ) ); + mProviderLoader->load( mType, mProviderList ); +} + +void Engine::getMetaInformation( Provider::List *providers ) +{ + mProviderLoader->disconnect(); + + mNewStuffJobData.clear(); + + if ( !mDownloadDialog ) { + mDownloadDialog = new DownloadDialog( this, mParentWidget ); + mDownloadDialog->show(); + } + mDownloadDialog->clear(); + + Provider *p; + for ( p = providers->first(); p; p = providers->next() ) { + if ( p->downloadUrl().isEmpty() ) continue; + + TDEIO::TransferJob *job = TDEIO::get( p->downloadUrl(), false, false ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotNewStuffJobResult( TDEIO::Job * ) ) ); + connect( job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), + TQT_SLOT( slotNewStuffJobData( TDEIO::Job *, const TQByteArray & ) ) ); + + mNewStuffJobData.insert( job, "" ); + mProviderJobs[ job ] = p; + } +} + +void Engine::slotNewStuffJobData( TDEIO::Job *job, const TQByteArray &data ) +{ + if ( data.isEmpty() ) return; + + kdDebug() << "Engine:slotNewStuffJobData()" << endl; + + TQCString str( data, data.size() + 1 ); + + mNewStuffJobData[ job ].append( TQString::fromUtf8( str ) ); +} + +void Engine::slotNewStuffJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + kdDebug() << "Error downloading new stuff descriptions." << endl; + job->showErrorDialog( mParentWidget ); + } else { + TQString knewstuffDoc = mNewStuffJobData[ job ]; + + kdDebug() << "---START---" << endl << knewstuffDoc << "---END---" << endl; + + mDownloadDialog->addProvider( mProviderJobs[ job ] ); + + TQDomDocument doc; + if ( !doc.setContent( knewstuffDoc ) ) { + kdDebug() << "Error parsing knewstuff.xml." << endl; + return; + } else { + TQDomElement knewstuff = doc.documentElement(); + + if ( knewstuff.isNull() ) { + kdDebug() << "No document in knewstuffproviders.xml." << endl; + } else { + TQDomNode p; + for ( p = knewstuff.firstChild(); !p.isNull(); p = p.nextSibling() ) { + TQDomElement stuff = p.toElement(); + if ( stuff.tagName() != "stuff" ) continue; + if ( stuff.attribute("type", mType) != mType ) continue; + + Entry *entry = new Entry( stuff ); + + mDownloadDialog->show(); + + mDownloadDialog->addEntry( entry ); + + kdDebug() << "KNEWSTUFF: " << entry->name() << endl; + + kdDebug() << " SUMMARY: " << entry->summary() << endl; + kdDebug() << " VERSION: " << entry->version() << endl; + kdDebug() << " RELEASEDATE: " << TQString(entry->releaseDate().toString()) << endl; + kdDebug() << " RATING: " << entry->rating() << endl; + + kdDebug() << " LANGS: " << entry->langs().join(", ") << endl; + } + } + } + } + + mNewStuffJobData.remove( job ); + mProviderJobs.remove( job ); + + if ( mNewStuffJobData.count() == 0 ) { + mDownloadDialog->show(); + mDownloadDialog->raise(); + } +} + +void Engine::download( Entry *entry ) +{ + kdDebug() << "Engine::download(entry)" << endl; + + KURL source = entry->payload(); + mDownloadDestination = d->mNewStuff->downloadDestination( entry ); + + if ( mDownloadDestination.isEmpty() ) { + kdDebug() << "Empty downloadDestination. Cancelling download." << endl; + return; + } + + KURL destination = KURL( mDownloadDestination ); + + kdDebug() << " SOURCE: " << source.url() << endl; + kdDebug() << " DESTINATION: " << destination.url() << endl; + + TDEIO::FileCopyJob *job = TDEIO::file_copy( source, destination, -1, true ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotDownloadJobResult( TDEIO::Job * ) ) ); +} + +void Engine::slotDownloadJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + kdDebug() << "Error downloading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + return; + } + + if ( d->mNewStuff->install( mDownloadDestination ) ) { + if ( !d->mIgnoreInstallResult ) { + KMessageBox::information( mParentWidget, + i18n("Successfully installed hot new stuff.") ); + } + } else + if ( !d->mIgnoreInstallResult ){ + KMessageBox::error( mParentWidget, + i18n("Failed to install hot new stuff.") ); + } +} + +void Engine::upload(const TQString &fileName, const TQString &previewName ) +{ + mUploadFile = fileName; + mPreviewFile = previewName; + + connect( mProviderLoader, + TQT_SIGNAL( providersLoaded( Provider::List * ) ), + TQT_SLOT( selectUploadProvider( Provider::List * ) ) ); + mProviderLoader->load( mType ); +} + +void Engine::selectUploadProvider( Provider::List *providers ) +{ + kdDebug() << "Engine:selectUploadProvider()" << endl; + + mProviderLoader->disconnect(); + + if ( !mProviderDialog ) { + mProviderDialog = new ProviderDialog( this, mParentWidget ); + } + + mProviderDialog->clear(); + + mProviderDialog->show(); + mProviderDialog->raise(); + + for( Provider *p = providers->first(); p; p = providers->next() ) { + mProviderDialog->addProvider( p ); + } +} + +void Engine::requestMetaInformation( Provider *provider ) +{ + mUploadProvider = provider; + + if ( !mUploadDialog ) { + mUploadDialog = new UploadDialog( this, mParentWidget ); + } + mUploadDialog->setPreviewFile( mPreviewFile ); + mUploadDialog->setPayloadFile( mUploadFile ); + mUploadDialog->show(); + mUploadDialog->raise(); +} + +void Engine::upload( Entry *entry ) +{ + if ( mUploadFile.isNull()) { + mUploadFile = entry->fullName(); + mUploadFile = locateLocal( "data", TQString(kapp->instanceName()) + "/upload/" + mUploadFile ); + + if ( !d->mNewStuff->createUploadFile( mUploadFile ) ) { + KMessageBox::error( mParentWidget, i18n("Unable to create file to upload.") ); + emit uploadFinished( false ); + return; + } + } + + TQString lang = entry->langs().first(); + TQFileInfo fi( mUploadFile ); + entry->setPayload( KURL::fromPathOrURL( fi.fileName() ), lang ); + + if ( !createMetaFile( entry ) ) { + emit uploadFinished( false ); + return; + } + + TQString text = i18n("The files to be uploaded have been created at:\n"); + text.append( i18n("Data file: %1\n").arg( mUploadFile) ); + if (!mPreviewFile.isEmpty()) { + text.append( i18n("Preview image: %1\n").arg( mPreviewFile) ); + } + text.append( i18n("Content information: %1\n").arg( mUploadMetaFile) ); + text.append( i18n("Those files can now be uploaded.\n") ); + text.append( i18n("Beware that any people might have access to them at any time.") ); + + TQString caption = i18n("Upload Files"); + + if ( mUploadProvider->noUpload() ) { + KURL noUploadUrl = mUploadProvider->noUploadUrl(); + if ( noUploadUrl.isEmpty() ) { + text.append( i18n("Please upload the files manually.") ); + KMessageBox::information( mParentWidget, text, caption ); + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("Upload Info"), + KStdGuiItem::close() ); + if ( result == KMessageBox::Yes ) { + kapp->invokeBrowser( noUploadUrl.url() ); + } + } + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("&Upload"), KStdGuiItem::cancel() ); + if ( result == KMessageBox::Yes ) { + KURL destination = mUploadProvider->uploadUrl(); + destination.setFileName( fi.fileName() ); + + TDEIO::FileCopyJob *job = TDEIO::file_copy( KURL::fromPathOrURL( mUploadFile ), destination ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotUploadPayloadJobResult( TDEIO::Job * ) ) ); + } else { + emit uploadFinished( false ); + } + } +} + +bool Engine::createMetaFile( Entry *entry ) +{ + TQDomDocument doc("knewstuff"); + doc.appendChild( doc.createProcessingInstruction( + "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); + TQDomElement de = doc.createElement("knewstuff"); + doc.appendChild( de ); + + entry->setType(type()); + de.appendChild( entry->createDomElement( doc, de ) ); + + kdDebug() << "--DOM START--" << endl << doc.toString() + << "--DOM_END--" << endl; + + if ( mUploadMetaFile.isNull() ) { + mUploadMetaFile = entry->fullName() + ".meta"; + mUploadMetaFile = locateLocal( "data", TQString(kapp->instanceName()) + "/upload/" + mUploadMetaFile ); + } + + TQFile f( mUploadMetaFile ); + if ( !f.open( IO_WriteOnly ) ) { + mUploadMetaFile = TQString::null; + return false; + } + + TQTextStream ts( &f ); + ts.setEncoding( TQTextStream::UnicodeUTF8 ); + ts << doc.toString(); + + f.close(); + + return true; +} + +void Engine::slotUploadPayloadJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + kdDebug() << "Error uploading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + if (mPreviewFile.isEmpty()) { + slotUploadPreviewJobResult(job); + return; + } + + TQFileInfo fi( mPreviewFile ); + + KURL previewDestination = mUploadProvider->uploadUrl(); + previewDestination.setFileName( fi.fileName() ); + + TDEIO::FileCopyJob *newJob = TDEIO::file_copy( KURL::fromPathOrURL( mPreviewFile ), previewDestination ); + connect( newJob, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotUploadPreviewJobResult( TDEIO::Job * ) ) ); +} + +void Engine::slotUploadPreviewJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + kdDebug() << "Error uploading new stuff preview." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( true ); + return; + } + + TQFileInfo fi( mUploadMetaFile ); + + KURL metaDestination = mUploadProvider->uploadUrl(); + metaDestination.setFileName( fi.fileName() ); + + TDEIO::FileCopyJob *newJob = TDEIO::file_copy( KURL::fromPathOrURL( mUploadMetaFile ), metaDestination ); + connect( newJob, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotUploadMetaJobResult( TDEIO::Job * ) ) ); +} + +void Engine::slotUploadMetaJobResult( TDEIO::Job *job ) +{ + mUploadMetaFile = TQString::null; + if ( job->error() ) { + kdDebug() << "Error uploading new stuff metadata." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + KMessageBox::information( mParentWidget, + i18n("Successfully uploaded new stuff.") ); + emit uploadFinished( true ); +} + +void Engine::ignoreInstallResult(bool ignore) +{ + d->mIgnoreInstallResult = ignore; +} diff --git a/tdenewstuff/engine.h b/tdenewstuff/engine.h new file mode 100644 index 000000000..432f3b04c --- /dev/null +++ b/tdenewstuff/engine.h @@ -0,0 +1,189 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_ENGINE_H +#define KNEWSTUFF_ENGINE_H + +#include +#include +#include + +#include "entry.h" +#include "provider.h" + +namespace TDEIO { class Job; } + +class TDENewStuff; + +namespace KNS { + +class DownloadDialog; +class UploadDialog; +class ProviderDialog; + +/** + * @short Central class combining all possible TDENewStuff operations. + * + * In most cases, Engine objects are built and used internally. + * Using this class explicitely does however give fine-grained control about the + * upload and download operations. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT Engine : public TQObject +{ + Q_OBJECT + struct Private; + public: + /** + Constructor. + + @param newStuff a TDENewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param parentWidget the parent window + */ + Engine( TDENewStuff *newStuff, const TQString &type, TQWidget *parentWidget = 0 ); + /** + Constructor. + + @param newStuff a TDENewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param providerList the URL of the provider list + @param parentWidget the parent window + */ + Engine( TDENewStuff *newStuff, const TQString &type, const TQString &providerList, TQWidget *parentWidget = 0 ); + + /** + Destructor. + */ + virtual ~Engine(); + + /** + Returns the previously set data type. + + @return the Hotstuff data type + */ + TQString type() const { return mType; } + + /** + Returns the previously set parent widget. + + @return parent widget + */ + TQWidget *parentWidget() const { return mParentWidget; } + + /** + Initiates the download process, retrieving provider lists and invoking + the download dialog. + */ + void download(); + + /** + Initiates the upload process, invoking the provider selection dialog + and the file upload dialog. + + @param fileName name of the payload data file + @param previewName name of the preview image file + */ + void upload( const TQString &fileName = TQString::null, const TQString &previewName = TQString::null ); + + /** + Downloads the specified data file. + + @param entry the Hotstuff data object to be downloaded + */ + void download( Entry *entry ); + + /** + Asynchronous lookup of provider information such as upload and + download locations, icon etc. + + @param provider the Hotstuff provider to request information from + */ + void requestMetaInformation( Provider *provider ); + + /** + Uploads the specified data file to the provider-dependent location. + + @param entry the Hotstuff data object to be uploaded + */ + void upload( Entry *entry ); + + /** + Ignores the return value of the install method. Used internally to + avoid showing of the success/failure dialog when installation is done + in another place, like in @ref TDENewStuffSecure + */ + void ignoreInstallResult(bool ignore); + + signals: + /** Emitted when the upload has finished. + @param result indicates the success/failure of the upload + */ + void uploadFinished( bool result ); + protected slots: + void getMetaInformation( Provider::List *providers ); + void selectUploadProvider( Provider::List *providers ); + + void slotNewStuffJobData( TDEIO::Job *job, const TQByteArray &data ); + void slotNewStuffJobResult( TDEIO::Job *job ); + + void slotDownloadJobResult( TDEIO::Job *job ); + + void slotUploadPayloadJobResult( TDEIO::Job *job ); + void slotUploadPreviewJobResult (TDEIO::Job *job ); + void slotUploadMetaJobResult( TDEIO::Job *job ); + + protected: + bool createMetaFile( Entry * ); + + private: + TQWidget *mParentWidget; + + ProviderLoader *mProviderLoader; + + TQMap mNewStuffJobData; + TQMap mProviderJobs; + + TQPtrList mNewStuffList; + + DownloadDialog *mDownloadDialog; + UploadDialog *mUploadDialog; + ProviderDialog *mProviderDialog; + + TQString mDownloadDestination; + + Provider *mUploadProvider; + + TQString mUploadMetaFile; + TQString mUploadFile; + TQString mPreviewFile; + TQString mProviderList; + + Private* d; + + TQString mType; +}; + +} + +#endif diff --git a/tdenewstuff/entry.cpp b/tdenewstuff/entry.cpp new file mode 100644 index 000000000..2713fadfb --- /dev/null +++ b/tdenewstuff/entry.cpp @@ -0,0 +1,392 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "entry.h" + +#include +#include + +#include +#include + +using namespace KNS; + +// BCI for KDE 3.5 only + +class EntryPrivate +{ + public: + EntryPrivate(){} + TQString mEmail; + TQMap mNameMap; +}; + +static TQPtrDict *d_ptr = 0; + +static EntryPrivate *d(const Entry *e) +{ + if(!d_ptr) + { + d_ptr = new TQPtrDict(); + d_ptr->setAutoDelete(true); + } + EntryPrivate *ret = d_ptr->find((void*)e); + if(!ret) + { + ret = new EntryPrivate(); + d_ptr->replace((void*)e, ret); + } + return ret; +} + +TQString Entry::authorEmail() const +{ + return d(this)->mEmail; +} + +void Entry::setAuthorEmail( const TQString& email ) +{ + d(this)->mEmail = email; +} + +TQString Entry::name( const TQString &lang ) const +{ + if ( d(this)->mNameMap.isEmpty() ) return TQString::null; + + if ( !d(this)->mNameMap[ lang ].isEmpty() ) return d(this)->mNameMap[ lang ]; + else { + TQStringList langs = TDEGlobal::locale()->languageList(); + for(TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !d(this)->mNameMap[ *it ].isEmpty() ) return d(this)->mNameMap[ *it ]; + } + if ( !d(this)->mNameMap[ TQString::null ].isEmpty() ) return d(this)->mNameMap[ TQString::null ]; + else return *(mSummaryMap.begin()); +} + +void Entry::setName( const TQString &name, const TQString &lang ) +{ + d(this)->mNameMap.insert( lang, name ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +// BCI part ends here + +Entry::Entry() : + mRelease( 0 ), mReleaseDate( TQDate::currentDate() ), mRating( 0 ), + mDownloads( 0 ) +{ +} + +Entry::Entry( const TQDomElement &e ) : + mRelease( 0 ), mRating( 0 ), mDownloads( 0 ) +{ + parseDomElement( e ); +} + +Entry::~Entry() +{ + if (d_ptr) + { + EntryPrivate *p = d_ptr->find(this); + if (p) + d_ptr->remove(p); + + if (d_ptr->isEmpty()) + { + delete d_ptr; + d_ptr = 0L; + } + } +} + + +void Entry::setName( const TQString &name ) +{ + mName = name; +} + +TQString Entry::name() const +{ + return mName; +} + + +void Entry::setType( const TQString &type ) +{ + mType = type; +} + +TQString Entry::type() const +{ + return mType; +} + + +void Entry::setAuthor( const TQString &author ) +{ + mAuthor = author; +} + +TQString Entry::author() const +{ + return mAuthor; +} + + +void Entry::setLicence( const TQString &license ) +{ + mLicence = license; +} + +TQString Entry::license() const +{ + return mLicence; +} + + +void Entry::setSummary( const TQString &text, const TQString &lang ) +{ + mSummaryMap.insert( lang, text ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +TQString Entry::summary( const TQString &lang ) const +{ + if ( mSummaryMap.isEmpty() ) return TQString::null; + + if ( !mSummaryMap[ lang ].isEmpty() ) return mSummaryMap[ lang ]; + else { + TQStringList langs = TDEGlobal::locale()->languageList(); + for(TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mSummaryMap[ *it ].isEmpty() ) return mSummaryMap[ *it ]; + } + if ( !mSummaryMap[ TQString::null ].isEmpty() ) return mSummaryMap[ TQString::null ]; + else return *(mSummaryMap.begin()); +} + + +void Entry::setVersion( const TQString &version ) +{ + mVersion = version; +} + +TQString Entry::version() const +{ + return mVersion; +} + + +void Entry::setRelease( int release ) +{ + mRelease = release; +} + +int Entry::release() const +{ + return mRelease; +} + + +void Entry::setReleaseDate( const TQDate &d ) +{ + mReleaseDate = d; +} + +TQDate Entry::releaseDate() const +{ + return mReleaseDate; +} + + +void Entry::setPayload( const KURL &url, const TQString &lang ) +{ + mPayloadMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::payload( const TQString &lang ) const +{ + KURL payload = mPayloadMap[ lang ]; + if ( payload.isEmpty() ) { + TQStringList langs = TDEGlobal::locale()->languageList(); + for(TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPayloadMap[ *it ].isEmpty() ) return mPayloadMap[ *it ]; + } + if ( payload.isEmpty() ) payload = mPayloadMap [ TQString::null ]; + if ( payload.isEmpty() && !mPayloadMap.isEmpty() ) { + payload = *(mPayloadMap.begin()); + } + return payload; +} + + +void Entry::setPreview( const KURL &url, const TQString &lang ) +{ + mPreviewMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::preview( const TQString &lang ) const +{ + KURL preview = mPreviewMap[ lang ]; + if ( preview.isEmpty() ) { + TQStringList langs = TDEGlobal::locale()->languageList(); + for(TQStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPreviewMap[ *it ].isEmpty() ) return mPreviewMap[ *it ]; + } + if ( preview.isEmpty() ) preview = mPreviewMap [ TQString::null ]; + if ( preview.isEmpty() && !mPreviewMap.isEmpty() ) { + preview = *(mPreviewMap.begin()); + } + return preview; +} + + +void Entry::setRating( int rating ) +{ + mRating = rating; +} + +int Entry::rating() +{ + return mRating; +} + + +void Entry::setDownloads( int downloads ) +{ + mDownloads = downloads; +} + +int Entry::downloads() +{ + return mDownloads; +} + +TQString Entry::fullName() +{ + if ( version().isEmpty() ) + return name(); + else + return name() + "-" + version() + "-" + TQString::number( release() ); +} + +TQStringList Entry::langs() +{ + return mLangs; +} + +// FIXME +// It appears that OCS has removed the ability to retrieve author EMail; +// further confirmation is needed before removing EMail-related code +void Entry::parseDomElement( const TQDomElement &element ) +{ + if ( element.tagName() != "content" ) return; + mType = element.attribute("type"); + + TQDomNode n; + TQString lang; + for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + TQDomElement e = n.toElement(); + if ( e.tagName() == "language" ) + { + lang = e.text(); + } + } + if (lang == "") { + lang = TQString::null; + } + + for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + TQDomElement e = n.toElement(); + if ( e.tagName() == "name" ) + { + setName( e.text().stripWhiteSpace(), lang ); + setName( e.text().stripWhiteSpace() ); /* primary key - no i18n */ + } + if ( e.tagName() == "personid" ) { + setAuthor( e.text().stripWhiteSpace() ); +// TQString email = e.attribute( "email" ); +// setAuthorEmail( email ); + } +// if ( e.tagName() == "email" ) setAuthorEmail( e.text().stripWhiteSpace() ); /* kde-look; change on server! */ + if ( e.tagName() == "licence" ) setLicence( e.text().stripWhiteSpace() ); + if ( e.tagName() == "description" ) { + setSummary( e.text().stripWhiteSpace(), lang ); + } + if ( e.tagName() == "version" ) setVersion( e.text().stripWhiteSpace() ); +// if ( e.tagName() == "release" ) setRelease( e.text().toInt() ); + if ( e.tagName() == "created" ) { + TQDate date = TQT_TQDATE_OBJECT(TQDate::fromString( e.text().stripWhiteSpace(), Qt::ISODate )); + setReleaseDate( date ); + } + if ( e.tagName() == "smallpreviewpic1" ) { + setPreview( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "downloadlink1" ) { + setPayload( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "score" ) setRating( e.text().toInt() ); + if ( e.tagName() == "downloads" ) setDownloads( e.text().toInt() ); + } +} + +TQDomElement Entry::createDomElement( TQDomDocument &doc, + TQDomElement &parent ) +{ + TQDomElement entry = doc.createElement( "content" ); + entry.setAttribute("type", mType); + parent.appendChild( entry ); + + addElement( doc, entry, "language", langs().first() ); + + addElement( doc, entry, "name", name() ); + addElement( doc, entry, "personid", author() ); +// addElement( doc, entry, "email", authorEmail() ); + addElement( doc, entry, "licence", license() ); + addElement( doc, entry, "version", version() ); +// addElement( doc, entry, "release", TQString::number( release() ) ); + addElement( doc, entry, "score", TQString::number( rating() ) ); + addElement( doc, entry, "downloads", TQString::number( downloads() ) ); + + addElement( doc, entry, "created", + releaseDate().toString( Qt::ISODate ) ); + + addElement( doc, entry, "description", summary() ); + addElement( doc, entry, "preview", preview().url() ); + addElement( doc, entry, "payload", payload().url() ); + + return entry; +} + +TQDomElement Entry::addElement( TQDomDocument &doc, TQDomElement &parent, + const TQString &tag, const TQString &value ) +{ + TQDomElement n = doc.createElement( tag ); + n.appendChild( doc.createTextNode( value ) ); + parent.appendChild( n ); + + return n; +} diff --git a/tdenewstuff/entry.h b/tdenewstuff/entry.h new file mode 100644 index 000000000..e04822e39 --- /dev/null +++ b/tdenewstuff/entry.h @@ -0,0 +1,282 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_ENTRY_H +#define KNEWSTUFF_ENTRY_H + +#include +#include +#include +#include +#include + +#include + +namespace KNS { + +/** + * @short TDENewStuff data entry container. + * + * This class provides accessor methods to the data objects + * as used by TDENewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT Entry +{ + public: + Entry(); + /** + * Constructor. + */ + Entry( const TQDomElement & ); + + /** + * Destructor. + */ + ~Entry(); + + /** + * Sets the (unique) name for this data object. + */ + void setName( const TQString & ); + + /** + * Sets the (internationalised) name for this data object. + */ + void setName( const TQString &, const TQString & ); + + /** + * Retrieve the name of the data object. + * + * @return object name + */ + TQString name() const; + + /** + * Retrieve the internationalised name of the data object. + * + * @return object name (potentially translated) + */ + TQString name( const TQString &lang ) const; + + /** + * Sets the application type, e.g. 'kdesktop/wallpaper'. + */ + void setType( const TQString & ); + + /** + * Retrieve the type of the data object. + * + * @return object type + */ + TQString type() const; + + /** + * Sets the full name of the object's author. + */ + void setAuthor( const TQString & ); + + /** + * Retrieve the author's name of the object. + * + * @return object author + */ + TQString author() const; + + /** + * Sets the email address of the object's author. + */ + void setAuthorEmail( const TQString & ); + + /** + * Retrieve the author's email address of the object. + * + * @return object author email address + */ + TQString authorEmail() const; + + /** + * Sets the license (abbreviation) applicable to the object. + */ + void setLicence( const TQString & ); + + /** + * Retrieve the license name of the object. + * + * @return object license + */ + TQString license() const; + + /** + * Sets a short description on what the object is all about. + */ + void setSummary( const TQString &, const TQString &lang = TQString::null ); + + /** + * Retrieve a short description about the object. + * + * @param lang preferred language, or TQString::null for KDE default + * @return object description + */ + TQString summary( const TQString &lang = TQString::null ) const; + + /** + * Sets the version number. + */ + void setVersion( const TQString & ); + + /** + * Retrieve the version string of the object. + * + * @return object version + */ + TQString version() const; + + /** + * Sets the release number, which is increased for feature-equal objects + * with the same version number, but slightly updated contents. + */ + void setRelease( int ); + + /** + * Retrieve the release number of the object + * + * @return object release + */ + int release() const; + + /** + * Sets the release date. + */ + void setReleaseDate( const TQDate & ); + + /** + * Retrieve the date of the object's publication. + * + * @return object release date + */ + TQDate releaseDate() const; + + /** + * Sets the object's file. + */ + void setPayload( const KURL &, const TQString &lang = TQString::null ); + + /** + * Retrieve the file name of the object. + * + * @param lang preferred language, or TQString::null for KDE default + * @return object filename + */ + KURL payload( const TQString &lang = TQString::null ) const; + + /** + * Sets the object's preview file, if available. This should be a + * picture file. + */ + void setPreview( const KURL &, const TQString &lang = TQString::null ); + + /** + * Retrieve the file name of an image containing a preview of the object. + * + * @param lang preferred language, or TQString::null for KDE default + * @return object preview filename + */ + KURL preview( const TQString &lang = TQString::null ) const; + + /** + * Sets the rating between 0 (worst) and 10 (best). + * + * @internal + */ + void setRating( int ); + + /** + * Retrieve the rating for the object, which has been determined by its + * users and thus might change over time. + * + * @return object rating + */ + int rating(); + + /** + * Sets the number of downloads. + * + * @internal + */ + void setDownloads( int ); + + /** + * Retrieve the download count for the object, which has been determined + * by its hosting sites and thus might change over time. + * + * @return object download count + */ + int downloads(); + + /** + * Return the full name for the meta information. It is constructed as + * name-version-release. + */ + TQString fullName(); + + /** + * Return the list of languages this object supports. + */ + TQStringList langs(); + + /** + * @internal + */ + void parseDomElement( const TQDomElement & ); + + /** + * @internal + */ + TQDomElement createDomElement( TQDomDocument &, TQDomElement &parent ); + + protected: + TQDomElement addElement( TQDomDocument &doc, TQDomElement &parent, + const TQString &tag, const TQString &value ); + + private: + TQString mName; + TQString mType; + TQString mAuthor; + TQString mLicence; + TQMap mSummaryMap; + TQString mVersion; + int mRelease; + TQDate mReleaseDate; + TQMap mPayloadMap; + TQMap mPreviewMap; + int mRating; + int mDownloads; + + TQStringList mLangs; +}; + +} + +#endif diff --git a/tdenewstuff/ghns.cpp b/tdenewstuff/ghns.cpp new file mode 100644 index 000000000..3217de80e --- /dev/null +++ b/tdenewstuff/ghns.cpp @@ -0,0 +1,93 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "knewstuffgeneric.h" + +#include "ghns.h" + +using namespace std; + +GhnsWidget::GhnsWidget() +{ + mWallpapers = new TDENewStuffGeneric( "kdesktop/wallpaper", this ); + + TQBoxLayout *topLayout = new TQVBoxLayout( this ); + topLayout->setMargin( KDialog::marginHint() ); + topLayout->setSpacing( KDialog::spacingHint() ); + + topLayout->addWidget( new TQLabel( i18n("Get hot new stuff:"), this ) ); + + TQPushButton *button = new TQPushButton( "Wallpapers", this ); + topLayout->addWidget( button ); + connect( button, TQT_SIGNAL( clicked() ), TQT_SLOT( downloadWallpapers() ) ); + + topLayout->addSpacing( 5 ); + + TQBoxLayout *buttonLayout = new TQHBoxLayout( topLayout ); + + buttonLayout->addStretch(); + + TQPushButton *closeButton = new TQPushButton( "Close", this ); + buttonLayout->addWidget( closeButton ); + connect( closeButton, TQT_SIGNAL( clicked() ), kapp, TQT_SLOT( quit() ) ); +} + +GhnsWidget::~GhnsWidget() +{ + delete mWallpapers; +} + +void GhnsWidget::downloadWallpapers() +{ + kdDebug() << "downloadWallpapers()" << endl; + + mWallpapers->download(); +} + +int main(int argc,char **argv) +{ + TDEAboutData aboutData("ghns","Get Hot New Stuff","0.1"); + TDECmdLineArgs::init(argc,argv,&aboutData); + + TDEApplication app; + + GhnsWidget wid; + app.setMainWidget( &wid ); + wid.show(); + + app.exec(); +} + +#include "ghns.moc" diff --git a/tdenewstuff/ghns.h b/tdenewstuff/ghns.h new file mode 100644 index 000000000..7eea0c489 --- /dev/null +++ b/tdenewstuff/ghns.h @@ -0,0 +1,47 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef GHNS_H +#define GHNS_H + +#include + +#include + +#include +#include + +#include "knewstuff.h" + +class GhnsWidget : public TQWidget +{ + Q_OBJECT + public: + GhnsWidget(); + ~GhnsWidget(); + + public slots: + void downloadWallpapers(); + + private: + TDENewStuff *mWallpapers; +}; + +#endif diff --git a/tdenewstuff/knewstuff.cpp b/tdenewstuff/knewstuff.cpp new file mode 100644 index 000000000..ad4f0fb98 --- /dev/null +++ b/tdenewstuff/knewstuff.cpp @@ -0,0 +1,86 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "engine.h" + +#include "knewstuff.h" + +using namespace KNS; + +TDEAction* KNS::standardAction(const TQString& what, + const TQObject *recvr, + const char *slot, TDEActionCollection* parent, + const char *name) +{ + return new TDEAction(i18n("Download New %1").arg(what), "knewstuff", + 0, recvr, slot, parent, name); +} + +TDENewStuff::TDENewStuff( const TQString &type, TQWidget *parentWidget ) +{ + mEngine = new Engine( this, type, parentWidget ); +} + +TDENewStuff::TDENewStuff( const TQString &type, const TQString &providerList, TQWidget *parentWidget ) +{ + mEngine = new Engine( this, type, providerList, parentWidget ); +} + +TQString TDENewStuff::type() const +{ + return mEngine->type(); +} + +TQWidget *TDENewStuff::parentWidget() const +{ + return mEngine->parentWidget(); +} + +TDENewStuff::~TDENewStuff() +{ + delete mEngine; +} + +void TDENewStuff::download() +{ + mEngine->download(); +} + +TQString TDENewStuff::downloadDestination( Entry * ) +{ + return TDEGlobal::dirs()->saveLocation( "tmp" ) + + TDEApplication::randomString( 10 ); +} + +void TDENewStuff::upload() +{ + mEngine->upload(); +} + +void TDENewStuff::upload( const TQString &fileName, const TQString previewName ) +{ + mEngine->upload(fileName, previewName); +} diff --git a/tdenewstuff/knewstuff.h b/tdenewstuff/knewstuff.h new file mode 100644 index 000000000..55d6db9b4 --- /dev/null +++ b/tdenewstuff/knewstuff.h @@ -0,0 +1,161 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_H +#define KNEWSTUFF_H + +#include + +#include + +class TQObject; +class TQWidget; +class TDEAction; +class TDEActionCollection; + +namespace KNS { +class Engine; +class Entry; + +KDE_EXPORT TDEAction* standardAction(const TQString& what, + const TQObject *recvr, + const char *slot, + TDEActionCollection* parent, + const char *name = 0); +} + +/** + * @short This class provides the functionality to download and upload "new stuff". + * + * Applications have to subclass TDENewStuff, implement the pure virtual functions + * and link to against libknewstuff. + * + * By calling download() the download process is started which means that a list + * of "providers" is fetched from a "master server", information about new stuff + * is collected from the providers and presented to the user. Selected entries + * get downloaded and installed to the application. The required functions to + * install new stuff are provided by implementing install(). The location where + * the downloaded files are stored can be customized by reimplementing + * downloadDestination(). + * + * By calling upload() the upload process is started which means the user has to + * select a provider from the list fetched from the master server and to put in + * information about the entry to be uploaded. Then the file to be uploaded is + * fetched from the application by calling createUploadFile() and transfered to + * the upload destination specified in the provider list. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + * + * @since 3.3 + */ +class KDE_EXPORT TDENewStuff +{ + public: + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the TDENewStuff + engine + */ + TDENewStuff( const TQString &type, TQWidget *parentWidget = 0 ); + + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param providerList the URL of the provider list + @param parentWidget parent widget of dialogs opened by the TDENewStuff + engine + */ + TDENewStuff( const TQString &type, const TQString &providerList, TQWidget *parentWidget = 0 ); + virtual ~TDENewStuff(); + + /** + Return type of data. + */ + TQString type() const; + + /** + Return parent widget. + */ + TQWidget *parentWidget() const; + + /** + Start download process. + */ + void download(); + + /** + Start upload process. + */ + void upload(); + + /** + Upload with pre-defined files. + */ + void upload( const TQString &fileName, const TQString previewName ); + + /** + Install file to application. The given fileName points to the file + downloaded by the TDENewStuff engine. This is a temporary file by default. + The application can do whatever is needed to handle the information + contained in the file. + + The function returns true, when the installation + was successful and false if were errors. + + @param fileName name of downloaded file + */ + virtual bool install( const TQString &fileName ) = 0; + /** + Create a file to be uploaded to a "new stuff provider" and return the + filename. The format of the file is application specific. The only + constraint is that the corresponding install() implementation is able to + use the file. + + @param fileName name of the file to be written + @return @c true on success, @c false on error. + */ + virtual bool createUploadFile( const TQString &fileName ) = 0; + + /** + Return a filename which should be used as destination for downloading the + specified new stuff entry. Reimplement this function, if you don't want + the new stuff to be downloaded to a temporary file. + */ + virtual TQString downloadDestination( KNS::Entry *entry ); + + + protected: + /** + Get the pointer to the engine. Needed by subclasses to access the KNS::Engine object. + */ + KNS::Engine *engine() { return mEngine; } + + + private: + KNS::Engine *mEngine; +}; + +#endif diff --git a/tdenewstuff/knewstuffbutton.cpp b/tdenewstuff/knewstuffbutton.cpp new file mode 100644 index 000000000..3baa83397 --- /dev/null +++ b/tdenewstuff/knewstuffbutton.cpp @@ -0,0 +1,90 @@ +/* + Copyright (c) 2004 Aaron J. Seigo + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "downloaddialog.h" +#include "knewstuffbutton.h" +#include "knewstuffbutton.moc" + +namespace KNS +{ + +Button::Button(const TQString& what, + const TQString& providerList, + const TQString& resourceType, + TQWidget* parent, const char* name) + : KPushButton(parent, name), + d(0), + m_providerList(providerList), + m_type(resourceType), + m_downloadDialog(0) +{ + setButtonText(what); + init(); +} + +Button::Button(TQWidget* parent, const char* name) + : KPushButton(parent, name), + d(0), + m_downloadDialog(0) +{ + setButtonText(i18n("Download New Stuff")); + init(); +} + +void Button::init() +{ + setIconSet(SmallIconSet("knewstuff")); + connect(this, TQT_SIGNAL(clicked()), TQT_SLOT(showDialog())); +} + +void Button::setButtonText(const TQString& what) +{ + setText(i18n("Download New %1").arg(what)); +} + +void Button::setProviderList(const TQString& providerList) +{ + m_providerList = providerList; +} + +void Button::setResourceType(const TQString& resourceType) +{ + m_type = resourceType; +} + +void Button::showDialog() +{ + emit aboutToShowDialog(); + + if (!m_downloadDialog) + { + m_downloadDialog = new DownloadDialog(0, this); + } + + m_downloadDialog->setType(m_type); + m_downloadDialog->load(m_providerList); + + m_downloadDialog->exec(); // TODO: make non-modal? + emit dialogFinished(); +} + +} diff --git a/tdenewstuff/knewstuffbutton.h b/tdenewstuff/knewstuffbutton.h new file mode 100644 index 000000000..e4a98ae3a --- /dev/null +++ b/tdenewstuff/knewstuffbutton.h @@ -0,0 +1,115 @@ +/* + Copyright (c) 2004 Aaron J. Seigo + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _khotnewbutton_h +#define _khotnewbutton_h + +#include + +namespace KNS +{ + +class DownloadDialog; + +/** + * TDEHotNewStuff push button that makes using KHNS in an application + * more convenient by encapsulating most of the details involved in + * using TDEHotNewStuff in the button itself. + * + * @since 3.4 + */ +class Button : public KPushButton +{ + Q_OBJECT + + public: + /** + * Constructor used when the details of the TDEHotNewStuff + * download is known when the button is created. + * + * @param what text describing what is being downloaded. will be + * shown on the button as "Download New " + * @param providerList the URL to the list of providers; if empty + * we first try the ProvidersUrl from TDEGlobal::config, then we + * fall back to a hardcoded value + * @param resourceType the Hotstuff data type for this downlaod such + * as "korganizer/calendar" + * @param parent the parent widget + * @param name the name to be used for this widget + */ + Button(const TQString& what, + const TQString& providerList, + const TQString& resourceType, + TQWidget* parent, const char* name); + + /** + * Constructor used when the details of the TDEHotNewStuff + * download is not known in advance of the button being created. + * + * @param parent the parent widget + * @param name the name to be used for this widget + */ + Button(TQWidget* parent, const char* name); + + /** + * set the URL to the list of providers for this button to use + */ + void setProviderList(const TQString& providerList); + + /** + * the Hotstuff data type for this downlaod such as + * "korganizer/calendar" + */ + void setResourceType(const TQString& resourceType); + + /** + * set the text that should appear on the button. will be prefaced + * with i18n("Download New") + */ + void setButtonText(const TQString& what); + + signals: + /** + * emitted when the Hot New Stuff dialog is about to be shown, usually + * as a result of the user having click on the button + */ + void aboutToShowDialog(); + + /** + * emitted when the Hot New Stuff dialog has been closed + */ + void dialogFinished(); + + protected slots: + void showDialog(); + + private: + void init(); + + class ButtonPrivate; + ButtonPrivate* d; + + TQString m_providerList; + TQString m_type; + DownloadDialog* m_downloadDialog; +}; + +} + +#endif diff --git a/tdenewstuff/knewstuffgeneric.cpp b/tdenewstuff/knewstuffgeneric.cpp new file mode 100644 index 000000000..16fda977c --- /dev/null +++ b/tdenewstuff/knewstuffgeneric.cpp @@ -0,0 +1,146 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "entry.h" + +#include "knewstuffgeneric.h" + +using namespace std; + +TDENewStuffGeneric::TDENewStuffGeneric( const TQString &type, TQWidget *parent ) + : TDENewStuff( type, parent ) +{ + mConfig = TDEGlobal::config(); +} + +TDENewStuffGeneric::~TDENewStuffGeneric() +{ +} + +bool TDENewStuffGeneric::install( const TQString &fileName ) +{ + kdDebug() << "TDENewStuffGeneric::install(): " << fileName << endl; + TQStringList list, list2; + + mConfig->setGroup("TDENewStuff"); + + TQString uncompress = mConfig->readEntry( "Uncompress" ); + if ( !uncompress.isEmpty() ) { + kdDebug() << "Uncompression method: " << uncompress << endl; + KTar tar(fileName, uncompress); + tar.open(IO_ReadOnly); + const KArchiveDirectory *dir = tar.directory(); + dir->copyTo(destinationPath(0)); + tar.close(); + TQFile::remove(fileName); + } + + TQString cmd = mConfig->readEntry( "InstallationCommand" ); + if ( !cmd.isEmpty() ) { + kdDebug() << "InstallationCommand: " << cmd << endl; + list = TQStringList::split( " ", cmd ); + for ( TQStringList::iterator it = list.begin(); it != list.end(); ++it ) { + list2 << (*it).replace("%f", fileName); + } + TDEProcess proc; + proc << list2; + proc.start( TDEProcess::Block ); + } + + return true; +} + +bool TDENewStuffGeneric::createUploadFile( const TQString & /*fileName*/ ) +{ + return false; +} + +TQString TDENewStuffGeneric::destinationPath( KNS::Entry *entry ) +{ + TQString path, file, target, ext; + + mConfig->setGroup("TDENewStuff"); + + if ( entry ) + { + ext = entry->payload().fileName().section('.', 1); + if ( ! ext.isEmpty() ) ext = "." + ext; + + target = entry->fullName() + ext; + } + else target = "/"; + TQString res = mConfig->readEntry( "StandardResource" ); + if ( res.isEmpty() ) + { + target = mConfig->readEntry("TargetDir"); + if ( !target.isEmpty()) + { + res = "data"; + if ( entry ) target.append("/" + entry->fullName() + ext); + else target.append("/"); + } + } + if ( res.isEmpty() ) + { + path = mConfig->readEntry( "InstallPath" ); + } + if ( res.isEmpty() && path.isEmpty() ) + { + if ( !entry ) return TQString::null; + else return TDENewStuff::downloadDestination( entry ); + } + + if ( !path.isEmpty() ) + { + file = TQDir::home().path() + "/" + path + "/"; + if ( entry ) file += entry->fullName() + ext; + } + else file = locateLocal( res.utf8() , target ); + + return file; +} + +TQString TDENewStuffGeneric::downloadDestination( KNS::Entry *entry ) +{ + TQString file = destinationPath(entry); + + if ( TDEStandardDirs::exists( file ) ) { + int result = KMessageBox::warningContinueCancel( parentWidget(), + i18n("The file '%1' already exists. Do you want to overwrite it?") + .arg( file ), + TQString::null, i18n("Overwrite") ); + if ( result == KMessageBox::Cancel ) return TQString::null; + } + + return file; +} diff --git a/tdenewstuff/knewstuffgeneric.h b/tdenewstuff/knewstuffgeneric.h new file mode 100644 index 000000000..36feb1a77 --- /dev/null +++ b/tdenewstuff/knewstuffgeneric.h @@ -0,0 +1,86 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFFGENERIC_H +#define KNEWSTUFFGENERIC_H + +#include "knewstuff.h" + +class TDEConfig; + +/** + * @short Basic TDENewStuff class with predefined actions. + * + * This class is used for data uploads and installation. + * \code + * TQString payload, preview; + * TDENewStuffGeneric *ns = new TDENewStuffGeneric("kamikaze/level", this); + * ns->upload(payload, preview); + * \endcode + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT TDENewStuffGeneric : public TDENewStuff +{ + public: + /** + Constructor. + + @param type a Hotstuff data type such as "korganizer/calendar" + @param parent the parent window. + */ + TDENewStuffGeneric( const TQString &type, TQWidget *parent = 0 ); + ~TDENewStuffGeneric(); + + /** + Installs a downloaded file according to the application's configuration. + + @param fileName filename of the donwloaded file + @return @c true in case of installation success, @c false otherwise + */ + bool install( const TQString &fileName ); + + /** + Creates a file suitable for upload. + Note that this method always fails, since using TDENewStuffGeneric + means that the provided file must already be in a usable format. + + @param fileName the name of the file to upload after its creation + @return @c true in case of creation success, @c false otherwise + */ + bool createUploadFile( const TQString &fileName ); + + /** + Queries the preferred destination file for a download. + + @param entry a Hotstuff data entry + @return destination filename, or 0 to return directory only + */ + TQString downloadDestination( KNS::Entry *entry ); + + private: + TQString destinationPath( KNS::Entry *entry ); + + TDEConfig *mConfig; +}; + +#endif diff --git a/tdenewstuff/knewstuffsecure.cpp b/tdenewstuff/knewstuffsecure.cpp new file mode 100644 index 000000000..0f95c8c0c --- /dev/null +++ b/tdenewstuff/knewstuffsecure.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** + knewstuffsecure.cpp - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ +//qt includes +#include + +//kde includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//app includes +#include "engine.h" +#include "knewstuffsecure.h" +#include "security.h" + +using namespace KNS; + +TDENewStuffSecure::TDENewStuffSecure(const TQString &type, TQWidget *parentWidget) + : TDENewStuff(type, parentWidget) +{ + m_tempDir = 0L; + connect(engine(), TQT_SIGNAL(uploadFinished(bool)), TQT_SLOT(slotUploadFinished(bool))); +} + + +TDENewStuffSecure::~TDENewStuffSecure() +{ + removeTempDirectory(); +} + +bool TDENewStuffSecure::install(const TQString &fileName) +{ + bool ok = true; + + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + KTar tar(fileName, "application/x-gzip"); + if (tar.open(IO_ReadOnly)) + { + const KArchiveDirectory *directory = tar.directory(); + directory->copyTo(m_tempDir->name(), true); + m_tarName = ""; + TQStringList entries = directory->entries(); + for (TQStringList::Iterator it = entries.begin(); it != entries.end(); ++it) + { + if (*it != "signature" && *it != "md5sum") + { + m_tarName = *it; + break; + } + } + tar.close(); + if (m_tarName.isEmpty()) + ok = false; + else + { + m_tarName.prepend(m_tempDir->name()); + connect(Security::ref(), TQT_SIGNAL(validityResult(int)), this, TQT_SLOT(slotValidated(int))); + Security::ref()->checkValidity(m_tarName); + } + } else + ok = false; + if (!ok) + KMessageBox::error(parentWidget(), i18n("There was an error with the downloaded resource tarball file. Possible causes are damaged archive or invalid directory structure in the archive."), i18n("Resource Installation Error")); + return ok; +} + +void TDENewStuffSecure::slotValidated(int result) +{ + TQString errorString; + TQString signatureStr; + bool valid = true; + if (result == -1) + { + errorString ="
- " + i18n("No keys were found."); + valid = false; + } else + if (result == 0) + { + errorString ="
- " + i18n("The validation failed for unknown reason."); + valid = false; + } else + { + KeyStruct key = Security::ref()->signatureKey(); + if (!(result & Security::MD5_OK )) + { + errorString = "
- " + i18n("The MD5SUM check failed, the archive might be broken."); + valid = false; + } + if (result & Security::SIGNED_BAD) + { + errorString += "
- " + i18n("The signature is bad, the archive might be broken or altered."); + valid = false; + } + if (result & Security::SIGNED_OK) + { + if (result & Security::TRUSTED) + { + kdDebug() << "Signed and trusted " << endl; + } else + { + errorString += "
- " + i18n("The signature is valid, but untrusted."); + valid = false; + } + } + if (result & Security::UNKNOWN) + { + errorString += "
- " + i18n("The signature is unknown."); + valid = false; + } else + { + signatureStr = i18n("The resource was signed with key 0x%1, belonging to %2 <%3>.").arg(key.id.right(8)).arg(key.name).arg(key.mail); + } + } + if (!valid) + { + signatureStr.prepend( "
"); + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("There is a problem with the resource file you have downloaded. The errors are :%1
%2

Installation of the resource is not recommended.

Do you want to proceed with the installation?
").arg(errorString).arg(signatureStr), i18n("Problematic Resource File")) == KMessageBox::Continue) + valid = true; + } else + KMessageBox::information(parentWidget(), i18n("%1

Press OK to install it.
").arg(signatureStr), i18n("Valid Resource"), "Show Valid Signature Information"); + if (valid) + { + installResource(); + emit installFinished(); + } else + { + TDEConfig *cfg = TDEGlobal::config(); + cfg->deleteGroup("TDENewStuffStatus"); + cfg->setGroup("TDENewStuffStatus"); + for (TQMap::ConstIterator it = m_installedResources.constBegin(); it != m_installedResources.constEnd(); ++it) + { + cfg->writeEntry(it.key(), it.data()); + } + cfg->sync(); + } + removeTempDirectory(); + disconnect(Security::ref(), TQT_SIGNAL(validityResult(int)), this, TQT_SLOT(slotValidated(int))); +} + +void TDENewStuffSecure::downloadResource() +{ + TDEConfig *cfg = TDEGlobal::config(); + m_installedResources = cfg->entryMap("TDENewStuffStatus"); + engine()->ignoreInstallResult(true); + TDENewStuff::download(); +} + +bool TDENewStuffSecure::createUploadFile(const TQString &fileName) +{ + Q_UNUSED(fileName); + return true; +} + +void TDENewStuffSecure::uploadResource(const TQString& fileName) +{ + connect(Security::ref(), TQT_SIGNAL(fileSigned(int)), this, TQT_SLOT(slotFileSigned(int))); + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + TQFileInfo f(fileName); + m_signedFileName = m_tempDir->name() + "/" + f.fileName(); + TDEIO::NetAccess::file_copy(KURL::fromPathOrURL(fileName), KURL::fromPathOrURL(m_signedFileName), -1, true); + Security::ref()->signFile(m_signedFileName); +} + +void TDENewStuffSecure::slotFileSigned(int result) +{ + if (result == 0) + { + KMessageBox::error(parentWidget(), i18n("The signing failed for unknown reason.")); + } else + { + if (result & Security::BAD_PASSPHRASE) + { + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("There are no keys usable for signing or you did not entered the correct passphrase.\nProceed without signing the resource?")) == KMessageBox::Cancel) + { + disconnect(Security::ref(), TQT_SIGNAL(fileSigned(int)), this, TQT_SLOT(slotFileSigned(int))); + removeTempDirectory(); + return; + } + } + KTar tar(m_signedFileName + ".signed", "application/x-gzip"); + tar.open(IO_WriteOnly); + TQStringList files; + files << m_signedFileName; + files << m_tempDir->name() + "/md5sum"; + files << m_tempDir->name() + "/signature"; + + for (TQStringList::Iterator it_f = files.begin(); it_f != files.end(); ++it_f) + { + TQFile file(*it_f); + file.open(IO_ReadOnly); + TQByteArray bArray = file.readAll(); + tar.writeFile(TQFileInfo(file).fileName(), "user", "group", bArray.size(), bArray.data()); + file.close(); + } + tar.close(); + TDEIO::NetAccess::file_move(KURL::fromPathOrURL(m_signedFileName + ".signed"), KURL::fromPathOrURL(m_signedFileName), -1, true); + TDENewStuff::upload(m_signedFileName, TQString::null); + disconnect(Security::ref(), TQT_SIGNAL(fileSigned(int)), this, TQT_SLOT(slotFileSigned(int))); + } +} + +void TDENewStuffSecure::slotUploadFinished(bool result) +{ + Q_UNUSED(result); + removeTempDirectory(); +} + +void TDENewStuffSecure::removeTempDirectory() +{ + if (m_tempDir) + { + TDEIO::NetAccess::del(KURL().fromPathOrURL(m_tempDir->name()), parentWidget()); + delete m_tempDir; + m_tempDir = 0L; + } +} + +#include "knewstuffsecure.moc" diff --git a/tdenewstuff/knewstuffsecure.h b/tdenewstuff/knewstuffsecure.h new file mode 100644 index 000000000..1c292a9a8 --- /dev/null +++ b/tdenewstuff/knewstuffsecure.h @@ -0,0 +1,101 @@ +/*************************************************************************** + knewstuffsecure.h - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + +#ifndef KNEWSTUFFSECURE_H +#define KNEWSTUFFSECURE_H + +//qt includes +#include + +//kde includes +#include "knewstuff.h" + +class KTempDir; +/** +Makes possible downloading and installing signed resource files from a server. +You must subclass it and implement the @ref installResource() pure +virtual method to install a resource. For uploading you must create a resource +tarball (which is installabale by @ref installResource()) and call the +@ref uploadResource() method with this tarball as the argument. +Signing and verification is done by the gpg application, so the user must +have it installed, otherwise this class does not give any extra security compared +to the standard TDENewStuff class. + +@since 3.4 + +@author Andras Mantia +*/ +class KDE_EXPORT TDENewStuffSecure : public TQObject, public TDENewStuff +{ + Q_OBJECT + +public: + /** Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the TDENewStuff + engine + */ + TDENewStuffSecure(const TQString &type, TQWidget *parentWidget=0); + virtual ~TDENewStuffSecure(); + + /** Installs the downloaded resource. Do not call or reimplement directly. + It's reimplemented from TDENewStuff for internal reasons. + */ + bool install( const TQString &fileName ); + + /** Reimplemented for internal reasons. */ + bool createUploadFile(const TQString &fileName); + + /** Initiates a download. This is the method that must be called in + * order to download a signed resource. */ + void downloadResource(); + + /** Signs the file and uploads to the central server. + * @param fileName The file to be signed and uploaded + */ + void uploadResource(const TQString &fileName); + + +private slots: + /** Checks the validity of the downloaded tarball and installs it*/ + void slotValidated(int result); + /** The file is signed, so it can be uploaded.*/ + void slotFileSigned(int result); + /** Called when the upload has finished. + @param result the result of the upload + Be careful if you reimplement it, as it deletes the temporary directory + m_tempDir used for upload. You must also delete it (call the parent's method) + if you reimplement it. + */ + void slotUploadFinished(bool result); + +signals: + void installFinished(); + +protected: + /** Installs the resource specified by m_tarName. Implement it in the subclass. */ + virtual void installResource() = 0; + /** Removes the temporary directory m_tempDir. */ + void removeTempDirectory(); + + KTempDir *m_tempDir; + TQString m_tarName; + TQString m_signedFileName; + TQMap m_installedResources; +}; + +#endif diff --git a/tdenewstuff/provider.cpp b/tdenewstuff/provider.cpp new file mode 100644 index 000000000..4157c5025 --- /dev/null +++ b/tdenewstuff/provider.cpp @@ -0,0 +1,428 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "provider.h" +#include "provider.moc" + +using namespace KNS; + +// BCI for KDE 3.5 only + +class ProviderPrivate +{ + public: + ProviderPrivate(){} + KURL mDownloadUrlLatest; + KURL mDownloadUrlScore; + KURL mDownloadUrlDownloads; +}; + +static TQPtrDict *d_ptr_prov = 0; + +static ProviderPrivate *d_prov(const Provider *p) +{ + if(!d_ptr_prov) + { + d_ptr_prov = new TQPtrDict(); + d_ptr_prov->setAutoDelete(true); + } + ProviderPrivate *ret = d_ptr_prov->find((void*)p); + if(!ret) + { + ret = new ProviderPrivate(); + d_ptr_prov->replace((void*)p, ret); + } + return ret; +} + +KURL Provider::downloadUrlVariant( TQString variant ) const +{ + if((variant == "latest") && (d_prov(this)->mDownloadUrlLatest.isValid())) + return d_prov(this)->mDownloadUrlLatest; + if((variant == "score") && (d_prov(this)->mDownloadUrlScore.isValid())) + return d_prov(this)->mDownloadUrlScore; + if((variant == "downloads") && (d_prov(this)->mDownloadUrlDownloads.isValid())) + return d_prov(this)->mDownloadUrlDownloads; + + return mDownloadUrl; +} + +// BCI part ends here + +Provider::Provider( TQString type, TQWidget* parent ) : mNoUpload( false ), mParent( parent ), mLoaded( false ), mContentType( type ) +{ +} + +Provider::Provider( const TQDomElement &e, TQString type, TQWidget* parent ) : mNoUpload( false ), mParent( parent ), mLoaded( false ), mContentType( type ) +{ + parseDomElement( e ); +} + +Provider::~Provider() +{ + if (d_ptr_prov) + { + ProviderPrivate *p = d_ptr_prov->find(this); + if (p) + d_ptr_prov->remove(p); + + if (d_ptr_prov->isEmpty()) + { + delete d_ptr_prov; + d_ptr_prov = 0L; + } + } +} + +bool Provider::loaded() +{ + return mLoaded; +} + +void Provider::setName( const TQString &name ) +{ + mName = name; +} + +TQString Provider::name() const +{ + return mName; +} + + +void Provider::setIcon( const KURL &url ) +{ + mIcon = url; +} + +KURL Provider::icon() const +{ + return mIcon; +} + + +void Provider::setDownloadUrl( const KURL &url ) +{ + mDownloadUrl = url; +} + +KURL Provider::downloadUrl() const +{ + return mDownloadUrl; +} + + +void Provider::setUploadUrl( const KURL &url ) +{ + mUploadUrl = url; +} + +KURL Provider::uploadUrl() const +{ + return mUploadUrl; +} + + +void Provider::setNoUploadUrl( const KURL &url ) +{ + mNoUploadUrl = url; +} + +KURL Provider::noUploadUrl() const +{ + return mNoUploadUrl; +} + + +void Provider::setNoUpload( bool enabled ) +{ + mNoUpload = enabled; +} + +bool Provider::noUpload() const +{ + return mNoUpload; +} + +void Provider::parseDomElement( const TQDomElement &element ) +{ + bool contentAvailable = false; + + if ( element.tagName() != "provider" ) return; + + TQDomNode n; + for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + TQDomElement p = n.toElement(); + + if ( p.tagName() == "location" ) mBaseURL = p.text(); + if ( p.tagName() == "icon" ) { + KURL iconurl( p.text() ); + if(!iconurl.isValid()) iconurl.setPath( p.text() ); + setIcon( iconurl ); + } + + if ( p.tagName() == "noupload" ) setNoUpload( true ); + if ( p.tagName() == "name" ) setName( p.text().stripWhiteSpace() ); + + if ( p.tagName() == "services" ) { + TQDomNode n2; + for ( n2 = p.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + TQDomElement p = n2.toElement(); + + if ( p.tagName() == "content" ) contentAvailable = true; + } + } + } + + if (!mBaseURL.endsWith("/")) { + mBaseURL.append("/"); + } + + if (contentAvailable) { + // Load content type list + KURL contentTypeUrl( mBaseURL + "content/categories" ); + + kdDebug() << "Provider::parseDomElement(): contentTypeUrl: " << contentTypeUrl << endl; + + TDEIO::TransferJob *job = TDEIO::get( KURL( contentTypeUrl ), false, false ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotJobResult( TDEIO::Job * ) ) ); + connect( job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), + TQT_SLOT( slotJobData( TDEIO::Job *, const TQByteArray & ) ) ); + } +} + +TQDomElement Provider::createDomElement( TQDomDocument &doc, TQDomElement &parent ) +{ + TQDomElement entry = doc.createElement( "stuff" ); + parent.appendChild( entry ); + + TQDomElement n = doc.createElement( "name" ); + n.appendChild( doc.createTextNode( name() ) ); + entry.appendChild( n ); + + return entry; +} + +void Provider::slotJobData( TDEIO::Job *, const TQByteArray &data ) +{ + kdDebug() << "ProviderLoader::slotJobData()" << endl; + + if ( data.size() == 0 ) return; + + TQCString str( data, data.size() + 1 ); + + mJobData.append( TQString::fromUtf8( str ) ); +} + +void Provider::slotJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + if (mParent) { + job->showErrorDialog( mParent ); + } + return; + } + + kdDebug() << "--CONTENT-START--" << endl << mJobData << "--CONT_END--" + << endl; + + TQDomDocument doc; + if ( !doc.setContent( mJobData ) ) { + if (mParent) { + KMessageBox::error( mParent, i18n("Error parsing category list.") ); + } + return; + } + + TQDomElement categories = doc.documentElement(); + + if ( categories.isNull() ) { + kdDebug() << "No document in Content.xml." << endl; + } + + TQStringList desiredCategoryList; + TQString desiredCategories; + + TQDomNode n; + for ( n = categories.firstChild(); !n.isNull(); n = n.nextSibling() ) { + TQDomElement p = n.toElement(); + + if ( p.tagName() == "data" ) { + TQDomNode n2; + for ( n2 = p.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + TQDomElement p = n2.toElement(); + + if ( p.tagName() == "category" ) { + TQDomNode n3; + TQString id; + TQString name; + for ( n3 = p.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) { + TQDomElement p = n3.toElement(); + + if ( p.tagName() == "id" ) { + id = p.text(); + } + + if ( p.tagName() == "name" ) { + name = p.text(); + } + } + + if (mContentType == "") { + desiredCategoryList.append(id); + } + else { + if (name.lower().contains(mContentType.lower())) { + desiredCategoryList.append(id); + } + } + } + } + } + } + + desiredCategories = desiredCategoryList.join("x"); + + // int maxEntries = 10; + int maxEntries = 50; + + setDownloadUrl( KURL( mBaseURL ) ); + setUploadUrl( KURL( mBaseURL ) ); + setNoUploadUrl( KURL( mBaseURL ) ); + + d_prov(this)->mDownloadUrlLatest = KURL( mBaseURL + "content/data?categories=" + desiredCategories + "&search=&sortmode=new&page=1&pagesize=" + TQString("%1").arg(maxEntries) ); + d_prov(this)->mDownloadUrlScore = KURL( mBaseURL + "content/data?categories=" + desiredCategories + "&search=&sortmode=high&page=1&pagesize=" + TQString("%1").arg(maxEntries) ); + d_prov(this)->mDownloadUrlDownloads = KURL( mBaseURL + "content/data?categories=" + desiredCategories + "&search=&sortmode=down&page=1&pagesize=" + TQString("%1").arg(maxEntries) ); + + mLoaded = true; + emit providerLoaded(); +} + + +ProviderLoader::ProviderLoader( TQWidget *parentWidget ) : + TQObject( parentWidget ) +{ + mProviders.setAutoDelete( true ); +} + +void ProviderLoader::load( const TQString &type, const TQString &providersList ) +{ + kdDebug() << "ProviderLoader::load()" << endl; + + mProviders.clear(); + mJobData = ""; + mContentType = type; + + TDEConfig *cfg = TDEGlobal::config(); + cfg->setGroup("TDENewStuff"); + + TQString providersUrl = providersList; + if( providersUrl.isEmpty() ) + providersUrl = cfg->readEntry( "ProvidersUrl" ); + + if ( providersUrl.isEmpty() ) { + // TODO: Replace the default by the real one. + TQString server = cfg->readEntry( "MasterServer", + "https://www.trinitydesktop.org" ); + + providersUrl = server + "/ocs/" + type + "/providers.xml"; + } + + kdDebug() << "ProviderLoader::load(): providersUrl: " << providersUrl << endl; + + TDEIO::TransferJob *job = TDEIO::get( KURL( providersUrl ), false, false ); + connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), + TQT_SLOT( slotJobResult( TDEIO::Job * ) ) ); + connect( job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), + TQT_SLOT( slotJobData( TDEIO::Job *, const TQByteArray & ) ) ); + +// job->dumpObjectInfo(); +} + +void ProviderLoader::slotJobData( TDEIO::Job *, const TQByteArray &data ) +{ + kdDebug() << "ProviderLoader::slotJobData()" << endl; + + if ( data.size() == 0 ) return; + + TQCString str( data, data.size() + 1 ); + + mJobData.append( TQString::fromUtf8( str ) ); +} + +void ProviderLoader::slotJobResult( TDEIO::Job *job ) +{ + if ( job->error() ) { + job->showErrorDialog( TQT_TQWIDGET(parent()) ); + } + + kdDebug() << "--PROVIDERS-START--" << endl << mJobData << "--PROV_END--" + << endl; + + TQDomDocument doc; + if ( !doc.setContent( mJobData ) ) { + KMessageBox::error( TQT_TQWIDGET(parent()), i18n("Error parsing providers list.") ); + return; + } + + TQDomElement providers = doc.documentElement(); + + if ( providers.isNull() ) { + kdDebug() << "No document in Providers.xml." << endl; + } + + TQDomNode n; + for ( n = providers.firstChild(); !n.isNull(); n = n.nextSibling() ) { + TQDomElement p = n.toElement(); + + if ( p.tagName() == "provider" ) { + Provider* prov = new Provider( p, mContentType, TQT_TQWIDGET(parent()) ); + mProviders.append( prov ); + connect( prov, TQT_SIGNAL( providerLoaded() ), this, TQT_SLOT( providerLoaded() ) ); + } + } +} + +void ProviderLoader::providerLoaded() { + Provider* prov = NULL; + bool allLoaded = true; + for ( prov = mProviders.first(); prov; prov = mProviders.next() ) { + if (!prov->loaded()) { + allLoaded = false; + break; + } + } + + if (allLoaded) { + emit providersLoaded( &mProviders ); + } +} \ No newline at end of file diff --git a/tdenewstuff/provider.h b/tdenewstuff/provider.h new file mode 100644 index 000000000..130864158 --- /dev/null +++ b/tdenewstuff/provider.h @@ -0,0 +1,235 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + Copyright (c) 2014 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_PROVIDER_H +#define KNEWSTUFF_PROVIDER_H + +#include +#include +#include +#include +#include + +#include + +namespace TDEIO { class Job; } + +namespace KNS { + +/** + * @short TDENewStuff provider container. + * + * This class provides accessors for the provider object. + * as used by TDENewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT Provider : public TQObject +{ + Q_OBJECT + public: + typedef TQPtrList List; + + /** + * Constructor. + */ + Provider( TQString type = TQString::null, TQWidget* parent = 0 ); + + /** + * Constructor with XML feed. + */ + Provider( const TQDomElement &, TQString type = TQString::null, TQWidget* parent = 0 ); + + /** + * Destructor. + */ + virtual ~Provider(); + + /** + * @return provider load status + */ + bool loaded(); + + /** + * Sets the common name of the provider. + */ + void setName( const TQString & ); + + /** + * Retrieves the common name of the provider. + * + * @return provider name + */ + TQString name() const; + + /** + * Sets the download URL. + */ + void setDownloadUrl( const KURL & ); + + /** + * Retrieves the download URL. + * + * @return download URL + */ + KURL downloadUrl() const; + + /** + * Variant to retrieve 'tagged' download URLs. + * Variant can be one of 'score', 'downloads', 'latest'. + * + * @return download specific URL + */ + KURL downloadUrlVariant( TQString variant ) const; + + /** + * Sets the upload URL. + */ + void setUploadUrl( const KURL & ); + + /** + * Retrieves the upload URL. + * + * @return upload URL + */ + KURL uploadUrl() const; + + /** + * Sets the URL where a user is led if the provider does not support + * uploads. + * + * @see setNoUpload + */ + void setNoUploadUrl( const KURL & ); + + /** + * Retrieves the URL where a user is led if the provider does not + * support uploads. + * + * @return website URL + */ + KURL noUploadUrl() const; + + /** + * Indicate whether provider supports uploads. + */ + void setNoUpload( bool ); + + /** + * Query whether provider supports uploads. + * + * @return upload support status + */ + bool noUpload() const; + + /** + * Sets the URL for an icon for this provider. + * The icon should be in 32x32 format. If not set, the default icon + * of KDialogBase is used. + */ + void setIcon( const KURL & ); + + /** + * Retrieves the icon URL for this provider. + * + * @return icon URL + */ + KURL icon() const; + + protected: + void parseDomElement( const TQDomElement & ); + + TQDomElement createDomElement( TQDomDocument &, TQDomElement &parent ); + + protected slots: + void slotJobData( TDEIO::Job *, const TQByteArray & ); + void slotJobResult( TDEIO::Job * ); + + signals: + void providerLoaded(); + + private: + TQString mName; + KURL mDownloadUrl; + KURL mUploadUrl; + KURL mNoUploadUrl; + KURL mIcon; + bool mNoUpload; + TQString mJobData; + TQString mBaseURL; + TQWidget* mParent; + bool mLoaded; + TQString mContentType; +}; + +/** + * TDENewStuff provider loader. + * This class sets up a list of all possible providers by querying + * the main provider database for this specific application. + * It should probably not be used directly by the application. + */ +class KDE_EXPORT ProviderLoader : public TQObject +{ + Q_OBJECT + public: + /** + * Constructor. + * + * @param parentWidget the parent widget + */ + ProviderLoader( TQWidget *parentWidget ); + + /** + * Starts asynchronously loading the list of providers of the + * specified type. + * + * @param type data type such as 'kdesktop/wallpaper'. + * @param providerList the URl to the list of providers; if empty + * we first try the ProvidersUrl from TDEGlobal::config, then we + * fall back to a hardcoded value. + */ + void load( const TQString &type, const TQString &providerList = TQString::null ); + + signals: + /** + * Indicates that the list of providers has been successfully loaded. + */ + void providersLoaded( Provider::List * ); + + protected slots: + void slotJobData( TDEIO::Job *, const TQByteArray & ); + void slotJobResult( TDEIO::Job * ); + void providerLoaded(); + + private: + TQWidget *mParentWidget; + + TQString mJobData; + TQString mContentType; + + Provider::List mProviders; +}; + +} + +#endif diff --git a/tdenewstuff/providerdialog.cpp b/tdenewstuff/providerdialog.cpp new file mode 100644 index 000000000..f71558ecd --- /dev/null +++ b/tdenewstuff/providerdialog.cpp @@ -0,0 +1,95 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include +#include +#include + +#include "engine.h" +#include "provider.h" + +#include "providerdialog.h" +#include "providerdialog.moc" + +using namespace KNS; + +class ProviderItem : public TDEListViewItem +{ + public: + ProviderItem( TDEListView *parent, Provider *provider ) : + TDEListViewItem( parent ), mProvider( provider ) + { + setText( 0, provider->name() ); + } + + Provider *provider() { return mProvider; } + + private: + Provider *mProvider; +}; + +ProviderDialog::ProviderDialog( Engine *engine, TQWidget *parent ) : + KDialogBase( Plain, i18n("Hot New Stuff Providers"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + TQFrame *topPage = plainPage(); + + TQBoxLayout *topLayout = new TQVBoxLayout( topPage ); + + TQLabel *description = new TQLabel( i18n("Please select one of the providers listed below:"), topPage ); + topLayout->addWidget( description ); + + mListView = new TDEListView( topPage ); + mListView->addColumn( i18n("Name") ); + topLayout->addWidget( mListView ); +} + +void ProviderDialog::clear() +{ + mListView->clear(); +} + +void ProviderDialog::addProvider( Provider *provider ) +{ + new ProviderItem( mListView, provider ); + if ( mListView->childCount() == 1 ) { + mListView->setSelected(mListView->firstChild(), true); + } else if (mListView->childCount() > 1) { + mListView->setSelected(mListView->firstChild(), false); + } +} + +void ProviderDialog::slotOk() +{ + ProviderItem *item = static_cast( mListView->selectedItem() ); + if ( !item ) { + KMessageBox::error( this, i18n("No provider selected.") ); + return; + } + + mEngine->requestMetaInformation( item->provider() ); + + accept(); +} diff --git a/tdenewstuff/providerdialog.h b/tdenewstuff/providerdialog.h new file mode 100644 index 000000000..fe7652f14 --- /dev/null +++ b/tdenewstuff/providerdialog.h @@ -0,0 +1,76 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_PROVIDERDIALOG_H +#define KNEWSTUFF_PROVIDERDIALOG_H + +#include + +class TDEListView; + +namespace KNS { + +class Provider; +class Engine; + +/** + * @short Dialog displaying a list of Hotstuff providers. + * + * This is normally used in the process of uploading data, thus limiting the + * list to providers which support uploads. + * One of the providers is then chosen by the user for further operation. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class ProviderDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a TDENewStuff engine object + @param parent the parent window + */ + ProviderDialog( Engine *engine, TQWidget *parent ); + + /** + Clears the list of providers. + */ + void clear(); + + /** + Adds a Hotstuff provider to the list. + */ + void addProvider( Provider * ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + TDEListView *mListView; +}; + +} + +#endif diff --git a/tdenewstuff/security.cpp b/tdenewstuff/security.cpp new file mode 100644 index 000000000..d161c2969 --- /dev/null +++ b/tdenewstuff/security.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + security.cpp - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + + //qt includes +#include +#include +#include +#include + + //kde includes +#include +#include +#include +#include +#include +#include +#include + + //app includes +#include "security.h" + +using namespace KNS; + +Security::Security() +{ + m_keysRead = false; + m_gpgRunning = false; + readKeys(); + readSecretKeys(); +} + + +Security::~Security() +{ +} + +void Security::readKeys() +{ + if (m_gpgRunning) + { + TQTimer::singleShot(5, this, TQT_SLOT(readKeys())); + return; + } + m_runMode = List; + m_keys.clear(); + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys"; + connect(readProcess, TQT_SIGNAL(processExited(TDEProcess *)), this, TQT_SLOT(slotProcessExited(TDEProcess *))); + connect(readProcess, TQT_SIGNAL(readReady(KProcIO *)) ,this, TQT_SLOT(slotDataArrived(KProcIO *))); + if (!readProcess->start(TDEProcess::NotifyOnExit, true)) + KMessageBox::error(0L, i18n("Cannot start gpg and retrieve the available keys. Make sure that gpg is installed, otherwise verification of downloaded resources will not be possible.")); + else + m_gpgRunning = true; +} + +void Security::readSecretKeys() +{ + if (m_gpgRunning) + { + TQTimer::singleShot(5, this, TQT_SLOT(readSecretKeys())); + return; + } + m_runMode = ListSecret; + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-secret-keys"; + connect(readProcess, TQT_SIGNAL(processExited(TDEProcess *)), this, TQT_SLOT(slotProcessExited(TDEProcess *))); + connect(readProcess, TQT_SIGNAL(readReady(KProcIO *)) ,this, TQT_SLOT(slotDataArrived(KProcIO *))); + if (readProcess->start(TDEProcess::NotifyOnExit, true)) + m_gpgRunning = true; +} + +void Security::slotProcessExited(TDEProcess *process) +{ + switch (m_runMode) + { + case ListSecret: + m_keysRead = true; + break; + case Verify: emit validityResult(m_result); + break; + case Sign: emit fileSigned(m_result); + break; + + } + m_gpgRunning = false; + delete process; +} + +void Security::slotDataArrived(KProcIO *procIO) +{ + TQString data; + while (procIO->readln(data, true) != -1) + { + switch (m_runMode) + { + case List: + case ListSecret: + if (data.startsWith("pub") || data.startsWith("sec")) + { + KeyStruct key; + if (data.startsWith("pub")) + key.secret = false; + else + key.secret = true; + TQStringList line = TQStringList::split(":", data, true); + key.id = line[4]; + TQString shortId = key.id.right(8); + TQString trustStr = line[1]; + key.trusted = false; + if (trustStr == "u" || trustStr == "f") + key.trusted = true; + data = line[9]; + key.mail=data.section('<', -1, -1); + key.mail.truncate(key.mail.length() - 1); + key.name=data.section('<',0,0); + if (key.name.find("(")!=-1) + key.name=key.name.section('(',0,0); + m_keys[shortId] = key; + } + break; + case Verify: + data = TQString(data.section("]",1,-1)).stripWhiteSpace(); + if (data.startsWith("GOODSIG")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= SIGNED_OK; + TQString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("NO_PUBKEY")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= UNKNOWN; + } else + if (data.startsWith("BADSIG")) + { + m_result |= SIGNED_BAD; + TQString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("TRUST_ULTIMATE")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= TRUSTED; + } + break; + + case Sign: + if (data.find("passphrase.enter") != -1) + { + TQCString password; + KeyStruct key = m_keys[m_secretKey]; + int result = KPasswordDialog::getPassword(password, i18n("Enter passphrase for key 0x%1, belonging to
%2<%3>:
").arg(m_secretKey).arg(key.name).arg(key.mail)); + if (result == KPasswordDialog::Accepted) + { + procIO->writeStdin(password, true); + password.fill(' '); + } + else + { + m_result |= BAD_PASSPHRASE; + slotProcessExited(procIO); + return; + } + } else + if (data.find("BAD_PASSPHRASE") != -1) + { + m_result |= BAD_PASSPHRASE; + } + break; + } + } +} + +void Security::checkValidity(const TQString& filename) +{ + m_fileName = filename; + slotCheckValidity(); +} + +void Security::slotCheckValidity() +{ + if (!m_keysRead || m_gpgRunning) + { + TQTimer::singleShot(5, this, TQT_SLOT(slotCheckValidity())); + return; + } + if (m_keys.count() == 0) + { + emit validityResult(-1); + return; + } + + m_result = 0; + m_runMode = Verify; + TQFileInfo f(m_fileName); + //check the MD5 sum + TQString md5sum; + const char* c = ""; + KMD5 context(c); + TQFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(TQT_TQIODEVICE_OBJECT(file)); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_ReadOnly)) + { + TQString md5sum_file; + file.readLine(md5sum_file, 50); + if (!md5sum.isEmpty() && !md5sum_file.isEmpty() && md5sum_file.startsWith(md5sum)) + m_result |= MD5_OK; + file.close(); + } + m_result |= SIGNED_BAD; + m_signatureKey.id = ""; + m_signatureKey.name = ""; + m_signatureKey.mail = ""; + m_signatureKey.trusted = false; + + //verify the signature + KProcIO *verifyProcess=new KProcIO(); + *verifyProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--verify" << f.dirPath() + "/signature"<< m_fileName; + connect(verifyProcess, TQT_SIGNAL(processExited(TDEProcess *)),this, TQT_SLOT(slotProcessExited(TDEProcess *))); + connect(verifyProcess, TQT_SIGNAL(readReady(KProcIO *)),this, TQT_SLOT(slotDataArrived(KProcIO *))); + if (verifyProcess->start(TDEProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("Cannot start gpg and check the validity of the file. Make sure that gpg is installed, otherwise verification of downloaded resources will not be possible.")); + emit validityResult(0); + delete verifyProcess; + } +} + +void Security::signFile(const TQString &fileName) +{ + m_fileName = fileName; + slotSignFile(); +} + +void Security::slotSignFile() +{ + if (!m_keysRead || m_gpgRunning) + { + TQTimer::singleShot(5, this, TQT_SLOT(slotSignFile())); + return; + } + + TQStringList secretKeys; + for (TQMap::Iterator it = m_keys.begin(); it != m_keys.end(); ++it) + { + if (it.data().secret) + secretKeys.append(it.key()); + } + + if (secretKeys.count() == 0) + { + emit fileSigned(-1); + return; + } + + m_result = 0; + TQFileInfo f(m_fileName); + + //create the MD5 sum + TQString md5sum; + const char* c = ""; + KMD5 context(c); + TQFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(TQT_TQIODEVICE_OBJECT(file)); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_WriteOnly)) + { + TQTextStream stream(&file); + stream << md5sum; + m_result |= MD5_OK; + file.close(); + } + + if (secretKeys.count() > 1) + { + bool ok; + secretKeys = KInputDialog::getItemList(i18n("Select Signing Key"), i18n("Key used for signing:"), secretKeys, secretKeys[0], false, &ok); + if (ok) + m_secretKey = secretKeys[0]; + else + { + emit fileSigned(0); + return; + } + } else + m_secretKey = secretKeys[0]; + + //verify the signature + KProcIO *signProcess=new KProcIO(); + *signProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--no-tty"<<"--detach-sign" << "-u" << m_secretKey << "-o" << f.dirPath() + "/signature" << m_fileName; + connect(signProcess, TQT_SIGNAL(processExited(TDEProcess *)),this, TQT_SLOT(slotProcessExited(TDEProcess *))); + connect(signProcess, TQT_SIGNAL(readReady(KProcIO *)),this, TQT_SLOT(slotDataArrived(KProcIO *))); + m_runMode = Sign; + if (signProcess->start(TDEProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("Cannot start gpg and sign the file. Make sure that gpg is installed, otherwise signing of the resources will not be possible.")); + emit fileSigned(0); + delete signProcess; + } +} + +#include "security.moc" diff --git a/tdenewstuff/security.h b/tdenewstuff/security.h new file mode 100644 index 000000000..230821e7e --- /dev/null +++ b/tdenewstuff/security.h @@ -0,0 +1,141 @@ +/*************************************************************************** + security.h - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + + +#ifndef SECURITY_H +#define SECURITY_H + +//qt includes +#include +#include + +class KProcIO; +class TDEProcess; + +struct KeyStruct { + TQString id; + TQString name; + TQString mail; + bool trusted; + bool secret; +}; + +/** +Handles security releated issues, like signing, verifying. +It is a private class, not meant to be used by third party applications. + +@author Andras Mantia +*/ + +namespace KNS { + +class Security : public TQObject +{ +Q_OBJECT +public: + static Security* const ref() + { + static Security *m_ref; + if (!m_ref) m_ref = new Security(); + return m_ref; + } + ~Security(); + + + /** Verifies the integrity and the signature of a tarball file. + * @param fileName the file to be verified. It should be a tar.gz (.tgz) file. The directory where + * the file is should contain a "signature" and a "md5sum" file, otherwise verification will fail. + * The method is asynchronous and the result is signalled with @ref validityResult. + */ + void checkValidity(const TQString &fileName); + + /** Creates a signature and an md5sum file for the fileName and packs + * everything into a gzipped tarball. + * @param fileName the file with full path to sign + * + * The method is asynchronous and the result is signalled with @ref fileSigned. + */ + void signFile(const TQString &fileName); + /** Get the key used for signing. This method is valid only if: + * - the checkValidity was called + * - the result of the validity check does not have the UNKNOWN bit set + * + * @return the key used for signing the file + */ + KeyStruct signatureKey() {return m_signatureKey;} + + enum Results { + MD5_OK = 1, /// The MD5 sum check is OK + SIGNED_OK = 2, /// The file is signed with a good signature + SIGNED_BAD = 4, /// The file is signed with a bad signature + TRUSTED = 8, /// The signature is trusted + UNKNOWN = 16, ///The key is unknown + SIGNED_BAD_CLEAR = 27, ///used to clear the SIGNED_BAD flag + BAD_PASSPHRASE = 32 ///wrong passhprase entered + }; + +public slots: + /** Reads the available public keys */ + void readKeys(); + /** Reads the available secret keys */ + void readSecretKeys(); + /** Verifies the integrity and the signature of a tarball file (see m_fileName). + */ + void slotCheckValidity(); + + /** Creates a signature and an md5sum file for the m_fileName and packs + * everything into a gzipped tarball. + */ + void slotSignFile(); + +private: + Security(); + + enum RunMode { + List = 0, ///read the public keys + ListSecret, ///read the secret keys + Verify, ///verify the signature + Sign ///create signature + }; + + KeyStruct m_signatureKey; + int m_result; + int m_runMode; + bool m_gpgRunning; /// true if gpg is currently running + bool m_keysRead; /// true if all the keys were read + TQMap m_keys; /// holds information about the available key + TQString m_fileName; /// the file to sign/verify + TQString m_secretKey; /// the key used for signing + +private slots: + void slotProcessExited(TDEProcess *process); + void slotDataArrived(KProcIO *process); + +signals: + /** Sent when the validity check is done. + * + * @return the result of the check. See @ref Results + */ + void validityResult(int result); + /** Sent when the signing is done. + * + * @return the result of the operation. See @ref Results + */ + void fileSigned(int result); +}; + +} + +#endif diff --git a/tdenewstuff/tdehotnewstuff.cpp b/tdenewstuff/tdehotnewstuff.cpp new file mode 100644 index 000000000..7f4135b84 --- /dev/null +++ b/tdenewstuff/tdehotnewstuff.cpp @@ -0,0 +1,55 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "downloaddialog.h" + +static const TDECmdLineOptions op[] = +{ + {"type ", I18N_NOOP("Display only media of this type"), 0}, + {"+[providerlist]", I18N_NOOP("Provider list to use"), 0}, + TDECmdLineLastOption +}; + +int main(int argc, char **argv) +{ + TDEAboutData about("tdehotnewstuff", "TDEHotNewStuff", "0.2"); + TDECmdLineArgs *args; + + TDECmdLineArgs::init(argc, argv, &about); + TDECmdLineArgs::addCmdLineOptions(op); + args = TDECmdLineArgs::parsedArgs(); + + TDEApplication i; + + KNS::DownloadDialog d; + if(args->isSet("type")) d.setType(args->getOption("type")); + if(args->count() == 1) d.setProviderList(args->arg(0)); + d.load(); + d.exec(); + + return 0; +} + diff --git a/tdenewstuff/tdehotnewstuffrc b/tdenewstuff/tdehotnewstuffrc new file mode 100644 index 000000000..546ebb053 --- /dev/null +++ b/tdenewstuff/tdehotnewstuffrc @@ -0,0 +1,3 @@ +[TDENewStuff] +ProvidersUrl=https://www.trinitydesktop.org/ocs/providers.xml + diff --git a/tdenewstuff/testnewstuff.cpp b/tdenewstuff/testnewstuff.cpp new file mode 100644 index 000000000..f9fc7269f --- /dev/null +++ b/tdenewstuff/testnewstuff.cpp @@ -0,0 +1,120 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "testnewstuff.h" +#include "testnewstuff.moc" + +using namespace std; + +bool TestNewStuff::install( const TQString &fileName ) +{ + kdDebug() << "TestNewStuff::install(): " << fileName << endl; + TQFile f( fileName ); + if ( !f.open( IO_ReadOnly ) ) { + kdDebug() << "Error opening file." << endl; + return false; + } + TQTextStream ts( &f ); + kdDebug() << "--BEGIN-NEW_STUFF--" << endl; + cout << ts.read().utf8(); + kdDebug() << "---END-NEW_STUFF---" << endl; + return true; +} + +bool TestNewStuff::createUploadFile( const TQString &fileName ) +{ + TDEProcess p; + p << "touch" << fileName; + p.start(TDEProcess::Block); + kdDebug() << "TestNewStuff::createUploadFile(): " << fileName << endl; + return true; +} + + +MyWidget::MyWidget() +{ + mNewStuff = new TestNewStuff; + + TQBoxLayout *topLayout = new TQVBoxLayout( this ); + topLayout->setMargin( KDialog::marginHint() ); + topLayout->setSpacing( KDialog::spacingHint() ); + + TQPushButton *downloadButton = new TQPushButton( "Download", this ); + topLayout->addWidget( downloadButton ); + connect( downloadButton, TQT_SIGNAL( clicked() ), TQT_SLOT( download() ) ); + + TQPushButton *uploadButton = new TQPushButton( "Upload", this ); + topLayout->addWidget( uploadButton ); + connect( uploadButton, TQT_SIGNAL( clicked() ), TQT_SLOT( upload() ) ); + + topLayout->addSpacing( 5 ); + + TQPushButton *closeButton = new TQPushButton( "Close", this ); + topLayout->addWidget( closeButton ); + connect( closeButton, TQT_SIGNAL( clicked() ), kapp, TQT_SLOT( quit() ) ); +} + +MyWidget::~MyWidget() +{ + delete mNewStuff; +} + +void MyWidget::download() +{ + kdDebug() << "MyWidget::download()" << endl; + + mNewStuff->download(); +} + +void MyWidget::upload() +{ + kdDebug() << "MyWidget::download()" << endl; + + mNewStuff->upload(); +} + + +int main(int argc,char **argv) +{ + TDEAboutData aboutData("knewstufftest","TDENewStuff Test","0.1"); + TDECmdLineArgs::init(argc,argv,&aboutData); + + TDEApplication app; + + MyWidget wid; + app.setMainWidget( &wid ); + wid.show(); + + app.exec(); +} diff --git a/tdenewstuff/testnewstuff.h b/tdenewstuff/testnewstuff.h new file mode 100644 index 000000000..acd9aece4 --- /dev/null +++ b/tdenewstuff/testnewstuff.h @@ -0,0 +1,58 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef TESTNEWSTUFF_H +#define TESTNEWSTUFF_H + +#include + +#include + +#include +#include + +#include "knewstuff.h" + +class TestNewStuff : public TDENewStuff +{ + public: + TestNewStuff() : TDENewStuff( "korganizer/calendar" ) {} + + bool install( const TQString &fileName ); + + bool createUploadFile( const TQString &fileName ); +}; + +class MyWidget : public TQWidget +{ + Q_OBJECT + public: + MyWidget(); + ~MyWidget(); + + public slots: + void upload(); + void download(); + + private: + TDENewStuff *mNewStuff; +}; + +#endif diff --git a/tdenewstuff/types b/tdenewstuff/types new file mode 100644 index 000000000..6f47cbf63 --- /dev/null +++ b/tdenewstuff/types @@ -0,0 +1,7 @@ +[kdesktop/wallpaper] +StandardResource=wallpaper +InstallationCommand=dcop kdesktop KBackgroundIface setWallpaper %f 2 + +[kamikaze/level] +TargetDir=kamikaze + diff --git a/tdenewstuff/uploaddialog.cpp b/tdenewstuff/uploaddialog.cpp new file mode 100644 index 000000000..a8e13a493 --- /dev/null +++ b/tdenewstuff/uploaddialog.cpp @@ -0,0 +1,206 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "engine.h" +#include "entry.h" + +#include "uploaddialog.h" +#include "uploaddialog.moc" + +using namespace KNS; + +UploadDialog::UploadDialog( Engine *engine, TQWidget *parent ) : + KDialogBase( Plain, i18n("Share Hot New Stuff"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + mEntryList.setAutoDelete( true ); + + TQFrame *topPage = plainPage(); + + TQGridLayout *topLayout = new TQGridLayout( topPage ); + topLayout->setSpacing( spacingHint() ); + + TQLabel *nameLabel = new TQLabel( i18n("Name:"), topPage ); + topLayout->addWidget( nameLabel, 0, 0 ); + mNameEdit = new TQLineEdit( topPage ); + topLayout->addWidget( mNameEdit, 0, 1 ); + + TQLabel *authorLabel = new TQLabel( i18n("Author:"), topPage ); + topLayout->addWidget( authorLabel, 1, 0 ); + mAuthorEdit = new TQLineEdit( topPage ); + topLayout->addWidget( mAuthorEdit, 1, 1 ); + + TQLabel *emailLabel = new TQLabel( i18n("Email:"), topPage ); + topLayout->addWidget( emailLabel, 2, 0 ); + mEmailEdit = new TQLineEdit( topPage ); + topLayout->addWidget( mEmailEdit, 2, 1 ); + + TQLabel *versionLabel = new TQLabel( i18n("Version:"), topPage ); + topLayout->addWidget( versionLabel, 3, 0 ); + mVersionEdit = new TQLineEdit( topPage ); + topLayout->addWidget( mVersionEdit, 3, 1 ); + + TQLabel *releaseLabel = new TQLabel( i18n("Release:"), topPage ); + topLayout->addWidget( releaseLabel, 4, 0 ); + mReleaseSpin = new TQSpinBox( topPage ); + mReleaseSpin->setMinValue( 1 ); + topLayout->addWidget( mReleaseSpin, 4, 1 ); + + TQLabel *licenceLabel = new TQLabel( i18n("License:"), topPage ); + topLayout->addWidget( licenceLabel, 5, 0 ); + mLicenceCombo = new TQComboBox( topPage ); + mLicenceCombo->setEditable( true ); + mLicenceCombo->insertItem( i18n("GPL") ); + mLicenceCombo->insertItem( i18n("LGPL") ); + mLicenceCombo->insertItem( i18n("BSD") ); + topLayout->addWidget( mLicenceCombo, 5, 1 ); + + TQLabel *languageLabel = new TQLabel( i18n("Language:"), topPage ); + topLayout->addWidget( languageLabel, 6, 0 ); + mLanguageCombo = new TQComboBox( topPage ); + topLayout->addWidget( mLanguageCombo, 6, 1 ); + mLanguageCombo->insertStringList( TDEGlobal::locale()->languageList() ); + + TQLabel *previewLabel = new TQLabel( i18n("Preview URL:"), topPage ); + topLayout->addWidget( previewLabel, 7, 0 ); + mPreviewUrl = new KURLRequester( topPage ); + topLayout->addWidget( mPreviewUrl, 7, 1 ); + + TQLabel *summaryLabel = new TQLabel( i18n("Summary:"), topPage ); + topLayout->addMultiCellWidget( summaryLabel, 8, 8, 0, 1 ); + mSummaryEdit = new KTextEdit( topPage ); + topLayout->addMultiCellWidget( mSummaryEdit, 9, 9, 0, 1 ); + + KUser user; + mAuthorEdit->setText(user.fullName()); +} + +UploadDialog::~UploadDialog() +{ + mEntryList.clear(); +} + +void UploadDialog::slotOk() +{ + if ( mNameEdit->text().isEmpty() ) { + KMessageBox::error( this, i18n("Please put in a name.") ); + return; + } + + Entry *entry = new Entry; + + mEntryList.append( entry ); + + entry->setName( mNameEdit->text() ); + entry->setAuthor( mAuthorEdit->text() ); + entry->setAuthorEmail( mEmailEdit->text() ); + entry->setVersion( mVersionEdit->text() ); + entry->setRelease( mReleaseSpin->value() ); + entry->setLicence( mLicenceCombo->currentText() ); + entry->setPreview( KURL( mPreviewUrl->url().section("/", -1) ), mLanguageCombo->currentText() ); + entry->setSummary( mSummaryEdit->text(), mLanguageCombo->currentText() ); + + if ( mPayloadUrl.isValid() ) { + TDEConfig *conf = kapp->config(); + conf->setGroup( TQString("TDENewStuffUpload:%1").arg(mPayloadUrl.fileName()) ); + conf->writeEntry("name", mNameEdit->text()); + conf->writeEntry("author", mAuthorEdit->text()); + conf->writeEntry("email", mEmailEdit->text()); + conf->writeEntry("version", mVersionEdit->text()); + conf->writeEntry("release", mReleaseSpin->value()); + conf->writeEntry("licence", mLicenceCombo->currentText()); + conf->writeEntry("preview", mPreviewUrl->url()); + conf->writeEntry("summary", mSummaryEdit->text()); + conf->writeEntry("language", mLanguageCombo->currentText()); + conf->sync(); + } + + mEngine->upload( entry ); + + accept(); +} + +void UploadDialog::setPreviewFile( const TQString &previewFile ) +{ + mPreviewUrl->setURL( previewFile ); +} + +void UploadDialog::setPayloadFile( const TQString &payloadFile ) +{ + mPayloadUrl = payloadFile; + + TDEConfig *conf = kapp->config(); + conf->setGroup( TQString("TDENewStuffUpload:%1").arg(mPayloadUrl.fileName()) ); + TQString name = conf->readEntry("name"); + TQString author = conf->readEntry("author"); + TQString email = conf->readEntry("email"); + TQString version = conf->readEntry("version"); + TQString release = conf->readEntry("release"); + TQString preview = conf->readEntry("preview"); + TQString summary = conf->readEntry("summary"); + TQString lang = conf->readEntry("language"); + TQString licence = conf->readEntry("licence"); + + mNameEdit->clear(); + mAuthorEdit->clear(); + mEmailEdit->clear(); + mVersionEdit->clear(); + mReleaseSpin->setValue(1); + mPreviewUrl->clear(); + mSummaryEdit->clear(); + mLanguageCombo->setCurrentItem(0); + mLicenceCombo->setCurrentItem(0); + + if(!name.isNull()) + { + int prefill = KMessageBox::questionYesNo(this, i18n("Old upload information found, fill out fields?"),TQString::null,i18n("Fill Out"),i18n("Do Not Fill Out")); + if(prefill == KMessageBox::Yes) + { + mNameEdit->setText(name); + mAuthorEdit->setText(author); + mEmailEdit->setText(email); + mVersionEdit->setText(version); + mReleaseSpin->setValue(release.toInt()); + mPreviewUrl->setURL(preview); + mSummaryEdit->setText(summary); + if(!lang.isEmpty()) mLanguageCombo->setCurrentText(lang); + if(!licence.isEmpty()) mLicenceCombo->setCurrentText(licence); + } + } +} + diff --git a/tdenewstuff/uploaddialog.h b/tdenewstuff/uploaddialog.h new file mode 100644 index 000000000..3fc068e3a --- /dev/null +++ b/tdenewstuff/uploaddialog.h @@ -0,0 +1,103 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_UPLOADDIALOG_H +#define KNEWSTUFF_UPLOADDIALOG_H + +#include + +class TQLineEdit; +class TQSpinBox; +class KURLRequester; +class TQTextEdit; +class TQComboBox; + +namespace KNS { + +class Engine; +class Entry; + +/** + * @short TDENewStuff file upload dialog. + * + * Using this dialog, data can easily be uploaded to the Hotstuff servers. + * It should however not be used on its own, instead a TDENewStuff (or + * TDENewStuffGeneric) object invokes it. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class UploadDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a TDENewStuff engine object to be used for uploads + @param parent the parent window + */ + UploadDialog( Engine *engine, TQWidget *parent ); + + /** + Destructor. + */ + ~UploadDialog(); + + /** + Sets the preview filename. + This is only meaningful if the application supports previews. + + @param previewFile the preview image file + */ + void setPreviewFile( const TQString &previewFile ); + + /** + Sets the payload filename. + This is optional, but necessary if the application wants to support + reusing previously filled out form data based on the filename. + + @param payloadFile the payload data file + */ + void setPayloadFile( const TQString &payloadFile ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + TQLineEdit *mNameEdit; + TQLineEdit *mAuthorEdit; + TQLineEdit *mEmailEdit; + TQLineEdit *mVersionEdit; + TQSpinBox *mReleaseSpin; + KURLRequester *mPreviewUrl; + TQTextEdit *mSummaryEdit; + TQComboBox *mLanguageCombo; + TQComboBox *mLicenceCombo; + + TQPtrList mEntryList; + KURL mPayloadUrl; +}; + +} + +#endif -- cgit v1.2.1