yacreader/YACReaderLibrary/classic_comics_view.cpp
Igor Kushnir 8a54100804 Library: allow configuring a shortcut to focus comics view
Focusing the current comics view allows to use keyboard arrow keys to
choose among the visible comics.

The shortcut for this new action should not be a single character
without modifiers because it won't work when the search line has focus.

The Qt::FocusReason parameter in ComicsView::focusComicsNavigation()
allows to reuse this function for other keyboard navigation features.
For instance the search line can transfer focus to comics navigation
when the user presses Return or Enter key. In this case
Qt::OtherFocusReason can be used (an application-specific reason).
2021-03-13 15:08:33 +02:00

378 lines
12 KiB
C++

#include "classic_comics_view.h"
#include "QStackedWidget"
#include "comic_flow_widget.h"
#include "QsLog.h"
#include "shortcuts_manager.h"
#include "yacreader_table_view.h"
#include "yacreader_tool_bar_stretch.h"
ClassicComicsView::ClassicComicsView(QWidget *parent)
: ComicsView(parent), searching(false)
{
auto layout = new QHBoxLayout;
settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
settings->beginGroup("libraryConfig");
//FLOW-----------------------------------------------------------------------
//---------------------------------------------------------------------------
//FORCE_ANGLE is not used here, because ComicFlowWidgetGL will use OpenGL ES in the future
#ifndef NO_OPENGL
if ((settings->value(USE_OPEN_GL).toBool() == true))
comicFlow = new ComicFlowWidgetGL(0);
else
comicFlow = new ComicFlowWidgetSW(0);
#else
comicFlow = new ComicFlowWidgetSW(0);
#endif
comicFlow->updateConfig(settings);
comicFlow->setFocusPolicy(Qt::StrongFocus);
comicFlow->setShowMarks(true);
setFocusProxy(comicFlow);
comicFlow->setFocus(Qt::OtherFocusReason);
comicFlow->setContextMenuPolicy(Qt::CustomContextMenu);
//layout-----------------------------------------------
sVertical = new QSplitter(Qt::Vertical); //spliter derecha
stack = new QStackedWidget;
stack->addWidget(comicFlow);
setupSearchingIcon();
stack->addWidget(searchingIcon);
sVertical->addWidget(stack);
comics = new QWidget;
auto comicsLayout = new QVBoxLayout;
comicsLayout->setSpacing(0);
comicsLayout->setContentsMargins(0, 0, 0, 0);
//TODO ComicsView:(set toolbar) comicsLayout->addWidget(editInfoToolBar);
tableView = new YACReaderTableView;
tableView->verticalHeader()->hide();
tableView->setFocusPolicy(Qt::StrongFocus);
comicsLayout->addWidget(tableView);
comics->setLayout(comicsLayout);
sVertical->addWidget(comics);
tableView->setContextMenuPolicy(Qt::CustomContextMenu);
//config--------------------------------------------------
if (settings->contains(COMICS_VIEW_HEADERS))
tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray());
//connections---------------------------------------------
connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(centerComicFlow(QModelIndex)));
connect(tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectedComicForOpening(QModelIndex)));
connect(comicFlow, SIGNAL(centerIndexChanged(int)), this, SLOT(updateTableView(int)));
connect(tableView, SIGNAL(comicRated(int, QModelIndex)), this, SIGNAL(comicRated(int, QModelIndex)));
connect(comicFlow, SIGNAL(selected(uint)), this, SIGNAL(selected(uint)));
connect(tableView->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), this, SLOT(saveTableHeadersStatus()));
connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this, SLOT(saveTableHeadersStatus()));
connect(comicFlow, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedViewContextMenu(QPoint)));
connect(tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedItemContextMenu(QPoint)));
layout->addWidget(sVertical);
setLayout(layout);
layout->setMargin(0);
#ifdef Q_OS_MAC
sVertical->setCollapsible(1, false);
#endif
if (settings->contains(COMICS_VIEW_FLOW_SPLITTER_STATUS))
sVertical->restoreState(settings->value(COMICS_VIEW_FLOW_SPLITTER_STATUS).toByteArray());
//hide flow widgets
hideFlowViewAction = new QAction(this);
hideFlowViewAction->setText(tr("Hide comic flow"));
hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL));
hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.png"));
hideFlowViewAction->setCheckable(true);
hideFlowViewAction->setChecked(false);
connect(hideFlowViewAction, SIGNAL(toggled(bool)), this, SLOT(hideComicFlow(bool)));
}
void ClassicComicsView::hideComicFlow(bool hide)
{
if (hide) {
QList<int> sizes;
sizes.append(0);
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
sizes.append(total);
sVertical->setSizes(sizes);
} else {
QList<int> sizes;
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
sizes.append(2 * total / 3);
sizes.append(total / 3);
sVertical->setSizes(sizes);
}
}
//the toolbar has to be populated
void ClassicComicsView::setToolBar(QToolBar *toolBar)
{
static_cast<QVBoxLayout *>(comics->layout())->insertWidget(0, toolBar);
this->toolbar = toolBar;
toolBarStretch = new YACReaderToolBarStretch(this);
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
toolBar->addAction(hideFlowViewAction);
}
void ClassicComicsView::setModel(ComicModel *model)
{
ComicsView::setModel(model);
if (model == NULL) {
comicFlow->clear();
} else {
connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QVector<int>)), this, SLOT(applyModelChanges(QModelIndex, QModelIndex, QVector<int>)), Qt::UniqueConnection);
connect(model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(removeItemsFromFlow(QModelIndex, int, int)), Qt::UniqueConnection);
connect(model, SIGNAL(resortedIndexes(QList<int>)), comicFlow, SLOT(resortCovers(QList<int>)), Qt::UniqueConnection);
connect(model, SIGNAL(newSelectedIndex(QModelIndex)), this, SLOT(setCurrentIndex(QModelIndex)), Qt::UniqueConnection);
tableView->setModel(model);
if (model->rowCount() > 0)
tableView->setCurrentIndex(model->index(0, 0));
tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
#if QT_VERSION >= 0x050000
tableView->horizontalHeader()->setSectionsMovable(true);
#else
tableView->horizontalHeader()->setMovable(true);
#endif
//TODO parametrizar la configuración de las columnas
/*if(!settings->contains(COMICS_VIEW_HEADERS))
{*/
for (int i = 0; i < tableView->horizontalHeader()->count(); i++)
tableView->horizontalHeader()->hideSection(i);
tableView->horizontalHeader()->showSection(ComicModel::Number);
tableView->horizontalHeader()->showSection(ComicModel::Title);
tableView->horizontalHeader()->showSection(ComicModel::FileName);
tableView->horizontalHeader()->showSection(ComicModel::NumPages);
tableView->horizontalHeader()->showSection(ComicModel::Hash); //Size is part of the Hash...TODO add Columns::Size to Columns
tableView->horizontalHeader()->showSection(ComicModel::ReadColumn);
tableView->horizontalHeader()->showSection(ComicModel::CurrentPage);
tableView->horizontalHeader()->showSection(ComicModel::Rating);
//}
//debido a un bug, qt4 no es capaz de ajustar el ancho teniendo en cuenta todas la filas (no sólo las visibles)
//así que se ecala la primera vez y después se deja el control al usuario.
//if(!settings->contains(COMICS_VIEW_HEADERS))
QStringList paths = model->getPaths(model->getCurrentPath()); //TODO ComicsView: get currentpath from somewhere currentPath());
comicFlow->setImagePaths(paths);
comicFlow->setMarks(model->getReadList());
//comicFlow->setFocus(Qt::OtherFocusReason);
if (settings->contains(COMICS_VIEW_HEADERS))
tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray());
tableView->resizeColumnsToContents();
tableView->horizontalHeader()->setStretchLastSection(true);
}
}
void ClassicComicsView::setCurrentIndex(const QModelIndex &index)
{
tableView->setCurrentIndex(index);
centerComicFlow(index);
}
QModelIndex ClassicComicsView::currentIndex()
{
return tableView->currentIndex();
}
QItemSelectionModel *ClassicComicsView::selectionModel()
{
return tableView->selectionModel();
}
void ClassicComicsView::scrollTo(const QModelIndex &mi, QAbstractItemView::ScrollHint hint)
{
Q_UNUSED(hint);
comicFlow->setCenterIndex(mi.row());
}
void ClassicComicsView::toFullScreen()
{
comicFlow->hide();
comicFlow->setCenterIndex(comicFlow->centerIndex());
comics->hide();
//showFullScreen() //parent windows
comicFlow->show();
comicFlow->setFocus(Qt::OtherFocusReason);
}
void ClassicComicsView::toNormal()
{
comicFlow->hide();
comicFlow->setCenterIndex(comicFlow->centerIndex());
comicFlow->render();
comics->show();
comicFlow->show();
}
void ClassicComicsView::updateConfig(QSettings *settings)
{
comicFlow->updateConfig(settings);
}
void ClassicComicsView::enableFilterMode(bool enabled)
{
if (enabled) {
comicFlow->clear();
if (previousSplitterStatus.isEmpty())
previousSplitterStatus = sVertical->saveState();
sVertical->setSizes(QList<int>() << 100 << 10000000);
showSearchingIcon();
} else {
hideSearchingIcon();
sVertical->restoreState(previousSplitterStatus);
previousSplitterStatus.clear();
}
//sVertical->setCollapsible(0,!enabled);
searching = enabled;
}
void ClassicComicsView::selectIndex(int index)
{
tableView->selectRow(index);
}
void ClassicComicsView::updateCurrentComicView()
{
}
void ClassicComicsView::focusComicsNavigation(Qt::FocusReason reason)
{
const bool comicFlowVisible = stack->currentWidget() == comicFlow && sVertical->sizes().constFirst() != 0;
if (comicFlowVisible)
comicFlow->setFocus(reason);
else // Let the user navigate the table.
tableView->setFocus(reason);
}
void ClassicComicsView::selectAll()
{
tableView->selectAll();
}
void ClassicComicsView::selectedComicForOpening(const QModelIndex &mi)
{
emit selected(mi.row());
}
void ClassicComicsView::requestedViewContextMenu(const QPoint &point)
{
emit customContextMenuViewRequested(comicFlow->mapTo(this, point));
}
void ClassicComicsView::requestedItemContextMenu(const QPoint &point)
{
emit customContextMenuItemRequested(tableView->mapTo(this, point));
}
void ClassicComicsView::setShowMarks(bool show)
{
comicFlow->setShowMarks(show);
}
void ClassicComicsView::centerComicFlow(const QModelIndex &mi)
{
comicFlow->showSlide(mi.row());
comicFlow->setFocus(Qt::OtherFocusReason);
}
void ClassicComicsView::updateTableView(int i)
{
QModelIndex mi = model->index(i, 2);
tableView->setCurrentIndex(mi);
tableView->scrollTo(mi, QAbstractItemView::EnsureVisible);
}
void ClassicComicsView::saveTableHeadersStatus()
{
settings->setValue(COMICS_VIEW_HEADERS, tableView->horizontalHeader()->saveState());
}
void ClassicComicsView::saveSplitterStatus()
{
settingsMutex.lock();
if (!searching)
settings->setValue(COMICS_VIEW_FLOW_SPLITTER_STATUS, sVertical->saveState());
settingsMutex.unlock();
}
void ClassicComicsView::applyModelChanges(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
Q_UNUSED(topLeft);
Q_UNUSED(bottomRight);
if (roles.contains(ComicModel::ReadColumnRole)) {
comicFlow->setMarks(model->getReadList());
comicFlow->updateMarks();
}
}
void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from, int to)
{
Q_UNUSED(parent);
for (int i = from; i <= to; i++)
comicFlow->remove(i);
}
void ClassicComicsView::closeEvent(QCloseEvent *event)
{
toolbar->removeAction(toolBarStretchAction);
toolbar->removeAction(hideFlowViewAction);
saveTableHeadersStatus();
saveSplitterStatus();
ComicsView::closeEvent(event);
}
void ClassicComicsView::setupSearchingIcon()
{
searchingIcon = new QWidget(comicFlow);
auto h = new QHBoxLayout;
QPixmap p(":/images/searching_icon.png");
QLabel *l = new QLabel(searchingIcon);
l->setPixmap(p);
l->setFixedSize(p.size());
h->addWidget(l, 0, Qt::AlignCenter);
searchingIcon->setLayout(h);
QPalette pal(searchingIcon->palette());
pal.setColor(QPalette::Background, Qt::black);
searchingIcon->setAutoFillBackground(true);
searchingIcon->setPalette(pal);
hideSearchingIcon();
}
void ClassicComicsView::showSearchingIcon()
{
stack->setCurrentWidget(searchingIcon);
}
void ClassicComicsView::hideSearchingIcon()
{
stack->setCurrentWidget(comicFlow);
}