/* * Copyright 2015 Luca Beltrame * * This file is part of Danbooru Client. * * Danbooru Client is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Danbooru Client is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Danbooru Client. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libdanbooru/danbooruservice.h" #include "libdanbooru/danboorupost.h" #include "libdanbooru/danboorupool.h" #include "model/danboorupostmodel.h" #include "model/danboorupoolmodel.h" #include "mainwindow.h" #include "danbooruconnectwidget.h" #include "danboorusearchwidget.h" #include "danboorusettings.h" #include "generalpage.h" namespace Danbooru { QHash DanbooruMainWindow::ratingMap = { {0, DanbooruPost::Safe}, {1, DanbooruPost::Questionable}, {2, DanbooruPost::Explicit} }; DanbooruMainWindow::DanbooruMainWindow(QWidget *parent) : KXmlGuiWindow(parent), m_view(new QQuickWidget(this)), m_model(new DanbooruPostModel(this)), m_poolModel(new DanbooruPoolModel(this)), m_service(new DanbooruService()), m_connectWidget(nullptr), m_searchWidget(new DanbooruSearchWidget(this)), m_tableView(new QTableView(this)), m_cache(nullptr) { m_service->setParent(this); setCentralWidget(m_view); // QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); qmlRegisterType("DanbooruClient", 1, 0, "DanbooruPost"); qmlRegisterType("DanbooruClient", 1, 0, "DanbooruService"); qRegisterMetaType(); loadSettings(); // TODO Configurable m_cache = new KImageCache(qApp->applicationName(), DanbooruSettings::self()->cacheSize()); m_service->setImageCache(m_cache); // Set up declarative bindings for the QQuickWidget m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); KDeclarative::KDeclarative declarative; declarative.setDeclarativeEngine(m_view->engine()); declarative.setupBindings(); auto qmlViewPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, qApp->applicationName() + QChar('/') + QLatin1Literal("danbooruimageview.qml")); QQmlContext *ctxt = m_view->rootContext(); ctxt->setContextProperty("danbooruModel", m_model); ctxt->setContextProperty("danbooruService", m_service); m_view->setSource(QUrl::fromLocalFile(qmlViewPath)); m_view->rootObject()->setProperty("poolMode", QVariant(false)); QVector boardsList = { QUrl("http://konachan.com"), QUrl("https://yande.re") }; m_connectWidget = new DanbooruConnectWidget(boardsList, this); statusBar()->addPermanentWidget(m_connectWidget); m_connectWidget->hide(); setupDockWidgets(); // then, setup our actions setupActions(); // add a status bar statusBar()->show(); setupGUI(KXmlGuiWindow::ToolBar|Keys|Save|Create|StatusBar, "danbooru-clientui.rc"); // connections connect(m_connectWidget, &DanbooruConnectWidget::accepted, [this]() { m_service->setBoardUrl(m_connectWidget->boardUrl()); if (!m_connectWidget->isAnonymous() && !m_connectWidget->username().isEmpty() && !m_connectWidget->password().isEmpty()) { m_service->setUserName(m_connectWidget->username()); m_service->setPassword(m_connectWidget->password()); } actionCollection()->action(QLatin1String("fetch"))->setEnabled(true); actionCollection()->action(QLatin1String("find"))->setEnabled(true); actionCollection()->action(QLatin1String("poolDownload"))->setEnabled(true); if (DanbooruSettings::self()->autoDownload()) { m_view->rootObject()->setProperty("poolMode", QVariant(false)); m_service->setPostTags(QStringList()); m_service->getPostList(); } m_connectWidget->hide(); }); connect(m_connectWidget, &DanbooruConnectWidget::rejected, [this]() { m_connectWidget->hide(); }); connect(m_service, &Danbooru::DanbooruService::postDownloaded, m_model, &Danbooru::DanbooruPostModel::addPost); connect(m_service, &Danbooru::DanbooruService::poolDownloaded, m_poolModel, &DanbooruPoolModel::addPool); connect(m_service, &Danbooru::DanbooruService::poolDownloadFinished, [this]() { m_tableView->resizeColumnsToContents(); } ); connect(m_tableView, &QTableView::doubleClicked, [this](QModelIndex index) { auto pool = m_poolModel->poolAt(index.row()); m_model->clear(); m_view->rootObject()->setProperty("poolMode", QVariant(true)); m_service->getPool(pool->id()); }); connect(m_searchWidget, &DanbooruSearchWidget::accepted, [this]() { QDockWidget* searchDockWidget = findChild(QLatin1String("SearchView")); searchDockWidget->hide(); m_model->clear(); m_service->setPostTags(m_searchWidget->selectedTags()); m_view->rootObject()->setProperty("poolMode", QVariant(false)); m_service->getPostList(); }); connect(m_searchWidget, &DanbooruSearchWidget::rejected, [this]() { QDockWidget* searchDockWidget = findChild(QLatin1String("SearchView")); searchDockWidget->hide(); }); } DanbooruMainWindow::~DanbooruMainWindow() { } void DanbooruMainWindow::loadSettings() { m_service->setBlacklist(DanbooruSettings::self()->tagBlacklist()); m_service->setMaxPosts(DanbooruSettings::self()->maxPosts()); m_service->setMaximumAllowedRating(ratingMap.value(DanbooruSettings::self()->maxRating())); m_service->setMaxPosts(DanbooruSettings::self()->maxPosts()); } void DanbooruMainWindow::setupActions() { QAction *connectAction = new QAction( QIcon::fromTheme(QLatin1String("document-open-remote")), i18n("Connect..."), this); QAction *fetchAction = new QAction(QIcon::fromTheme(QLatin1String("download")), i18n("Download"), this); KToggleAction *findAction = new KToggleAction(QIcon::fromTheme(QLatin1String("edit-find")), i18n("Search"), this); KToggleAction *poolAction = new KToggleAction(QIcon::fromTheme(QLatin1String("image-x-generic")), i18n("Pools"), this); fetchAction->setEnabled(false); findAction->setEnabled(false); poolAction->setEnabled(false); poolAction->setChecked(false); findAction->setChecked(false); actionCollection()->addAction(QLatin1String("connect"), connectAction); actionCollection()->addAction(QLatin1String("fetch"), fetchAction); actionCollection()->addAction(QLatin1String("find"), findAction); actionCollection()->addAction(QLatin1String("poolDownload"), poolAction); actionCollection()->setDefaultShortcut(connectAction, KStandardShortcut::Open); actionCollection()->setDefaultShortcut(findAction, KStandardShortcut::Find); KStandardAction::quit(qApp, SLOT(quit()), actionCollection()); KStandardAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); connect(connectAction, &QAction::triggered, this, &DanbooruMainWindow::connectToBoard); connect(fetchAction, &QAction::triggered, this, &DanbooruMainWindow::downloadPosts); connect(poolAction, &KToggleAction::toggled, [this](bool checked) { if (!m_service) { return; } QDockWidget* poolDockWidget = findChild(QLatin1String("PoolView")); if (checked) { if (m_poolModel->rowCount() == 0) { m_service->getPoolList(); } poolDockWidget->show(); m_tableView->show(); } else { poolDockWidget->hide(); m_tableView->hide(); } }); connect(findAction, &KToggleAction::toggled, [this](bool checked) { QDockWidget* searchDockWidget = findChild(QLatin1String("SearchView")); if (checked) { searchDockWidget->show(); m_searchWidget->show(); } else { searchDockWidget->hide(); m_searchWidget->hide(); } }); } void DanbooruMainWindow::setupDockWidgets() { // Set up PoolWidget m_tableView->setModel(m_poolModel); QDockWidget* poolDockWidget = new QDockWidget(i18n("Pools"), this); poolDockWidget->setAllowedAreas(Qt::BottomDockWidgetArea); poolDockWidget->setWidget(m_tableView); poolDockWidget->setObjectName("PoolView"); // Prevent the use of winId() when detached, leads to QQuickWidget bugs poolDockWidget->setFeatures(QDockWidget::DockWidgetClosable); addDockWidget(Qt::BottomDockWidgetArea, poolDockWidget); m_tableView->hide(); poolDockWidget->hide(); // Find widget QDockWidget *searchDockWidget = new QDockWidget(QLatin1String(""), this); searchDockWidget->setAllowedAreas(Qt::TopDockWidgetArea); searchDockWidget->setWidget(m_searchWidget); searchDockWidget->setObjectName("SearchView"); // FIXME: Get rid of the close button in the widget searchDockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures); addDockWidget(Qt::TopDockWidgetArea, searchDockWidget); searchDockWidget->hide(); m_searchWidget->hide(); searchDockWidget->setTitleBarWidget(new QWidget(this)); // Connections connect(poolDockWidget, &QDockWidget::visibilityChanged, [this](bool visible) { actionCollection()->action(QLatin1String("poolDownload"))->setChecked(visible); }); connect(searchDockWidget, &QDockWidget::visibilityChanged, [this](bool visible) { actionCollection()->action(QLatin1String("find"))->setChecked(visible); }); } void DanbooruMainWindow::connectToBoard() { if (!m_view) { return; } m_model->clear(); m_poolModel->clear(); m_service->reset(); m_connectWidget->show(); } void DanbooruMainWindow::downloadPosts() { if (!m_service) { return; } m_model->clear(); m_service->setPostTags(QStringList()); m_view->rootObject()->setProperty("poolMode", QVariant(false)); m_service->getPostList(); } void DanbooruMainWindow::optionsPreferences() { KConfigDialog* dialog = new KConfigDialog(this, "danboorusettings", DanbooruSettings::self()); dialog->addPage(new GeneralPage(DanbooruSettings::self(), this), i18n("General"), "table"); connect(dialog, &KConfigDialog::settingsChanged, this, &DanbooruMainWindow::loadSettings); dialog->show(); } } // namespace Danbooru