/********* * * This file is part of BibleTime's source code, http://www.bibletime.info/. * * Copyright 1999-2016 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ #include "bibletime.h" #include #include #include #include #include #include #include #include #include #include #include "backend/config/btconfig.h" #include "backend/drivers/cswordbiblemoduleinfo.h" #include "backend/drivers/cswordbookmoduleinfo.h" #include "backend/drivers/cswordcommentarymoduleinfo.h" #include "backend/drivers/cswordlexiconmoduleinfo.h" #include "backend/drivers/cswordmoduleinfo.h" #include "backend/keys/cswordldkey.h" #include "backend/keys/cswordversekey.h" #include "bibletimeapp.h" #include "frontend/btaboutmoduledialog.h" #include "frontend/cmdiarea.h" #include "frontend/display/btfindwidget.h" #include "frontend/displaywindow/btactioncollection.h" #include "frontend/displaywindow/cbiblereadwindow.h" #include "frontend/displaywindow/cbookreadwindow.h" #include "frontend/displaywindow/ccommentaryreadwindow.h" #include "frontend/displaywindow/cdisplaywindow.h" #include "frontend/displaywindow/chtmlwritewindow.h" #include "frontend/displaywindow/clexiconreadwindow.h" #include "frontend/displaywindow/cplainwritewindow.h" #include "frontend/displaywindow/creadwindow.h" #include "frontend/keychooser/ckeychooser.h" #include "frontend/messagedialog.h" #include "frontend/searchdialog/csearchdialog.h" #include "util/btassert.h" #include "util/cresmgr.h" #include "util/directory.h" BibleTime *BibleTime::m_instance = nullptr; BibleTime::BibleTime(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { namespace DU = util::directory; BT_ASSERT(!m_instance); m_instance = this; QSplashScreen *splash = nullptr; QString splashHtml; if (btConfig().value("GUI/showSplashScreen", true)) { splashHtml = "
%1" "
"; static const char splash1[] = "startuplogo.png"; static const char splash2[] = "startuplogo_christmas.png"; static const char splash3[] = "startuplogo_easter.jpg"; static const char * const splashes[3] = { splash1, splash2, splash3 }; QString splashImage = DU::getPicsDir().canonicalPath().append("/") .append(splashes[rand() % 3]); QPixmap pm; if (!pm.load(splashImage)) { qWarning("Can't load startuplogo! Check your installation."); } splash = new QSplashScreen(this, pm); splash->setAttribute(Qt::WA_DeleteOnClose); splash->finish(this); splash->showMessage(splashHtml.arg(tr("Initializing the SWORD engine...")), Qt::AlignCenter); splash->show(); qApp->processEvents(); } initBackends(); if (splash != nullptr) { splash->showMessage(splashHtml.arg(tr("Creating BibleTime's user interface...")), Qt::AlignCenter); qApp->processEvents(); } initView(); if (splash != nullptr) { splash->showMessage(splashHtml.arg(tr("Initializing menu- and toolbars...")), Qt::AlignCenter); qApp->processEvents(); } initActions(); initMenubar(); initToolbars(); initConnections(); setWindowTitle("BibleTime " BT_VERSION); setWindowIcon(CResMgr::mainWindow::icon()); retranslateUi(); } BibleTime::~BibleTime() { // delete m_dcopInterface; // The backend is deleted by the BibleTimeApp instance #ifndef NDEBUG deleteDebugWindow(); #endif saveProfile(); } namespace { CReadWindow * createReadInstance(QList const modules, CMDIArea * const parent) { switch (modules.first()->type()) { case CSwordModuleInfo::Bible: return new CBibleReadWindow(modules, parent); case CSwordModuleInfo::Commentary: return new CCommentaryReadWindow(modules, parent); case CSwordModuleInfo::Lexicon: return new CLexiconReadWindow(modules, parent); case CSwordModuleInfo::GenericBook: return new CBookReadWindow(modules, parent); default: qFatal("unknown module type"); std::terminate(); } } } // anonymous namespace /** Creates a new presenter in the MDI area according to the type of the module. */ CDisplayWindow* BibleTime::createReadDisplayWindow(QList modules, const QString& key) { qApp->setOverrideCursor( QCursor(Qt::WaitCursor) ); // qDebug() << "BibleTime::createReadDisplayWindow(QList modules, const QString& key)"; CDisplayWindow * const displayWindow = createReadInstance(modules, m_mdi); if ( displayWindow ) { displayWindow->init(); m_mdi->addSubWindow(displayWindow); displayWindow->show(); // if (!key.isEmpty()) displayWindow->lookupKey(key); } // We have to process pending events here, otherwise displayWindow is not fully painted qApp->processEvents(); // Now all events, including mouse clicks for the displayWindow have been handled // and we can let the user click the same module again //m_bookshelfPage->unfreezeModules(modules); qApp->restoreOverrideCursor(); return displayWindow; } /** Creates a new presenter in the MDI area according to the type of the module. */ CDisplayWindow* BibleTime::createReadDisplayWindow(CSwordModuleInfo* module, const QString& key) { return createReadDisplayWindow(QList() << module, key); } CDisplayWindow * BibleTime::createWriteDisplayWindow(CSwordModuleInfo * module, const QString & key, CPlainWriteWindow::WriteWindowType type) { qApp->setOverrideCursor( QCursor(Qt::WaitCursor) ); CDisplayWindow * const displayWindow = (type == CPlainWriteWindow::HTMLWindow) ? new CHTMLWriteWindow(QList() << module, m_mdi) : new CPlainWriteWindow(QList() << module, m_mdi); displayWindow->init(); m_mdi->addSubWindow(displayWindow); if (m_mdi->subWindowList().isEmpty()) displayWindow->showMaximized(); else displayWindow->show(); displayWindow->lookupKey(key); qApp->restoreOverrideCursor(); return displayWindow; } CDisplayWindow* BibleTime::moduleEditPlain(CSwordModuleInfo *module) { /// \todo Refactor this. return createWriteDisplayWindow(module, QString::null, CPlainWriteWindow::PlainTextWindow); } CDisplayWindow* BibleTime::moduleEditHtml(CSwordModuleInfo *module) { /// \todo Refactor this. return createWriteDisplayWindow(module, QString::null, CPlainWriteWindow::HTMLWindow); } void BibleTime::searchInModule(CSwordModuleInfo *module) { /// \todo Refactor this. BtConstModuleList modules; modules.append(module); Search::CSearchDialog::openDialog(modules, QString::null); } bool BibleTime::moduleUnlock(CSwordModuleInfo *module, QWidget *parent) { /// \todo Write a proper unlocking dialog with integrated error messages. QString unlockKey; bool ok; for (;;) { unlockKey = QInputDialog::getText( parent, tr("Unlock Work"), tr("Enter the unlock key for %1.").arg(module->name()), QLineEdit::Normal, module->config(CSwordModuleInfo::CipherKey), &ok ); if (!ok) return false; module->unlock(unlockKey); /// \todo refactor this module reload /* There is currently a deficiency in sword 1.6.1 in that backend->setCipherKey() does * not work correctly for modules from which data was already fetched. Therefore we have to * reload the modules. */ { const QString moduleName(module->name()); CSwordBackend *backend = CSwordBackend::instance(); backend->reloadModules(CSwordBackend::OtherChange); module = backend->findModuleByName(moduleName); BT_ASSERT(module); } if (!module->isLocked()) break; message::showWarning(parent, tr("Warning: Invalid unlock key!"), tr("The unlock key you provided did not properly unlock this " "module. Please try again.")); } return true; } void BibleTime::slotModuleUnlock(CSwordModuleInfo *module) { moduleUnlock(module, this); } void BibleTime::moduleAbout(CSwordModuleInfo *module) { BTAboutModuleDialog *dialog = new BTAboutModuleDialog(module, this); dialog->setAttribute(Qt::WA_DeleteOnClose); // Destroy dialog when closed dialog->show(); dialog->raise(); } /** Refreshes all presenters.*/ void BibleTime::refreshDisplayWindows() const { Q_FOREACH(QMdiSubWindow const * const subWindow, m_mdi->subWindowList()) if (CDisplayWindow * const window = dynamic_cast(subWindow->widget())) window->reload(CSwordBackend::OtherChange); } void BibleTime::closeEvent(QCloseEvent *event) { /* Sequentially queries all open subwindows whether its fine to close them. If some sub- window returns false, the querying is stopped and the close event is ignored. If all subwindows return true, the close event is accepted. */ Q_FOREACH (QMdiSubWindow * const subWindow, m_mdi->subWindowList()) { if (CDisplayWindow * const window = dynamic_cast(subWindow->widget())) { if (!window->queryClose()) { event->ignore(); return; } } } event->accept(); } void BibleTime::processCommandline(bool ignoreSession, const QString &bibleKey) { if (btConfig().value("state/crashedTwoTimes", false)) { return; } // Restore workspace if not not ignoring session data: if (!ignoreSession) reloadProfile(); if (btConfig().value("state/crashedLastTime", false)) { return; } if (!bibleKey.isNull()) { CSwordModuleInfo* bible = btConfig().getDefaultSwordModuleByType("standardBible"); if (bibleKey == "random") { CSwordVerseKey vk(nullptr); const int maxIndex = 31100; int newIndex = rand() % maxIndex; vk.setPosition(sword::TOP); vk.setIndex(newIndex); createReadDisplayWindow(bible, vk.key()); } else { createReadDisplayWindow(bible, bibleKey); } /* We are sure only one window is open - it should be displayed fullscreen in the working area: */ m_mdi->myTileVertical(); } if (btConfig().value("state/crashedLastTime", false)) { btConfig().setValue("state/crashedTwoTimes", true); } else { btConfig().setValue("state/crashedLastTime", true); } btConfig().sync(); } bool BibleTime::event(QEvent* event) { if (event->type() == QEvent::Close) Search::CSearchDialog::closeDialog(); return QMainWindow::event(event); } const CSwordModuleInfo* BibleTime::getCurrentModule() { QMdiSubWindow* activeSubWindow = m_mdi->activeSubWindow(); if (!activeSubWindow) return nullptr; CDisplayWindow* w = dynamic_cast(activeSubWindow->widget()); if (!w) return nullptr; return w->modules().first(); } void BibleTime::openFindWidget() { m_findWidget->setVisible(true); m_findWidget->showAndSelect(); }