diff options
Diffstat (limited to 'src/frontend/bookshelfmanager/installpage/btsourcearea.cpp')
-rw-r--r-- | src/frontend/bookshelfmanager/installpage/btsourcearea.cpp | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp b/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp new file mode 100644 index 0000000..2f8de1a --- /dev/null +++ b/src/frontend/bookshelfmanager/installpage/btsourcearea.cpp @@ -0,0 +1,298 @@ +/********* +* +* 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 "btsourcearea.h" + +#include "frontend/bookshelfmanager/instbackend.h" + +#include "util/ctoolclass.h" +#include "util/cpointers.h" +#include "util/cresmgr.h" +#include "util/directoryutil.h" + +#include "backend/managers/cswordbackend.h" +#include "frontend/btaboutmoduledialog.h" + +#include <installmgr.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> + +// **************************************************************** +// ******** Installation source and module list widget ************ +// **************************************************************** + +BtSourceArea::BtSourceArea(const QString& sourceName) + : QWidget(), + m_sourceName(sourceName), + m_treeAlreadyInitialized(false), + m_remoteBackend(0) //important! +{ + m_checkedModules = QMap<QString, bool>(); + qDebug() << "BtSourceArea::BtSourceArea, " << m_sourceName; + initView(); +} + +BtSourceArea::~BtSourceArea() +{ + delete m_remoteBackend; +} + +void BtSourceArea::initView() +{ + qDebug("BtSourceArea::initView"); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + //QHBoxLayout *refreshLabelLayout = new QHBoxLayout(); + //QLabel *refreshLabel = new QLabel(tr("Last refreshed:")); + //m_refreshTimeLabel = new QLabel(); + //QSpacerItem *refreshLabelSpacer = new QSpacerItem(201, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + //refreshLabelLayout->addWidget(refreshLabel); + //refreshLabelLayout->addWidget(m_refreshTimeLabel); + //refreshLabelLayout->addItem(refreshLabelSpacer); + // TODO: or would it be better to integrate this information into the tooltip + // of the source tab? + //mainLayout->addLayout(refreshLabelLayout); + + // 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(util::filesystem::DirectoryUtil::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...")); + //m_editButton->setEnabled(false); // TODO after writing the edit widget + m_deleteButton = new QPushButton(tr("Delete...")); + m_deleteButton->setToolTip(tr("Delete this source")); + m_deleteButton->setIcon(util::filesystem::DirectoryUtil::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(util::filesystem::DirectoryUtil::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, CToolClass::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); +} + +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) { + // possible TODO: 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)); + 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 = CToolClass::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(); +} |