diff options
author | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:35 -0400 |
---|---|---|
committer | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:35 -0400 |
commit | df8f1d512c60a96f9041f9663b3fdc2db51cba33 (patch) | |
tree | 3d2bdbd4732d417aca73be022ae9044eac96b7d3 /src/frontend/bookshelfmanager | |
parent | 4885bfcef4d89cf0cb391e00af617b9fd19c9cbb (diff) |
Imported Upstream version 2.8.1
Diffstat (limited to 'src/frontend/bookshelfmanager')
38 files changed, 1380 insertions, 1796 deletions
diff --git a/src/frontend/bookshelfmanager/btconfigdialog.cpp b/src/frontend/bookshelfmanager/btconfigdialog.cpp index 565765d..3d02388 100644 --- a/src/frontend/bookshelfmanager/btconfigdialog.cpp +++ b/src/frontend/bookshelfmanager/btconfigdialog.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -20,8 +20,6 @@ #include <QListWidgetItem> #include <QStackedWidget> #include <QVBoxLayout> -#include "util/directory.h" -#include "util/tool.h" BtConfigDialog::BtConfigDialog(QWidget* parent) @@ -44,14 +42,6 @@ BtConfigDialog::BtConfigDialog(QWidget* parent) m_pageLayout->addWidget(m_pageWidget); - // Horizontal line - QFrame* line = new QFrame(); - line->setGeometry(QRect(1, 1, 1, 3)); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_pageLayout->addWidget(line); - connect(m_contentsList, SIGNAL(currentRowChanged(int)), this, SLOT(slotChangePage(int)) @@ -62,22 +52,14 @@ BtConfigDialog::BtConfigDialog(QWidget* parent) BtConfigDialog::~BtConfigDialog() {} void BtConfigDialog::addPage(BtConfigPage* pageWidget) { - namespace DU = util::directory; - // this is a friend pageWidget->m_parentDialog = this; - QVBoxLayout* containerLayout = new QVBoxLayout; - QLabel* headerLabel = util::tool::explanationLabel(pageWidget, pageWidget->header(), pageWidget->label()); - containerLayout->addWidget(headerLabel); - containerLayout->addWidget(pageWidget); - QWidget* containerWidget = new QWidget(m_pageWidget); - containerWidget->setLayout(containerLayout); - m_pageWidget->addWidget(containerWidget); + m_pageWidget->addWidget(pageWidget); QListWidgetItem* item = new QListWidgetItem(m_contentsList); - item->setIcon(DU::getIcon(pageWidget->iconName())); + item->setIcon(pageWidget->icon()); item->setText(pageWidget->header()); item->setTextAlignment(Qt::AlignHCenter); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); @@ -96,11 +78,16 @@ void BtConfigDialog::addPage(BtConfigPage* pageWidget) { } void BtConfigDialog::addButtonBox(QDialogButtonBox* box) { - m_pageLayout->addWidget(box); -} + // First add a horizontal ruler: + QFrame *line = new QFrame(); + line->setGeometry(QRect(1, 1, 1, 3)); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_pageLayout->addWidget(line); -BtConfigPage* BtConfigDialog::currentPage() { - return dynamic_cast<BtConfigPage*>(m_pageWidget->currentWidget()); + // Add button box: + m_pageLayout->addWidget(box); } void BtConfigDialog::slotChangePage(int newIndex) { @@ -113,6 +100,13 @@ void BtConfigDialog::slotChangePage(int newIndex) { -BtConfigPage::BtConfigPage() {} +BtConfigPage::BtConfigPage(QWidget *parent) + : QWidget(parent) + , m_parentDialog(0) +{ + setLayout(new QVBoxLayout); +} -BtConfigPage::~BtConfigPage() {} +BtConfigPage::~BtConfigPage() { + // Intentionally empty +} diff --git a/src/frontend/bookshelfmanager/btconfigdialog.h b/src/frontend/bookshelfmanager/btconfigdialog.h index 547cb4e..dce22ab 100644 --- a/src/frontend/bookshelfmanager/btconfigdialog.h +++ b/src/frontend/bookshelfmanager/btconfigdialog.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -17,10 +17,11 @@ class BtConfigPage; -class QListWidgetItem; +class QDialogButtonBox; +class QLabel; class QListWidget; +class QListWidgetItem; class QStackedWidget; -class QDialogButtonBox; class QVBoxLayout; /** @@ -34,7 +35,7 @@ class QVBoxLayout; class BtConfigDialog : public QDialog { Q_OBJECT public: - BtConfigDialog(QWidget* parent); + BtConfigDialog(QWidget *parent = 0); virtual ~BtConfigDialog(); /** Adds a BtConfigPage to the paged widget stack. The new page will be the current page.*/ @@ -42,9 +43,6 @@ class BtConfigDialog : public QDialog { /** Adds a button box to the lower edge of the dialog. */ void addButtonBox(QDialogButtonBox* buttonBox); - /** Returns the currently selected page. */ - BtConfigPage* currentPage(); - public slots: /** Changes the current page using the given index number. */ void slotChangePage(int newIndex); @@ -64,24 +62,29 @@ class BtConfigDialog : public QDialog { */ class BtConfigPage : public QWidget { Q_OBJECT + friend class BtConfigDialog; + public: - BtConfigPage(); + /** + Constructs a configuration dialog base, with QVBoxLayout as layout() and a header + label as the first widget in this layout. + \param[in] parent The parent widget. + */ + BtConfigPage(QWidget *parent = 0); virtual ~BtConfigPage(); /** Implement these to return the correct values. * For example: header(){return tr("General");} */ - virtual QString iconName() = 0; - virtual QString label() = 0; - virtual QString header() = 0; - BtConfigDialog* parentDialog() { + virtual const QIcon &icon() const = 0; + virtual QString header() const = 0; + + inline BtConfigDialog *parentDialog() const { return m_parentDialog; } private: - friend class BtConfigDialog; - BtConfigDialog* m_parentDialog; - + BtConfigDialog *m_parentDialog; }; diff --git a/src/frontend/bookshelfmanager/btinstallmgr.cpp b/src/frontend/bookshelfmanager/btinstallmgr.cpp index ace804f..756fcae 100644 --- a/src/frontend/bookshelfmanager/btinstallmgr.cpp +++ b/src/frontend/bookshelfmanager/btinstallmgr.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -10,7 +10,7 @@ #include "frontend/bookshelfmanager/btinstallmgr.h" #include "backend/managers/cswordbackend.h" -#include "frontend/bookshelfmanager/instbackend.h" +#include "backend/btinstallbackend.h" #include <QDebug> #include <QList> #include <QObject> @@ -25,8 +25,9 @@ using namespace sword; BtInstallMgr::BtInstallMgr() - : InstallMgr(instbackend::configPath().toLatin1(), this), - m_firstCallOfPreStatus(true) { //use this class also as status reporter + : InstallMgr(BtInstallBackend::configPath().toLatin1(), this), + m_totalBytes(1), m_completedBytes(0), m_firstCallOfPreStatus(true) +{ //use this class also as status reporter qDebug() << "BtInstallMgr::BtInstallMgr"; this->setFTPPassive(true); } diff --git a/src/frontend/bookshelfmanager/btinstallmgr.h b/src/frontend/bookshelfmanager/btinstallmgr.h index 7eff1ae..7d39440 100644 --- a/src/frontend/bookshelfmanager/btinstallmgr.h +++ b/src/frontend/bookshelfmanager/btinstallmgr.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -21,53 +21,42 @@ #include <ftptrans.h> -class CSwordBackend; - -typedef QList<sword::InstallSource*> InstallSourceList; - /** * Our own reimplementation to provide installation and status bar updates. */ class BtInstallMgr : public QObject, public sword::InstallMgr, public sword::StatusReporter { Q_OBJECT public: - BtInstallMgr(); - virtual ~BtInstallMgr(); - - /** - * Refreshing the source should be cancellable (othewise it might freeze the app if there is - * for example something wrong with the network). - */ - void slotRefreshCanceled(); + ~BtInstallMgr(); /** Re-implemented from sword::InstallMgr. */ - virtual bool isUserDisclaimerConfirmed() const; + bool isUserDisclaimerConfirmed() const; + + signals: + /** Download status. Percent of total and file.*/ + void percentCompleted(const int total, const int file); + void downloadStarted(); protected: - /* Reimplementations of methods in StatusReporter */ /** - * Gets the total and current file status, emits the signal with those values as percents. + Reimplementation of sword::StatusReporter::statusUpdate(). */ - virtual void statusUpdate(double dltotal, double dlnow); + void statusUpdate(double dltotal, double dlnow); + /** + * Reimplementation of sword::StatusReporter::preStatus(). + * \warning This method is not always called before statusUpdate(). * Called before starting to download each file of the module package. * The sword message is not i18n'ed, it's in the form "Downloading (1 of 6): nt.bzs". * This function is not utilized in the UI ATM. */ - virtual void preStatus(long totalBytes, long completedBytes, const char *message); + void preStatus(long totalBytes, long completedBytes, const char *message); + private: long m_totalBytes; long m_completedBytes; - - private: bool m_firstCallOfPreStatus; - - signals: - /** Download status. Percent of total and file.*/ - void percentCompleted( const int, const int); - void downloadStarted(); }; - #endif diff --git a/src/frontend/bookshelfmanager/btmodulemanagerdialog.cpp b/src/frontend/bookshelfmanager/btmodulemanagerdialog.cpp index b261305..f0547b8 100644 --- a/src/frontend/bookshelfmanager/btmodulemanagerdialog.cpp +++ b/src/frontend/bookshelfmanager/btmodulemanagerdialog.cpp @@ -2,21 +2,18 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ #include "frontend/bookshelfmanager/btmodulemanagerdialog.h" -#include <QDialogButtonBox> #include "backend/config/cbtconfig.h" #include "backend/managers/cswordbackend.h" #include "frontend/bookshelfmanager/indexpage/btindexpage.h" #include "frontend/bookshelfmanager/installpage/btinstallpage.h" #include "frontend/bookshelfmanager/removepage/btremovepage.h" -#include "util/cpointers.h" -#include "util/dialogutil.h" static BtModuleManagerDialog *m_staticModuleManagerDialog = 0; @@ -48,13 +45,6 @@ BtModuleManagerDialog::BtModuleManagerDialog(QWidget* parent) slotChangePage(0); - // Dialog button (Close) - QDialogButtonBox* bbox = new QDialogButtonBox(this); - bbox->addButton(QDialogButtonBox::Close); - util::prepareDialogBox(bbox); - addButtonBox(bbox); - connect(bbox, SIGNAL(rejected()), SLOT(close())); - loadDialogSettings(); } diff --git a/src/frontend/bookshelfmanager/btmodulemanagerdialog.h b/src/frontend/bookshelfmanager/btmodulemanagerdialog.h index c51efd2..0392cc2 100644 --- a/src/frontend/bookshelfmanager/btmodulemanagerdialog.h +++ b/src/frontend/bookshelfmanager/btmodulemanagerdialog.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -44,7 +44,7 @@ class BtModuleManagerDialog : public BtConfigDialog { //signals: -// void swordSetupChanged(); +// void swordSetupChanged(); }; diff --git a/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.cpp b/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.cpp index e326641..14aecb9 100644 --- a/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.cpp +++ b/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.cpp @@ -2,14 +2,14 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ #include "frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h" -#include <boost/scoped_ptr.hpp> +#include <QSharedPointer> #include <QComboBox> #include <QDir> #include <QFileInfo> @@ -25,7 +25,7 @@ #include <QProgressDialog> #include <QApplication> #include <QDebug> -#include "frontend/bookshelfmanager/instbackend.h" +#include "backend/btinstallbackend.h" #include "util/dialogutil.h" const QString PROTO_FILE( QObject::tr("Local") ); //Local path @@ -102,11 +102,10 @@ void CSwordSetupInstallSourcesDialog::slotOk() { //BTInstallMgr iMgr; //sword::InstallSource is = BTInstallMgr::Tool::RemoteConfig::source( &iMgr, m_captionEdit->text() ); - sword::InstallSource is = instbackend::source(m_captionEdit->text()); + sword::InstallSource is = BtInstallBackend::source(m_captionEdit->text()); if ( (QString)is.caption.c_str() == m_captionEdit->text() ) { //source already exists util::showInformation( this, tr( "Error" ), - /** \bug Double space in the following string: */ - tr("A source with this caption already exists. Please provide a different caption.")); + tr("A source with this caption already exists. Please provide a different caption.")); return; } @@ -177,17 +176,15 @@ void CSwordSetupInstallSourcesDialog::slotGetListClicked() { qApp->processEvents(); qWarning() << "Start downloading the list of sources"; int ret = iMgr.refreshRemoteSourceConfiguration(); - bool success = false; + if ( !ret ) { //make sure the sources were updated sucessfully qDebug() << "download succeeded"; - success = true; m_progressDialog->setValue(100); //make sure the dialog closes m_remoteListAdded = true; accept(); } else { qWarning("InstallMgr: getting remote list returned an error."); - success = false; } delete m_progressDialog; m_progressDialog = 0; diff --git a/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h b/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h index 12df221..e69e9a9 100644 --- a/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h +++ b/src/frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ diff --git a/src/frontend/bookshelfmanager/indexpage/btindexpage.cpp b/src/frontend/bookshelfmanager/indexpage/btindexpage.cpp index 984700c..026aad5 100644 --- a/src/frontend/bookshelfmanager/indexpage/btindexpage.cpp +++ b/src/frontend/bookshelfmanager/indexpage/btindexpage.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -19,20 +19,20 @@ #include "backend/config/cbtconfig.h" #include "backend/drivers/cswordmoduleinfo.h" #include "backend/managers/cswordbackend.h" -#include "frontend/cmoduleindexdialog.h" +#include "frontend/btmoduleindexdialog.h" #include "util/directory.h" -#include "util/cpointers.h" #include "util/cresmgr.h" #include "util/tool.h" -BtIndexPage::BtIndexPage() - : BtConfigPage() { +BtIndexPage::BtIndexPage(QWidget *parent) + : BtConfigPage(parent) +{ namespace DU = util::directory; - QVBoxLayout *vboxLayout; + Q_ASSERT(qobject_cast<QVBoxLayout*>(layout()) != 0); + QVBoxLayout *vboxLayout = static_cast<QVBoxLayout*>(layout()); QHBoxLayout *hboxLayout; - vboxLayout = new QVBoxLayout(this); m_autoDeleteOrphanedIndicesBox = new QCheckBox(this); m_autoDeleteOrphanedIndicesBox->setToolTip(tr("If selected, those indexes which have no corresponding work will be deleted when BibleTime starts")); @@ -75,22 +75,20 @@ BtIndexPage::BtIndexPage() // connect our signals/slots connect(m_createButton, SIGNAL(clicked()), this, SLOT(createIndices())); connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(deleteIndices())); - connect(CPointers::backend(), SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)), SLOT(slotSwordSetupChanged())); + connect(CSwordBackend::instance(), SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)), SLOT(slotSwordSetupChanged())); populateModuleList(); } BtIndexPage::~BtIndexPage() { CBTConfig::set( CBTConfig::autoDeleteOrphanedIndices, m_autoDeleteOrphanedIndicesBox->isChecked() ); - -} -QString BtIndexPage::label() { - return tr("Create new search indexes and delete created indexes for the installed works."); } -QString BtIndexPage::iconName() { - return CResMgr::bookshelfmgr::indexpage::icon; + +const QIcon &BtIndexPage::icon() const { + return util::directory::getIcon(CResMgr::bookshelfmgr::indexpage::icon); } -QString BtIndexPage::header() { + +QString BtIndexPage::header() const { return tr("Search Indexes"); } @@ -114,7 +112,7 @@ void BtIndexPage::populateModuleList() { - const QList<CSwordModuleInfo*> &modules(CPointers::backend()->moduleList()); + const QList<CSwordModuleInfo*> &modules(CSwordBackend::instance()->moduleList()); for (MLCI it(modules.begin()); it != modules.end(); ++it) { QTreeWidgetItem* item = 0; @@ -138,11 +136,11 @@ void BtIndexPage::populateModuleList() { /** Creates indices for selected modules if no index currently exists */ void BtIndexPage::createIndices() { bool indicesCreated = false; - QList<CSwordModuleInfo*> moduleList; + QList<const CSwordModuleInfo*> moduleList; for (int i = 0; i < m_modsWithoutIndices->childCount(); i++) { if (m_modsWithoutIndices->child(i)->checkState(0) == Qt::Checked) { - CSwordModuleInfo* module = CPointers::backend()->findModuleByName(m_modsWithoutIndices->child(i)->text(0).toUtf8()); + CSwordModuleInfo* module = CSwordBackend::instance()->findModuleByName(m_modsWithoutIndices->child(i)->text(0).toUtf8()); if (module) { moduleList.append( module ); indicesCreated = true; @@ -152,7 +150,7 @@ void BtIndexPage::createIndices() { //Shows the progress dialog if (indicesCreated) { - CModuleIndexDialog::getInstance()->indexAllModules( moduleList ); + BtModuleIndexDialog::indexAllModules(moduleList); populateModuleList(); } } @@ -163,7 +161,7 @@ void BtIndexPage::deleteIndices() { for (int i = 0; i < m_modsWithIndices->childCount(); i++) { if (m_modsWithIndices->child(i)->checkState(0) == Qt::Checked) { - CSwordModuleInfo* module = CPointers::backend()->findModuleByName(m_modsWithIndices->child(i)->text(0).toUtf8()); + CSwordModuleInfo* module = CSwordBackend::instance()->findModuleByName(m_modsWithIndices->child(i)->text(0).toUtf8()); if (module) { module->deleteIndex(); indicesDeleted = true; @@ -177,27 +175,6 @@ void BtIndexPage::deleteIndices() { } } -void BtIndexPage::deleteOrphanedIndices() { - QDir dir(CSwordModuleInfo::getGlobalBaseIndexLocation()); - dir.setFilter(QDir::Dirs); - CSwordModuleInfo* module; - - for (unsigned int i = 0; i < dir.count(); i++) { - if (dir[i] != "." && dir[i] != "..") { - if ( (module = CPointers::backend()->findModuleByName(dir[i])) ) { //mod exists - if (!module->hasIndex()) { //index files found, but wrong version etc. - CSwordModuleInfo::deleteIndexForModule( dir[i] ); - } - } - else { //no module exists - if (CBTConfig::get( CBTConfig::autoDeleteOrphanedIndices ) ) { - CSwordModuleInfo::deleteIndexForModule( dir[i] ); - } - } - } - } -} - void BtIndexPage::slotSwordSetupChanged() { populateModuleList(); } diff --git a/src/frontend/bookshelfmanager/indexpage/btindexpage.h b/src/frontend/bookshelfmanager/indexpage/btindexpage.h index 795cc0b..89a7e35 100644 --- a/src/frontend/bookshelfmanager/indexpage/btindexpage.h +++ b/src/frontend/bookshelfmanager/indexpage/btindexpage.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -26,20 +26,14 @@ class BtIndexPage : public BtConfigPage { Q_OBJECT public: - /** - * Constructor - */ - BtIndexPage(); - - /** - * Destructor - */ + BtIndexPage(QWidget *parent = 0); ~BtIndexPage(); - // BtConfigPage methods - QString header(); - QString iconName(); - QString label(); + /** Reimplemented from BtConfigPage. */ + virtual QString header() const; + + /** Reimplemented from BtConfigPage. */ + virtual const QIcon &icon() const; public slots: void slotSwordSetupChanged(); @@ -63,13 +57,6 @@ class BtIndexPage : public BtConfigPage { */ void deleteIndices(); - public: - /** - * Deletes orphaned indices if the autoDeleteOrphanedIndices is true - * Always deletes indices of existing modules where hasIndex() returns false - */ - static void deleteOrphanedIndices(); - private: QCheckBox *m_autoDeleteOrphanedIndicesBox; diff --git a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.cpp b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.cpp index 8fd87ec..01ca55b 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.cpp +++ b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.cpp @@ -1,127 +1,83 @@ /********* * +* In the name of the Father, and of the Son, and of the Holy Spirit. +* * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2009 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. * **********/ #include "frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h" -#include <QBrush> -#include <QDebug> -#include <QList> -#include <QPushButton> -#include <QString> -#include <QTreeWidgetItem> -#include <QWidget> -#include "backend/btmoduletreeitem.h" -#include "backend/drivers/cswordmoduleinfo.h" -#include "frontend/cmodulechooserdialog.h" +#include <QAction> +#include <QHeaderView> +#include <QToolButton> +#include "backend/bookshelfmodel/btbookshelffiltermodel.h" +#include "frontend/btbookshelfview.h" +#include "util/tool.h" -BtInstallModuleChooserDialog::BtInstallModuleChooserDialog(QWidget* parent, QString title, QString label, QList<CSwordModuleInfo*>* empty) - : CModuleChooserDialog(parent, title, label, empty) { - qDebug() << "BtInstallModuleChooserDialog::BtInstallModuleChooserDialog start"; - init(); - okButton()->setText(tr("Install")); - m_nameList = QStringList(); +namespace { +const QString groupingOrderKey("GUI/BookshelfManager/InstallConfirmDialog/grouping"); } -// Do nothing, the tree is initialized outside this class. -void BtInstallModuleChooserDialog::initModuleItem(BTModuleTreeItem*, QTreeWidgetItem*) {} - -void BtInstallModuleChooserDialog::initModuleItem(QString name, QTreeWidgetItem* sourceItem) { - /// \todo Use new bookshelf model instead - /// \bug Valgrind reports memory leak: - QTreeWidgetItem* moduleItem = new QTreeWidgetItem(sourceItem); - moduleItem->setText(0, name); - moduleItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - moduleItem->setCheckState(0, Qt::Checked); +BtInstallModuleChooserDialog::BtInstallModuleChooserDialog(const BtBookshelfTreeModel::Grouping &g, + QWidget *parent, + Qt::WindowFlags flags) + : BtModuleChooserDialog(parent, flags), m_shown(false) +{ + resize(550, 340); - // prevent double items - if (m_nameList.contains(name)) { - qDebug() << "item already in list:" << name; - //moduleItem->setCheckState(0, Qt::Unchecked); - QBrush bg(Qt::red); - moduleItem->setBackground(0, bg); - //find and change the other offending items - foreach (QTreeWidgetItem* doubleItem, treeWidget()->findItems(name, Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive, 0)) { - //doubleItem->setCheckState(0, Qt::Unchecked); - //qDebug() << "CInstallModuleChooserDialog::initModuleItem" << doubleItem; - doubleItem->setBackground(0, bg); - } - m_doubleCheckedModules[name] = true; - enableOk(false); + // Read grouping order from settings or the default from argument: + BtBookshelfTreeModel::Grouping groupingOrder(false); + if (!groupingOrder.loadFrom(groupingOrderKey)) { + groupingOrder = g; } - m_nameList << name; -} -void BtInstallModuleChooserDialog::slotItemChecked(QTreeWidgetItem* item, int column) { - QString moduleName = item->text(0); - qDebug() << "BtInstallModuleChooserDialog::slotItemChecked start"; - // handle only non-toplevel items which has duplicates and where the first column was changed - if (item->parent() && column == 0 && (findModuleItemsByName(moduleName).count() > 1)) { - //prevent handling when the color is changed - if (item->data(1, Qt::UserRole).toBool() == false) { - qDebug() << "was not updating"; - item->setData(1, Qt::UserRole, true); - } - else { - qDebug() << "was updating"; - item->setData(1, Qt::UserRole, false); - return; - } + BtInstallModuleChooserDialogModel *treeModel; + treeModel = new BtInstallModuleChooserDialogModel(groupingOrder, this); + connect(treeModel, SIGNAL(groupingOrderChanged(BtBookshelfTreeModel::Grouping)), + this, SLOT(slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping&))); - QList<QTreeWidgetItem*> doubleNameItems = findModuleItemsByName(moduleName); - QList<QTreeWidgetItem*> doubleCheckedItems; - foreach (QTreeWidgetItem* nItem, doubleNameItems) { - if (nItem->checkState(0) == Qt::Checked) { - doubleCheckedItems << nItem; - } - } + m_bookshelfModel = new BtBookshelfModel(this); + bookshelfWidget()->postFilterModel()->setShowShown(true); + bookshelfWidget()->setTreeModel(treeModel); + bookshelfWidget()->setSourceModel(m_bookshelfModel); + bookshelfWidget()->showHideAction()->setVisible(false); + bookshelfWidget()->showHideButton()->hide(); + bookshelfWidget()->treeView()->header()->show(); - if (doubleCheckedItems.count() > 1) { - enableOk(false); - // color the items - qDebug() << "there were more than 1 item of the name" << moduleName; - foreach (QTreeWidgetItem* i, doubleNameItems) { - QBrush bg(Qt::red); - i->setBackground(0, bg); - } - m_doubleCheckedModules[moduleName] = true; - } - else if (doubleCheckedItems.count() == 1) { - qDebug() << "there were 1 checked items of the name" << moduleName; - // uncolor the items - foreach (QTreeWidgetItem* i, doubleNameItems) { - i->setBackground(0, i->parent()->background(0)); - } - m_doubleCheckedModules.remove(moduleName); - if (m_doubleCheckedModules.count() == 0) { - enableOk(true); - } - } - } + retranslateUi(); } -QList<QTreeWidgetItem*> BtInstallModuleChooserDialog::findModuleItemsByName(QString name) { - qDebug() << "BtInstallModuleChooserDialog::findModuleItemsByName:" << name << treeWidget()->topLevelItemCount(); - QList<QTreeWidgetItem*> doubleNamedAllItems = treeWidget()->findItems(name, Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive); - //qDebug() << "doubleNamedAllItems: " << doubleNamedAllItems.count(); - QList<QTreeWidgetItem*> doubleNamedModuleItems; - foreach (QTreeWidgetItem* item, doubleNamedAllItems) { - //qDebug() << "item:" << item; - if (item->parent()) { - doubleNamedModuleItems << item; - } - } - //qDebug() << "module items:" << doubleNamedModuleItems.count(); - return doubleNamedModuleItems; +void BtInstallModuleChooserDialog::addModuleItem(CSwordModuleInfo *module, + const QString &sourceName) +{ + module->setProperty("installSourceName", sourceName); + m_bookshelfModel->addModule(module); +} + +void BtInstallModuleChooserDialog::retranslateUi() { + setWindowTitle(tr("Install/Update works?")); + util::tool::initExplanationLabel( + label(), QString::null, + tr("Do you really want to install these works?") + "<br/><br/><small>" + + tr("Only one version of a work can be installed at the same time. Select only " + "one if there are items marked with red.") + "</small>"); +} + +void BtInstallModuleChooserDialog::showEvent(QShowEvent *event) { + Q_UNUSED(event); + + if (m_shown) return; + bookshelfWidget()->treeView()->expandAll(); + bookshelfWidget()->treeView()->header()->resizeSections(QHeaderView::ResizeToContents); + m_shown = true; } -void BtInstallModuleChooserDialog::enableOk(bool enabled) { - qDebug() << "BtInstallModuleChooserDialog::enableOk" << enabled; - okButton()->setEnabled(enabled); +void BtInstallModuleChooserDialog::slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g) { + g.saveTo(groupingOrderKey); } diff --git a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h index 06144ff..070df6f 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h +++ b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h @@ -1,51 +1,55 @@ /********* * +* In the name of the Father, and of the Son, and of the Holy Spirit. +* * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. * **********/ #ifndef BTINSTALLMODULECHOOSERDIALOG_H #define BTINSTALLMODULECHOOSERDIALOG_H -#include "frontend/cmodulechooserdialog.h" +#include "frontend/btmodulechooserdialog.h" -#include <QList> -#include <QMap> -#include <QObject> -#include <QString> +#include "frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.h" -class BTModuleTreeItem; -class QWidget; -class QTreeWidgetItem; +class BtBookshelfModel; +class BtInstallModuleChooserDialogModel; +class CSwordModuleInfo; /** * Confirmation dialog for installation. Lets the user * uncheck modules from the list. */ -class BtInstallModuleChooserDialog : public CModuleChooserDialog { - Q_OBJECT - +class BtInstallModuleChooserDialog: public BtModuleChooserDialog { + Q_OBJECT public: - BtInstallModuleChooserDialog(QWidget* parent, QString title, QString label, QList<CSwordModuleInfo*>* empty); + BtInstallModuleChooserDialog(const BtBookshelfTreeModel::Grouping &g, + QWidget *parent = 0, + Qt::WindowFlags flags = 0); - void initModuleItem(QString name, QTreeWidgetItem* sourceItem); - void enableOk(bool enabled); + inline const QSet<CSwordModuleInfo*> &checkedModules() const { + return bookshelfWidget()->treeModel()->checkedModules(); + } - public slots: - void slotItemChecked(QTreeWidgetItem* item, int column); + void addModuleItem(CSwordModuleInfo *module, const QString &sourceName); protected: - virtual void initModuleItem(BTModuleTreeItem*, QTreeWidgetItem*); + void retranslateUi(); + void showEvent(QShowEvent *event); + + protected slots: + void slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g); - QList<QTreeWidgetItem*> findModuleItemsByName(QString name); private: - QStringList m_nameList; - QMap<QString, bool> m_doubleCheckedModules; + BtBookshelfModel *m_bookshelfModel; + bool m_shown; }; -#endif +#endif // BTINSTALLMODULECHOOSERDIALOG_H diff --git a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.cpp b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.cpp new file mode 100644 index 0000000..880ea6a --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.cpp @@ -0,0 +1,136 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#include "frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.h" + +#include <QBrush> +#include "backend/drivers/cswordmoduleinfo.h" +#include "backend/managers/cswordbackend.h" + + +#define MODULEPOINTERFORINDEX(i) static_cast<CSwordModuleInfo *>(\ + BtBookshelfTreeModel::data((i), BtBookshelfModel::ModulePointerRole).value<void*>()) + +BtInstallModuleChooserDialogModel::BtInstallModuleChooserDialogModel( + const Grouping &grouping, + QObject *parent) + : BtBookshelfTreeModel(grouping, parent), m_dataChangedFired(false) +{ + setDefaultChecked(BtBookshelfTreeModel::CHECKED); + setCheckable(true); + connect(this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(parentDataChanged(QModelIndex,QModelIndex)), + Qt::DirectConnection); +} + +BtInstallModuleChooserDialogModel::~BtInstallModuleChooserDialogModel() { + // Intentionally empty +} + +QVariant BtInstallModuleChooserDialogModel::data(const QModelIndex &i, int role) const { + switch (role) { + case Qt::BackgroundRole: + if (isMulti(i)) return QBrush(Qt::red); + return BtBookshelfTreeModel::data(i, role); + case Qt::ForegroundRole: + if (isMulti(i)) return QBrush(Qt::white); + return BtBookshelfTreeModel::data(i, role); + case Qt::DisplayRole: + switch (i.column()) { + case 0: + return BtBookshelfTreeModel::data(i, role); + case 1: + { + CSwordModuleInfo *module = MODULEPOINTERFORINDEX(index(i.row(), 0, i.parent())); + if (module != 0) return module->property("installSourceName"); + break; + } + case 2: + { + CSwordModuleInfo *module = MODULEPOINTERFORINDEX(index(i.row(), 0, i.parent())); + if (module == 0) break; + CSwordBackend *b = CSwordBackend::instance(); + CSwordModuleInfo *imodule = b->findModuleByName(module->name()); + if (imodule == 0) { + return module->config(CSwordModuleInfo::ModuleVersion); + } else { + return imodule->config(CSwordModuleInfo::ModuleVersion) + + " => " + + module->config(CSwordModuleInfo::ModuleVersion); + } + } + default: break; + } + default: + if (i.column() == 0) return BtBookshelfTreeModel::data(i, role); + } + + return QVariant(); +} + +int BtInstallModuleChooserDialogModel::columnCount(const QModelIndex &parent) const { + Q_UNUSED(parent); + + return 3; +} + +QVariant BtInstallModuleChooserDialogModel::headerData(int section, + Qt::Orientation orientation, + int role) const +{ + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + switch (section) { + case 0: return tr("Work"); + case 1: return tr("Installation source"); + case 2: return tr("Version"); + default: break; + } + } + + return QVariant(); +} + +void BtInstallModuleChooserDialogModel::parentDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight) +{ + Q_UNUSED(topLeft); + Q_UNUSED(bottomRight); + + if (m_dataChangedFired) return; + m_dataChangedFired = true; + resetData(); + m_dataChangedFired = false; +} + +bool BtInstallModuleChooserDialogModel::isMulti(CSwordModuleInfo *m1) const { + if (m1 != 0 && checkedModules().contains(m1)) { + Q_FOREACH(CSwordModuleInfo *m2, m_modules.keys()) { + if (m1 != m2 && checkedModules().contains(m2) && m1->name() == m2->name()) { + return true; + } + } + } + return false; +} + +bool BtInstallModuleChooserDialogModel::isMulti(const QModelIndex &i) const { + if (!i.isValid()) return false; + + if (!hasChildren(i)) { + return isMulti(MODULEPOINTERFORINDEX(index(i.row(), 0, i.parent()))); + } else { + for (int row = 0; row < rowCount(i); row++) { + if (isMulti(i.child(row, 0))) return true; + } + } + return false; +} diff --git a/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.h b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.h new file mode 100644 index 0000000..6120fa8 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallmodulechooserdialogmodel.h @@ -0,0 +1,44 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#ifndef BTINSTALLMODULECHOOSERDIALOGMODEL_H +#define BTINSTALLMODULECHOOSERDIALOGMODEL_H + +#include "backend/bookshelfmodel/btbookshelftreemodel.h" + +#include <QMap> + + +class BtInstallModuleChooserDialogModel: public BtBookshelfTreeModel { + Q_OBJECT + public: + BtInstallModuleChooserDialogModel(const Grouping &grouping, QObject *parent = 0); + ~BtInstallModuleChooserDialogModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + private slots: + void parentDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + + private: + bool isMulti(CSwordModuleInfo *module) const; + bool isMulti(const QModelIndex &index) const; + + private: + QMap<QString, int> m_nameCounts; + bool m_dataChangedFired; +}; + +#endif // BTINSTALLMODULECHOOSERDIALOGMODEL_H diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpage.cpp b/src/frontend/bookshelfmanager/installpage/btinstallpage.cpp index b71599a..d3bac59 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallpage.cpp +++ b/src/frontend/bookshelfmanager/installpage/btinstallpage.cpp @@ -2,63 +2,60 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ #include "frontend/bookshelfmanager/installpage/btinstallpage.h" -#include <QAction> #include <QApplication> -#include <QButtonGroup> #include <QComboBox> -#include <QDialog> -#include <QFileInfo> +#include <QGroupBox> #include <QHBoxLayout> #include <QHeaderView> #include <QLabel> -#include <QMessageBox> -#include <QProgressBar> -#include <QProgressDialog> #include <QPushButton> -#include <QSpacerItem> -#include <QStackedWidget> -#include <QTabBar> -#include <QTimer> -#include <QTreeWidget> -#include <QTreeWidgetItem> +#include <QSettings> +#include <QSharedPointer> +#include <QStackedLayout> #include <QToolButton> -#include <QVBoxLayout> -#include <QWidget> #include "backend/config/cbtconfig.h" -#include "backend/drivers/cswordmoduleinfo.h" -#include "backend/managers/cswordbackend.h" -#include "frontend/bookshelfmanager/btconfigdialog.h" -#include "frontend/bookshelfmanager/btinstallmgr.h" +#include "backend/btinstallbackend.h" #include "frontend/bookshelfmanager/btmodulemanagerdialog.h" #include "frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h" +#include "frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h" +#include "frontend/bookshelfmanager/installpage/btinstallpageworkswidget.h" #include "frontend/bookshelfmanager/installpage/btinstallpathdialog.h" #include "frontend/bookshelfmanager/installpage/btinstallprogressdialog.h" -#include "frontend/bookshelfmanager/installpage/btsourcewidget.h" -#include "frontend/bookshelfmanager/installpage/btsourcearea.h" -#include "frontend/bookshelfmanager/instbackend.h" -#include "frontend/cmodulechooserdialog.h" -#include "util/directory.h" -#include "util/cpointers.h" +#include "frontend/btbookshelfview.h" #include "util/cresmgr.h" +#include "util/dialogutil.h" +#include "util/directory.h" +#include "util/tool.h" + -// Sword includes: -#include <swversion.h> +namespace { +const QString groupingOrderKey ("GUI/BookshelfManager/InstallPage/grouping"); +const QString headerStateKey ("GUI/BookshelfManager/InstallPage/headerState"); +const QString selectedModuleKey("GUI/BookshelfManager/InstallPage/selectedModule"); +} // anonymous namespace // ********************************************************* // *********** Config dialog page: Install/Update ********** // ********************************************************* -BtInstallPage::BtInstallPage() - : BtConfigPage() { - qDebug() << "BtInstallPage::BtInstallPage() start"; +BtInstallPage::BtInstallPage(QWidget *parent) + : BtConfigPage(parent) + , m_groupingOrder(groupingOrderKey) + , m_modulesSelected(0) + , m_modulesSelectedSources(0) +{ + // Read settings: + m_headerState = CBTConfig::getConfig()->value(headerStateKey).toByteArray(); + + // Initialize widgets: initView(); initConnections(); } @@ -75,68 +72,105 @@ QString BtInstallPage::selectedInstallPath() { void BtInstallPage::initView() { namespace DU = util::directory; - qDebug() << "void BtInstallPage::initView() start"; - QVBoxLayout *mainLayout = new QVBoxLayout(this); - - // installation path chooser - QHBoxLayout* pathLayout = new QHBoxLayout(); - // beautify the layout - int top; - int bottom; - int left; - int right; - pathLayout->getContentsMargins(&left, &top, &right, &bottom); - pathLayout->setContentsMargins(left, top + 7, right, bottom + 7 ); - QLabel* pathLabel = new QLabel(tr("Install folder:")); - m_pathCombo = new QComboBox(); + // Warning label: + + m_warningLabel = util::tool::explanationLabel(this, tr("WARNING!!!"), + tr("If you live in a persecuted country and don't want to risk " + "detection don't use remote sources.")); + + // Source chooser: + m_sourceGroupBox = new QGroupBox(tr("Select installation &source:"), this); + m_sourceGroupBox->setFlat(true); + + m_sourceComboBox = new QComboBox(this); + m_sourceComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + initSourcesCombo(); + + m_sourceAddButton = new QPushButton(tr("&Add...")); + m_sourceAddButton ->setToolTip(tr("Add new source")); + m_sourceAddButton ->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::add_icon)); + + m_sourceDeleteButton = new QPushButton(tr("&Delete...")); + m_sourceDeleteButton->setToolTip(tr("Delete this source")); + m_sourceDeleteButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::delete_icon)); + + QHBoxLayout *sourceChooserLayout = new QHBoxLayout(); + sourceChooserLayout->setContentsMargins(0, 0, 0, 0); + sourceChooserLayout->addWidget(m_sourceComboBox, 1); + sourceChooserLayout->addWidget(m_sourceAddButton); + sourceChooserLayout->addWidget(m_sourceDeleteButton); + m_sourceGroupBox->setLayout(sourceChooserLayout); + + // Works chooser: + m_worksGroupBox = new QGroupBox(tr("Select &works to install:"), this); + m_worksGroupBox->setFlat(true); + m_worksLayout = new QStackedLayout(); + m_worksGroupBox->setLayout(m_worksLayout); + slotSourceIndexChanged(m_sourceComboBox->currentIndex()); + + // Installation path chooser: + m_installGroupBox = new QGroupBox(this); + m_installGroupBox->setFlat(true); + retranslateInstallGroupBox(); + + m_pathLabel = new QLabel(tr("Install &folder:")); + m_pathCombo = new QComboBox(this); m_pathCombo->setMinimumContentsLength(20); m_pathCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); m_pathCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_pathCombo->setToolTip(tr("The folder where the new works will be installed")); m_pathCombo->view()->setTextElideMode(Qt::ElideMiddle); - initPathCombo(); // set the paths and the current path + m_pathLabel->setBuddy(m_pathCombo); + initPathCombo(); + m_configurePathButton = new QToolButton(this); m_configurePathButton->setToolTip(tr("Configure folders where works are installed and found")); m_configurePathButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::path_icon)); - pathLayout->addWidget(pathLabel); - pathLayout->addWidget(m_pathCombo); - pathLayout->addWidget(m_configurePathButton); - mainLayout->addLayout(pathLayout); - - // Source widget - m_sourceWidget = new BtSourceWidget(this); - mainLayout->addWidget(m_sourceWidget); - // Install button - QHBoxLayout *installButtonLayout = new QHBoxLayout(); - installButtonLayout->setContentsMargins(0, 5, 0, 5); - QSpacerItem *installButtonSpacer = new QSpacerItem(371, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - installButtonLayout->addItem(installButtonSpacer); - m_installButton = new QPushButton(tr("Install..."), this); + m_installButton = new QPushButton(tr("&Install..."), this); m_installButton->setToolTip(tr("Install or update selected works")); m_installButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::install_icon)); m_installButton->setEnabled(false); - installButtonLayout->addWidget(m_installButton); - mainLayout->addLayout(installButtonLayout); + QHBoxLayout *pathLayout = new QHBoxLayout(); + pathLayout->setContentsMargins(0, 0, 0, 0); + pathLayout->addWidget(m_pathLabel); + pathLayout->addWidget(m_pathCombo); + pathLayout->addWidget(m_configurePathButton); + pathLayout->addWidget(m_installButton); + m_installGroupBox->setLayout(pathLayout); + + Q_ASSERT(qobject_cast<QVBoxLayout*>(layout()) != 0); + QVBoxLayout *mainLayout = static_cast<QVBoxLayout*>(layout()); + mainLayout->addWidget(m_warningLabel); + mainLayout->addWidget(m_sourceGroupBox); + mainLayout->addWidget(m_worksGroupBox, 1); + mainLayout->addWidget(m_installGroupBox); } void BtInstallPage::initConnections() { - qDebug() << "void BtInstallPage::initConnections() start"; - QObject::connect(m_pathCombo, SIGNAL(activated(const QString&)), this , SLOT(slotPathChanged(const QString&))); - QObject::connect(m_configurePathButton, SIGNAL(clicked()), this, SLOT(slotEditPaths())); - QObject::connect(m_installButton, SIGNAL(clicked()), m_sourceWidget, SLOT(slotInstall()) ); - - QObject::connect(CPointers::backend(), SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)), this, SLOT(slotSwordSetupChanged())); - //source widget has its own connections, not here + connect(m_sourceComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotSourceIndexChanged(int))); + connect(m_sourceAddButton, SIGNAL(clicked()), + this, SLOT(slotSourceAdd())); + connect(m_sourceDeleteButton, SIGNAL(clicked()), + this, SLOT(slotSourceDelete())); + connect(m_installButton, SIGNAL(clicked()), + this, SLOT(slotInstall())); + connect(m_pathCombo, SIGNAL(activated(const QString&)), + this , SLOT(slotPathChanged(const QString&))); + connect(m_configurePathButton, SIGNAL(clicked()), + this, SLOT(slotEditPaths())); + connect(CSwordBackend::instance(), + SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)), + this, SLOT(slotSwordSetupChanged())); } void BtInstallPage::initPathCombo() { - qDebug() << "void BtInstallPage::initPathCombo() start"; //populate the combo list m_pathCombo->clear(); - QStringList targets = instbackend::targetList(); + QStringList targets = BtInstallBackend::targetList(); for (QStringList::iterator it = targets.begin(); it != targets.end(); ++it) { // Add the path only if it's writable if ((*it).isEmpty()) continue; @@ -154,43 +188,252 @@ void BtInstallPage::initPathCombo() { m_pathCombo->setCurrentIndex(index); } +void BtInstallPage::initSourcesCombo() { + /// \todo Implement a proper model for this + + m_sourceComboBox->clear(); + QStringList sourceList = BtInstallBackend::sourceNameList(); + + // Add a default entry, the Crosswire main repository + if (sourceList.empty()) { + /// \todo Open a dialog which asks whether to get list from server and add sources + sword::InstallSource is("FTP"); //default return value + is.caption = "CrossWire Bible Society"; + is.source = "ftp.crosswire.org"; + is.directory = "/pub/sword/raw"; + // passive ftp is not needed here, it's the default + + BtInstallBackend::addSource(is); + + sourceList = BtInstallBackend::sourceNameList(); + Q_ASSERT(!sourceList.empty()); + } + + // Read selected module from config: + QString selected = CBTConfig::getConfig()->value(selectedModuleKey).toString(); + + // Populate combo box + bool selectionOk = false; + for (int i = 0; i < sourceList.size(); i++) { + m_sourceComboBox->addItem(sourceList.at(i)); + + // Select configured item: + if (!selectionOk && sourceList.at(i) == selected) { + m_sourceComboBox->setCurrentIndex(i); + selectionOk = true; + } + } + + // Set selection, if it wasn't properly configured: + if (!selectionOk) { + m_sourceComboBox->setCurrentIndex(0); + CBTConfig::getConfig()->setValue(selectedModuleKey, sourceList.at(0)); + } +} + +void BtInstallPage::activateSource(const sword::InstallSource &src) { + qDebug() << "Selected source" << src.caption; + qApp->setOverrideCursor(Qt::WaitCursor); + BtInstallPageWorksWidget *w = m_sourceMap.value(QString(src.caption), 0); + if (w == 0) { + if (parentDialog() != 0) parentDialog()->setEnabled(false); + qApp->processEvents(); + w = new BtInstallPageWorksWidget(src, m_groupingOrder, this); + m_sourceMap.insert(QString(src.caption), w); + m_worksLayout->addWidget(w); + connect(w->treeModel(), SIGNAL(groupingOrderChanged(BtBookshelfTreeModel::Grouping)), + this, SLOT(slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping&))); + connect(w->treeModel(), SIGNAL(moduleChecked(CSwordModuleInfo*,bool)), + this, SLOT(slotSelectedModulesChanged())); + if (parentDialog() != 0) parentDialog()->setEnabled(true); + } else { + disconnect(w->treeView()->header(), SIGNAL(geometriesChanged()), + this, SLOT(slotHeaderChanged())); + } + m_worksLayout->setCurrentWidget(w); + w->treeModel()->setGroupingOrder(m_groupingOrder); + w->treeView()->header()->restoreState(m_headerState); + connect(w->treeView()->header(), SIGNAL(geometriesChanged()), + this, SLOT(slotHeaderChanged())); + qApp->restoreOverrideCursor(); +} + +void BtInstallPage::retranslateInstallGroupBox() { + if (m_modulesSelected > 0) { + m_installGroupBox->setTitle(tr("Start installation of %1 works from %2 sources:") + .arg(m_modulesSelected) + .arg(m_modulesSelectedSources)); + } else { + m_installGroupBox->setTitle(tr("Start installation:")); + } +} + +void BtInstallPage::slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g) { + m_groupingOrder = g; + m_groupingOrder.saveTo(groupingOrderKey); +} + +void BtInstallPage::slotHeaderChanged() { + typedef BtInstallPageWorksWidget IPWW; + Q_ASSERT(qobject_cast<IPWW*>(m_worksLayout->currentWidget()) != 0); + IPWW *w = static_cast<IPWW*>(m_worksLayout->currentWidget()); + m_headerState = w->treeView()->header()->saveState(); + CBTConfig::getConfig()->setValue(headerStateKey, m_headerState); +} + +void BtInstallPage::slotInstall() { + qDebug() << "BtInstallPage::slotInstall"; + + // check that the destination path is writable, do nothing if not and user doesn't want to continue + QDir dir = selectedInstallPath(); + bool canWrite = true; + if (dir.isReadable()) { + const QFileInfo fi( dir.canonicalPath() ); + if (!fi.exists() || !fi.isWritable()) { + canWrite = false; + } + } + else { + canWrite = false; + } + if (!canWrite) { + const int result = util::showWarning(this, tr("Warning"), tr("The destination directory is not writable or does not exist. Installation will fail unless this has first been fixed."), QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Cancel); + if (result != QMessageBox::Ignore) { + return; + } + } + + // create the confirmation dialog + BtInstallModuleChooserDialog *dlg = new BtInstallModuleChooserDialog(m_groupingOrder, this); + + // Add all checked modules from all tabs: + Q_FOREACH (BtInstallPageWorksWidget *w, m_sourceMap.values()) { + Q_FOREACH (CSwordModuleInfo *module, w->treeModel()->checkedModules()) { + dlg->addModuleItem(module, QString(w->installSource().caption)); + } + } + + if (dlg->exec() == QDialog::Accepted) { + QSet<const CSwordModuleInfo*> cm; + Q_FOREACH(const CSwordModuleInfo *m, dlg->checkedModules()) { + cm.insert(m); + } + + if (cm.empty()) return; + + /// \todo first remove all modules which will be updated from the module list + // but what modules? all with the same real name? (there may be _n modules...) + + BtModuleManagerDialog *parentDlg = dynamic_cast<BtModuleManagerDialog*>(parentDialog()); + + BtInstallProgressDialog *dlg = new BtInstallProgressDialog(cm, selectedInstallPath(), parentDlg); + + if (!parentDlg) qDebug() << "error, wrong parent!"; + + m_installButton->setEnabled(false); + + // the progress dialog is now modal, it can be made modeless later. + dlg->exec(); + + qDebug() << "BtSourceWidget::slotInstallAccepted end"; + } + delete dlg; +} + void BtInstallPage::slotPathChanged(const QString& /*pathText*/) { CBTConfig::set(CBTConfig::installPathIndex, m_pathCombo->currentIndex( ) ); } void BtInstallPage::slotEditPaths() { - qDebug() << "void BtInstallPage::slotEditPaths() start"; - BtInstallPathDialog* dlg = new BtInstallPathDialog(); int result = dlg->exec(); if (result == QDialog::Accepted) { //dynamic_cast<BtModuleManagerDialog*>(parentDialog())->slotSwordSetupChanged(); - CPointers::backend()->reloadModules(CSwordBackend::PathChanged); + CSwordBackend::instance()->reloadModules(CSwordBackend::PathChanged); } } -// implement the BtConfigPage methods +void BtInstallPage::slotSourceAdd() { + typedef CSwordSetupInstallSourcesDialog SSISD; -QString BtInstallPage::iconName() { - return CResMgr::bookshelfmgr::installpage::icon; + QSharedPointer<SSISD> dlg(new SSISD()); + if (dlg->exec() == QDialog::Accepted) { + if (!dlg->wasRemoteListAdded()) { + sword::InstallSource newSource = dlg->getSource(); + if ( !((QString)newSource.type.c_str()).isEmpty() ) { // we have a valid source to add + BtInstallBackend::addSource(newSource); + } + initSourcesCombo(); + for (int i = 0; i < m_sourceComboBox->count(); i++) { + if (m_sourceComboBox->itemText(i) == newSource.caption) { + m_sourceComboBox->setCurrentIndex(i); + break; + } + } + } + } } -QString BtInstallPage::label() { - // \todo move the warning to a dialog which is shown when adding a source. - return tr("Install and update works. Add remote or local sources, refresh them, select the works to be installed/updated and click Install.<br/><b>WARNING:</b> If you live in a persecuted country and don't want to risk detection don't use remote sources."); + +void BtInstallPage::slotSourceDelete() { + typedef BtInstallPageWorksWidget IPWW; + + int ret = util::showWarning(this, tr("Delete Source?"), + tr("Do you really want to delete this source?"), + QMessageBox::Yes | QMessageBox::No); + + if (ret == QMessageBox::Yes) { + Q_ASSERT(qobject_cast<IPWW*>(m_worksLayout->currentWidget())); + IPWW *w = static_cast<IPWW*>(m_worksLayout->currentWidget()); + w->deleteSource(); + initSourcesCombo(); + slotSourceIndexChanged(m_sourceComboBox->currentIndex()); + delete w; + } } -QString BtInstallPage::header() { - return tr("Install/Update"); + +void BtInstallPage::slotSourceIndexChanged(int index) { + if (index < 0) index = 0; + + /// \todo use pointers instead of text + QString moduleName = m_sourceComboBox->itemText(index); + CBTConfig::getConfig()->setValue(selectedModuleKey, moduleName); + activateSource(BtInstallBackend::source(moduleName)); } -void BtInstallPage::slotSwordSetupChanged() { - qDebug() << "BtInstallPage::slotSwordSetupChanged"; - initPathCombo(); -// for (int i = 0; i < m_sourceWidget->count(); i++ ) { -// BtSourceArea* sourceArea = dynamic_cast<BtSourceArea*>(m_sourceWidget->widget(i)); -// Q_ASSERT(sourceArea); -// sourceArea->createModuleTree(); -// } +void BtInstallPage::slotSelectedModulesChanged() { + m_modulesSelected = 0; + m_modulesSelectedSources = 0; + Q_FOREACH (BtInstallPageWorksWidget *w, m_sourceMap.values()) { + int selected = w->treeModel()->checkedModules().size(); + if (selected > 0) { + m_modulesSelectedSources++; + m_modulesSelected += selected; + } + } + + m_installButton->setEnabled(m_modulesSelected > 0); + retranslateInstallGroupBox(); +} + +// implement the BtConfigPage methods + +const QIcon &BtInstallPage::icon() const { + return util::directory::getIcon(CResMgr::bookshelfmgr::installpage::icon); } +QString BtInstallPage::header() const { + return tr("Install/Update"); +} +void BtInstallPage::slotSwordSetupChanged() { + QString moduleName = m_sourceComboBox->currentText(); + initSourcesCombo(); + qDeleteAll(m_sourceMap.values()); + m_sourceMap.clear(); + m_sourceComboBox->setCurrentIndex(m_sourceComboBox->findText(moduleName)); + initPathCombo(); + m_modulesSelected = 0; + m_modulesSelectedSources = 0; + retranslateInstallGroupBox(); +} diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpage.h b/src/frontend/bookshelfmanager/installpage/btinstallpage.h index fde9919..88d1f92 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallpage.h +++ b/src/frontend/bookshelfmanager/installpage/btinstallpage.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -12,29 +12,34 @@ #include "frontend/bookshelfmanager/btconfigdialog.h" -#include <QString> +#include "backend/bookshelfmodel/btbookshelftreemodel.h" -// Sword includes: -#include <installmgr.h> +namespace sword { +class InstallSource; +} -class BtSourceWidget; +class BtInstallPageWorksWidget; class QComboBox; +class QGroupBox; class QPushButton; +class QStackedLayout; class QToolButton; /** * The Install page includes module path chooser, source/module handler and install button. */ -class BtInstallPage : public BtConfigPage { +class BtInstallPage: public BtConfigPage { Q_OBJECT + public: - BtInstallPage(); + BtInstallPage(QWidget *parent = 0); + + /** Reimplemented from BtConfigPage. */ + virtual const QIcon &icon() const; - // reimplemented from btinstallpage - QString iconName(); - QString label(); - QString header(); + /** Reimplemented from BtConfigPage. */ + virtual QString header() const; void setInstallEnabled(bool b); @@ -47,18 +52,46 @@ class BtInstallPage : public BtConfigPage { void initView(); void initConnections(); void initPathCombo(); + void initSourcesCombo(); + + void activateSource(const sword::InstallSource &src); + void retranslateInstallGroupBox(); private slots: + void slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g); + void slotHeaderChanged(); + void slotInstall(); void slotPathChanged(const QString& pathText); void slotEditPaths(); + void slotSourceAdd(); + void slotSourceDelete(); + void slotSourceIndexChanged(int index); + void slotSelectedModulesChanged(); private: + BtBookshelfTreeModel::Grouping m_groupingOrder; + QByteArray m_headerState; + + QMap<QString, BtInstallPageWorksWidget*> m_sourceMap; + + QLabel *m_warningLabel; + + QGroupBox *m_sourceGroupBox; + QComboBox *m_sourceComboBox; + QPushButton *m_sourceAddButton; + QPushButton *m_sourceDeleteButton; + + QGroupBox *m_worksGroupBox; + QStackedLayout *m_worksLayout; + + QGroupBox *m_installGroupBox; + QLabel *m_pathLabel; + QComboBox *m_pathCombo; + QToolButton *m_configurePathButton; + QPushButton *m_installButton; - QComboBox* m_pathCombo; - //QPushButton* m_configurePathButton; - QToolButton* m_configurePathButton; - BtSourceWidget* m_sourceWidget; - QPushButton* m_installButton; + unsigned m_modulesSelected; + unsigned m_modulesSelectedSources; }; #endif diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.cpp b/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.cpp new file mode 100644 index 0000000..9aa6743 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.cpp @@ -0,0 +1,87 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#include "frontend/bookshelfmanager/installpage/btinstallpagemodel.h" + + +#include "backend/drivers/cswordmoduleinfo.h" +#include "backend/managers/cswordbackend.h" + + +#define MODULEPOINTERFORINDEX(i) static_cast<CSwordModuleInfo *>(\ + BtBookshelfTreeModel::data((i), BtBookshelfModel::ModulePointerRole).value<void*>()) + +BtInstallPageModel::BtInstallPageModel(const Grouping &grouping, QObject *parent) + : BtBookshelfTreeModel(grouping, parent) +{ + setDefaultChecked(BtBookshelfTreeModel::UNCHECKED); + setCheckable(true); +} + +BtInstallPageModel::~BtInstallPageModel() { + // Intentionally empty +} + +QVariant BtInstallPageModel::data(const QModelIndex &i, int role) const { + switch (role) { + case Qt::DisplayRole: + switch (i.column()) { + case 0: + return BtBookshelfTreeModel::data(i, role); + case 1: + { + CSwordModuleInfo *module = MODULEPOINTERFORINDEX(index(i.row(), 0, i.parent())); + if (module == 0) break; + CSwordBackend *b = CSwordBackend::instance(); + CSwordModuleInfo *imodule = b->findModuleByName(module->name()); + if (imodule == 0) { + return module->config(CSwordModuleInfo::ModuleVersion); + } else { + return imodule->config(CSwordModuleInfo::ModuleVersion) + + " => " + + module->config(CSwordModuleInfo::ModuleVersion); + } + } + case 2: + { + CSwordModuleInfo *module = MODULEPOINTERFORINDEX(index(i.row(), 0, i.parent())); + if (module != 0) return module->config(CSwordModuleInfo::Description); + } + default: break; + } + default: + if (i.column() == 0) return BtBookshelfTreeModel::data(i, role); + } + + return QVariant(); +} + +int BtInstallPageModel::columnCount(const QModelIndex &parent) const { + Q_UNUSED(parent); + + return 3; +} + +QVariant BtInstallPageModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + switch (section) { + case 0: return tr("Work"); + case 1: return tr("Version"); + case 2: return tr("Description"); + default: break; + } + } + + return QVariant(); +} diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.h b/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.h new file mode 100644 index 0000000..8a02409 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallpagemodel.h @@ -0,0 +1,33 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#ifndef BTINSTALLPAGEMODEL_H +#define BTINSTALLPAGEMODEL_H + +#include "backend/bookshelfmodel/btbookshelftreemodel.h" + +#include <QMap> + + +class BtInstallPageModel: public BtBookshelfTreeModel { + Q_OBJECT + public: + BtInstallPageModel(const Grouping &grouping, QObject *parent = 0); + ~BtInstallPageModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; +}; + +#endif // BTINSTALLPAGEMODEL_H diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.cpp b/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.cpp new file mode 100644 index 0000000..6b9fb53 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.cpp @@ -0,0 +1,140 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "frontend/bookshelfmanager/installpage/btinstallpageworkswidget.h" + +#include <QApplication> +#include <QAction> +#include <QDebug> +#include <QTimer> +#include <QToolButton> +#include "backend/btinstallbackend.h" +#include "backend/managers/cswordbackend.h" +#include "frontend/bookshelfmanager/installpage/btinstallpage.h" +#include "frontend/bookshelfmanager/installpage/btinstallpagemodel.h" +#include "frontend/bookshelfmanager/installpage/btrefreshprogressdialog.h" +#include "frontend/btbookshelfview.h" +#include "util/cresmgr.h" +#include "util/directory.h" + + +namespace { + +/** Filters out already installed modules which can't be updated right now. */ +bool filter(CSwordModuleInfo *mInfo) { + typedef CSwordModuleInfo CSMI; + typedef sword::SWVersion SV; + + const CSMI *installedModule = CSwordBackend::instance()->findModuleByName(mInfo->name()); + if (installedModule) { + // Already installed, check if it's an update: + const SV curVersion(installedModule->config(CSMI::ModuleVersion).toLatin1()); + const SV newVersion(mInfo->config(CSMI::ModuleVersion).toLatin1()); + if (curVersion >= newVersion) { + return false; + } + } + return true; +} + +} + +BtInstallPageWorksWidget::BtInstallPageWorksWidget( + const sword::InstallSource &source, + const BtBookshelfTreeModel::Grouping &g, + BtInstallPage *parent, Qt::WindowFlags flags) + : BtBookshelfWidget(parent, flags) + , m_source(source) + , m_parent(parent) + , m_backend(0) + , m_myModel(0) +{ + namespace DU = util::directory; + + qDebug() << "Creating new BtInstallPageWorksWidget for source" << source.caption; + + setTreeModel(new BtInstallPageModel(g, this)); + + treeView()->setHeaderHidden(false); + showHideButton()->hide(); + showHideAction()->setVisible(false); + + m_sourceRefreshButton = new QToolButton(this); + m_sourceRefreshButton->setAutoRaise(true); + m_sourceRefreshButton ->setToolTip(tr("Refresh the list of works from this source")); + m_sourceRefreshButton ->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::refresh_icon)); + setRightCornerWidget(m_sourceRefreshButton); + + connect(m_sourceRefreshButton, SIGNAL(clicked()), + this, SLOT(slotSourceRefresh())); + + // Delayed init, part 1 - disable parent: + parent->setEnabled(false); +} + +BtInstallPageWorksWidget::~BtInstallPageWorksWidget() { + qDebug() << "Deleting BtInstallPageWorksWidget for source" << m_source.caption; + + delete m_backend; +} + +void BtInstallPageWorksWidget::deleteSource() { + qDebug() << "Deleting source" << m_source.caption; + + setEnabled(false); + m_myModel->clear(); + BtInstallBackend::deleteSource(QString(m_source.caption)); +} + +void BtInstallPageWorksWidget::updateTree() { + qDebug() << "Updating BtInstallPageWorksWidget tree for source" << m_source.caption; + + m_myModel->clear(); + + // Is this necessary? + m_source = BtInstallBackend::source(QString(m_source.caption)); + m_backend = BtInstallBackend::backend(m_source); + + // Repopulate model: + Q_FOREACH(CSwordModuleInfo *module, m_backend->moduleList()) { + if (filter(module)) m_myModel->addModule(module); + } +} + +void BtInstallPageWorksWidget::paintEvent(QPaintEvent *e) { + // Delayed init, part 2 - queue init when painted: + if (m_myModel == 0) { + QTimer::singleShot(0, this, SLOT(slotDelayedInit())); + } + BtBookshelfWidget::paintEvent(e); +} + +void BtInstallPageWorksWidget::slotDelayedInit() { + // Delayed init, part 3 - initialize + reenable parent + qApp->setOverrideCursor(Qt::WaitCursor); + m_backend = BtInstallBackend::backend(m_source); + Q_ASSERT(m_backend != 0); + m_myModel = new BtBookshelfModel(this); + Q_FOREACH(CSwordModuleInfo *module, m_backend->moduleList()) { + if (filter(module)) m_myModel->addModule(module); + } + setSourceModel(m_myModel); + m_parent->setEnabled(true); + qApp->restoreOverrideCursor(); +} + +void BtInstallPageWorksWidget::slotSourceRefresh() { + qDebug() << "Refreshing source" << m_source.caption; + + if (BtInstallBackend::isRemote(m_source)) { + BtRefreshProgressDialog d(m_source, this); + if (!d.runAndDelete()) return; + } + updateTree(); +} diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.h b/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.h new file mode 100644 index 0000000..1a9bd8f --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btinstallpageworkswidget.h @@ -0,0 +1,59 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef BTINSTALLPAGEWORKSWIDGET_H +#define BTINSTALLPAGEWORKSWIDGET_H + + +#include "frontend/btbookshelfwidget.h" + +// Sword includes +#include <installmgr.h> + + +class BtInstallPage; + +class BtInstallPageWorksWidget: public BtBookshelfWidget { + Q_OBJECT + + public: /* Methods: */ + + BtInstallPageWorksWidget(const sword::InstallSource &source, + const BtBookshelfTreeModel::Grouping &g, + BtInstallPage *parent, Qt::WindowFlags f = 0); + + ~BtInstallPageWorksWidget(); + + inline const sword::InstallSource &installSource() const { + return m_source; + } + void deleteSource(); + + private: /* Methods: */ + + void updateTree(); + + /** Reimplemented from QWidget. */ + virtual void paintEvent(QPaintEvent *e); + + private slots: + + void slotDelayedInit(); + void slotSourceRefresh(); + + private: /* Fields: */ + + sword::InstallSource m_source; + BtInstallPage *m_parent; + QToolButton *m_sourceRefreshButton; + CSwordBackend *m_backend; + BtBookshelfModel *m_myModel; +}; + +#endif // BTINSTALLPAGEWORKSWIDGET_H diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.cpp b/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.cpp index 9efb9f0..a272d89 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.cpp +++ b/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -15,13 +15,12 @@ #include <QDir> #include <QFileDialog> #include <QGridLayout> -#include <QHeaderView> #include <QLabel> #include <QPushButton> #include <QString> #include <QTreeWidget> #include <QTreeWidgetItem> -#include "frontend/bookshelfmanager/instbackend.h" +#include "backend/btinstallbackend.h" #include "util/dialogutil.h" #include "util/directory.h" #include "util/cresmgr.h" @@ -47,7 +46,7 @@ BtInstallPathDialog::BtInstallPathDialog() { tr("Configure bookshelf folders"), l1 + QString("<small><br/><br/>") + l2 + QString("</small>")); mainLayout->addWidget(mainLabel); - QString swordConfPath = instbackend::swordConfigFilename(); + QString swordConfPath = BtInstallBackend::swordConfigFilename(); /// \todo After releasing 2.4, change the following line to: QLabel *confPathLabel = new QLabel(tr("Configuration file for the folders is: <b>%1</b>").arg(swordConfPath), this); QLabel* confPathLabel = new QLabel(tr("Configuration file for the folders is: ").append("<b>%1</b>").arg(swordConfPath), this); confPathLabel->setWordWrap(true); @@ -55,7 +54,7 @@ BtInstallPathDialog::BtInstallPathDialog() { m_swordPathListBox = new QTreeWidget(this); - m_swordPathListBox->header()->hide(); + m_swordPathListBox->setHeaderHidden(true); QString rwfolderitem(tr("Folders where new works can be installed")); m_writableItem = new QTreeWidgetItem(m_swordPathListBox, QStringList(rwfolderitem));; @@ -65,7 +64,7 @@ BtInstallPathDialog::BtInstallPathDialog() { m_nonexistingItem = new QTreeWidgetItem(m_swordPathListBox, QStringList(tr("Nonexistent folders")));; m_nonexistingItem->setFlags(Qt::ItemIsEnabled); - QStringList targets = instbackend::targetList(); + QStringList targets = BtInstallBackend::targetList(); foreach (QString pathname, targets) { addPathToList(pathname); @@ -76,19 +75,19 @@ BtInstallPathDialog::BtInstallPathDialog() { QVBoxLayout* buttonLayout = new QVBoxLayout(); - m_addButton = new QPushButton(tr("Add..."), this); + m_addButton = new QPushButton(tr("&Add..."), this); m_addButton->setToolTip(tr("Add new folder")); m_addButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::paths::add_icon)); connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAddClicked())); buttonLayout->addWidget(m_addButton); - m_editButton = new QPushButton(tr("Edit..."), this); + m_editButton = new QPushButton(tr("&Edit..."), this); m_editButton->setToolTip(tr("Edit the selected folder")); m_editButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::paths::edit_icon)); connect(m_editButton, SIGNAL(clicked()), this, SLOT(slotEditClicked())); buttonLayout->addWidget(m_editButton); - m_removeButton = new QPushButton(tr("Remove"), this); + m_removeButton = new QPushButton(tr("&Remove"), this); m_removeButton->setToolTip(tr("Remove the selected folder")); m_removeButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::paths::remove_icon)); connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveClicked())); @@ -162,7 +161,7 @@ void BtInstallPathDialog::addPathToList(QString pathname) { i = new QTreeWidgetItem(m_readableItem, QStringList(pathname) ); } } - if (i && QDir(pathname) == instbackend::swordDir()) { + if (i && QDir(pathname) == BtInstallBackend::swordDir()) { i->setFlags(Qt::NoItemFlags); i->setToolTip(0, tr("This default folder in your home directory can't be removed")); } @@ -231,7 +230,7 @@ void BtInstallPathDialog::writeSwordConfig() { ++it; } qDebug() << "save the target list" << targets; - instbackend::setTargetList(targets); //creates new Sword config + BtInstallBackend::setTargetList(targets); //creates new Sword config } void BtInstallPathDialog::accept() { diff --git a/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.h b/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.h index e72da3c..9adf6bc 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.h +++ b/src/frontend/bookshelfmanager/installpage/btinstallpathdialog.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ diff --git a/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.cpp b/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.cpp index 365d5c8..465ec03 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.cpp +++ b/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -22,11 +22,13 @@ #include <QVBoxLayout> #include "backend/managers/cswordbackend.h" #include "frontend/bookshelfmanager/installpage/btinstallthread.h" -#include "util/cpointers.h" -BtInstallProgressDialog::BtInstallProgressDialog(QWidget* parent, QTreeWidget* selectedModulesTreeWidget, QString destination) - : QDialog(parent) { +BtInstallProgressDialog::BtInstallProgressDialog( + const QSet<const CSwordModuleInfo*> &modules, + const QString &destination, QWidget *parent, Qt::WindowFlags flags) + : QDialog(parent, flags) +{ // we want this dialog to be deleted when user closes it or the downloads are completed setAttribute(Qt::WA_DeleteOnClose, true); setWindowTitle(tr("Install Progress")); @@ -39,39 +41,34 @@ BtInstallProgressDialog::BtInstallProgressDialog(QWidget* parent, QTreeWidget* s m_statusWidget->header()->setMovable(false); //m_statusWidget->setColumnWidth(1, util::tool::mWidth(m_statusWidget, 2)); - foreach (QTreeWidgetItem* sourceItem, selectedModulesTreeWidget->invisibleRootItem()->takeChildren()) { - // create items and threads for modules under this source - foreach (QTreeWidgetItem* moduleItem, sourceItem->takeChildren()) { - if (moduleItem->checkState(0) == Qt::Checked) { - // create a thread for this module - BtInstallThread* thread = new BtInstallThread(this, moduleItem->text(0), sourceItem->text(0), destination); - m_waitingThreads.insert(sourceItem->text(0), thread); - m_threadsByModule.insert(moduleItem->text(0), thread); - // progress widget/item - QPushButton* stopButton = new QPushButton(tr("Stop"), m_statusWidget); - stopButton->setFixedSize(stopButton->sizeHint()); - - // the item - QTreeWidgetItem* progressItem = new QTreeWidgetItem(m_statusWidget); - m_statusWidget->setColumnWidth(2, stopButton->sizeHint().width()); - progressItem->setSizeHint(2, stopButton->sizeHint()); - progressItem->setText(0, moduleItem->text(0)); - progressItem->setFlags(Qt::ItemIsEnabled); - m_statusWidget->setItemWidget(progressItem, 2, stopButton); - progressItem->setText(1, tr("Waiting for turn...")); - - //connect the signals between the dialog, items and threads - QObject::connect(stopButton, SIGNAL(clicked()), thread, SLOT(slotStopInstall()), Qt::QueuedConnection); - QObject::connect(thread, SIGNAL(installStopped(QString, QString)), this, SLOT(slotOneItemStopped(QString, QString)), Qt::QueuedConnection); - //is this needed or is statusUpdated enough? - QObject::connect(thread, SIGNAL(installCompleted(QString, QString, int)), this, SLOT(slotOneItemCompleted(QString, QString, int)), Qt::QueuedConnection); - QObject::connect(thread, SIGNAL(statusUpdated(QString, int)), this, SLOT(slotStatusUpdated(QString, int)), Qt::QueuedConnection); - QObject::connect(thread, SIGNAL(downloadStarted(QString)), this, SLOT(slotDownloadStarted(QString)), Qt::QueuedConnection); - - QObject::connect(thread, SIGNAL(preparingInstall(QString, QString)), this, SLOT(slotInstallStarted(QString, QString)), Qt::QueuedConnection); - - } - } + Q_FOREACH(const CSwordModuleInfo *module, modules) { + const QString sourceName(module->property("installSourceName").toString()); + // create a thread for this module + BtInstallThread* thread = new BtInstallThread(module->name(), sourceName, destination); + m_waitingThreads.insert(sourceName, thread); + m_threadsByModule.insert(module->name(), thread); + // progress widget/item + QPushButton* stopButton = new QPushButton(tr("Stop"), m_statusWidget); + stopButton->setFixedSize(stopButton->sizeHint()); + + // the item + QTreeWidgetItem* progressItem = new QTreeWidgetItem(m_statusWidget); + m_statusWidget->setColumnWidth(2, stopButton->sizeHint().width()); + progressItem->setSizeHint(2, stopButton->sizeHint()); + progressItem->setText(0, module->name()); + progressItem->setFlags(Qt::ItemIsEnabled); + m_statusWidget->setItemWidget(progressItem, 2, stopButton); + progressItem->setText(1, tr("Waiting for turn...")); + + //connect the signals between the dialog, items and threads + QObject::connect(stopButton, SIGNAL(clicked()), thread, SLOT(slotStopInstall()), Qt::QueuedConnection); + QObject::connect(thread, SIGNAL(installStopped(QString, QString)), this, SLOT(slotOneItemStopped(QString, QString)), Qt::QueuedConnection); + //is this needed or is statusUpdated enough? + QObject::connect(thread, SIGNAL(installCompleted(QString, QString, int)), this, SLOT(slotOneItemCompleted(QString, QString, int)), Qt::QueuedConnection); + QObject::connect(thread, SIGNAL(statusUpdated(QString, int)), this, SLOT(slotStatusUpdated(QString, int)), Qt::QueuedConnection); + QObject::connect(thread, SIGNAL(downloadStarted(QString)), this, SLOT(slotDownloadStarted(QString)), Qt::QueuedConnection); + + QObject::connect(thread, SIGNAL(preparingInstall(QString, QString)), this, SLOT(slotInstallStarted(QString, QString)), Qt::QueuedConnection); } m_statusWidget->setMinimumWidth(m_statusWidget->size().width()); @@ -93,22 +90,22 @@ void BtInstallProgressDialog::startThreads() { // remove all the updated modules from the backend module list at once //foreach (QString mName, m_threadsByModule.keys()) { //} - //QList<CSwordModuleInfo*> CPointers::backend()->takeModulesFromList(m_threadsByModule.keys()); + //QList<CSwordModuleInfo*> CSwordBackend::instance()()->takeModulesFromList(m_threadsByModule.keys()); qDebug() << "start threads..."; //loop through the multimap of the waiting threads, start at most 3 threads for each source QMultiMap<QString, BtInstallThread*>::iterator threadIterator = m_waitingThreads.end(); // concurrency is disabled for now -// while (threadIterator != m_waitingThreads.end()) { -// QString sourceName = threadIterator.key(); -// qDebug() << sourceName; -// if (m_runningThreads.values(sourceName).count() < 3) { -// BtInstallThread* t = threadIterator.value(); -// m_runningThreads.insert(sourceName, t); -// threadIterator = m_waitingThreads.erase(threadIterator); -// t->start(); -// } -// else ++threadIterator; -// } +// while (threadIterator != m_waitingThreads.end()) { +// QString sourceName = threadIterator.key(); +// qDebug() << sourceName; +// if (m_runningThreads.values(sourceName).count() < 3) { +// BtInstallThread* t = threadIterator.value(); +// m_runningThreads.insert(sourceName, t); +// threadIterator = m_waitingThreads.erase(threadIterator); +// t->start(); +// } +// else ++threadIterator; +// } //non-concurrent if (threadIterator != m_waitingThreads.begin()) { // go to the last item which is actually the first in the visible list @@ -157,16 +154,16 @@ void BtInstallProgressDialog::oneItemStoppedOrCompleted(QString module, QString m_waitingThreads.remove(source, m_threadsByModule.value(module)); //concurrency is disabled for now -// //start a waiting thread if there are any -// QList<BtInstallThread*> threadsForSource = m_waitingThreads.values(source); -// qDebug() << threadsForSource; -// if (!threadsForSource.isEmpty()) { -// qDebug() << "Threads are waiting for turn"; -// BtInstallThread* thread = threadsForSource.at(0); -// m_waitingThreads.remove(source, thread); -// m_runningThreads.insert(source, thread); -// thread->start(); -// } +// //start a waiting thread if there are any +// QList<BtInstallThread*> threadsForSource = m_waitingThreads.values(source); +// qDebug() << threadsForSource; +// if (!threadsForSource.isEmpty()) { +// qDebug() << "Threads are waiting for turn"; +// BtInstallThread* thread = threadsForSource.at(0); +// m_waitingThreads.remove(source, thread); +// m_runningThreads.insert(source, thread); +// thread->start(); +// } //non-concurrent QMultiMap<QString, BtInstallThread*>::iterator threadIterator = m_waitingThreads.end(); @@ -238,7 +235,7 @@ void BtInstallProgressDialog::closeEvent(QCloseEvent* event) { return; } // other parts of the UI/engine must be updated - CPointers::backend()->reloadModules(CSwordBackend::AddedModules); + CSwordBackend::instance()->reloadModules(CSwordBackend::AddedModules); } bool BtInstallProgressDialog::threadsDone() { diff --git a/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.h b/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.h index 1d8113a..8b990ad 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.h +++ b/src/frontend/bookshelfmanager/installpage/btinstallprogressdialog.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -17,13 +17,16 @@ class BtInstallThread; +class CSwordModuleInfo; class QTreeWidget; class QTreeWidgetItem; class BtInstallProgressDialog : public QDialog { Q_OBJECT public: - BtInstallProgressDialog(QWidget* parent, QTreeWidget* selectedModulesTreeWidget, QString destination); + BtInstallProgressDialog(const QSet<const CSwordModuleInfo*> &modules, + const QString &destination, QWidget *parent = 0, + Qt::WindowFlags flags = 0); ~BtInstallProgressDialog(); @@ -43,7 +46,7 @@ class BtInstallProgressDialog : public QDialog { virtual void closeEvent(QCloseEvent* event); //signals: -// void swordSetupChanged(); +// void swordSetupChanged(); private: diff --git a/src/frontend/bookshelfmanager/installpage/btinstallthread.cpp b/src/frontend/bookshelfmanager/installpage/btinstallthread.cpp index 53ae071..2d04a51 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallthread.cpp +++ b/src/frontend/bookshelfmanager/installpage/btinstallthread.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -16,14 +16,14 @@ #include <QThread> #include "backend/managers/cswordbackend.h" #include "frontend/bookshelfmanager/btinstallmgr.h" -#include "frontend/bookshelfmanager/instbackend.h" -#include "util/cpointers.h" +#include "backend/btinstallbackend.h" // Sword includes: #include <filemgr.h> -BtInstallThread::BtInstallThread(QObject* parent, QString moduleName, QString sourceName, QString destinationName) +BtInstallThread::BtInstallThread(const QString &moduleName, const QString &sourceName, + const QString &destinationName, QObject *parent) : QThread(parent), done(false), m_module(moduleName), @@ -45,8 +45,8 @@ void BtInstallThread::run() { emit preparingInstall(m_module, m_source); //This is 0 before set here - remember when using the value when cancelling // the installation before this has been run - m_installSource.reset(new sword::InstallSource(instbackend::source(m_source))); - m_backendForSource.reset(instbackend::backend(*m_installSource)); + m_installSource = QSharedPointer<sword::InstallSource>(new sword::InstallSource(BtInstallBackend::source(m_source))); + m_backendForSource = QSharedPointer<CSwordBackend>(BtInstallBackend::backend(*m_installSource)); //make sure target/mods.d and target/modules exist /// \todo move this to some common precondition @@ -74,9 +74,9 @@ void BtInstallThread::run() { // manager for the destination path sword::SWMgr lMgr( m_destination.toLatin1() ); - if (instbackend::isRemote(*m_installSource)) { + if (BtInstallBackend::isRemote(*m_installSource)) { qDebug() << "calling install"; - int status = m_iMgr->installModule(&lMgr, 0, m_module.toLatin1(), m_installSource.get()); + int status = m_iMgr->installModule(&lMgr, 0, m_module.toLatin1(), m_installSource.data()); if (status != 0) { qWarning() << "Error with install: " << status << "module:" << m_module; } @@ -123,7 +123,7 @@ void BtInstallThread::slotStopInstall() { qDebug() << "BtInstallThread::slotStopInstall 3"; // cleanup: remove the module, remove the temp files // if installation has already started - if (m_installSource.get() != 0) { + if (m_installSource.data() != 0) { qDebug() << "BtInstallThread::slotStopInstall 4"; // remove the installed module, just to be sure because mgr may // have been terminated when copying files @@ -148,9 +148,9 @@ void BtInstallThread::slotDownloadStarted() { void BtInstallThread::removeModule() { qDebug() << "BtInstallThread::removeModule start"; CSwordModuleInfo* m; - m = CPointers::backend()->findModuleByName(m_module); + m = CSwordBackend::instance()->findModuleByName(m_module); if (!m) { - m = instbackend::backend(instbackend::source(m_destination.toLatin1()))->findModuleByName(m_module); + m = BtInstallBackend::backend(BtInstallBackend::source(m_destination.toLatin1()))->findModuleByName(m_module); } if (m) { //module found? qDebug() << "BtInstallThread::removeModule, module" << m_module << "found"; @@ -164,7 +164,7 @@ void BtInstallThread::removeModule() { prefixPath.remove( prefixPath.indexOf(dataPath), dataPath.length() ); } else { - prefixPath = QString::fromLatin1(CPointers::backend()->prefixPath); + prefixPath = QString::fromLatin1(CSwordBackend::instance()->prefixPath); } sword::SWMgr mgr(prefixPath.toLatin1()); @@ -182,8 +182,8 @@ void BtInstallThread::removeTempFiles() { // (take the remote conf file for this module, take DataPath, // take the absolute path of the InstallMgr) - //sword::InstallSource is = instbackend::source(m_source); - if (instbackend::isRemote(*m_installSource)) { + //sword::InstallSource is = BtInstallBackend::source(m_source); + if (BtInstallBackend::isRemote(*m_installSource)) { // get the path for the module temp files CSwordModuleInfo* mInfo = m_backendForSource->findModuleByName(m_module); QString dataPath = mInfo->config(CSwordModuleInfo::AbsoluteDataPath); diff --git a/src/frontend/bookshelfmanager/installpage/btinstallthread.h b/src/frontend/bookshelfmanager/installpage/btinstallthread.h index a50910f..8bb660d 100644 --- a/src/frontend/bookshelfmanager/installpage/btinstallthread.h +++ b/src/frontend/bookshelfmanager/installpage/btinstallthread.h @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2008 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -12,11 +12,12 @@ #include <QThread> -#include <boost/scoped_ptr.hpp> +#include <QSharedPointer> #include "frontend/bookshelfmanager/btinstallmgr.h" class BtInstallProgressDialog; +class CSwordBackend; /** * Thread for installing a module. @@ -54,7 +55,8 @@ temporary files manually. class BtInstallThread : public QThread { Q_OBJECT public: - BtInstallThread(QObject* parent, QString moduleName, QString sourceName, QString destinationName); + BtInstallThread(const QString &moduleName, const QString &sourceName, + const QString &destinationName, QObject *parent = 0); ~BtInstallThread(); @@ -77,10 +79,10 @@ class BtInstallThread : public QThread { bool m_cancelled; BtInstallMgr* m_iMgr; //BtInstallMgr m_iMgr; - boost::scoped_ptr<sword::InstallSource> m_installSource; + QSharedPointer<sword::InstallSource> m_installSource; /// \todo it would be best to get the backend from the bookshelf manager install page // where it has already been created. Could fasten the progress dialog startup. - boost::scoped_ptr<CSwordBackend> m_backendForSource; + QSharedPointer<CSwordBackend> m_backendForSource; signals: /** Emitted when the install progress status is updated. */ diff --git a/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.cpp b/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.cpp new file mode 100644 index 0000000..3666888 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.cpp @@ -0,0 +1,62 @@ +#include "frontend/bookshelfmanager/installpage/btrefreshprogressdialog.h" + +#include <QApplication> +#include <QDebug> +#include "backend/btinstallbackend.h" +#include "util/dialogutil.h" + + +BtRefreshProgressDialog::BtRefreshProgressDialog(sword::InstallSource &source, + QWidget *parent, + Qt::WindowFlags flags) + : QProgressDialog(parent, flags) + , m_source(source) +{ + qDebug() << "Creating BtRefreshProgressDialog for source" << source.caption; + + Q_ASSERT(BtInstallBackend::isRemote(source)); + setWindowTitle(tr("Refreshing source %1").arg(QString(source.caption))); + setCancelButtonText(tr("&Cancel")); + setLabelText(tr("Connecting...")); + Q_ASSERT(minimum() == 0); + setMaximum(100); + setValue(0); + setWindowModality(Qt::ApplicationModal); + setMinimumDuration(1000); + + connect(this, SIGNAL(canceled()), + this, SLOT(slotCanceled())); + connect(&m_installMgr, SIGNAL(percentCompleted(int,int)), + this, SLOT(slotPercentCompleted(int,int))); +} + +void BtRefreshProgressDialog::slotPercentCompleted(int, int current) { + qDebug() << "BtRefreshProgressDialog progress:" << current; + + setValue(current); + qApp->processEvents(); +} + +void BtRefreshProgressDialog::slotCanceled() { + qDebug() << "BtRefreshProgressDialog cancel clicked."; + + m_installMgr.terminate(); +} + +bool BtRefreshProgressDialog::runAndDelete() { + qDebug() << "BtRefreshProgressDialog runAndDelete()"; + + show(); + qApp->processEvents(); + bool r = (m_installMgr.refreshRemoteSource(&m_source) == 0); + if (r) { + setValue(100); + qApp->processEvents(); + } else { + util::showWarning(this, tr("Warning"), + tr("Failed to refresh source %1") + .arg(QString(m_source.caption))); + } + deleteLater(); + return r; +} diff --git a/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.h b/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.h new file mode 100644 index 0000000..dfabcf6 --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btrefreshprogressdialog.h @@ -0,0 +1,38 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2011 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef BTREFRESHPROGRESSDIALOG_H +#define BTREFRESHPROGRESSDIALOG_H + +#include <QProgressDialog> + +#include "frontend/bookshelfmanager/btinstallmgr.h" + + +class BtRefreshProgressDialog: public QProgressDialog { + Q_OBJECT + + public: /* Methods: */ + BtRefreshProgressDialog(sword::InstallSource &source, + QWidget *parent = 0, Qt::WindowFlags f = 0); + + bool runAndDelete(); + + private slots: + + void slotPercentCompleted(int, int); + void slotCanceled(); + + private: /* Fields: */ + + sword::InstallSource m_source; + BtInstallMgr m_installMgr; +}; + +#endif // BTREFRESHPROGRESSDIALOG_H diff --git a/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp b/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp deleted file mode 100644 index ca85822..0000000 --- a/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ - -#include "frontend/bookshelfmanager/installpage/btsourcearea.h" - -#include <QString> -#include <QWidget> -#include <QMap> -#include <QVBoxLayout> -#include <QHBoxLayout> -#include <QSpacerItem> -#include <QLabel> -#include <QPushButton> -#include <QTreeWidget> -#include <QTreeWidgetItem> -#include <QHeaderView> -#include <QDebug> -#include <QTime> -#include "backend/managers/cswordbackend.h" -#include "frontend/bookshelfmanager/instbackend.h" -#include "frontend/btaboutmoduledialog.h" -#include "util/directory.h" -#include "util/cpointers.h" -#include "util/cresmgr.h" -#include "util/tool.h" - -// Sword includes: -#include <installmgr.h> - - -// **************************************************************** -// ******** Installation source and module list widget ************ -// **************************************************************** - -BtSourceArea::BtSourceArea(const QString& sourceName) - : QWidget(), - m_sourceName(sourceName), - m_treeAlreadyInitialized(false), - m_remoteBackend(0) { //important! - setObjectName(sourceName); - m_checkedModules = QMap<QString, bool>(); - qDebug() << "BtSourceArea::BtSourceArea, " << m_sourceName; - initView(); -} - -BtSourceArea::~BtSourceArea() { - qDebug() << "BtSourceArea::~BtSourceArea" << m_sourceName; - delete m_remoteBackend; -} - -void BtSourceArea::initView() { - namespace DU = util::directory; - - qDebug() << "BtSourceArea::initView"; - QVBoxLayout *mainLayout = new QVBoxLayout(this); - - // source related button row - QHBoxLayout *sourceLayout = new QHBoxLayout(); - m_refreshButton = new QPushButton(tr("Refresh...")); - m_refreshButton->setToolTip(tr("Refresh the list of works from this source")); - m_refreshButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::refresh_icon)); - //m_refreshButton->setEnabled(false); - QSpacerItem *sourceSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - //m_editButton = new QPushButton(tr("Edit...")); - /// \todo after writing the edit widget: - //m_editButton->setEnabled(false); - m_deleteButton = new QPushButton(tr("Delete...")); - m_deleteButton->setToolTip(tr("Delete this source")); - m_deleteButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::delete_icon)); - //m_deleteButton->setEnabled(false); - m_addButton = new QPushButton(tr("Add...")); - m_addButton->setToolTip(tr("Add new source")); - m_addButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::installpage::add_icon)); - - sourceLayout->addWidget(m_refreshButton); - sourceLayout->addItem(sourceSpacer); - //sourceLayout->addWidget(m_editButton); - sourceLayout->addWidget(m_deleteButton); - sourceLayout->addWidget(m_addButton); - - mainLayout->addLayout(sourceLayout); - // There are no views for the stack yet, see initSources - m_view = new QTreeWidget(this); - m_view->setHeaderLabels(QStringList() << tr("Work") << tr("Description")); - m_view->setColumnWidth(0, util::tool::mWidth(m_view, 20)); - mainLayout->addWidget(m_view); - - connect(m_view, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), SLOT(slotItemDoubleClicked(QTreeWidgetItem*, int))); - connect(CPointers::backend(), SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)), SLOT(slotSwordSetupChanged())); - connect(this, SIGNAL(signalCreateTree()), SLOT(slotCreateTree()), Qt::QueuedConnection); -} - -void BtSourceArea::prepareRemove() { - // don't create tree anymore, this will be removed - disconnect(this, SIGNAL(signalCreateTree()), this, SLOT(slotCreateTree())); -} - -QSize BtSourceArea::sizeHint() const { - return QSize(100, m_refreshButton->height() + (m_view->header()->height() * 5)); -} - -void BtSourceArea::initTreeFirstTime() { - if (!m_treeAlreadyInitialized) { - createModuleTree(); - m_treeAlreadyInitialized = true; - } -} - -void BtSourceArea::createModuleTree() { - qDebug() << "BtSourceArea::createModuleTree start"; - // Start creating tree with a queued connection. - // This makes showing the dialog possible even before the tree is initialized. - emit signalCreateTree(); -} -void BtSourceArea::slotCreateTree() { - qDebug() << "BtSourceArea::slotCreateTree" << QTime::currentTime (); - //let the dialog become visible - QCoreApplication::processEvents(); - // Creating the view and populating list may take time - QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); - - // disconnect the signal so that we don't have to run functions for every module - // (note: what to do if we want to restore the item selection when rebuilding? - disconnect(m_view, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(slotSelectionChanged(QTreeWidgetItem*, int)) ); - m_view->clear(); - - /// \todo if the tree already exists for this source, maybe the selections should be preserved - m_checkedModules.clear(); - - sword::InstallSource is = instbackend::source(m_sourceName); - delete m_remoteBackend; // the old one can be deleted - m_remoteBackend = instbackend::backend(is); - Q_ASSERT(m_remoteBackend); - m_moduleList = m_remoteBackend->moduleList(); - - // give the list to BTModuleTreeItem, create filter to remove - // those modules which are installed already - InstalledFilter alreadyInstalledFilter(m_sourceName); - QList<BTModuleTreeItem::Filter*> filterList; - filterList.append(&alreadyInstalledFilter); - BTModuleTreeItem rootItem(filterList, BTModuleTreeItem::CatLangMod, &m_moduleList); - - addToTree(&rootItem, m_view->invisibleRootItem()); - QCoreApplication::processEvents(); - // receive signal when user checks modules - connect(m_view, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(slotSelectionChanged(QTreeWidgetItem*, int)) ); - QApplication::restoreOverrideCursor(); - qDebug() << "BtSourceArea::createModuleTree end" << QTime::currentTime (); -} - -void BtSourceArea::addToTree(BTModuleTreeItem* item, QTreeWidgetItem* widgetItem) { - //qDebug()<<"BtSourceArea::addToTree "<<item->text(); - //qDebug() << "BTMTItem type: " << item->type(); - - foreach (BTModuleTreeItem* i, item->children()) { - addToTree(i, new QTreeWidgetItem(widgetItem)); - } - if (item->type() != BTModuleTreeItem::Root) { - CSwordModuleInfo* mInfo = item->moduleInfo(); - widgetItem->setText(0, item->text()); - if (item->type() == BTModuleTreeItem::Category || item->type() == BTModuleTreeItem::Language) { - //qDebug() << "item"<<item->text()<< "was cat or lang"; - widgetItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate); - } - if (item->type() == BTModuleTreeItem::Module) { - //qDebug() << "item"<<item->text()<< "was a module"; - widgetItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - widgetItem->setCheckState(0, Qt::Unchecked); - - CSwordModuleInfo* const installedModule = CPointers::backend()->findModuleByName(mInfo->name()); - QString installedV; - - if (!installedModule) { - /** - \todo maybe? save the module list of a source before refreshing, - compare after refreshing, mark the newly added modules if - not newly added: - state: installable (no indicator) - else: status: newly added, color yellow - */ - } else { // the module is already installed - QBrush bg(QColor(255, 153, 153)); /// \bug Possible color conflict - widgetItem->setBackground(0, bg); - widgetItem->setBackground(1, bg); - installedV = QString(installedModule->config(CSwordModuleInfo::ModuleVersion).toLatin1()); - // set the color for the parent items - QTreeWidgetItem* parent1 = widgetItem->parent(); - if (parent1) { - parent1->setBackground(0, bg); - parent1->setBackground(1, bg); - QTreeWidgetItem* parent2 = parent1->parent(); - if (parent2) { - parent2->setBackground(0, bg); - parent2->setBackground(1, bg); - } - } - } - - - QString descr(mInfo->config(CSwordModuleInfo::Description)); - QString toolTipText = util::tool::remoteModuleToolTip(mInfo, installedV); - - widgetItem->setText(1, descr); - widgetItem->setToolTip(0, toolTipText); - widgetItem->setToolTip(1, toolTipText); - } - } -} - -QTreeWidget* BtSourceArea::treeWidget() { - return m_view; -} - -// return the selected modules -QMap<QString, bool>* BtSourceArea::selectedModules() { - return &m_checkedModules; -} - -// when a module is checked/unchecked -void BtSourceArea::slotSelectionChanged(QTreeWidgetItem* item, int column) { - //qDebug() << "BtSourceArea::slotSelectionChanged"; - // modify the internal list of selected (actually checked) modules - // if() leaves groups away - if (!item->childCount() && column == 0) { - foreach (CSwordModuleInfo* module, m_moduleList) { - if (module->name() == item->text(0)) { - if (item->checkState(0) == Qt::Checked) { - qDebug() << module->name() << "was checked"; - m_checkedModules.insert(module->name(), true); - } - else { - qDebug() << module->name() << "was unchecked"; - m_checkedModules.remove(module->name()); - } - emit signalSelectionChanged(m_sourceName, m_checkedModules.count()); - break; - } - } - } -} - -void BtSourceArea::slotItemDoubleClicked(QTreeWidgetItem* item, int /*column*/) { - CSwordModuleInfo* mInfo = m_remoteBackend->findModuleByName(item->text(0)); - if (mInfo) { - BTAboutModuleDialog* dialog = new BTAboutModuleDialog(this, mInfo); - dialog->show(); - dialog->raise(); - } -} - -BtSourceArea::InstalledFilter::InstalledFilter(QString sourceName) - : BTModuleTreeItem::Filter(), - m_source(instbackend::source(sourceName)), - m_swordBackend(instbackend::backend(m_source)) { - // these are set once to optimize away repeated calls - // m_source, m_swordBackend - -} -//filter out already installed, not updateable modules -bool BtSourceArea::InstalledFilter::filter(CSwordModuleInfo* mInfo) { - //qDebug() << "BtSourceArea::InstalledFilter::filter, module " << mInfo->name(); - CSwordModuleInfo* const installedModule = CPointers::backend()->findModuleByName(mInfo->name()); - if (installedModule) { - //qDebug() << "already installed, check if it's an update..."; - const sword::SWVersion installedVersion(installedModule->config(CSwordModuleInfo::ModuleVersion).toLatin1()); - const sword::SWVersion newVersion(mInfo->config(CSwordModuleInfo::ModuleVersion).toLatin1()); - if (installedVersion >= newVersion) { - return false; - } - } - return true; -} - -void BtSourceArea::slotSwordSetupChanged() { - createModuleTree(); -} diff --git a/src/frontend/bookshelfmanager/installpage/btsourcearea.h b/src/frontend/bookshelfmanager/installpage/btsourcearea.h deleted file mode 100644 index ece20ed..0000000 --- a/src/frontend/bookshelfmanager/installpage/btsourcearea.h +++ /dev/null @@ -1,96 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ - -#ifndef BTSOURCEAREA_H -#define BTSOURCEAREA_H - -#include <QWidget> - -#include <boost/scoped_ptr.hpp> -#include <QApplication> -#include <QMap> -#include "backend/btmoduletreeitem.h" - -// Sword includes: -#include <installmgr.h> - - -class QTreeWidget; -class QTreeWidgetItem; -class QLabel; -class QPushButton; - -/** -* Area for one install source. -* -* - Tree widget for modules -* - Buttons for handling the source(s): refresh, edit, remove, add -* -* Each source has -* QTreeWidget, populated with the module tree if the source -* module list is in a local cache. Refreshing the source refreshes -* the cache and rebuilds the module tree. Sources are not refreshed -* automatically, only by the user action, one source at a time. -*/ -class BtSourceArea : public QWidget { - Q_OBJECT - - friend class BtSourceWidget; - public: - - struct InstalledFilter : BTModuleTreeItem::Filter { - InstalledFilter(QString sourceName); - bool filter(CSwordModuleInfo*); - sword::InstallSource m_source; - boost::scoped_ptr<CSwordBackend> m_swordBackend; - }; - - BtSourceArea(const QString& sourceName); - ~BtSourceArea(); - - void initView(); - void prepareRemove(); - /** Reimplemented from QWidget. */ - virtual QSize sizeHint() const; - void initTreeFirstTime(); - QTreeWidget* treeWidget(); - - QMap<QString, bool>* selectedModules(); - - public slots: - void slotSwordSetupChanged(); - /** Create a module tree for a tree widget */ - void createModuleTree(); - - signals: - void signalSelectionChanged(QString sourceName, int selectedCount); - void signalCreateTree(); - - private slots: - void slotCreateTree(); - void slotSelectionChanged(QTreeWidgetItem* item, int column); - void slotItemDoubleClicked(QTreeWidgetItem* item, int column); - private: - void addToTree(BTModuleTreeItem* item, QTreeWidgetItem* widgetItem); - - QString m_sourceName; - bool m_treeAlreadyInitialized; - QMap<QString, bool> m_checkedModules; - CSwordBackend* m_remoteBackend; // needed for the module list - QList<CSwordModuleInfo*> m_moduleList; - - QTreeWidget* m_view; - QLabel* m_refreshTimeLabel; - QPushButton* m_refreshButton; - QPushButton* m_editButton; - QPushButton* m_deleteButton; - QPushButton* m_addButton; -}; - -#endif diff --git a/src/frontend/bookshelfmanager/installpage/btsourcewidget.cpp b/src/frontend/bookshelfmanager/installpage/btsourcewidget.cpp deleted file mode 100644 index 81e84fb..0000000 --- a/src/frontend/bookshelfmanager/installpage/btsourcewidget.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ - -#include "frontend/bookshelfmanager/installpage/btsourcewidget.h" - -#include <QApplication> -#include <QFileInfo> -#include <QHBoxLayout> -#include <QLabel> -#include <QProgressDialog> -#include <QPushButton> -#include <QString> -#include <QTabBar> -#include <QTabWidget> -#include <QTreeWidget> -#include <QTreeWidgetItem> -#include <QWidget> -#include "frontend/bookshelfmanager/btinstallmgr.h" -#include "frontend/bookshelfmanager/btmodulemanagerdialog.h" -#include "frontend/bookshelfmanager/cswordsetupinstallsourcesdialog.h" -#include "frontend/bookshelfmanager/installpage/btinstallmodulechooserdialog.h" -#include "frontend/bookshelfmanager/installpage/btinstallpage.h" -#include "frontend/bookshelfmanager/installpage/btinstallprogressdialog.h" -#include "frontend/bookshelfmanager/installpage/btsourcearea.h" -#include "frontend/bookshelfmanager/instbackend.h" -#include "util/dialogutil.h" - - -/** -* Tab Widget that holds source widgets -*/ -BtSourceWidget::BtSourceWidget(BtInstallPage* parent) - : QTabWidget(parent), - m_page(parent) { - qDebug() << "BtSourceWidget::BtSourceWidget start"; - initSources(); - // send queued event because "Delete" is initiated from tab which should be deleted - connect(this, SIGNAL(sigInitSources()), SLOT(initSources()), Qt::QueuedConnection); - /// \todo choose the page from config - -} - -BtSourceArea* BtSourceWidget::area() { - return dynamic_cast<BtSourceArea*>(currentWidget()); -} - -QString BtSourceWidget::currentSourceName() { - qDebug() << "BtSourceWidget::currentSourceName: " << m_sourceNameList.at(currentIndex()); - return m_sourceNameList.at(currentIndex()); -} - -void BtSourceWidget::initSourceConnections() { - qDebug() << "void BtSourceWidget::initSourceConnections() start"; - if (area()) { - connect(area()->m_refreshButton, SIGNAL(clicked()), SLOT(slotRefresh())); - //connect(area()->m_editButton, SIGNAL(clicked()), SLOT(slotEdit())); - connect(area()->m_deleteButton, SIGNAL(clicked()), SLOT(slotDelete()), Qt::QueuedConnection); - connect(area()->m_addButton, SIGNAL(clicked()), SLOT(slotAdd())); - connect(area(), SIGNAL(signalSelectionChanged(QString, int)), SLOT(slotModuleSelectionChanged(QString, int)) ); - } - qDebug() << "void BtSourceWidget::initSourceConnections() end"; -} - -void BtSourceWidget::slotEdit() { - qDebug() << "BtSourceWidget::slotEdit"; - /// \todo open the source editor dialog - - // if the source was changed, init the sources - -} - -void BtSourceWidget::slotDelete() { - qDebug() << "void BtSourceWidget::slotDelete() start"; - // ask for confirmation - int ret = util::showWarning(this, tr("Delete Source?"), - tr("Do you really want to delete this source?"), - QMessageBox::Yes | QMessageBox::No); - - if (ret == QMessageBox::Yes) { - instbackend::deleteSource(currentSourceName()); - initSources(); - } -} - -void BtSourceWidget::slotAdd() { - - boost::scoped_ptr<CSwordSetupInstallSourcesDialog> dlg( new CSwordSetupInstallSourcesDialog() ); - sword::InstallSource newSource(""); //empty, invalid Source - - if (dlg->exec() == QDialog::Accepted) { - if (!dlg->wasRemoteListAdded()) { - newSource = dlg->getSource(); - if ( !((QString)newSource.type.c_str()).isEmpty() ) { // we have a valid source to add - instbackend::addSource(newSource); - } - } - initSources(); - } -} - - -void BtSourceWidget::slotRefresh() { - qDebug() << "void BtSourceWidget::slotRefresh() start"; - // (re)build the module cache for the source - - QString sourceName = currentSourceName(); - - // quick enough, make it modal so that we don't need to take care of anything else - m_progressDialog = new QProgressDialog("", tr("Cancel"), 0 , 100, this); - m_progressDialog->setWindowTitle(tr("Refreshing Source")); - m_progressDialog->setMinimumDuration(0); - - /// \todo get rid of the backend code, BtInstallMgr and progressdialog could handle this - //write method BtInstallMgr::slotRefreshCanceled() - connect(m_progressDialog, SIGNAL(canceled()), SLOT(slotRefreshCanceled())); - - // BACKEND CODE ********************************************************** - // would this be possible: instbackend::refreshSource( arguments ); - qDebug() << "void BtSourceWidget::slotRefresh 1"; - BtInstallMgr iMgr; - m_currentInstallMgr = &iMgr; //for the progress dialog - sword::InstallSource is = instbackend::source(sourceName); - bool success = false; - qDebug() << "void BtSourceWidget::slotRefresh 2"; - // connect this directly to the dialog setValue(int) if possible - connect(&iMgr, SIGNAL(percentCompleted(const int, const int)), SLOT(slotRefreshCompleted(const int, const int))); - - if (instbackend::isRemote(is)) { - m_progressDialog->show(); - qApp->processEvents(); - this->slotRefreshCompleted(0, 0); - m_progressDialog->setLabelText(tr("Connecting...")); - m_progressDialog->setValue(0); - qApp->processEvents(); - qDebug() << "void BtSourceWidget::slotRefresh 3"; - bool successful = iMgr.refreshRemoteSource( &is ); - if (!successful ) { //make sure the sources were updated sucessfully - success = true; - m_progressDialog->setValue(100); //make sure the dialog closes - } - else { - qWarning("InstallMgr: refreshRemoteSources returned an error."); - success = false; - } - } - else { - // Local source, update the list - success = true; - } - - delete m_progressDialog; - m_progressDialog = 0; - - // rebuild the view tree and refresh the view - if (success) { - qDebug() << "void BtSourceWidget::slotRefresh 4"; - area()->createModuleTree(); - } -} - -/// \todo try to move this to BtInstallMgr -void BtSourceWidget::slotRefreshCanceled() { - qDebug() << "BtSourceWidget::slotRefreshCanceled"; - Q_ASSERT(m_currentInstallMgr); - if (m_currentInstallMgr) { - m_currentInstallMgr->terminate(); - } - qApp->processEvents(); -} - -/// \todo try to move this to progress dialog -void BtSourceWidget::slotRefreshCompleted(const int, const int current) { - qDebug() << "BtSourceWidget::slotRefreshCompleted"; - if (m_progressDialog) { - if (m_progressDialog->labelText() != tr("Refreshing...")) { - m_progressDialog->setLabelText(tr("Refreshing...")); - } - m_progressDialog->setValue(current); - } - qApp->processEvents(); -} - -// init the tabbar, setup the module tree for the current source -void BtSourceWidget::initSources() { - qDebug() << "void BtSourceWidget::initSources() start"; - - //first clear all sources - //int i = count(); - for (int i = count() - 1; i >= 0; i--) { - BtSourceArea* a = dynamic_cast<BtSourceArea*>(widget(i)); - a->prepareRemove(); - } - for (int i = count() - 1; i >= 0; i--) { - qDebug() << "remove tab" << tabText(i); - QWidget* w = widget(i); - removeTab(i); - delete w; - qDebug() << "deleted"; - } - m_sourceNameList.clear(); - - // ***** Use the backend to get the list of sources ***** - instbackend::initPassiveFtpMode(); - QStringList sourceList = instbackend::sourceList(); - qDebug() << "got the source list from backend:" << sourceList; - // Add a default entry, the Crosswire main repository - if (!sourceList.count()) { - /// \todo Open a dialog which asks whether to get list from server and add sources - sword::InstallSource is("FTP"); //default return value - is.caption = "CrossWire Bible Society"; - is.source = "ftp.crosswire.org"; - is.directory = "/pub/sword/raw"; - // passive ftp is not needed here, it's the default - - instbackend::addSource(is); - - sourceList = instbackend::sourceList(); - //Q_ASSERT( sourceList.count() > 0 ); - } - qDebug() << "void BtSourceWidget::initSources 1"; - // Add the sources to the widget - foreach (QString sourceName, sourceList) { - addSource(sourceName); - } - // connect this after the tabs have been created, - // otherwise the signal is caught too early. - QObject::connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotTabSelected(int))); - qDebug() << "void BtSourceWidget::initSources end"; - /// \todo select the current source from the config - // It's important to choose something because the tree is not initialized until now - setCurrentIndex(0); - slotTabSelected(0); // setting the index wasn't enough if there were only 1 tab - - if (sourceList.count() == 0) { - QHBoxLayout* l = new QHBoxLayout(this); - QLabel* message = new QLabel(QString("<i>") + tr("No sources were found in the SWORD configuration and BibleTime couldn't create a default source. Check your SWORD configuration and that the configuration path is writable. Then restart the Bookshelf Manager.") + QString("</i>"), this); - message->setWordWrap(true); - l->addWidget(message); - } -} - -void BtSourceWidget::addSource(const QString& sourceName) { - qDebug() << "void BtSourceWidget::addSource(const QString& sourceName) start, with name" << sourceName; - // The source has already been added to the backend. - - QString type; - QString server; - QString path; - sword::InstallSource is = instbackend::source(sourceName); - if (instbackend::isRemote(is)) { - type = tr("Remote:"); - server = is.source.c_str(); - path = is.directory.c_str(); - } - else { // local source - type = tr("Local:"); - QFileInfo fi( is.directory.c_str() ); - path = is.directory.c_str(); - if (!(fi.isDir() )) { - path = path + QString(" ") + tr("Not a directory!"); /// \todo change this - } - if (!fi.isReadable()) { - path = path + QString(" ") + tr("Not readable!"); /// \todo change this - } - } - - // Here the tab UI is created and added to the tab widget - BtSourceArea* area = new BtSourceArea(sourceName); - int tabNumber = this->addTab(area, sourceName); - - /// \todo add "remote/local", server, path etc. - QString toolTip(QString("<p style='white-space:pre'>") + sourceName + QString("<br/><b>") + type + QString("</b> ") + server + path + QString("</p>")); - tabBar()->setTabToolTip(tabNumber, toolTip); - - //select the new tab - setCurrentIndex(tabNumber); - m_sourceNameList.append(sourceName); - initSourceConnections(); - qDebug() << "BtSourceWidget::addSource end"; -} - -// -void BtSourceWidget::slotModuleSelectionChanged(QString sourceName, int selectedCount) { - /// \todo editing sources should update the map also - qDebug() << "BtSourceWidget::slotModuleSelectionChanged start"; - - int overallCount = 0; - m_selectedModulesCountMap.insert(sourceName, selectedCount); - foreach (int count, m_selectedModulesCountMap) { - qDebug() << "add" << count << "to overall count of selected modules"; - overallCount += count; - } - - if (overallCount > 0) { - m_page->setInstallEnabled(true); - } - else { - m_page->setInstallEnabled(false); - } -} - -void BtSourceWidget::slotTabSelected(int /*index*/) { - BtSourceArea* area = dynamic_cast<BtSourceArea*>(currentWidget()); - if (area) area->initTreeFirstTime(); -} - -void BtSourceWidget::slotInstall() { - qDebug() << "void BtInstallPage::slotInstall start"; - - // check that the destination path is writable, do nothing if not and user doesn't want to continue - QDir dir = QDir(dynamic_cast<BtInstallPage*>(parent())->selectedInstallPath()); - bool canWrite = true; - if (dir.isReadable()) { - const QFileInfo fi( dir.canonicalPath() ); - if (!fi.exists() || !fi.isWritable()) { - canWrite = false; - } - } - else { - canWrite = false; - } - if (!canWrite) { - const int result = util::showWarning(this, tr("Warning"), tr("The destination directory is not writable or does not exist. Installation will fail unless this has first been fixed."), QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Cancel); - if (result != QMessageBox::Ignore) { - return; - } - } - - // create the confirmation dialog - // (module tree dialog, modules taken from all sources) - QString dlgTitle(tr("Install/Update works?")); - QString dlgLabel(tr("Do you really want to install these works?") + - QString("<br/><br/><small>") + - tr("Only one version of a work can be installed at the same time. Select only one if there are items marked with red.") + - QString("</small>")); - - // with empty list we avoid creating the module tree inside the dialog code - QList<CSwordModuleInfo*> emptyList; - BtInstallModuleChooserDialog* dlg = new BtInstallModuleChooserDialog(this, dlgTitle, dlgLabel, &emptyList); - //dlg->setGrouping(BTModuleTreeItem::Mod); - QTreeWidget* treeWidget = dlg->treeWidget(); - QTreeWidgetItem* rootItem = treeWidget->invisibleRootItem(); - - QStringList nameList; - - // loop through each tab - for (int tab = 0; tab < count(); ++tab) { - BtSourceArea* sArea = dynamic_cast<BtSourceArea*>(widget(tab)); - if (sArea && sArea->selectedModules()->count() > 0) { - // there are selected modules in the source, create items for these - /// \todo Use new bookshelf model instead - /// \bug Valgrind reports memory leak: - QTreeWidgetItem* sourceItem = new QTreeWidgetItem(rootItem); - sourceItem->setText(0, m_sourceNameList.at(tab)); - sourceItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsTristate | Qt::ItemIsEnabled); - foreach (QString mName, sArea->selectedModules()->keys()) { - dlg->initModuleItem(mName, sourceItem); - } - sourceItem->setExpanded(true); - } - } - - //user accepts the dialog - connect(dlg, SIGNAL(modulesChanged(QList<CSwordModuleInfo*>, QTreeWidget*)), SLOT(slotInstallAccepted(QList<CSwordModuleInfo*>, QTreeWidget*)) ); - // user checks/unchecks an item, needed for preventing double items - QObject::connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), dlg, SLOT(slotItemChecked(QTreeWidgetItem*, int))); - dlg->exec(); - // The OK signal sent by the dialog is catched with slotInstallAccepted. -} - -void BtSourceWidget::slotStopInstall(QTreeWidget* /*treeWidget*/) { - qDebug() << "BtSourceWidget::slotStopInstall"; - // not needed? -} - -void BtSourceWidget::slotInstallAccepted(QList<CSwordModuleInfo*> /*modules*/, QTreeWidget* treeWidget) { - qDebug() << "BtSourceWidget::slotInstallAccepted"; - - /// \todo first remove all modules which will be updated from the module list - // but what modules? all with the same real name? (there may be _n modules...) - - BtModuleManagerDialog* parentDialog = dynamic_cast<BtModuleManagerDialog*>(dynamic_cast<BtInstallPage*>(parent())->parentDialog()); - - BtInstallProgressDialog* dlg = new BtInstallProgressDialog(parentDialog, treeWidget, dynamic_cast<BtInstallPage*>(parent())->selectedInstallPath()); - - if (!parentDialog) qDebug() << "error, wrong parent!"; - - m_page->setInstallEnabled(false); - // the progress dialog is now modal, it can be made modeless later. - dlg->exec(); - - qDebug() << "BtSourceWidget::slotInstallAccepted end"; -} diff --git a/src/frontend/bookshelfmanager/installpage/btsourcewidget.h b/src/frontend/bookshelfmanager/installpage/btsourcewidget.h deleted file mode 100644 index fbe8426..0000000 --- a/src/frontend/bookshelfmanager/installpage/btsourcewidget.h +++ /dev/null @@ -1,86 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ -#ifndef BTSOURCEWIDGET_H -#define BTSOURCEWIDGET_H - -#include <QTabWidget> - -#include <QMap> -#include <QString> - - -class BtInstallMgr; -class BtInstallPage; -class BtSourceArea; -class CSwordModuleInfo; -class QProgressDialog; -class QTreeWidget; - -/** -* Tabwidget which holds the source widgets. -* This widget implements the slots for the source action buttons and -* applies the actions to the proper source(s). -*/ -class BtSourceWidget : public QTabWidget { - Q_OBJECT - public: - friend class BtInstallPage; - - BtSourceWidget(BtInstallPage* parent); - virtual ~BtSourceWidget() {} - - BtSourceArea* area(); - QString currentSourceName(); - - public slots: - /** Install button has been clicked. */ - void slotInstall(); - /** "Stop All" button clicked */ - void slotStopInstall(QTreeWidget* treeWidget); - - private: - void initSourceConnections(); - - /** Add one source to tabs/stack. */ - void addSource(const QString& sourceName); - - private slots: - /** Add tabs/views for each source. */ - void initSources(); - - void slotRefresh(); - - void slotRefreshCanceled(); - - void slotRefreshCompleted(int, int); - - /** Edit button clicked. */ - void slotEdit(); - /** Delete button clicked. */ - void slotDelete(); - /** Add button clicked. */ - void slotAdd(); - /** Modules have been checked/unchecked in the view. */ - void slotModuleSelectionChanged(QString sourceName, int selectedCount); - - void slotTabSelected(int index); - void slotInstallAccepted(QList<CSwordModuleInfo*> mi, QTreeWidget* treeWidget); - - signals: - void sigInitSources(); - - private: - QStringList m_sourceNameList; - BtInstallPage* m_page; - QProgressDialog* m_progressDialog; // for refreshing - BtInstallMgr* m_currentInstallMgr; // for refreshing - QMap<QString, int> m_selectedModulesCountMap; -}; - -#endif diff --git a/src/frontend/bookshelfmanager/instbackend.cpp b/src/frontend/bookshelfmanager/instbackend.cpp deleted file mode 100644 index 463a6e5..0000000 --- a/src/frontend/bookshelfmanager/instbackend.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ - -#include "frontend/bookshelfmanager/instbackend.h" - -#include <functional> -#include <map> -#include <QDebug> -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <utility> -#include "backend/managers/cswordbackend.h" -#include "frontend/bookshelfmanager/btinstallmgr.h" -#include "util/cpointers.h" -#include "util/directory.h" -#include "util/dialogutil.h" - -// Sword includes: -#include <filemgr.h> -#include <swconfig.h> -#include <swbuf.h> - - -using namespace sword; - -namespace instbackend { - -/** Adds the source described by Source to the backend. */ -bool addSource(sword::InstallSource& source) { - qDebug() << "backend::addSource"; - SWConfig config(configFilename().toLatin1()); - if (!strcmp(source.type, "FTP")) { - //make sure the path doesn't have a trailing slash, sword doesn't like it - if (source.directory[ source.directory.length()-1 ] == '/') { - source.directory--; //make one char shorter - } - - config["Sources"].insert( std::make_pair(SWBuf("FTPSource"), source.getConfEnt()) ); - } - else if (!strcmp(source.type, "DIR")) { - config["Sources"].insert( std::make_pair(SWBuf("DIRSource"), source.getConfEnt()) ); - } - config.Save(); - return true; -} - -/** Returns the Source struct. */ -sword::InstallSource source(QString name) { - qDebug() << "backend::source"; - BtInstallMgr mgr; - InstallSourceMap::iterator source = mgr.sources.find(name.toLatin1().data()); - if (source != mgr.sources.end()) { - return *(source->second); - } - else { //not found in Sword, may be a local DIR source - SWConfig config(configFilename().toLatin1()); - SectionMap::iterator sourcesSection = config.Sections.find("Sources"); - if (sourcesSection != config.Sections.end()) { - ConfigEntMap::iterator sourceBegin = - sourcesSection->second.lower_bound("DIRSource"); - ConfigEntMap::iterator sourceEnd = - sourcesSection->second.upper_bound("DIRSource"); - - while (sourceBegin != sourceEnd) { - InstallSource is("DIR", sourceBegin->second.c_str()); - if (!strcmp(is.caption, name.toLatin1()) ) { //found local dir source - return is; - } - - sourceBegin++;//next source - } - } - } - - InstallSource is("EMPTY"); //default return value - is.caption = "unknown caption"; - is.source = "unknown source"; - is.directory = "unknown dir"; - return is; -} - -/** Deletes the source. */ -bool deleteSource(QString name) { - qDebug() << "backend::deleteSource"; - sword::InstallSource is = source(name ); - - SWConfig config(configFilename().toLatin1()); - - //this code can probably be shortened by using the stl remove_if functionality - std::pair< ConfigEntMap::iterator, ConfigEntMap::iterator > range = - isRemote(is) - ? config["Sources"].equal_range("FTPSource") - : config["Sources"].equal_range("DIRSource"); - - ConfigEntMap::iterator it = range.first; - SWBuf sourceConfigEntry = is.getConfEnt(); - bool notFound = true; - while (it != range.second) { - //SWORD lib gave us a "nice" surprise: getConfEnt() adds uid, so old sources added by BT are not recognized here - if (it->second == sourceConfigEntry) { - config["Sources"].erase(it); - notFound = false; - break; - } - ++it; - } - if (notFound) { - qDebug() << "source was not found, try without uid"; - //try again without uid - QString sce(sourceConfigEntry.c_str()); - QStringList l = sce.split('|'); - l.removeLast(); - sce = l.join("|").append("|"); - it = range.first; - while (it != range.second) { - qDebug() << it->second; - if (it->second == sce) { - config["Sources"].erase(it); - break; - } - ++it; - } - } - - config.Save(); - return true; /// \todo dummy -} - -/** Refreshes the remote source module list. */ -bool refreshSource(QString /*name*/) { - // not possible until manager and progressdialog work together - return true; /// \todo dummy -} - -/** Returns the moduleinfo list for the source. Delete the pointer after using. IS THIS POSSIBLE?*/ -QList<CSwordModuleInfo*> moduleList(QString /*name*/) { - QList<CSwordModuleInfo*> list; /// \todo dummy - return list; -} - -bool isRemote(const sword::InstallSource& source) { - return !strcmp(source.type, "FTP"); -} - -const QString configPath() { - QString confPath = util::directory::getUserHomeSwordDir().absolutePath(); - confPath.append("/InstallMgr"); - return confPath; -} - -const QString configFilename() { - return (configPath() + "/InstallMgr.conf"); -} - -QStringList targetList() { - qDebug() << "backend::targetList"; - QStringList names = CPointers::backend()->swordDirList(); - return names; -} - -bool setTargetList( const QStringList& targets ) { - namespace DU = util::directory; - - qDebug() << "backend::setTargetList"; - //saves a new Sword config using the provided target list - //QString filename = KGlobal::dirs()->saveLocation("data", "bibletime/") + "sword.conf"; //default is to assume the real location isn't writable - //QString filename = util::DirectoryUtil::getUserBaseDir().canonicalPath().append("/.sword/sword.conf"); - //bool directAccess = false; - QString filename = swordConfigFilename(); - QFileInfo i(filename); - QFileInfo dirInfo(i.absolutePath()); - - - if ( !i.exists() && dirInfo.isWritable() ) { - // if the file doesn't exist but the parent is writable, create it - qWarning() << "The Sword config file does not exist, it has to be created"; - QFile f(filename); - f.open(QIODevice::WriteOnly); - f.close(); - i.refresh(); - } - if ( i.exists() && i.isWritable() ) { //we can write to the file ourself - qDebug() << "The Sword config file is writable"; - } - else { - // There is no way to save to the file - qWarning() << "The Sword config file is not writable!"; - util::showWarning(0, QObject::tr("Can't write file"), QObject::tr("The Sword config file can't be written!")); - return false; - } - - filename = util::directory::convertDirSeparators(filename); - SWConfig conf(filename.toLocal8Bit()); - conf.Sections.clear(); - -#ifdef Q_WS_WIN - // On Windows, add the sword directory to the config file. - QString swordPath = DU::convertDirSeparators( DU::getApplicationSwordDir().absolutePath()); - conf["Install"].insert( - std::make_pair( SWBuf("LocalePath"), swordPath.toLocal8Bit().data() ) - ); -#endif - - bool setDataPath = false; - for (QStringList::const_iterator it = targets.begin(); it != targets.end(); ++it) { - QString t = DU::convertDirSeparators(*it); -#ifdef Q_WS_WIN - if (t.contains(DU::convertDirSeparators(DU::getUserHomeDir().canonicalPath().append("\\Sword")))) { -#else - if (t.contains(DU::getUserHomeDir().canonicalPath().append("/.sword"))) { -#endif - //we don't want $HOME/.sword in the config - continue; - } - else { - qDebug() << "Add path to the conf file" << filename << ":" << t; - conf["Install"].insert( std::make_pair(!setDataPath ? SWBuf("DataPath") : SWBuf("AugmentPath"), t.toLocal8Bit().data()) ); - setDataPath = true; - } - } - qDebug() << "save the sword conf..."; - conf.Save(); - CPointers::backend()->reloadModules(CSwordBackend::PathChanged); - return true; -} - -QStringList sourceList() { - qDebug() << "backend::sourceList"; - BtInstallMgr mgr; - Q_ASSERT(mgr.installConf); - - QStringList names; - - //add Sword remote sources - for (InstallSourceMap::iterator it = mgr.sources.begin(); it != mgr.sources.end(); it++) { - names << QString::fromLocal8Bit(it->second->caption); - } - - // Add local directory sources - SWConfig config(configFilename().toLatin1()); - sword::SectionMap::iterator sourcesSection = config.Sections.find("Sources"); - if (sourcesSection != config.Sections.end()) { - sword::ConfigEntMap::iterator sourceBegin = sourcesSection->second.lower_bound("DIRSource"); - sword::ConfigEntMap::iterator sourceEnd = sourcesSection->second.upper_bound("DIRSource"); - - while (sourceBegin != sourceEnd) { - InstallSource is("DIR", sourceBegin->second.c_str()); - names << QString::fromLatin1(is.caption.c_str()); - - sourceBegin++; - } - } - - return names; -} - - -void initPassiveFtpMode() { - qDebug() << "backend::initPassiveFtpMode"; - SWConfig config(configFilename().toLatin1()); - config["General"]["PassiveFTP"] = "true"; - config.Save(); -} -const QString swordConfigFilename() { - namespace DU = util::directory; - - qDebug() << "backend::swordConfigFilename"; -#ifdef Q_WS_WIN - qDebug() << DU::getUserHomeDir().absolutePath().append("/Sword/sword.conf"); - return DU::getUserHomeDir().absolutePath().append("/Sword/sword.conf"); -// return DU::getApplicationDir().absolutePath().append("/sword.conf"); -#else - qDebug() << DU::getUserHomeDir().absolutePath().append("/.sword/sword.conf"); - return DU::getUserHomeDir().absolutePath().append("/.sword/sword.conf"); -#endif -} - -const QDir swordDir() { - namespace DU = util::directory; - -#ifdef Q_WS_WIN - return QDir(DU::getUserHomeDir().absolutePath().append("/Sword/")); -#else - return QDir(DU::getUserHomeDir().absolutePath().append("/.sword/")); -#endif -} - -CSwordBackend* backend( const sword::InstallSource& is) { - qDebug() << "backend::backend"; - CSwordBackend* ret = 0; - if (isRemote(is)) { - ret = new CSwordBackend( QString(is.localShadow.c_str()), false ); - } - else { - ret = new CSwordBackend( QString(is.directory.c_str()), false); - } - - Q_ASSERT(ret); - if (ret) { - ret->initModules(CSwordBackend::OtherChange); - } - return ret; -} - -} diff --git a/src/frontend/bookshelfmanager/instbackend.h b/src/frontend/bookshelfmanager/instbackend.h deleted file mode 100644 index 3a98e5a..0000000 --- a/src/frontend/bookshelfmanager/instbackend.h +++ /dev/null @@ -1,74 +0,0 @@ -/********* -* -* This file is part of BibleTime's source code, http://www.bibletime.info/. -* -* Copyright 1999-2008 by the BibleTime developers. -* The BibleTime source code is licensed under the GNU General Public License version 2.0. -* -**********/ - -#ifndef INSTBACKEND_H -#define INSTBACKEND_H - -#include <QDir> -#include <QString> -#include "backend/managers/cswordbackend.h" - -// Sword includes: -#include <installmgr.h> - - -class CSwordModuleInfo; - -namespace instbackend { - -/** Adds the source to the backend. */ -bool addSource(sword::InstallSource& source); - -/** Returns the source struct. */ -sword::InstallSource source(QString name); - -/** Deletes the source. */ -bool deleteSource(QString name); - -/** Refreshes the remote source module list. */ -bool refreshSource(QString name); - -/** Returns the moduleinfo list for the source. */ -QList<CSwordModuleInfo*> moduleList(QString name); - -/** Tells if the source is remote or local. */ -bool isRemote(const sword::InstallSource& source); - -/** Returns the list of available install target paths. */ -QStringList targetList(); - -/** Saves the list of available install target paths to the sword config. Return success indicator.*/ -bool setTargetList( const QStringList& targets ); - -QStringList sourceList(); - -/** Returns the path of the sword installer configuration file. */ -const QString configPath(); - -/** Returns the name of the sword installer configuration file. */ -const QString configFilename(); - -/** Sets the passive mode for as default. -* \todo see if we can en/disable this per source. -*/ -void initPassiveFtpMode(); - -/** Returns the file name for the Sword config file. */ -const QString swordConfigFilename(); - -/** Returns the Sword directory ($HOME/.sword/) as a QDir, created with absolute path (not canonical). -*/ -const QDir swordDir(); - -/** Returns backend Sword manager for the source. */ -CSwordBackend* backend( const sword::InstallSource& is); - -} - -#endif diff --git a/src/frontend/bookshelfmanager/removepage/btremovepage.cpp b/src/frontend/bookshelfmanager/removepage/btremovepage.cpp index 3f602e0..a19ab89 100644 --- a/src/frontend/bookshelfmanager/removepage/btremovepage.cpp +++ b/src/frontend/bookshelfmanager/removepage/btremovepage.cpp @@ -4,7 +4,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2009 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License * version 2.0. * @@ -12,90 +12,137 @@ #include "frontend/bookshelfmanager/removepage/btremovepage.h" -#include <QGridLayout> +#include <QAction> +#include <QGroupBox> +#include <QHBoxLayout> #include <QHeaderView> -#include <QList> +#include <QMessageBox> #include <QPushButton> -#include <QTreeView> -#include "backend/drivers/cswordmoduleinfo.h" +#include <QToolButton> +#include <QVBoxLayout> +#include "backend/bookshelfmodel/btbookshelffiltermodel.h" #include "backend/managers/cswordbackend.h" -#include "util/directory.h" -#include "util/dialogutil.h" -#include "util/cpointers.h" +#include "frontend/btbookshelfview.h" +#include "frontend/btbookshelfwidget.h" #include "util/cresmgr.h" +#include "util/dialogutil.h" +#include "util/directory.h" // Sword includes: #include <swmgr.h> #include <installmgr.h> -BtRemovePage::BtRemovePage() - : BtConfigPage() { - namespace DU = util::directory; - - QGridLayout* layout = new QGridLayout(this); - layout->setMargin(5); - - layout->setSpacing(10); - layout->setColumnStretch(1, 1); - layout->setRowStretch(2, 1); - - m_model = new BtRemovePageTreeModel(this); - m_model->setSourceModel(CPointers::backend()->model()); - - m_view = new QTreeView(this); - m_view->header()->setResizeMode(QHeaderView::ResizeToContents); - m_view->setModel(m_model); +namespace { +const QString groupingOrderKey("GUI/BookshelfManager/RemovePage/grouping"); +} - layout->addWidget(m_view, 2, 0, 1, 2); +BtRemovePage::BtRemovePage(QWidget *parent) + : BtConfigPage(parent) +{ + namespace DU = util::directory; - m_removeButton = new QPushButton(tr("Remove..."), this); + m_worksGroupBox = new QGroupBox(tr("Select &works to uninstall:"), this); + m_worksGroupBox->setFlat(true); + QVBoxLayout *wLayout = new QVBoxLayout; + wLayout->setContentsMargins(0, 0, 0, 0); + m_worksGroupBox->setLayout(wLayout); + + BtRemovePageTreeModel *treeModel = new BtRemovePageTreeModel(groupingOrderKey, + this); + connect(treeModel, SIGNAL(groupingOrderChanged(BtBookshelfTreeModel::Grouping)), + this, SLOT(slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping&))); + + m_bookshelfWidget = new BtBookshelfWidget(this); + m_bookshelfWidget->postFilterModel()->setShowHidden(true); + m_bookshelfWidget->setTreeModel(treeModel); + m_bookshelfWidget->setSourceModel(CSwordBackend::instance()->model()); + m_bookshelfWidget->showHideAction()->setVisible(false); + m_bookshelfWidget->showHideButton()->hide(); + m_bookshelfWidget->treeView()->header()->show(); + m_bookshelfWidget->treeView()->header()->setResizeMode(QHeaderView::ResizeToContents); + wLayout->addWidget(m_bookshelfWidget); + + m_uninstallGroupBox = new QGroupBox(this); + m_uninstallGroupBox->setFlat(true); + retranslateUninstallGroupBox(); + QHBoxLayout *uLayout = new QHBoxLayout; + uLayout->setContentsMargins(0, 0, 0, 0); + m_uninstallGroupBox->setLayout(uLayout); + uLayout->addStretch(1); + + m_removeButton = new QPushButton(tr("&Remove..."), this); m_removeButton->setToolTip(tr("Remove the selected works")); m_removeButton->setIcon(DU::getIcon(CResMgr::bookshelfmgr::removepage::remove_icon)); m_removeButton->setEnabled(false); - layout->addWidget(m_removeButton, 3, 1, Qt::AlignRight); + uLayout->addWidget(m_removeButton, 0, Qt::AlignRight); + + Q_ASSERT(qobject_cast<QVBoxLayout*>(layout()) != 0); + QVBoxLayout *mainLayout = static_cast<QVBoxLayout*>(layout()); + mainLayout->addWidget(m_worksGroupBox, 1); + mainLayout->addWidget(m_uninstallGroupBox); connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveModules())); - connect(m_model, SIGNAL(moduleChecked(CSwordModuleInfo*, bool)), - this, SLOT(resetRemoveButton())); - connect(m_model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(resetRemoveButton())); + connect(m_bookshelfWidget->treeModel(), SIGNAL(moduleChecked(CSwordModuleInfo*,bool)), + this, SLOT(slotResetRemoveButton())); + connect(m_bookshelfWidget->treeModel(), SIGNAL(rowsRemoved(const QModelIndex&,int,int)), + this, SLOT(slotResetRemoveButton())); } -QString BtRemovePage::label() { - return tr("Remove installed works. Select the works and click Remove button."); +const QIcon &BtRemovePage::icon() const { + return util::directory::getIcon(CResMgr::bookshelfmgr::removepage::icon); } -QString BtRemovePage::iconName() { - return CResMgr::bookshelfmgr::removepage::icon; +QString BtRemovePage::header() const { + return tr("Remove"); } -QString BtRemovePage::header() { - return tr("Remove"); +void BtRemovePage::retranslateUninstallGroupBox() { + int count = m_bookshelfWidget->treeModel()->checkedModules().count(); + if (count > 0) { + m_uninstallGroupBox->setTitle(tr("Start removal of %1 works:") + .arg(count)); + } else { + m_uninstallGroupBox->setTitle(tr("Start removal:")); + } } -void BtRemovePage::resetRemoveButton() { - m_removeButton->setEnabled(!m_model->checkedModules().empty()); +void BtRemovePage::slotResetRemoveButton() { + retranslateUninstallGroupBox(); + m_removeButton->setEnabled(!m_bookshelfWidget->treeModel()->checkedModules().empty()); } void BtRemovePage::slotRemoveModules() { // Do nothing when this signal fires without anything selected to remove: - if (m_model->checkedModules().empty()) return; + if (m_bookshelfWidget->treeModel()->checkedModules().empty()) return; QStringList moduleNames; - foreach (CSwordModuleInfo *m, m_model->checkedModules()) { - moduleNames.append(m->name()); + const int textHeight = fontMetrics().height(); + /// \bug <nobr> is not working, Qt bug + const QString moduleString("<nobr><img src=\"%1\" width=\"%2\" height=\"%3\"/> %4</nobr>"); + const QString iconDir = util::directory::getIconDir().canonicalPath() + '/'; + Q_FOREACH(const CSwordModuleInfo *m, + m_bookshelfWidget->treeModel()->checkedModules()) + { + const QIcon icon = CSwordModuleInfo::moduleIcon(m); + const QSize iconSize = icon.actualSize(QSize(textHeight, textHeight)); + moduleNames.append(moduleString + .arg(iconDir + CSwordModuleInfo::moduleIconFilename(m)) + .arg(iconSize.width()) + .arg(iconSize.height()) + .arg(m->name())); } const QString message = tr("You selected the following work(s): ") - .append(moduleNames.join(", ")) - .append("\n\n") + .append("<br/><br/> ") + .append(moduleNames.join(", ")) + .append("<br/><br/>") .append(tr("Do you really want to remove them from your system?")); if ((util::showQuestion(this, tr("Remove Works?"), message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)) { //Yes was pressed. // Update the module list before really removing. Remember deleting the pointers later. - QList<CSwordModuleInfo*> toBeDeleted = CPointers::backend()->takeModulesFromList(moduleNames); + QList<CSwordModuleInfo*> toBeDeleted = CSwordBackend::instance()->takeModulesFromList(moduleNames); sword::InstallMgr installMgr; QMap<QString, sword::SWMgr*> mgrDict; //maps config paths to SWMgr objects @@ -131,3 +178,7 @@ void BtRemovePage::slotRemoveModules() { mgrDict.clear(); } } + +void BtRemovePage::slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g) { + g.saveTo(groupingOrderKey); +} diff --git a/src/frontend/bookshelfmanager/removepage/btremovepage.h b/src/frontend/bookshelfmanager/removepage/btremovepage.h index 2950619..11017d0 100644 --- a/src/frontend/bookshelfmanager/removepage/btremovepage.h +++ b/src/frontend/bookshelfmanager/removepage/btremovepage.h @@ -4,7 +4,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2009 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License * version 2.0. * @@ -21,29 +21,36 @@ #include "frontend/bookshelfmanager/removepage/btremovepagetreemodel.h" +class BtBookshelfWidget; +class QGroupBox; class QPushButton; -class QTreeView; class BtRemovePage: public BtConfigPage { Q_OBJECT public: - BtRemovePage(); + BtRemovePage(QWidget *parent = 0); - // BtConfigPage methods: - QString header(); - QString iconName(); - QString label(); + /** Reimplemented from BtConfigPage. */ + virtual QString header() const; - protected slots: + /** Reimplemented from BtConfigPage. */ + virtual const QIcon &icon() const; + + private: + void retranslateUninstallGroupBox(); + + private slots: void slotRemoveModules(); - void resetRemoveButton(); + void slotResetRemoveButton(); + void slotGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &g); - protected: - BtRemovePageTreeModel *m_model; + private: + QGroupBox *m_worksGroupBox; + BtBookshelfWidget *m_bookshelfWidget; - QTreeView *m_view; - QPushButton *m_removeButton; + QGroupBox *m_uninstallGroupBox; + QPushButton *m_removeButton; }; #endif diff --git a/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.cpp b/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.cpp index fe566d1..a0955b2 100644 --- a/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.cpp +++ b/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.cpp @@ -4,7 +4,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2009 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License * version 2.0. * @@ -13,8 +13,9 @@ #include "frontend/bookshelfmanager/removepage/btremovepagetreemodel.h" -BtRemovePageTreeModel::BtRemovePageTreeModel(QObject *parent) - : BtBookshelfTreeModel(parent) { +BtRemovePageTreeModel::BtRemovePageTreeModel(const QString &configKey, QObject *parent) + : BtBookshelfTreeModel(configKey, parent) +{ setCheckable(true); setDefaultChecked(BtBookshelfTreeModel::UNCHECKED); } diff --git a/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.h b/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.h index 619a1ff..14e0a67 100644 --- a/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.h +++ b/src/frontend/bookshelfmanager/removepage/btremovepagetreemodel.h @@ -4,7 +4,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2009 by the BibleTime developers. +* Copyright 1999-2011 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License * version 2.0. * @@ -19,7 +19,7 @@ class BtRemovePageTreeModel: public BtBookshelfTreeModel { Q_OBJECT public: - BtRemovePageTreeModel(QObject *parent = 0); + BtRemovePageTreeModel(const QString &configKey, QObject *parent = 0); int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |