KNewStuff
engine.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of KNewStuff2. 00003 Copyright (c) 2008 Jeremy Whiting <jpwhiting@kde.org> 00004 Copyright (c) 2007 Josef Spillner <spillner@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with this library. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 #include "knewstuff2/engine.h" 00020 00021 #include "knewstuff2/ui/downloaddialog.h" 00022 #include "knewstuff2/ui/uploaddialog.h" 00023 #include "knewstuff2/ui/providerdialog.h" 00024 00025 #include "knewstuff2/core/entryhandler.h" // tmp 00026 00027 #include <kcomponentdata.h> 00028 #include <kdebug.h> 00029 #include <kglobal.h> 00030 #include <kwindowsystem.h> 00031 00032 #include <qeventloop.h> 00033 00034 using namespace KNS; 00035 00036 class KNS::EnginePrivate : public DxsEngine 00037 { 00038 Q_OBJECT 00039 00040 public: 00041 EnginePrivate(QWidget* parent) 00042 : DxsEngine(parent) { 00043 m_command = EnginePrivate::command_none; 00044 m_uploaddialog = NULL; 00045 m_downloaddialog = NULL; 00046 m_uploadedEntry = NULL; 00047 m_modal = false; 00048 m_parent = parent; 00049 m_loop = 0; 00050 } 00051 00052 enum Command { 00053 command_none, 00054 command_upload, 00055 command_download 00056 }; 00057 00058 void workflow(); 00059 KNS::Entry* upload(const QString& file); 00060 00061 static QHash<QString, QPointer<KDialog> > s_dialogs; 00062 00063 Command m_command; 00064 UploadDialog *m_uploaddialog; 00065 DownloadDialog *m_downloaddialog; 00066 QString m_uploadfile; 00067 KNS::Entry *m_uploadedEntry; 00068 KNS::Provider::List m_providers; 00069 bool m_modal; 00070 QWidget * m_parent; 00071 QSet<KNS::Entry*> m_changedEntries; 00072 QEventLoop* m_loop; 00073 00074 public Q_SLOTS: 00075 void slotDownloadDialogDestroyed(); 00076 00077 private Q_SLOTS: 00079 void stopLoop(); 00080 00081 void slotProviderLoaded(KNS::Provider *provider); 00082 00085 void slotEntryChanged(KNS::Entry *entry); 00086 00087 void slotHandleUpload(); 00088 void slotEntriesFinished(); 00089 00090 void slotDownloadDialogClosed(); 00091 }; 00092 00093 00094 QHash<QString, QPointer<KDialog> > KNS::EnginePrivate::s_dialogs; 00095 00096 Engine::Engine(QWidget* parent) 00097 : d(new EnginePrivate(parent)) 00098 { 00099 } 00100 00101 Engine::~Engine() 00102 { 00103 //kDebug() << d->m_downloaddialog; 00104 if (d->m_downloaddialog) { 00105 d->slotDownloadDialogDestroyed(); 00106 } 00107 00108 delete d; 00109 } 00110 00111 void EnginePrivate::workflow() 00112 { 00113 disconnect(this, 0, this, 0); 00114 if ((m_command == command_upload) || (m_command == command_download)) { 00115 connect(this, 00116 SIGNAL(signalProviderLoaded(KNS::Provider*)), 00117 SLOT(slotProviderLoaded(KNS::Provider*))); 00118 } 00119 00120 if (m_command == command_upload) { 00121 connect(this, 00122 SIGNAL(signalProvidersFinished()), 00123 SLOT(slotHandleUpload())); 00124 connect(this, 00125 SIGNAL(signalProvidersFailed()), 00126 SLOT(stopLoop())); 00127 00128 m_uploadedEntry = NULL; 00129 } 00130 00131 if (m_command == command_download) { 00132 m_downloaddialog = new DownloadDialog(this, m_parent); 00133 //kDebug() << "adding!"; 00134 s_dialogs.insert(componentName(), m_downloaddialog); 00135 00136 connect(this, SIGNAL(signalEntriesFinished()), 00137 SLOT(slotEntriesFinished())); 00138 connect(this, 00139 SIGNAL(signalEntryChanged(KNS::Entry *)), 00140 SLOT(slotEntryChanged(KNS::Entry *))); 00141 connect(this, 00142 SIGNAL(signalProvidersFailed()), 00143 SLOT(slotDownloadDialogClosed())); 00144 connect(m_downloaddialog, 00145 SIGNAL(destroyed(QObject*)), 00146 SLOT(slotDownloadDialogDestroyed())); 00147 connect(m_downloaddialog, SIGNAL(finished()), SLOT(slotDownloadDialogClosed())); 00148 //kDebug() << "done adding!"; 00149 00150 m_downloaddialog->show(); 00151 } 00152 00153 start(); 00154 00155 if (m_modal) { 00156 QEventLoop loop; 00157 m_loop = &loop; 00158 loop.exec(); 00159 } 00160 } 00161 00162 void EnginePrivate::stopLoop() 00163 { 00164 m_command = command_none; 00165 00166 if (m_loop) { 00167 m_loop->exit(); 00168 m_loop = 0; 00169 00170 if (m_downloaddialog) { 00171 slotDownloadDialogDestroyed(); 00172 } 00173 } 00174 } 00175 00176 KNS::Entry::List Engine::download() 00177 { 00178 KNS::Entry::List entries; 00179 00180 Engine *engine = new Engine(0); 00181 00182 KComponentData component = KGlobal::activeComponent(); 00183 QString name = component.componentName(); 00184 00185 bool ret = engine->init(name + ".knsrc"); 00186 if (!ret) { 00187 delete engine; 00188 return entries; 00189 } 00190 00191 KNS::Entry::List tempList = engine->downloadDialogModal(0); 00192 00193 // copy the list since the entries will be deleted when we delete the engine 00194 foreach(Entry * entry, tempList) { 00195 entries << new Entry(*entry); 00196 } 00197 delete engine; 00198 00199 return entries; 00200 } 00201 00202 KNS::Entry::List Engine::downloadDialogModal(QWidget* parent) 00203 { 00204 //kDebug() << "Engine: downloadDialogModal"; 00205 KDialog *existingDialog = EnginePrivate::s_dialogs.value(d->componentName()); 00206 if (existingDialog) { 00207 existingDialog->show(); 00208 KWindowSystem::setOnDesktop(existingDialog->winId(), KWindowSystem::currentDesktop()); 00209 KWindowSystem::activateWindow(existingDialog->winId()); 00210 return QList<KNS::Entry*>(); 00211 } 00212 00213 d->m_command = EnginePrivate::command_download; 00214 d->m_modal = true; 00215 if (parent) { 00216 d->m_parent = parent; 00217 } 00218 00219 d->workflow(); 00220 00221 return QList<KNS::Entry*>::fromSet(d->m_changedEntries); 00222 } 00223 00224 void Engine::downloadDialog() 00225 { 00226 //kDebug() << "Engine: downloadDialog"; 00227 KDialog *existingDialog = EnginePrivate::s_dialogs.value(d->componentName()); 00228 if (existingDialog) { 00229 //kDebug() << "got an existing dialog"; 00230 existingDialog->show(); 00231 KWindowSystem::setOnDesktop(existingDialog->winId(), KWindowSystem::currentDesktop()); 00232 KWindowSystem::activateWindow(existingDialog->winId()); 00233 return; 00234 } 00235 00236 if (d->m_command != EnginePrivate::command_none) { 00237 kError() << "Engine: asynchronous workflow already going on" << endl; 00238 return; 00239 } 00240 00241 d->m_command = EnginePrivate::command_download; 00242 d->m_modal = false; 00243 00244 d->workflow(); 00245 } 00246 00247 void Engine::downloadDialog(QObject * receiver, const char * slot) 00248 { 00249 QObject::disconnect(d, SIGNAL(signalDownloadDialogDone(KNS::Entry::List)), receiver, slot); 00250 QObject::connect(d, SIGNAL(signalDownloadDialogDone(KNS::Entry::List)), receiver, slot); 00251 downloadDialog(); 00252 } 00253 00254 KNS::Entry *EnginePrivate::upload(const QString& file) 00255 { 00256 KNS::Entry *entry = NULL; 00257 00258 Engine engine(0); 00259 00260 KComponentData component = KGlobal::activeComponent(); 00261 QString name = component.componentName(); 00262 00263 bool ret = engine.init(name + ".knsrc"); 00264 if (!ret) return entry; 00265 00266 entry = engine.uploadDialogModal(file); 00267 00268 // FIXME: refcounting? 00269 return entry; 00270 } 00271 00272 bool Engine::init(const QString& config) 00273 { 00274 return d->init(config); 00275 } 00276 00277 00278 KNS::Entry *Engine::upload(const QString& file) 00279 { 00280 #ifdef __GNUC__ 00281 #warning KNS::Engine::upload() not implemented! 00282 #endif 00283 #if 0 00284 return d->upload(file); 00285 #else 00286 Q_UNUSED(file); 00287 #endif 00288 Q_ASSERT(false); 00289 return 0; 00290 } 00291 00292 KNS::Entry *Engine::uploadDialogModal(const QString& file) 00293 { 00294 //kDebug() << "Engine: uploadDialogModal"; 00295 00296 d->m_command = EnginePrivate::command_upload; 00297 d->m_modal = true; 00298 d->m_uploadfile = file; 00299 00300 d->workflow(); 00301 00302 return d->m_uploadedEntry; 00303 } 00304 00305 void Engine::uploadDialog(const QString& file) 00306 { 00307 //kDebug() << "Engine: uploadDialog"; 00308 00309 if (d->m_command != EnginePrivate::command_none) { 00310 kError() << "Engine: asynchronous workflow already going on" << endl; 00311 return; 00312 } 00313 00314 d->m_command = EnginePrivate::command_upload; 00315 d->m_modal = false; 00316 d->m_uploadfile = file; 00317 00318 d->workflow(); 00319 } 00320 00321 void EnginePrivate::slotProviderLoaded(KNS::Provider *provider) 00322 { 00323 if (m_command == command_download) { 00324 loadEntries(provider); 00325 } else if (m_command == command_upload) { 00326 // FIXME: inject into upload dialog 00327 // FIXME: dialog could do this by itself! 00328 00329 // FIXME: for the modal dialog, do nothing here 00330 // ... and wait for slotProvidersFinished() 00331 m_providers.append(provider); 00332 } else { 00333 kError() << "Engine: invalid command" << endl; 00334 } 00335 } 00336 00337 void EnginePrivate::slotHandleUpload() 00338 { 00339 // NOTE: this is only connected when we are doing an upload 00340 //kDebug() << "Engine: slotProvidersFinished"; 00341 00342 //Provider *fakeprovider = new Provider(); 00343 //fakeprovider->setName(QString("Fake Provider")); 00344 //fakeprovider->setUploadUrl(KUrl("http://localhost/dav/")); 00345 //fakeprovider->setUploadUrl(KUrl("webdav://localhost/uploads/")); 00346 00347 00348 // let the user select the provider 00349 QPointer<ProviderDialog> provdialog = new ProviderDialog(NULL); 00350 for (Provider::List::Iterator it = m_providers.begin(); it != m_providers.end(); ++it) { 00351 Provider *provider = (*it); 00352 provdialog->addProvider(provider); 00353 } 00354 //provdialog.addProvider(fakeprovider); 00355 if (provdialog->exec() == QDialog::Rejected) { 00356 stopLoop(); 00357 return; 00358 } 00359 00360 KNS::Provider *provider = provdialog->provider(); 00361 00362 // fill in the details of the upload (name, author...) 00363 QPointer<UploadDialog> uploaddialog = new UploadDialog(NULL); 00364 uploaddialog->setPayloadFile(KUrl(m_uploadfile)); 00365 if (uploaddialog->exec() == QDialog::Rejected) { 00366 stopLoop(); 00367 return; 00368 } 00369 00370 Entry *entry = uploaddialog->entry(); 00371 if (!entry) { 00372 stopLoop(); 00373 return; 00374 } 00375 00376 KTranslatable payload; 00377 // add all the translations to the payload 00378 QStringList langs = entry->name().languages(); 00379 for (QStringList::const_iterator it = langs.constBegin(); it != langs.constEnd(); ++it) { 00380 payload.addString(*it, m_uploadfile); 00381 } 00382 entry->setPayload(payload); 00383 00384 EntryHandler eh(*entry); 00385 QDomElement xml = eh.entryXML(); 00386 QByteArray ar; 00387 QTextStream txt(&ar); 00388 txt << xml; 00389 //kDebug() << "Upload: " << QString(ar); 00390 00391 connect(this, SIGNAL(signalEntryUploaded()), SLOT(stopLoop())); 00392 connect(this, SIGNAL(signalEntryFailed()), SLOT(stopLoop())); 00393 00394 uploadEntry(provider, entry); 00395 m_uploadedEntry=entry; 00396 } 00397 00398 void EnginePrivate::slotEntryChanged(KNS::Entry * entry) 00399 { 00400 //kDebug() << "adding entries to list of changed entries"; 00401 m_changedEntries << entry; 00402 } 00403 00404 // BIGFIXME: make this method go away when we are using goya 00405 void EnginePrivate::slotEntriesFinished() 00406 { 00407 //m_downloaddialog->refresh(); 00408 } 00409 00410 void EnginePrivate::slotDownloadDialogDestroyed() 00411 { 00412 //kDebug() << m_downloaddialog << "is destroyed!" << s_dialogs.count() << s_dialogs.keys(); 00413 QHash<QString, QPointer<KDialog> >::iterator it = s_dialogs.begin(); 00414 while (it != s_dialogs.end()) { 00415 if (it.value() == m_downloaddialog) { 00416 //kDebug() << "found it!"; 00417 it = s_dialogs.erase(it); 00418 } 00419 00420 if (it != s_dialogs.end()) { 00421 ++it; 00422 } 00423 } 00424 00425 //kDebug() << s_dialogs.count() << s_dialogs.keys(); 00426 } 00427 00428 void EnginePrivate::slotDownloadDialogClosed() 00429 { 00430 //kDebug() << sender() << m_downloaddialog; 00431 disconnect(m_downloaddialog, SIGNAL(destroyed(QObject*)), 00432 this, SLOT(slotDownloadDialogDestroyed())); 00433 slotDownloadDialogDestroyed(); 00434 m_downloaddialog->deleteLater(); 00435 m_downloaddialog = NULL; 00436 stopLoop(); 00437 emit signalDownloadDialogDone(QList<KNS::Entry*>::fromSet(m_changedEntries)); 00438 } 00439 00440 #include "engine.moc"
KDE 4.6 API Reference