diff --git a/CHANGELOG.md b/CHANGELOG.md
index 935e4f2f7..69fd0a09d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,17 @@ Version counting is based on semantic versioning (Major.Feature.Patch)
## 10.3.0
+### YACReaderLibrary
+* Unify folder and comic browsing in the grid view. The side information panel can show information about folders and lists. There are settings to decide if folders should be displayed alongside comics and if folders and comics should be kept visually separated.
+* Fix drag & drop for sorting comics in lists.
+* Add state restoration when going back and forth through the navigation history.
+* Add scroll and current item restoration when switching between content views.
+* Keep current scroll position when editing comics.
+* Fix info panel in the grid view not getting updates when the select comic metadata changes.
+
### WebUI
-* Add per library search.
-* Use the same sorting used in the rest of the apps.
+* Add per-library search.
+* Use the same sorting as the rest of the apps.
## 10.2.0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 06c9dd077..577568a62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -126,7 +126,7 @@ if(BUILD_SERVER_STANDALONE)
Sql
)
else()
- find_package(Qt6 6.7 REQUIRED COMPONENTS
+ find_package(Qt6 6.9 REQUIRED COMPONENTS
Core
Core5Compat
Gui
diff --git a/README.md b/README.md
index 485fa3e5e..bf35ae677 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ Contributions are not restricted to coding; you can help the project by bringing
If you can't do it yourself please don't open PRs based on ideas developed using AI. If you are a software engineer it's ok to use AI as long as you know what you are doing, understanding and reviewing agent generated code before opening a PR is a must. Code that just works won't be enough to ensure I'll accept your contribution.
#### Dev Setup
-YACReader is developed in *C++/Qt* and built with *CMake*. You need a *C++20* compiler and *Qt 6.7+*. In *Windows* I use *Visual Studio 2022* and in *macOS* I use Xcode, but I do all the coding using *QtCreator*.
+YACReader is developed in *C++/Qt* and built with *CMake*. You need a *C++20* compiler and *Qt 6.9+*. In *Windows* I use *Visual Studio 2022* and in *macOS* I use Xcode, but I do all the coding using *QtCreator*.
The repo includes binaries for the dependencies needed for *Windows* (MSVC compiler) and *macOS* (clang). The *7zip* decompression backend source is downloaded automatically by CMake during configuration.
@@ -86,4 +86,4 @@ YACReader is free but it needs money to keep being alive, so please, if you like
If you are interested in YACReader, please contact me so we can discuss your next steps.
## Sponsors
-Free code signing on Windows provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
\ No newline at end of file
+Free code signing on Windows provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
diff --git a/YACReader/yacreader_de.ts b/YACReader/yacreader_de.ts
index 70c25659e..c32a6cbed 100644
--- a/YACReader/yacreader_de.ts
+++ b/YACReader/yacreader_de.ts
@@ -371,7 +371,7 @@
Löschen
-
+ Comics directoryComics-Verzeichnis
@@ -774,48 +774,48 @@ Wenn keiner aktiv ist, geschieht beim Drücken der Escape-Taste nichts.
Viewer
-
+ Page not available!Seite nicht verfügbar!
-
-
+
+ Press 'O' to open comic.'O' drücken, um Comic zu öffnen.
-
+ Error opening comicFehler beim Öffnen des Comics
-
+ Cover!Titelseite!
-
+ CRC ErrorCRC Fehler
-
+ Comic not foundComic nicht gefunden
-
+ Not foundNicht gefunden
-
+ Last page!Letzte Seite!
-
+ Loading...please wait!Ladevorgang... Bitte warten!
diff --git a/YACReader/yacreader_en.ts b/YACReader/yacreader_en.ts
index 71ff4c863..442a1f802 100644
--- a/YACReader/yacreader_en.ts
+++ b/YACReader/yacreader_en.ts
@@ -536,7 +536,7 @@ If none is active, Escape does nothing.
Options
-
+ Comics directoryComics directory
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
-
+
+ Press 'O' to open comic.Press 'O' to open comic.
-
+ Not foundNot found
-
+ Comic not foundComic not found
-
+ Error opening comicError opening comic
-
+ CRC ErrorCRC Error
-
+ Loading...please wait!Loading...please wait!
-
+ Page not available!Page not available!
-
+ Cover!Cover!
-
+ Last page!Last page!
diff --git a/YACReader/yacreader_es.ts b/YACReader/yacreader_es.ts
index 19c9df467..a59db3122 100644
--- a/YACReader/yacreader_es.ts
+++ b/YACReader/yacreader_es.ts
@@ -371,7 +371,7 @@
Limpiar
-
+ Comics directoryDirectorio de cómics
@@ -774,48 +774,48 @@ Si ninguno está activo, la tecla Esc no hace nada.
Viewer
-
+ Page not available!¡Página no disponible!
-
-
+
+ Press 'O' to open comic.Pulsa 'O' para abrir un fichero.
-
+ Error opening comicError abriendo cómic
-
+ Cover!¡Portada!
-
+ CRC ErrorError CRC
-
+ Comic not foundCómic no encontrado
-
+ Not foundNo encontrado
-
+ Last page!¡Última página!
-
+ Loading...please wait!Cargando...espere, por favor!
diff --git a/YACReader/yacreader_fr.ts b/YACReader/yacreader_fr.ts
index f86d19b94..592acac34 100644
--- a/YACReader/yacreader_fr.ts
+++ b/YACReader/yacreader_fr.ts
@@ -346,7 +346,7 @@
Clair
-
+ Comics directoryRépertoire des bandes dessinées
@@ -774,48 +774,48 @@ Si aucun n’est actif, la touche Échap ne fait rien.
Viewer
-
+ Page not available!Page non disponible !
-
-
+
+ Press 'O' to open comic.Appuyez sur "O" pour ouvrir une bande dessinée.
-
+ Error opening comicErreur d'ouverture de la bande dessinée
-
+ Cover!Couverture!
-
+ CRC ErrorErreur CRC
-
+ Comic not foundBande dessinée introuvable
-
+ Not foundIntrouvable
-
+ Last page!Dernière page!
-
+ Loading...please wait!Chargement... Patientez
diff --git a/YACReader/yacreader_it.ts b/YACReader/yacreader_it.ts
index f6271e7a2..c387e5947 100644
--- a/YACReader/yacreader_it.ts
+++ b/YACReader/yacreader_it.ts
@@ -346,7 +346,7 @@
Cancella
-
+ Comics directoryCartella Fumetti
@@ -463,7 +463,7 @@ If none is active, Escape does nothing.
Tooltip listing the order in which modes are cancelled. Only the first active mode in the list is cancelled per Escape keypress.Il tasto Esc annulla la prima modalità attiva tra le seguenti:
-1. Lente d'ingrandimento
+1. Lente d'ingrandimento
2. Dizionario
3. Barra Vai alla pagina
4. Schermo intero
@@ -774,48 +774,48 @@ Se non è attiva alcuna modalità, il tasto Esc non esegue alcuna azione.
Viewer
-
+ Page not available!Pagina non disponibile!
-
-
+
+ Press 'O' to open comic.Premi "O" per aprire il fumettto.
-
+ Error opening comicErrore nell'apertura
-
+ Cover!Copertina!
-
+ CRC ErrorErrore CRC
-
+ Comic not foundFumetto non trovato
-
+ Not foundNon trovato
-
+ Last page!Ultima pagina!
-
+ Loading...please wait!In caricamento...Attendi!
diff --git a/YACReader/yacreader_ko.ts b/YACReader/yacreader_ko.ts
index 475e4c299..766006e5d 100644
--- a/YACReader/yacreader_ko.ts
+++ b/YACReader/yacreader_ko.ts
@@ -536,7 +536,7 @@ If none is active, Escape does nothing.
재시작이 필요합니다
-
+ Comics directory만화 폴더
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
-
+
+ Press 'O' to open comic.'O'를 눌러 만화를 열어보세요.
-
+ Not found찾을 수 없음
-
+ Comic not found만화를 찾을 수 없습니다
-
+ Error opening comic만화를 여는 중 오류가 발생했습니다
-
+ CRC ErrorCRC 오류
-
+ Loading...please wait!불러오는 중... 잠시 기다려주세요!
-
+ Page not available!페이지를 불러올 수 없습니다!
-
+ Cover!표지!
-
+ Last page!마지막 페이지!
@@ -1002,12 +1002,12 @@ If none is active, Escape does nothing.
Extract page(s)
-
+ 페이지 추출Extract page(s) from the original source
-
+ 원본 소스에서 페이지 추출
@@ -1302,32 +1302,32 @@ If none is active, Escape does nothing.
Overwrite file?
-
+ 파일을 덮어쓰시겠습니까?The file already exists. Do you want to overwrite it?
-
+ 파일이 이미 존재합니다. 덮어쓰시겠습니까?The current page could not be extracted.
-
+ 현재 페이지를 추출할 수 없습니다.Overwrite files?
-
+ 파일을 덮어쓰시겠습니까?Some files already exist. Do you want to overwrite them?
-
+ 일부 파일이 이미 존재합니다. 덮어쓰시겠습니까?Some pages could not be extracted.
-
+ 일부 페이지를 추출할 수 없습니다.
@@ -1495,12 +1495,12 @@ If none is active, Escape does nothing.
Release notes are not available.
-
+ 릴리스 노트를 사용할 수 없습니다.Previous versions
-
+ 이전 버전
diff --git a/YACReader/yacreader_nl.ts b/YACReader/yacreader_nl.ts
index 17fd353fb..f03b46043 100644
--- a/YACReader/yacreader_nl.ts
+++ b/YACReader/yacreader_nl.ts
@@ -371,7 +371,7 @@
Duidelijk
-
+ Comics directoryStrips map
@@ -774,48 +774,48 @@ Als geen enkele modus actief is, doet de Escape-toets niets.Viewer
-
-
+
+ Press 'O' to open comic.Druk 'O' om een strip te openen.
-
+ Cover!Omslag!
-
+ Comic not foundStrip niet gevonden
-
+ Not foundNiet gevonden
-
+ Last page!Laatste pagina!
-
+ Loading...please wait!Inladen...even wachten!
-
+ Error opening comicFout bij openen strip
-
+ CRC ErrorCRC-fout
-
+ Page not available!Pagina niet beschikbaar!
diff --git a/YACReader/yacreader_pt.ts b/YACReader/yacreader_pt.ts
index 2adf055d5..88c9f5eab 100644
--- a/YACReader/yacreader_pt.ts
+++ b/YACReader/yacreader_pt.ts
@@ -316,7 +316,7 @@
Claro
-
+ Comics directoryDiretório de quadrinhos
@@ -774,48 +774,48 @@ Se nenhum estiver ativo, a tecla Escape não faz nada.
Viewer
-
-
+
+ Press 'O' to open comic.Pressione 'O' para abrir um quadrinho.
-
+ Loading...please wait!Carregando... por favor, aguarde!
-
+ Not foundNão encontrado
-
+ Comic not foundQuadrinho não encontrado
-
+ Error opening comicErro ao abrir quadrinho
-
+ CRC ErrorErro CRC
-
+ Page not available!Página não disponível!
-
+ Cover!Cobrir!
-
+ Last page!Última página!
diff --git a/YACReader/yacreader_ru.ts b/YACReader/yacreader_ru.ts
index 25966fa4b..7614cdcd1 100644
--- a/YACReader/yacreader_ru.ts
+++ b/YACReader/yacreader_ru.ts
@@ -346,7 +346,7 @@
Очистить
-
+ Comics directoryПапка комиксов
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
+ Page not available!Страница недоступна!
-
-
+
+ Press 'O' to open comic.Нажмите "O" чтобы открыть комикс.
-
+ Error opening comicОшибка открытия комикса
-
+ Cover!Начало!
-
+ CRC ErrorОшибка CRC
-
+ Comic not foundКомикс не найден
-
+ Not foundНе найдено
-
+ Last page!Конец!
-
+ Loading...please wait!Загрузка... Пожалуйста подождите!
diff --git a/YACReader/yacreader_source.ts b/YACReader/yacreader_source.ts
index b0f23d4a1..39b770628 100644
--- a/YACReader/yacreader_source.ts
+++ b/YACReader/yacreader_source.ts
@@ -525,7 +525,7 @@ If none is active, Escape does nothing.
-
+ Comics directory
@@ -760,48 +760,48 @@ If none is active, Escape does nothing.
Viewer
-
-
+
+ Press 'O' to open comic.
-
+ Not found
-
+ Comic not found
-
+ Error opening comic
-
+ CRC Error
-
+ Loading...please wait!
-
+ Page not available!
-
+ Cover!
-
+ Last page!
diff --git a/YACReader/yacreader_tr.ts b/YACReader/yacreader_tr.ts
index d397cdd45..235e63225 100644
--- a/YACReader/yacreader_tr.ts
+++ b/YACReader/yacreader_tr.ts
@@ -371,7 +371,7 @@
Temizle
-
+ Comics directoryÇizgi roman konumu
@@ -774,48 +774,48 @@ Hiçbiri etkin değilse Escape tuşu hiçbir şey yapmaz.
Viewer
-
-
+
+ Press 'O' to open comic.'O'ya basarak aç.
-
+ Cover!Kapak!
-
+ Comic not foundÇizgi roman bulunamadı
-
+ Not foundBulunamadı
-
+ Last page!Son sayfa!
-
+ Loading...please wait!Yükleniyor... lütfen bekleyin!
-
+ Error opening comicÇizgi roman açılırken hata
-
+ CRC ErrorCRC Hatası
-
+ Page not available!Sayfa bulunamadı!
diff --git a/YACReader/yacreader_zh_CN.ts b/YACReader/yacreader_zh_CN.ts
index 0a717df42..dbba6b62a 100644
--- a/YACReader/yacreader_zh_CN.ts
+++ b/YACReader/yacreader_zh_CN.ts
@@ -466,7 +466,7 @@ If none is active, Escape does nothing.
清空
-
+ Comics directory漫画目录
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
+ Page not available!页面不可用!
-
-
+
+ Press 'O' to open comic.按下 'O' 以打开漫画.
-
+ Error opening comic打开漫画时发生错误
-
+ Cover!封面!
-
+ CRC ErrorCRC 校验失败
-
+ Comic not found未找到漫画
-
+ Not found未找到
-
+ Last page!尾页!
-
+ Loading...please wait!载入中... 请稍候!
diff --git a/YACReader/yacreader_zh_HK.ts b/YACReader/yacreader_zh_HK.ts
index 67c895019..0a1f57757 100644
--- a/YACReader/yacreader_zh_HK.ts
+++ b/YACReader/yacreader_zh_HK.ts
@@ -536,7 +536,7 @@ If none is active, Escape does nothing.
選項
-
+ Comics directory漫畫目錄
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
-
+
+ Press 'O' to open comic.按下 'O' 以打開漫畫.
-
+ Not found未找到
-
+ Comic not found未找到漫畫
-
+ Error opening comic打開漫畫時發生錯誤
-
+ CRC ErrorCRC 校驗失敗
-
+ Loading...please wait!載入中... 請稍候!
-
+ Page not available!頁面不可用!
-
+ Cover!封面!
-
+ Last page!尾頁!
diff --git a/YACReader/yacreader_zh_TW.ts b/YACReader/yacreader_zh_TW.ts
index 4c7fb9b82..fc9174538 100644
--- a/YACReader/yacreader_zh_TW.ts
+++ b/YACReader/yacreader_zh_TW.ts
@@ -536,7 +536,7 @@ If none is active, Escape does nothing.
選項
-
+ Comics directory漫畫目錄
@@ -774,48 +774,48 @@ If none is active, Escape does nothing.
Viewer
-
-
+
+ Press 'O' to open comic.按下 'O' 以打開漫畫.
-
+ Not found未找到
-
+ Comic not found未找到漫畫
-
+ Error opening comic打開漫畫時發生錯誤
-
+ CRC ErrorCRC 校驗失敗
-
+ Loading...please wait!載入中... 請稍候!
-
+ Page not available!頁面不可用!
-
+ Cover!封面!
-
+ Last page!尾頁!
diff --git a/YACReaderLibrary/CMakeLists.txt b/YACReaderLibrary/CMakeLists.txt
index 803149a7c..fac73e197 100644
--- a/YACReaderLibrary/CMakeLists.txt
+++ b/YACReaderLibrary/CMakeLists.txt
@@ -122,16 +122,17 @@ qt_add_executable(YACReaderLibrary WIN32
yacreader_main_toolbar.cpp
comics_view.h
comics_view.cpp
+ content_view_state.h
comics_view_transition.h
comics_view_transition.cpp
classic_comics_view.h
classic_comics_view.cpp
grid_comics_view.h
grid_comics_view.cpp
+ grid_content_model.h
+ grid_content_model.cpp
no_search_results_widget.h
no_search_results_widget.cpp
- folder_content_view.h
- folder_content_view.cpp
recent_visibility_coordinator.h
recent_visibility_coordinator.cpp
library_comic_opener.h
@@ -348,7 +349,14 @@ set_source_files_properties(
)
set(yacreaderlibrary_qml_files
${CMAKE_CURRENT_SOURCE_DIR}/qml/GridComicsView.qml
- ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderContentView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ComicGridDelegate.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/EmptyInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderCover.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderGridDelegate.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/LibraryInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ListInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ContinueReadingGridHeader.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/FlowView.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/InfoTick.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/InfoFavorites.qml
@@ -370,7 +378,14 @@ set(yacreaderlibrary_qml_files
)
set(yacreaderlibrary_qml_translation_files
${CMAKE_CURRENT_SOURCE_DIR}/qml/GridComicsView.qml
- ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderContentView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ComicGridDelegate.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/EmptyInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderCover.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderGridDelegate.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/FolderInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/LibraryInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ListInfoView.qml
+ ${CMAKE_CURRENT_SOURCE_DIR}/qml/ContinueReadingGridHeader.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/FlowView.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/InfoTick.qml
${CMAKE_CURRENT_SOURCE_DIR}/qml/InfoFavorites.qml
diff --git a/YACReaderLibrary/classic_comics_view.cpp b/YACReaderLibrary/classic_comics_view.cpp
index ba7c6a082..75f92a03d 100644
--- a/YACReaderLibrary/classic_comics_view.cpp
+++ b/YACReaderLibrary/classic_comics_view.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -16,7 +17,7 @@
#include
ClassicComicsView::ClassicComicsView(QWidget *parent)
- : ComicsView(parent), searching(false)
+ : ComicsView(parent), toolbar(nullptr), startSeparatorAction(nullptr), searching(false)
{
auto layout = new QHBoxLayout;
@@ -132,10 +133,33 @@ void ClassicComicsView::hideComicFlow(bool hide)
void ClassicComicsView::setToolBar(QToolBar *toolBar)
{
static_cast(comics->layout())->insertWidget(0, toolBar);
- this->toolbar = toolBar;
+ toolbar = toolBar;
- startSeparatorAction = toolBar->addSeparator();
- toolBar->addAction(hideFlowViewAction);
+ if (!startSeparatorAction) {
+ startSeparatorAction = new QAction(this);
+ startSeparatorAction->setSeparator(true);
+ }
+
+ const auto actions = toolbar->actions();
+ if (!actions.contains(startSeparatorAction))
+ toolbar->addAction(startSeparatorAction);
+ if (!actions.contains(hideFlowViewAction))
+ toolbar->addAction(hideFlowViewAction);
+}
+
+void ClassicComicsView::releaseToolBar()
+{
+ if (!toolbar)
+ return;
+
+ toolbar->removeAction(startSeparatorAction);
+ toolbar->removeAction(hideFlowViewAction);
+}
+
+void ClassicComicsView::saveViewConfig()
+{
+ saveTableHeadersStatus();
+ saveSplitterStatus();
}
void ClassicComicsView::setModel(ComicModel *model)
@@ -235,6 +259,49 @@ void ClassicComicsView::scrollTo(const QModelIndex &mi, QAbstractItemView::Scrol
comicFlow->setCenterIndex(mi.row());
}
+ContentViewState ClassicComicsView::captureViewState() const
+{
+ ContentViewState state;
+ const auto topIndex = tableView->indexAt(QPoint(0, 0));
+ if (topIndex.isValid()) {
+ state.topItem.kind = ContentItemRef::Comic;
+ state.topItem.id = topIndex.data(ComicModel::IdRole).toULongLong();
+ state.fallbackComicRow = topIndex.row();
+ state.offset = -tableView->visualRect(topIndex).top();
+ state.itemExtent = tableView->rowHeight(topIndex.row());
+ }
+
+ const auto selectedIndex = tableView->currentIndex();
+ if (selectedIndex.isValid()) {
+ state.currentItem.kind = ContentItemRef::Comic;
+ state.currentItem.id = selectedIndex.data(ComicModel::IdRole).toULongLong();
+ }
+ return state;
+}
+
+void ClassicComicsView::restoreViewState(const ContentViewState &state)
+{
+ if (!model || model->rowCount() == 0)
+ return;
+
+ if (state.currentItem.kind == ContentItemRef::Comic) {
+ const auto current = model->getIndexFromId(state.currentItem.id);
+ if (current.isValid()) {
+ tableView->setCurrentIndex(current);
+ comicFlow->setCenterIndexWithoutAnimation(current.row());
+ }
+ }
+
+ const auto topIndex = state.topItem.kind == ContentItemRef::Comic ? model->getIndexFromId(state.topItem.id) : QModelIndex();
+ const auto fallbackRow = qBound(0, state.fallbackComicRow, model->rowCount() - 1);
+ const auto restoreIndex = topIndex.isValid() ? topIndex : model->index(fallbackRow, 0);
+ if (restoreIndex.isValid()) {
+ tableView->scrollTo(restoreIndex, QAbstractItemView::PositionAtTop);
+ if (state.offset > 0)
+ tableView->verticalScrollBar()->setValue(tableView->verticalScrollBar()->value() + qRound(state.offset));
+ }
+}
+
void ClassicComicsView::toFullScreen()
{
comicFlow->hide();
@@ -383,12 +450,19 @@ void ClassicComicsView::saveSplitterStatus()
void ClassicComicsView::applyModelChanges(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles)
{
- Q_UNUSED(topLeft);
- Q_UNUSED(bottomRight);
if (roles.contains(ComicModel::ReadColumnRole)) {
comicFlow->setMarks(model->getReadList());
comicFlow->updateMarks();
}
+
+ if (roles.contains(ComicModel::CoverPathRole)) {
+ const auto centerIndex = comicFlow->centerIndex();
+ for (auto row = topLeft.row(); row <= bottomRight.row(); ++row) {
+ comicFlow->remove(row);
+ comicFlow->add(model->index(row, 0).data(ComicModel::CoverPathRole).toUrl().toLocalFile(), row);
+ }
+ comicFlow->setCenterIndexWithoutAnimation(centerIndex);
+ }
}
void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from, int to)
@@ -409,11 +483,8 @@ void ClassicComicsView::addItemsToFlow(const QModelIndex &parent, int from, int
void ClassicComicsView::closeEvent(QCloseEvent *event)
{
- toolbar->removeAction(startSeparatorAction);
- toolbar->removeAction(hideFlowViewAction);
-
- saveTableHeadersStatus();
- saveSplitterStatus();
+ releaseToolBar();
+ saveViewConfig();
ComicsView::closeEvent(event);
}
diff --git a/YACReaderLibrary/classic_comics_view.h b/YACReaderLibrary/classic_comics_view.h
index 836dce9c1..729c1f0d6 100644
--- a/YACReaderLibrary/classic_comics_view.h
+++ b/YACReaderLibrary/classic_comics_view.h
@@ -27,6 +27,8 @@ class ClassicComicsView : public ComicsView, protected Themable
protected:
void applyTheme(const Theme &theme) override;
void setToolBar(QToolBar *toolBar) override;
+ void releaseToolBar() override;
+ void saveViewConfig() override;
void setModel(ComicModel *model) override;
QModelIndex currentIndex() override;
@@ -39,6 +41,8 @@ class ClassicComicsView : public ComicsView, protected Themable
void selectIndex(int index) override;
void updateCurrentComicView() override;
void focusComicsNavigation(Qt::FocusReason reason) override;
+ ContentViewState captureViewState() const override;
+ void restoreViewState(const ContentViewState &state) override;
public slots:
void setCurrentIndex(const QModelIndex &index) override;
diff --git a/YACReaderLibrary/comic_flow_widget.cpp b/YACReaderLibrary/comic_flow_widget.cpp
index 0c2b603ed..00bbdad55 100644
--- a/YACReaderLibrary/comic_flow_widget.cpp
+++ b/YACReaderLibrary/comic_flow_widget.cpp
@@ -92,6 +92,11 @@ void ComicFlowWidget::setCenterIndex(int index)
flow->setCenterIndex(index);
}
+void ComicFlowWidget::setCenterIndexWithoutAnimation(int index)
+{
+ flow->setCurrentIndexWithoutAnimation(index);
+}
+
void ComicFlowWidget::showSlide(int index)
{
flow->showSlide(index);
diff --git a/YACReaderLibrary/comic_flow_widget.h b/YACReaderLibrary/comic_flow_widget.h
index 175564967..0ee35b5bc 100644
--- a/YACReaderLibrary/comic_flow_widget.h
+++ b/YACReaderLibrary/comic_flow_widget.h
@@ -26,6 +26,7 @@ public slots:
void clear();
void setImagePaths(QStringList paths);
void setCenterIndex(int index);
+ void setCenterIndexWithoutAnimation(int index);
void showSlide(int index);
int centerIndex();
void updateMarks();
diff --git a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp
index ff4910e32..2e68974ec 100644
--- a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp
+++ b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp
@@ -110,8 +110,6 @@ void ComicVineDialog::doConnections()
connect(selectVolumeWidget, &SelectVolume::loadPage, this, &ComicVineDialog::searchVolume);
connect(selectComicWidget, &SelectComic::loadPage, this, &ComicVineDialog::getVolumeComicsInfo);
connect(sortVolumeComicsWidget, &SortVolumeComics::loadPage, this, &ComicVineDialog::getVolumeComicsInfo);
-
- connect(this, &QDialog::accepted, this, &QWidget::close, Qt::QueuedConnection);
}
void ComicVineDialog::goNext()
@@ -463,7 +461,7 @@ void ComicVineDialog::getComicsInfo(QList> matchingInfo,
DBHelper::updateComicsInfo(comics, databasePath);
- emit accepted();
+ finishSuccessfully();
}
void ComicVineDialog::getComicInfo(const QString &comicId, const SelectedVolumeInfo &volumeInfo)
@@ -474,12 +472,11 @@ void ComicVineDialog::getComicInfo(const QString &comicId, const SelectedVolumeI
bool timeout;
QByteArray result = comicVineClient->getComicDetail(comicId, error, timeout); // TODO check timeOut or Connection error
if (error || timeout) {
- // TODO
- if (mode == ScraperMode::SingleComic || currentIndex == (comics.count() - 1)) {
- emit accepted();
- } else {
+ if (mode == ScraperMode::SingleComic || currentIndex == (comics.count() - 1))
+ finishSuccessfully();
+ else
goToNextComic();
- }
+ return;
}
ComicDB comic = YACReader::parseCVJSONComicInfo(comics[currentIndex], result, volumeInfo); // TODO check result error
@@ -499,7 +496,7 @@ void ComicVineDialog::getComicInfo(const QString &comicId, const SelectedVolumeI
QSqlDatabase::removeDatabase(connectionName);
if (mode == ScraperMode::SingleComic || currentIndex == (comics.count() - 1)) {
- emit accepted();
+ finishSuccessfully();
} else {
goToNextComic();
}
@@ -535,7 +532,7 @@ QString ComicVineDialog::volumeSearchStringFromComic(const ComicDB &comic)
void ComicVineDialog::goToNextComic()
{
if (mode == ScraperMode::SingleComic || currentIndex == (comics.count() - 1)) {
- emit accepted();
+ finishSuccessfully();
return;
}
@@ -554,6 +551,16 @@ void ComicVineDialog::clearState()
selectVolumeWidget->clearFilter();
}
+void ComicVineDialog::finishSuccessfully()
+{
+ // Scraping completion may be reported from a worker thread. Complete the
+ // dialog through QDialog's canonical success path on the GUI thread so it
+ // closes and emits accepted exactly once.
+ QMetaObject::invokeMethod(this, [this]() {
+ clearState();
+ accept(); }, Qt::QueuedConnection);
+}
+
void ComicVineDialog::showLoading(const QString &message)
{
content->setCurrentIndex(0);
diff --git a/YACReaderLibrary/comic_vine/comic_vine_dialog.h b/YACReaderLibrary/comic_vine/comic_vine_dialog.h
index ecd4485b6..547bbfc5b 100644
--- a/YACReaderLibrary/comic_vine/comic_vine_dialog.h
+++ b/YACReaderLibrary/comic_vine/comic_vine_dialog.h
@@ -68,6 +68,7 @@ protected slots:
private:
void clearState();
+ void finishSuccessfully();
void toggleSkipButton();
QString volumeSearchStringFromComic(const ComicDB &comic);
diff --git a/YACReaderLibrary/comics_view.cpp b/YACReaderLibrary/comics_view.cpp
index 149b2057f..cd56cf7bd 100644
--- a/YACReaderLibrary/comics_view.cpp
+++ b/YACReaderLibrary/comics_view.cpp
@@ -8,6 +8,8 @@
#include
#include
+#include
+
ComicsView::ComicsView(QWidget *parent)
: QWidget(parent), model(nullptr), comicDB(nullptr)
{
@@ -26,7 +28,7 @@ ComicsView::ComicsView(QWidget *parent)
}
});
- auto comicDB = new ComicDB();
+ comicDB = new ComicDB();
auto comicInfo = &(comicDB->info);
QQmlContext *ctxt = view->rootContext();
@@ -55,8 +57,10 @@ void ComicsView::updateInfoForIndex(int index)
{
QQmlContext *ctxt = view->rootContext();
- if (comicDB != nullptr)
- delete comicDB;
+ // Clear the member before destroying the object. Deleting ComicDB notifies
+ // QML and can re-enter this method; an invalid index must also not leave a
+ // dangling pointer that is deleted again when the next comic is selected.
+ delete std::exchange(comicDB, nullptr);
if ((index < 0) || (index >= model->rowCount())) {
ctxt->setContextProperty("comic", nullptr);
diff --git a/YACReaderLibrary/comics_view.h b/YACReaderLibrary/comics_view.h
index 22ab71e38..ccf14520b 100644
--- a/YACReaderLibrary/comics_view.h
+++ b/YACReaderLibrary/comics_view.h
@@ -2,6 +2,7 @@
#define COMICS_VIEW_H
#include "comic_model.h"
+#include "content_view_state.h"
#include
#include
@@ -20,6 +21,8 @@ class ComicsView : public QWidget
public:
explicit ComicsView(QWidget *parent = nullptr);
virtual void setToolBar(QToolBar *toolBar) = 0;
+ virtual void releaseToolBar() = 0;
+ virtual void saveViewConfig() { }
virtual void setModel(ComicModel *model);
virtual void setCurrentIndex(const QModelIndex &index) = 0;
virtual QModelIndex currentIndex() = 0;
@@ -33,6 +36,8 @@ class ComicsView : public QWidget
virtual void updateCurrentComicView() = 0;
virtual void focusComicsNavigation(Qt::FocusReason reason) = 0;
virtual void reloadContent();
+ virtual ContentViewState captureViewState() const { return { }; }
+ virtual void restoreViewState(const ContentViewState &state) { Q_UNUSED(state); }
public slots:
virtual void updateInfoForIndex(int index);
diff --git a/YACReaderLibrary/content_view_state.h b/YACReaderLibrary/content_view_state.h
new file mode 100644
index 000000000..399262aed
--- /dev/null
+++ b/YACReaderLibrary/content_view_state.h
@@ -0,0 +1,26 @@
+#ifndef CONTENT_VIEW_STATE_H
+#define CONTENT_VIEW_STATE_H
+
+#include
+
+struct ContentItemRef {
+ enum Kind {
+ None,
+ Comic,
+ Folder,
+ Header
+ };
+
+ Kind kind = None;
+ qulonglong id = 0;
+};
+
+struct ContentViewState {
+ ContentItemRef topItem;
+ int fallbackComicRow = -1;
+ qreal offset = 0;
+ qreal itemExtent = 0;
+ ContentItemRef currentItem;
+};
+
+#endif // CONTENT_VIEW_STATE_H
diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp
index 0368175f1..524b96999 100644
--- a/YACReaderLibrary/db/comic_model.cpp
+++ b/YACReaderLibrary/db/comic_model.cpp
@@ -61,14 +61,18 @@ bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, i
// TODO: optimize this method (seriously)
bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
-
- QAbstractItemModel::dropMimeData(data, action, row, column, parent);
QLOG_TRACE() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<" << parent << row << "," << column;
- if (!data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat))
+ if (!canDropMimeData(data, action, row, column, parent))
return false;
const QList comicIds = YACReader::mimeDataToComicsIds(data);
+ if (comicIds.isEmpty())
+ return false;
+
+ if (row < 0 || row > _data.count())
+ row = _data.count();
+
QList currentIndexes;
int i;
{
@@ -85,6 +89,9 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
}
}
+ if (currentIndexes.size() != comicIds.size())
+ return false;
+
std::sort(currentIndexes.begin(), currentIndexes.end());
QList resortedData;
@@ -132,26 +139,24 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
int tempRow = row;
- if (tempRow < 0)
- tempRow = _data.count();
-
for (const auto id : comicIds) {
int i = 0;
const auto dataSnapshot = _data;
for (auto *item : dataSnapshot) {
if (item->data(Id) == id) {
- beginMoveRows(parent, i, i, parent, tempRow);
-
- bool skipElement = i == tempRow || i + 1 == tempRow;
+ const bool skipElement = i == tempRow || i + 1 == tempRow;
if (!skipElement) {
+ if (!beginMoveRows(parent, i, i, parent, tempRow))
+ return false;
+
if (i > tempRow)
_data.move(i, tempRow);
else
_data.move(i, tempRow - 1);
- }
- endMoveRows();
+ endMoveRows();
+ }
if (i > tempRow)
tempRow++;
@@ -327,9 +332,13 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
return item->data(FileName);
else if (role == RatingRole)
return item->data(Rating);
- else if (role == CoverPathRole)
- return getCoverUrlPathForComicHash(item->data(Hash).toString());
- else if (role == NumPagesRole)
+ else if (role == CoverPathRole) {
+ auto coverUrl = getCoverUrlPathForComicHash(item->data(Hash).toString());
+ const auto revision = coverRevisions.value(item->data(Id).toULongLong());
+ if (revision > 0)
+ coverUrl.setQuery(QStringLiteral("revision=%1").arg(revision));
+ return coverUrl;
+ } else if (role == NumPagesRole)
return item->data(NumPages);
else if (role == CurrentPageRole)
return item->data(CurrentPage);
@@ -1224,20 +1233,16 @@ void ComicModel::resetComicRating(const QModelIndex &mi)
void ComicModel::notifyCoverChange(const ComicDB &comic)
{
auto it = std::find_if(_data.begin(), _data.end(), [comic](ComicItem *item) { return item->data(ComicModel::Id).toULongLong() == comic.id; });
- auto itemIndex = std::distance(_data.begin(), it);
- auto item = _data[itemIndex];
-
- // emiting a dataChage doesn't work in QML for some reason, CoverPathRole is requested but the view doesn't update the image
- // removing and reading again works with the flow views without any additional code, but it's not the best solution
- beginRemoveRows(QModelIndex(), itemIndex, itemIndex);
- _data.removeAt(itemIndex);
- endRemoveRows();
-
- beginInsertRows(QModelIndex(), itemIndex, itemIndex);
- _data.insert(itemIndex, item);
- endInsertRows();
+ if (it == _data.end())
+ return;
- // this doesn't work in QML -> emit dataChanged(index(itemIndex, 0), index(itemIndex, 0), QVector() << CoverPathRole);
+ // Keep cover changes non-structural. Removing and reinserting the row makes
+ // views adjust their selection and scroll position before the edit refresh can
+ // capture them. Changing the URL also makes QML reload the image even though
+ // the underlying cover file path is unchanged.
+ ++coverRevisions[comic.id];
+ const auto itemIndex = std::distance(_data.begin(), it);
+ emit dataChanged(index(itemIndex, 0), index(itemIndex, columnCount() - 1), { CoverPathRole });
}
QUrl ComicModel::getCoverUrlPathForComicHash(const QString &hash) const
@@ -1262,6 +1267,12 @@ void ComicModel::addComicsToFavorites(const QList &comicsList)
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
+
+ QList comicIds;
+ comicIds.reserve(comics.size());
+ for (const auto &comic : comics)
+ comicIds.append(comic.id);
+ emit favoritesChanged(comicIds);
}
void ComicModel::addComicsToLabel(const QList &comicIds, qulonglong labelId)
@@ -1312,6 +1323,12 @@ void ComicModel::deleteComicsFromFavorites(const QList &comicsList)
}
QSqlDatabase::removeDatabase(connectionName);
+ QList comicIds;
+ comicIds.reserve(comics.size());
+ for (const auto &comic : comics)
+ comicIds.append(comic.id);
+ emit favoritesChanged(comicIds);
+
if (mode == Favorites)
deleteComicsFromModel(comicsList);
}
diff --git a/YACReaderLibrary/db/comic_model.h b/YACReaderLibrary/db/comic_model.h
index 9426ed57b..c996bd93d 100644
--- a/YACReaderLibrary/db/comic_model.h
+++ b/YACReaderLibrary/db/comic_model.h
@@ -4,6 +4,7 @@
#include "yacreader_global.h"
#include
+#include
#include
#include
#include
@@ -173,6 +174,7 @@ public slots:
protected:
private:
+ QHash coverRevisions;
QList createModelData(QSqlQuery &sqlquery) const;
QList createModelDataForList(QSqlQuery &sqlquery) const;
@@ -201,6 +203,7 @@ public slots:
signals:
void isEmpty();
+ void favoritesChanged(const QList &comicIds);
void searchNumResults(int);
void resortedIndexes(QList);
void newSelectedIndex(const QModelIndex &);
diff --git a/YACReaderLibrary/db/folder_model.cpp b/YACReaderLibrary/db/folder_model.cpp
index 3048f60fd..c5712a029 100644
--- a/YACReaderLibrary/db/folder_model.cpp
+++ b/YACReaderLibrary/db/folder_model.cpp
@@ -51,8 +51,6 @@ QIcon drawFinishedFolderIcon(const QPixmap &overlay)
return finishedIcon;
}
-#define ROOT 1
-
struct FolderColumns {
int name;
int path;
@@ -123,14 +121,14 @@ FolderItem *createRoot(QSqlDatabase &db)
data[0] = "root";
auto root = new FolderItem(data);
- root->id = ROOT;
+ root->id = FolderModel::RootFolderId;
root->parentItem = nullptr;
return root;
}
FolderModel::FolderModel(QObject *parent)
- : QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr), showRecent(false), recentDays(1)
+ : QAbstractItemModel(parent), rootItem(nullptr), showRecent(false), recentDays(1)
{
initTheme(this);
}
@@ -190,49 +188,18 @@ void FolderModel::reload()
if (rootItem == nullptr)
return;
- if (!isSubfolder) {
- auto newModelData = createModelData(_databasePath);
+ auto newModelData = createModelData(_databasePath);
- takeUpdatedChildrenInfo(rootItem, QModelIndex(), newModelData.rootItem);
+ takeUpdatedChildrenInfo(rootItem, QModelIndex(), newModelData.rootItem);
- // copy items from newModelData to this model that are not in this model
- for (const auto key : newModelData.items.keys()) {
- if (!items.contains(key)) {
- items[key] = (newModelData.items[key]);
- }
+ // copy items from newModelData to this model that are not in this model
+ for (const auto key : newModelData.items.keys()) {
+ if (!items.contains(key)) {
+ items[key] = (newModelData.items[key]);
}
-
- delete newModelData.rootItem;
- } else {
- QString connectionName = "";
- {
- QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
-
- QSqlQuery selectQuery(db);
- selectQuery.prepare("SELECT * FROM folder WHERE parentId = :parentId and id <> 1");
- selectQuery.bindValue(":parentId", rootItem->id);
- selectQuery.exec();
-
- auto tempRoot = new FolderItem(rootItem->getData(), rootItem->parentItem);
- tempRoot->id = rootItem->id;
- auto newModelData = createModelData(selectQuery, tempRoot);
- takeUpdatedChildrenInfo(rootItem, QModelIndex(), newModelData.rootItem);
-
- items = newModelData.items;
-
- // copy items from newModelData to this model that are not in this model
- for (const auto key : newModelData.items.keys()) {
- if (!items.contains(key)) {
- items[key] = (newModelData.items[key]);
- }
- }
-
- delete newModelData.rootItem;
-
- connectionName = db.connectionName();
- }
- QSqlDatabase::removeDatabase(connectionName);
}
+
+ delete newModelData.rootItem;
}
void FolderModel::takeUpdatedChildrenInfo(FolderItem *parent, const QModelIndex &parentModelIndex, FolderItem *updated)
@@ -327,7 +294,7 @@ void FolderModel::takeUpdatedChildrenInfo(FolderItem *parent, const QModelIndex
}
}
-Folder FolderModel::folderFromItem(FolderItem *folderItem)
+Folder FolderModel::folderFromItem(FolderItem *folderItem) const
{
auto name = folderItem->data(FolderModel::Name).toString();
auto parentItem = folderItem->parent();
@@ -601,6 +568,9 @@ QString FolderModel::getFolderPath(const QModelIndex &folder)
void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool status)
{
+ if (list.isEmpty())
+ return;
+
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
@@ -609,22 +579,24 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
auto item = static_cast(mi.internalPointer());
item->setData(FolderModel::Completed, status);
- if (!isSubfolder) {
- Folder f = DBHelper::loadFolder(item->id, db);
- f.completed = status;
- DBHelper::update(f, db);
- }
+ Folder f = DBHelper::loadFolder(item->id, db);
+ f.completed = status;
+ DBHelper::update(f, db);
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
- emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
+ const auto parent = list.first().parent();
+ emit dataChanged(index(list.first().row(), FolderModel::Name, parent), index(list.last().row(), FolderModel::Updated, parent));
}
void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
{
+ if (list.isEmpty())
+ return;
+
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
@@ -633,22 +605,24 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
auto item = static_cast(mi.internalPointer());
item->setData(FolderModel::Finished, status);
- if (!isSubfolder) {
- Folder f = DBHelper::loadFolder(item->id, db);
- f.finished = status;
- DBHelper::update(f, db);
- }
+ Folder f = DBHelper::loadFolder(item->id, db);
+ f.finished = status;
+ DBHelper::update(f, db);
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
- emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
+ const auto parent = list.first().parent();
+ emit dataChanged(index(list.first().row(), FolderModel::Name, parent), index(list.last().row(), FolderModel::Updated, parent));
}
void FolderModel::updateFolderType(const QModelIndexList &list, YACReader::FileType type)
{
+ if (list.isEmpty())
+ return;
+
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
@@ -667,16 +641,15 @@ void FolderModel::updateFolderType(const QModelIndexList &list, YACReader::FileT
setType(item, type);
- if (!isSubfolder) {
- DBHelper::updateFolderTreeType(item->id, db, type);
- }
+ DBHelper::updateFolderTreeType(item->id, db, type);
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
- emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
+ const auto parent = list.first().parent();
+ emit dataChanged(index(list.first().row(), FolderModel::Name, parent), index(list.last().row(), FolderModel::Updated, parent));
}
void FolderModel::updateTreeType(YACReader::FileType type)
@@ -699,9 +672,7 @@ void FolderModel::updateTreeType(YACReader::FileType type)
setType(item, type);
- if (!isSubfolder) {
- DBHelper::updateDBType(db, type);
- }
+ DBHelper::updateDBType(db, type);
db.commit();
connectionName = db.connectionName();
}
@@ -776,50 +747,7 @@ QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
return result;
}
-FolderModel *FolderModel::getSubfoldersModel(const QModelIndex &mi)
-{
- qulonglong id = 1;
- FolderItem *parent = nullptr;
- if (mi.isValid()) {
- auto item = static_cast(mi.internalPointer());
- parent = new FolderItem(item->getData(), item->parent());
- id = parent->id = item->id;
- }
-
- if (id == 1) {
- if (parent != nullptr) {
- delete parent;
- }
- return this;
- }
-
- auto model = new FolderModel();
-
- QString connectionName = "";
- {
- QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
-
- QSqlQuery selectQuery(db); // TODO check
- selectQuery.prepare("SELECT * FROM folder WHERE parentId = :parentId and id <> 1");
- selectQuery.bindValue(":parentId", id);
- selectQuery.exec();
-
- if (parent != nullptr) {
- model->setModelData(createModelData(selectQuery, parent));
- }
-
- connectionName = db.connectionName();
- }
- QSqlDatabase::removeDatabase(connectionName);
-
- model->_databasePath = _databasePath;
-
- model->isSubfolder = true;
-
- return model;
-}
-
-Folder FolderModel::getRootFolder()
+Folder FolderModel::getRootFolder() const
{
if (this->rootItem == nullptr) {
return Folder();
@@ -828,7 +756,7 @@ Folder FolderModel::getRootFolder()
return folderFromItem(this->rootItem);
}
-Folder FolderModel::getFolder(const QModelIndex &mi)
+Folder FolderModel::getFolder(const QModelIndex &mi) const
{
if (!mi.isValid()) {
return Folder();
@@ -946,7 +874,7 @@ void FolderModel::setShowRecent(bool showRecent)
this->showRecent = showRecent;
- emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { FolderModel::ShowRecentRole });
+ emitDataChangedRecursively({ }, FolderModel::ShowRecentRole);
}
void FolderModel::setRecentRange(int days)
@@ -956,7 +884,18 @@ void FolderModel::setRecentRange(int days)
this->recentDays = days;
- emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { FolderModel::RecentRangeRole });
+ emitDataChangedRecursively({ }, FolderModel::RecentRangeRole);
+}
+
+void FolderModel::emitDataChangedRecursively(const QModelIndex &parent, int role)
+{
+ const auto rows = rowCount(parent);
+ if (rows == 0)
+ return;
+
+ emit dataChanged(index(0, 0, parent), index(rows - 1, 0, parent), { role });
+ for (int row = 0; row < rows; ++row)
+ emitDataChangedRecursively(index(row, 0, parent), role);
}
void FolderModel::deleteFolder(const QModelIndex &mi)
diff --git a/YACReaderLibrary/db/folder_model.h b/YACReaderLibrary/db/folder_model.h
index f1cf381ba..4b64669b0 100644
--- a/YACReaderLibrary/db/folder_model.h
+++ b/YACReaderLibrary/db/folder_model.h
@@ -44,6 +44,8 @@ class FolderModel : public QAbstractItemModel, protected Themable
friend class YACReader::FolderQueryResultProcessor;
public:
+ static constexpr qulonglong RootFolderId = 1;
+
explicit FolderModel(QObject *parent = nullptr);
~FolderModel() override;
@@ -75,10 +77,9 @@ class FolderModel : public QAbstractItemModel, protected Themable
void resetFolderCover(const QModelIndex &index);
QStringList getSubfoldersNames(const QModelIndex &mi);
- FolderModel *getSubfoldersModel(const QModelIndex &mi); // it creates a model that contains just the direct subfolders
- Folder getRootFolder();
- Folder getFolder(const QModelIndex &mi);
+ Folder getRootFolder() const;
+ Folder getFolder(const QModelIndex &mi) const;
QModelIndex getIndexFromFolderId(qulonglong folderId, const QModelIndex &parent = QModelIndex());
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
@@ -117,12 +118,13 @@ class FolderModel : public QAbstractItemModel, protected Themable
RecentRangeRole,
};
- bool isSubfolder;
public slots:
void deleteFolder(const QModelIndex &mi);
void updateFolderChildrenInfo(qulonglong folderId);
private:
+ void emitDataChangedRecursively(const QModelIndex &parent, int role);
+
struct ModelData {
FolderItem *rootItem; // items tree
QMap items; // items lookup
@@ -135,7 +137,7 @@ public slots:
// parent contains the current data in the model (parentModelIndex is its index), updated contains fresh info loaded from the DB,
void takeUpdatedChildrenInfo(FolderItem *parent, const QModelIndex &parentModelIndex, FolderItem *updated);
- Folder folderFromItem(FolderItem *item);
+ Folder folderFromItem(FolderItem *item) const;
FolderItem *rootItem; // items tree
QMap items; // items lookup
diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp
index 469c05f2e..82f00f025 100644
--- a/YACReaderLibrary/db_helper.cpp
+++ b/YACReaderLibrary/db_helper.cpp
@@ -2182,15 +2182,14 @@ bool DBHelper::isFavoriteComic(qulonglong id, QSqlDatabase &db)
return false;
}
-QString DBHelper::getLibraryInfo(QUuid id)
+QVariantMap DBHelper::getLibraryInfoData(QUuid id)
{
- QString info;
- QString libraryPath = DBHelper::getLibraries().getPath(id);
-
- info = "Library path: " + libraryPath + "
";
+ const QString libraryPath = DBHelper::getLibraries().getPath(id);
+ QVariantMap info {
+ { QStringLiteral("path"), libraryPath },
+ };
QString connectionName = "";
- QList list;
{
QSqlDatabase db = DataBaseManagement::loadDatabase(LibraryPaths::libraryDataPath(libraryPath));
connectionName = db.connectionName();
@@ -2198,22 +2197,29 @@ QString DBHelper::getLibraryInfo(QUuid id)
// num folders
auto foldersQuery = db.exec("SELECT COUNT(*) FROM folder WHERE id <> 1");
foldersQuery.next();
-
- info += "Number of folders: " + foldersQuery.value(0).toString() + "
";
+ info.insert(QStringLiteral("folderCount"), foldersQuery.value(0));
// num comics
auto comicsQuery = db.exec("SELECT COUNT(*) FROM comic");
comicsQuery.next();
-
- info += "Number of comics: " + comicsQuery.value(0).toString() + "
";
+ info.insert(QStringLiteral("comicCount"), comicsQuery.value(0));
// num read comics
auto readComicsQuery = db.exec("SELECT count(*) FROM comic c INNER JOIN comic_info ci ON c.comicInfoId = ci.id WHERE ci.read = 1");
readComicsQuery.next();
-
- info += "Number of read comics: " + readComicsQuery.value(0).toString() + "
";
+ info += "Number of folders: " + libraryInfo.value(QStringLiteral("folderCount")).toString() + "
";
+ info += "Number of comics: " + libraryInfo.value(QStringLiteral("comicCount")).toString() + "
";
+ info += "Number of read comics: " + libraryInfo.value(QStringLiteral("readComicCount")).toString() + "
";
+ return info;
+}
diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h
index c67b38921..94f546bc0 100644
--- a/YACReaderLibrary/db_helper.h
+++ b/YACReaderLibrary/db_helper.h
@@ -6,6 +6,7 @@ class QString;
#include
#include
+#include
class ComicDB;
class Folder;
@@ -108,6 +109,7 @@ class DBHelper
static bool isFavoriteComic(qulonglong id, QSqlDatabase &db);
// library
+ static QVariantMap getLibraryInfoData(QUuid id);
static QString getLibraryInfo(QUuid id);
};
diff --git a/YACReaderLibrary/empty_special_list.cpp b/YACReaderLibrary/empty_special_list.cpp
index 8f0b9d1a6..891457aa7 100644
--- a/YACReaderLibrary/empty_special_list.cpp
+++ b/YACReaderLibrary/empty_special_list.cpp
@@ -23,7 +23,7 @@ void EmptySpecialListWidget::showReading()
void EmptySpecialListWidget::showRecent()
{
currentType = Recent;
- setPixmap(QPixmap());
+ setPixmap(theme.emptyContainer.emptyRecentIcon);
setText(tr("There are no recent comics!"));
}
@@ -43,6 +43,8 @@ void EmptySpecialListWidget::updateIcon()
setPixmap(theme.emptyContainer.emptyCurrentReadingsIcon);
break;
case Recent:
+ setPixmap(theme.emptyContainer.emptyRecentIcon);
+ break;
case None:
break;
}
diff --git a/YACReaderLibrary/folder_content_view.cpp b/YACReaderLibrary/folder_content_view.cpp
deleted file mode 100644
index 7f8faaa58..000000000
--- a/YACReaderLibrary/folder_content_view.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-#include "folder_content_view.h"
-
-#include "QsLog.h"
-#include "comic.h"
-#include "comic_files_manager.h"
-#include "folder_model.h"
-#include "grid_comics_view.h"
-#include "yacreader_global_gui.h"
-#include "yacreader_tool_bar_stretch.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace YACReader;
-
-FolderContentView::FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent)
- : QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel()), smallZoomLabel(nullptr), bigZoomLabel(nullptr)
-{
- qmlRegisterType("com.yacreader.FolderModel", 1, 0, "FolderModel");
-
- settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat, this);
- settings->beginGroup("libraryConfig");
-
- view = new QQuickWidget();
-
- view->setResizeMode(QQuickWidget::SizeRootObjectToView);
- connect(
- view, &QQuickWidget::statusChanged, this,
- [=](QQuickWidget::Status status) {
- if (status == QQuickWidget::Error) {
- QLOG_ERROR() << view->errors();
- }
- });
-
- coverSizeSliderWidget = new QWidget(this);
- coverSizeSliderWidget->setFixedWidth(200);
- coverSizeSlider = new QSlider(coverSizeSliderWidget);
- coverSizeSlider->setOrientation(Qt::Horizontal);
- coverSizeSlider->setRange(YACREADER_MIN_GRID_ZOOM_WIDTH, YACREADER_MAX_GRID_ZOOM_WIDTH);
-
- const auto &comicsToolbar = theme.comicsViewToolbar;
-
- auto horizontalLayout = new QHBoxLayout();
- smallZoomLabel = new QLabel();
- smallZoomLabel->setPixmap(comicsToolbar.smallGridZoomIcon.pixmap(18, 18));
- horizontalLayout->addWidget(smallZoomLabel);
- horizontalLayout->addWidget(coverSizeSlider, 0, Qt::AlignVCenter);
- bigZoomLabel = new QLabel();
- bigZoomLabel->setPixmap(comicsToolbar.bigGridZoomIcon.pixmap(18, 18));
- horizontalLayout->addWidget(bigZoomLabel);
- horizontalLayout->addSpacing(10);
- horizontalLayout->setContentsMargins(0, 0, 0, 0);
-
- coverSizeSliderWidget->setLayout(horizontalLayout);
-
- connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize);
-
- toolbar = new QToolBar();
- toolbar->setIconSize(QSize(18, 18));
- toolbar->addWidget(new YACReaderToolBarStretch);
- toolbar->addAction(toogleRecentVisibilityAction);
- toolbar->addSeparator();
- toolbar->addWidget(coverSizeSliderWidget);
-
- auto l = new QVBoxLayout;
- setContentsMargins(0, 0, 0, 0);
- l->setContentsMargins(0, 0, 0, 0);
- l->setSpacing(0);
- l->addWidget(view);
- l->addWidget(toolbar);
- this->setLayout(l);
-
- QQmlContext *ctxt = view->rootContext();
-
- // fonts settings (not theme-dependent)
- int fontSize = QApplication::font().pointSize();
- if (fontSize == -1)
- fontSize = QApplication::font().pixelSize();
- ctxt->setContextProperty("fontSize", fontSize);
- ctxt->setContextProperty("fontFamily", QApplication::font().family());
- ctxt->setContextProperty("fontSpacing", 0.5);
-
- // Apply theme colors
- initTheme(this);
-
- updateCoversSizeInContext(YACREADER_MIN_COVER_WIDTH, ctxt);
-
- ctxt->setContextProperty("comicsList", comicModel.get());
- ctxt->setContextProperty("foldersList", folderModel);
-
- auto showContinueReading = settings->value(DISPLAY_GLOBAL_CONTINUE_READING_IN_GRID_VIEW, true).toBool();
- ctxt->setContextProperty("showContinueReading", QVariant(showContinueReading));
-
- ctxt->setContextProperty("openHelper", this);
- ctxt->setContextProperty("dropManager", this);
- ctxt->setContextProperty("contextMenuHelper", this);
-
- view->setSource(QUrl("qrc:/qml/FolderContentView.qml"));
-}
-
-void FolderContentView::setModel(const QModelIndex &parent, FolderModel *model)
-{
- this->parent = parent;
- QQmlContext *ctxt = view->rootContext();
-
- ctxt->setContextProperty("foldersList", model);
-
- // when the root folder is set, FolderModel just returns itself in `getSubfoldersModel`, I need to measure the performance of create a deep copy...
- if (folderModel->isSubfolder) {
- delete folderModel;
- }
- folderModel = model;
-
- auto *root = view->rootObject();
- auto grid = root ? root->findChild(QStringLiteral("grid")) : nullptr;
-
- if (grid != nullptr) {
- grid->setProperty("currentIndex", 0);
- }
-}
-
-void FolderContentView::setContinueReadingModel(ComicModel *model)
-{
- QQmlContext *ctxt = view->rootContext();
-
- ctxt->setContextProperty("comicsList", model);
- this->comicModel.reset(model);
-
- auto *root = view->rootObject();
- auto list = root ? root->findChild(QStringLiteral("list")) : nullptr;
-
- if (list != nullptr) {
- list->setProperty("currentIndex", 0);
- }
-}
-
-void FolderContentView::reloadContent()
-{
- folderModel->reload();
- reloadContinueReadingModel();
-}
-
-void FolderContentView::reloadContinueReadingModel()
-{
- if (!folderModel->isSubfolder) {
- comicModel->reloadContinueReading();
- }
-}
-
-void FolderContentView::setShowRecent(bool visible)
-{
- folderModel->setShowRecent(visible);
-}
-
-void FolderContentView::setRecentRange(int days)
-{
- folderModel->setRecentRange(days);
-}
-
-void FolderContentView::updateSettings()
-{
- QQmlContext *ctxt = view->rootContext();
-
- auto showContinueReading = settings->value(DISPLAY_GLOBAL_CONTINUE_READING_IN_GRID_VIEW, true).toBool();
- ctxt->setContextProperty("showContinueReading", QVariant(showContinueReading));
-}
-
-void FolderContentView::openFolder(int index)
-{
- emit subfolderSelected(this->parent, index);
-}
-
-void FolderContentView::openComicFromContinueReadingList(int index)
-{
- auto comic = comicModel->getComic(comicModel->index(index, 0));
- emit openComic(comic, ComicModel::Folder);
-}
-
-void FolderContentView::requestedFolderContextMenu(QPoint point, int index)
-{
- auto folder = folderModel->getFolder(folderModel->index(index, 0));
- emit openFolderContextMenu(point, folder);
-}
-
-void FolderContentView::requestedContinueReadingComicContextMenu(QPoint point, int index)
-{
- auto comic = comicModel->getComic(comicModel->index(index, 0));
- emit openContinueReadingComicContextMenu(point, comic);
-}
-
-void FolderContentView::updateCoversSizeInContext(int width, QQmlContext *ctxt)
-{
- int cellBottomMarging = 8 * (1 + 2 * (1 - (float(YACREADER_MAX_GRID_ZOOM_WIDTH - width) / (YACREADER_MAX_GRID_ZOOM_WIDTH - YACREADER_MIN_GRID_ZOOM_WIDTH))));
-
- ctxt->setContextProperty("cellCustomHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51 + cellBottomMarging);
- ctxt->setContextProperty("cellCustomWidth", (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_COVER_WIDTH);
-
- ctxt->setContextProperty("itemWidth", width);
- ctxt->setContextProperty("itemHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51);
-
- ctxt->setContextProperty("coverWidth", width);
- ctxt->setContextProperty("coverHeight", (width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH);
-}
-
-void FolderContentView::setCoversSize(int width)
-{
- QQmlContext *ctxt = view->rootContext();
-
- auto *root = view->rootObject();
- auto grid = root ? root->findChild(QStringLiteral("grid")) : nullptr;
-
- if (grid != 0) {
- QVariant cellCustomWidth = (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_GRID_ZOOM_WIDTH;
- QMetaObject::invokeMethod(grid, "calculateCellWidths",
- Q_ARG(QVariant, cellCustomWidth));
- }
-
- updateCoversSizeInContext(width, ctxt);
-
- settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
-}
-
-void FolderContentView::showEvent(QShowEvent *event)
-{
- QWidget::showEvent(event);
-
- int coverSize = settings->value(COMICS_GRID_COVER_SIZES, YACREADER_MIN_COVER_WIDTH).toInt();
-
- coverSizeSlider->setValue(coverSize);
- setCoversSize(coverSize);
-}
-
-bool FolderContentView::canDropUrls(const QList &urls, Qt::DropAction action)
-{
- if (action == Qt::CopyAction) {
- QString currentPath;
- for (const auto &url : urls) {
- // comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping)
- currentPath = url.toLocalFile();
- if (Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir())
- return true;
- }
- }
- return false;
-}
-
-bool FolderContentView::canDropFormats(const QString &formats)
-{
- return true;
-}
-
-void FolderContentView::droppedFiles(const QList &urls, Qt::DropAction action)
-{
- bool validAction = action == Qt::CopyAction; // TODO add move
-
- if (validAction) {
- QList> droppedFiles = ComicFilesManager::getDroppedFiles(urls);
- emit copyComicsToCurrentFolder(droppedFiles);
- }
-}
-
-void FolderContentView::applyTheme(const Theme &theme)
-{
- QQmlContext *ctxt = view->rootContext();
- const auto &giv = theme.gridAndInfoView;
-
- toolbar->setStyleSheet(theme.comicsViewToolbar.toolbarQSS);
-
- // Continue reading section colors
- ctxt->setContextProperty("continueReadingBackgroundColor", giv.continueReadingBackgroundColor);
- ctxt->setContextProperty("continueReadingTextColor", giv.continueReadingTextColor);
-
- // Grid colors
- ctxt->setContextProperty("backgroundColor", giv.backgroundColor);
- ctxt->setContextProperty("cellColor", giv.cellColor);
- ctxt->setContextProperty("cellSelectedColor", giv.cellSelectedColor);
- ctxt->setContextProperty("cellSelectedBorderColor", giv.cellSelectedBorderColor);
- ctxt->setContextProperty("borderColor", giv.borderColor);
- ctxt->setContextProperty("itemTitleColor", giv.itemTitleColor);
- ctxt->setContextProperty("itemDetailsColor", giv.itemDetailsColor);
- ctxt->setContextProperty("dropShadow", QVariant(giv.showDropShadow));
-
- // Info panel colors
- ctxt->setContextProperty("infoBackgroundColor", giv.infoBackgroundColor);
- ctxt->setContextProperty("infoMetadataTextColor", giv.infoMetadataTextColor);
- ctxt->setContextProperty("infoTextColor", giv.infoTextColor);
-
- // Rating and favorite colors
- ctxt->setContextProperty("ratingUnselectedColor", giv.ratingUnselectedColor);
- ctxt->setContextProperty("ratingSelectedColor", giv.ratingSelectedColor);
- ctxt->setContextProperty("favUncheckedColor", giv.favUncheckedColor);
- ctxt->setContextProperty("favCheckedColor", giv.favCheckedColor);
- ctxt->setContextProperty("readTickUncheckedColor", giv.readTickUncheckedColor);
- ctxt->setContextProperty("readTickCheckedColor", giv.readTickCheckedColor);
-
- // New item indicator, cover borders, placeholder pages, scrollbar
- ctxt->setContextProperty("newItemColor", giv.newItemColor);
- ctxt->setContextProperty("scrollbarColor", giv.scrollbarColor);
- ctxt->setContextProperty("scrollbarBorderColor", giv.scrollbarBorderColor);
- ctxt->setContextProperty("comicCoverBorderColor", giv.comicCoverBorderColor);
- ctxt->setContextProperty("folderCoverBorderColor", giv.folderCoverBorderColor);
- ctxt->setContextProperty("placeholderFolder1Color", giv.placeholderFolder1Color);
- ctxt->setContextProperty("placeholderFolder1BorderColor", giv.placeholderFolder1BorderColor);
- ctxt->setContextProperty("placeholderFolder2Color", giv.placeholderFolder2Color);
- ctxt->setContextProperty("placeholderFolder2BorderColor", giv.placeholderFolder2BorderColor);
-
- // Update zoom slider icons
- if (smallZoomLabel) {
- smallZoomLabel->setPixmap(theme.comicsViewToolbar.smallGridZoomIcon.pixmap(18, 18));
- }
- if (bigZoomLabel) {
- bigZoomLabel->setPixmap(theme.comicsViewToolbar.bigGridZoomIcon.pixmap(18, 18));
- }
-}
diff --git a/YACReaderLibrary/folder_content_view.h b/YACReaderLibrary/folder_content_view.h
deleted file mode 100644
index 22d124779..000000000
--- a/YACReaderLibrary/folder_content_view.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef FOLDERCONTENTVIEW_H
-#define FOLDERCONTENTVIEW_H
-
-#include "comic_db.h"
-#include "comic_model.h"
-#include "folder.h"
-#include "themable.h"
-
-#include
-#include
-#include
-#include
-
-class FolderModel;
-class ComicModel;
-class YACReaderToolBarStretch;
-
-class QQuickWidget;
-class QQmlContext;
-
-class FolderContentView : public QWidget, protected Themable
-{
- Q_OBJECT
-public:
- explicit FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent = nullptr);
- void setModel(const QModelIndex &parent, FolderModel *model);
- void setContinueReadingModel(ComicModel *model);
- void reloadContent();
- void reloadContinueReadingModel();
- void setShowRecent(bool visible);
- void setRecentRange(int days);
-
- FolderModel *currentFolderModel() { return folderModel; }
-
-public slots:
- void updateSettings();
-
-signals:
- void subfolderSelected(QModelIndex, int);
- void openComic(const ComicDB &comic, const ComicModel::Mode mode);
-
- // Drops
- void copyComicsToCurrentFolder(QList>);
- void moveComicsToCurrentFolder(QList>);
-
- void openFolderContextMenu(QPoint point, Folder folder);
- void openContinueReadingComicContextMenu(QPoint point, ComicDB comic);
-
-protected slots:
- // void onItemClicked(const QModelIndex &mi);
- void updateCoversSizeInContext(int width, QQmlContext *ctxt);
- void setCoversSize(int width);
- virtual void showEvent(QShowEvent *event) override;
- void openFolder(int index);
- void openComicFromContinueReadingList(int index);
- void requestedFolderContextMenu(QPoint point, int index);
- void requestedContinueReadingComicContextMenu(QPoint point, int index);
- bool canDropUrls(const QList &urls, Qt::DropAction action);
- bool canDropFormats(const QString &formats);
- void droppedFiles(const QList &urls, Qt::DropAction action);
-
-protected:
- QQuickWidget *view;
- QModelIndex parent;
-
- std::unique_ptr comicModel;
- FolderModel *folderModel;
-
- void applyTheme(const Theme &theme) override;
-
-private:
- QSettings *settings;
- QToolBar *toolbar;
- YACReaderToolBarStretch *toolBarStretch;
- QAction *toolBarStretchAction;
- QWidget *coverSizeSliderWidget;
- QSlider *coverSizeSlider;
- QAction *coverSizeSliderAction;
- QAction *showInfoAction;
- QAction *showInfoSeparatorAction;
-
- // Zoom slider labels (for theming)
- QLabel *smallZoomLabel;
- QLabel *bigZoomLabel;
-};
-
-#endif // FOLDERCONTENTVIEW_H
diff --git a/YACReaderLibrary/grid_comics_view.cpp b/YACReaderLibrary/grid_comics_view.cpp
index 970b66d63..671229f0b 100644
--- a/YACReaderLibrary/grid_comics_view.cpp
+++ b/YACReaderLibrary/grid_comics_view.cpp
@@ -5,30 +5,54 @@
#include "comic_db.h"
#include "comic_files_manager.h"
#include "current_comic_view_helper.h"
+#include "folder_model.h"
+#include "grid_content_model.h"
+#include "reading_list_model.h"
#include "yacreader_comic_info_helper.h"
#include "yacreader_comics_selection_helper.h"
#include "yacreader_global_gui.h"
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
+#include
+
+namespace {
+QString pixmapDataUrl(const QPixmap &pixmap)
+{
+ if (pixmap.isNull())
+ return { };
+
+ QByteArray data;
+ QBuffer buffer(&data);
+ buffer.open(QIODevice::WriteOnly);
+ pixmap.save(&buffer, "PNG");
+ return QStringLiteral("data:image/png;base64,") + QString::fromLatin1(data.toBase64());
+}
+} // namespace
GridComicsView::GridComicsView(QWidget *parent)
- : ComicsView(parent), filterEnabled(false), smallZoomLabel(nullptr), bigZoomLabel(nullptr)
+ : ComicsView(parent), toolbar(nullptr), coverSizeSliderWidget(nullptr), coverSizeSlider(nullptr), coverSizeSliderAction(nullptr), showInfoSeparatorAction(nullptr), startSeparatorAction(nullptr), filterEnabled(false), contentModel(new GridContentModel(this)), viewStateTimer(new QTimer(this)), smallZoomLabel(nullptr), bigZoomLabel(nullptr)
{
+ qmlRegisterUncreatableType("com.yacreader.GridContentModel", 1, 0, "GridContentModel", QStringLiteral("GridContentModel is provided by GridComicsView"));
+
settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat, this);
settings->beginGroup("libraryConfig");
// view->setFocusPolicy(Qt::TabFocus);
selectionHelper = new YACReaderComicsSelectionHelper(this);
- connect(selectionHelper, &YACReaderComicsSelectionHelper::selectionChanged, this, &GridComicsView::dummyUpdater);
+ connect(selectionHelper, &YACReaderComicsSelectionHelper::selectionChanged, this, [this]() {
+ emit comicSelectionStateChanged(selectionHelper->numItemsSelected() > 0);
+ });
comicInfoHelper = new YACReaderComicInfoHelper(this);
@@ -49,30 +73,45 @@ GridComicsView::GridComicsView(QWidget *parent)
auto model = new ComicModel();
selectionHelper->setModel(model);
- ctxt->setContextProperty("comicsList", model);
+ contentModel->setComicModel(model);
+ connect(contentModel, &QAbstractItemModel::modelReset, this, [this]() {
+ if (focusedFolderIndex.isValid())
+ setFocusedFolder(focusedFolderIndex.row());
+ else
+ clearFocusedFolder();
+ });
+ connect(contentModel, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
+ const auto focusedRow = focusedFolderRow();
+ if (focusedRow >= topLeft.row() && focusedRow <= bottomRight.row())
+ setFocusedFolder(focusedRow);
+ });
+ ctxt->setContextProperty("comicsList", contentModel);
ctxt->setContextProperty("comicsSelection", selectionHelper->selectionModel());
ctxt->setContextProperty("contextMenuHelper", this);
ctxt->setContextProperty("comicsSelectionHelper", selectionHelper);
ctxt->setContextProperty("currentIndexHelper", this);
ctxt->setContextProperty("comicRatingHelper", this);
- ctxt->setContextProperty("dummyValue", true);
ctxt->setContextProperty("dragManager", this);
ctxt->setContextProperty("dropManager", this);
ctxt->setContextProperty("comicOpener", this);
+ rootContinueReadingModelStorage = std::make_unique();
+ globalContinueReadingEnabled = settings->value(DISPLAY_GLOBAL_CONTINUE_READING_IN_GRID_VIEW, true).toBool();
+ contentModel->setMixFoldersAndComics(settings->value(COMICS_GRID_MIX_FOLDERS_AND_COMICS, true).toBool());
+ contentModel->setStartComicsOnNewRow(settings->value(COMICS_GRID_START_COMICS_ON_NEW_ROW, false).toBool());
+
+ viewStateTimer->setSingleShot(true);
+ connect(viewStateTimer, &QTimer::timeout, this, &GridComicsView::applyPendingViewState);
bool showInfo = settings->value(COMICS_GRID_SHOW_INFO, false).toBool();
ctxt->setContextProperty("showInfo", showInfo);
- auto comicDB = new ComicDB();
- auto comicInfo = &(comicDB->info);
- ctxt->setContextProperty("currentComic", comicDB);
- ctxt->setContextProperty("currentComicInfo", comicInfo);
- ctxt->setContextProperty("showCurrentComic", QVariant(false));
+ ctxt->setContextProperty("currentComic", ¤tComic);
+ ctxt->setContextProperty("currentComicInfo", ¤tComic.info);
showInfoAction = new QAction(tr("Show info"), this);
showInfoAction->setCheckable(true);
showInfoAction->setChecked(showInfo);
- connect(showInfoAction, &QAction::toggled, this, &GridComicsView::showInfo);
+ connect(showInfoAction, &QAction::toggled, this, &GridComicsView::updateInfoPanelVisibility);
updateCoversSizeInContext(YACREADER_MIN_COVER_WIDTH, ctxt);
@@ -140,37 +179,110 @@ void GridComicsView::createCoverSizeSliderWidget()
void GridComicsView::setToolBar(QToolBar *toolBar)
{
static_cast(this->layout())->insertWidget(1, toolBar);
- this->toolbar = toolBar;
+ toolbar = toolBar;
+
+ if (!coverSizeSliderWidget)
+ createCoverSizeSliderWidget();
+
+ if (!startSeparatorAction) {
+ startSeparatorAction = new QAction(this);
+ startSeparatorAction->setSeparator(true);
+ }
+ if (!showInfoSeparatorAction) {
+ showInfoSeparatorAction = new QAction(this);
+ showInfoSeparatorAction->setSeparator(true);
+ }
+ if (!coverSizeSliderAction) {
+ auto *sliderAction = new QWidgetAction(this);
+ sliderAction->setDefaultWidget(coverSizeSliderWidget);
+ coverSizeSliderAction = sliderAction;
+ }
+
+ const auto actions = toolbar->actions();
+ if (!actions.contains(startSeparatorAction))
+ toolbar->addAction(startSeparatorAction);
+ if (!actions.contains(showInfoAction))
+ toolbar->addAction(showInfoAction);
+ if (!actions.contains(showInfoSeparatorAction))
+ toolbar->addAction(showInfoSeparatorAction);
+ if (!actions.contains(coverSizeSliderAction))
+ toolbar->addAction(coverSizeSliderAction);
+}
- createCoverSizeSliderWidget();
+void GridComicsView::releaseToolBar()
+{
+ if (!toolbar)
+ return;
- startSeparatorAction = toolBar->addSeparator();
- toolBar->addAction(showInfoAction);
- showInfoSeparatorAction = toolBar->addSeparator();
- coverSizeSliderAction = toolBar->addWidget(coverSizeSliderWidget);
+ toolbar->removeAction(startSeparatorAction);
+ toolbar->removeAction(showInfoAction);
+ toolbar->removeAction(showInfoSeparatorAction);
+ toolbar->removeAction(coverSizeSliderAction);
+}
+
+void GridComicsView::saveViewConfig()
+{
+ int infoWidth = 0;
+ if (auto *rootObject = view->rootObject()) {
+ auto infoContainer = rootObject->findChild("infoContainer", Qt::FindChildrenRecursively);
+ infoWidth = QQmlProperty(infoContainer, "width").read().toInt();
+ }
+
+ if (coverSizeSlider)
+ settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
+ settings->setValue(COMICS_GRID_SHOW_INFO, showInfoAction->isChecked());
+ settings->setValue(COMICS_GRID_INFO_WIDTH, infoWidth);
}
void GridComicsView::setModel(ComicModel *model)
{
- if (model == NULL)
+ if (model == nullptr)
return;
+ // Keep the previous frame visible while QML resets the model. The pending
+ // origin/anchor is applied before painting is enabled again.
+ view->setUpdatesEnabled(false);
+
+ clearFocusedFolder();
+ disconnect(modelDataChangedConnection);
+ disconnect(modelFavoritesChangedConnection);
ComicsView::setModel(model);
- setCurrentComicIfNeeded();
+ modelDataChangedConnection = connect(model, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
+ if (!showInfoAction->isChecked() || focusedFolderIndex.isValid())
+ return;
+
+ const auto index = currentIndex();
+ if (index.isValid() && index.row() >= topLeft.row() && index.row() <= bottomRight.row())
+ updateInfoForIndex(index.row());
+ });
+
+ modelFavoritesChangedConnection = connect(model, &ComicModel::favoritesChanged, this, [this](const QList &comicIds) {
+ if (!showInfoAction->isChecked() || focusedFolderIndex.isValid())
+ return;
+
+ const auto index = currentIndex();
+ if (index.isValid() && comicIds.contains(index.data(ComicModel::IdRole).toULongLong()))
+ updateInfoForIndex(index.row());
+ });
+
+ updateCurrentComicBanner();
selectionHelper->setModel(model);
comicInfoHelper->setModel(model);
+ contentModel->setComicModel(model);
+
+ if (model->getMode() != ComicModel::Folder)
+ clearFolderModel();
QQmlContext *ctxt = view->rootContext();
- ctxt->setContextProperty("comicsList", model);
+ ctxt->setContextProperty("comicsList", contentModel);
ctxt->setContextProperty("comicsSelection", selectionHelper->selectionModel());
ctxt->setContextProperty("contextMenuHelper", this);
ctxt->setContextProperty("comicsSelectionHelper", selectionHelper);
ctxt->setContextProperty("currentIndexHelper", this);
ctxt->setContextProperty("comicRatingHelper", this);
- ctxt->setContextProperty("dummyValue", true);
ctxt->setContextProperty("dragManager", this);
ctxt->setContextProperty("dropManager", this);
ctxt->setContextProperty("comicInfoHelper", comicInfoHelper);
@@ -178,40 +290,36 @@ void GridComicsView::setModel(ComicModel *model)
auto *root = view->rootObject();
auto grid = root ? root->findChild(QStringLiteral("grid")) : nullptr;
- if (grid != nullptr) {
- grid->setProperty("currentIndex", 0);
- }
+ if (grid != nullptr)
+ grid->setProperty("currentIndex", -1);
updateBackgroundConfig();
selectionHelper->clear();
+ updateInfoForIndex(-1);
- if (model->rowCount() > 0) {
- setCurrentIndex(model->index(0, 0));
- if (showInfoAction->isChecked())
- updateInfoForIndex(0);
- }
-
- // If the currentComicView was hidden before showing it sometimes the scroll view doesn't show it
- // this is a hacky solution...
- QTimer::singleShot(0, this, &GridComicsView::resetScroll);
+ pendingViewState.reset();
+ viewStateTimer->start(0);
}
void GridComicsView::updateBackgroundConfig()
{
- if (this->model == NULL)
+ if (this->model == nullptr)
return;
QQmlContext *ctxt = view->rootContext();
// backgroun image configuration
- bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
+ const bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
+ const bool hasBackgroundComic = this->model->rowCount() > 0;
+ const bool showBackgroundImage = useBackgroundImage && hasBackgroundComic;
- if (useBackgroundImage && this->model->rowCount() > 0) {
+ if (showBackgroundImage) {
float opacity = settings->value(OPACITY_BACKGROUND_IMAGE_IN_GRID_VIEW, 0.2).toFloat();
float blurRadius = settings->value(BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW, 75).toInt();
- int row = settings->value(USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW, false).toBool() ? currentIndex().row() : 0;
+ const auto selectedIndex = currentIndex();
+ int row = settings->value(USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW, false).toBool() && selectedIndex.isValid() ? selectedIndex.row() : 0;
ctxt->setContextProperty("backgroundImage", this->model->data(this->model->index(row, 0), ComicModel::CoverPathRole));
ctxt->setContextProperty("backgroundBlurOpacity", opacity);
@@ -226,23 +334,29 @@ void GridComicsView::updateBackgroundConfig()
// Use theme colors for cell and selected colors
const auto &giv = theme.gridAndInfoView;
- ctxt->setContextProperty("backgroundColor", useBackgroundImage ? giv.backgroundBlurOverlayColor : giv.backgroundColor);
- ctxt->setContextProperty("cellColor", useBackgroundImage ? giv.cellColorWithBackground : giv.cellColor);
+ ctxt->setContextProperty("backgroundColor", showBackgroundImage ? giv.backgroundBlurOverlayColor : giv.backgroundColor);
+ ctxt->setContextProperty("cellColor", showBackgroundImage ? giv.cellColorWithBackground : giv.cellColor);
ctxt->setContextProperty("cellSelectedColor", giv.cellSelectedColor);
}
-void GridComicsView::showInfo()
+void GridComicsView::updateInfoPanelVisibility()
{
QQmlContext *ctxt = view->rootContext();
ctxt->setContextProperty("showInfo", showInfoAction->isChecked());
- updateInfoForIndex(currentIndex().row());
+ if (!focusedFolderIndex.isValid())
+ updateInfoForIndex(currentIndex().row());
}
void GridComicsView::setCurrentIndex(const QModelIndex &index)
{
- selectionHelper->clear();
- selectionHelper->selectIndex(index.row());
+ clearFocusedFolder();
+ selectionHelper->selectOnly(index.row());
+
+ auto *root = view->rootObject();
+ auto grid = root ? root->findChild(QStringLiteral("grid")) : nullptr;
+ if (grid)
+ grid->setProperty("currentIndex", contentModel->viewRowForComicRow(index.row()));
if (settings->value(USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW, false).toBool())
updateBackgroundConfig();
@@ -251,11 +365,6 @@ void GridComicsView::setCurrentIndex(const QModelIndex &index)
updateInfoForIndex(index.row());
}
-void GridComicsView::setCurrentIndex(int index)
-{
- setCurrentIndex(model->index(index, 0));
-}
-
QModelIndex GridComicsView::currentIndex()
{
return selectionHelper->currentIndex();
@@ -294,20 +403,25 @@ void GridComicsView::enableFilterMode(bool enabled)
QQmlContext *ctxt = view->rootContext();
if (enabled) {
- ctxt->setContextProperty("showCurrentComic", QVariant(false));
+ if (currentComicBannerVisible) {
+ currentComicBannerVisible = false;
+ emit currentComicBannerVisibleChanged();
+ }
ctxt->setContextProperty("currentComic", nullptr);
} else {
- setCurrentComicIfNeeded();
+ updateCurrentComicBanner();
}
}
void GridComicsView::selectAll()
{
+ clearFocusedFolder();
selectionHelper->selectAll();
}
void GridComicsView::selectIndex(int index)
{
+ clearFocusedFolder();
selectionHelper->selectIndex(index);
}
@@ -322,8 +436,25 @@ void GridComicsView::triggerOpenCurrentComic()
void GridComicsView::updateSettings()
{
+ contentModel->setMixFoldersAndComics(settings->value(COMICS_GRID_MIX_FOLDERS_AND_COMICS, true).toBool());
+ contentModel->setStartComicsOnNewRow(settings->value(COMICS_GRID_START_COMICS_ON_NEW_ROW, false).toBool());
+ if (currentLocationInfo.value(QStringLiteral("kind")).toString() == QStringLiteral("recent")) {
+ currentLocationInfo.insert(QStringLiteral("recentDays"), settings->value(NUM_DAYS_TO_CONSIDER_RECENT, 1).toInt());
+ emit currentLocationInfoChanged();
+ }
+ updateBannerSettings();
updateBackgroundConfig();
- setCurrentComicIfNeeded();
+}
+
+void GridComicsView::updateBannerSettings()
+{
+ const bool enabled = settings->value(DISPLAY_GLOBAL_CONTINUE_READING_IN_GRID_VIEW, true).toBool();
+ if (globalContinueReadingEnabled != enabled) {
+ globalContinueReadingEnabled = enabled;
+ emit globalContinueReadingEnabledChanged();
+ }
+
+ updateCurrentComicBanner();
}
void GridComicsView::rate(int index, int rating)
@@ -331,11 +462,303 @@ void GridComicsView::rate(int index, int rating)
model->updateRating(rating, model->index(index, 0));
}
-void GridComicsView::requestedContextMenu(const QPoint &point)
+void GridComicsView::requestItemContextMenu(const QPoint &point, int viewRow)
{
+ if (contentModel->isFolderRow(viewRow)) {
+ emit openFolderContextMenu(point, contentModel->folderAt(viewRow));
+ return;
+ }
+
emit customContextMenuViewRequested(point);
}
+void GridComicsView::requestOpenLibraryFolder()
+{
+ emit openLibraryFolderRequested();
+}
+
+void GridComicsView::setFolderModel(FolderModel *model, const QModelIndex &folderIndex, const QString &rootName, const QVariantMap &libraryInfo)
+{
+ clearFocusedFolder();
+ contentModel->setFolderModel(model, folderIndex);
+ const bool selectedFolderIsRoot = !folderIndex.isValid();
+ if (rootFolder != selectedFolderIsRoot) {
+ rootFolder = selectedFolderIsRoot;
+ emit rootFolderChanged();
+ }
+
+ if (selectedFolderIsRoot) {
+ currentLocationInfo = libraryInfo;
+ currentLocationInfo.insert(QStringLiteral("kind"), QStringLiteral("library"));
+ currentLocationInfo.insert(QStringLiteral("name"), rootName);
+ } else {
+ const auto folder = model->getFolder(folderIndex);
+ const auto cover = folder.customImage.isEmpty() ? model->getCoverUrlPathForComicHash(folder.firstChildHash) : model->getCoverUrlPathForFolderId(folder.id);
+ currentLocationInfo = makeFolderInfo(folder, cover);
+ }
+ emit currentLocationInfoChanged();
+}
+
+void GridComicsView::clearFolderModel()
+{
+ clearFocusedFolder();
+ contentModel->clearFolderModel();
+ if (rootFolder) {
+ rootFolder = false;
+ emit rootFolderChanged();
+ }
+}
+
+void GridComicsView::setCurrentList(const QModelIndex &listIndex)
+{
+ const auto listType = static_cast(listIndex.data(ReadingListModel::TypeListsRole).toInt());
+ QString kind;
+ int labelColor = -1;
+ int recentDays = 0;
+ int sublistCount = 0;
+
+ switch (listType) {
+ case ReadingListModel::SpecialList: {
+ const auto specialType = static_cast(listIndex.data(ReadingListModel::SpecialListTypeRole).toInt());
+ switch (specialType) {
+ case ReadingListModel::TypeSpecialList::Favorites:
+ kind = QStringLiteral("favorites");
+ break;
+ case ReadingListModel::TypeSpecialList::Reading:
+ kind = QStringLiteral("reading");
+ break;
+ case ReadingListModel::TypeSpecialList::Recent:
+ kind = QStringLiteral("recent");
+ recentDays = settings->value(NUM_DAYS_TO_CONSIDER_RECENT, 1).toInt();
+ break;
+ }
+ break;
+ }
+ case ReadingListModel::Label: {
+ kind = QStringLiteral("tag");
+ labelColor = listIndex.data(ReadingListModel::LabelColorRole).toInt();
+ break;
+ }
+ case ReadingListModel::ReadingList: {
+ kind = QStringLiteral("readingList");
+ sublistCount = listIndex.model()->rowCount(listIndex);
+ break;
+ }
+ case ReadingListModel::Separator:
+ return;
+ }
+
+ currentLocationInfo = {
+ { QStringLiteral("kind"), kind },
+ { QStringLiteral("name"), listIndex.data(Qt::DisplayRole).toString() },
+ { QStringLiteral("itemCount"), model ? model->rowCount() : 0 },
+ { QStringLiteral("labelColor"), labelColor },
+ { QStringLiteral("recentDays"), recentDays },
+ { QStringLiteral("sublistCount"), sublistCount },
+ };
+ updateCurrentListIcon();
+ emit currentLocationInfoChanged();
+}
+
+void GridComicsView::updateCurrentListIcon()
+{
+ const auto kind = currentLocationInfo.value(QStringLiteral("kind")).toString();
+ QPixmap icon;
+
+ if (kind == QStringLiteral("favorites"))
+ icon = theme.emptyContainer.emptyFavoritesIcon;
+ else if (kind == QStringLiteral("reading"))
+ icon = theme.emptyContainer.emptyCurrentReadingsIcon;
+ else if (kind == QStringLiteral("recent"))
+ icon = theme.emptyContainer.emptyRecentIcon;
+ else if (kind == QStringLiteral("tag"))
+ icon = theme.emptyContainer.emptyLabelIcons.value(currentLocationInfo.value(QStringLiteral("labelColor")).toInt());
+ else if (kind == QStringLiteral("readingList"))
+ icon = theme.emptyContainer.emptyReadingListIcon;
+ else
+ return;
+
+ currentLocationInfo.insert(QStringLiteral("icon"), pixmapDataUrl(icon));
+}
+
+void GridComicsView::setRootContinueReadingModel(std::unique_ptr model)
+{
+ rootContinueReadingModelStorage = std::move(model);
+ emit rootContinueReadingModelChanged();
+}
+
+void GridComicsView::clearRootContinueReadingModel()
+{
+ setRootContinueReadingModel(nullptr);
+}
+
+ComicModel *GridComicsView::rootContinueReadingModel() const
+{
+ return rootContinueReadingModelStorage.get();
+}
+
+bool GridComicsView::isRootFolder() const
+{
+ return rootFolder;
+}
+
+bool GridComicsView::isGlobalContinueReadingEnabled() const
+{
+ return globalContinueReadingEnabled;
+}
+
+bool GridComicsView::isCurrentComicBannerVisible() const
+{
+ return currentComicBannerVisible;
+}
+
+int GridComicsView::focusedFolderRow() const
+{
+ return focusedFolderIndex.isValid() ? focusedFolderIndex.row() : -1;
+}
+
+QVariantMap GridComicsView::folderInfoForFocusedFolder() const
+{
+ return focusedFolderInfo;
+}
+
+QVariantMap GridComicsView::locationInfo() const
+{
+ return currentLocationInfo;
+}
+
+bool GridComicsView::hasComicSelection() const
+{
+ return selectionHelper->numItemsSelected() > 0;
+}
+
+void GridComicsView::reloadRootContinueReadingModel()
+{
+ if (rootFolder && rootContinueReadingModelStorage)
+ rootContinueReadingModelStorage->reloadContinueReading();
+}
+
+ContentViewState GridComicsView::captureViewState() const
+{
+ ContentViewState state;
+ auto *rootObject = view->rootObject();
+ auto *scrollView = rootObject ? rootObject->findChild(QStringLiteral("topScrollView"), Qt::FindChildrenRecursively) : nullptr;
+ if (!scrollView)
+ return state;
+
+ QVariant position;
+ QMetaObject::invokeMethod(scrollView, "capturePosition", Q_RETURN_ARG(QVariant, position));
+ const auto values = position.toMap();
+ const auto viewRow = values.value(QStringLiteral("viewRow"), -1).toInt();
+
+ state.offset = values.value(QStringLiteral("offset")).toReal();
+ state.itemExtent = values.value(QStringLiteral("itemExtent")).toReal();
+ if (model && model->rowCount() > 0)
+ state.fallbackComicRow = qBound(0, contentModel->sourceComicRow(viewRow), model->rowCount() - 1);
+
+ if (values.value(QStringLiteral("header")).toBool()) {
+ state.topItem.kind = ContentItemRef::Header;
+ } else if (viewRow >= 0 && viewRow < contentModel->rowCount()) {
+ const auto index = contentModel->index(viewRow, 0);
+ const auto kind = contentModel->data(index, GridContentModel::ItemKindRole).toInt();
+ state.topItem.kind = kind == GridContentModel::FolderItem ? ContentItemRef::Folder : ContentItemRef::Comic;
+ state.topItem.id = contentModel->data(index, GridContentModel::IdRole).toULongLong();
+ }
+
+ if (focusedFolderIndex.isValid()) {
+ state.currentItem.kind = ContentItemRef::Folder;
+ state.currentItem.id = focusedFolderIndex.data(FolderModel::IdRole).toULongLong();
+ } else if (const auto index = selectionHelper->currentIndex(); index.isValid()) {
+ state.currentItem.kind = ContentItemRef::Comic;
+ state.currentItem.id = index.data(ComicModel::IdRole).toULongLong();
+ }
+
+ return state;
+}
+
+void GridComicsView::restoreViewState(const ContentViewState &state)
+{
+ pendingViewState = state;
+ viewStateTimer->start(0);
+}
+
+void GridComicsView::openContinueReadingComic(int sourceRow)
+{
+ if (!rootContinueReadingModelStorage || sourceRow < 0 || sourceRow >= rootContinueReadingModelStorage->rowCount())
+ return;
+
+ emit openComic(rootContinueReadingModelStorage->getComic(rootContinueReadingModelStorage->index(sourceRow, 0)), ComicModel::Folder);
+}
+
+void GridComicsView::requestContinueReadingComicContextMenu(const QPoint &point, int sourceRow)
+{
+ if (!rootContinueReadingModelStorage || sourceRow < 0 || sourceRow >= rootContinueReadingModelStorage->rowCount())
+ return;
+
+ emit openContinueReadingComicContextMenu(point, rootContinueReadingModelStorage->getComic(rootContinueReadingModelStorage->index(sourceRow, 0)));
+}
+
+void GridComicsView::openFolder(int viewRow)
+{
+ const QPersistentModelIndex sourceIndex(contentModel->sourceFolderIndex(viewRow));
+ if (!sourceIndex.isValid())
+ return;
+
+ // setupFolderModelData()/setFolderModel() reset the model that owns the QML
+ // delegate. Defer navigation until Qt Quick finishes dispatching the event.
+ QTimer::singleShot(0, this, [this, sourceIndex]() {
+ if (sourceIndex.isValid())
+ emit folderSelected(sourceIndex);
+ });
+}
+
+void GridComicsView::focusItem(int viewRow)
+{
+ if (contentModel->isSpacerRow(viewRow))
+ return;
+
+ if (contentModel->isFolderRow(viewRow)) {
+ selectionHelper->clear();
+ setFocusedFolder(viewRow);
+ return;
+ }
+
+ const auto sourceRow = contentModel->sourceComicRow(viewRow);
+ if (sourceRow >= 0 && model && sourceRow < model->rowCount())
+ setCurrentIndex(model->index(sourceRow, 0));
+}
+
+void GridComicsView::selectComicRange(int from, int to)
+{
+ clearFocusedFolder();
+
+ if (from > to)
+ std::swap(from, to);
+
+ const auto firstComic = qMax(from, contentModel->viewRowForComicRow(0));
+ const auto lastComic = qMin(to, contentModel->rowCount() - 1);
+ for (auto row = firstComic; row <= lastComic; ++row)
+ selectionHelper->selectIndex(contentModel->sourceComicRow(row));
+}
+
+int GridComicsView::viewRowForComicRow(int sourceRow) const
+{
+ return contentModel->viewRowForComicRow(sourceRow);
+}
+
+void GridComicsView::setGridColumnCount(int columns)
+{
+ contentModel->setGridColumnCount(columns);
+}
+
+int GridComicsView::nearestSelectableRow(int viewRow, int direction) const
+{
+ if (!contentModel->isSpacerRow(viewRow))
+ return viewRow;
+
+ return direction < 0 ? contentModel->visibleFolderCount() - 1 : contentModel->viewRowForComicRow(0);
+}
+
void GridComicsView::setCoversSize(int width)
{
QQmlContext *ctxt = view->rootContext();
@@ -370,13 +793,7 @@ void GridComicsView::updateCoversSizeInContext(int width, QQmlContext *ctxt)
ctxt->setContextProperty("coverHeight", (width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH);
}
-void GridComicsView::dummyUpdater()
-{
- QQmlContext *ctxt = view->rootContext();
- ctxt->setContextProperty("dummyValue", true);
-}
-
-void GridComicsView::setCurrentComicIfNeeded()
+void GridComicsView::updateCurrentComicBanner()
{
if (model == nullptr) {
return;
@@ -389,24 +806,151 @@ void GridComicsView::setCurrentComicIfNeeded()
ComicModel::Mode mode = model->getMode();
- bool showCurrentComic = found &&
+ const bool showCurrentComic = found &&
filterEnabled == false &&
(mode == ComicModel::Mode::Folder || mode == ComicModel::Mode::ReadingList) &&
settings->value(DISPLAY_CONTINUE_READING_IN_GRID_VIEW, true).toBool();
ctxt->setContextProperty("currentComic", ¤tComic);
ctxt->setContextProperty("currentComicInfo", &(currentComic.info));
- ctxt->setContextProperty("showCurrentComic", QVariant(showCurrentComic));
+ if (currentComicBannerVisible != showCurrentComic) {
+ currentComicBannerVisible = showCurrentComic;
+ emit currentComicBannerVisibleChanged();
+ }
}
-void GridComicsView::resetScroll()
+void GridComicsView::clearFolderFocus()
+{
+ clearFocusedFolder();
+}
+
+QVariantMap GridComicsView::makeFolderInfo(const Folder &folder, const QVariant &cover) const
+{
+ QString typeName;
+ switch (folder.type) {
+ case YACReader::FileType::Manga:
+ typeName = tr("Manga");
+ break;
+ case YACReader::FileType::WesternManga:
+ typeName = tr("Western manga");
+ break;
+ case YACReader::FileType::WebComic:
+ typeName = tr("Web comic");
+ break;
+ case YACReader::FileType::Yonkoma:
+ typeName = tr("Yonkoma");
+ break;
+ case YACReader::FileType::Comic:
+ default:
+ typeName = tr("Comic");
+ break;
+ }
+
+ const QVariant itemCount = folder.numChildren < 0 ? QVariant(tr("Unknown")) : QVariant(folder.numChildren);
+ return {
+ { QStringLiteral("kind"), QStringLiteral("folder") },
+ { QStringLiteral("name"), folder.name },
+ { QStringLiteral("path"), folder.path },
+ { QStringLiteral("cover"), cover },
+ { QStringLiteral("itemCount"), itemCount },
+ { QStringLiteral("typeName"), typeName },
+ { QStringLiteral("finished"), folder.finished },
+ { QStringLiteral("completed"), folder.completed },
+ { QStringLiteral("added"), folder.added },
+ { QStringLiteral("updated"), folder.updated },
+ };
+}
+
+void GridComicsView::setFocusedFolder(int viewRow)
+{
+ if (!contentModel->isFolderRow(viewRow)) {
+ clearFocusedFolder();
+ return;
+ }
+
+ const auto sourceIndex = contentModel->sourceFolderIndex(viewRow);
+ if (!sourceIndex.isValid()) {
+ clearFocusedFolder();
+ return;
+ }
+
+ focusedFolderIndex = sourceIndex;
+ focusedFolderInfo = makeFolderInfo(contentModel->folderAt(viewRow), sourceIndex.data(FolderModel::CoverPathRole));
+ emit focusedFolderChanged();
+}
+
+void GridComicsView::clearFocusedFolder()
+{
+ if (!focusedFolderIndex.isValid() && focusedFolderInfo.isEmpty())
+ return;
+
+ focusedFolderIndex = QModelIndex();
+ focusedFolderInfo.clear();
+ emit focusedFolderChanged();
+}
+
+void GridComicsView::applyPendingViewState()
{
auto *rootObject = view->rootObject();
- if (!rootObject)
+ if (!rootObject) {
+ view->setUpdatesEnabled(true);
return;
+ }
auto scrollView = rootObject->findChild("topScrollView", Qt::FindChildrenRecursively);
+ if (!scrollView) {
+ view->setUpdatesEnabled(true);
+ return;
+ }
+
+ if (!pendingViewState) {
+ QMetaObject::invokeMethod(scrollView, "scrollToOrigin");
+ view->setUpdatesEnabled(true);
+ view->update();
+ return;
+ }
+
+ const auto state = *pendingViewState;
+ pendingViewState.reset();
+
+ if (state.currentItem.kind != ContentItemRef::None) {
+ const auto currentRow = viewRowForItem(state.currentItem);
+ if (currentRow >= 0)
+ focusItem(currentRow);
+ }
- QMetaObject::invokeMethod(scrollView, "scrollToOrigin");
+ auto viewRow = viewRowForItem(state.topItem);
+ if (state.topItem.kind == ContentItemRef::Header) {
+ viewRow = -1;
+ } else if (viewRow < 0 && contentModel->rowCount() > 0) {
+ if (model && model->rowCount() > 0 && state.fallbackComicRow >= 0) {
+ const auto comicRow = qBound(0, state.fallbackComicRow, model->rowCount() - 1);
+ viewRow = contentModel->viewRowForComicRow(comicRow);
+ } else {
+ viewRow = 0;
+ }
+ viewRow = nearestSelectableRow(viewRow, 1);
+ }
+
+ QMetaObject::invokeMethod(scrollView, "restorePosition",
+ Q_ARG(QVariant, viewRow),
+ Q_ARG(QVariant, state.offset),
+ Q_ARG(QVariant, state.itemExtent));
+ view->setUpdatesEnabled(true);
+ view->update();
+}
+
+int GridComicsView::viewRowForItem(const ContentItemRef &item) const
+{
+ switch (item.kind) {
+ case ContentItemRef::Comic:
+ return contentModel->viewRowForComicId(item.id);
+ case ContentItemRef::Folder:
+ return contentModel->viewRowForFolderId(item.id);
+ case ContentItemRef::None:
+ case ContentItemRef::Header:
+ return -1;
+ }
+ return -1;
}
void GridComicsView::showEvent(QShowEvent *event)
@@ -432,7 +976,7 @@ QByteArray GridComicsView::getMimeDataFromSelection()
void GridComicsView::updateCurrentComicView()
{
- setCurrentComicIfNeeded();
+ updateCurrentComicBanner();
}
void GridComicsView::focusComicsNavigation(Qt::FocusReason reason)
@@ -469,7 +1013,7 @@ bool GridComicsView::canDropUrls(const QList &urls, Qt::DropAction action)
return false;
}
-bool GridComicsView::canDropFormats(const QString &formats)
+bool GridComicsView::canDropFormats(const QStringList &formats)
{
return (formats.contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat) && model->canBeResorted());
}
@@ -488,12 +1032,21 @@ void GridComicsView::droppedComicsForResortingAt(const QString &data, int index)
{
Q_UNUSED(data);
- model->dropMimeData(model->mimeData(selectionHelper->selectedRows()), Qt::MoveAction, index, 0, QModelIndex());
+ const auto comicIndex = qBound(0, contentModel->sourceComicRow(index), model->rowCount());
+ model->dropMimeData(model->mimeData(selectionHelper->selectedRows()), Qt::MoveAction, comicIndex, 0, QModelIndex());
}
-void GridComicsView::selectedItem(int index)
+void GridComicsView::activateItem(int viewRow)
{
- emit selected(index);
+ if (viewRow < 0 || viewRow >= contentModel->rowCount() || contentModel->isSpacerRow(viewRow))
+ return;
+
+ if (contentModel->isFolderRow(viewRow)) {
+ openFolder(viewRow);
+ return;
+ }
+
+ emit selected(contentModel->sourceComicRow(viewRow));
}
void GridComicsView::applyTheme(const Theme &theme)
@@ -501,6 +1054,9 @@ void GridComicsView::applyTheme(const Theme &theme)
QQmlContext *ctxt = view->rootContext();
const auto &giv = theme.gridAndInfoView;
+ ctxt->setContextProperty("continueReadingBackgroundColor", giv.continueReadingBackgroundColor);
+ ctxt->setContextProperty("continueReadingTextColor", giv.continueReadingTextColor);
+
// Grid colors
ctxt->setContextProperty("backgroundColor", giv.backgroundColor);
ctxt->setContextProperty("backgroundBlurOverlayColor", giv.backgroundBlurOverlayColor);
@@ -538,6 +1094,11 @@ void GridComicsView::applyTheme(const Theme &theme)
ctxt->setContextProperty("scrollbarBorderColor", giv.scrollbarBorderColor);
ctxt->setContextProperty("infoScrollbarColor", giv.infoScrollbarColor);
ctxt->setContextProperty("comicCoverBorderColor", giv.comicCoverBorderColor);
+ ctxt->setContextProperty("folderCoverBorderColor", giv.folderCoverBorderColor);
+ ctxt->setContextProperty("placeholderFolder1Color", giv.placeholderFolder1Color);
+ ctxt->setContextProperty("placeholderFolder1BorderColor", giv.placeholderFolder1BorderColor);
+ ctxt->setContextProperty("placeholderFolder2Color", giv.placeholderFolder2Color);
+ ctxt->setContextProperty("placeholderFolder2BorderColor", giv.placeholderFolder2BorderColor);
ctxt->setContextProperty("currentComicCoverShadowColor", giv.currentComicCoverShadowColor);
ctxt->setContextProperty("buttonShadowColor", giv.buttonShadowColor);
@@ -554,6 +1115,12 @@ void GridComicsView::applyTheme(const Theme &theme)
if (bigZoomLabel) {
bigZoomLabel->setPixmap(theme.comicsViewToolbar.bigGridZoomIcon.pixmap(18, 18));
}
+
+ const auto locationKind = currentLocationInfo.value(QStringLiteral("kind")).toString();
+ if (locationKind == QStringLiteral("favorites") || locationKind == QStringLiteral("reading") || locationKind == QStringLiteral("recent") || locationKind == QStringLiteral("tag") || locationKind == QStringLiteral("readingList")) {
+ updateCurrentListIcon();
+ emit currentLocationInfoChanged();
+ }
}
void GridComicsView::setShowMarks(bool show)
@@ -564,16 +1131,8 @@ void GridComicsView::setShowMarks(bool show)
void GridComicsView::closeEvent(QCloseEvent *event)
{
- toolbar->removeAction(startSeparatorAction);
- toolbar->removeAction(showInfoAction);
- toolbar->removeAction(showInfoSeparatorAction);
- toolbar->removeAction(coverSizeSliderAction);
-
- int infoWidth = 0;
- if (auto *rootObject = view->rootObject()) {
- auto infoContainer = rootObject->findChild("infoContainer", Qt::FindChildrenRecursively);
- infoWidth = QQmlProperty(infoContainer, "width").read().toInt();
- }
+ releaseToolBar();
+ saveViewConfig();
/*QObject *object = view->rootObject();
QMetaObject::invokeMethod(object, "exit");
@@ -582,9 +1141,4 @@ void GridComicsView::closeEvent(QCloseEvent *event)
event->accept();
ComicsView::closeEvent(event);
-
- // save settings
- settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
- settings->setValue(COMICS_GRID_SHOW_INFO, showInfoAction->isChecked());
- settings->setValue(COMICS_GRID_INFO_WIDTH, infoWidth);
}
diff --git a/YACReaderLibrary/grid_comics_view.h b/YACReaderLibrary/grid_comics_view.h
index b3b674fff..8e72b8c7e 100644
--- a/YACReaderLibrary/grid_comics_view.h
+++ b/YACReaderLibrary/grid_comics_view.h
@@ -7,15 +7,24 @@
#include
#include
+#include
+#include
+
+#include
+#include
class QAbstractListModel;
class QItemSelectionModel;
class QQuickWidget;
class QQmlContext;
+class QTimer;
class YACReaderToolBarStretch;
class YACReaderComicsSelectionHelper;
class YACReaderComicInfoHelper;
+class GridContentModel;
+class FolderModel;
+class Folder;
// values relative to visible cells
const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156;
@@ -36,14 +45,49 @@ const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH;
class GridComicsView : public ComicsView, protected Themable
{
Q_OBJECT
+ Q_PROPERTY(ComicModel *rootContinueReadingModel READ rootContinueReadingModel NOTIFY rootContinueReadingModelChanged)
+ Q_PROPERTY(bool rootFolder READ isRootFolder NOTIFY rootFolderChanged)
+ Q_PROPERTY(bool globalContinueReadingEnabled READ isGlobalContinueReadingEnabled NOTIFY globalContinueReadingEnabledChanged)
+ Q_PROPERTY(bool currentComicBannerVisible READ isCurrentComicBannerVisible NOTIFY currentComicBannerVisibleChanged)
+ Q_PROPERTY(int focusedFolderRow READ focusedFolderRow NOTIFY focusedFolderChanged)
+ Q_PROPERTY(QVariantMap focusedFolderInfo READ folderInfoForFocusedFolder NOTIFY focusedFolderChanged)
+ Q_PROPERTY(QVariantMap currentLocationInfo READ locationInfo NOTIFY currentLocationInfoChanged)
+ Q_PROPERTY(bool hasComicSelection READ hasComicSelection NOTIFY comicSelectionStateChanged)
public:
explicit GridComicsView(QWidget *parent = nullptr);
+ ComicModel *rootContinueReadingModel() const;
+ bool isRootFolder() const;
+ bool isGlobalContinueReadingEnabled() const;
+ bool isCurrentComicBannerVisible() const;
+ int focusedFolderRow() const;
+ QVariantMap folderInfoForFocusedFolder() const;
+ QVariantMap locationInfo() const;
+ bool hasComicSelection() const;
+ void setFolderModel(FolderModel *model, const QModelIndex &folderIndex, const QString &rootName = { }, const QVariantMap &libraryInfo = { });
+ void clearFolderModel();
+ void setCurrentList(const QModelIndex &listIndex);
+ void setModel(ComicModel *model) override;
+ void setRootContinueReadingModel(std::unique_ptr model);
+ void clearRootContinueReadingModel();
+ void reloadRootContinueReadingModel();
+
+ Q_INVOKABLE void requestOpenLibraryFolder();
+ Q_INVOKABLE void openFolder(int viewRow);
+ Q_INVOKABLE void focusItem(int viewRow);
+ Q_INVOKABLE void clearFolderFocus();
+ Q_INVOKABLE void selectComicRange(int from, int to);
+ Q_INVOKABLE int viewRowForComicRow(int sourceRow) const;
+ Q_INVOKABLE void setGridColumnCount(int columns);
+ Q_INVOKABLE int nearestSelectableRow(int viewRow, int direction) const;
+ Q_INVOKABLE void openContinueReadingComic(int sourceRow);
+ Q_INVOKABLE void requestContinueReadingComicContextMenu(const QPoint &point, int sourceRow);
protected:
void applyTheme(const Theme &theme) override;
~GridComicsView() override;
void setToolBar(QToolBar *toolBar) override;
- void setModel(ComicModel *model) override;
+ void releaseToolBar() override;
+ void saveViewConfig() override;
void setCurrentIndex(const QModelIndex &index) override;
QModelIndex currentIndex() override;
QItemSelectionModel *selectionModel() override;
@@ -56,6 +100,8 @@ class GridComicsView : public ComicsView, protected Themable
void updateCurrentComicView() override;
void focusComicsNavigation(Qt::FocusReason reason) override;
void reloadContent() override;
+ ContentViewState captureViewState() const override;
+ void restoreViewState(const ContentViewState &state) override;
public slots:
// ComicsView
@@ -64,13 +110,13 @@ public slots:
void selectIndex(int index) override;
void triggerOpenCurrentComic();
void updateSettings();
+ void updateBannerSettings();
void updateBackgroundConfig();
- void showInfo();
+ void updateInfoPanelVisibility();
protected slots:
- void setCurrentIndex(int index);
// QML - double clicked item
- void selectedItem(int index);
+ void activateItem(int viewRow);
// QML - rating
void rate(int index, int rating);
@@ -78,25 +124,34 @@ protected slots:
void startDrag();
// QML - dropManager
bool canDropUrls(const QList &urls, Qt::DropAction action);
- bool canDropFormats(const QString &formats);
+ bool canDropFormats(const QStringList &formats);
void droppedFiles(const QList &urls, Qt::DropAction action);
void droppedComicsForResortingAt(const QString &data, int index);
// QML - context menu
- void requestedContextMenu(const QPoint &point);
+ void requestItemContextMenu(const QPoint &point, int viewRow);
void setCoversSize(int width);
void updateCoversSizeInContext(int width, QQmlContext *ctxt);
- void dummyUpdater(); // TODO remove this
-
- void setCurrentComicIfNeeded();
+ void updateCurrentComicBanner();
- void resetScroll();
+ void applyPendingViewState();
virtual void showEvent(QShowEvent *event) override;
signals:
void onScrollToOrigin();
+ void folderSelected(const QModelIndex &index);
+ void openFolderContextMenu(const QPoint &point, const Folder &folder);
+ void openContinueReadingComicContextMenu(const QPoint &point, const ComicDB &comic);
+ void comicSelectionStateChanged(bool hasSelection);
+ void rootContinueReadingModelChanged();
+ void rootFolderChanged();
+ void globalContinueReadingEnabledChanged();
+ void currentComicBannerVisibleChanged();
+ void focusedFolderChanged();
+ void currentLocationInfoChanged();
+ void openLibraryFolderRequested();
private:
QSettings *settings;
@@ -112,12 +167,28 @@ protected slots:
YACReaderComicsSelectionHelper *selectionHelper;
YACReaderComicInfoHelper *comicInfoHelper;
+ GridContentModel *contentModel;
+ std::unique_ptr rootContinueReadingModelStorage;
+ bool rootFolder = false;
+ bool globalContinueReadingEnabled = true;
+ bool currentComicBannerVisible = false;
+ QPersistentModelIndex focusedFolderIndex;
+ QVariantMap focusedFolderInfo;
+ QVariantMap currentLocationInfo;
+ QTimer *viewStateTimer;
+ std::optional pendingViewState;
+ QMetaObject::Connection modelDataChangedConnection;
+ QMetaObject::Connection modelFavoritesChangedConnection;
ComicDB currentComic;
- bool dummy;
void closeEvent(QCloseEvent *event) override;
void createCoverSizeSliderWidget();
+ QVariantMap makeFolderInfo(const Folder &folder, const QVariant &cover) const;
+ void updateCurrentListIcon();
+ void setFocusedFolder(int viewRow);
+ void clearFocusedFolder();
+ int viewRowForItem(const ContentItemRef &item) const;
// Zoom slider labels (for theming)
QLabel *smallZoomLabel;
diff --git a/YACReaderLibrary/grid_content_model.cpp b/YACReaderLibrary/grid_content_model.cpp
new file mode 100644
index 000000000..d6fee766a
--- /dev/null
+++ b/YACReaderLibrary/grid_content_model.cpp
@@ -0,0 +1,388 @@
+#include "grid_content_model.h"
+
+#include "comic_model.h"
+#include "folder_model.h"
+
+#include
+
+GridContentModel::GridContentModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+int GridContentModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ const auto comics = comicModel ? comicModel->rowCount() : 0;
+ return visibleFolderCount() + spacerCount() + comics;
+}
+
+QVariant GridContentModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() < 0 || index.row() >= rowCount())
+ return { };
+
+ if (isFolderRow(index.row())) {
+ const auto sourceIndex = sourceFolderIndex(index.row());
+ switch (role) {
+ case ItemKindRole:
+ return FolderItem;
+ case SourceIndexRole:
+ return sourceIndex.row();
+ case TitleRole:
+ case FileNameRole:
+ return sourceIndex.data(FolderModel::FolderNameRole);
+ case IdRole:
+ return sourceIndex.data(FolderModel::IdRole);
+ case CoverPathRole:
+ return sourceIndex.data(FolderModel::CoverPathRole);
+ case AddedRole:
+ return sourceIndex.data(FolderModel::AddedRole);
+ case TypeRole:
+ return sourceIndex.data(FolderModel::TypeRole);
+ case ShowRecentRole:
+ return sourceIndex.data(FolderModel::ShowRecentRole);
+ case RecentRangeRole:
+ return sourceIndex.data(FolderModel::RecentRangeRole);
+ case UpdatedRole:
+ return sourceIndex.data(FolderModel::UpdatedRole);
+ case FinishedRole:
+ return sourceIndex.data(FolderModel::FinishedRole);
+ default:
+ return { };
+ }
+ }
+
+ if (isSpacerRow(index.row())) {
+ if (role == ItemKindRole)
+ return SpacerItem;
+ if (role == SourceIndexRole)
+ return -1;
+ return { };
+ }
+
+ if (!comicModel)
+ return { };
+
+ const auto sourceRow = sourceComicRow(index.row());
+ const auto sourceIndex = comicModel->index(sourceRow, 0);
+ switch (role) {
+ case ItemKindRole:
+ return ComicItem;
+ case SourceIndexRole:
+ return sourceRow;
+ case NumberRole:
+ return sourceIndex.data(ComicModel::NumberRole);
+ case TitleRole:
+ return sourceIndex.data(ComicModel::TitleRole);
+ case FileNameRole:
+ return sourceIndex.data(ComicModel::FileNameRole);
+ case NumPagesRole:
+ return sourceIndex.data(ComicModel::NumPagesRole);
+ case IdRole:
+ return sourceIndex.data(ComicModel::IdRole);
+ case ReadRole:
+ return sourceIndex.data(ComicModel::ReadColumnRole);
+ case CurrentPageRole:
+ return sourceIndex.data(ComicModel::CurrentPageRole);
+ case RatingRole:
+ return sourceIndex.data(ComicModel::RatingRole);
+ case HasBeenOpenedRole:
+ return sourceIndex.data(ComicModel::HasBeenOpenedRole);
+ case CoverPathRole:
+ return sourceIndex.data(ComicModel::CoverPathRole);
+ case AddedRole:
+ return sourceIndex.data(ComicModel::AddedRole);
+ case TypeRole:
+ return sourceIndex.data(ComicModel::TypeRole);
+ case ShowRecentRole:
+ return sourceIndex.data(ComicModel::ShowRecentRole);
+ case RecentRangeRole:
+ return sourceIndex.data(ComicModel::RecentRangeRole);
+ default:
+ return { };
+ }
+}
+
+QHash GridContentModel::roleNames() const
+{
+ return {
+ { ItemKindRole, "item_kind" },
+ { SourceIndexRole, "source_index" },
+ { NumberRole, "number" },
+ { TitleRole, "title" },
+ { FileNameRole, "file_name" },
+ { NumPagesRole, "num_pages" },
+ { IdRole, "id" },
+ { ReadRole, "read_column" },
+ { CurrentPageRole, "current_page" },
+ { RatingRole, "rating" },
+ { HasBeenOpenedRole, "has_been_opened" },
+ { CoverPathRole, "cover_path" },
+ { AddedRole, "added_date" },
+ { TypeRole, "type" },
+ { ShowRecentRole, "show_recent" },
+ { RecentRangeRole, "recent_range" },
+ { UpdatedRole, "updated" },
+ { FinishedRole, "is_finished" },
+ };
+}
+
+void GridContentModel::setComicModel(ComicModel *model)
+{
+ if (comicModel == model)
+ return;
+
+ beginResetModel();
+ comicModel = model;
+ endResetModel();
+ reconnectModels();
+}
+
+void GridContentModel::setFolderModel(FolderModel *model, const QModelIndex &folderIndex)
+{
+ beginResetModel();
+ folderModel = model;
+ selectedFolderIndex = folderIndex;
+ selectedFolderIsRoot = model && !folderIndex.isValid();
+ endResetModel();
+ reconnectModels();
+}
+
+void GridContentModel::clearFolderModel()
+{
+ setFolderModel(nullptr, { });
+}
+
+void GridContentModel::setMixFoldersAndComics(bool enabled)
+{
+ if (mixFoldersAndComics == enabled)
+ return;
+
+ beginResetModel();
+ mixFoldersAndComics = enabled;
+ endResetModel();
+}
+
+void GridContentModel::setStartComicsOnNewRow(bool enabled)
+{
+ if (startComicsOnNewRow == enabled)
+ return;
+
+ beginResetModel();
+ startComicsOnNewRow = enabled;
+ endResetModel();
+}
+
+void GridContentModel::setGridColumnCount(int columns)
+{
+ columns = qMax(1, columns);
+ if (gridColumnCount == columns)
+ return;
+
+ const auto previousSpacerCount = spacerCount();
+ gridColumnCount = columns;
+ if (previousSpacerCount != spacerCount())
+ resetFromSource();
+}
+
+bool GridContentModel::isFolderRow(int viewRow) const
+{
+ return viewRow >= 0 && viewRow < visibleFolderCount();
+}
+
+bool GridContentModel::isSpacerRow(int viewRow) const
+{
+ return viewRow >= visibleFolderCount() && viewRow < visibleFolderCount() + spacerCount();
+}
+
+int GridContentModel::visibleFolderCount() const
+{
+ const auto folders = sourceFolderCount();
+ if (!mixFoldersAndComics && comicModel && comicModel->rowCount() > 0)
+ return 0;
+ return folders;
+}
+
+int GridContentModel::sourceComicRow(int viewRow) const
+{
+ return viewRow - visibleFolderCount() - spacerCount();
+}
+
+int GridContentModel::viewRowForComicRow(int sourceRow) const
+{
+ return sourceRow < 0 ? -1 : visibleFolderCount() + spacerCount() + sourceRow;
+}
+
+int GridContentModel::viewRowForComicId(qulonglong id) const
+{
+ if (!comicModel)
+ return -1;
+
+ const auto sourceIndex = comicModel->getIndexFromId(id);
+ return sourceIndex.isValid() ? viewRowForComicRow(sourceIndex.row()) : -1;
+}
+
+int GridContentModel::viewRowForFolderId(qulonglong id) const
+{
+ for (auto row = 0; row < visibleFolderCount(); ++row) {
+ if (data(index(row, 0), IdRole).toULongLong() == id)
+ return row;
+ }
+ return -1;
+}
+
+QModelIndex GridContentModel::sourceFolderIndex(int viewRow) const
+{
+ if (!folderModel || !isFolderRow(viewRow))
+ return { };
+ const QModelIndex parent = selectedFolderIsRoot ? QModelIndex() : QModelIndex(selectedFolderIndex);
+ return folderModel->index(viewRow, 0, parent);
+}
+
+Folder GridContentModel::folderAt(int viewRow) const
+{
+ if (!folderModel)
+ return { };
+
+ return folderModel->getFolder(sourceFolderIndex(viewRow));
+}
+
+QUrl GridContentModel::comicCoverUrlForHash(const QString &hash) const
+{
+ return comicModel ? comicModel->getCoverUrlPathForComicHash(hash) : QUrl();
+}
+
+void GridContentModel::reconnectModels()
+{
+ for (const auto &connection : std::as_const(sourceConnections))
+ disconnect(connection);
+ sourceConnections.clear();
+
+ if (folderModel) {
+ sourceConnections << connect(folderModel, &QAbstractItemModel::modelReset, this, &GridContentModel::resetFromSource);
+ sourceConnections << connect(folderModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [this](const QModelIndex &parent, int first, int last) {
+ if (parent == selectedFolderIndex && forwardsFolderRowsDirectly())
+ beginInsertRows({ }, first, last);
+ });
+ sourceConnections << connect(folderModel, &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &parent) {
+ if (parent != selectedFolderIndex)
+ return;
+ if (forwardsFolderRowsDirectly())
+ endInsertRows();
+ else if (mixFoldersAndComics)
+ resetFromSource();
+ });
+ sourceConnections << connect(folderModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [this](const QModelIndex &parent, int first, int last) {
+ if (parent == selectedFolderIndex && forwardsFolderRowsDirectly())
+ beginRemoveRows({ }, first, last);
+ });
+ sourceConnections << connect(folderModel, &QAbstractItemModel::rowsRemoved, this, [this](const QModelIndex &parent) {
+ if (parent != selectedFolderIndex)
+ return;
+ if (forwardsFolderRowsDirectly())
+ endRemoveRows();
+ else if (mixFoldersAndComics)
+ resetFromSource();
+ });
+ sourceConnections << connect(folderModel, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
+ if (visibleFolderCount() > 0 && topLeft.parent() == selectedFolderIndex && bottomRight.parent() == selectedFolderIndex)
+ emit dataChanged(index(topLeft.row()), index(bottomRight.row()));
+ });
+ }
+
+ if (comicModel) {
+ sourceConnections << connect(comicModel, &QAbstractItemModel::modelReset, this, &GridContentModel::resetFromSource);
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [this](const QModelIndex &parent, int first, int last) {
+ if (parent.isValid())
+ return;
+ if (!forwardsComicRowsDirectly())
+ return;
+ const auto offset = visibleFolderCount();
+ beginInsertRows({ }, offset + first, offset + last);
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &parent) {
+ if (parent.isValid())
+ return;
+ if (forwardsComicRowsDirectly())
+ endInsertRows();
+ else
+ resetFromSource();
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [this](const QModelIndex &parent, int first, int last) {
+ if (parent.isValid())
+ return;
+ if (!forwardsComicRowsDirectly())
+ return;
+ const auto offset = visibleFolderCount();
+ beginRemoveRows({ }, offset + first, offset + last);
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsRemoved, this, [this](const QModelIndex &parent) {
+ if (parent.isValid())
+ return;
+ if (forwardsComicRowsDirectly())
+ endRemoveRows();
+ else
+ resetFromSource();
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsAboutToBeMoved, this, [this](const QModelIndex &sourceParent, int first, int last, const QModelIndex &destinationParent, int destination) {
+ if (sourceParent.isValid() || destinationParent.isValid())
+ return;
+ if (!forwardsComicRowsDirectly())
+ return;
+ const auto offset = visibleFolderCount();
+ beginMoveRows({ }, offset + first, offset + last, { }, offset + destination);
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::rowsMoved, this, [this](const QModelIndex &sourceParent, int, int, const QModelIndex &destinationParent) {
+ if (sourceParent.isValid() || destinationParent.isValid())
+ return;
+ if (forwardsComicRowsDirectly())
+ endMoveRows();
+ else
+ resetFromSource();
+ });
+ sourceConnections << connect(comicModel, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
+ if (topLeft.parent().isValid() || bottomRight.parent().isValid())
+ return;
+ emit dataChanged(index(viewRowForComicRow(topLeft.row())), index(viewRowForComicRow(bottomRight.row())));
+ });
+ }
+}
+
+void GridContentModel::resetFromSource()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+int GridContentModel::sourceFolderCount() const
+{
+ if (!folderModel)
+ return 0;
+ if (selectedFolderIsRoot)
+ return folderModel->rowCount();
+ return selectedFolderIndex.isValid() ? folderModel->rowCount(selectedFolderIndex) : 0;
+}
+
+int GridContentModel::spacerCount() const
+{
+ const auto folders = visibleFolderCount();
+ const auto comics = comicModel ? comicModel->rowCount() : 0;
+ if (!mixFoldersAndComics || !startComicsOnNewRow || folders == 0 || comics == 0)
+ return 0;
+
+ return (gridColumnCount - (folders % gridColumnCount)) % gridColumnCount;
+}
+
+bool GridContentModel::forwardsFolderRowsDirectly() const
+{
+ const auto comics = comicModel ? comicModel->rowCount() : 0;
+ return comics == 0 || (mixFoldersAndComics && !startComicsOnNewRow);
+}
+
+bool GridContentModel::forwardsComicRowsDirectly() const
+{
+ return mixFoldersAndComics && !startComicsOnNewRow;
+}
diff --git a/YACReaderLibrary/grid_content_model.h b/YACReaderLibrary/grid_content_model.h
new file mode 100644
index 000000000..6df74bc8f
--- /dev/null
+++ b/YACReaderLibrary/grid_content_model.h
@@ -0,0 +1,87 @@
+#ifndef GRID_CONTENT_MODEL_H
+#define GRID_CONTENT_MODEL_H
+
+#include
+#include
+#include
+
+class ComicModel;
+class FolderModel;
+class Folder;
+
+class GridContentModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ enum ItemKind {
+ FolderItem = 0,
+ ComicItem,
+ SpacerItem
+ };
+ Q_ENUM(ItemKind)
+
+ enum Roles {
+ ItemKindRole = Qt::UserRole + 1,
+ SourceIndexRole,
+ NumberRole,
+ TitleRole,
+ FileNameRole,
+ NumPagesRole,
+ IdRole,
+ ReadRole,
+ CurrentPageRole,
+ RatingRole,
+ HasBeenOpenedRole,
+ CoverPathRole,
+ AddedRole,
+ TypeRole,
+ ShowRecentRole,
+ RecentRangeRole,
+ UpdatedRole,
+ FinishedRole
+ };
+
+ explicit GridContentModel(QObject *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QHash roleNames() const override;
+
+ void setComicModel(ComicModel *model);
+ void setFolderModel(FolderModel *model, const QModelIndex &selectedFolderIndex);
+ void clearFolderModel();
+ void setMixFoldersAndComics(bool enabled);
+ void setStartComicsOnNewRow(bool enabled);
+ void setGridColumnCount(int columns);
+
+ bool isFolderRow(int viewRow) const;
+ bool isSpacerRow(int viewRow) const;
+ int visibleFolderCount() const;
+ int sourceComicRow(int viewRow) const;
+ int viewRowForComicRow(int sourceRow) const;
+ int viewRowForComicId(qulonglong id) const;
+ int viewRowForFolderId(qulonglong id) const;
+ QModelIndex sourceFolderIndex(int viewRow) const;
+ Folder folderAt(int viewRow) const;
+ Q_INVOKABLE QUrl comicCoverUrlForHash(const QString &hash) const;
+
+private:
+ void reconnectModels();
+ void resetFromSource();
+ int sourceFolderCount() const;
+ int spacerCount() const;
+ bool forwardsFolderRowsDirectly() const;
+ bool forwardsComicRowsDirectly() const;
+
+ ComicModel *comicModel = nullptr;
+ FolderModel *folderModel = nullptr;
+ QPersistentModelIndex selectedFolderIndex;
+ bool selectedFolderIsRoot = false;
+ bool mixFoldersAndComics = true;
+ bool startComicsOnNewRow = false;
+ int gridColumnCount = 1;
+ QList sourceConnections;
+};
+
+#endif // GRID_CONTENT_MODEL_H
diff --git a/YACReaderLibrary/info_comics_view.cpp b/YACReaderLibrary/info_comics_view.cpp
index 3bcaa6623..1608dffb0 100644
--- a/YACReaderLibrary/info_comics_view.cpp
+++ b/YACReaderLibrary/info_comics_view.cpp
@@ -14,7 +14,7 @@
#include
InfoComicsView::InfoComicsView(QWidget *parent)
- : ComicsView(parent), flow(nullptr), list(nullptr)
+ : ComicsView(parent), toolbar(nullptr), flow(nullptr), list(nullptr)
{
// container->setFocusPolicy(Qt::StrongFocus);
@@ -53,7 +53,11 @@ InfoComicsView::~InfoComicsView()
void InfoComicsView::setToolBar(QToolBar *toolBar)
{
static_cast(this->layout())->insertWidget(1, toolBar);
- this->toolbar = toolBar;
+ toolbar = toolBar;
+}
+
+void InfoComicsView::releaseToolBar()
+{
}
void InfoComicsView::setModel(ComicModel *model)
@@ -143,6 +147,36 @@ void InfoComicsView::scrollTo(const QModelIndex &mi, QAbstractItemView::ScrollHi
Q_UNUSED(hint);
}
+ContentViewState InfoComicsView::captureViewState() const
+{
+ ContentViewState state;
+ const auto index = selectionHelper->currentIndex();
+ if (index.isValid()) {
+ state.topItem.kind = ContentItemRef::Comic;
+ state.topItem.id = index.data(ComicModel::IdRole).toULongLong();
+ state.fallbackComicRow = index.row();
+ state.currentItem = state.topItem;
+ }
+ return state;
+}
+
+void InfoComicsView::restoreViewState(const ContentViewState &state)
+{
+ if (!model || model->rowCount() == 0)
+ return;
+
+ auto index = state.currentItem.kind == ContentItemRef::Comic ? model->getIndexFromId(state.currentItem.id) : QModelIndex();
+ if (!index.isValid() && state.fallbackComicRow >= 0)
+ index = model->index(qBound(0, state.fallbackComicRow, model->rowCount() - 1), 0);
+ if (!index.isValid())
+ return;
+
+ selectionHelper->clear();
+ selectionHelper->selectIndex(index.row());
+ if (list)
+ QMetaObject::invokeMethod(list, "restoreCurrentIndex", Q_ARG(QVariant, index.row()));
+}
+
void InfoComicsView::toFullScreen()
{
toolbar->hide();
diff --git a/YACReaderLibrary/info_comics_view.h b/YACReaderLibrary/info_comics_view.h
index d898cee4e..69485a8d4 100644
--- a/YACReaderLibrary/info_comics_view.h
+++ b/YACReaderLibrary/info_comics_view.h
@@ -21,6 +21,7 @@ class InfoComicsView : public ComicsView, protected Themable
void applyTheme(const Theme &theme) override;
~InfoComicsView() override;
void setToolBar(QToolBar *toolBar) override;
+ void releaseToolBar() override;
void setModel(ComicModel *model) override;
void setCurrentIndex(const QModelIndex &index) override;
QModelIndex currentIndex() override;
@@ -33,6 +34,8 @@ class InfoComicsView : public ComicsView, protected Themable
void selectIndex(int index) override;
void updateCurrentComicView() override;
void focusComicsNavigation(Qt::FocusReason reason) override;
+ ContentViewState captureViewState() const override;
+ void restoreViewState(const ContentViewState &state) override;
public slots:
void setShowMarks(bool show) override;
diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp
index 49f0ebf7e..f63776767 100644
--- a/YACReaderLibrary/library_window.cpp
+++ b/YACReaderLibrary/library_window.cpp
@@ -53,9 +53,9 @@
#include "edit_shortcuts_dialog.h"
#include "export_comics_info_dialog.h"
#include "export_library_dialog.h"
-#include "folder_content_view.h"
#include "folder_item.h"
#include "folder_model.h"
+#include "grid_comics_view.h"
#include "help_about_dialog.h"
#include "import_comics_info_dialog.h"
#include "import_library_dialog.h"
@@ -157,17 +157,19 @@ void LibraryWindow::showEvent(QShowEvent *event)
bool LibraryWindow::eventFilter(QObject *object, QEvent *event)
{
if (this->isActiveWindow()) {
- if (event->type() == QEvent::MouseButtonRelease) {
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
auto mouseEvent = static_cast(event);
if (mouseEvent->button() == Qt::ForwardButton) {
- actions.forwardAction->trigger();
+ if (event->type() == QEvent::MouseButtonRelease)
+ actions.forwardAction->trigger();
event->accept();
return true;
}
if (mouseEvent->button() == Qt::BackButton) {
- actions.backAction->trigger();
+ if (event->type() == QEvent::MouseButtonRelease)
+ actions.backAction->trigger();
event->accept();
return true;
}
@@ -424,7 +426,7 @@ void LibraryWindow::doModels()
void LibraryWindow::setupCoordinators()
{
- recentVisibilityCoordinator = new RecentVisibilityCoordinator(settings, foldersModel, contentViewsManager->folderContentView, comicsModel);
+ recentVisibilityCoordinator = new RecentVisibilityCoordinator(settings, foldersModel, comicsModel);
auto canStartUpdateProvider = [this]() {
return comicVineDialog->isVisible() == false &&
@@ -542,8 +544,10 @@ void LibraryWindow::createToolBars()
editInfoToolBar->addAction(actions.deleteComicsAction);
+ comicToolbarEntries = editInfoToolBar->actions();
+
auto toolBarStretch = new YACReaderToolBarStretch(this);
- editInfoToolBar->addWidget(toolBarStretch);
+ comicToolbarEndAnchor = editInfoToolBar->addWidget(toolBarStretch);
editInfoToolBar->addAction(actions.toogleShowRecentIndicatorAction);
@@ -834,6 +838,7 @@ void LibraryWindow::createConnections()
{
actions.createConnections(
historyController,
+ navigationController,
this,
had,
exportLibraryDialog,
@@ -972,13 +977,15 @@ void LibraryWindow::createConnections()
connect(foldersView, &QWidget::customContextMenuRequested, this, &LibraryWindow::showFoldersContextMenu);
// properties & config
- connect(propertiesDialog, &QDialog::accepted, contentViewsManager, &YACReaderContentViewsManager::updateCurrentContentView);
+ connect(propertiesDialog, &QDialog::accepted, navigationController, &YACReaderNavigationController::refreshCurrentSource);
+ connect(propertiesDialog, &QDialog::rejected, navigationController, &YACReaderNavigationController::cancelCurrentSourceRefresh);
connect(propertiesDialog, &PropertiesDialog::coverChangedSignal, this, [=](const ComicDB &comic) {
comicsModel->notifyCoverChange(comic);
});
// comic vine
- connect(comicVineDialog, &QDialog::accepted, contentViewsManager, &YACReaderContentViewsManager::updateCurrentContentView, Qt::QueuedConnection);
+ connect(comicVineDialog, &QDialog::accepted, navigationController, &YACReaderNavigationController::refreshCurrentSource, Qt::QueuedConnection);
+ connect(comicVineDialog, &QDialog::rejected, navigationController, &YACReaderNavigationController::cancelCurrentSourceRefresh);
connect(optionsDialog, &YACReaderOptionsDialog::optionsChanged, this, &LibraryWindow::reloadOptions);
connect(optionsDialog, &YACReaderOptionsDialog::editShortcuts, editShortcutsDialog, &QWidget::show);
@@ -1116,7 +1123,7 @@ void LibraryWindow::loadLibrary(const QString &name)
actions.openContainingFolderAction->setDisabled(true);
actions.rescanLibraryForXMLInfoAction->setDisabled(true);
- disableComicsActions(true);
+ setComicActionsDisabled(true);
#ifndef Q_OS_MACOS
actions.toggleFullScreenAction->setEnabled(true);
#endif
@@ -1328,7 +1335,7 @@ QProgressDialog *LibraryWindow::newProgressDialog(const QString &label, int maxV
void LibraryWindow::reloadCurrentFolderComicsContent()
{
- navigationController->loadFolderInfo(getCurrentFolderIndex());
+ navigationController->loadFolderContent(getCurrentFolderIndex());
enableNeededActions();
}
@@ -1344,7 +1351,7 @@ void LibraryWindow::reloadAfterCopyMove(const QModelIndex &mi)
foldersModel->reload(mi);
}
- contentViewsManager->updateCurrentContentView();
+ navigationController->refreshCurrentSource();
}
enableNeededActions();
@@ -1367,19 +1374,34 @@ void LibraryWindow::enableNeededActions()
actions.disableFoldersActions(false);
if (comicsModel->rowCount() > 0)
- disableComicsActions(false);
+ setComicActionsDisabled(false);
actions.disableLibrariesActions(false);
}
-void LibraryWindow::disableComicsActions(bool disabled)
+void LibraryWindow::setComicActionsDisabled(bool disabled)
{
if (!disabled && librariesUpdateCoordinator->isRunning()) {
- disableComicsActions(true);
+ setComicActionsDisabled(true);
return;
}
- actions.disableComicsActions(disabled);
+ actions.setComicActionsDisabled(disabled);
+ setComicToolbarEntriesVisible(comicsModel != nullptr && comicsModel->rowCount() > 0);
+}
+
+void LibraryWindow::setComicToolbarEntriesVisible(bool visible)
+{
+ if (editInfoToolBar == nullptr || comicToolbarEndAnchor == nullptr)
+ return;
+
+ const auto currentActions = editInfoToolBar->actions();
+ for (auto *action : comicToolbarEntries) {
+ if (visible && !currentActions.contains(action))
+ editInfoToolBar->insertAction(comicToolbarEndAnchor, action);
+ else if (!visible && currentActions.contains(action))
+ editInfoToolBar->removeAction(action);
+ }
}
void LibraryWindow::addFolderToCurrentIndex()
@@ -1404,10 +1426,8 @@ void LibraryWindow::addFolderToCurrentIndex()
if (parentDir.mkdir(newFolderName) || newFolder.exists()) {
QModelIndex newIndex = foldersModel->addFolderAtParent(newFolderName, currentIndex);
foldersView->setCurrentIndex(foldersModelProxy->mapFromSource(newIndex));
- navigationController->loadFolderInfo(newIndex);
+ navigationController->loadFolderContent(newIndex);
historyController->updateHistory(YACReaderLibrarySourceContainer(newIndex, YACReaderLibrarySourceContainer::Folder));
- // a new folder is always an empty folder
- contentViewsManager->showFolderContentView();
}
}
}
@@ -1435,6 +1455,15 @@ void LibraryWindow::deleteSelectedFolder()
QList paths;
paths << folderPath;
+ // The unified grid observes the main folder model directly. Move
+ // away from the folder before removing its model index so the
+ // content view never retains the index being deleted.
+ const QModelIndex parentIndex = currentIndex.parent();
+ if (parentIndex.isValid())
+ foldersView->setCurrentIndex(foldersModelProxy->mapFromSource(parentIndex));
+ else
+ setRootIndex();
+
auto remover = new FoldersRemover(indexList, paths);
const auto thread = new QThread(this);
moveAndConnectRemoverToThread(remover, thread);
@@ -1541,20 +1570,22 @@ void LibraryWindow::showComicsItemContextMenu(const QPoint &point)
void LibraryWindow::showComicsContextMenu(const QPoint &point, bool showFullScreenAction)
{
auto selection = this->getSelectedComics();
+ auto menu = new QMenu(this);
+ connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
- auto setNormalAction = new QAction();
+ auto setNormalAction = new QAction(menu);
setNormalAction->setText(tr("comic"));
- auto setMangaAction = new QAction();
+ auto setMangaAction = new QAction(menu);
setMangaAction->setText(tr("manga"));
- auto setWesternMangaAction = new QAction();
+ auto setWesternMangaAction = new QAction(menu);
setWesternMangaAction->setText(tr("western manga (left to right)"));
- auto setWebComicAction = new QAction();
+ auto setWebComicAction = new QAction(menu);
setWebComicAction->setText(tr("web comic"));
- auto setYonkomaAction = new QAction();
+ auto setYonkomaAction = new QAction(menu);
setYonkomaAction->setText(tr("4koma (top to botom)"));
setNormalAction->setCheckable(true);
@@ -1595,114 +1626,113 @@ void LibraryWindow::showComicsContextMenu(const QPoint &point, bool showFullScre
setupActions(type);
}
- QMenu menu;
-
- menu.addAction(actions.openComicAction);
- menu.addAction(actions.saveCoversToAction);
- menu.addSeparator();
- menu.addAction(actions.openContainingFolderComicAction);
- menu.addAction(actions.updateCurrentFolderAction);
- menu.addSeparator();
- menu.addAction(actions.resetComicRatingAction);
- menu.addSeparator();
- menu.addAction(actions.editSelectedComicsAction);
- menu.addAction(actions.getInfoAction);
- menu.addAction(actions.asignOrderAction);
- menu.addSeparator();
- menu.addAction(actions.selectAllComicsAction);
- menu.addSeparator();
- menu.addAction(actions.setAsReadAction);
- menu.addAction(actions.setAsNonReadAction);
- menu.addSeparator();
- auto typeMenu = new QMenu(tr("Set type"));
- menu.addMenu(typeMenu);
+ menu->addAction(actions.openComicAction);
+ menu->addAction(actions.saveCoversToAction);
+ menu->addSeparator();
+ menu->addAction(actions.openContainingFolderComicAction);
+ menu->addAction(actions.updateCurrentFolderAction);
+ menu->addSeparator();
+ menu->addAction(actions.resetComicRatingAction);
+ menu->addSeparator();
+ menu->addAction(actions.editSelectedComicsAction);
+ menu->addAction(actions.getInfoAction);
+ menu->addAction(actions.asignOrderAction);
+ menu->addSeparator();
+ menu->addAction(actions.selectAllComicsAction);
+ menu->addSeparator();
+ menu->addAction(actions.setAsReadAction);
+ menu->addAction(actions.setAsNonReadAction);
+ menu->addSeparator();
+ auto typeMenu = new QMenu(tr("Set type"), menu);
+ menu->addMenu(typeMenu);
typeMenu->addAction(setNormalAction);
typeMenu->addAction(setMangaAction);
typeMenu->addAction(setWesternMangaAction);
typeMenu->addAction(setWebComicAction);
typeMenu->addAction(setYonkomaAction);
- menu.addSeparator();
- menu.addAction(actions.deleteMetadataAction);
- menu.addSeparator();
- menu.addAction(actions.deleteComicsAction);
- menu.addSeparator();
- menu.addAction(actions.addToMenuAction);
- QMenu subMenu;
- setupAddToSubmenu(subMenu);
+ menu->addSeparator();
+ menu->addAction(actions.deleteMetadataAction);
+ menu->addSeparator();
+ menu->addAction(actions.deleteComicsAction);
+ menu->addSeparator();
+ menu->addAction(actions.addToMenuAction);
+ auto subMenu = new QMenu(menu);
+ setupAddToSubmenu(*subMenu);
#ifndef Q_OS_MACOS
if (showFullScreenAction) {
- menu.addSeparator();
- menu.addAction(actions.toggleFullScreenAction);
+ menu->addSeparator();
+ menu->addAction(actions.toggleFullScreenAction);
}
#endif
- menu.exec(contentViewsManager->comicsView->mapToGlobal(point));
+ menu->popup(contentViewsManager->comicsView->mapToGlobal(point));
}
void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
{
- QMenu menu;
+ auto menu = new QMenu(this);
+ connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
const auto &menuIcons = theme.menuIcons;
- auto openContainingFolderAction = new QAction();
+ auto openContainingFolderAction = new QAction(menu);
openContainingFolderAction->setText(tr("Open folder..."));
openContainingFolderAction->setIcon(menuIcons.openContainingFolderIcon);
- auto updateFolderAction = new QAction(tr("Update folder"), this);
+ auto updateFolderAction = new QAction(tr("Update folder"), menu);
updateFolderAction->setIcon(menuIcons.updateCurrentFolderIcon);
- auto rescanLibraryForXMLInfoAction = new QAction(tr("Rescan library for XML info"), this);
+ auto rescanLibraryForXMLInfoAction = new QAction(tr("Rescan library for XML info"), menu);
- auto setFolderAsNotCompletedAction = new QAction();
+ auto setFolderAsNotCompletedAction = new QAction(menu);
setFolderAsNotCompletedAction->setText(tr("Set as uncompleted"));
- auto setFolderAsCompletedAction = new QAction();
+ auto setFolderAsCompletedAction = new QAction(menu);
setFolderAsCompletedAction->setText(tr("Set as completed"));
- auto setFolderAsReadAction = new QAction();
+ auto setFolderAsReadAction = new QAction(menu);
setFolderAsReadAction->setText(tr("Set as read"));
- auto setFolderAsUnreadAction = new QAction();
+ auto setFolderAsUnreadAction = new QAction(menu);
setFolderAsUnreadAction->setText(tr("Set as unread"));
- auto setFolderAsMangaAction = new QAction();
+ auto setFolderAsMangaAction = new QAction(menu);
setFolderAsMangaAction->setText(tr("manga"));
- auto setFolderAsNormalAction = new QAction();
+ auto setFolderAsNormalAction = new QAction(menu);
setFolderAsNormalAction->setText(tr("comic"));
- auto setFolderAsWesternMangaAction = new QAction();
+ auto setFolderAsWesternMangaAction = new QAction(menu);
setFolderAsWesternMangaAction->setText(tr("western manga (left to right)"));
- auto setFolderAsWebComicAction = new QAction();
+ auto setFolderAsWebComicAction = new QAction(menu);
setFolderAsWebComicAction->setText(tr("web comic"));
- auto setFolderAs4KomaAction = new QAction();
+ auto setFolderAs4KomaAction = new QAction(menu);
setFolderAs4KomaAction->setText(tr("4koma (top to botom)"));
- auto setFolderCoverAction = new QAction();
+ auto setFolderCoverAction = new QAction(menu);
setFolderCoverAction->setText(tr("Set custom cover"));
- auto deleteCustomFolderCoverAction = new QAction();
+ auto deleteCustomFolderCoverAction = new QAction(menu);
deleteCustomFolderCoverAction->setText(tr("Delete custom cover"));
- menu.addAction(openContainingFolderAction);
- menu.addAction(updateFolderAction);
- menu.addSeparator();
- menu.addAction(rescanLibraryForXMLInfoAction);
- menu.addSeparator();
+ menu->addAction(openContainingFolderAction);
+ menu->addAction(updateFolderAction);
+ menu->addSeparator();
+ menu->addAction(rescanLibraryForXMLInfoAction);
+ menu->addSeparator();
if (folder.completed)
- menu.addAction(setFolderAsNotCompletedAction);
+ menu->addAction(setFolderAsNotCompletedAction);
else
- menu.addAction(setFolderAsCompletedAction);
- menu.addSeparator();
+ menu->addAction(setFolderAsCompletedAction);
+ menu->addSeparator();
if (folder.finished)
- menu.addAction(setFolderAsUnreadAction);
+ menu->addAction(setFolderAsUnreadAction);
else
- menu.addAction(setFolderAsReadAction);
- menu.addSeparator();
+ menu->addAction(setFolderAsReadAction);
+ menu->addSeparator();
setFolderAsNormalAction->setCheckable(true);
setFolderAsMangaAction->setCheckable(true);
@@ -1728,16 +1758,14 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
break;
}
- auto typeMenu = new QMenu(tr("Set type"));
- menu.addMenu(typeMenu);
+ auto typeMenu = new QMenu(tr("Set type"), menu);
+ menu->addMenu(typeMenu);
typeMenu->addAction(setFolderAsNormalAction);
typeMenu->addAction(setFolderAsMangaAction);
typeMenu->addAction(setFolderAsWesternMangaAction);
typeMenu->addAction(setFolderAsWebComicAction);
typeMenu->addAction(setFolderAs4KomaAction);
- auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel();
-
connect(openContainingFolderAction, &QAction::triggered, this, [=]() {
QDesktopServices::openUrl(QUrl("file:///" + QDir::cleanPath(currentPath() + "/" + folder.path), QUrl::TolerantMode));
});
@@ -1749,39 +1777,30 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
});
connect(setFolderAsNotCompletedAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderCompletedStatus(QModelIndexList() << foldersModel->getIndexFromFolder(folder), false);
- subfolderModel->updateFolderCompletedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
});
connect(setFolderAsCompletedAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderCompletedStatus(QModelIndexList() << foldersModel->getIndexFromFolder(folder), true);
- subfolderModel->updateFolderCompletedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), true);
});
connect(setFolderAsReadAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModel->getIndexFromFolder(folder), true);
- subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), true);
});
connect(setFolderAsUnreadAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModel->getIndexFromFolder(folder), false);
- subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
});
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
- subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
});
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
- subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
});
connect(setFolderAsWesternMangaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
- subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
});
connect(setFolderAsWebComicAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
- subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
});
connect(setFolderAs4KomaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
- subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
});
connect(setFolderCoverAction, &QAction::triggered, this, [=]() {
setCustomFolderCover(folder);
@@ -1791,14 +1810,14 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
resetFolderCover(folder);
});
- menu.addSeparator();
+ menu->addSeparator();
- menu.addAction(setFolderCoverAction);
+ menu->addAction(setFolderCoverAction);
if (!folder.customImage.isEmpty()) {
- menu.addAction(deleteCustomFolderCoverAction);
+ menu->addAction(deleteCustomFolderCoverAction);
}
- menu.exec(contentViewsManager->folderContentView->mapToGlobal(point));
+ menu->popup(point);
}
void LibraryWindow::showContinueReadingContextMenu(QPoint point, ComicDB comic)
@@ -1820,10 +1839,10 @@ void LibraryWindow::showContinueReadingContextMenu(QPoint point, ComicDB comic)
info.lastTimeOpened = QVariant();
DBHelper::update(libraryId, info);
- contentViewsManager->folderContentView->reloadContinueReadingModel();
+ navigationController->reloadRootContinueReading();
});
- menu.exec(contentViewsManager->folderContentView->mapToGlobal(point));
+ menu.exec(point);
}
void LibraryWindow::setupAddToSubmenu(QMenu &menu)
@@ -1835,7 +1854,7 @@ void LibraryWindow::setupAddToSubmenu(QMenu &menu)
if (labels.count() > 0)
menu.addSeparator();
for (auto *label : labels) {
- auto action = new QAction(this);
+ auto action = new QAction(&menu);
action->setIcon(label->getIcon());
action->setText(label->name());
@@ -1894,21 +1913,14 @@ void LibraryWindow::checkMaxNumLibraries()
}
}
-void LibraryWindow::selectSubfolder(const QModelIndex &mi, int child)
-{
- QModelIndex dest = foldersModel->index(child, 0, mi);
- foldersView->setCurrentIndex(dest);
- navigationController->selectedFolder(dest);
-}
-
// this methods is only using after deleting comics
// TODO broken window :)
void LibraryWindow::checkEmptyFolder()
{
if (comicsModel->rowCount() > 0 && !importedCovers) {
- disableComicsActions(false);
+ setComicActionsDisabled(false);
} else {
- disableComicsActions(true);
+ setComicActionsDisabled(true);
#ifndef Q_OS_MACOS
if (comicsModel->rowCount() > 0)
actions.toggleFullScreenAction->setEnabled(true);
@@ -2009,7 +2021,7 @@ void LibraryWindow::reloadCurrentLibrary()
return;
foldersModel->reload();
- contentViewsManager->updateCurrentContentView();
+ navigationController->refreshCurrentSource();
enableNeededActions();
}
@@ -2556,11 +2568,11 @@ void LibraryWindow::setComicSearchFilterData(QList *data, const QSt
contentViewsManager->comicsView->setModel(comicsModel); // TODO, columns are messed up after ResetModel some times, this shouldn't be necesary
if (comicsModel->rowCount() == 0) {
- contentViewsManager->showNoSearchResultsView();
- disableComicsActions(true);
+ contentViewsManager->showNoSearchResults();
+ setComicActionsDisabled(true);
} else {
contentViewsManager->showComicsView();
- disableComicsActions(false);
+ setComicActionsDisabled(false);
}
}
@@ -2597,6 +2609,7 @@ void LibraryWindow::showProperties()
propertiesDialog->setComicsForSequentialEditing(index, comicsModel->getAllComics());
}
+ navigationController->beginCurrentSourceRefresh();
propertiesDialog->show();
}
@@ -2622,6 +2635,7 @@ void LibraryWindow::showComicVineScraper()
comicVineDialog->basePath = currentPath();
comicVineDialog->setComics(comics);
+ navigationController->beginCurrentSourceRefresh();
comicVineDialog->show();
}
}
@@ -2653,7 +2667,7 @@ void LibraryWindow::resetComicRating()
void LibraryWindow::checkSearchNumResults(int numResults)
{
if (numResults == 0)
- contentViewsManager->showNoSearchResultsView();
+ contentViewsManager->showNoSearchResults();
else
contentViewsManager->showComicsView();
}
@@ -2675,7 +2689,7 @@ void LibraryWindow::asignNumbers()
qint64 edited = comicsModel->asignNumbers(indexList, startingNumber);
// TODO add resorting without reloading
- navigationController->loadFolderInfo(foldersModelProxy->mapToSource(foldersView->currentIndex()));
+ navigationController->loadFolderContent(foldersModelProxy->mapToSource(foldersView->currentIndex()));
const QModelIndex &mi = comicsModel->getIndexFromId(edited);
if (mi.isValid()) {
@@ -2866,7 +2880,7 @@ void LibraryWindow::prepareToCloseApp()
settings->setValue(MAIN_WINDOW_GEOMETRY, saveGeometry());
settings->setValue(MAIN_WINDOW_STATE, saveState());
- contentViewsManager->comicsView->close();
+ contentViewsManager->prepareToClose();
sideBar->close();
QApplication::instance()->processEvents();
@@ -3118,7 +3132,7 @@ void LibraryWindow::updateViewsOnClientSync()
{
comicsModel->reload();
contentViewsManager->updateCurrentComicView();
- contentViewsManager->updateContinueReadingView();
+ navigationController->reloadRootContinueReading();
}
void LibraryWindow::updateViewsOnComicUpdateWithId(quint64 libraryId, quint64 comicId)
@@ -3149,7 +3163,7 @@ void LibraryWindow::updateViewsOnComicUpdate(quint64 libraryId, const ComicDB &c
if (libraryId == (quint64)libraries.getId(selectedLibrary->currentText())) {
comicsModel->reload(comic);
contentViewsManager->updateCurrentComicView();
- contentViewsManager->updateContinueReadingView();
+ navigationController->reloadRootContinueReading();
}
}
diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h
index c418d745d..7b6c5aad4 100644
--- a/YACReaderLibrary/library_window.h
+++ b/YACReaderLibrary/library_window.h
@@ -170,6 +170,8 @@ class LibraryWindow : public QMainWindow, protected Themable
QToolBar *treeActions;
QToolBar *comicsToolBar;
QToolBar *editInfoToolBar;
+ QList comicToolbarEntries;
+ QAction *comicToolbarEndAnchor = nullptr;
OptionsDialog *optionsDialog;
ServerConfigDialog *serverConfigDialog;
@@ -236,7 +238,6 @@ class LibraryWindow : public QMainWindow, protected Themable
void errorUpgradingLibrary(const QString &path);
public slots:
void loadLibrary(const QString &path);
- void selectSubfolder(const QModelIndex &mi, int child);
void checkEmptyFolder();
void openComic();
void openComic(const ComicDB &comic, const ComicModel::Mode mode);
@@ -338,7 +339,8 @@ public slots:
void reloadAfterCopyMove(const QModelIndex &mi);
QModelIndex getCurrentFolderIndex();
void enableNeededActions();
- void disableComicsActions(bool disabled);
+ void setComicActionsDisabled(bool disabled);
+ void setComicToolbarEntriesVisible(bool visible);
void addFolderToCurrentIndex();
void deleteSelectedFolder();
void errorDeletingFolder();
diff --git a/YACReaderLibrary/library_window_actions.cpp b/YACReaderLibrary/library_window_actions.cpp
index d6b634d20..2758e8d88 100644
--- a/YACReaderLibrary/library_window_actions.cpp
+++ b/YACReaderLibrary/library_window_actions.cpp
@@ -11,6 +11,7 @@
#include "yacreader_content_views_manager.h"
#include "yacreader_folders_view.h"
#include "yacreader_history_controller.h"
+#include "yacreader_navigation_controller.h"
#include "yacreader_options_dialog.h"
#include
@@ -427,6 +428,7 @@ void LibraryWindowActions::createActions(LibraryWindow *window, QSettings *setti
void LibraryWindowActions::createConnections(
YACReaderHistoryController *historyController,
+ YACReaderNavigationController *navigationController,
LibraryWindow *window,
HelpAboutDialog *had,
ExportLibraryDialog *exportLibraryDialog,
@@ -437,10 +439,8 @@ void LibraryWindowActions::createConnections(
ServerConfigDialog *serverConfigDialog,
RecentVisibilityCoordinator *recentVisibilityCoordinator)
{
- // history navigation
- QObject::connect(backAction, &QAction::triggered, historyController, &YACReaderHistoryController::backward);
- QObject::connect(forwardAction, &QAction::triggered, historyController, &YACReaderHistoryController::forward);
- //--
+ QObject::connect(backAction, &QAction::triggered, navigationController, &YACReaderNavigationController::backward);
+ QObject::connect(forwardAction, &QAction::triggered, navigationController, &YACReaderNavigationController::forward);
QObject::connect(historyController, &YACReaderHistoryController::enabledBackward, backAction, &QAction::setEnabled);
QObject::connect(historyController, &YACReaderHistoryController::enabledForward, forwardAction, &QAction::setEnabled);
// connect(foldersView, SIGNAL(clicked(QModelIndex)), historyController, SLOT(updateHistory(QModelIndex)));
@@ -678,37 +678,42 @@ void LibraryWindowActions::setUpShortcutsManagement(EditShortcutsDialog *editSho
ShortcutsManager::getShortcutsManager().registerActions(allActions);
}
-void LibraryWindowActions::disableComicsActions(bool disabled)
+void LibraryWindowActions::setComicActionsDisabled(bool disabled)
{
// if there aren't comics, no fullscreen option will be available
#ifndef Q_OS_MACOS
toggleFullScreenAction->setDisabled(disabled);
#endif
// edit toolbar
- openComicAction->setDisabled(disabled);
- editSelectedComicsAction->setDisabled(disabled);
+ setComicSelectionActionsEnabled(!disabled);
selectAllComicsAction->setDisabled(disabled);
- asignOrderAction->setDisabled(disabled);
- setAsReadAction->setDisabled(disabled);
- setAsNonReadAction->setDisabled(disabled);
- setNormalAction->setDisabled(disabled);
- setMangaAction->setDisabled(disabled);
- setWebComicAction->setDisabled(disabled);
- setWesternMangaAction->setDisabled(disabled);
- setYonkomaAction->setDisabled(disabled);
// setAllAsReadAction->setDisabled(disabled);
// setAllAsNonReadAction->setDisabled(disabled);
showHideMarksAction->setDisabled(disabled);
- deleteMetadataAction->setDisabled(disabled);
- deleteComicsAction->setDisabled(disabled);
- // context menu
- openContainingFolderComicAction->setDisabled(disabled);
- resetComicRatingAction->setDisabled(disabled);
-
- getInfoAction->setDisabled(disabled);
-
updateCurrentFolderAction->setDisabled(disabled);
}
+
+void LibraryWindowActions::setComicSelectionActionsEnabled(bool enabled)
+{
+ openComicAction->setEnabled(enabled);
+ saveCoversToAction->setEnabled(enabled);
+ editSelectedComicsAction->setEnabled(enabled);
+ asignOrderAction->setEnabled(enabled);
+ setAsReadAction->setEnabled(enabled);
+ setAsNonReadAction->setEnabled(enabled);
+ setNormalAction->setEnabled(enabled);
+ setMangaAction->setEnabled(enabled);
+ setWebComicAction->setEnabled(enabled);
+ setWesternMangaAction->setEnabled(enabled);
+ setYonkomaAction->setEnabled(enabled);
+ deleteMetadataAction->setEnabled(enabled);
+ deleteComicsAction->setEnabled(enabled);
+ openContainingFolderComicAction->setEnabled(enabled);
+ resetComicRatingAction->setEnabled(enabled);
+ getInfoAction->setEnabled(enabled);
+ addToMenuAction->setEnabled(enabled);
+ addToFavoritesAction->setEnabled(enabled);
+}
void LibraryWindowActions::disableLibrariesActions(bool disabled)
{
updateLibraryAction->setDisabled(disabled);
@@ -750,7 +755,7 @@ void LibraryWindowActions::disableFoldersActions(bool disabled)
void LibraryWindowActions::disableAllActions()
{
- disableComicsActions(true);
+ setComicActionsDisabled(true);
disableLibrariesActions(true);
disableFoldersActions(true);
}
diff --git a/YACReaderLibrary/library_window_actions.h b/YACReaderLibrary/library_window_actions.h
index 4c60580ff..60d45ce29 100644
--- a/YACReaderLibrary/library_window_actions.h
+++ b/YACReaderLibrary/library_window_actions.h
@@ -8,6 +8,7 @@
class LibraryWindow;
class YACReaderHistoryController;
+class YACReaderNavigationController;
class EditShortcutsDialog;
class HelpAboutDialog;
class ExportLibraryDialog;
@@ -127,6 +128,7 @@ class LibraryWindowActions
LibraryWindowActions();
void createActions(LibraryWindow *window, QSettings *settings);
void createConnections(YACReaderHistoryController *historyController,
+ YACReaderNavigationController *navigationController,
LibraryWindow *window,
HelpAboutDialog *had,
ExportLibraryDialog *exportLibraryDialog,
@@ -137,7 +139,8 @@ class LibraryWindowActions
ServerConfigDialog *serverConfigDialog,
RecentVisibilityCoordinator *recentVisibilityCoordinator);
- void disableComicsActions(bool disabled);
+ void setComicActionsDisabled(bool disabled);
+ void setComicSelectionActionsEnabled(bool enabled);
void disableLibrariesActions(bool disabled);
void disableNoUpdatedLibrariesActions(bool disabled);
void disableFoldersActions(bool disabled);
diff --git a/YACReaderLibrary/options_dialog.cpp b/YACReaderLibrary/options_dialog.cpp
index b3c68b757..125d9f3d4 100644
--- a/YACReaderLibrary/options_dialog.cpp
+++ b/YACReaderLibrary/options_dialog.cpp
@@ -90,6 +90,9 @@ void OptionsDialog::restoreOptions(QSettings *settings)
displayGlobalContinueReadingBannerCheck->setChecked(settings->value(DISPLAY_GLOBAL_CONTINUE_READING_IN_GRID_VIEW, true).toBool());
displayContinueReadingBannerCheck->setChecked(settings->value(DISPLAY_CONTINUE_READING_IN_GRID_VIEW, true).toBool());
+ mixFoldersAndComicsCheck->setChecked(settings->value(COMICS_GRID_MIX_FOLDERS_AND_COMICS, true).toBool());
+ startComicsOnNewRowCheck->setChecked(settings->value(COMICS_GRID_START_COMICS_ON_NEW_ROW, false).toBool());
+ startComicsOnNewRowCheck->setEnabled(mixFoldersAndComicsCheck->isChecked());
updateLibrariesAtStartupCheck->setChecked(settings->value(UPDATE_LIBRARIES_AT_STARTUP, false).toBool());
detectChangesAutomaticallyCheck->setChecked(settings->value(DETECT_CHANGES_IN_LIBRARIES_AUTOMATICALLY, false).toBool());
@@ -421,6 +424,16 @@ QWidget *OptionsDialog::createGridTab()
auto continueReadingGroup = new QGroupBox(tr("Continue reading"));
continueReadingGroup->setLayout(continueReadingLayout);
+ mixFoldersAndComicsCheck = new QCheckBox(tr("Mix folders and comics"));
+ startComicsOnNewRowCheck = new QCheckBox(tr("Start comics on a new row"));
+
+ auto gridContentLayout = new QVBoxLayout();
+ gridContentLayout->addWidget(mixFoldersAndComicsCheck);
+ gridContentLayout->addWidget(startComicsOnNewRowCheck);
+
+ auto gridContentGroup = new QGroupBox(tr("Content"));
+ gridContentGroup->setLayout(gridContentLayout);
+
connect(useBackgroundImageCheck, &QAbstractButton::clicked, this, &OptionsDialog::useBackgroundImageCheckClicked);
connect(backgroundImageOpacitySlider, &QAbstractSlider::valueChanged, this, &OptionsDialog::backgroundImageOpacitySliderChanged);
connect(backgroundImageBlurRadiusSlider, &QAbstractSlider::valueChanged, this, &OptionsDialog::backgroundImageBlurRadiusSliderChanged);
@@ -440,8 +453,20 @@ QWidget *OptionsDialog::createGridTab()
emit optionsChanged();
});
+ connect(mixFoldersAndComicsCheck, &QCheckBox::clicked, this, [this](bool checked) {
+ settings->setValue(COMICS_GRID_MIX_FOLDERS_AND_COMICS, checked);
+ startComicsOnNewRowCheck->setEnabled(checked);
+ emit optionsChanged();
+ });
+
+ connect(startComicsOnNewRowCheck, &QCheckBox::clicked, this, [this](bool checked) {
+ settings->setValue(COMICS_GRID_START_COMICS_ON_NEW_ROW, checked);
+ emit optionsChanged();
+ });
+
auto gridViewLayout = new QVBoxLayout();
gridViewLayout->addWidget(gridBackgroundGroup);
+ gridViewLayout->addWidget(gridContentGroup);
gridViewLayout->addWidget(continueReadingGroup);
gridViewLayout->addStretch();
diff --git a/YACReaderLibrary/options_dialog.h b/YACReaderLibrary/options_dialog.h
index 017a3ced1..d1b4af090 100644
--- a/YACReaderLibrary/options_dialog.h
+++ b/YACReaderLibrary/options_dialog.h
@@ -63,6 +63,8 @@ private slots:
QLabel *opacityLabel;
QLabel *blurLabel;
QPushButton *resetButton;
+ QCheckBox *mixFoldersAndComicsCheck;
+ QCheckBox *startComicsOnNewRowCheck;
QWidget *createGeneralTab();
QWidget *createLibrariesTab();
diff --git a/YACReaderLibrary/properties_dialog.cpp b/YACReaderLibrary/properties_dialog.cpp
index 0d900ca9b..09fd20682 100644
--- a/YACReaderLibrary/properties_dialog.cpp
+++ b/YACReaderLibrary/properties_dialog.cpp
@@ -1061,7 +1061,6 @@ void PropertiesDialog::saveAndClose()
updateComics();
close();
- emit accepted();
}
void PropertiesDialog::setDisableUniqueValues(bool disabled)
diff --git a/YACReaderLibrary/qml/ComicGridDelegate.qml b/YACReaderLibrary/qml/ComicGridDelegate.qml
new file mode 100644
index 000000000..d0daae547
--- /dev/null
+++ b/YACReaderLibrary/qml/ComicGridDelegate.qml
@@ -0,0 +1,305 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Basic
+import QtQuick.Controls.impl
+
+// Delegate for GridContentModel comic rows; required properties intentionally match its role names.
+Rectangle {
+ id: cell
+
+ required property int index
+ required property int source_index
+ required property var number
+ required property string title
+ required property int num_pages
+ required property bool read_column
+ required property int current_page
+ required property int rating
+ required property bool has_been_opened
+ required property url cover_path
+ required property double added_date
+ required property bool show_recent
+ required property double recent_range
+
+ required property int currentViewIndex
+ required property var selectionHelper
+
+ readonly property int selectionRevision: selectionHelper.selectionRevision
+ readonly property bool selected: selectionRevision >= 0 && selectionHelper.isSelectedIndex(source_index)
+
+ property alias interactionItem: realCell
+
+ signal activateRequested(int viewRow)
+ signal clearFolderFocusRequested()
+ signal contextMenuRequested(point localPosition)
+ signal focusViewRowRequested(int viewRow)
+ signal rateRequested(int sourceRow, int rating)
+ signal selectRangeRequested(int from, int to)
+ signal setCurrentViewRowRequested(int viewRow)
+ signal setCurrentComicRowRequested(int sourceRow)
+ signal startDragRequested()
+
+ color: "transparent"
+ scale: mouseArea.containsMouse ? 1.025 : 1
+
+ Behavior on scale { NumberAnimation { duration: 90 } }
+
+ BorderImage {
+ anchors {
+ top: realCell.top
+ left: realCell.left
+ right: realCell.right
+ bottom: realCell.bottom
+ margins: -10
+ }
+ border { left: 10; top: 10; right: 10; bottom: 10 }
+ horizontalTileMode: BorderImage.Stretch
+ verticalTileMode: BorderImage.Stretch
+ source: "prerendered_cover_shadow.png"
+ visible: showDropShadow
+ }
+
+ Rectangle {
+ id: realCell
+
+ property bool dragging: false
+
+ Drag.active: mouseArea.drag.active
+ Drag.hotSpot.x: 32
+ Drag.hotSpot.y: 32
+ Drag.dragType: Drag.Automatic
+ Drag.proposedAction: Qt.CopyAction
+ Drag.onActiveChanged: {
+ if (!dragging) {
+ cell.startDragRequested()
+ dragging = true
+ } else {
+ dragging = false
+ }
+ }
+
+ width: itemWidth
+ height: itemHeight
+ color: cell.selected ? cellSelectedColor : cellColor
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Rectangle {
+ z: -1
+ color: "transparent"
+ anchors {
+ fill: parent
+ margins: -2
+ }
+ border.color: cellSelectedBorderColor
+ border.width: 3
+ opacity: cell.selected ? 1 : 0
+ radius: 2
+
+ Behavior on opacity { NumberAnimation { duration: 300 } }
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ drag.target: realCell
+ drag.minimumX: 0
+ drag.maximumX: 0
+ drag.minimumY: 0
+ drag.maximumY: 0
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: true
+
+ onDoubleClicked: {
+ cell.selectionHelper.selectOnly(cell.source_index)
+ cell.setCurrentViewRowRequested(cell.index)
+ cell.activateRequested(cell.index)
+ }
+
+ onPressed: mouse => {
+ const currentIndex = cell.currentViewIndex
+ cell.clearFolderFocusRequested()
+
+ if (mouse.modifiers & Qt.ShiftModifier) {
+ if (cell.index < currentIndex) {
+ cell.selectRangeRequested(cell.index, currentIndex)
+ cell.setCurrentViewRowRequested(cell.index)
+ } else if (cell.index > currentIndex) {
+ cell.selectRangeRequested(currentIndex, cell.index)
+ cell.setCurrentViewRowRequested(cell.index)
+ }
+ }
+
+ mouse.accepted = true
+
+ if (mouse.button === Qt.RightButton) {
+ if (!cell.selectionHelper.isSelectedIndex(cell.source_index))
+ cell.focusViewRowRequested(cell.index)
+
+ cell.contextMenuRequested(Qt.point(mouseX, mouseY))
+ mouse.accepted = false
+ } else {
+ if (mouse.modifiers & Qt.ControlModifier) {
+ if (cell.selectionHelper.isSelectedIndex(cell.source_index)) {
+ if (cell.selectionHelper.numItemsSelected() > 1) {
+ cell.selectionHelper.deselectIndex(cell.source_index)
+ if (cell.currentViewIndex === cell.index)
+ cell.setCurrentComicRowRequested(cell.selectionHelper.lastSelectedIndex())
+ }
+ } else {
+ cell.selectionHelper.selectIndex(cell.source_index)
+ cell.setCurrentViewRowRequested(cell.index)
+ }
+ }
+
+ if (!(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) {
+ if (!cell.selectionHelper.isSelectedIndex(cell.source_index))
+ cell.focusViewRowRequested(cell.index)
+
+ cell.setCurrentViewRowRequested(cell.index)
+ }
+ }
+ }
+
+ onReleased: mouse => {
+ if (mouse.button === Qt.LeftButton
+ && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)
+ && cell.selectionHelper.isSelectedIndex(cell.source_index)) {
+ cell.focusViewRowRequested(cell.index)
+ }
+ }
+ }
+ }
+
+ Image {
+ id: coverElement
+ width: coverWidth
+ height: coverHeight
+ anchors { horizontalCenter: parent.horizontalCenter; top: realCell.top }
+ source: cell.cover_path
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ mipmap: true
+ asynchronous: true
+ cache: false
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ radius: 5
+ anchors { left: coverElement.left; top: coverElement.top; topMargin: 5; leftMargin: 5 }
+ color: newItemColor
+ visible: (((new Date() / 1000) - cell.added_date) < cell.recent_range) && cell.show_recent
+ }
+
+ Rectangle {
+ width: coverElement.width
+ height: coverElement.height
+ anchors { horizontalCenter: parent.horizontalCenter; top: realCell.top }
+ color: "transparent"
+ border { color: comicCoverBorderColor; width: 1 }
+ }
+
+ Image {
+ width: 23
+ height: 23
+ source: cell.read_column && show_marks ? "tick.svg"
+ : cell.has_been_opened && show_marks ? "reading.svg" : ""
+ anchors { right: coverElement.right; top: coverElement.top; topMargin: 9; rightMargin: 9 }
+ asynchronous: true
+ }
+
+ Text {
+ anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 4 }
+ width: itemWidth - 8
+ maximumLineCount: 2
+ wrapMode: Text.WordWrap
+ text: cell.title
+ elide: Text.ElideRight
+ color: itemTitleColor
+ clip: true
+ font.letterSpacing: fontSpacing
+ font.pointSize: fontSize
+ font.family: fontFamily
+ }
+
+ Text {
+ anchors { bottom: realCell.bottom; left: realCell.left; margins: 4 }
+ text: cell.number ? "#" + cell.number : ""
+ color: itemDetailsColor
+ font.letterSpacing: fontSpacing
+ font.pointSize: fontSize
+ font.family: fontFamily
+ }
+
+ ColorImage {
+ id: pageImage
+ anchors { bottom: realCell.bottom; right: realCell.right; bottomMargin: 6; rightMargin: 4; leftMargin: 4 }
+ source: "page.svg"
+ color: itemDetailsColor
+ width: 8
+ height: 10
+ }
+
+ Text {
+ id: pages
+ anchors { bottom: realCell.bottom; right: pageImage.left; margins: 4 }
+ text: cell.has_been_opened ? cell.current_page + "/" + cell.num_pages : cell.num_pages
+ color: itemDetailsColor
+ font.letterSpacing: fontSpacing
+ font.pointSize: fontSize
+ font.family: fontFamily
+ }
+
+ ColorImage {
+ id: ratingImage
+ anchors { bottom: realCell.bottom; right: pageImage.left; bottomMargin: 6.5; rightMargin: Math.floor(pages.width) + 12 }
+ source: "star.svg"
+ color: itemDetailsColor
+ width: 11
+ height: 11
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ cell.selectionHelper.selectOnly(cell.source_index)
+ cell.setCurrentViewRowRequested(cell.index)
+ ratingLoader.active = true
+ ratingLoader.item.popup()
+ }
+ }
+
+ Loader {
+ id: ratingLoader
+ active: false
+ sourceComponent: ratingContextMenuComponent
+ }
+
+ Component {
+ id: ratingContextMenuComponent
+ Menu {
+ background: Rectangle {
+ implicitWidth: 42
+ implicitHeight: 100
+ }
+
+ Action { text: "1"; onTriggered: cell.rateRequested(cell.source_index, 1) }
+ Action { text: "2"; onTriggered: cell.rateRequested(cell.source_index, 2) }
+ Action { text: "3"; onTriggered: cell.rateRequested(cell.source_index, 3) }
+ Action { text: "4"; onTriggered: cell.rateRequested(cell.source_index, 4) }
+ Action { text: "5"; onTriggered: cell.rateRequested(cell.source_index, 5) }
+
+ delegate: MenuItem { implicitHeight: 30 }
+ }
+ }
+ }
+
+ Text {
+ anchors { bottom: realCell.bottom; right: ratingImage.left; margins: 4 }
+ text: cell.rating > 0 ? cell.rating : "-"
+ color: itemDetailsColor
+ }
+}
diff --git a/YACReaderLibrary/qml/ContinueReadingGridHeader.qml b/YACReaderLibrary/qml/ContinueReadingGridHeader.qml
new file mode 100644
index 000000000..cfc35923a
--- /dev/null
+++ b/YACReaderLibrary/qml/ContinueReadingGridHeader.qml
@@ -0,0 +1,120 @@
+import QtQuick
+
+Rectangle {
+ id: header
+
+ required property var contentModel
+ required property bool sectionVisible
+
+ signal openRequested(int index)
+ signal contextMenuRequested(int index, point position)
+
+ readonly property int sectionHeight: 430
+ readonly property int topMargin: 20
+
+ color: "transparent"
+ height: list.count > 0 && sectionVisible ? sectionHeight : topMargin
+
+ Rectangle {
+ width: header.width
+ height: header.sectionHeight - header.topMargin
+ visible: list.count > 0 && header.sectionVisible
+ color: continueReadingBackgroundColor
+
+ Text {
+ id: heading
+ text: qsTr("Continue Reading...")
+ color: continueReadingTextColor
+ anchors { left: parent.left; top: parent.top; topMargin: 15; leftMargin: 25 }
+ font.pointSize: 18
+ font.weight: Font.DemiBold
+ }
+
+ ListView {
+ id: list
+ objectName: "continueReadingList"
+ anchors {
+ top: heading.bottom
+ left: parent.left
+ right: parent.right
+ bottom: parent.bottom
+ topMargin: 15
+ bottomMargin: 20
+ leftMargin: 25
+ rightMargin: 20
+ }
+ orientation: Qt.Horizontal
+ pixelAligned: true
+ model: header.contentModel
+ spacing: 20
+ property int verticalPadding: 20
+
+ WheelHandler {
+ onWheel: event => {
+ if (list.contentWidth <= list.width)
+ return
+ list.contentX = Math.min(list.contentWidth - list.width - list.anchors.leftMargin,
+ Math.max(list.originX, list.contentX - event.angleDelta.y))
+ }
+ }
+
+ delegate: Rectangle {
+ width: Math.floor((list.height - (list.verticalPadding * 2)) * 0.65)
+ height: list.height - (list.verticalPadding * 2)
+ color: "transparent"
+ scale: mouseArea.containsMouse ? 1.025 : 1
+ Behavior on scale { NumberAnimation { duration: 90 } }
+
+ Image {
+ id: cover
+ anchors.fill: parent
+ source: cover_path
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ mipmap: true
+ asynchronous: true
+ cache: true
+ }
+
+ Text {
+ anchors { top: cover.bottom; left: cover.left; right: cover.right; leftMargin: 4; rightMargin: 4; topMargin: 4 }
+ maximumLineCount: 2
+ wrapMode: Text.WordWrap
+ text: readable_title
+ elide: Text.ElideRight
+ color: itemTitleColor
+ font.letterSpacing: fontSpacing
+ font.pointSize: fontSize
+ font.family: fontFamily
+ }
+
+ Rectangle {
+ anchors.fill: cover
+ color: "transparent"
+ border.color: comicCoverBorderColor
+ border.width: 1
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: true
+
+ onDoubleClicked: {
+ list.currentIndex = index
+ header.openRequested(index)
+ }
+ onReleased: mouse => {
+ list.currentIndex = index
+ if (mouse.button === Qt.RightButton) {
+ var position = header.mapFromItem(cover, mouseX, mouseY)
+ header.contextMenuRequested(index, Qt.point(position.x, position.y))
+ }
+ mouse.accepted = true
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/YACReaderLibrary/qml/EmptyInfoView.qml b/YACReaderLibrary/qml/EmptyInfoView.qml
new file mode 100644
index 000000000..af85f581e
--- /dev/null
+++ b/YACReaderLibrary/qml/EmptyInfoView.qml
@@ -0,0 +1,40 @@
+import QtQuick
+import QtQuick.Layouts
+
+Rectangle {
+ id: root
+
+ color: "transparent"
+ height: 240
+
+ ColumnLayout {
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: parent.top
+ margins: 30
+ }
+ spacing: 8
+
+ Text {
+ Layout.fillWidth: true
+ text: qsTr("Nothing selected")
+ color: infoTextColor
+ font.family: "Arial"
+ font.bold: true
+ font.pixelSize: 21
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: qsTr("Select a comic or folder to see its information.")
+ color: infoMetadataTextColor
+ font.family: "Arial"
+ font.pixelSize: 14
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+}
diff --git a/YACReaderLibrary/qml/FlowView.qml b/YACReaderLibrary/qml/FlowView.qml
index 5038ba001..8e5f95376 100644
--- a/YACReaderLibrary/qml/FlowView.qml
+++ b/YACReaderLibrary/qml/FlowView.qml
@@ -99,6 +99,16 @@ Rectangle {
highlightMoveDuration: 250
+ function restoreCurrentIndex(index) {
+ const previousDuration = highlightMoveDuration
+ highlightMoveDuration = 0
+ currentIndex = index
+ positionViewAtIndex(index, ListView.SnapPosition)
+ Qt.callLater(function() {
+ list.highlightMoveDuration = previousDuration
+ })
+ }
+
onCurrentIndexChanged: currentIndex => {
if (list.currentIndex !== -1) {
mainFlowContainer.currentCoverChanged(list.currentIndex);
diff --git a/YACReaderLibrary/qml/FolderContentView.qml b/YACReaderLibrary/qml/FolderContentView.qml
deleted file mode 100644
index cceea9adf..000000000
--- a/YACReaderLibrary/qml/FolderContentView.qml
+++ /dev/null
@@ -1,482 +0,0 @@
-import QtQuick
-
-import QtQuick.Controls
-import QtQuick.Layouts
-
-import QtQuick.Effects
-
-import com.yacreader.ComicModel 1.0
-
-import com.yacreader.ComicInfo 1.0
-import com.yacreader.ComicDB 1.0
-
-import QtQuick.Controls.Basic
-
-Rectangle {
- id: main
-
- property int continuReadingHeight: 430;
- property int topContentMargin: 20;
-
- color: backgroundColor
- anchors.margins: 0
-
- Component {
- id: appDelegate
- Rectangle
- {
- id: cell
- width: grid.cellWidth
- height: grid.cellHeight
- color: "#00000000"
-
- scale: mouseArea.containsMouse ? 1.025 : 1
-
- Behavior on scale {
- NumberAnimation { duration: 90 }
- }
-
- Rectangle {
- id: realCell
-
- property int position : 0
-
- width: itemWidth
- height: itemHeight
-
- color: "transparent"
- anchors.horizontalCenter: parent.horizontalCenter
-
- MouseArea {
- id: mouseArea
-
- anchors.fill: parent
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- hoverEnabled: true
-
- onDoubleClicked: {
- openHelper.openFolder(index);
- }
-
- onPressed: mouse => {
- var ci = grid.currentIndex; //save current index
-
- mouse.accepted = true;
-
- if(mouse.button === Qt.RightButton) // context menu is requested
- {
- var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
- contextMenuHelper.requestedFolderContextMenu(Qt.point(coordinates.x,coordinates.y), index);
- mouse.accepted = false;
-
- }
- }
-
- }
- }
-
- /**/
-
- Rectangle {
- transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: -4}
- width: coverElement.width
- height: coverElement.height
- radius: 10
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- color: placeholderFolder1Color
- border {
- color: placeholderFolder1BorderColor
- width: 1
- }
- }
-
- Rectangle {
- transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: 3}
- width: coverElement.width
- height: coverElement.height
- radius: 10
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- color: placeholderFolder2Color
- border {
- color: placeholderFolder2BorderColor
- width: 1
- }
- }
-
- Item {
- width: coverWidth
- height: coverHeight
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- id: coverElement
-
- Image {
- id: coverImage
- anchors.fill: parent
- source: cover_path
- fillMode: Image.PreserveAspectCrop
- smooth: true
- mipmap: true
- asynchronous : true
- cache: true
- visible: false
- }
-
- Item {
- id: coverMask
- anchors.fill: parent
- layer.enabled: true
- layer.smooth: true
- visible: false
-
- Rectangle {
- anchors.fill: parent
- radius: 10
- color: "black"
- }
- }
-
- MultiEffect {
- source: coverImage
- anchors.fill: coverImage
- maskEnabled: true
- maskSource: coverMask
- maskThresholdMin: 0.5
- maskSpreadAtMin: 1.0
- }
- }
-
- //is new
- Rectangle {
- width: 10
- height: 10
- radius: 5
- anchors { left: coverElement.left; top: coverElement.top; topMargin: 10; leftMargin: 10; }
- color: newItemColor
- visible: (((new Date() / 1000) - added) < recent_range || ((new Date() / 1000) - updated) < recent_range) && show_recent
- }
-
- //border
- Rectangle {
- width: coverElement.width
- height: coverElement.height
- radius: 10
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- color: "transparent"
- border {
- color: folderCoverBorderColor
- width: 1
- }
- }
-
- //folder name
- Text {
- id : titleText
- anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 10; }
- width: itemWidth - 8
- maximumLineCount: 2
- wrapMode: Text.WordWrap
- text: name
- elide: Text.ElideRight
- color: itemTitleColor
- font.letterSpacing: fontSpacing
- font.pointSize: fontSize
- font.family: fontFamily
- }
- }
- }
-
- Rectangle {
- id: scrollView
- objectName: "topScrollView"
- anchors.fill: parent
- anchors.margins: 0
- children: grid
-
- color: "transparent"
-
- function scrollToOrigin() {
- grid.contentY = grid.originY
- grid.contentX = grid.originX
- }
-
- property Component continueReadingView: Component {
- id: continueReadingView
- Rectangle {
- id: continueReadingTopView
- color: "#00000000"
-
- height: list.count > 0 && showContinueReading ? main.continuReadingHeight : main.topContentMargin
-
- Rectangle {
- color: continueReadingBackgroundColor
-
- id: continueReadingBackground
-
- width: main.width
- height: main.continuReadingHeight - main.topContentMargin
-
- visible: list.count > 0 && showContinueReading
-
- Text {
- id: continueReadingText
- text: qsTr("Continue Reading...")
- color: continueReadingTextColor
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.topMargin: 15
- anchors.bottomMargin: 20
- anchors.leftMargin: 25
- anchors.rightMargin: 0
- font.pointSize: 18
- font.weight: Font.DemiBold
- }
-
- ListView {
- id: list
- objectName: "list"
- anchors { top: continueReadingText.bottom; left: parent.left; right: parent.right; bottom: parent.bottom; }
-
- property int previousIndex;
- property int verticalPadding: 20
-
- orientation: Qt.Horizontal
- pixelAligned: true
-
- model: comicsList
-
- spacing: 20
- anchors.topMargin: 15
- anchors.bottomMargin: 20
- anchors.leftMargin: 25
- anchors.rightMargin: 20
-
- WheelHandler {
- onWheel: event => {
- if (list.contentWidth <= list.width) {
- return;
- }
-
- var newValue = Math.min(list.contentWidth - list.width - anchors.leftMargin, (Math.max(list.originX , list.contentX - event.angleDelta.y)));
- list.contentX = newValue
- }
- }
-
- delegate: Component {
-
- //cover
- Rectangle {
- width: Math.floor((list.height - (list.verticalPadding * 2)) * 0.65);
- height: list.height - (list.verticalPadding * 2);
-
- color:"transparent"
-
- scale: mouseArea.containsMouse ? 1.025 : 1
-
- Behavior on scale {
- NumberAnimation { duration: 90 }
- }
-
- Image {
- id: coverElement
- anchors.fill: parent
- source: cover_path
- fillMode: Image.PreserveAspectCrop
- smooth: true
- mipmap: true
- asynchronous : true
- cache: true
- }
-
- //title
- Text {
- id : comicTitleText
- anchors { top: coverElement.bottom; left: coverElement.left; right: coverElement.right; leftMargin: 4; rightMargin: 4; topMargin: 4; }
- width: itemWidth - 8
- maximumLineCount: 2
- wrapMode: Text.WordWrap
- text: readable_title
- elide: Text.ElideRight
- color: itemTitleColor
- font.letterSpacing: fontSpacing
- font.pointSize: fontSize
- font.family: fontFamily
- }
-
- //border
- Rectangle {
- width: coverElement.width
- height: coverElement.height
- anchors.centerIn: coverElement
- color: "transparent"
- border {
- color: comicCoverBorderColor
- width: 1
- }
- }
-
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- hoverEnabled: true
-
- onDoubleClicked: {
- list.currentIndex = index;
- openHelper.openComicFromContinueReadingList(index);
- }
-
- onReleased: mouse => {
- list.currentIndex = index;
-
- if(mouse.button === Qt.RightButton) // context menu is requested
- {
- var coordinates = main.mapFromItem(coverElement,mouseX,mouseY)
- contextMenuHelper.requestedContinueReadingComicContextMenu(Qt.point(coordinates.x,coordinates.y), index);
- }
-
- mouse.accepted = true;
- }
- }
- }
- }
-
- focus: true
- }
- }
- }
- }
-
- GridView {
- id:grid
- objectName: "grid"
- anchors.fill: parent
- cellHeight: cellCustomHeight
- header: continueReadingView
- focus: true
- model: foldersList
- delegate: appDelegate
- anchors.topMargin: 0
- anchors.bottomMargin: 10
- anchors.leftMargin: 0
- anchors.rightMargin: 0
- pixelAligned: true
- highlightFollowsCurrentItem: true
-
- currentIndex: 0
- cacheBuffer: 0
-
- interactive: true
-
- move: Transition {
- NumberAnimation { properties: "x,y"; duration: 250 }
- }
-
- moveDisplaced: Transition {
- NumberAnimation { properties: "x,y"; duration: 250 }
- }
-
- remove: Transition {
- ParallelAnimation {
- NumberAnimation { property: "opacity"; to: 0; duration: 250 }
-
- }
- }
-
- removeDisplaced: Transition {
- NumberAnimation { properties: "x,y"; duration: 250 }
- }
-
- displaced: Transition {
- NumberAnimation { properties: "x,y"; duration: 250 }
- }
-
- function numCellsPerRow() {
- return Math.floor(width / cellCustomWidth);
- }
-
- onWidthChanged: {
- calculateCellWidths(cellCustomWidth);
- }
-
- function calculateCellWidths(cWidth) {
- var wholeCells = Math.floor(width / cWidth);
- var rest = width - (cWidth * wholeCells)
-
- grid.cellWidth = cWidth + Math.floor(rest / wholeCells);
- }
-
- WheelHandler {
- onWheel: event => {
- if (grid.contentHeight <= grid.height) {
- return;
- }
-
- var newValue = Math.min((grid.contentHeight - grid.height + grid.originY), (Math.max(grid.originY , grid.contentY - event.angleDelta.y)));
- grid.contentY = newValue;
- }
- }
-
- ScrollBar.vertical: ScrollBar {
- visible: grid.contentHeight > grid.height
-
- contentItem: Item {
- implicitWidth: 12
- implicitHeight: 26
- Rectangle {
- color: scrollbarColor
- anchors.fill: parent
- anchors.topMargin: 6
- anchors.leftMargin: 3
- anchors.rightMargin: 2
- anchors.bottomMargin: 6
- border.color: scrollbarBorderColor
- border.width: 1
- radius: 3.5
- }
- }
- }
-
- DropArea {
- anchors.fill: parent
-
- onEntered: drag => {
- if(drag.hasUrls)
- {
- if(dropManager.canDropUrls(drag.urls, drag.action))
- {
- drag.accepted = true;
- }else
- drag.accepted = false;
- }
- else if (dropManager.canDropFormats(drag.formats)) {
- drag.accepted = true;
- } else
- drag.accepted = false;
- }
-
- onDropped: drop => {
- if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action))
- {
- dropManager.droppedFiles(drop.urls, drop.action);
- }
- else{
- if (dropManager.canDropFormats(drop.formats))
- {
- var destItem = grid.itemAt(drop.x,drop.y + grid.contentY);
- var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x
- var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY);
-
- if(realIndex === -1)
- realIndex = grid.count - 1;
-
- var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1;
- dropManager.droppedComicsForResortingAt("", destIndex);
- }
- }
- }
- }
- }
- }
-}
diff --git a/YACReaderLibrary/qml/FolderCover.qml b/YACReaderLibrary/qml/FolderCover.qml
new file mode 100644
index 000000000..d72cc1034
--- /dev/null
+++ b/YACReaderLibrary/qml/FolderCover.qml
@@ -0,0 +1,105 @@
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: root
+
+ required property url coverSource
+ property bool selected: false
+ property bool showRecentIndicator: false
+ property bool showFinishedMark: false
+ property real cornerRadius: 10
+
+ Rectangle {
+ anchors.fill: parent
+ transform: Rotation { origin.x: root.width / 2; origin.y: root.height / 2; angle: -4 }
+ radius: root.cornerRadius
+ color: placeholderFolder1Color
+ border.color: placeholderFolder1BorderColor
+ border.width: 1
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ transform: Rotation { origin.x: root.width / 2; origin.y: root.height / 2; angle: 3 }
+ radius: root.cornerRadius
+ color: placeholderFolder2Color
+ border.color: placeholderFolder2BorderColor
+ border.width: 1
+ }
+
+ Image {
+ id: coverImage
+ anchors.fill: parent
+ source: root.coverSource
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ mipmap: true
+ asynchronous: true
+ cache: true
+ visible: false
+ }
+
+ Item {
+ id: coverMask
+ anchors.fill: parent
+ layer.enabled: true
+ layer.smooth: true
+ visible: false
+
+ Rectangle {
+ anchors.fill: parent
+ radius: root.cornerRadius
+ color: "black"
+ }
+ }
+
+ MultiEffect {
+ anchors.fill: coverImage
+ source: coverImage
+ maskEnabled: true
+ maskSource: coverMask
+ maskThresholdMin: 0.5
+ maskSpreadAtMin: 1.0
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ radius: root.cornerRadius
+ color: "transparent"
+ border.color: folderCoverBorderColor
+ border.width: 1
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ radius: 5
+ anchors { left: parent.left; top: parent.top; topMargin: 10; leftMargin: 10 }
+ color: newItemColor
+ visible: root.showRecentIndicator
+ }
+
+ Image {
+ z: 2
+ width: 23
+ height: 23
+ source: "tick.svg"
+ visible: root.showFinishedMark
+ anchors { right: parent.right; top: parent.top; topMargin: 9; rightMargin: 9 }
+ asynchronous: true
+ }
+
+ Rectangle {
+ z: 2
+ anchors.fill: parent
+ anchors.margins: -3
+ radius: root.cornerRadius + 3
+ color: "transparent"
+ border.color: cellSelectedBorderColor
+ border.width: 3
+ opacity: root.selected ? 1 : 0
+
+ Behavior on opacity { NumberAnimation { duration: 150 } }
+ }
+}
diff --git a/YACReaderLibrary/qml/FolderGridDelegate.qml b/YACReaderLibrary/qml/FolderGridDelegate.qml
new file mode 100644
index 000000000..b62c92cee
--- /dev/null
+++ b/YACReaderLibrary/qml/FolderGridDelegate.qml
@@ -0,0 +1,78 @@
+import QtQuick
+
+// Delegate for GridContentModel folder rows; required properties intentionally match its role names.
+Rectangle {
+ id: cell
+
+ required property int index
+ required property string title
+ required property url cover_path
+ required property double added_date
+ required property double updated
+ required property double recent_range
+ required property bool show_recent
+ required property bool is_finished
+ required property bool selected
+
+ signal openRequested()
+ signal contextMenuRequested(point localPosition)
+ signal focusRequested()
+
+ property alias interactionItem: realCell
+
+ color: "transparent"
+
+ scale: mouseArea.containsMouse ? 1.025 : 1
+ Behavior on scale { NumberAnimation { duration: 90 } }
+
+ Rectangle {
+ id: realCell
+ width: itemWidth
+ height: itemHeight
+ color: "transparent"
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: true
+
+ onDoubleClicked: cell.openRequested()
+ onPressed: mouse => {
+ cell.focusRequested()
+ if (mouse.button === Qt.RightButton) {
+ cell.contextMenuRequested(Qt.point(mouseX, mouseY))
+ mouse.accepted = false
+ }
+ }
+ }
+ }
+
+ FolderCover {
+ id: coverElement
+ width: coverWidth
+ height: coverHeight
+ anchors { horizontalCenter: parent.horizontalCenter; top: realCell.top }
+ coverSource: cell.cover_path
+ selected: cell.selected
+ showFinishedMark: cell.is_finished && show_marks
+ showRecentIndicator: (((new Date() / 1000) - cell.added_date) < cell.recent_range
+ || ((new Date() / 1000) - cell.updated) < cell.recent_range)
+ && cell.show_recent
+ }
+
+ Text {
+ z: 4
+ anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 10 }
+ width: itemWidth - 8
+ maximumLineCount: 2
+ wrapMode: Text.WordWrap
+ text: cell.title
+ elide: Text.ElideRight
+ color: itemTitleColor
+ font.letterSpacing: fontSpacing
+ font.pointSize: fontSize
+ font.family: fontFamily
+ }
+}
diff --git a/YACReaderLibrary/qml/FolderInfoView.qml b/YACReaderLibrary/qml/FolderInfoView.qml
new file mode 100644
index 000000000..194a10cf3
--- /dev/null
+++ b/YACReaderLibrary/qml/FolderInfoView.qml
@@ -0,0 +1,88 @@
+import QtQuick
+import QtQuick.Layouts
+
+Rectangle {
+ id: root
+
+ required property var folderInfo
+
+ property int panelMargin: 30
+ property color secondaryTextColor: infoMetadataTextColor
+
+ component MetadataText: Text {
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ }
+
+ color: "transparent"
+ height: content.implicitHeight + panelMargin * 2
+
+ function formattedDate(timestamp) {
+ if (!timestamp)
+ return qsTr("Unknown")
+ return new Date(timestamp * 1000).toLocaleDateString(Qt.locale(), Locale.ShortFormat)
+ }
+
+ ColumnLayout {
+ id: content
+ x: root.panelMargin
+ y: root.panelMargin
+ width: root.width - root.panelMargin * 2
+ spacing: 12
+
+ FolderCover {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: Math.min(220, content.width)
+ Layout.preferredHeight: Layout.preferredWidth * coverHeight / coverWidth
+ coverSource: root.folderInfo.cover ?? ""
+ }
+
+ Text {
+ Layout.fillWidth: true
+ Layout.topMargin: 6
+ text: root.folderInfo.name ?? ""
+ color: infoTextColor
+ font.family: "Arial"
+ font.bold: true
+ font.pixelSize: 21
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: root.folderInfo.path ?? ""
+ color: root.secondaryTextColor
+ font.family: "Arial"
+ font.pixelSize: 13
+ wrapMode: Text.WrapAnywhere
+ horizontalAlignment: Text.AlignHCenter
+ visible: text.length > 0
+ }
+
+ GridLayout {
+ Layout.fillWidth: true
+ columns: 2
+ columnSpacing: 18
+ rowSpacing: 9
+
+ MetadataText { text: qsTr("Items"); color: root.secondaryTextColor }
+ MetadataText { text: root.folderInfo.itemCount ?? 0; color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Type"); color: root.secondaryTextColor }
+ MetadataText { text: root.folderInfo.typeName ?? ""; color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Reading status"); color: root.secondaryTextColor }
+ MetadataText { text: root.folderInfo.finished ? qsTr("Read") : qsTr("Unread"); color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Collection status"); color: root.secondaryTextColor }
+ MetadataText { text: root.folderInfo.completed ? qsTr("Completed") : qsTr("In progress"); color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Added"); color: root.secondaryTextColor }
+ MetadataText { text: root.formattedDate(root.folderInfo.added); color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Updated"); color: root.secondaryTextColor }
+ MetadataText { text: root.formattedDate(root.folderInfo.updated); color: infoTextColor; Layout.fillWidth: true }
+ }
+ }
+}
diff --git a/YACReaderLibrary/qml/GridComicsView.qml b/YACReaderLibrary/qml/GridComicsView.qml
index 1aa16186e..abf00b47f 100644
--- a/YACReaderLibrary/qml/GridComicsView.qml
+++ b/YACReaderLibrary/qml/GridComicsView.qml
@@ -1,4 +1,4 @@
-import QtQuick
+import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -9,9 +9,10 @@ import com.yacreader.ComicModel 1.0
import com.yacreader.ComicInfo 1.0
import com.yacreader.ComicDB 1.0
+import com.yacreader.GridContentModel 1.0
import QtQuick.Controls.Basic
-import QtQuick.Controls.impl
+import QtQml.Models
SplitView {
orientation: Qt.Horizontal
@@ -55,375 +56,67 @@ SplitView {
height: parent.height
anchors.margins: 0
- Component {
+ DelegateChooser {
id: appDelegate
- Rectangle
- {
- id: cell
- width: grid.cellWidth
- height: grid.cellHeight
- color: "#00000000"
+ role: "item_kind"
- scale: mouseArea.containsMouse ? 1.025 : 1
+ DelegateChoice {
+ roleValue: GridContentModel.FolderItem
- Behavior on scale {
- NumberAnimation { duration: 90 }
- }
+ FolderGridDelegate {
+ id: folderCell
+ width: grid.cellWidth
+ height: grid.cellHeight
+ selected: currentIndexHelper.focusedFolderRow === index
- BorderImage {
- anchors {
- top: realCell.top
- left: realCell.left
- right: realCell.right
- bottom: realCell.bottom
- margins: -10
+ onFocusRequested: {
+ comicsSelectionHelper.clear()
+ grid.focusItemFromPointer(index)
}
- border { left: 10; top: 10; right: 10; bottom: 10 }
- horizontalTileMode: BorderImage.Stretch
- verticalTileMode: BorderImage.Stretch
- source: "prerendered_cover_shadow.png"
- visible: showDropShadow
- }
-
- Rectangle {
- id: realCell
-
- property int position : 0
- property bool dragging: false;
- Drag.active: mouseArea.drag.active
- Drag.hotSpot.x: 32
- Drag.hotSpot.y: 32
- Drag.dragType: Drag.Automatic
- //Drag.mimeData: { "x": 1 }
- Drag.proposedAction: Qt.CopyAction
- Drag.onActiveChanged: {
- if(!dragging)
- {
- dragManager.startDrag();
- dragging = true;
- }else
- dragging = false;
+ onOpenRequested: currentIndexHelper.openFolder(index)
+ onContextMenuRequested: localPosition => {
+ var coordinates = main.mapFromItem(folderCell.interactionItem,
+ localPosition.x,
+ localPosition.y)
+ contextMenuHelper.requestItemContextMenu(Qt.point(coordinates.x, coordinates.y), folderCell.index)
}
-
- width: itemWidth
- height: itemHeight
-
- color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?cellSelectedColor:cellColor;
- //border.color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?cellSelectedBorderColor:borderColor;
- //border.width: ?1:0;
- anchors.horizontalCenter: parent.horizontalCenter
-
- Rectangle
- {
- id: mouseOverBorder
-
- property bool commonBorder : false
-
- property int lBorderwidth : 2
- property int rBorderwidth : 2
- property int tBorderwidth : 2
- property int bBorderwidth : 2
-
- property int commonBorderWidth : 1
-
- z : -1
-
- color: "#00000000"
-
- anchors
- {
- left: parent.left
- right: parent.right
- top: parent.top
- bottom: parent.bottom
-
- topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth
- bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth
- leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth
- rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth
- }
-
- border.color: cellSelectedBorderColor
- border.width: 3
-
- opacity: (dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index) ? 1 : 0
-
- Behavior on opacity {
- NumberAnimation { duration: 300 }
- }
-
- radius : 2
- }
-
-
- MouseArea {
- id: mouseArea
- drag.target: realCell
-
- drag.minimumX: 0
- drag.maximumX: 0
- drag.minimumY: 0
- drag.maximumY: 0
-
- anchors.fill: parent
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- hoverEnabled: true
-
- onDoubleClicked: {
- comicsSelectionHelper.clear();
-
- comicsSelectionHelper.selectIndex(index);
- grid.currentIndex = index;
- currentIndexHelper.selectedItem(index);
- }
-
- function selectAll(from,to)
- {
- for(var i = from;i<=to;i++)
- {
- comicsSelectionHelper.selectIndex(i);
- }
- }
-
- onPressed: mouse => {
- var ci = grid.currentIndex; //save current index
-
- /*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier))
- {
- if(!comicsSelectionHelper.isSelectedIndex(index))
- comicsSelectionHelper.clear();
- }*/
-
- if(mouse.modifiers & Qt.ShiftModifier)
- if(index < ci)
- {
- selectAll(index,ci);
- grid.currentIndex = index;
- }
- else if (index > ci)
- {
- selectAll(ci,index);
- grid.currentIndex = index;
- }
-
- mouse.accepted = true;
-
- if(mouse.button === Qt.RightButton) // context menu is requested
- {
- if(!comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be
- {
- currentIndexHelper.setCurrentIndex(index)
- grid.currentIndex = index;
- }
-
- var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
- contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y));
- mouse.accepted = false;
-
- } else //left button
- {
-
- if(mouse.modifiers & Qt.ControlModifier)
- {
- if(comicsSelectionHelper.isSelectedIndex(index))
- {
- if(comicsSelectionHelper.numItemsSelected()>1)
- {
- comicsSelectionHelper.deselectIndex(index);
- if(grid.currentIndex === index)
- grid.currentIndex = comicsSelectionHelper.lastSelectedIndex();
- }
- }
- else
- {
- comicsSelectionHelper.selectIndex(index);
- grid.currentIndex = index;
- }
- }
-
- if(mouse.button !== Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) //just left button click
- {
- if(comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be
- {
-
- }
- else
- {
- currentIndexHelper.setCurrentIndex(index)
- }
-
- grid.currentIndex = index;
- }
- }
-
- }
-
- onReleased: mouse => {
- if(mouse.button === Qt.LeftButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier))
- {
- if(comicsSelectionHelper.isSelectedIndex(index))
- {
- currentIndexHelper.setCurrentIndex(index)
- grid.currentIndex = index;
- }
- }
- }
- }
- }
-
- /**/
-
- //cover
- Image {
- id: coverElement
- width: coverWidth
- height: coverHeight
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- source: cover_path
- fillMode: Image.PreserveAspectCrop
- smooth: true
- mipmap: true
- asynchronous : true
- cache: false //TODO clear cache only when it is needed
-
- }
-
- //is new
- Rectangle {
- width: 10
- height: 10
- radius: 5
- anchors { left: coverElement.left; top: coverElement.top; topMargin: 5; leftMargin: 5; }
- color: newItemColor
- visible: (((new Date() / 1000) - added_date) < recent_range) && show_recent
}
+ }
- //border
- Rectangle {
- width: coverElement.width
- height: coverElement.height
- anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
- color: "transparent"
- border {
- color: comicCoverBorderColor
- width: 1
+ DelegateChoice {
+ roleValue: GridContentModel.ComicItem
+
+ ComicGridDelegate {
+ id: comicCell
+ width: grid.cellWidth
+ height: grid.cellHeight
+ currentViewIndex: grid.currentIndex
+ selectionHelper: comicsSelectionHelper
+
+ onActivateRequested: viewRow => currentIndexHelper.activateItem(viewRow)
+ onClearFolderFocusRequested: currentIndexHelper.clearFolderFocus()
+ onContextMenuRequested: localPosition => {
+ var coordinates = main.mapFromItem(comicCell.interactionItem,
+ localPosition.x,
+ localPosition.y)
+ contextMenuHelper.requestItemContextMenu(Qt.point(coordinates.x, coordinates.y), comicCell.index)
}
+ onFocusViewRowRequested: viewRow => grid.focusItemFromPointer(viewRow)
+ onRateRequested: (sourceRow, rating) => comicRatingHelper.rate(sourceRow, rating)
+ onSelectRangeRequested: (from, to) => currentIndexHelper.selectComicRange(from, to)
+ onSetCurrentViewRowRequested: viewRow => grid.setCurrentIndexFromPointer(viewRow)
+ onSetCurrentComicRowRequested: sourceRow => {
+ grid.setCurrentIndexFromPointer(currentIndexHelper.viewRowForComicRow(sourceRow))
+ }
+ onStartDragRequested: dragManager.startDrag()
}
+ }
- //mark
- Image {
- id: mark
- width: 23
- height: 23
- source: read_column&&show_marks?"tick.svg":has_been_opened&&show_marks?"reading.svg":""
- anchors {right: coverElement.right; top: coverElement.top; topMargin: 9; rightMargin: 9}
- asynchronous : true
- }
-
- //title
- Text {
- id : titleText
- anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 4; }
- width: itemWidth - 8
- maximumLineCount: 2
- wrapMode: Text.WordWrap
- text: title
- elide: Text.ElideRight
- color: itemTitleColor
- clip: true
- font.letterSpacing: fontSpacing
- font.pointSize: fontSize
- font.family: fontFamily
- }
-
- //number
- Text {
- anchors {bottom: realCell.bottom; left: realCell.left; margins: 4}
- text: number?"#"+number:""
- color: itemDetailsColor
- font.letterSpacing: fontSpacing
- font.pointSize: fontSize
- font.family: fontFamily
- }
-
- //page icon
- ColorImage {
- id: pageImage
- anchors {bottom: realCell.bottom; right: realCell.right; bottomMargin: 6; rightMargin: 4; leftMargin: 4}
- source: "page.svg"
- color: itemDetailsColor
- width: 8
- height: 10
- }
-
- //numPages
- Text {
- id: pages
- anchors {bottom: realCell.bottom; right: pageImage.left; margins: 4}
- text: has_been_opened?current_page+"/"+num_pages:num_pages
- color: itemDetailsColor
- font.letterSpacing: fontSpacing
- font.pointSize: fontSize
- font.family: fontFamily
- }
-
- //rating icon
- ColorImage {
- id: ratingImage
- anchors {bottom: realCell.bottom; right: pageImage.left; bottomMargin: 6.5; rightMargin: Math.floor(pages.width)+12}
- source: "star.svg"
- color: itemDetailsColor
- width: 11
- height: 11
-
- MouseArea {
- anchors.fill: parent
- onPressed: {
- console.log("rating");
- comicsSelectionHelper.clear();
- comicsSelectionHelper.selectIndex(index);
- grid.currentIndex = index;
- ratingLoader.active = true;
- ratingLoader.item.popup();
- }
- }
-
- Loader {
- id: ratingLoader
- active: false
- sourceComponent: ratingConextMenuComponent
- }
-
- Component {
- id: ratingConextMenuComponent
- Menu {
- background: Rectangle {
- implicitWidth: 42
- implicitHeight: 100
- }
-
- id: ratingConextMenu
-
- Action { text: "1"; enabled: true; onTriggered: comicRatingHelper.rate(index,1) }
- Action { text: "2"; enabled: true; onTriggered: comicRatingHelper.rate(index,2) }
- Action { text: "3"; enabled: true; onTriggered: comicRatingHelper.rate(index,3) }
- Action { text: "4"; enabled: true; onTriggered: comicRatingHelper.rate(index,4) }
- Action { text: "5"; enabled: true; onTriggered: comicRatingHelper.rate(index,5) }
-
- delegate: MenuItem {
- implicitHeight: 30
- }
- }
- }
- }
-
- //comic rating
- Text {
- id: comicRating
- anchors {bottom: realCell.bottom; right: ratingImage.left; margins: 4}
- text: rating>0?rating:"-"
- color: itemDetailsColor
+ DelegateChoice {
+ roleValue: GridContentModel.SpacerItem
+ Item {
+ width: grid.cellWidth
+ height: grid.cellHeight
}
}
}
@@ -442,13 +135,52 @@ SplitView {
grid.contentX = grid.originX
}
+ function capturePosition() {
+ const probeX = Math.max(1, grid.cellWidth / 2)
+ const viewRow = grid.indexAt(probeX, grid.contentY + 1)
+ if (viewRow < 0) {
+ return {
+ "header": true,
+ "viewRow": -1,
+ "offset": grid.contentY - grid.originY,
+ "itemExtent": Math.max(1, -grid.originY)
+ }
+ }
+
+ const item = grid.itemAtIndex(viewRow)
+ return {
+ "header": false,
+ "viewRow": viewRow,
+ "offset": item ? grid.contentY - item.y : 0,
+ "itemExtent": grid.cellHeight
+ }
+ }
+
+ function restorePosition(viewRow, offset, oldItemExtent) {
+ if (viewRow < 0) {
+ const currentExtent = Math.max(1, -grid.originY)
+ const restoredOffset = oldItemExtent === currentExtent
+ ? offset
+ : offset * currentExtent / Math.max(1, oldItemExtent)
+ grid.contentY = grid.originY + restoredOffset
+ return
+ }
+
+ grid.positionViewAtIndex(viewRow, GridView.Beginning)
+ const restoredOffset = oldItemExtent === grid.cellHeight
+ ? offset
+ : offset * grid.cellHeight / Math.max(1, oldItemExtent)
+ const maximumY = Math.max(grid.originY, grid.contentHeight - grid.height + grid.originY)
+ grid.contentY = Math.max(grid.originY, Math.min(maximumY, grid.contentY + restoredOffset))
+ }
+
property Component currentComicView: Component {
id: currentComicView
Rectangle {
id: currentComicViewTopView
color: "#00000000"
- height: showCurrentComic ? 270 : 20
+ height: currentIndexHelper.currentComicBannerVisible ? 270 : 20
Rectangle {
color: currentComicBackgroundColor
@@ -458,7 +190,7 @@ SplitView {
width: main.width
height: 250
- visible: showCurrentComic
+ visible: currentIndexHelper.currentComicBannerVisible
//cover
Image {
@@ -471,7 +203,7 @@ SplitView {
anchors.rightMargin: 15
horizontalAlignment: Image.AlignLeft
anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 0}
- source: comicsList.getCoverUrlPathForComicHash(currentComicInfo.hash.toString())
+ source: comicsList.comicCoverUrlForHash(currentComicInfo.hash.toString())
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
@@ -698,12 +430,26 @@ SplitView {
}
}
+ property Component rootFolderHeader: Component {
+ ContinueReadingGridHeader {
+ id: continueReadingHeader
+ width: main.width
+ contentModel: currentIndexHelper.rootContinueReadingModel
+ sectionVisible: currentIndexHelper.globalContinueReadingEnabled
+ onOpenRequested: index => currentIndexHelper.openContinueReadingComic(index)
+ onContextMenuRequested: (index, position) => {
+ var coordinates = main.mapFromItem(continueReadingHeader, position.x, position.y)
+ currentIndexHelper.requestContinueReadingComicContextMenu(Qt.point(coordinates.x, coordinates.y), index)
+ }
+ }
+ }
+
GridView {
id:grid
objectName: "grid"
anchors.fill: parent
cellHeight: cellCustomHeight
- header: currentComicView
+ header: currentIndexHelper.rootFolder ? scrollView.rootFolderHeader : scrollView.currentComicView
focus: true
model: comicsList
delegate: appDelegate
@@ -714,7 +460,7 @@ SplitView {
pixelAligned: true
highlightFollowsCurrentItem: true
- currentIndex: 0
+ currentIndex: -1
cacheBuffer: 0
interactive: true
@@ -748,15 +494,43 @@ SplitView {
return Math.floor(width / cellCustomWidth);
}
+ function firstVisibleSelectableIndex() {
+ if (count === 0)
+ return -1
+
+ const columns = Math.max(1, numCellsPerRow())
+ const visibleRow = Math.max(0, Math.floor((contentY - originY) / cellHeight))
+ const candidate = Math.min(visibleRow * columns, count - 1)
+ return currentIndexHelper.nearestSelectableRow(candidate, 1)
+ }
+
+ function setCurrentIndexFromPointer(index) {
+ var previousContentX = contentX
+ var previousContentY = contentY
+ currentIndex = index
+ contentX = previousContentX
+ contentY = previousContentY
+ }
+
+ function focusItemFromPointer(index) {
+ var previousContentX = contentX
+ var previousContentY = contentY
+ currentIndexHelper.focusItem(index)
+ currentIndex = index
+ contentX = previousContentX
+ contentY = previousContentY
+ }
+
onWidthChanged: {
calculateCellWidths(cellCustomWidth);
}
function calculateCellWidths(cWidth) {
- var wholeCells = Math.floor(width / cWidth);
+ var wholeCells = Math.max(1, Math.floor(width / cWidth));
var rest = width - (cWidth * wholeCells)
grid.cellWidth = cWidth + Math.floor(rest / wholeCells);
+ currentIndexHelper.setGridColumnCount(wholeCells)
}
WheelHandler {
@@ -796,6 +570,25 @@ SplitView {
return;
}
+ if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
+ event.accepted = true
+ currentIndexHelper.activateItem(grid.currentIndex)
+ return
+ }
+
+ const cursorKey = event.key === Qt.Key_Right || event.key === Qt.Key_Left
+ || event.key === Qt.Key_Up || event.key === Qt.Key_Down
+ if (cursorKey && grid.currentIndex < 0) {
+ const initialIndex = grid.firstVisibleSelectableIndex()
+ if (initialIndex >= 0) {
+ comicsSelectionHelper.clear()
+ currentIndexHelper.focusItem(initialIndex)
+ grid.currentIndex = initialIndex
+ }
+ event.accepted = true
+ return
+ }
+
var numCells = grid.numCellsPerRow();
var ci = 0;
if (event.key === Qt.Key_Right) {
@@ -813,10 +606,13 @@ SplitView {
return;
}
+ ci = currentIndexHelper.nearestSelectableRow(ci,
+ event.key === Qt.Key_Left || event.key === Qt.Key_Up ? -1 : 1)
+
event.accepted = true;
grid.currentIndex = -1
comicsSelectionHelper.clear();
- currentIndexHelper.setCurrentIndex(ci);
+ currentIndexHelper.focusItem(ci);
grid.currentIndex = ci;
}
@@ -846,14 +642,15 @@ SplitView {
else{
if (dropManager.canDropFormats(drop.formats))
{
- var destItem = grid.itemAt(drop.x,drop.y + grid.contentY);
- var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x
var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY);
-
- if(realIndex === -1)
- realIndex = grid.count - 1;
-
- var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1;
+ var destIndex = grid.count;
+ if (realIndex !== -1) {
+ var destItem = grid.itemAtIndex(realIndex);
+ var destLocalX = grid.mapToItem(destItem,
+ drop.x,
+ drop.y + grid.contentY).x;
+ destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1;
+ }
dropManager.droppedComicsForResortingAt("", destIndex);
}
}
@@ -883,9 +680,56 @@ SplitView {
contentWidth: infoView.width
contentHeight: infoView.height
- ComicInfoView {
+ Loader {
id: infoView
width: info_container.width
+ sourceComponent: currentIndexHelper.focusedFolderRow >= 0
+ ? folderInfoComponent
+ : currentIndexHelper.hasComicSelection
+ ? comicInfoComponent
+ : currentIndexHelper.currentLocationInfo.kind === "folder"
+ ? folderInfoComponent
+ : currentIndexHelper.currentLocationInfo.kind === "library"
+ ? libraryInfoComponent
+ : currentIndexHelper.currentLocationInfo.name
+ ? listInfoComponent
+ : emptyInfoComponent
+ }
+
+ Component {
+ id: comicInfoComponent
+ ComicInfoView { width: infoView.width }
+ }
+
+ Component {
+ id: folderInfoComponent
+ FolderInfoView {
+ width: infoView.width
+ folderInfo: currentIndexHelper.focusedFolderRow >= 0
+ ? currentIndexHelper.focusedFolderInfo
+ : currentIndexHelper.currentLocationInfo
+ }
+ }
+
+ Component {
+ id: libraryInfoComponent
+ LibraryInfoView {
+ width: infoView.width
+ libraryInfo: currentIndexHelper.currentLocationInfo
+ }
+ }
+
+ Component {
+ id: listInfoComponent
+ ListInfoView {
+ width: infoView.width
+ listInfo: currentIndexHelper.currentLocationInfo
+ }
+ }
+
+ Component {
+ id: emptyInfoComponent
+ EmptyInfoView { width: infoView.width }
}
WheelHandler {
diff --git a/YACReaderLibrary/qml/LibraryInfoView.qml b/YACReaderLibrary/qml/LibraryInfoView.qml
new file mode 100644
index 000000000..0e39d967b
--- /dev/null
+++ b/YACReaderLibrary/qml/LibraryInfoView.qml
@@ -0,0 +1,84 @@
+import QtQuick
+import QtQuick.Layouts
+
+Rectangle {
+ id: root
+
+ required property var libraryInfo
+
+ property int panelMargin: 30
+ property color secondaryTextColor: infoMetadataTextColor
+
+ color: "transparent"
+ height: content.implicitHeight + panelMargin * 2
+
+ component MetadataText: Text {
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ }
+
+ ColumnLayout {
+ id: content
+ x: root.panelMargin
+ y: root.panelMargin
+ width: root.width - root.panelMargin * 2
+ spacing: 12
+
+ Text {
+ Layout.fillWidth: true
+ text: root.libraryInfo.name ?? ""
+ color: infoTextColor
+ font.family: "Arial"
+ font.bold: true
+ font.pixelSize: 21
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: qsTr("Library info")
+ color: root.secondaryTextColor
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ font.bold: true
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ Layout.topMargin: 12
+ text: root.libraryInfo.path ?? ""
+ color: themeLinkColor
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ font.underline: pathMouseArea.containsMouse
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+
+ MouseArea {
+ id: pathMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: currentIndexHelper.requestOpenLibraryFolder()
+ }
+ }
+
+ GridLayout {
+ Layout.fillWidth: true
+ Layout.topMargin: 6
+ columns: 2
+ columnSpacing: 18
+ rowSpacing: 12
+
+ MetadataText { text: qsTr("Number of folders"); color: root.secondaryTextColor }
+ MetadataText { text: root.libraryInfo.folderCount ?? 0; color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Number of comics"); color: root.secondaryTextColor }
+ MetadataText { text: root.libraryInfo.comicCount ?? 0; color: infoTextColor; Layout.fillWidth: true }
+
+ MetadataText { text: qsTr("Number of read comics"); color: root.secondaryTextColor }
+ MetadataText { text: root.libraryInfo.readComicCount ?? 0; color: infoTextColor; Layout.fillWidth: true }
+ }
+ }
+}
diff --git a/YACReaderLibrary/qml/ListInfoView.qml b/YACReaderLibrary/qml/ListInfoView.qml
new file mode 100644
index 000000000..a23a62115
--- /dev/null
+++ b/YACReaderLibrary/qml/ListInfoView.qml
@@ -0,0 +1,78 @@
+import QtQuick
+import QtQuick.Layouts
+
+Rectangle {
+ id: root
+
+ required property var listInfo
+
+ property int panelMargin: 30
+ property color secondaryTextColor: infoMetadataTextColor
+
+ color: "transparent"
+ height: content.implicitHeight + panelMargin * 2
+
+ ColumnLayout {
+ id: content
+ x: root.panelMargin
+ y: root.panelMargin
+ width: root.width - root.panelMargin * 2
+ spacing: 12
+
+ Image {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: Math.min(110, content.width)
+ Layout.preferredHeight: 95
+ source: root.listInfo.icon ?? ""
+ fillMode: Image.PreserveAspectFit
+ visible: source.toString().length > 0
+ }
+
+ Text {
+ Layout.fillWidth: true
+ Layout.topMargin: 8
+ text: root.listInfo.name ?? ""
+ color: infoTextColor
+ font.family: "Arial"
+ font.bold: true
+ font.pixelSize: 21
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: (root.listInfo.itemCount ?? 0) === 1
+ ? qsTr("1 comic")
+ : qsTr("%1 comics").arg(root.listInfo.itemCount ?? 0)
+ color: root.secondaryTextColor
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: (root.listInfo.recentDays ?? 0) === 1
+ ? qsTr("Last day")
+ : qsTr("Last %1 days").arg(root.listInfo.recentDays ?? 0)
+ color: root.secondaryTextColor
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ horizontalAlignment: Text.AlignHCenter
+ visible: (root.listInfo.recentDays ?? 0) > 0
+ }
+
+ Text {
+ Layout.fillWidth: true
+ text: (root.listInfo.sublistCount ?? 0) === 1
+ ? qsTr("1 sublist")
+ : qsTr("%1 sublists").arg(root.listInfo.sublistCount ?? 0)
+ color: root.secondaryTextColor
+ font.family: fontFamily
+ font.pointSize: fontSize + 1
+ horizontalAlignment: Text.AlignHCenter
+ visible: (root.listInfo.sublistCount ?? 0) > 0
+ }
+ }
+}
diff --git a/YACReaderLibrary/recent_visibility_coordinator.cpp b/YACReaderLibrary/recent_visibility_coordinator.cpp
index f62979e2a..151be5835 100644
--- a/YACReaderLibrary/recent_visibility_coordinator.cpp
+++ b/YACReaderLibrary/recent_visibility_coordinator.cpp
@@ -3,8 +3,8 @@
#include "yacreader_global_gui.h"
-RecentVisibilityCoordinator::RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, FolderContentView *folderContentView, ComicModel *comicModel)
- : QObject(), settings(settings), folderModel(folderModel), folderContentView(folderContentView), comicModel(comicModel)
+RecentVisibilityCoordinator::RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, ComicModel *comicModel)
+ : QObject(), settings(settings), folderModel(folderModel), comicModel(comicModel)
{
updateVisibility();
updateTimeRange();
@@ -21,7 +21,6 @@ void RecentVisibilityCoordinator::updateTimeRange()
{
auto days = settings->value(NUM_DAYS_TO_CONSIDER_RECENT, 1).toInt();
folderModel->setRecentRange(days);
- folderContentView->setRecentRange(days);
comicModel->setRecentRange(days);
}
@@ -30,6 +29,5 @@ void RecentVisibilityCoordinator::updateVisibility()
auto visibility = settings->value(DISPLAY_RECENTLY_INDICATOR, true).toBool();
folderModel->setShowRecent(visibility);
- folderContentView->setShowRecent(visibility);
comicModel->setShowRecent(visibility);
}
diff --git a/YACReaderLibrary/recent_visibility_coordinator.h b/YACReaderLibrary/recent_visibility_coordinator.h
index b6e917ceb..729ba23b5 100644
--- a/YACReaderLibrary/recent_visibility_coordinator.h
+++ b/YACReaderLibrary/recent_visibility_coordinator.h
@@ -3,14 +3,13 @@
#define RECENT_VISIBILITY_COORDINATOR_H
#include "comic_model.h"
-#include "folder_content_view.h"
#include "folder_model.h"
class RecentVisibilityCoordinator : public QObject
{
Q_OBJECT
public:
- explicit RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, FolderContentView *folderContentView, ComicModel *comicModel);
+ explicit RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, ComicModel *comicModel);
public slots:
void toggleVisibility(bool visibility);
@@ -19,7 +18,6 @@ public slots:
private:
QSettings *settings;
FolderModel *folderModel;
- FolderContentView *folderContentView;
ComicModel *comicModel;
void updateVisibility();
diff --git a/YACReaderLibrary/themes/theme.h b/YACReaderLibrary/themes/theme.h
index 57719ffca..acad7291a 100644
--- a/YACReaderLibrary/themes/theme.h
+++ b/YACReaderLibrary/themes/theme.h
@@ -128,6 +128,7 @@ struct EmptyContainerTheme {
QPixmap emptyFolderIcon;
QPixmap emptyFavoritesIcon;
QPixmap emptyCurrentReadingsIcon;
+ QPixmap emptyRecentIcon;
QPixmap emptyReadingListIcon;
QMap emptyLabelIcons; // Keyed by YACReader::LabelColors enum value
};
@@ -211,7 +212,7 @@ struct NavigationTreeTheme {
QIcon folderFinishedIcon;
};
-// Grid and info view theme colors (used by GridComicsView, FolderContentView, InfoComicsView)
+// Grid and info view theme colors (used by GridComicsView and InfoComicsView)
struct GridAndInfoViewTheme {
// Grid colors
QColor backgroundColor;
@@ -243,7 +244,7 @@ struct GridAndInfoViewTheme {
// Current comic banner
QColor currentComicBackgroundColor;
- // Continue reading section (FolderContentView)
+ // Continue reading section (grid content view)
QColor continueReadingBackgroundColor;
QColor continueReadingTextColor;
diff --git a/YACReaderLibrary/themes/theme_factory.cpp b/YACReaderLibrary/themes/theme_factory.cpp
index 11ead49c9..7db497c90 100644
--- a/YACReaderLibrary/themes/theme_factory.cpp
+++ b/YACReaderLibrary/themes/theme_factory.cpp
@@ -176,7 +176,7 @@ struct GridAndInfoViewParams {
// Current comic banner
QColor currentComicBackgroundColor;
- // Continue reading section (FolderContentView)
+ // Continue reading section (grid content view)
QColor continueReadingBackgroundColor;
QColor continueReadingTextColor;
@@ -497,6 +497,7 @@ Theme makeTheme(const ThemeParams ¶ms)
theme.emptyContainer.emptyFolderIcon = renderSvgToPixmap(recoloredSvgToThemeFile(":/images/empty_container/empty_folder.svg", ec.iconColor, params.meta.id), 319, 243, dpr);
theme.emptyContainer.emptyFavoritesIcon = renderSvgToPixmap(recoloredSvgToThemeFile(":/images/empty_container/empty_favorites.svg", rli.favoritesMainColor, params.meta.id), 238, 223, dpr);
theme.emptyContainer.emptyCurrentReadingsIcon = renderSvgToPixmap(recoloredSvgToThemeFile(":/images/empty_container/empty_current_readings.svg", ec.iconColor, params.meta.id), 167, 214, dpr);
+ theme.emptyContainer.emptyRecentIcon = renderSvgToPixmap(recoloredSvgToThemeFile(":/images/lists/default_2.svg", rli.currentlyReadingMainColor, rli.specialListShadowColor, rli.currentlyReadingOuterColor, params.meta.id), 167, dpr);
theme.emptyContainer.emptyReadingListIcon = renderSvgToPixmap(recoloredSvgToThemeFile(":/images/empty_container/empty_reading_list.svg", ec.iconColor, params.meta.id), 248, 187, dpr);
// Generate empty label icons for each label color
diff --git a/YACReaderLibrary/yacreader_comics_selection_helper.cpp b/YACReaderLibrary/yacreader_comics_selection_helper.cpp
index 4aebc4fcd..a727c39ac 100644
--- a/YACReaderLibrary/yacreader_comics_selection_helper.cpp
+++ b/YACReaderLibrary/yacreader_comics_selection_helper.cpp
@@ -3,7 +3,7 @@
#include "comic_model.h"
YACReaderComicsSelectionHelper::YACReaderComicsSelectionHelper(QObject *parent)
- : QObject(parent), _selectionModel(nullptr)
+ : QObject(parent)
{
}
@@ -14,89 +14,88 @@ void YACReaderComicsSelectionHelper::setModel(ComicModel *model)
this->model = model;
- if (_selectionModel != nullptr)
- delete _selectionModel;
+ delete itemSelectionModel;
- _selectionModel = new QItemSelectionModel(model);
+ itemSelectionModel = new QItemSelectionModel(model, this);
+ connect(itemSelectionModel, &QItemSelectionModel::selectionChanged, this, [this]() {
+ ++revision;
+ emit selectionChanged();
+ });
+
+ ++revision;
+ emit selectionChanged();
}
void YACReaderComicsSelectionHelper::selectIndex(int index)
{
- if (_selectionModel != nullptr && model != nullptr) {
- _selectionModel->select(model->index(index, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ if (itemSelectionModel != nullptr && model != nullptr && index >= 0 && index < model->rowCount())
+ itemSelectionModel->select(model->index(index, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
+}
- emit selectionChanged();
- }
+void YACReaderComicsSelectionHelper::selectOnly(int index)
+{
+ if (itemSelectionModel != nullptr && model != nullptr && index >= 0 && index < model->rowCount())
+ itemSelectionModel->select(model->index(index, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
}
void YACReaderComicsSelectionHelper::deselectIndex(int index)
{
- if (_selectionModel != nullptr && model != nullptr) {
- _selectionModel->select(model->index(index, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
-
- emit selectionChanged();
- }
+ if (itemSelectionModel != nullptr && model != nullptr && index >= 0 && index < model->rowCount())
+ itemSelectionModel->select(model->index(index, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
}
bool YACReaderComicsSelectionHelper::isSelectedIndex(int index) const
{
- if (_selectionModel != nullptr && model != nullptr) {
+ if (itemSelectionModel != nullptr && model != nullptr) {
QModelIndex mi = model->index(index, 0);
- return _selectionModel->isSelected(mi);
+ return itemSelectionModel->isSelected(mi);
}
return false;
}
void YACReaderComicsSelectionHelper::clear()
{
- if (_selectionModel != nullptr) {
- _selectionModel->clear();
-
- emit selectionChanged();
- }
+ if (itemSelectionModel != nullptr)
+ itemSelectionModel->clear();
}
QModelIndex YACReaderComicsSelectionHelper::currentIndex()
{
- if (!_selectionModel)
+ if (!itemSelectionModel)
return QModelIndex();
- QModelIndexList indexes = _selectionModel->selectedRows();
+ QModelIndexList indexes = itemSelectionModel->selectedRows();
if (indexes.length() > 0)
return indexes[0];
- this->selectIndex(0);
- indexes = _selectionModel->selectedRows();
- if (indexes.length() > 0)
- return indexes[0];
- else
- return QModelIndex();
+ return QModelIndex();
}
void YACReaderComicsSelectionHelper::selectAll()
{
+ if (!itemSelectionModel || !model || model->rowCount() == 0)
+ return;
+
QModelIndex top = model->index(0, 0);
QModelIndex bottom = model->index(model->rowCount() - 1, 0);
QItemSelection selection(top, bottom);
- _selectionModel->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
-
- emit selectionChanged();
+ itemSelectionModel->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
}
QModelIndexList YACReaderComicsSelectionHelper::selectedRows(int column) const
{
- return _selectionModel->selectedRows(column);
+ return itemSelectionModel ? itemSelectionModel->selectedRows(column) : QModelIndexList();
}
QList YACReaderComicsSelectionHelper::selectedIndexes() const
{
- return _selectionModel->selectedIndexes();
+ return itemSelectionModel ? itemSelectionModel->selectedIndexes() : QModelIndexList();
}
int YACReaderComicsSelectionHelper::numItemsSelected() const
{
- if (_selectionModel != nullptr) {
- return _selectionModel->selectedRows().length();
+ if (itemSelectionModel != nullptr) {
+ return itemSelectionModel->selectedRows().length();
}
return 0;
@@ -104,8 +103,9 @@ int YACReaderComicsSelectionHelper::numItemsSelected() const
int YACReaderComicsSelectionHelper::lastSelectedIndex() const
{
- if (_selectionModel != nullptr) {
- return _selectionModel->selectedRows().last().row();
+ if (itemSelectionModel != nullptr) {
+ const auto selectedRows = itemSelectionModel->selectedRows();
+ return selectedRows.isEmpty() ? -1 : selectedRows.last().row();
}
return -1;
@@ -113,9 +113,10 @@ int YACReaderComicsSelectionHelper::lastSelectedIndex() const
QItemSelectionModel *YACReaderComicsSelectionHelper::selectionModel()
{
- QModelIndexList indexes = _selectionModel->selectedRows();
- if (indexes.length() == 0)
- this->selectIndex(0);
+ return itemSelectionModel;
+}
- return _selectionModel;
+qulonglong YACReaderComicsSelectionHelper::selectionRevision() const
+{
+ return revision;
}
diff --git a/YACReaderLibrary/yacreader_comics_selection_helper.h b/YACReaderLibrary/yacreader_comics_selection_helper.h
index 05566d89d..b5a727e56 100644
--- a/YACReaderLibrary/yacreader_comics_selection_helper.h
+++ b/YACReaderLibrary/yacreader_comics_selection_helper.h
@@ -11,12 +11,14 @@ class ComicModel;
class YACReaderComicsSelectionHelper : public QObject
{
Q_OBJECT
+ Q_PROPERTY(qulonglong selectionRevision READ selectionRevision NOTIFY selectionChanged)
public:
explicit YACReaderComicsSelectionHelper(QObject *parent = nullptr);
void setModel(ComicModel *model);
Q_INVOKABLE void selectIndex(int index);
+ Q_INVOKABLE void selectOnly(int index);
Q_INVOKABLE void deselectIndex(int index);
Q_INVOKABLE bool isSelectedIndex(int index) const;
Q_INVOKABLE void clear();
@@ -26,6 +28,7 @@ class YACReaderComicsSelectionHelper : public QObject
Q_INVOKABLE void selectAll();
Q_INVOKABLE QModelIndexList selectedIndexes() const;
Q_INVOKABLE QModelIndexList selectedRows(int column = 0) const;
+ qulonglong selectionRevision() const;
QItemSelectionModel *selectionModel();
@@ -34,10 +37,10 @@ class YACReaderComicsSelectionHelper : public QObject
public slots:
-protected:
- QItemSelectionModel *_selectionModel;
-
- ComicModel *model;
+private:
+ QItemSelectionModel *itemSelectionModel = nullptr;
+ ComicModel *model = nullptr;
+ qulonglong revision = 0;
};
#endif // YACREADERCOMICSSELECTIONHELPER_H
diff --git a/YACReaderLibrary/yacreader_content_views_manager.cpp b/YACReaderLibrary/yacreader_content_views_manager.cpp
index 6abacc2a5..df2f324d3 100644
--- a/YACReaderLibrary/yacreader_content_views_manager.cpp
+++ b/YACReaderLibrary/yacreader_content_views_manager.cpp
@@ -6,24 +6,21 @@
#include "empty_label_widget.h"
#include "empty_reading_list_widget.h"
#include "empty_special_list.h"
-#include "folder_content_view.h"
#include "grid_comics_view.h"
#include "info_comics_view.h"
#include "library_window.h"
#include "no_search_results_widget.h"
#include "options_dialog.h"
-#include "reading_list_model.h"
#include "yacreader_options_dialog.h"
-#include "yacreader_reading_lists_view.h"
#include "yacreader_sidebar.h"
-//--
-#include "yacreader_search_line_edit.h"
+#include
YACReaderContentViewsManager::YACReaderContentViewsManager(QSettings *settings, LibraryWindow *parent)
- : QObject(parent), libraryWindow(parent), classicComicsView(nullptr), gridComicsView(nullptr), infoComicsView(nullptr)
+ : QObject(parent), libraryWindow(parent), classicComicsView(nullptr), gridComicsView(nullptr), infoComicsView(nullptr), toolbarOwner(nullptr)
{
comicsViewStack = new QStackedWidget();
+ gridComicsView = new GridComicsView();
switch ((YACReader::ComicsViewStatus)settings->value(COMICS_VIEW_STATUS).toInt()) {
case Flow:
@@ -38,32 +35,31 @@ YACReaderContentViewsManager::YACReaderContentViewsManager(QSettings *settings,
case Grid:
default:
- comicsView = gridComicsView = new GridComicsView();
- connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, gridComicsView, &GridComicsView::updateBackgroundConfig);
- connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::finished, gridComicsView, &GridComicsView::updateSettings); // TODO: we can link constante changes to updateSettings because of bad performance
+ comicsView = gridComicsView;
comicsViewStatus = Grid;
break;
}
- doComicsViewConnections();
+ connectComicsViewConnections(comicsView);
+ toolbarOwner = comicsView;
+ connect(gridComicsView, &GridComicsView::comicSelectionStateChanged, this, [this](bool hasSelection) {
+ if (comicsViewStack->currentWidget() == gridComicsView)
+ libraryWindow->actions.setComicSelectionActionsEnabled(hasSelection);
+ });
+ connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, gridComicsView, &GridComicsView::updateSettings);
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
- comicsViewStack->addWidget(folderContentView = new FolderContentView(parent->actions.toogleShowRecentIndicatorAction));
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
comicsViewStack->addWidget(emptySpecialList = new EmptySpecialListWidget());
comicsViewStack->addWidget(emptyReadingList = new EmptyReadingListWidget());
comicsViewStack->addWidget(emptyFolderWidget = new EmptyFolderWidget());
comicsViewStack->addWidget(noSearchResultsWidget = new NoSearchResultsWidget());
- comicsViewStack->addWidget(comicsView);
+ ensureInStack(comicsView);
+ ensureInStack(gridComicsView);
comicsViewStack->setCurrentWidget(comicsView);
- // connections
- connect(folderContentView, &FolderContentView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
- connect(folderContentView, &FolderContentView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
- connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, folderContentView, &FolderContentView::updateSettings);
-
initTheme(this);
}
@@ -72,44 +68,46 @@ QWidget *YACReaderContentViewsManager::containerWidget()
return comicsViewStack;
}
-void YACReaderContentViewsManager::updateCurrentContentView()
+GridComicsView *YACReaderContentViewsManager::gridView() const
{
- if (!libraryWindow->hasLoadedLibraryModels())
- return;
+ return gridComicsView;
+}
- if (libraryWindow->status == LibraryWindow::Searching) {
- auto currentWidget = comicsViewStack->currentWidget();
+bool YACReaderContentViewsManager::isComicsViewVisible() const
+{
+ return comicsViewStack->currentWidget() == comicsView;
+}
- libraryWindow->comicsModel->reload();
+void YACReaderContentViewsManager::prepareToClose()
+{
+ const auto saveIfInactive = [this](ComicsView *view) {
+ if (view && view != comicsView)
+ view->saveViewConfig();
+ };
- if (currentWidget == comicsView) {
- comicsView->reloadContent();
- }
- return;
- }
+ saveIfInactive(classicComicsView);
+ saveIfInactive(gridComicsView);
+ saveIfInactive(infoComicsView);
- if (!libraryWindow->listsView->selectionModel()->selectedRows().isEmpty()) {
- auto currentListIndex = libraryWindow->listsModelProxy->mapToSource(libraryWindow->listsView->currentIndex());
- if (currentListIndex.isValid()) {
- libraryWindow->navigationController->loadListInfo(currentListIndex);
- return;
- }
- }
+ comicsView->close();
+}
- libraryWindow->navigationController->loadFolderInfo(libraryWindow->getCurrentFolderIndex());
+ContentViewState YACReaderContentViewsManager::captureViewState() const
+{
+ const auto *view = qobject_cast(comicsViewStack->currentWidget());
+ return view ? view->captureViewState() : ContentViewState { };
}
-void YACReaderContentViewsManager::updateCurrentComicView()
+void YACReaderContentViewsManager::restoreViewState(const ContentViewState &state)
{
- if (comicsViewStack->currentWidget() == comicsView) {
- comicsView->updateCurrentComicView();
- }
+ if (auto *view = qobject_cast(comicsViewStack->currentWidget()))
+ view->restoreViewState(state);
}
-void YACReaderContentViewsManager::updateContinueReadingView()
+void YACReaderContentViewsManager::updateCurrentComicView()
{
- if (comicsViewStack->currentWidget() == folderContentView) {
- folderContentView->reloadContinueReadingModel();
+ if (comicsViewStack->currentWidget() == comicsView) {
+ comicsView->updateCurrentComicView();
}
}
@@ -131,7 +129,9 @@ void YACReaderContentViewsManager::toNormal()
void YACReaderContentViewsManager::showComicsView()
{
- comicsViewStack->setCurrentWidget(comicsView);
+ setToolBarOwner(comicsView);
+
+ showStackWidget(comicsView, true);
// TODO: check if this is still needed in the rhi implementation
// BUG, ugly workaround for glitch when QOpenGLWidget (flow) is used just after any other widget in the views stack
@@ -139,50 +139,67 @@ void YACReaderContentViewsManager::showComicsView()
libraryWindow->sideBar->update();
}
-void YACReaderContentViewsManager::showFolderContentView()
+void YACReaderContentViewsManager::showFoldersOnlyGrid()
{
- comicsViewStack->setCurrentWidget(folderContentView);
+ setToolBarOwner(gridComicsView);
+ connectComicsViewConnections(gridComicsView);
+ ensureInStack(gridComicsView);
+ showStackWidget(gridComicsView, false);
}
-void YACReaderContentViewsManager::showEmptyLabelView()
+void YACReaderContentViewsManager::showEmptyLabel(YACReader::LabelColors color)
{
- comicsViewStack->setCurrentWidget(emptyLabelWidget);
+ emptyLabelWidget->setColor(color);
+ showStackWidget(emptyLabelWidget, true);
}
-void YACReaderContentViewsManager::showEmptySpecialList()
+void YACReaderContentViewsManager::showEmptySpecialList(ReadingListModel::TypeSpecialList type)
{
- comicsViewStack->setCurrentWidget(emptySpecialList);
+ switch (type) {
+ case ReadingListModel::TypeSpecialList::Favorites:
+ emptySpecialList->showFavorites();
+ break;
+ case ReadingListModel::TypeSpecialList::Reading:
+ emptySpecialList->showReading();
+ break;
+ case ReadingListModel::TypeSpecialList::Recent:
+ emptySpecialList->showRecent();
+ break;
+ }
+
+ showStackWidget(emptySpecialList, true);
}
-void YACReaderContentViewsManager::showEmptyReadingListWidget()
+void YACReaderContentViewsManager::showEmptyReadingList()
{
- comicsViewStack->setCurrentWidget(emptyReadingList);
+ showStackWidget(emptyReadingList, true);
}
-void YACReaderContentViewsManager::showEmptyFolderWidget()
+void YACReaderContentViewsManager::showEmptyFolder()
{
- comicsViewStack->setCurrentWidget(emptyFolderWidget);
+ showStackWidget(emptyFolderWidget, false);
}
-void YACReaderContentViewsManager::showNoSearchResultsView()
+void YACReaderContentViewsManager::showNoSearchResults()
{
- comicsViewStack->setCurrentWidget(noSearchResultsWidget);
+ showStackWidget(noSearchResultsWidget, true);
}
-// TODO recover the current comics selection and restore it in the destination
void YACReaderContentViewsManager::toggleComicsView()
{
+ const auto viewState = captureViewState();
if (comicsViewStack->currentWidget() == comicsView) {
QTimer::singleShot(0, this, &YACReaderContentViewsManager::showComicsViewTransition);
- QTimer::singleShot(100, this, &YACReaderContentViewsManager::_toggleComicsView);
+ QTimer::singleShot(100, this, [this, viewState]() { switchToNextComicsView(viewState); });
} else {
- _toggleComicsView();
+ switchToNextComicsView(viewState);
}
}
void YACReaderContentViewsManager::focusComicsViewViaShortcut()
{
- comicsView->focusComicsNavigation(Qt::ShortcutFocusReason);
+ if (auto *currentView = qobject_cast(comicsViewStack->currentWidget()))
+ currentView->focusComicsNavigation(Qt::ShortcutFocusReason);
}
// PROTECTED
@@ -194,41 +211,42 @@ void YACReaderContentViewsManager::disconnectComicsViewConnections(ComicsView *w
disconnect(widget, &ComicsView::selected, libraryWindow, QOverload<>::of(&LibraryWindow::openComic));
disconnect(widget, &ComicsView::openComic, libraryWindow, QOverload::of(&LibraryWindow::openComic));
disconnect(libraryWindow->actions.selectAllComicsAction, &QAction::triggered, widget, &ComicsView::selectAll);
- disconnect(comicsView, &ComicsView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
- disconnect(comicsView, &ComicsView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
- disconnect(comicsView, &ComicsView::customContextMenuViewRequested, libraryWindow, &LibraryWindow::showComicsViewContextMenu);
- disconnect(comicsView, &ComicsView::customContextMenuItemRequested, libraryWindow, &LibraryWindow::showComicsItemContextMenu);
+ disconnect(widget, &ComicsView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
+ disconnect(widget, &ComicsView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
+ disconnect(widget, &ComicsView::customContextMenuViewRequested, libraryWindow, &LibraryWindow::showComicsViewContextMenu);
+ disconnect(widget, &ComicsView::customContextMenuItemRequested, libraryWindow, &LibraryWindow::showComicsItemContextMenu);
}
-void YACReaderContentViewsManager::doComicsViewConnections()
+void YACReaderContentViewsManager::connectComicsViewConnections(ComicsView *view)
{
- connect(comicsView, &ComicsView::comicRated, libraryWindow->comicsModel, &ComicModel::updateRating);
- connect(libraryWindow->actions.showHideMarksAction, &QAction::toggled, comicsView, &ComicsView::setShowMarks);
- connect(comicsView, &ComicsView::selected, libraryWindow, QOverload<>::of(&LibraryWindow::openComic));
- connect(comicsView, &ComicsView::openComic, libraryWindow, QOverload::of(&LibraryWindow::openComic));
+ connect(view, &ComicsView::comicRated, libraryWindow->comicsModel, &ComicModel::updateRating, Qt::UniqueConnection);
+ connect(libraryWindow->actions.showHideMarksAction, &QAction::toggled, view, &ComicsView::setShowMarks, Qt::UniqueConnection);
+ connect(view, &ComicsView::selected, libraryWindow, QOverload<>::of(&LibraryWindow::openComic), Qt::UniqueConnection);
+ connect(view, &ComicsView::openComic, libraryWindow, QOverload::of(&LibraryWindow::openComic), Qt::UniqueConnection);
- connect(libraryWindow->actions.selectAllComicsAction, &QAction::triggered, comicsView, &ComicsView::selectAll);
+ connect(libraryWindow->actions.selectAllComicsAction, &QAction::triggered, view, &ComicsView::selectAll, Qt::UniqueConnection);
- connect(comicsView, &ComicsView::customContextMenuViewRequested, libraryWindow, &LibraryWindow::showComicsViewContextMenu);
- connect(comicsView, &ComicsView::customContextMenuItemRequested, libraryWindow, &LibraryWindow::showComicsItemContextMenu);
+ connect(view, &ComicsView::customContextMenuViewRequested, libraryWindow, &LibraryWindow::showComicsViewContextMenu, Qt::UniqueConnection);
+ connect(view, &ComicsView::customContextMenuItemRequested, libraryWindow, &LibraryWindow::showComicsItemContextMenu, Qt::UniqueConnection);
// Drops
- connect(comicsView, &ComicsView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
- connect(comicsView, &ComicsView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
+ connect(view, &ComicsView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder, Qt::UniqueConnection);
+ connect(view, &ComicsView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder, Qt::UniqueConnection);
}
-void YACReaderContentViewsManager::switchToComicsView(ComicsView *from, ComicsView *to)
+void YACReaderContentViewsManager::switchToComicsView(ComicsView *from, ComicsView *to, const ContentViewState &viewState)
{
// setup views
disconnectComicsViewConnections(from);
- from->close();
+ from->saveViewConfig();
+ from->hide();
comicsView = to;
- doComicsViewConnections();
+ connectComicsViewConnections(comicsView);
- comicsView->setToolBar(libraryWindow->editInfoToolBar);
+ setToolBarOwner(comicsView);
comicsViewStack->removeWidget(from);
- comicsViewStack->addWidget(comicsView);
+ ensureInStack(comicsView);
// delete from; No need to delete the previews view, because all views are going to be kept in memory
@@ -238,66 +256,120 @@ void YACReaderContentViewsManager::switchToComicsView(ComicsView *from, ComicsVi
if (!libraryWindow->searchText().isEmpty()) {
comicsView->enableFilterMode(true);
}
+
+ to->restoreViewState(viewState);
+ updateComicActionsForCurrentView();
}
-void YACReaderContentViewsManager::showComicsViewTransition()
+void YACReaderContentViewsManager::ensureInStack(ComicsView *view)
{
- comicsViewStack->setCurrentWidget(comicsViewTransition);
+ if (comicsViewStack->indexOf(view) < 0)
+ comicsViewStack->addWidget(view);
+}
+
+void YACReaderContentViewsManager::showStackWidget(QWidget *widget, bool viewSelectorEnabled)
+{
+ // showFoldersOnlyGrid() lends the comics view connections to gridComicsView while
+ // another view mode owns comicsView. Take them back as soon as the grid stops
+ // being shown, otherwise it keeps reacting to comic actions while hidden.
+ if (widget != gridComicsView && comicsView != gridComicsView)
+ disconnectComicsViewConnections(gridComicsView);
+
+ comicsViewStack->setCurrentWidget(widget);
+ setViewSelectorEnabled(viewSelectorEnabled);
}
-void YACReaderContentViewsManager::_toggleComicsView()
+void YACReaderContentViewsManager::updateComicActionsForCurrentView()
+{
+ if (libraryWindow->comicsModel == nullptr)
+ return;
+
+ libraryWindow->setComicActionsDisabled(libraryWindow->comicsModel->rowCount() == 0);
+
+ // Only the grid tracks a live comic selection, and it can have a folder focused
+ // instead of a comic. Every other view keeps the comic actions available as long
+ // as the current content has comics.
+ if (comicsView == gridComicsView)
+ libraryWindow->actions.setComicSelectionActionsEnabled(gridComicsView->hasComicSelection());
+}
+
+void YACReaderContentViewsManager::setToolBarOwner(ComicsView *view)
+{
+ if (!view || toolbarOwner == view)
+ return;
+
+ if (toolbarOwner)
+ toolbarOwner->releaseToolBar();
+
+ view->setToolBar(libraryWindow->editInfoToolBar);
+ toolbarOwner = view;
+}
+
+void YACReaderContentViewsManager::setViewSelectorEnabled(bool enabled)
+{
+ libraryWindow->actions.toggleComicsViewAction->setEnabled(enabled);
+}
+
+void YACReaderContentViewsManager::updateViewSelectorIcon(const Theme &theme)
{
const auto &mainToolbar = theme.mainToolbar;
+ QIcon icon;
switch (comicsViewStatus) {
- case Flow: {
- QIcon icoViewsButton = mainToolbar.infoIcon;
- libraryWindow->actions.toggleComicsViewAction->setIcon(icoViewsButton);
+ case Flow:
+ icon = mainToolbar.gridIcon;
+ break;
+ case Grid:
+ icon = mainToolbar.infoIcon;
+ break;
+ case Info:
+ icon = mainToolbar.flowIcon;
+ break;
+ }
+
+ libraryWindow->actions.toggleComicsViewAction->setIcon(icon);
#ifdef Y_MAC_UI
- libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);
+ libraryWindow->libraryToolBar->updateViewSelectorIcon(icon);
#endif
- if (gridComicsView == nullptr)
- gridComicsView = new GridComicsView();
+}
- switchToComicsView(classicComicsView, gridComicsView);
- connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, gridComicsView, &GridComicsView::updateBackgroundConfig);
- connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::finished, gridComicsView, &GridComicsView::updateSettings); // TODO: we can link constante changes to updateSettings because of bad performance
+void YACReaderContentViewsManager::showComicsViewTransition()
+{
+ comicsViewStack->setCurrentWidget(comicsViewTransition);
+}
+
+void YACReaderContentViewsManager::switchToNextComicsView(const ContentViewState &viewState)
+{
+ switch (comicsViewStatus) {
+ case Flow: {
+ switchToComicsView(classicComicsView, gridComicsView, viewState);
comicsViewStatus = Grid;
break;
}
case Grid: {
- QIcon icoViewsButton = mainToolbar.flowIcon;
- libraryWindow->actions.toggleComicsViewAction->setIcon(icoViewsButton);
-#ifdef Y_MAC_UI
- libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);
-#endif
if (infoComicsView == nullptr)
infoComicsView = new InfoComicsView();
- switchToComicsView(gridComicsView, infoComicsView);
+ switchToComicsView(gridComicsView, infoComicsView, viewState);
comicsViewStatus = Info;
break;
}
case Info: {
- QIcon icoViewsButton = mainToolbar.gridIcon;
- libraryWindow->actions.toggleComicsViewAction->setIcon(icoViewsButton);
-#ifdef Y_MAC_UI
- libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);
-#endif
if (classicComicsView == nullptr)
classicComicsView = new ClassicComicsView();
- switchToComicsView(infoComicsView, classicComicsView);
+ switchToComicsView(infoComicsView, classicComicsView, viewState);
comicsViewStatus = Flow;
break;
}
}
+ updateViewSelectorIcon(theme);
libraryWindow->settings->setValue(COMICS_VIEW_STATUS, comicsViewStatus);
if (comicsViewStack->currentWidget() == comicsViewTransition)
@@ -306,25 +378,5 @@ void YACReaderContentViewsManager::_toggleComicsView()
void YACReaderContentViewsManager::applyTheme(const Theme &theme)
{
- const auto &mainToolbar = theme.mainToolbar;
-
- // Update the toggle button icon based on current view status
- // The icon shows what the NEXT view will be when clicked
- QIcon icon;
- switch (comicsViewStatus) {
- case Flow:
- icon = mainToolbar.gridIcon;
- break;
- case Grid:
- icon = mainToolbar.infoIcon;
- break;
- case Info:
- icon = mainToolbar.flowIcon;
- break;
- }
-
- libraryWindow->actions.toggleComicsViewAction->setIcon(icon);
-#ifdef Y_MAC_UI
- libraryWindow->libraryToolBar->updateViewSelectorIcon(icon);
-#endif
+ updateViewSelectorIcon(theme);
}
diff --git a/YACReaderLibrary/yacreader_content_views_manager.h b/YACReaderLibrary/yacreader_content_views_manager.h
index e78a1f62f..41d50c020 100644
--- a/YACReaderLibrary/yacreader_content_views_manager.h
+++ b/YACReaderLibrary/yacreader_content_views_manager.h
@@ -1,6 +1,8 @@
#ifndef YACREADERCONTENTVIEWSMANAGER_H
#define YACREADERCONTENTVIEWSMANAGER_H
+#include "content_view_state.h"
+#include "reading_list_model.h"
#include "themable.h"
#include "yacreader_global_gui.h"
@@ -10,16 +12,17 @@
class LibraryWindow;
class ComicsView;
+class ComicModel;
class ClassicComicsView;
class GridComicsView;
class InfoComicsView;
class ComicsViewTransition;
-class FolderContentView;
class EmptyLabelWidget;
class EmptySpecialListWidget;
class EmptyReadingListWidget;
class EmptyFolderWidget;
class NoSearchResultsWidget;
+class FolderModel;
using namespace YACReader;
@@ -30,22 +33,17 @@ class YACReaderContentViewsManager : public QObject, protected Themable
explicit YACReaderContentViewsManager(QSettings *settings, LibraryWindow *parent = nullptr);
QWidget *containerWidget();
+ GridComicsView *gridView() const;
+ bool isComicsViewVisible() const;
+ void prepareToClose();
+ ContentViewState captureViewState() const;
+ void restoreViewState(const ContentViewState &state);
ComicsView *comicsView;
ComicsViewTransition *comicsViewTransition;
- FolderContentView *folderContentView;
- EmptyLabelWidget *emptyLabelWidget;
- EmptySpecialListWidget *emptySpecialList;
- EmptyReadingListWidget *emptyReadingList;
- EmptyFolderWidget *emptyFolderWidget;
-
- NoSearchResultsWidget *noSearchResultsWidget;
-
- void updateCurrentContentView();
void updateCurrentComicView();
- void updateContinueReadingView();
void toFullscreen();
void toNormal();
@@ -59,31 +57,42 @@ class YACReaderContentViewsManager : public QObject, protected Themable
ClassicComicsView *classicComicsView;
GridComicsView *gridComicsView;
InfoComicsView *infoComicsView;
+ ComicsView *toolbarOwner;
- void applyTheme(const Theme &theme) override;
+ EmptyLabelWidget *emptyLabelWidget;
+ EmptySpecialListWidget *emptySpecialList;
+ EmptyReadingListWidget *emptyReadingList;
+ EmptyFolderWidget *emptyFolderWidget;
+ NoSearchResultsWidget *noSearchResultsWidget;
-signals:
+ void applyTheme(const Theme &theme) override;
public slots:
void toggleComicsView();
void focusComicsViewViaShortcut();
void showComicsView();
- void showFolderContentView();
- void showEmptyLabelView();
- void showEmptySpecialList();
- void showEmptyReadingListWidget();
- void showEmptyFolderWidget();
- void showNoSearchResultsView();
+ void showFoldersOnlyGrid();
+ void showEmptyLabel(YACReader::LabelColors color);
+ void showEmptySpecialList(ReadingListModel::TypeSpecialList type);
+ void showEmptyReadingList();
+ void showEmptyFolder();
+ void showNoSearchResults();
protected slots:
void showComicsViewTransition();
- void _toggleComicsView();
void disconnectComicsViewConnections(ComicsView *widget);
- void doComicsViewConnections();
-
- void switchToComicsView(ComicsView *from, ComicsView *to);
+ void connectComicsViewConnections(ComicsView *view);
+
+ void switchToNextComicsView(const ContentViewState &viewState);
+ void switchToComicsView(ComicsView *from, ComicsView *to, const ContentViewState &viewState);
+ void setToolBarOwner(ComicsView *view);
+ void setViewSelectorEnabled(bool enabled);
+ void updateViewSelectorIcon(const Theme &theme);
+ void ensureInStack(ComicsView *view);
+ void showStackWidget(QWidget *widget, bool viewSelectorEnabled);
+ void updateComicActionsForCurrentView();
};
#endif // YACREADERCONTENTVIEWSMANAGER_H
diff --git a/YACReaderLibrary/yacreader_history_controller.cpp b/YACReaderLibrary/yacreader_history_controller.cpp
index 9ac7d4017..a8ceacf2f 100644
--- a/YACReaderLibrary/yacreader_history_controller.cpp
+++ b/YACReaderLibrary/yacreader_history_controller.cpp
@@ -15,9 +15,10 @@ void YACReaderHistoryController::clear()
emit enabledForward(false);
}
-void YACReaderHistoryController::backward()
+void YACReaderHistoryController::backward(const ContentViewState ¤tViewState)
{
if (currentFolderNavigation > 0) {
+ history[currentFolderNavigation].viewState = currentViewState;
currentFolderNavigation--;
emit modelIndexSelected(history.at(currentFolderNavigation));
emit enabledForward(true);
@@ -27,9 +28,10 @@ void YACReaderHistoryController::backward()
emit enabledBackward(false);
}
-void YACReaderHistoryController::forward()
+void YACReaderHistoryController::forward(const ContentViewState ¤tViewState)
{
if (currentFolderNavigation < history.count() - 1) {
+ history[currentFolderNavigation].viewState = currentViewState;
currentFolderNavigation++;
emit modelIndexSelected(history.at(currentFolderNavigation));
emit enabledBackward(true);
@@ -39,6 +41,12 @@ void YACReaderHistoryController::forward()
emit enabledForward(false);
}
+void YACReaderHistoryController::recordViewStateForCurrentEntry(const ContentViewState &state)
+{
+ if (!history.isEmpty())
+ history[currentFolderNavigation].viewState = state;
+}
+
void YACReaderHistoryController::updateHistory(const YACReaderLibrarySourceContainer &source)
{
// remove history from current index
@@ -93,6 +101,11 @@ YACReaderLibrarySourceContainer::SourceType YACReaderLibrarySourceContainer::get
return type;
}
+ContentViewState YACReaderLibrarySourceContainer::getViewState() const
+{
+ return viewState;
+}
+
bool YACReaderLibrarySourceContainer::operator==(const YACReaderLibrarySourceContainer &other) const
{
return sourceModelIndex == other.sourceModelIndex && type == other.type;
diff --git a/YACReaderLibrary/yacreader_history_controller.h b/YACReaderLibrary/yacreader_history_controller.h
index 8bf539d6b..4ef66e35a 100644
--- a/YACReaderLibrary/yacreader_history_controller.h
+++ b/YACReaderLibrary/yacreader_history_controller.h
@@ -1,6 +1,8 @@
#ifndef YACREADER_HISTORY_CONTROLLER_H
#define YACREADER_HISTORY_CONTROLLER_H
+#include "content_view_state.h"
+
#include
#include
@@ -19,6 +21,7 @@ class YACReaderLibrarySourceContainer
explicit YACReaderLibrarySourceContainer(const QModelIndex &sourceModelIndex, YACReaderLibrarySourceContainer::SourceType type);
QModelIndex getSourceModelIndex() const;
YACReaderLibrarySourceContainer::SourceType getType() const;
+ ContentViewState getViewState() const;
bool operator==(const YACReaderLibrarySourceContainer &other) const;
bool operator!=(const YACReaderLibrarySourceContainer &other) const;
@@ -26,6 +29,7 @@ class YACReaderLibrarySourceContainer
protected:
QModelIndex sourceModelIndex;
YACReaderLibrarySourceContainer::SourceType type;
+ ContentViewState viewState;
friend class YACReaderHistoryController;
};
@@ -45,9 +49,10 @@ class YACReaderHistoryController : public QObject
public slots:
void clear();
- void backward();
- void forward();
+ void backward(const ContentViewState ¤tViewState);
+ void forward(const ContentViewState ¤tViewState);
void updateHistory(const YACReaderLibrarySourceContainer &source);
+ void recordViewStateForCurrentEntry(const ContentViewState &state);
YACReaderLibrarySourceContainer lastSourceContainer();
YACReaderLibrarySourceContainer currentSourceContainer();
diff --git a/YACReaderLibrary/yacreader_navigation_controller.cpp b/YACReaderLibrary/yacreader_navigation_controller.cpp
index 2e728a5ff..85081913e 100644
--- a/YACReaderLibrary/yacreader_navigation_controller.cpp
+++ b/YACReaderLibrary/yacreader_navigation_controller.cpp
@@ -3,44 +3,49 @@
#include "QsLog.h"
#include "comic_model.h"
#include "comics_view.h"
+#include "db_helper.h"
#include "empty_label_widget.h"
#include "empty_special_list.h"
-#include "folder_content_view.h"
#include "folder_item.h"
#include "folder_model.h"
+#include "grid_comics_view.h"
#include "library_window.h"
#include "reading_list_model.h"
#include "yacreader_content_views_manager.h"
#include "yacreader_folders_view.h"
#include "yacreader_global.h"
#include "yacreader_history_controller.h"
+#include "yacreader_library_list_widget.h"
#include "yacreader_reading_lists_view.h"
#include
+#include
+
YACReaderNavigationController::YACReaderNavigationController(LibraryWindow *parent, YACReaderContentViewsManager *contentViewsManager)
: QObject(parent), libraryWindow(parent), contentViewsManager(contentViewsManager)
{
setupConnections();
}
-void YACReaderNavigationController::selectedFolder(const QModelIndex &mi)
+void YACReaderNavigationController::selectedFolder(const QModelIndex &proxyIndex)
{
- // A proxy is used
- QModelIndex modelIndex = libraryWindow->foldersModelProxy->mapToSource(mi);
+ const QModelIndex folderIndex = libraryWindow->foldersModelProxy->mapToSource(proxyIndex);
- // update history
- libraryWindow->historyController->updateHistory(YACReaderLibrarySourceContainer(modelIndex, YACReaderLibrarySourceContainer::Folder));
+ if (!restoringHistorySelection) {
+ recordCurrentViewState();
+ libraryWindow->historyController->updateHistory(YACReaderLibrarySourceContainer(folderIndex, YACReaderLibrarySourceContainer::Folder));
+ }
// when a folder is selected the search mode has to be reset
if (libraryWindow->exitSearchMode()) {
- libraryWindow->foldersView->scrollTo(modelIndex, QAbstractItemView::PositionAtTop);
- libraryWindow->foldersView->setCurrentIndex(modelIndex);
+ libraryWindow->foldersView->scrollTo(folderIndex, QAbstractItemView::PositionAtTop);
+ libraryWindow->foldersView->setCurrentIndex(folderIndex);
}
- loadFolderInfo(modelIndex);
+ loadFolderContent(folderIndex);
- libraryWindow->setToolbarTitle(modelIndex);
+ libraryWindow->setToolbarTitle(folderIndex);
}
void YACReaderNavigationController::reselectCurrentFolder()
@@ -48,60 +53,64 @@ void YACReaderNavigationController::reselectCurrentFolder()
selectedFolder(libraryWindow->foldersView->currentIndex());
}
-void YACReaderNavigationController::loadFolderInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadFolderContent(const QModelIndex &folderIndex)
{
- // Get FolderItem
- qulonglong folderId = folderModelIndexToID(modelIndex);
+ const qulonglong folderId = folderIdForIndex(folderIndex);
+ const bool isRoot = folderId == FolderModel::RootFolderId;
- // check comics in folder with id = folderId
libraryWindow->comicsModel->setupFolderModelData(folderId, libraryWindow->foldersModel->getDatabase());
- // configure views
+ if (isRoot) {
+ loadRootContinueReading();
+ } else {
+ contentViewsManager->gridView()->clearRootContinueReadingModel();
+ }
+
+ const auto libraryName = libraryWindow->selectedLibrary->currentText();
+ const auto libraryInfo = isRoot ? DBHelper::getLibraryInfoData(libraryWindow->libraries.getUuid(libraryName)) : QVariantMap();
+ contentViewsManager->gridView()->setFolderModel(libraryWindow->foldersModel, folderIndex, libraryName, libraryInfo);
+
if (libraryWindow->comicsModel->rowCount() > 0) {
- // updateView
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
contentViewsManager->showComicsView();
- libraryWindow->disableComicsActions(false);
- } else if (libraryWindow->foldersModel->rowCount(modelIndex) > 0 || !modelIndex.isValid()) {
- // folder has subfolders (or is root), show folder content view
- loadEmptyFolderInfo(modelIndex);
- contentViewsManager->showFolderContentView();
- libraryWindow->disableComicsActions(true);
+ libraryWindow->setComicActionsDisabled(false);
+ } else if (libraryWindow->foldersModel->rowCount(folderIndex) > 0) {
+ // Folder has subfolders, so show the unified content grid.
+ contentViewsManager->gridView()->setModel(libraryWindow->comicsModel);
+ contentViewsManager->showFoldersOnlyGrid();
+ libraryWindow->setComicActionsDisabled(true);
} else {
- // folder has no comics and no subfolders
- contentViewsManager->showEmptyFolderWidget();
- libraryWindow->disableComicsActions(true);
+ contentViewsManager->showEmptyFolder();
+ libraryWindow->setComicActionsDisabled(true);
}
-
- // libraryWindow->updateFoldersViewConextMenu(modelIndex);
-
// if a folder is selected, listsView selection must be cleared
libraryWindow->listsView->clearSelection();
}
-void YACReaderNavigationController::loadListInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadListContent(const QModelIndex &listIndex)
{
- switch (modelIndex.data(ReadingListModel::TypeListsRole).toInt()) {
+ contentViewsManager->gridView()->clearFolderModel();
+ switch (listIndex.data(ReadingListModel::TypeListsRole).toInt()) {
case ReadingListModel::SpecialList:
- loadSpecialListInfo(modelIndex);
+ loadSpecialListContent(listIndex);
break;
case ReadingListModel::Label:
- loadLabelInfo(modelIndex);
+ loadLabelContent(listIndex);
break;
case ReadingListModel::ReadingList:
- loadReadingListInfo(modelIndex);
+ loadReadingListContent(listIndex);
break;
}
-
+ contentViewsManager->gridView()->setCurrentList(listIndex);
// if a list is selected, foldersView selection must be cleared
libraryWindow->foldersView->clearSelection();
}
-void YACReaderNavigationController::loadSpecialListInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadSpecialListContent(const QModelIndex &listIndex)
{
- ReadingListModel::TypeSpecialList type = (ReadingListModel::TypeSpecialList)modelIndex.data(ReadingListModel::SpecialListTypeRole).toInt();
+ const auto type = static_cast(listIndex.data(ReadingListModel::SpecialListTypeRole).toInt());
switch (type) {
case ReadingListModel::TypeSpecialList::Favorites:
@@ -119,29 +128,16 @@ void YACReaderNavigationController::loadSpecialListInfo(const QModelIndex &model
if (libraryWindow->comicsModel->rowCount() > 0) {
contentViewsManager->showComicsView();
- libraryWindow->disableComicsActions(false);
+ libraryWindow->setComicActionsDisabled(false);
} else {
- // setup empty special list widget
- switch (type) {
- case ReadingListModel::TypeSpecialList::Favorites:
- contentViewsManager->emptySpecialList->showFavorites();
- break;
- case ReadingListModel::TypeSpecialList::Reading:
- contentViewsManager->emptySpecialList->showReading();
- break;
- case ReadingListModel::TypeSpecialList::Recent:
- contentViewsManager->emptySpecialList->showRecent();
- break;
- }
-
- contentViewsManager->showEmptySpecialList();
- libraryWindow->disableComicsActions(true);
+ contentViewsManager->showEmptySpecialList(type);
+ libraryWindow->setComicActionsDisabled(true);
}
}
-void YACReaderNavigationController::loadLabelInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadLabelContent(const QModelIndex &listIndex)
{
- qulonglong id = modelIndex.data(ReadingListModel::IDRole).toULongLong();
+ const qulonglong id = listIndex.data(ReadingListModel::IDRole).toULongLong();
// check comics in label with id = id
libraryWindow->comicsModel->setupLabelModelData(id, libraryWindow->foldersModel->getDatabase());
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
@@ -150,19 +146,18 @@ void YACReaderNavigationController::loadLabelInfo(const QModelIndex &modelIndex)
if (libraryWindow->comicsModel->rowCount() > 0) {
// updateView
contentViewsManager->showComicsView();
- libraryWindow->disableComicsActions(false);
+ libraryWindow->setComicActionsDisabled(false);
} else {
// showEmptyFolder
// loadEmptyLabelInfo(); //there is no info in an empty label by now, TODO design something
- contentViewsManager->emptyLabelWidget->setColor((YACReader::LabelColors)modelIndex.data(ReadingListModel::LabelColorRole).toInt());
- contentViewsManager->showEmptyLabelView();
- libraryWindow->disableComicsActions(true);
+ contentViewsManager->showEmptyLabel(static_cast(listIndex.data(ReadingListModel::LabelColorRole).toInt()));
+ libraryWindow->setComicActionsDisabled(true);
}
}
-void YACReaderNavigationController::loadReadingListInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadReadingListContent(const QModelIndex &listIndex)
{
- qulonglong id = modelIndex.data(ReadingListModel::IDRole).toULongLong();
+ const qulonglong id = listIndex.data(ReadingListModel::IDRole).toULongLong();
// check comics in label with id = id
libraryWindow->comicsModel->setupReadingListModelData(id, libraryWindow->foldersModel->getDatabase());
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
@@ -171,31 +166,30 @@ void YACReaderNavigationController::loadReadingListInfo(const QModelIndex &model
if (libraryWindow->comicsModel->rowCount() > 0) {
// updateView
contentViewsManager->showComicsView();
- libraryWindow->disableComicsActions(false);
+ libraryWindow->setComicActionsDisabled(false);
} else {
- contentViewsManager->showEmptyReadingListWidget();
- libraryWindow->disableComicsActions(true);
+ contentViewsManager->showEmptyReadingList();
+ libraryWindow->setComicActionsDisabled(true);
}
}
-void YACReaderNavigationController::selectedList(const QModelIndex &mi)
+void YACReaderNavigationController::selectedList(const QModelIndex &proxyIndex)
{
- // A proxy is used
- QModelIndex modelIndex = libraryWindow->listsModelProxy->mapToSource(mi);
+ const QModelIndex listIndex = libraryWindow->listsModelProxy->mapToSource(proxyIndex);
- // update history
- libraryWindow->historyController->updateHistory(YACReaderLibrarySourceContainer(modelIndex, YACReaderLibrarySourceContainer::List));
+ recordCurrentViewState();
+ libraryWindow->historyController->updateHistory(YACReaderLibrarySourceContainer(listIndex, YACReaderLibrarySourceContainer::List));
// when a list is selected the search mode has to be reset
if (libraryWindow->exitSearchMode()) {
- libraryWindow->listsView->scrollTo(mi, QAbstractItemView::PositionAtTop);
- libraryWindow->listsView->setCurrentIndex(mi);
+ libraryWindow->listsView->scrollTo(proxyIndex, QAbstractItemView::PositionAtTop);
+ libraryWindow->listsView->setCurrentIndex(proxyIndex);
}
- loadListInfo(modelIndex);
+ loadListContent(listIndex);
- libraryWindow->setToolbarTitle(modelIndex);
+ libraryWindow->setToolbarTitle(listIndex);
}
void YACReaderNavigationController::reselectCurrentList()
@@ -215,12 +209,71 @@ void YACReaderNavigationController::reselectCurrentSource()
}
}
+void YACReaderNavigationController::beginCurrentSourceRefresh()
+{
+ pendingRefreshViewState = contentViewsManager->captureViewState();
+}
+
+void YACReaderNavigationController::cancelCurrentSourceRefresh()
+{
+ pendingRefreshViewState.reset();
+}
+
+void YACReaderNavigationController::refreshCurrentSource()
+{
+ if (!libraryWindow->hasLoadedLibraryModels()) {
+ pendingRefreshViewState.reset();
+ return;
+ }
+
+ // Reloading resets the models used by every content view. Keep the view-specific
+ // state outside that operation so each view can restore its stable item anchor
+ // once the refreshed source has been populated.
+ const auto viewState = pendingRefreshViewState.value_or(contentViewsManager->captureViewState());
+ pendingRefreshViewState.reset();
+
+ if (libraryWindow->status == LibraryWindow::Searching) {
+ libraryWindow->comicsModel->reload();
+
+ if (contentViewsManager->isComicsViewVisible())
+ contentViewsManager->comicsView->reloadContent();
+
+ contentViewsManager->restoreViewState(viewState);
+ return;
+ }
+
+ if (!libraryWindow->listsView->selectionModel()->selectedRows().isEmpty()) {
+ auto currentListIndex = libraryWindow->listsModelProxy->mapToSource(libraryWindow->listsView->currentIndex());
+ if (currentListIndex.isValid()) {
+ loadListContent(currentListIndex);
+ contentViewsManager->restoreViewState(viewState);
+ return;
+ }
+ }
+
+ loadFolderContent(libraryWindow->getCurrentFolderIndex());
+ contentViewsManager->restoreViewState(viewState);
+}
+
+void YACReaderNavigationController::backward()
+{
+ libraryWindow->historyController->backward(contentViewsManager->captureViewState());
+}
+
+void YACReaderNavigationController::forward()
+{
+ libraryWindow->historyController->forward(contentViewsManager->captureViewState());
+}
+
void YACReaderNavigationController::selectedIndexFromHistory(const YACReaderLibrarySourceContainer &sourceContainer)
{
// TODO NO searching allowed, just disable backward/forward actions in searching mode
// when a folder or a list is selected the search mode has to be reset
libraryWindow->exitSearchMode();
+ restoringHistorySelection = true;
loadIndexFromHistory(sourceContainer);
+ contentViewsManager->restoreViewState(sourceContainer.getViewState());
+ restoringHistorySelection = false;
libraryWindow->setToolbarTitle(sourceContainer.getSourceModelIndex());
}
@@ -229,20 +282,25 @@ void YACReaderNavigationController::loadIndexFromHistory(const YACReaderLibraryS
QModelIndex sourceMI = sourceContainer.getSourceModelIndex();
switch (sourceContainer.getType()) {
case YACReaderLibrarySourceContainer::Folder: {
+ if (!sourceMI.isValid()) {
+ libraryWindow->setRootIndex(); // TODO: we do a double update, without it the continue reading list height comes later and causes a small flash
+ break;
+ }
+
QModelIndex mi = libraryWindow->foldersModelProxy->mapFromSource(sourceMI);
libraryWindow->foldersView->scrollTo(mi, QAbstractItemView::PositionAtTop);
// currentIndexChanged is about to be emited, but we don't want it to end in YACReaderHistoryController::updateHistory
disconnect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
libraryWindow->foldersView->setCurrentIndex(mi);
connect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
- loadFolderInfo(sourceMI);
+ loadFolderContent(sourceMI);
break;
}
case YACReaderLibrarySourceContainer::List: {
QModelIndex mi = libraryWindow->listsModelProxy->mapFromSource(sourceMI);
libraryWindow->listsView->scrollTo(mi, QAbstractItemView::PositionAtTop);
libraryWindow->listsView->setCurrentIndex(mi);
- loadListInfo(sourceMI);
+ loadListContent(sourceMI);
break;
}
case YACReaderLibrarySourceContainer::None:
@@ -251,28 +309,18 @@ void YACReaderNavigationController::loadIndexFromHistory(const YACReaderLibraryS
}
}
-void YACReaderNavigationController::selectSubfolder(const QModelIndex &sourceMIParent, int child)
-{
- QModelIndex dest = libraryWindow->foldersModel->index(child, 0, sourceMIParent);
- libraryWindow->foldersView->setCurrentIndex(libraryWindow->foldersModelProxy->mapFromSource(dest));
- libraryWindow->historyController->updateHistory(YACReaderLibrarySourceContainer(dest, YACReaderLibrarySourceContainer::Folder));
- loadFolderInfo(dest);
-}
-
-void YACReaderNavigationController::loadEmptyFolderInfo(const QModelIndex &modelIndex)
+void YACReaderNavigationController::loadRootContinueReading()
{
- auto readingComicsModel = new ComicModel();
+ auto readingComicsModel = std::make_unique();
- auto isRoot = !modelIndex.isValid();
+ readingComicsModel->setupReadingModelData(libraryWindow->foldersModel->getDatabase());
- if (isRoot) {
- readingComicsModel->setupReadingModelData(libraryWindow->foldersModel->getDatabase());
- }
-
- contentViewsManager->folderContentView->setContinueReadingModel(readingComicsModel);
+ contentViewsManager->gridView()->setRootContinueReadingModel(std::move(readingComicsModel));
+}
- auto subFolderModel = libraryWindow->foldersModel->getSubfoldersModel(modelIndex);
- contentViewsManager->folderContentView->setModel(modelIndex, subFolderModel);
+void YACReaderNavigationController::reloadRootContinueReading()
+{
+ contentViewsManager->gridView()->reloadRootContinueReadingModel();
}
void YACReaderNavigationController::loadPreviousStatus()
@@ -283,26 +331,39 @@ void YACReaderNavigationController::loadPreviousStatus()
void YACReaderNavigationController::setupConnections()
{
+ auto *gridView = contentViewsManager->gridView();
+
// we need YACReaderTreeView::currentIndexChanged to be able to navigate the folders tree using the keyboard cursors
connect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
connect(libraryWindow->foldersView, &YACReaderTreeView::clicked, this, &YACReaderNavigationController::selectedFolder);
connect(libraryWindow->listsView, &QAbstractItemView::clicked, this, &YACReaderNavigationController::selectedList);
connect(libraryWindow->historyController, &YACReaderHistoryController::modelIndexSelected, this, &YACReaderNavigationController::selectedIndexFromHistory);
- connect(contentViewsManager->folderContentView, &FolderContentView::subfolderSelected, this, &YACReaderNavigationController::selectSubfolder);
- connect(contentViewsManager->folderContentView, &FolderContentView::openComic, libraryWindow, QOverload::of(&LibraryWindow::openComic));
- connect(contentViewsManager->folderContentView, &FolderContentView::openFolderContextMenu, libraryWindow, &LibraryWindow::showGridFoldersContextMenu);
- connect(contentViewsManager->folderContentView, &FolderContentView::openContinueReadingComicContextMenu, libraryWindow, &LibraryWindow::showContinueReadingContextMenu);
+ connect(gridView, &GridComicsView::folderSelected, this, [this](const QModelIndex &index) {
+ libraryWindow->foldersView->setCurrentIndex(libraryWindow->foldersModelProxy->mapFromSource(index));
+ });
+ connect(gridView, &GridComicsView::openFolderContextMenu, libraryWindow, [this, gridView](const QPoint &point, const Folder &folder) {
+ libraryWindow->showGridFoldersContextMenu(gridView->mapToGlobal(point), folder);
+ });
+ connect(gridView, &GridComicsView::openContinueReadingComicContextMenu, libraryWindow, [this, gridView](const QPoint &point, const ComicDB &comic) {
+ libraryWindow->showContinueReadingContextMenu(gridView->mapToGlobal(point), comic);
+ });
+ connect(gridView, &GridComicsView::openLibraryFolderRequested, libraryWindow, &LibraryWindow::openLibraryFolder);
connect(libraryWindow->comicsModel, &ComicModel::isEmpty, this, &YACReaderNavigationController::reselectCurrentSource);
}
-qulonglong YACReaderNavigationController::folderModelIndexToID(const QModelIndex &mi)
+void YACReaderNavigationController::recordCurrentViewState()
+{
+ libraryWindow->historyController->recordViewStateForCurrentEntry(contentViewsManager->captureViewState());
+}
+
+qulonglong YACReaderNavigationController::folderIdForIndex(const QModelIndex &folderIndex) const
{
- if (!mi.isValid())
- return 1;
+ if (!folderIndex.isValid())
+ return FolderModel::RootFolderId;
- auto folderItem = static_cast(mi.internalPointer());
+ auto folderItem = static_cast(folderIndex.internalPointer());
if (folderItem != nullptr)
return folderItem->id;
- return 1;
+ return FolderModel::RootFolderId;
}
diff --git a/YACReaderLibrary/yacreader_navigation_controller.h b/YACReaderLibrary/yacreader_navigation_controller.h
index 74a5588ef..ffab5ae4e 100644
--- a/YACReaderLibrary/yacreader_navigation_controller.h
+++ b/YACReaderLibrary/yacreader_navigation_controller.h
@@ -1,7 +1,12 @@
#ifndef YACREADER_NAVIGATION_CONTROLLER_H
#define YACREADER_NAVIGATION_CONTROLLER_H
+#include "content_view_state.h"
+
#include
+
+#include
+
class LibraryWindow;
class YACReaderLibrarySourceContainer;
class YACReaderContentViewsManager;
@@ -12,42 +17,43 @@ class YACReaderNavigationController : public QObject
public:
explicit YACReaderNavigationController(LibraryWindow *parent, YACReaderContentViewsManager *contentViewsManager);
-signals:
-
public slots:
- // info origins
- // folders view
- void selectedFolder(const QModelIndex &mi);
+ void selectedFolder(const QModelIndex &proxyIndex);
void reselectCurrentFolder();
- // reading lists
- void selectedList(const QModelIndex &mi);
+ void selectedList(const QModelIndex &proxyIndex);
void reselectCurrentList();
void reselectCurrentSource();
+ void beginCurrentSourceRefresh();
+ void cancelCurrentSourceRefresh();
+ void refreshCurrentSource();
// history navigation
+ void backward();
+ void forward();
void selectedIndexFromHistory(const YACReaderLibrarySourceContainer &sourceContainer);
void loadIndexFromHistory(const YACReaderLibrarySourceContainer &sourceContainer);
- // empty subfolder
- void selectSubfolder(const QModelIndex &sourceMI, int child);
-
- void loadEmptyFolderInfo(const QModelIndex &modelIndex);
- void loadFolderInfo(const QModelIndex &modelIndex);
- void loadListInfo(const QModelIndex &modelIndex);
- void loadSpecialListInfo(const QModelIndex &modelIndex);
- void loadLabelInfo(const QModelIndex &modelIndex);
- void loadReadingListInfo(const QModelIndex &modelIndex);
+ void loadFolderContent(const QModelIndex &folderIndex);
+ void loadListContent(const QModelIndex &listIndex);
+ void loadSpecialListContent(const QModelIndex &listIndex);
+ void loadLabelContent(const QModelIndex &listIndex);
+ void loadReadingListContent(const QModelIndex &listIndex);
void loadPreviousStatus();
+ void reloadRootContinueReading();
private:
void setupConnections();
+ void loadRootContinueReading();
+ void recordCurrentViewState();
+
LibraryWindow *libraryWindow;
YACReaderContentViewsManager *contentViewsManager;
+ bool restoringHistorySelection = false;
+ std::optional pendingRefreshViewState;
- // convenience methods
- qulonglong folderModelIndexToID(const QModelIndex &mi);
+ qulonglong folderIdForIndex(const QModelIndex &folderIndex) const;
};
#endif // YACREADER_NAVIGATION_CONTROLLER_H
diff --git a/YACReaderLibrary/yacreaderlibrary_de.ts b/YACReaderLibrary/yacreaderlibrary_de.ts
index ae6a71375..43c53db4e 100644
--- a/YACReaderLibrary/yacreaderlibrary_de.ts
+++ b/YACReaderLibrary/yacreaderlibrary_de.ts
@@ -425,6 +425,14 @@
Herunterladen von Info zu Ausgabe...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Weiterlesen...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Dieser Ordner enthält noch keine Comics
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Nichts ausgewählt
+
+
+
+ Select a comic or folder to see its information.
+ Wählen Sie einen Comic oder Ordner aus, um Informationen anzuzeigen.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Weiterlesen...
+ Weiterlesen...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Unbekannt
+
+
+
+ Items
+ Elemente
+
+
+
+ Type
+ Typ
+
+
+
+ Reading status
+ Lesestatus
+
+
+
+ Read
+ Lesen
+
+
+
+ Unread
+ Ungelesen
+
+
+
+ Collection status
+ Sammlungsstatus
+
+
+
+ Completed
+ Abgeschlossen
+
+
+
+ In progress
+ In Bearbeitung
+
+
+
+ Added
+ Hinzugefügt
+
+
+
+ Updated
+ AktualisiertGridComicsView
-
+ Show infoInfo anzeigen
+
+ Library
+ Bibliothek
+
+
+ Folder
+ Ordner
+
+
+ Favorites
+ Favoriten
+
+
+ Recently added
+ Kürzlich hinzugefügt
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Westlicher Manga
+
+
+
+ Web comic
+ Webcomic
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Comic
+
+
+
+ Unknown
+ Unbekannt
+ HelpAboutDialog
@@ -805,31 +929,54 @@
<p>Die aktuelle Bibliothek wird auf fehlende Cover und unvollständige Comic-Informationen überprüft.</p><p>Dies kann mehrere Minuten dauern. Sie können den Vorgang stoppen und später erneut ausführen.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Informationen zur Bibliothek
+
+
+
+ Number of folders
+ Anzahl der Ordner
+
+
+
+ Number of comics
+ Anzahl der Comics
+
+
+
+ Number of read comics
+ Anzahl der gelesenen Comics
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.Der ausgewählte Ordner enthält keine Bibliothek.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Diese Bibliothek wurde mit einer älteren Version von YACReader erzeugt. Sie muss geupdated werden. Jetzt updaten?
-
+ ComicKomisch
-
+ Error opening the libraryFehler beim Öffnen der Bibliothek
-
-
+
+ YACReader not foundYACReader nicht gefunden
@@ -838,72 +985,72 @@
Entferne und lösche Metadaten
-
+ Old libraryAlte Bibliothek
-
+ Set as completedAls gelesen markieren
-
+ LibraryBibliothek
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Die Bibliothek wurde mit einer neueren Version von YACReader erstellt. Die neue Version jetzt herunterladen?
-
+ Library '%1' is no longer available. Do you want to remove it?Bibliothek '%1' ist nicht mehr verfügbar. Wollen Sie sie entfernen?
-
+ Open folder...Öffne Ordner...
-
+ Do you want remove Möchten Sie entfernen
-
+ Set as uncompletedAls nicht gelesen markieren
-
+ Error updating the libraryFehler beim Updaten der Bibliothek
-
+ FolderOrdner
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?Bibliothek '%1' wurde mit einer älteren Version von YACReader erstellt. Sie muss neu erzeugt werden. Wollen Sie die Bibliothek jetzt erzeugen?
-
+ Set as readAls gelesen markieren
-
+ Library not availableBibliothek nicht verfügbar
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Es gab ein Problem beim Löschen der ausgewählten Comics. Überprüfen Sie bitte die Schreibberechtigung für die ausgewählten Dateien oder Ordner.
@@ -913,301 +1060,301 @@
YACReader Bibliothek
-
+ Error creating the libraryFehler beim Erstellen der Bibliothek
-
+ Update neededUpdate benötigt
-
+ Library name already existsBibliothek-Name bereits vorhanden
-
+ There is another library with the name '%1'.Es gibt bereits eine Bibliothek mit dem Namen '%1'.
-
+ Download new versionNeue Version herunterladen
-
+ Delete comicsComics löschen
-
+ All the selected comics will be deleted from your disk. Are you sure?Alle ausgewählten Comics werden von Ihrer Festplatte gelöscht. Sind Sie sicher?
-
-
+
+ Set as unreadAls ungelesen markieren
-
+ Library not foundBibliothek nicht gefunden
-
-
-
+
+
+ mangaManga
-
-
-
+
+
+ comickomisch
-
-
-
+
+
+ web comicWebcomic
-
-
-
+
+
+ western manga (left to right)Western-Manga (von links nach rechts)
-
-
+
+ Unable to deleteLöschen nicht möglich
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (von oben nach unten)
-
+ library? Bibliothek?
-
+ Are you sure?Sind Sie sicher?
-
+ Rescan library for XML infoDurchsuchen Sie die Bibliothek erneut nach XML-Informationen
-
+ Add new folderNeuen Ordner erstellen
-
+ Delete folderOrdner löschen
-
+ Update folderOrdner aktualisieren
-
+ Upgrade failedUpdate gescheitert
-
+ There were errors during library upgrade in: Beim Upgrade der Bibliothek kam es zu Fehlern in:
-
-
+
+ Copying comics...Kopieren von Comics...
-
-
+
+ Moving comics...Verschieben von Comics...
-
+ Folder name:Ordnername
-
+ No folder selectedKein Ordner ausgewählt
-
+ Please, select a folder firstBitte wählen Sie zuerst einen Ordner aus
-
+ Error in pathFehler im Pfad
-
+ There was an error accessing the folder's pathBeim Aufrufen des Ordnerpfades kam es zu einem Fehler
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?Der ausgewählte Ordner und sein gesamter Inhalt wird von Ihrer Festplatte gelöscht. Sind Sie sicher?
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Beim Löschen des ausgewählten Ordners ist ein Problem aufgetreten. Bitte überprüfen Sie die Schreibrechte und stellen Sie sicher, dass keine Anwendung diese Ordner oder die darin enthaltenen Dateien verwendet.
-
+ Add new reading listsNeue Leseliste hinzufügen
-
-
+
+ List name:Name der Liste
-
+ Delete list/labelAusgewählte/s Liste/Label löschen
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?Das ausgewählte Element wird gelöscht; Ihre Comics oder Ordner werden NICHT von Ihrer Festplatte gelöscht. Sind Sie sicher?
-
+ Rename list nameListenname ändern
-
-
-
-
+
+
+
+ Set typeTyp festlegen
-
+ Search filtersSuchfilter
-
+ UnreadUngelesen
-
+ In progressIn Bearbeitung
-
+ Highly ratedHoch bewertet
-
+ Recently addedKürzlich hinzugefügt
-
+ Search syntax…Suchsyntax…
-
+ A repair of this library is already running (%1). Wait for it to finish.Für diese Bibliothek läuft bereits eine Reparatur (%1). Warten Sie, bis sie abgeschlossen ist.
-
+ The library is locked by a repair that did not finish.Die Bibliothek ist durch eine nicht abgeschlossene Reparatur gesperrt.
-
+ The library is locked by a repair started by %1.Die Bibliothek ist durch eine von %1 gestartete Reparatur gesperrt.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Wenn Sie sicher sind, dass keine andere Reparatur läuft, kann die Sperre entfernt werden. Sperre entfernen und fortfahren?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedWiederherstellung nach Abbruch fehlgeschlagen
-
+ Set custom coverLegen Sie ein benutzerdefiniertes Cover fest
-
+ Delete custom coverBenutzerdefiniertes Cover löschen
-
+ Save coversTitelbilder speichern
-
+ You are adding too many libraries.Sie fügen zu viele Bibliotheken hinzu.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1220,68 +1367,68 @@ Wahrscheinlich brauchen Sie nur eine Bibliothek in Ihrem obersten Comic-Ordner,
YACReaderLibrary wird Sie nicht daran hindern, weitere Bibliotheken zu erstellen, aber Sie sollten die Anzahl der Bibliotheken gering halten.
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader nicht gefunden. YACReader muss im gleichen Ordner installiert sein wie YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader nicht gefunden. Eventuell besteht ein Problem mit Ihrer YACReader-Installation.
-
+ ErrorFehler
-
+ Error opening comic with third party reader.Beim Öffnen des Comics mit dem Drittanbieter-Reader ist ein Fehler aufgetreten.
-
-
+
+ YACReader library database (*.ydb)YACReader-Bibliotheksdatenbank (*.ydb)
-
+ The library database backup was created at:
%1Die Sicherung der Bibliotheksdatenbank wurde hier erstellt:
%1
-
+ Unable to create the library database backup:
%1Die Sicherung der Bibliotheksdatenbank konnte nicht erstellt werden:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Schließen Sie vor der Wiederherstellung YACReaderLibraryServer und alle anderen YACReader-Anwendungen, die diese Bibliothek verwenden. Fortfahren?
-
+ Restoring library database...Bibliotheksdatenbank wird wiederhergestellt...
-
+ The current library database is invalid. Restore the selected backup anyway?Die aktuelle Bibliotheksdatenbank ist ungültig. Die ausgewählte Sicherung trotzdem wiederherstellen?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Die Wartungssperre der Bibliothek ist möglicherweise veraltet. Entfernen und erneut versuchen?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1290,71 +1437,71 @@ Restart YACReaderLibrary before attempting recovery again.
Starten Sie YACReaderLibrary neu, bevor Sie erneut eine Wiederherstellung versuchen.
-
+ The library database was restored successfully. Update the library now?Die Bibliotheksdatenbank wurde erfolgreich wiederhergestellt. Bibliothek jetzt aktualisieren?
-
+ Library database damagedBibliotheksdatenbank beschädigt
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.Die Datenbank der Bibliothek '%1' ist beschädigt, daher sind normale Aktualisierungen, Wartungsarbeiten und Sicherungen nicht verfügbar. YACReader kann versuchen, die Datenbank zu reparieren. Einige beschädigte Daten können möglicherweise nicht wiederhergestellt werden. Vorhandene Sicherungen werden nicht verändert.
-
+ Attempt repairReparatur versuchen
-
+ Restore a backup...Sicherung wiederherstellen...
-
+ Repairing library database...Bibliotheksdatenbank wird repariert...
-
-
-
+
+
+ Library database repairReparatur der Bibliotheksdatenbank
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Ein anderer Wartungsvorgang verwendet diese Bibliothek derzeit. Versuchen Sie es nach dessen Abschluss erneut.
-
+ The library database is already valid.Die Bibliotheksdatenbank ist bereits gültig.
-
+ Library database repairedBibliotheksdatenbank repariert
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1Die Bibliotheksdatenbank wurde durch den Neuaufbau ihrer Indizes repariert. Das beschädigte Original wurde hier aufbewahrt:
%1
-
+ Library database rebuiltBibliotheksdatenbank neu aufgebaut
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1365,7 +1512,7 @@ Update the library now?
Bibliothek jetzt aktualisieren?
-
+
The damaged original was preserved at:
@@ -1376,12 +1523,12 @@ Das beschädigte Original wurde hier aufbewahrt:
%1
-
+ Library database repair failedReparatur der Bibliotheksdatenbank fehlgeschlagen
-
+ The library database could not be repaired:
%1%2
@@ -1392,57 +1539,57 @@ You can restore a backup from the Library menu or recreate the library.
Sie können über das Bibliotheksmenü eine Sicherung wiederherstellen oder die Bibliothek neu erstellen.
-
+ Remove and delete metadata and backupsMetadaten und Sicherungen entfernen und löschen
-
+ Library infoInformationen zur Bibliothek
-
+ Assign comics numbersComics Nummern zuweisen
-
+ Assign numbers starting in:Nummern zuweisen, beginnend mit:
-
+ Invalid imageUngültiges Bild
-
+ The selected file is not a valid image.Die ausgewählte Datei ist kein gültiges Bild.
-
+ Error saving coverFehler beim Speichern des Covers
-
+ There was an error saving the cover image.Beim Speichern des Titelbildes ist ein Fehler aufgetreten.
-
+ Remove comicsComics löschen
-
+ Comics will only be deleted from the current label/list. Are you sure?Comics werden nur vom aktuellen Label/der aktuellen Liste gelöscht. Sind Sie sicher?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Fehlende Dateien: %3
Ausgewählte Comics zu Favoriten hinzufügen
+
+ ListInfoView
+
+
+ 1 comic
+ 1 Comic
+
+
+
+ %1 comics
+ %1 Comics
+
+
+
+ Last day
+ Letzter Tag
+
+
+
+ Last %1 days
+ Letzte %1 Tage
+
+
+
+ 1 sublist
+ 1 Unterliste
+
+
+
+ %1 sublists
+ %1 Unterlisten
+
+LocalComicListModel
@@ -1982,143 +2162,143 @@ Fehlende Dateien: %3
Optionen
-
+ LanguageSprache
-
+ Application languageAnwendungssprache
-
+ System defaultSystemstandard
-
+ Tray icon settings (experimental)Taskleisten-Einstellungen (experimentell)
-
+ Close to trayIn Taskleiste schließen
-
+ Start into the system trayIn die Taskleiste starten
-
+ Edit Comic Vine API keyComic Vine API-Schlüssel ändern
-
+ Comic Vine API keyComic Vine API Schlüssel
-
+ ComicInfo.xml legacy supportComicInfo.xml-Legacy-Unterstützung
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImportieren Sie Metadaten aus ComicInfo.xml, wenn Sie neue Comics hinzufügen
-
+ Consider 'recent' items added or updated since X days agoBerücksichtigen Sie „neue“ Elemente, die seit X Tagen hinzugefügt oder aktualisiert wurden
-
+ Third party readerDrittanbieter-Reader
-
+ Write {comic_file_path} where the path should go in the commandSchreiben Sie {comic_file_path}, wohin der Pfad im Befehl gehen soll
-
+ ClearLöschen
-
+ Update libraries at startupAktualisieren Sie die Bibliotheken beim Start
-
+ Try to detect changes automaticallyVersuchen Sie, Änderungen automatisch zu erkennen
-
+ Update libraries periodicallyAktualisieren Sie die Bibliotheken regelmäßig
-
+ Interval:Intervall:
-
+ 30 minutes30 Minuten
-
+ 1 hour1 Stunde
-
+ 2 hours2 Stunden
-
+ 4 hours4 Stunden
-
+ 8 hours8 Stunden
-
+ 12 hours12 Stunden
-
+ dailytäglich
-
+ Update libraries at certain timeAktualisieren Sie Bibliotheken zu einem bestimmten Zeitpunkt
-
+ Time:Zeit:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2132,60 +2312,75 @@ Bei automatischen Updates blockiert die App einige Aktionen, bis das Update abge
Um eine automatische Aktualisierung zu stoppen, tippen Sie auf die Ladeanzeige neben dem Titel „Bibliotheken“.
-
+ Modifications detectionErkennung von Änderungen
-
+ Compare the modified date of files when updating a library (not recommended)Vergleichen Sie das Änderungsdatum von Dateien beim Aktualisieren einer Bibliothek (nicht empfohlen)
-
+ Enable background imageHintergrundbild aktivieren
-
+ Opacity levelDeckkraft-Stufe
-
+ Blur levelUnschärfe-Stufe
-
+ Use selected comic cover as backgroundDen ausgewählten Comic als Hintergrund verwenden
-
+ Restore defautlsStandardwerte wiederherstellen
-
+ BackgroundHintergrund
-
+ Display continue reading bannerWeiterlesen-Banner anzeigen
-
+ Display current comic bannerAktuelles Comic-Banner anzeigen
-
+ Continue readingWeiterlesen
+
+
+ Mix folders and comics
+ Ordner und Comics mischen
+
+
+
+ Start comics on a new row
+ Comics in einer neuen Zeile beginnen
+
+
+
+ Content
+ Inhalt
+ Comic Flow
@@ -2193,7 +2388,7 @@ Um eine automatische Aktualisierung zu stoppen, tippen Sie auf die Ladeanzeige n
-
+ LibrariesBibliotheken
@@ -3270,53 +3465,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivityServerkonnektivität
-
+ Scan to connectZum Verbinden scannen
-
+ Devices on this network can reach your library at the address below.Geräte in diesem Netzwerk können Ihre Bibliothek unter der unten angegebenen Adresse erreichen.
-
+ IP addressIP-Adresse
-
+ PortAnschluss
-
+ Web interfaceWeboberfläche
-
+ Copy linkLink kopieren
-
+ Open web UIWeboberfläche öffnen
-
+ Enable the serverServer aktivieren
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader ist für iOS und Android verfügbar. Entdecken Sie es für <a href='https://ios.yacreader.com'>iOS</a> oder <a href='https://android.yacreader.com'>Android</a>.
@@ -3325,7 +3520,7 @@ Use quotes to include spaces in a value.
Server aktivieren
-
+ Set portset portPort festlegen
diff --git a/YACReaderLibrary/yacreaderlibrary_en.ts b/YACReaderLibrary/yacreaderlibrary_en.ts
index fe6cac159..282133af4 100644
--- a/YACReaderLibrary/yacreaderlibrary_en.ts
+++ b/YACReaderLibrary/yacreaderlibrary_en.ts
@@ -425,6 +425,14 @@
Looking for comic...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Continue Reading...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
This folder doesn't contain comics yet
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Nothing selected
+
+
+
+ Select a comic or folder to see its information.
+ Select a comic or folder to see its information.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Continue Reading...
+ Continue Reading...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Unknown
+
+
+
+ Items
+ Items
+
+
+
+ Type
+ Type
+
+
+
+ Reading status
+ Reading status
+
+
+
+ Read
+ Read
+
+
+
+ Unread
+ Unread
+
+
+
+ Collection status
+ Collection status
+
+
+
+ Completed
+ Completed
+
+
+
+ In progress
+ In progress
+
+
+
+ Added
+ Added
+
+
+
+ Updated
+ UpdatedGridComicsView
-
+ Show infoShow info
+
+ Library
+ Library
+
+
+ Folder
+ Folder
+
+
+ Favorites
+ Favorites
+
+
+ Recently added
+ Recently added
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Western manga
+
+
+
+ Web comic
+ Web comic
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Comic
+
+
+
+ Unknown
+ Unknown
+ HelpAboutDialog
@@ -805,35 +929,58 @@
<p>The current library is being checked for missing covers and incomplete comic information.</p><p>This can take several minutes. You can stop the process and run it again later.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Library info
+
+
+
+ Number of folders
+ Number of folders
+
+
+
+ Number of comics
+ Number of comics
+
+
+
+ Number of read comics
+ Number of read comics
+
+LibraryWindow
-
+ LibraryLibrary
-
+ Open folder...Open folder...
-
-
-
+
+
+ western manga (left to right)western manga (left to right)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (top to botom)
-
+ Do you want remove Do you want remove
@@ -843,306 +990,306 @@
YACReader Library
-
-
-
+
+
+ mangamanga
-
-
-
+
+
+ comiccomic
-
+ Are you sure?Are you sure?
-
+ Rescan library for XML infoRescan library for XML info
-
+ Set as readSet as read
-
-
+
+ Set as unreadSet as unread
-
-
-
+
+
+ web comicweb comic
-
+ Add new folderAdd new folder
-
+ Delete folderDelete folder
-
+ Set as uncompletedSet as uncompleted
-
+ Set as completedSet as completed
-
+ Update folderUpdate folder
-
+ FolderFolder
-
+ ComicComic
-
+ Upgrade failedUpgrade failed
-
+ There were errors during library upgrade in: There were errors during library upgrade in:
-
+ Restore recovery failedRestore recovery failed
-
+ Update neededUpdate needed
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?
-
+ Download new versionDownload new version
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?This library was created with a newer version of YACReaderLibrary. Download the new version now?
-
+ Library not availableLibrary not available
-
+ Library '%1' is no longer available. Do you want to remove it?Library '%1' is no longer available. Do you want to remove it?
-
+ Old libraryOld library
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?
-
-
+
+ Copying comics...Copying comics...
-
-
+
+ Moving comics...Moving comics...
-
+ Folder name:Folder name:
-
+ No folder selectedNo folder selected
-
+ Please, select a folder firstPlease, select a folder first
-
+ Error in pathError in path
-
+ There was an error accessing the folder's pathThere was an error accessing the folder's path
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?The selected folder and all its contents will be deleted from your disk. Are you sure?
-
-
+
+ Unable to deleteUnable to delete
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.
-
+ Add new reading listsAdd new reading lists
-
-
+
+ List name:List name:
-
+ Delete list/labelDelete list/label
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?
-
+ Rename list nameRename list name
-
-
-
-
+
+
+
+ Set typeSet type
-
+ Search filtersSearch filters
-
+ UnreadUnread
-
+ In progressIn progress
-
+ Highly ratedHighly rated
-
+ Recently addedRecently added
-
+ Search syntax…Search syntax…
-
+ A repair of this library is already running (%1). Wait for it to finish.A repair of this library is already running (%1). Wait for it to finish.
-
+ The library is locked by a repair that did not finish.The library is locked by a repair that did not finish.
-
+ The library is locked by a repair started by %1.The library is locked by a repair started by %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Set custom coverSet custom cover
-
+ Delete custom coverDelete custom cover
-
+ Save coversSave covers
-
+ You are adding too many libraries.You are adding too many libraries.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1155,84 +1302,84 @@ You probably only need one library in your top level comics folder, you can brow
YACReaderLibrary will not stop you from creating more libraries but you should keep the number of libraries low.
-
-
+
+ YACReader not foundYACReader not found
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader not found. There might be a problem with your YACReader installation.
-
+ ErrorError
-
+ Error opening comic with third party reader.Error opening comic with third party reader.
-
+ Library not foundLibrary not found
-
+ The selected folder doesn't contain any library.The selected folder doesn't contain any library.
-
-
+
+ YACReader library database (*.ydb)YACReader library database (*.ydb)
-
+ The library database backup was created at:
%1The library database backup was created at:
%1
-
+ Unable to create the library database backup:
%1Unable to create the library database backup:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?
-
+ Restoring library database...Restoring library database...
-
+ The current library database is invalid. Restore the selected backup anyway?The current library database is invalid. Restore the selected backup anyway?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?The library maintenance lock may be stale. Remove it and retry?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1241,71 +1388,71 @@ Restart YACReaderLibrary before attempting recovery again.
Restart YACReaderLibrary before attempting recovery again.
-
+ The library database was restored successfully. Update the library now?The library database was restored successfully. Update the library now?
-
+ Library database damagedLibrary database damaged
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.
-
+ Attempt repairAttempt repair
-
+ Restore a backup...Restore a backup...
-
+ Repairing library database...Repairing library database...
-
-
-
+
+
+ Library database repairLibrary database repair
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Another maintenance operation is currently using this library. Try again after it finishes.
-
+ The library database is already valid.The library database is already valid.
-
+ Library database repairedLibrary database repaired
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1
-
+ Library database rebuiltLibrary database rebuilt
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1316,7 +1463,7 @@ Update the library now?
Update the library now?
-
+
The damaged original was preserved at:
@@ -1327,12 +1474,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failedLibrary database repair failed
-
+ The library database could not be repaired:
%1%2
@@ -1343,102 +1490,102 @@ You can restore a backup from the Library menu or recreate the library.
You can restore a backup from the Library menu or recreate the library.
-
+ library? library?
-
+ Remove and delete metadata and backupsRemove and delete metadata and backups
-
+ Library infoLibrary info
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.
-
+ Assign comics numbersAssign comics numbers
-
+ Assign numbers starting in:Assign numbers starting in:
-
+ Invalid imageInvalid image
-
+ The selected file is not a valid image.The selected file is not a valid image.
-
+ Error saving coverError saving cover
-
+ There was an error saving the cover image.There was an error saving the cover image.
-
+ Error creating the libraryError creating the library
-
+ Error updating the libraryError updating the library
-
+ Error opening the libraryError opening the library
-
+ Delete comicsDelete comics
-
+ All the selected comics will be deleted from your disk. Are you sure?All the selected comics will be deleted from your disk. Are you sure?
-
+ Remove comicsRemove comics
-
+ Comics will only be deleted from the current label/list. Are you sure?Comics will only be deleted from the current label/list. Are you sure?
-
+ Library name already existsLibrary name already exists
-
+ There is another library with the name '%1'.There is another library with the name '%1'.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1926,6 +2073,39 @@ Missing files: %3
Add selected comics to favorites list
+
+ ListInfoView
+
+
+ 1 comic
+ 1 comic
+
+
+
+ %1 comics
+ %1 comics
+
+
+
+ Last day
+ Last day
+
+
+
+ Last %1 days
+ Last %1 days
+
+
+
+ 1 sublist
+ 1 sublist
+
+
+
+ %1 sublists
+ %1 sublists
+
+LocalComicListModel
@@ -1968,143 +2148,143 @@ Missing files: %3
OptionsDialog
-
+ LanguageLanguage
-
+ Application languageApplication language
-
+ System defaultSystem default
-
+ Tray icon settings (experimental)Tray icon settings (experimental)
-
+ Close to trayClose to tray
-
+ Start into the system trayStart into the system tray
-
+ Edit Comic Vine API keyEdit Comic Vine API key
-
+ Comic Vine API keyComic Vine API key
-
+ ComicInfo.xml legacy supportComicInfo.xml legacy support
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImport metadata from ComicInfo.xml when adding new comics
-
+ Consider 'recent' items added or updated since X days agoConsider 'recent' items added or updated since X days ago
-
+ Third party readerThird party reader
-
+ Write {comic_file_path} where the path should go in the commandWrite {comic_file_path} where the path should go in the command
-
+ ClearClear
-
+ Update libraries at startupUpdate libraries at startup
-
+ Try to detect changes automaticallyTry to detect changes automatically
-
+ Update libraries periodicallyUpdate libraries periodically
-
+ Interval:Interval:
-
+ 30 minutes30 minutes
-
+ 1 hour1 hour
-
+ 2 hours2 hours
-
+ 4 hours4 hours
-
+ 8 hours8 hours
-
+ 12 hours12 hours
-
+ dailydaily
-
+ Update libraries at certain timeUpdate libraries at certain time
-
+ Time:Time:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2118,60 +2298,75 @@ During automatic updates the app will block some of the actions until the update
To stop an automatic update tap on the loading indicator next to the Libraries title.
-
+ Modifications detectionModifications detection
-
+ Compare the modified date of files when updating a library (not recommended)Compare the modified date of files when updating a library (not recommended)
-
+ Enable background imageEnable background image
-
+ Opacity levelOpacity level
-
+ Blur levelBlur level
-
+ Use selected comic cover as backgroundUse selected comic cover as background
-
+ Restore defautlsRestore defautls
-
+ BackgroundBackground
-
+ Display continue reading bannerDisplay continue reading banner
-
+ Display current comic bannerDisplay current comic banner
-
+ Continue readingContinue reading
+
+
+ Mix folders and comics
+ Mix folders and comics
+
+
+
+ Start comics on a new row
+ Start comics on a new row
+
+
+
+ Content
+ Content
+ Comic Flow
@@ -2179,7 +2374,7 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ LibrariesLibraries
@@ -3266,7 +3461,7 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
+ Set portset portSet port
@@ -3288,53 +3483,53 @@ Use quotes to include spaces in a value.
Choose an IP address
-
-
+
+ Server connectivityServer connectivity
-
+ Scan to connectScan to connect
-
+ Devices on this network can reach your library at the address below.Devices on this network can reach your library at the address below.
-
+ IP addressIP address
-
+ PortPort
-
+ Web interfaceWeb interface
-
+ Copy linkCopy link
-
+ Open web UIOpen web UI
-
+ Enable the serverEnable the server
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.
diff --git a/YACReaderLibrary/yacreaderlibrary_es.ts b/YACReaderLibrary/yacreaderlibrary_es.ts
index a0741405e..f5c61eda5 100644
--- a/YACReaderLibrary/yacreaderlibrary_es.ts
+++ b/YACReaderLibrary/yacreaderlibrary_es.ts
@@ -425,6 +425,14 @@
Recuperando información del volumen...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Continúa leyendo...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Esta carpeta aún no contiene cómics
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Nada seleccionado
+
+
+
+ Select a comic or folder to see its information.
+ Selecciona un cómic o una carpeta para ver su información.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Continúa leyendo...
+ Continúa leyendo...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Desconocido
+
+
+
+ Items
+ Elementos
+
+
+
+ Type
+ Tipo
+
+
+
+ Reading status
+ Estado de lectura
+
+
+
+ Read
+ Leído
+
+
+
+ Unread
+ No leído
+
+
+
+ Collection status
+ Estado de la colección
+
+
+
+ Completed
+ Completado
+
+
+
+ In progress
+ En curso
+
+
+
+ Added
+ Añadido
+
+
+
+ Updated
+ ActualizadoGridComicsView
-
+ Show infoMostrar información
+
+ Library
+ Librería
+
+
+ Folder
+ Carpeta
+
+
+ Favorites
+ Favoritos
+
+
+ Recently added
+ Añadido recientemente
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Manga occidental
+
+
+
+ Web comic
+ Cómic web
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Cómic
+
+
+
+ Unknown
+ Desconocido
+ HelpAboutDialog
@@ -805,31 +929,54 @@
<p>Se está comprobando si faltan portadas o información de cómics incompleta en la biblioteca actual.</p><p>Esto puede tardar varios minutos. Puedes detener el proceso y volver a ejecutarlo más tarde.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Información de la biblioteca
+
+
+
+ Number of folders
+ Número de carpetas
+
+
+
+ Number of comics
+ Número de cómics
+
+
+
+ Number of read comics
+ Número de cómics leídos
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.La carpeta seleccionada no contiene ninguna biblioteca.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Esta biblioteca fue creada con una versión anterior de YACReaderLibrary. Es necesario que se actualice. ¿Deseas hacerlo ahora?
-
+ ComicCómic
-
+ Error opening the libraryError abriendo la biblioteca
-
-
+
+ YACReader not foundYACReader no encontrado
@@ -838,72 +985,72 @@
Eliminar y borrar metadatos
-
+ Old libraryBiblioteca antigua
-
+ Set as completedMarcar como completo
-
+ LibraryLibrería
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Esta biblioteca fue creada con una versión más nueva de YACReaderLibrary. ¿Deseas descargar la nueva versión ahora?
-
+ Library '%1' is no longer available. Do you want to remove it?La biblioteca '%1' no está disponible. ¿Deseas eliminarla?
-
+ Open folder...Abrir carpeta...
-
+ Do you want remove ¿Deseas eliminar la biblioteca
-
+ Set as uncompletedMarcar como incompleto
-
+ Error updating the libraryError actualizando la biblioteca
-
+ FolderCarpeta
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?La biblioteca '%1' ha sido creada con una versión más antigua de YACReaderLibrary y debe ser creada de nuevo. ¿Deseas crear la biblioteca ahora?
-
+ Set as readMarcar como leído
-
+ Library not availableBiblioteca no disponible
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Ha habido algún problema intentando borrar los cómics selecionados. Por favor, verifica los permisos de escritura en los arhicovs seleccionados o los directorios que los conienen.
@@ -913,301 +1060,301 @@
Biblioteca YACReader
-
+ Error creating the libraryErrar creando la biblioteca
-
+ Update neededSe necesita actualizar
-
+ Library name already existsYa existe el nombre de la biblioteca
-
+ There is another library with the name '%1'.Hay otra biblioteca con el nombre '%1'.
-
+ Download new versionDescargar la nueva versión
-
+ Delete comicsBorrar cómics
-
+ All the selected comics will be deleted from your disk. Are you sure?Todos los cómics seleccionados serán borrados de tu disco. ¿Estás seguro?
-
-
+
+ Set as unreadMarcar como no leído
-
+ Library not foundBiblioteca no encontrada
-
-
-
+
+
+ mangahistorieta manga
-
-
-
+
+
+ comiccómic
-
-
-
+
+
+ web comiccómic web
-
-
-
+
+
+ western manga (left to right)manga occidental (izquierda a derecha)
-
-
+
+ Unable to deleteNo se ha podido borrar
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (de arriba a abajo)
-
+ library??
-
+ Are you sure?¿Estás seguro?
-
+ Rescan library for XML infoVolver a escanear la biblioteca en busca de información XML
-
+ Add new folderAñadir carpeta
-
+ Delete folderBorrar carpeta
-
+ Update folderActualizar carpeta
-
+ Upgrade failedLa actualización falló
-
+ There were errors during library upgrade in: Hubo errores durante la actualización de la biblioteca en:
-
-
+
+ Copying comics...Copiando cómics...
-
-
+
+ Moving comics...Moviendo cómics...
-
+ Folder name:Nombre de la carpeta:
-
+ No folder selectedNo has selecionado ninguna carpeta
-
+ Please, select a folder firstPor favor, selecciona una carpeta primero
-
+ Error in pathError en la ruta
-
+ There was an error accessing the folder's pathHubo un error al acceder a la ruta de la carpeta
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?¿Estás seguro de que deseas eliminar la carpeta seleccionada y todo su contenido de tu disco?
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Se produjo un problema al intentar eliminar las carpetas seleccionadas. Por favor, verifica los permisos de escritura y asegúrate de que no haya aplicaciones usando estas carpetas o alguno de los archivos contenidos en ellas.
-
+ Add new reading listsAñadir nuevas listas de lectura
-
-
+
+ List name:Nombre de la lista:
-
+ Delete list/labelEliminar lista/etiqueta
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?El elemento seleccionado se eliminará, tus cómics o carpetas NO se eliminarán de tu disco. ¿Estás seguro?
-
+ Rename list nameRenombrar lista
-
-
-
-
+
+
+
+ Set typeEstablecer tipo
-
+ Search filtersFiltros de búsqueda
-
+ UnreadNo leído
-
+ In progressEn curso
-
+ Highly ratedCon valoración alta
-
+ Recently addedAñadido recientemente
-
+ Search syntax…Sintaxis de búsqueda…
-
+ A repair of this library is already running (%1). Wait for it to finish.Ya se está ejecutando una reparación de esta biblioteca (%1). Espere a que finalice.
-
+ The library is locked by a repair that did not finish.La biblioteca está bloqueada por una reparación que no finalizó.
-
+ The library is locked by a repair started by %1.La biblioteca está bloqueada por una reparación iniciada por %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Si está seguro de que no se está ejecutando ninguna otra reparación, se puede eliminar el bloqueo. ¿Eliminar el bloqueo y continuar?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedError al recuperar la restauración
-
+ Set custom coverEstablecer portada personalizada
-
+ Delete custom coverEliminar portada personalizada
-
+ Save coversGuardar portadas
-
+ You are adding too many libraries.Estás añadiendo demasiadas bibliotecas.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1220,68 +1367,68 @@ Probablemente solo necesites una biblioteca en la carpeta principal de tus cómi
YACReaderLibrary no te detendrá de crear más bibliotecas, pero deberías mantener el número de bibliotecas bajo control.
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader no encontrado. YACReader debería estar instalado en la misma carpeta que YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader no encontrado. Podría haber un problema con tu instalación de YACReader.
-
+ ErrorFallo
-
+ Error opening comic with third party reader.Error al abrir el cómic con una aplicación de terceros.
-
-
+
+ YACReader library database (*.ydb)Base de datos de biblioteca de YACReader (*.ydb)
-
+ The library database backup was created at:
%1La copia de seguridad de la base de datos de la biblioteca se creó en:
%1
-
+ Unable to create the library database backup:
%1No se pudo crear la copia de seguridad de la base de datos de la biblioteca:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Cierra YACReaderLibraryServer y cualquier otra aplicación YACReader que esté usando esta biblioteca antes de restaurarla. ¿Quieres continuar?
-
+ Restoring library database...Restaurando la base de datos de la biblioteca...
-
+ The current library database is invalid. Restore the selected backup anyway?La base de datos actual de la biblioteca no es válida. ¿Quieres restaurar de todos modos la copia seleccionada?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?El bloqueo de mantenimiento de la biblioteca puede estar obsoleto. ¿Quieres eliminarlo y volver a intentarlo?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1290,71 +1437,71 @@ Restart YACReaderLibrary before attempting recovery again.
Reinicia YACReaderLibrary antes de volver a intentar la recuperación.
-
+ The library database was restored successfully. Update the library now?La base de datos de la biblioteca se restauró correctamente. ¿Quieres actualizar la biblioteca ahora?
-
+ Library database damagedBase de datos de la biblioteca dañada
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.La base de datos de la biblioteca '%1' está dañada, por lo que las actualizaciones, el mantenimiento y las copias de seguridad habituales no están disponibles. YACReader puede intentar reparar la base de datos. Es posible que algunos datos dañados no se puedan recuperar. Las copias de seguridad existentes no se modificarán.
-
+ Attempt repairIntentar reparar
-
+ Restore a backup...Restaurar una copia de seguridad...
-
+ Repairing library database...Reparando la base de datos de la biblioteca...
-
-
-
+
+
+ Library database repairReparación de la base de datos de la biblioteca
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Otra operación de mantenimiento está usando esta biblioteca. Vuelve a intentarlo cuando termine.
-
+ The library database is already valid.La base de datos de la biblioteca ya es válida.
-
+ Library database repairedBase de datos de la biblioteca reparada
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1La base de datos de la biblioteca se reparó reconstruyendo sus índices. El original dañado se conservó en:
%1
-
+ Library database rebuiltBase de datos de la biblioteca reconstruida
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1365,7 +1512,7 @@ Update the library now?
¿Quieres actualizar la biblioteca ahora?
-
+
The damaged original was preserved at:
@@ -1376,12 +1523,12 @@ El original dañado se conservó en:
%1
-
+ Library database repair failedError al reparar la base de datos de la biblioteca
-
+ The library database could not be repaired:
%1%2
@@ -1392,57 +1539,57 @@ You can restore a backup from the Library menu or recreate the library.
Puedes restaurar una copia de seguridad desde el menú Biblioteca o volver a crear la biblioteca.
-
+ Remove and delete metadata and backupsEliminar y borrar metadatos y copias de seguridad
-
+ Library infoInformación de la biblioteca
-
+ Assign comics numbersAsignar números a los cómics
-
+ Assign numbers starting in:Asignar números comenzando en:
-
+ Invalid imageImagen inválida
-
+ The selected file is not a valid image.El archivo seleccionado no es una imagen válida.
-
+ Error saving coverError guardando portada
-
+ There was an error saving the cover image.Hubo un error guardando la image de portada.
-
+ Remove comicsEliminar cómics
-
+ Comics will only be deleted from the current label/list. Are you sure?Los cómics sólo se eliminarán de la etiqueta/lista actual. ¿Estás seguro?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Archivos ausentes: %3
Añadir cómics seleccionados a la lista de favoritos
+
+ ListInfoView
+
+
+ 1 comic
+ 1 cómic
+
+
+
+ %1 comics
+ %1 cómics
+
+
+
+ Last day
+ Último día
+
+
+
+ Last %1 days
+ Últimos %1 días
+
+
+
+ 1 sublist
+ 1 sublista
+
+
+
+ %1 sublists
+ %1 sublistas
+
+LocalComicListModel
@@ -1982,143 +2162,143 @@ Archivos ausentes: %3
Opciones
-
+ LanguageIdioma
-
+ Application languageIdioma de la aplicación
-
+ System defaultPredeterminado del sistema
-
+ Tray icon settings (experimental)Opciones de bandeja de sistema (experimental)
-
+ Close to trayCerrar a la bandeja
-
+ Start into the system trayComenzar en la bandeja de sistema
-
+ Edit Comic Vine API keyEditar la clave API de Comic Vine
-
+ Comic Vine API keyClave API de Comic Vine
-
+ ComicInfo.xml legacy supportSoporte para ComicInfo.xml
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImportar metadatos desde ComicInfo.xml al añadir nuevos cómics
-
+ Consider 'recent' items added or updated since X days agoConsiderar elementos 'recientes' añadidos o actualizados desde hace X días
-
+ Third party readerLector externo
-
+ Write {comic_file_path} where the path should go in the commandEscribe {comic_file_path} donde la ruta al cómic debería ir en el comando
-
+ ClearBorrar
-
+ Update libraries at startupActualizar bibliotecas al inicio
-
+ Try to detect changes automaticallyIntentar detectar cambios automáticamente
-
+ Update libraries periodicallyActualizar bibliotecas periódicamente
-
+ Interval:Intervalo:
-
+ 30 minutes30 minutos
-
+ 1 hour1 hora
-
+ 2 hours2 horas
-
+ 4 hours4 horas
-
+ 8 hours8 horas
-
+ 12 hours12 horas
-
+ dailydirariamente
-
+ Update libraries at certain timeActualizar bibliotecas en un momento determinado
-
+ Time:Hora:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2132,60 +2312,75 @@ Durante las actualizaciones automáticas, la aplicación bloqueará algunas de l
Para detener una actualización automática, toca en el indicador de carga junto al título de Bibliotecas.
-
+ Modifications detectionDetección de modificaciones
-
+ Compare the modified date of files when updating a library (not recommended)Comparar la fecha de modificación de los archivos al actualizar una biblioteca (no recomendado)
-
+ Enable background imageActivar imagen de fondo
-
+ Opacity levelNivel de opacidad
-
+ Blur levelNivel de desenfoque
-
+ Use selected comic cover as backgroundUsar la portada del cómic seleccionado como fondo
-
+ Restore defautlsRestaurar valores predeterminados
-
+ BackgroundFondo
-
+ Display continue reading bannerMostrar banner de "Continuar leyendo"
-
+ Display current comic bannerMostar el báner del cómic actual
-
+ Continue readingContinuar leyendo
+
+
+ Mix folders and comics
+ Mezclar carpetas y cómics
+
+
+
+ Start comics on a new row
+ Empezar los cómics en una fila nueva
+
+
+
+ Content
+ Contenido
+ Comic Flow
@@ -2193,7 +2388,7 @@ Para detener una actualización automática, toca en el indicador de carga junto
-
+ LibrariesBibliotecas
@@ -3270,53 +3465,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivityConectividad del servidor
-
+ Scan to connectEscanea para conectar
-
+ Devices on this network can reach your library at the address below.Los dispositivos de esta red pueden acceder a tu biblioteca en la dirección que aparece a continuación.
-
+ IP addressDirección IP
-
+ PortPuerto
-
+ Web interfaceInterfaz web
-
+ Copy linkCopiar enlace
-
+ Open web UIAbrir interfaz web
-
+ Enable the serverActivar el servidor
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader está disponible para iOS y Android. Descúbrelo para <a href='https://ios.yacreader.com'>iOS</a> o <a href='https://android.yacreader.com'>Android</a>.
@@ -3325,7 +3520,7 @@ Use quotes to include spaces in a value.
activar el servidor
-
+ Set portset portEstablecer puerto
diff --git a/YACReaderLibrary/yacreaderlibrary_fr.ts b/YACReaderLibrary/yacreaderlibrary_fr.ts
index 52135d086..885f659dc 100644
--- a/YACReaderLibrary/yacreaderlibrary_fr.ts
+++ b/YACReaderLibrary/yacreaderlibrary_fr.ts
@@ -425,6 +425,14 @@
Récupération des informations sur le volume...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Continuer la lecture...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Ce dossier ne contient pas encore de bandes dessinées
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Aucune sélection
+
+
+
+ Select a comic or folder to see its information.
+ Sélectionnez une BD ou un dossier pour afficher ses informations.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Continuer la lecture...
+ Continuer la lecture...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Inconnu
+
+
+
+ Items
+ Éléments
+
+
+
+ Type
+ Type
+
+
+
+ Reading status
+ État de lecture
+
+
+
+ Read
+ Lu
+
+
+
+ Unread
+ Non lus
+
+
+
+ Collection status
+ État de la collection
+
+
+
+ Completed
+ Terminé
+
+
+
+ In progress
+ En cours
+
+
+
+ Added
+ Ajouté
+
+
+
+ Updated
+ Mis à jourGridComicsView
-
+ Show infoAfficher les informations
+
+ Library
+ Librairie
+
+
+ Folder
+ Dossier
+
+
+ Favorites
+ Favoris
+
+
+ Recently added
+ Ajoutés récemment
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Manga occidental
+
+
+
+ Web comic
+ Webcomic
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Bande dessinée
+
+
+
+ Unknown
+ Inconnu
+ HelpAboutDialog
@@ -805,53 +929,76 @@
<p>La bibliothèque actuelle est analysée pour rechercher les couvertures manquantes et les informations de BD incomplètes.</p><p>Cette opération peut prendre plusieurs minutes. Vous pouvez l'arrêter et la relancer plus tard.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Informations sur la bibliothèque
+
+
+
+ Number of folders
+ Nombre de dossiers
+
+
+
+ Number of comics
+ Nombre de BD
+
+
+
+ Number of read comics
+ Nombre de BD lues
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.Le dossier sélectionné ne contient aucune librairie.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Cette librairie a été créée avec une ancienne version de YACReaderLibrary. Mise à jour necessaire. Mettre à jour?
-
+ ComicBande dessinée
-
+ Error opening the libraryErreur lors de l'ouverture de la librairie
-
-
-
+
+
+ mangamangas
-
-
-
+
+
+ comiccomique
-
-
-
+
+
+ western manga (left to right)manga occidental (de gauche à droite)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (de haut en bas)
@@ -861,84 +1008,84 @@
Supprimer les métadata
-
+ Old libraryAncienne librairie
-
+ Set as completedMarquer comme complet
-
+ LibraryLibrairie
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Cette librairie a été créée avec une version plus récente de YACReaderLibrary. Télécharger la nouvelle version?
-
-
+
+ Moving comics...Déplacer la bande dessinée...
-
-
+
+ Copying comics...Copier la bande dessinée...
-
+ Library '%1' is no longer available. Do you want to remove it?La librarie '%1' n'est plus disponible. Voulez-vous la supprimer?
-
+ Open folder...Ouvrir le dossier...
-
+ Do you want remove Voulez-vous supprimer
-
+ Set as uncompletedMarquer comme incomplet
-
+ Error updating the libraryErreur lors de la mise à jour de la librairie
-
+ FolderDossier
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?L'élément sélectionné sera supprimé, vos bandes dessinées ou dossiers ne seront pas supprimés de votre disque. Êtes-vous sûr?
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?La librarie '%1' a été créée avec une ancienne version de YACReaderLibrary. Elle doit être re-créée. Voulez-vous créer la librairie?
-
+ Add new reading listsAjouter de nouvelles listes de lecture
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -951,12 +1098,12 @@ Vous n'avez probablement besoin que d'une bibliothèque dans votre dos
YACReaderLibrary ne vous empêchera pas de créer plus de bibliothèques, mais vous devriez garder le nombre de bibliothèques bas.
-
+ Set as readMarquer comme lu
-
+ Library not availableLibrairie non disponible
@@ -966,317 +1113,317 @@ YACReaderLibrary ne vous empêchera pas de créer plus de bibliothèques, mais v
Librairie de YACReader
-
+ Error creating the libraryErreur lors de la création de la librairie
-
+ Update folderMettre à jour le dossier
-
+ Update neededMise à jour requise
-
+ Library name already existsLe nom de la librairie existe déjà
-
+ There is another library with the name '%1'.Une autre librairie a le nom '%1'.
-
+ Download new versionTéléchrger la nouvelle version
-
+ Delete comicsSupprimer les comics
-
+ All the selected comics will be deleted from your disk. Are you sure?Tous les comics sélectionnés vont être supprimés de votre disque. Êtes-vous sûr?
-
-
+
+ Set as unreadMarquer comme non-lu
-
+ Library not foundLibrairie introuvable
-
+ library? la librairie?
-
+ Are you sure?Êtes-vous sûr?
-
+ Rescan library for XML infoRéanalyser la bibliothèque pour les informations XML
-
-
-
+
+
+ web comicbande dessinée Web
-
+ Add new folderAjouter un nouveau dossier
-
+ Delete folderSupprimer le dossier
-
+ Upgrade failedLa mise à niveau a échoué
-
+ There were errors during library upgrade in: Des erreurs se sont produites lors de la mise à niveau de la bibliothèque dans :
-
+ Folder name:Nom du dossier :
-
+ No folder selectedAucun dossier sélectionné
-
+ Please, select a folder firstVeuillez d'abord sélectionner un dossier
-
+ Error in pathErreur dans le chemin
-
+ There was an error accessing the folder's pathUne erreur s'est produite lors de l'accès au chemin du dossier
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?Le dossier sélectionné et tout son contenu seront supprimés de votre disque. Es-tu sûr?
-
-
+
+ Unable to deleteImpossible de supprimer
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Un problème est survenu lors de la tentative de suppression des dossiers sélectionnés. Veuillez vérifier les autorisations d'écriture et assurez-vous que toutes les applications utilisent ces dossiers ou l'un des fichiers contenus.
-
-
+
+ List name:Nom de la liste :
-
+ Delete list/labelSupprimer la liste/l'étiquette
-
+ Rename list nameRenommer le nom de la liste
-
-
-
-
+
+
+
+ Set typeDéfinir le type
-
+ Search filtersFiltres de recherche
-
+ UnreadNon lus
-
+ In progressEn cours
-
+ Highly ratedTrès bien notés
-
+ Recently addedAjoutés récemment
-
+ Search syntax…Syntaxe de recherche…
-
+ A repair of this library is already running (%1). Wait for it to finish.Une réparation de cette librairie est déjà en cours (%1). Attendez qu'elle se termine.
-
+ The library is locked by a repair that did not finish.La librairie est verrouillée par une réparation qui ne s'est pas terminée.
-
+ The library is locked by a repair started by %1.La librairie est verrouillée par une réparation démarrée par %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Si vous êtes sûr qu'aucune autre réparation n'est en cours, le verrou peut être supprimé. Supprimer le verrou et continuer ?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedÉchec de la récupération de la restauration
-
+ Set custom coverDéfinir une couverture personnalisée
-
+ Delete custom coverSupprimer la couverture personnalisée
-
+ Save coversEnregistrer les couvertures
-
+ You are adding too many libraries.Vous ajoutez trop de bibliothèques.
-
-
+
+ YACReader not foundYACReader introuvable
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader introuvable. YACReader doit être installé dans le même dossier que YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader introuvable. Il se peut qu'il y ait un problème avec votre installation de YACReader.
-
+ ErrorErreur
-
+ Error opening comic with third party reader.Erreur lors de l'ouverture de la bande dessinée avec un lecteur tiers.
-
-
+
+ YACReader library database (*.ydb)Base de données de bibliothèque YACReader (*.ydb)
-
+ The library database backup was created at:
%1La sauvegarde de la base de données de la bibliothèque a été créée ici :
%1
-
+ Unable to create the library database backup:
%1Impossible de créer la sauvegarde de la base de données de la bibliothèque :
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Fermez YACReaderLibraryServer et toute autre application YACReader utilisant cette bibliothèque avant la restauration. Continuer ?
-
+ Restoring library database...Restauration de la base de données de la bibliothèque...
-
+ The current library database is invalid. Restore the selected backup anyway?La base de données actuelle de la bibliothèque n'est pas valide. Restaurer quand même la sauvegarde sélectionnée ?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Le verrou de maintenance de la bibliothèque est peut-être obsolète. Le supprimer et réessayer ?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1285,71 +1432,71 @@ Restart YACReaderLibrary before attempting recovery again.
Redémarrez YACReaderLibrary avant de tenter à nouveau la récupération.
-
+ The library database was restored successfully. Update the library now?La base de données de la bibliothèque a été restaurée. Mettre à jour la bibliothèque maintenant ?
-
+ Library database damagedBase de données de la bibliothèque endommagée
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.La base de données de la bibliothèque « %1 » est endommagée. Les mises à jour, la maintenance et les sauvegardes habituelles sont donc indisponibles. YACReader peut tenter de réparer la base de données. Certaines données endommagées peuvent être irrécupérables. Les sauvegardes existantes ne seront pas modifiées.
-
+ Attempt repairTenter la réparation
-
+ Restore a backup...Restaurer une sauvegarde...
-
+ Repairing library database...Réparation de la base de données...
-
-
-
+
+
+ Library database repairRéparation de la base de données de la bibliothèque
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Une autre opération de maintenance utilise actuellement cette bibliothèque. Réessayez lorsqu'elle sera terminée.
-
+ The library database is already valid.La base de données de la bibliothèque est déjà valide.
-
+ Library database repairedBase de données de la bibliothèque réparée
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1La base de données de la bibliothèque a été réparée en reconstruisant ses index. L'original endommagé a été conservé ici :
%1
-
+ Library database rebuiltBase de données de la bibliothèque reconstruite
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1360,7 +1507,7 @@ Update the library now?
Mettre à jour la bibliothèque maintenant ?
-
+
The damaged original was preserved at:
@@ -1371,12 +1518,12 @@ L'original endommagé a été conservé ici :
%1
-
+ Library database repair failedÉchec de la réparation de la base de données
-
+ The library database could not be repaired:
%1%2
@@ -1387,62 +1534,62 @@ You can restore a backup from the Library menu or recreate the library.
Vous pouvez restaurer une sauvegarde depuis le menu Bibliothèque ou recréer la bibliothèque.
-
+ Remove and delete metadata and backupsRetirer et supprimer les métadonnées et les sauvegardes
-
+ Library infoInformations sur la bibliothèque
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Un problème est survenu lors de la tentative de suppression des bandes dessinées sélectionnées. Veuillez vérifier les autorisations d'écriture dans les fichiers sélectionnés ou le dossier contenant.
-
+ Assign comics numbersAttribuer des numéros de bandes dessinées
-
+ Assign numbers starting in:Attribuez des numéros commençant par :
-
+ Invalid imageImage invalide
-
+ The selected file is not a valid image.Le fichier sélectionné n'est pas une image valide.
-
+ Error saving coverErreur lors de l'enregistrement de la couverture
-
+ There was an error saving the cover image.Une erreur s'est produite lors de l'enregistrement de l'image de couverture.
-
+ Remove comicsSupprimer les bandes dessinées
-
+ Comics will only be deleted from the current label/list. Are you sure?Les bandes dessinées seront uniquement supprimées du label/liste actuelle. Es-tu sûr?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Fichiers manquants : %3
Ajouter la bande dessinée sélectionnée à la liste des favoris
+
+ ListInfoView
+
+
+ 1 comic
+ 1 BD
+
+
+
+ %1 comics
+ %1 BD
+
+
+
+ Last day
+ Dernier jour
+
+
+
+ Last %1 days
+ %1 derniers jours
+
+
+
+ 1 sublist
+ 1 sous-liste
+
+
+
+ %1 sublists
+ %1 sous-listes
+
+LocalComicListModel
@@ -1982,143 +2162,143 @@ Fichiers manquants : %3
Possibilités
-
+ LanguageLangue
-
+ Application languageLangue de l'application
-
+ System defaultPar défaut du système
-
+ Tray icon settings (experimental)Paramètres de l'icône de la barre d'état (expérimental)
-
+ Close to trayPrès du plateau
-
+ Start into the system trayCommencez dans la barre d'état système
-
+ Edit Comic Vine API keyModifier la clé API Comic Vine
-
+ Comic Vine API keyClé API Comic Vine
-
+ ComicInfo.xml legacy supportPrise en charge héritée de ComicInfo.xml
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImporter des métadonnées depuis ComicInfo.xml lors de l'ajout de nouvelles bandes dessinées
-
+ Consider 'recent' items added or updated since X days agoConsidérez les éléments « récents » ajoutés ou mis à jour depuis X jours
-
+ Third party readerLecteur tiers
-
+ Write {comic_file_path} where the path should go in the commandÉcrivez {comic_file_path} où le chemin doit aller dans la commande
-
+ ClearClair
-
+ Update libraries at startupMettre à jour les bibliothèques au démarrage
-
+ Try to detect changes automaticallyEssayez de détecter automatiquement les changements
-
+ Update libraries periodicallyMettre à jour les bibliothèques périodiquement
-
+ Interval:Intervalle:
-
+ 30 minutes30 min
-
+ 1 hour1 heure
-
+ 2 hours2 heures
-
+ 4 hours4 heures
-
+ 8 hours8 heures
-
+ 12 hours12 heures
-
+ dailytous les jours
-
+ Update libraries at certain timeMettre à jour les bibliothèques à un certain moment
-
+ Time:Temps:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2132,60 +2312,75 @@ Lors des mises à jour automatiques, l'application bloquera certaines actio
Pour arrêter une mise à jour automatique, appuyez sur l'indicateur de chargement à côté du titre Bibliothèques.
-
+ Modifications detectionDétection des modifications
-
+ Compare the modified date of files when updating a library (not recommended)Comparer la date de modification des fichiers lors de la mise à jour d'une bibliothèque (déconseillé)
-
+ Enable background imageActiver l'image d'arrière-plan
-
+ Opacity levelNiveau d'opacité
-
+ Blur levelNiveau de flou
-
+ Use selected comic cover as backgroundUtiliser la couverture de bande dessinée sélectionnée comme arrière-plan
-
+ Restore defautlsRestaurer les valeurs par défaut
-
+ BackgroundArrière-plan
-
+ Display continue reading bannerAfficher la bannière de lecture continue
-
+ Display current comic bannerAfficher la bannière de bande dessinée actuelle
-
+ Continue readingContinuer la lecture
+
+
+ Mix folders and comics
+ Mélanger les dossiers et les BD
+
+
+
+ Start comics on a new row
+ Commencer les BD sur une nouvelle ligne
+
+
+
+ Content
+ Contenu
+ Comic Flow
@@ -2193,7 +2388,7 @@ Pour arrêter une mise à jour automatique, appuyez sur l'indicateur de cha
-
+ LibrariesBibliothèques
@@ -3270,53 +3465,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivityConnectivité du serveur
-
+ Scan to connectScanner pour se connecter
-
+ Devices on this network can reach your library at the address below.Les appareils de ce réseau peuvent accéder à votre bibliothèque à l’adresse ci-dessous.
-
+ IP addressAdresse IP
-
+ PortPort r?seau
-
+ Web interfaceInterface web
-
+ Copy linkCopier le lien
-
+ Open web UIOuvrir l’interface web
-
+ Enable the serverActiver le serveur
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader est disponible pour iOS et Android. Découvrez-le pour <a href='https://ios.yacreader.com'>iOS</a> ou <a href='https://android.yacreader.com'>Android</a>.
@@ -3325,7 +3520,7 @@ Use quotes to include spaces in a value.
Autoriser le serveur
-
+ Set portset portDéfinir le port
diff --git a/YACReaderLibrary/yacreaderlibrary_it.ts b/YACReaderLibrary/yacreaderlibrary_it.ts
index 0f484bc54..84f644562 100644
--- a/YACReaderLibrary/yacreaderlibrary_it.ts
+++ b/YACReaderLibrary/yacreaderlibrary_it.ts
@@ -425,6 +425,14 @@
Sto ricevendo le informazioni per l'abum...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Continua a leggere...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Questa cartella non contiene ancora fumetti
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Nessuna selezione
+
+
+
+ Select a comic or folder to see its information.
+ Seleziona un fumetto o una cartella per visualizzarne le informazioni.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Continua a leggere...
+ Continua a leggere...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Sconosciuto
+
+
+
+ Items
+ Elementi
+
+
+
+ Type
+ Tipo
+
+
+
+ Reading status
+ Stato di lettura
+
+
+
+ Read
+ Leggi
+
+
+
+ Unread
+ Non letti
+
+
+
+ Collection status
+ Stato della raccolta
+
+
+
+ Completed
+ Completato
+
+
+
+ In progress
+ In corso
+
+
+
+ Added
+ Aggiunto
+
+
+
+ Updated
+ AggiornatoGridComicsView
-
+ Show infoMostra informazioni
+
+ Library
+ Libreria
+
+
+ Folder
+ Cartella
+
+
+ Favorites
+ Favoriti
+
+
+ Recently added
+ Aggiunti di recente
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Manga occidentale
+
+
+
+ Web comic
+ Fumetto web
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Fumetto
+
+
+
+ Unknown
+ Sconosciuto
+ HelpAboutDialog
@@ -805,51 +929,74 @@
<p>La libreria corrente viene controllata per individuare copertine mancanti e informazioni incomplete sui fumetti.</p><p>L'operazione può richiedere diversi minuti. Puoi interromperla ed eseguirla di nuovo in seguito.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Informazioni sulla biblioteca
+
+
+
+ Number of folders
+ Numero di cartelle
+
+
+
+ Number of comics
+ Numero di fumetti
+
+
+
+ Number of read comics
+ Numero di fumetti letti
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.La cartella selezionata non contiene nessuna Libreria.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Questa libreria è stata creata con una versione precedente di YACREaderLibrary. Deve essere aggiornata. Aggiorno ora?
-
+ ComicFumetto
-
+ Folder name:Nome della cartella:
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?La cartella seleziona e tutto il suo contenuto verranno cancellati dal tuo disco. Sei sicuro?
-
+ Error opening the libraryErrore nell'apertura della libreria
-
-
+
+ YACReader not foundYACReader non trovato
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.C'è stato un problema cancellando le cartelle selezionate. Per favore controlla i tuoi permessi di scrittura e sii sicuro che non ci siano altre applicazioni che usano le stesse cartelle.
-
+ Rename list nameRinomina la lista
@@ -858,110 +1005,110 @@
Rimuovi e cancella i Metadati
-
+ Old libraryVecchia libreria
-
+ Set as completedSegna come completo
-
+ There was an error accessing the folder's pathC'è stato un errore nell'accesso al percorso della cartella
-
+ LibraryLibreria
-
+ Comics will only be deleted from the current label/list. Are you sure?I fumetti verranno cancellati dall'etichetta/lista corrente. Sei sicuro?
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Questa libreria è stata creata con una verisone più recente di YACReaderLibrary. Scarico la versione aggiornata ora?
-
-
+
+ Moving comics...Sto muovendo i fumetti...
-
-
+
+ Copying comics...Sto copiando i fumetti...
-
+ Library '%1' is no longer available. Do you want to remove it?La libreria '%1' non è più disponibile, la vuoi cancellare?
-
+ Open folder...Apri Cartella...
-
+ Do you want remove Vuoi rimuovere
-
+ Set as uncompletedSegna come non completo
-
+ Error in pathErrore nel percorso
-
+ Error updating the libraryErrore aggiornando la libreria
-
+ FolderCartella
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?Gli elementi selezionati verranno cancellati, i tuoi fumetti o cartella NON verranno cancellati dal tuo disco. Sei sicuro?
-
-
+
+ List name:Nome lista:
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?La libreria '%1' è stata creata con una versione precedente di YACREaderLibrary. Deve essere ricreata. Lo vuoi fare ora?
-
+ Save coversSalva Copertine
-
+ Add new reading listsAggiungi una lista di lettura
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -974,32 +1121,32 @@ Hai probabilemnte bisogno di una sola Libreria al livello superiore, puoi poi na
YACReader non ti fermerà dal creare altre librerie ma è meglio se terrai il numero di librerie basso.
-
+ Set as readSetta come letto
-
+ Library infoInformazioni sulla biblioteca
-
+ Assign comics numbersAssegna un numero ai fumetti
-
+ Please, select a folder firstPer cortesia prima seleziona una cartella
-
+ Library not availableLibreria non disponibile
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.C'è un problema nel cancellare i fumetti selezionati. Per favore controlla i tuoi permessi di scrittura sui file o sulla cartella.
@@ -1009,293 +1156,293 @@ YACReader non ti fermerà dal creare altre librerie ma è meglio se terrai il nu
Libreria YACReader
-
+ Error creating the libraryErrore creando la libreria
-
+ You are adding too many libraries.Stai aggiungendto troppe librerie.
-
+ Update folderAggiorna Cartella
-
+ Update neededDevi aggiornarmi
-
+ Library name already existsEsiste già una libreria con lo stesso nome
-
+ There is another library with the name '%1'.Esiste già una libreria con il nome '%1'.
-
+ Delete folderCancella Cartella
-
+ Assign numbers starting in:Assegna numeri partendo da:
-
+ Download new versionScarica la nuova versione
-
+ Remove and delete metadata and backupsRimuovi ed elimina metadati e backup
-
+ Invalid imageImmagine non valida
-
+ The selected file is not a valid image.Il file selezionato non è un'immagine valida.
-
+ Error saving coverErrore durante il salvataggio della copertina
-
+ There was an error saving the cover image.Si è verificato un errore durante il salvataggio dell'immagine di copertina.
-
+ Delete comicsCancella i fumetti
-
+ Add new folderAggiungi una nuova cartella
-
+ Delete list/labelCancella Lista/Etichetta
-
+ No folder selectedNessuna cartella selezionata
-
+ All the selected comics will be deleted from your disk. Are you sure?Tutti i fumetti selezionati saranno cancellati dal tuo disco. Sei sicuro?
-
+ Remove comicsRimuovi i fumetti
-
-
+
+ Set as unreadSetta come non letto
-
+ Library not foundLibreria non trovata
-
-
-
+
+
+ mangaManga
-
-
-
+
+
+ comiccomico
-
-
-
+
+
+ web comicfumetto web
-
-
-
+
+
+ western manga (left to right)manga occidentale (da sinistra a destra)
-
-
+
+ Unable to deleteNon posso cancellare
-
-
-
+
+
+ 4koma (top to botom)4koma (dall'alto verso il basso)
-
+ Search filtersFiltri di ricerca
-
+ UnreadNon letti
-
+ In progressIn corso
-
+ Highly ratedCon valutazione alta
-
+ Recently addedAggiunti di recente
-
+ Search syntax…Sintassi di ricerca…
-
-
-
-
+
+
+
+ Set typeImposta il tipo
-
+ A repair of this library is already running (%1). Wait for it to finish.È già in corso una riparazione di questa libreria (%1). Attendere il completamento.
-
+ The library is locked by a repair that did not finish.La libreria è bloccata da una riparazione non completata.
-
+ The library is locked by a repair started by %1.La libreria è bloccata da una riparazione avviata da %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Se sei sicuro che non sia in corso nessun'altra riparazione, il blocco può essere rimosso. Rimuovere il blocco e continuare?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedRecupero del ripristino non riuscito
-
+ Set custom coverImposta la copertina personalizzata
-
+ Delete custom coverElimina la copertina personalizzata
-
+ ErrorErrore
-
+ Error opening comic with third party reader.Errore nell'apertura del fumetto con un lettore di terze parti.
-
-
+
+ YACReader library database (*.ydb)Database della libreria YACReader (*.ydb)
-
+ The library database backup was created at:
%1Il backup del database della libreria è stato creato in:
%1
-
+ Unable to create the library database backup:
%1Impossibile creare il backup del database della libreria:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Chiudi YACReaderLibraryServer e qualsiasi altra applicazione YACReader che usa questa libreria prima del ripristino. Continuare?
-
+ Restoring library database...Ripristino del database della libreria...
-
+ The current library database is invalid. Restore the selected backup anyway?Il database attuale della libreria non è valido. Ripristinare comunque il backup selezionato?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Il blocco di manutenzione della libreria potrebbe essere obsoleto. Rimuoverlo e riprovare?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1304,71 +1451,71 @@ Restart YACReaderLibrary before attempting recovery again.
Riavvia YACReaderLibrary prima di tentare nuovamente il recupero.
-
+ The library database was restored successfully. Update the library now?Il database della libreria è stato ripristinato correttamente. Aggiornare la libreria ora?
-
+ Library database damagedDatabase della libreria danneggiato
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.Il database della libreria '%1' è danneggiato, quindi gli aggiornamenti, la manutenzione e i backup normali non sono disponibili. YACReader può tentare di riparare il database. Alcuni dati danneggiati potrebbero non essere recuperabili. I backup esistenti non verranno modificati.
-
+ Attempt repairTenta la riparazione
-
+ Restore a backup...Ripristina un backup...
-
+ Repairing library database...Riparazione del database della libreria...
-
-
-
+
+
+ Library database repairRiparazione del database della libreria
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Un'altra operazione di manutenzione sta usando questa libreria. Riprova al termine.
-
+ The library database is already valid.Il database della libreria è già valido.
-
+ Library database repairedDatabase della libreria riparato
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1Il database della libreria è stato riparato ricostruendone gli indici. L'originale danneggiato è stato conservato in:
%1
-
+ Library database rebuiltDatabase della libreria ricostruito
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1379,7 +1526,7 @@ Update the library now?
Aggiornare la libreria ora?
-
+
The damaged original was preserved at:
@@ -1390,12 +1537,12 @@ L'originale danneggiato è stato conservato in:
%1
-
+ Library database repair failedRiparazione del database della libreria non riuscita
-
+ The library database could not be repaired:
%1%2
@@ -1406,42 +1553,42 @@ You can restore a backup from the Library menu or recreate the library.
Puoi ripristinare un backup dal menu Libreria o ricreare la libreria.
-
+ library? Libreria?
-
+ Are you sure?Sei sicuro?
-
+ Rescan library for XML infoEseguire nuovamente la scansione della libreria per informazioni XML
-
+ Upgrade failedAggiornamento non riuscito
-
+ There were errors during library upgrade in: Si sono verificati errori durante l'aggiornamento della libreria in:
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader non trovato. YACReader deve essere installato nella stessa cartella di YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader non trovato. Potrebbe esserci un problema con l'installazione di YACReader.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1929,6 +2076,39 @@ File mancanti: %3
Aggiungi i fumetti selezionati alla lista dei favoriti
+
+ ListInfoView
+
+
+ 1 comic
+ 1 fumetto
+
+
+
+ %1 comics
+ %1 fumetti
+
+
+
+ Last day
+ Ultimo giorno
+
+
+
+ Last %1 days
+ Ultimi %1 giorni
+
+
+
+ 1 sublist
+ 1 sottolista
+
+
+
+ %1 sublists
+ %1 sottoliste
+
+LocalComicListModel
@@ -1971,22 +2151,22 @@ File mancanti: %3
OptionsDialog
-
+ Restore defautlsResetta al Default
-
+ BackgroundSfondo
-
+ Blur levelLivello di sfumatura
-
+ Enable background imageAbilita l'immagine di sfondo
@@ -1996,17 +2176,17 @@ File mancanti: %3
Opzioni
-
+ Comic Vine API keyAPI di ComicVine
-
+ Edit Comic Vine API keyEdita l'API di ComicVine
-
+ Opacity levelLivello di opacità
@@ -2016,7 +2196,7 @@ File mancanti: %3
Generale
-
+ Use selected comic cover as backgroundUsa la cover del fumetto selezionato come sfondo
@@ -2027,7 +2207,7 @@ File mancanti: %3
-
+ LibrariesLibrerie
@@ -2042,133 +2222,133 @@ File mancanti: %3
Aspetto
-
+ LanguageLingua
-
+ Application languageLingua dell'applicazione
-
+ System defaultPredefinita del sistema
-
+ Tray icon settings (experimental)Impostazioni dell'icona nella barra delle applicazioni (sperimentale)
-
+ Close to trayVicino al vassoio
-
+ Start into the system trayInizia nella barra delle applicazioni
-
+ ComicInfo.xml legacy supportSupporto legacy ComicInfo.xml
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImporta metadati da ComicInfo.xml quando aggiungi nuovi fumetti
-
+ Consider 'recent' items added or updated since X days agoConsidera gli elementi "recenti" aggiunti o aggiornati da X giorni fa
-
+ Third party readerLettore di terze parti
-
+ Write {comic_file_path} where the path should go in the commandScrivi {comic_file_path} dove dovrebbe andare il percorso nel comando
-
+ ClearCancella
-
+ Update libraries at startupAggiorna le librerie all'avvio
-
+ Try to detect changes automaticallyProva a rilevare automaticamente le modifiche
-
+ Update libraries periodicallyAggiorna periodicamente le librerie
-
+ Interval:Intervallo:
-
+ 30 minutes30 minuti
-
+ 1 hour1 ora
-
+ 2 hours2 ore
-
+ 4 hours4 ore
-
+ 8 hours8 ore
-
+ 12 hours12 ore
-
+ dailyquotidiano
-
+ Update libraries at certain timeAggiorna le librerie in determinati orari
-
+ Time:Tempo:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2182,30 +2362,45 @@ Durante gli aggiornamenti automatici l'app bloccherà alcune azioni fino al
Per interrompere un aggiornamento automatico, tocca l'indicatore di caricamento accanto al titolo Librerie.
-
+ Modifications detectionRilevamento delle modifiche
-
+ Compare the modified date of files when updating a library (not recommended)Confronta la data di modifica dei file durante l'aggiornamento di una libreria (non consigliato)
-
+ Display continue reading bannerVisualizza il banner continua a leggere
-
+ Display current comic bannerVisualizza il banner del fumetto corrente
-
+ Continue readingContinua a leggere
+
+
+ Mix folders and comics
+ Mescola cartelle e fumetti
+
+
+
+ Start comics on a new row
+ Inizia i fumetti su una nuova riga
+
+
+
+ Content
+ Contenuto
+ Restart is needed
@@ -3269,53 +3464,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivityConnettività del server
-
+ Scan to connectScansiona per connetterti
-
+ Devices on this network can reach your library at the address below.I dispositivi su questa rete possono accedere alla tua libreria all’indirizzo riportato di seguito.
-
+ IP addressIndirizzo IP
-
+ PortPorta
-
+ Web interfaceInterfaccia web
-
+ Copy linkCopia link
-
+ Open web UIApri interfaccia web
-
+ Enable the serverAbilita il server
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader è disponibile per iOS e Android. Scoprilo per <a href='https://ios.yacreader.com'>iOS</a> o <a href='https://android.yacreader.com'>Android</a>.
@@ -3332,7 +3527,7 @@ Use quotes to include spaces in a value.
Scansiona!
-
+ Set portset portImposta porta
diff --git a/YACReaderLibrary/yacreaderlibrary_ko.ts b/YACReaderLibrary/yacreaderlibrary_ko.ts
index f0f8e8376..81b6fd2bb 100644
--- a/YACReaderLibrary/yacreaderlibrary_ko.ts
+++ b/YACReaderLibrary/yacreaderlibrary_ko.ts
@@ -425,6 +425,14 @@
만화 검색 중...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ 이어 읽기...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
이 폴더에는 아직 만화가 없습니다
+
+ EmptyInfoView
+
+
+ Nothing selected
+ 선택 항목 없음
+
+
+
+ Select a comic or folder to see its information.
+ 정보를 보려면 만화 또는 폴더를 선택하세요.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- 이어 읽기...
+ 이어 읽기...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ 알 수 없음
+
+
+
+ Items
+ 항목
+
+
+
+ Type
+ 유형
+
+
+
+ Reading status
+ 읽기 상태
+
+
+
+ Read
+ 읽음
+
+
+
+ Unread
+ 읽지 않음
+
+
+
+ Collection status
+ 컬렉션 상태
+
+
+
+ Completed
+ 완료
+
+
+
+ In progress
+ 읽는 중
+
+
+
+ Added
+ 추가됨
+
+
+
+ Updated
+ 업데이트됨GridComicsView
-
+ Show info정보 보기
+
+ Library
+ 라이브러리
+
+
+ Folder
+ 폴더
+
+
+ Favorites
+ 즐겨찾기
+
+
+ Recently added
+ 최근 추가
+
+
+
+ Manga
+ 망가
+
+
+
+ Western manga
+ 서양식 망가
+
+
+
+ Web comic
+ 웹툰
+
+
+
+ Yonkoma
+ 4컷 만화
+
+
+
+ Comic
+ 만화
+
+
+
+ Unknown
+ 알 수 없음
+ HelpAboutDialog
@@ -805,35 +929,58 @@
<p>현재 라이브러리에서 누락된 표지와 불완전한 만화 정보를 확인하고 있습니다.</p><p>몇 분 정도 걸릴 수 있습니다. 작업을 중지하고 나중에 다시 실행할 수 있습니다.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ 라이브러리 정보
+
+
+
+ Number of folders
+ 폴더 수
+
+
+
+ Number of comics
+ 만화 수
+
+
+
+ Number of read comics
+ 읽은 만화 수
+
+LibraryWindow
-
+ Library라이브러리
-
+ Open folder...폴더 열기...
-
-
-
+
+
+ western manga (left to right)서양 만화 (왼쪽 → 오른쪽)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4컷 (위 → 아래)
-
+ Do you want remove 다음을 제거하시겠습니까:
@@ -843,306 +990,306 @@
YACReader Library
-
-
-
+
+
+ manga망가
-
-
-
+
+
+ comic만화
-
+ Are you sure?확실합니까?
-
+ Rescan library for XML infoXML 정보로 라이브러리 재검색
-
+ Set as read읽음으로 표시
-
-
+
+ Set as unread읽지 않음으로 표시
-
-
-
+
+
+ web comic웹 만화
-
+ Add new folder새 폴더 추가
-
+ Delete folder폴더 삭제
-
+ Set as uncompleted미완료로 표시
-
+ Set as completed완료로 표시
-
+ Update folder폴더 업데이트
-
+ Folder폴더
-
+ Comic만화
-
+ Upgrade failed업그레이드 실패
-
+ There were errors during library upgrade in: 라이브러리 업그레이드 중 오류 발생:
-
+ Restore recovery failed복원 복구 실패
-
+ Update needed업데이트 필요
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?이 라이브러리는 YACReaderLibrary의 이전 버전으로 만들어졌습니다. 업데이트가 필요합니다. 지금 업데이트하시겠습니까?
-
+ Download new version새 버전 내려받기
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?이 라이브러리는 YACReaderLibrary의 최신 버전으로 만들어졌습니다. 지금 새 버전을 내려받으시겠습니까?
-
+ Library not available라이브러리를 사용할 수 없습니다
-
+ Library '%1' is no longer available. Do you want to remove it?'%1' 라이브러리를 더 이상 사용할 수 없습니다. 제거하시겠습니까?
-
+ Old library오래된 라이브러리
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?'%1' 라이브러리는 이전 버전의 YACReaderLibrary로 만들어졌습니다. 다시 만들어야 합니다. 지금 만드시겠습니까?
-
-
+
+ Copying comics...만화 복사 중...
-
-
+
+ Moving comics...만화 이동 중...
-
+ Folder name:폴더 이름:
-
+ No folder selected선택된 폴더 없음
-
+ Please, select a folder first먼저 폴더를 선택하세요
-
+ Error in path경로 오류
-
+ There was an error accessing the folder's path폴더 경로에 접근하는 중 오류가 발생했습니다
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?선택한 폴더와 그 안의 모든 내용이 디스크에서 삭제됩니다. 계속하시겠습니까?
-
-
+
+ Unable to delete삭제할 수 없음
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.선택한 폴더를 삭제하는 중 문제가 발생했습니다. 쓰기 권한을 확인하고, 다른 응용 프로그램이 이 폴더나 안의 파일을 사용 중인지 확인하세요.
-
+ Add new reading lists새 읽기 목록 추가
-
-
+
+ List name:목록 이름:
-
+ Delete list/label목록/라벨 삭제
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?선택한 항목이 삭제됩니다. 디스크에서 만화나 폴더는 삭제되지 않습니다. 계속하시겠습니까?
-
+ Rename list name목록 이름 변경
-
-
-
-
+
+
+
+ Set type유형 설정
-
+ Search filters검색 필터
-
+ Unread읽지 않음
-
+ In progress읽는 중
-
+ Highly rated높은 평점
-
+ Recently added최근 추가
-
+ Search syntax…검색 구문…
-
+ A repair of this library is already running (%1). Wait for it to finish.이 라이브러리에 대한 복구가 이미 진행 중입니다 (%1). 완료될 때까지 기다려 주세요.
-
+ The library is locked by a repair that did not finish.라이브러리가 완료되지 않은 복구에 의해 잠겨 있습니다.
-
+ The library is locked by a repair started by %1.라이브러리가 %1에서 시작한 복구에 의해 잠겨 있습니다.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?다른 복구가 실행 중이 아니라고 확신하면 잠금을 해제할 수 있습니다. 잠금을 해제하고 계속하시겠습니까?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Set custom cover사용자 지정 표지 설정
-
+ Delete custom cover사용자 지정 표지 삭제
-
+ Save covers표지 저장
-
+ You are adding too many libraries.라이브러리를 너무 많이 추가하고 있습니다.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1155,84 +1302,84 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
YACReaderLibrary는 라이브러리를 더 만드는 것을 막지 않지만, 라이브러리 수는 적게 유지하는 것이 좋습니다.
-
-
+
+ YACReader not foundYACReader를 찾을 수 없음
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader를 찾을 수 없습니다. YACReader는 YACReaderLibrary와 같은 폴더에 설치되어야 합니다.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader를 찾을 수 없습니다. YACReader 설치에 문제가 있을 수 있습니다.
-
+ Error오류
-
+ Error opening comic with third party reader.타사 뷰어로 만화를 여는 중 오류가 발생했습니다.
-
+ Library not found라이브러리를 찾을 수 없음
-
+ The selected folder doesn't contain any library.선택한 폴더에 라이브러리가 없습니다.
-
-
+
+ YACReader library database (*.ydb)YACReader 라이브러리 데이터베이스 (*.ydb)
-
+ The library database backup was created at:
%1라이브러리 데이터베이스 백업을 다음 위치에 만들었습니다:
%1
-
+ Unable to create the library database backup:
%1라이브러리 데이터베이스 백업을 만들 수 없습니다:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?복원하기 전에 YACReaderLibraryServer와 이 라이브러리를 사용하는 다른 모든 YACReader 애플리케이션을 종료하세요. 계속하시겠습니까?
-
+ Restoring library database...라이브러리 데이터베이스 복원 중...
-
+ The current library database is invalid. Restore the selected backup anyway?현재 라이브러리 데이터베이스가 유효하지 않습니다. 선택한 백업을 그래도 복원하시겠습니까?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?라이브러리 유지 관리 잠금이 오래된 것일 수 있습니다. 잠금을 제거하고 다시 시도하시겠습니까?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1241,71 +1388,71 @@ Restart YACReaderLibrary before attempting recovery again.
복구를 다시 시도하기 전에 YACReaderLibrary를 다시 시작하세요.
-
+ The library database was restored successfully. Update the library now?라이브러리 데이터베이스를 성공적으로 복원했습니다. 지금 라이브러리를 업데이트하시겠습니까?
-
+ Library database damaged라이브러리 데이터베이스 손상
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.'%1' 라이브러리의 데이터베이스가 손상되어 일반 업데이트, 유지 관리 및 백업을 사용할 수 없습니다. YACReader가 데이터베이스 복구를 시도할 수 있습니다. 손상된 일부 데이터는 복구하지 못할 수 있습니다. 기존 백업은 변경되지 않습니다.
-
+ Attempt repair복구 시도
-
+ Restore a backup...백업 복원...
-
+ Repairing library database...라이브러리 데이터베이스 복구 중...
-
-
-
+
+
+ Library database repair라이브러리 데이터베이스 복구
-
+ Another maintenance operation is currently using this library. Try again after it finishes.현재 다른 유지 관리 작업에서 이 라이브러리를 사용 중입니다. 작업이 끝난 후 다시 시도하세요.
-
+ The library database is already valid.라이브러리 데이터베이스가 이미 유효합니다.
-
+ Library database repaired라이브러리 데이터베이스 복구됨
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1인덱스를 다시 빌드하여 라이브러리 데이터베이스를 복구했습니다. 손상된 원본은 다음 위치에 보존되었습니다:
%1
-
+ Library database rebuilt라이브러리 데이터베이스 재구축됨
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1316,7 +1463,7 @@ Update the library now?
지금 라이브러리를 업데이트하시겠습니까?
-
+
The damaged original was preserved at:
@@ -1327,12 +1474,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failed라이브러리 데이터베이스 복구 실패
-
+ The library database could not be repaired:
%1%2
@@ -1343,12 +1490,12 @@ You can restore a backup from the Library menu or recreate the library.
라이브러리 메뉴에서 백업을 복원하거나 라이브러리를 다시 만들 수 있습니다.
-
+ library?라이브러리?
-
+ Remove and delete metadata and backups메타데이터 및 백업 제거 후 삭제
@@ -1357,92 +1504,92 @@ You can restore a backup from the Library menu or recreate the library.
제거 및 메타데이터 삭제
-
+ Library info라이브러리 정보
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.선택한 만화를 삭제하는 중 문제가 발생했습니다. 선택한 파일이나 포함된 폴더의 쓰기 권한을 확인하세요.
-
+ Assign comics numbers만화에 번호 부여
-
+ Assign numbers starting in:다음 번호부터 부여:
-
+ Invalid image잘못된 이미지
-
+ The selected file is not a valid image.선택한 파일이 유효한 이미지가 아닙니다.
-
+ Error saving cover표지 저장 오류
-
+ There was an error saving the cover image.표지 이미지를 저장하는 중 오류가 발생했습니다.
-
+ Error creating the library라이브러리 생성 오류
-
+ Error updating the library라이브러리 업데이트 오류
-
+ Error opening the library라이브러리 열기 오류
-
+ Delete comics만화 삭제
-
+ All the selected comics will be deleted from your disk. Are you sure?선택한 만화가 모두 디스크에서 삭제됩니다. 확실합니까?
-
+ Remove comics만화 제거
-
+ Comics will only be deleted from the current label/list. Are you sure?만화가 현재 라벨/목록에서만 삭제됩니다. 확실합니까?
-
+ Library name already exists라이브러리 이름 중복
-
+ There is another library with the name '%1'.'%1' 이름의 라이브러리가 이미 있습니다.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Missing files: %3
선택한 만화를 즐겨찾기 목록에 추가
+
+ ListInfoView
+
+
+ 1 comic
+ 만화 1권
+
+
+
+ %1 comics
+ 만화 %1권
+
+
+
+ Last day
+ 지난 1일
+
+
+
+ Last %1 days
+ 지난 %1일
+
+
+
+ 1 sublist
+ 하위 목록 1개
+
+
+
+ %1 sublists
+ 하위 목록 %1개
+
+LocalComicListModel
@@ -1972,143 +2152,143 @@ Missing files: %3
OptionsDialog
-
+ Language언어
-
+ Application language응용 프로그램 언어
-
+ System default시스템 기본값
-
+ Tray icon settings (experimental)트레이 아이콘 설정 (실험적)
-
+ Close to tray트레이로 최소화
-
+ Start into the system tray시스템 트레이에서 시작
-
+ Edit Comic Vine API keyComic Vine API 키 편집
-
+ Comic Vine API keyComic Vine API 키
-
+ ComicInfo.xml legacy supportComicInfo.xml 레거시 지원
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comics새 만화 추가 시 ComicInfo.xml에서 메타데이터 가져오기
-
+ Consider 'recent' items added or updated since X days agoX일 전부터 추가되거나 업데이트된 항목을 '최근'으로 간주
-
+ Third party reader타사 뷰어
-
+ Write {comic_file_path} where the path should go in the command명령어에서 경로가 들어갈 자리에 {comic_file_path}를 입력하세요
-
+ Clear지우기
-
+ Update libraries at startup시작 시 라이브러리 업데이트
-
+ Try to detect changes automatically변경 사항 자동 감지 시도
-
+ Update libraries periodically라이브러리 주기적으로 업데이트
-
+ Interval:간격:
-
+ 30 minutes30분
-
+ 1 hour1시간
-
+ 2 hours2시간
-
+ 4 hours4시간
-
+ 8 hours8시간
-
+ 12 hours12시간
-
+ daily매일
-
+ Update libraries at certain time특정 시간에 라이브러리 업데이트
-
+ Time:시간:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2122,60 +2302,75 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
자동 업데이트를 중단하려면 라이브러리 제목 옆에 표시되는 로딩 아이콘을 눌러주세요.
-
+ Modifications detection수정 감지
-
+ Compare the modified date of files when updating a library (not recommended)라이브러리 업데이트 시 파일 수정 날짜 비교 (권장하지 않음)
-
+ Enable background image배경 이미지 사용
-
+ Opacity level불투명도
-
+ Blur level흐림 정도
-
+ Use selected comic cover as background선택한 만화 표지를 배경으로 사용
-
+ Restore defautls기본값으로 복원
-
+ Background배경
-
+ Display continue reading banner이어 읽기 배너 표시
-
+ Display current comic banner현재 만화 배너 표시
-
+ Continue reading이어 읽기
+
+
+ Mix folders and comics
+ 폴더와 만화 함께 표시
+
+
+
+ Start comics on a new row
+ 만화를 새 행에서 시작
+
+
+
+ Content
+ 콘텐츠
+ Comic Flow
@@ -2183,7 +2378,7 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ Libraries라이브러리
@@ -3270,7 +3465,7 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
+ Set portset port포트 설정
@@ -3292,53 +3487,53 @@ Use quotes to include spaces in a value.
IP 주소 선택
-
-
+
+ Server connectivity서버 연결
-
+ Scan to connect스캔하여 연결
-
+ Devices on this network can reach your library at the address below.이 네트워크의 기기는 아래 주소를 통해 라이브러리에 접속할 수 있습니다.
-
+ IP addressIP 주소
-
+ Port포트
-
+ Web interface웹 인터페이스
-
+ Copy link링크 복사
-
+ Open web UI웹 UI 열기
-
+ Enable the server서버 활성화
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader는 iOS와 Android에서 사용할 수 있습니다. <a href='https://ios.yacreader.com'>iOS</a> 또는 <a href='https://android.yacreader.com'>Android</a>용 앱을 만나 보세요.
@@ -3765,12 +3960,12 @@ Use quotes to include spaces in a value.
Release notes are not available.
-
+ 릴리스 노트를 사용할 수 없습니다.Previous versions
-
+ 이전 버전
diff --git a/YACReaderLibrary/yacreaderlibrary_nl.ts b/YACReaderLibrary/yacreaderlibrary_nl.ts
index 6df1eaa3b..3410e1980 100644
--- a/YACReaderLibrary/yacreaderlibrary_nl.ts
+++ b/YACReaderLibrary/yacreaderlibrary_nl.ts
@@ -425,6 +425,14 @@
Op zoek naar komische...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Verder lezen...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Deze map bevat nog geen strips
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Niets geselecteerd
+
+
+
+ Select a comic or folder to see its information.
+ Selecteer een strip of map om de informatie te bekijken.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Verder lezen...
+ Verder lezen...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Onbekend
+
+
+
+ Items
+ Items
+
+
+
+ Type
+ Type
+
+
+
+ Reading status
+ Leesstatus
+
+
+
+ Read
+ Gelezen
+
+
+
+ Unread
+ Ongelezen
+
+
+
+ Collection status
+ Collectiestatus
+
+
+
+ Completed
+ Voltooid
+
+
+
+ In progress
+ Bezig
+
+
+
+ Added
+ Toegevoegd
+
+
+
+ Updated
+ BijgewerktGridComicsView
-
+ Show infoToon informatie
+
+ Library
+ Bibliotheek
+
+
+ Folder
+ Map
+
+
+ Favorites
+ Favorieten
+
+
+ Recently added
+ Onlangs toegevoegd
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Westerse manga
+
+
+
+ Web comic
+ Webcomic
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Grappig
+
+
+
+ Unknown
+ Onbekend
+ HelpAboutDialog
@@ -805,20 +929,43 @@
<p>De huidige bibliotheek wordt gecontroleerd op ontbrekende covers en onvolledige stripinformatie.</p><p>Dit kan enkele minuten duren. Je kunt het proces stoppen en later opnieuw uitvoeren.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Bibliotheekinformatie
+
+
+
+ Number of folders
+ Aantal mappen
+
+
+
+ Number of comics
+ Aantal strips
+
+
+
+ Number of read comics
+ Aantal gelezen strips
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.De geselecteerde map bevat geen bibliotheek.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Deze bibliotheek is gemaakt met een vorige versie van YACReaderLibrary. Het moet worden bijgewerkt. Nu bijwerken?
-
+ Error opening the libraryFout bij openen Bibliotheek
@@ -827,52 +974,52 @@
Verwijder metagegevens
-
+ Old libraryOude Bibliotheek
-
+ LibraryBibliotheek
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Deze bibliotheek is gemaakt met een nieuwere versie van YACReaderLibrary. Download de nieuwe versie?
-
+ Library '%1' is no longer available. Do you want to remove it?Bibliotheek ' %1' is niet langer beschikbaar. Wilt u het verwijderen?
-
+ Open folder...Map openen ...
-
+ Do you want remove Wilt u verwijderen
-
+ Error updating the libraryFout bij bijwerken Bibliotheek
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?Bibliotheek ' %1' is gemaakt met een oudere versie van YACReaderLibrary. Zij moet opnieuw worden aangemaakt. Wilt u de bibliotheek nu aanmaken?
-
+ Set as readInstellen als gelezen
-
+ Library not availableBibliotheek niet beschikbaar
@@ -882,321 +1029,321 @@
YACReader Bibliotheek
-
+ Error creating the libraryFout bij aanmaken Bibliotheek
-
+ Update neededBijwerken is nodig
-
+ Library name already existsBibliotheek naam bestaat al
-
+ There is another library with the name '%1'.Er is al een bibliotheek met de naam ' %1 '.
-
+ Download new versionNieuwe versie ophalen
-
+ Delete comicsStrips verwijderen
-
+ All the selected comics will be deleted from your disk. Are you sure?Alle geselecteerde strips worden verwijderd van uw schijf. Weet u het zeker?
-
-
+
+ Set as unreadInstellen als ongelezen
-
+ Library not foundBibliotheek niet gevonden
-
-
-
+
+
+ mangaManga
-
-
-
+
+
+ comicgrappig
-
-
-
+
+
+ western manga (left to right)westerse manga (van links naar rechts)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (van boven naar beneden)
-
+ library?Bibliotheek?
-
+ Are you sure?Weet u het zeker?
-
+ Rescan library for XML infoBibliotheek opnieuw scannen op XML-info
-
-
-
+
+
+ web comicweb-strip
-
+ Add new folderNieuwe map toevoegen
-
+ Delete folderMap verwijderen
-
+ Set as uncompletedIngesteld als onvoltooid
-
+ Set as completedInstellen als voltooid
-
+ Update folderMap bijwerken
-
+ FolderMap
-
+ ComicGrappig
-
+ Upgrade failedUpgrade mislukt
-
+ There were errors during library upgrade in: Er zijn fouten opgetreden tijdens de bibliotheekupgrade in:
-
-
+
+ Copying comics...Strips kopiëren...
-
-
+
+ Moving comics...Strips verplaatsen...
-
+ Folder name:Mapnaam:
-
+ No folder selectedGeen map geselecteerd
-
+ Please, select a folder firstSelecteer eerst een map
-
+ Error in pathFout in pad
-
+ There was an error accessing the folder's pathEr is een fout opgetreden bij het verkrijgen van toegang tot het pad van de map
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?De geselecteerde map en de volledige inhoud ervan worden van uw schijf verwijderd. Weet je het zeker?
-
-
+
+ Unable to deleteKan niet verwijderen
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Er is een probleem opgetreden bij het verwijderen van de geselecteerde mappen. Controleer of er schrijfrechten zijn en zorg ervoor dat alle toepassingen deze mappen of een van de daarin opgenomen bestanden gebruiken.
-
+ Add new reading listsVoeg nieuwe leeslijsten toe
-
-
+
+ List name:Lijstnaam:
-
+ Delete list/labelLijst/label verwijderen
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?Het geselecteerde item wordt verwijderd, uw strips of mappen worden NIET van uw schijf verwijderd. Weet je het zeker?
-
+ Rename list nameHernoem de lijstnaam
-
-
-
-
+
+
+
+ Set typeSoort instellen
-
+ Search filtersZoekfilters
-
+ UnreadOngelezen
-
+ In progressBezig
-
+ Highly ratedHoog gewaardeerd
-
+ Recently addedOnlangs toegevoegd
-
+ Search syntax…Zoeksyntaxis…
-
+ A repair of this library is already running (%1). Wait for it to finish.Er wordt al een herstel van deze bibliotheek uitgevoerd (%1). Wacht tot dit is voltooid.
-
+ The library is locked by a repair that did not finish.De bibliotheek is vergrendeld door een herstel dat niet is voltooid.
-
+ The library is locked by a repair started by %1.De bibliotheek is vergrendeld door een herstel gestart door %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Als u zeker weet dat er geen ander herstel bezig is, kan de vergrendeling worden verwijderd. Vergrendeling verwijderen en doorgaan?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedHerstel na onderbroken terugzetting mislukt
-
+ Set custom coverAangepaste omslag instellen
-
+ Delete custom coverAangepaste omslag verwijderen
-
+ Save coversBewaar hoesjes
-
+ You are adding too many libraries.U voegt te veel bibliotheken toe.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1209,74 +1356,74 @@ Je hebt waarschijnlijk maar één bibliotheek nodig in je stripmap op het hoogst
YACReaderLibrary zal u er niet van weerhouden om meer bibliotheken te creëren, maar u moet het aantal bibliotheken laag houden.
-
-
+
+ YACReader not foundYACReader niet gevonden
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader niet gevonden. YACReader moet in dezelfde map worden geïnstalleerd als YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader niet gevonden. Er is mogelijk een probleem met uw YACReader-installatie.
-
+ ErrorFout
-
+ Error opening comic with third party reader.Fout bij het openen van een strip met een lezer van een derde partij.
-
-
+
+ YACReader library database (*.ydb)YACReader-bibliotheekdatabase (*.ydb)
-
+ The library database backup was created at:
%1De back-up van de bibliotheekdatabase is gemaakt in:
%1
-
+ Unable to create the library database backup:
%1De back-up van de bibliotheekdatabase kon niet worden gemaakt:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Sluit YACReaderLibraryServer en alle andere YACReader-programma's die deze bibliotheek gebruiken voordat je deze herstelt. Doorgaan?
-
+ Restoring library database...Bibliotheekdatabase wordt hersteld...
-
+ The current library database is invalid. Restore the selected backup anyway?De huidige bibliotheekdatabase is ongeldig. De geselecteerde back-up toch herstellen?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Het onderhoudsslot van de bibliotheek is mogelijk verouderd. Verwijderen en opnieuw proberen?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1285,71 +1432,71 @@ Restart YACReaderLibrary before attempting recovery again.
Start YACReaderLibrary opnieuw voordat je nogmaals herstel probeert.
-
+ The library database was restored successfully. Update the library now?De bibliotheekdatabase is hersteld. De bibliotheek nu bijwerken?
-
+ Library database damagedBibliotheekdatabase beschadigd
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.De database van bibliotheek '%1' is beschadigd. Normale updates, onderhoud en back-ups zijn daarom niet beschikbaar. YACReader kan proberen de database te herstellen. Sommige beschadigde gegevens kunnen mogelijk niet worden hersteld. Bestaande back-ups worden niet gewijzigd.
-
+ Attempt repairHerstel proberen
-
+ Restore a backup...Een back-up herstellen...
-
+ Repairing library database...Bibliotheekdatabase wordt hersteld...
-
-
-
+
+
+ Library database repairBibliotheekdatabase herstellen
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Een andere onderhoudsbewerking gebruikt deze bibliotheek momenteel. Probeer het opnieuw wanneer die is voltooid.
-
+ The library database is already valid.De bibliotheekdatabase is al geldig.
-
+ Library database repairedBibliotheekdatabase hersteld
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1De bibliotheekdatabase is hersteld door de indexen opnieuw op te bouwen. Het beschadigde origineel is bewaard in:
%1
-
+ Library database rebuiltBibliotheekdatabase opnieuw opgebouwd
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1360,7 +1507,7 @@ Update the library now?
De bibliotheek nu bijwerken?
-
+
The damaged original was preserved at:
@@ -1371,12 +1518,12 @@ Het beschadigde origineel is bewaard in:
%1
-
+ Library database repair failedHerstel van bibliotheekdatabase mislukt
-
+ The library database could not be repaired:
%1%2
@@ -1387,62 +1534,62 @@ You can restore a backup from the Library menu or recreate the library.
Je kunt een back-up herstellen via het menu Bibliotheek of de bibliotheek opnieuw maken.
-
+ Remove and delete metadata and backupsMetagegevens en back-ups verwijderen en wissen
-
+ Library infoBibliotheekinformatie
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Er is een probleem opgetreden bij het verwijderen van de geselecteerde strips. Controleer of er schrijfrechten zijn voor de geselecteerde bestanden of de map waarin deze zich bevinden.
-
+ Assign comics numbersWijs stripnummers toe
-
+ Assign numbers starting in:Nummers toewijzen beginnend met:
-
+ Invalid imageOngeldige afbeelding
-
+ The selected file is not a valid image.Het geselecteerde bestand is geen geldige afbeelding.
-
+ Error saving coverFout bij opslaan van dekking
-
+ There was an error saving the cover image.Er is een fout opgetreden bij het opslaan van de omslagafbeelding.
-
+ Remove comicsVerwijder strips
-
+ Comics will only be deleted from the current label/list. Are you sure?Strips worden alleen verwijderd van het huidige label/de huidige lijst. Weet je het zeker?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Ontbrekende bestanden: %3
Voeg geselecteerde strips toe aan de favorietenlijst
+
+ ListInfoView
+
+
+ 1 comic
+ 1 strip
+
+
+
+ %1 comics
+ %1 strips
+
+
+
+ Last day
+ Afgelopen dag
+
+
+
+ Last %1 days
+ Afgelopen %1 dagen
+
+
+
+ 1 sublist
+ 1 sublijst
+
+
+
+ %1 sublists
+ %1 sublijsten
+
+LocalComicListModel
@@ -1982,143 +2162,143 @@ Ontbrekende bestanden: %3
Opties
-
+ LanguageTaal
-
+ Application languageApplicatietaal
-
+ System defaultStandaard van het systeem
-
+ Tray icon settings (experimental)Instellingen voor ladepictogram (experimenteel)
-
+ Close to trayDicht bij lade
-
+ Start into the system trayBegin in het systeemvak
-
+ Edit Comic Vine API keyBewerk de Comic Vine API-sleutel
-
+ Comic Vine API keyComic Vine API-sleutel
-
+ ComicInfo.xml legacy supportComicInfo.xml verouderde ondersteuning
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImporteer metagegevens uit ComicInfo.xml wanneer u nieuwe strips toevoegt
-
+ Consider 'recent' items added or updated since X days agoOverweeg 'recente' items die sinds X dagen geleden zijn toegevoegd of bijgewerkt
-
+ Third party readerLezer van derden
-
+ Write {comic_file_path} where the path should go in the commandSchrijf {comic_file_path} waar het pad naartoe moet in de opdracht
-
+ ClearDuidelijk
-
+ Update libraries at startupUpdate bibliotheken bij het opstarten
-
+ Try to detect changes automaticallyProbeer wijzigingen automatisch te detecteren
-
+ Update libraries periodicallyUpdate bibliotheken regelmatig
-
+ Interval:Tijdsinterval:
-
+ 30 minutes30 minuten
-
+ 1 hour1 uur
-
+ 2 hours2 uur
-
+ 4 hours4 uur
-
+ 8 hours8 uur
-
+ 12 hours12 uur
-
+ dailydagelijks
-
+ Update libraries at certain timeUpdate bibliotheken op een bepaald tijdstip
-
+ Time:Tijd:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2132,60 +2312,75 @@ During automatic updates the app will block some of the actions until the update
Om een automatische update te stoppen, tikt u op de laadindicator naast de titel van Bibliotheken.
-
+ Modifications detectionDetectie van wijzigingen
-
+ Compare the modified date of files when updating a library (not recommended)Vergelijk de wijzigingsdatum van bestanden bij het updaten van een bibliotheek (niet aanbevolen)
-
+ Enable background imageAchtergrondafbeelding inschakelen
-
+ Opacity levelDekkingsniveau
-
+ Blur levelVervagingsniveau
-
+ Use selected comic cover as backgroundGebruik geselecteerde stripomslag als achtergrond
-
+ Restore defautlsStandaardwaarden herstellen
-
+ BackgroundAchtergrond
-
+ Display continue reading bannerToon de banner voor verder lezen
-
+ Display current comic bannerToon huidige stripbanner
-
+ Continue readingLees verder
+
+
+ Mix folders and comics
+ Mappen en strips mengen
+
+
+
+ Start comics on a new row
+ Strips op een nieuwe rij beginnen
+
+
+
+ Content
+ Inhoud
+ Comic Flow
@@ -2193,7 +2388,7 @@ Om een automatische update te stoppen, tikt u op de laadindicator naast de
-
+ LibrariesBibliotheken
@@ -3270,53 +3465,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivitySerververbinding
-
+ Scan to connectScan om verbinding te maken
-
+ Devices on this network can reach your library at the address below.Apparaten op dit netwerk kunnen je bibliotheek bereiken via het onderstaande adres.
-
+ IP addressIP-adres
-
+ PortPoort
-
+ Web interfaceWebinterface
-
+ Copy linkLink kopiëren
-
+ Open web UIWebinterface openen
-
+ Enable the serverServer inschakelen
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader is beschikbaar voor iOS en Android. Ontdek de app voor <a href='https://ios.yacreader.com'>iOS</a> of <a href='https://android.yacreader.com'>Android</a>.
@@ -3325,7 +3520,7 @@ Use quotes to include spaces in a value.
De server instellen
-
+ Set portset portPoort instellen
diff --git a/YACReaderLibrary/yacreaderlibrary_pt.ts b/YACReaderLibrary/yacreaderlibrary_pt.ts
index cd7be4386..74830e0b6 100644
--- a/YACReaderLibrary/yacreaderlibrary_pt.ts
+++ b/YACReaderLibrary/yacreaderlibrary_pt.ts
@@ -425,6 +425,14 @@
Procurando quadrinhos...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Continuar a ler...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Esta pasta ainda não contém quadrinhos
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Nada selecionado
+
+
+
+ Select a comic or folder to see its information.
+ Selecione um quadrinho ou uma pasta para ver suas informações.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Continuar a ler...
+ Continuar a ler...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Desconhecido
+
+
+
+ Items
+ Itens
+
+
+
+ Type
+ Tipo
+
+
+
+ Reading status
+ Status de leitura
+
+
+
+ Read
+ Ler
+
+
+
+ Unread
+ Não lidos
+
+
+
+ Collection status
+ Status da coleção
+
+
+
+ Completed
+ Concluído
+
+
+
+ In progress
+ Em andamento
+
+
+
+ Added
+ Adicionado
+
+
+
+ Updated
+ AtualizadoGridComicsView
-
+ Show infoMostrar informações
+
+ Library
+ Biblioteca
+
+
+ Folder
+ Pasta
+
+
+ Favorites
+ Favoritos
+
+
+ Recently added
+ Adicionados recentemente
+
+
+
+ Manga
+ Mangá
+
+
+
+ Western manga
+ Mangá ocidental
+
+
+
+ Web comic
+ Quadrinho da web
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Quadrinhos
+
+
+
+ Unknown
+ Desconhecido
+ HelpAboutDialog
@@ -805,35 +929,58 @@
<p>A biblioteca atual está sendo verificada em busca de capas ausentes e informações incompletas dos quadrinhos.</p><p>Isso pode levar vários minutos. Você pode interromper o processo e executá-lo novamente mais tarde.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Informações da biblioteca
+
+
+
+ Number of folders
+ Número de pastas
+
+
+
+ Number of comics
+ Número de quadrinhos
+
+
+
+ Number of read comics
+ Número de quadrinhos lidos
+
+LibraryWindow
-
+ LibraryBiblioteca
-
+ Open folder...Abrir pasta...
-
-
-
+
+
+ western manga (left to right)mangá ocidental (da esquerda para a direita)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (de cima para baixo)
-
+ Do you want remove Você deseja remover
@@ -843,306 +990,306 @@
Biblioteca YACReader
-
-
-
+
+
+ mangamangá
-
-
-
+
+
+ comiccômico
-
+ Are you sure?Você tem certeza?
-
+ Rescan library for XML infoReanalisar biblioteca para informa??es XML
-
+ Set as readDefinir como lido
-
-
+
+ Set as unreadDefinir como não lido
-
-
-
+
+
+ web comicquadrinhos da web
-
+ Add new folderAdicionar nova pasta
-
+ Delete folderExcluir pasta
-
+ Set as uncompletedDefinir como incompleto
-
+ Set as completedDefinir como concluído
-
+ Update folderAtualizar pasta
-
+ FolderPasta
-
+ ComicQuadrinhos
-
+ Upgrade failedFalha na atualização
-
+ There were errors during library upgrade in: Ocorreram erros durante a atualização da biblioteca em:
-
+ Restore recovery failedFalha na recuperação do restauro
-
+ Update neededAtualização necessária
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Esta biblioteca foi criada com uma versão anterior do YACReaderLibrary. Ele precisa ser atualizado. Atualizar agora?
-
+ Download new versionBaixe a nova versão
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Esta biblioteca foi criada com uma versão mais recente do YACReaderLibrary. Baixe a nova versão agora?
-
+ Library not availableBiblioteca não disponível
-
+ Library '%1' is no longer available. Do you want to remove it?A biblioteca '%1' não está mais disponível. Você quer removê-lo?
-
+ Old libraryBiblioteca antiga
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?A biblioteca '%1' foi criada com uma versão mais antiga do YACReaderLibrary. Deve ser criado novamente. Deseja criar a biblioteca agora?
-
-
+
+ Copying comics...Copiando quadrinhos...
-
-
+
+ Moving comics...Quadrinhos em movimento...
-
+ Folder name:Nome da pasta:
-
+ No folder selectedNenhuma pasta selecionada
-
+ Please, select a folder firstPor favor, selecione uma pasta primeiro
-
+ Error in pathErro no caminho
-
+ There was an error accessing the folder's pathOcorreu um erro ao acessar o caminho da pasta
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?A pasta selecionada e todo o seu conteúdo serão excluídos do disco. Tem certeza?
-
-
+
+ Unable to deleteNão foi possível excluir
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Ocorreu um problema ao tentar excluir as pastas selecionadas. Por favor, verifique as permissões de gravação e certifique-se de que algum aplicativo esteja usando essas pastas ou qualquer um dos arquivos contidos.
-
+ Add new reading listsAdicione novas listas de leitura
-
-
+
+ List name:Nome da lista:
-
+ Delete list/labelExcluir lista/rótulo
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?O item selecionado será excluído, seus quadrinhos ou pastas NÃO serão excluídos do disco. Tem certeza?
-
+ Rename list nameRenomear nome da lista
-
-
-
-
+
+
+
+ Set typeDefinir tipo
-
+ Search filtersFiltros de pesquisa
-
+ UnreadNão lidos
-
+ In progressEm andamento
-
+ Highly ratedBem avaliados
-
+ Recently addedAdicionados recentemente
-
+ Search syntax…Sintaxe de pesquisa…
-
+ A repair of this library is already running (%1). Wait for it to finish.Uma reparação desta biblioteca já está em execução (%1). Aguarde a conclusão.
-
+ The library is locked by a repair that did not finish.A biblioteca está bloqueada por uma reparação que não terminou.
-
+ The library is locked by a repair started by %1.A biblioteca está bloqueada por uma reparação iniciada por %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Se tem certeza de que nenhuma outra reparação está em execução, o bloqueio pode ser removido. Remover o bloqueio e continuar?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Set custom coverDefinir capa personalizada
-
+ Delete custom coverExcluir capa personalizada
-
+ Save coversSalvar capas
-
+ You are adding too many libraries.Você está adicionando muitas bibliotecas.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1155,84 +1302,84 @@ Você provavelmente só precisa de uma biblioteca em sua pasta de quadrinhos de
YACReaderLibrary não impedirá você de criar mais bibliotecas, mas você deve manter o número de bibliotecas baixo.
-
-
+
+ YACReader not foundYACReader não encontrado
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader não encontrado. YACReader deve ser instalado na mesma pasta que YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader não encontrado. Pode haver um problema com a instalação do YACReader.
-
+ ErrorErro
-
+ Error opening comic with third party reader.Erro ao abrir o quadrinho com leitor de terceiros.
-
+ Library not foundBiblioteca não encontrada
-
+ The selected folder doesn't contain any library.A pasta selecionada não contém nenhuma biblioteca.
-
-
+
+ YACReader library database (*.ydb)Base de dados da biblioteca YACReader (*.ydb)
-
+ The library database backup was created at:
%1A cópia de segurança da base de dados da biblioteca foi criada em:
%1
-
+ Unable to create the library database backup:
%1Não foi possível criar a cópia de segurança da base de dados da biblioteca:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Feche o YACReaderLibraryServer e qualquer outra aplicação YACReader que esteja a usar esta biblioteca antes de restaurar. Continuar?
-
+ Restoring library database...A restaurar a base de dados da biblioteca...
-
+ The current library database is invalid. Restore the selected backup anyway?A base de dados atual da biblioteca não é válida. Restaurar a cópia de segurança selecionada mesmo assim?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?O bloqueio de manutenção da biblioteca pode estar obsoleto. Removê-lo e tentar novamente?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1241,71 +1388,71 @@ Restart YACReaderLibrary before attempting recovery again.
Reinicie o YACReaderLibrary antes de tentar novamente a recuperação.
-
+ The library database was restored successfully. Update the library now?A base de dados da biblioteca foi restaurada com êxito. Atualizar a biblioteca agora?
-
+ Library database damagedBase de dados da biblioteca danificada
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.A base de dados da biblioteca '%1' está danificada, pelo que as atualizações, a manutenção e as cópias de segurança normais não estão disponíveis. O YACReader pode tentar reparar a base de dados. Alguns dados danificados poderão não ser recuperados. As cópias de segurança existentes não serão alteradas.
-
+ Attempt repairTentar reparar
-
+ Restore a backup...Restaurar uma cópia de segurança...
-
+ Repairing library database...A reparar a base de dados da biblioteca...
-
-
-
+
+
+ Library database repairReparação da base de dados da biblioteca
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Outra operação de manutenção está a usar esta biblioteca. Tente novamente quando terminar.
-
+ The library database is already valid.A base de dados da biblioteca já é válida.
-
+ Library database repairedBase de dados da biblioteca reparada
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1A base de dados da biblioteca foi reparada através da reconstrução dos índices. O original danificado foi preservado em:
%1
-
+ Library database rebuiltBase de dados da biblioteca reconstruída
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1316,7 +1463,7 @@ Update the library now?
Atualizar a biblioteca agora?
-
+
The damaged original was preserved at:
@@ -1327,12 +1474,12 @@ O original danificado foi preservado em:
%1
-
+ Library database repair failedFalha ao reparar a base de dados da biblioteca
-
+ The library database could not be repaired:
%1%2
@@ -1343,12 +1490,12 @@ You can restore a backup from the Library menu or recreate the library.
Pode restaurar uma cópia de segurança no menu Biblioteca ou recriar a biblioteca.
-
+ library? biblioteca?
-
+ Remove and delete metadata and backupsRemover e eliminar metadados e cópias de segurança
@@ -1357,92 +1504,92 @@ Pode restaurar uma cópia de segurança no menu Biblioteca ou recriar a bibliote
Remover e excluir metadados
-
+ Library infoInformações da biblioteca
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Ocorreu um problema ao tentar excluir os quadrinhos selecionados. Por favor, verifique as permissões de gravação nos arquivos selecionados ou na pasta que os contém.
-
+ Assign comics numbersAtribuir números de quadrinhos
-
+ Assign numbers starting in:Atribua números começando em:
-
+ Invalid imageImagem inválida
-
+ The selected file is not a valid image.O arquivo selecionado não é uma imagem válida.
-
+ Error saving coverErro ao salvar a capa
-
+ There was an error saving the cover image.Ocorreu um erro ao salvar a imagem da capa.
-
+ Error creating the libraryErro ao criar a biblioteca
-
+ Error updating the libraryErro ao atualizar a biblioteca
-
+ Error opening the libraryErro ao abrir a biblioteca
-
+ Delete comicsExcluir quadrinhos
-
+ All the selected comics will be deleted from your disk. Are you sure?Todos os quadrinhos selecionados serão excluídos do seu disco. Tem certeza?
-
+ Remove comicsRemover quadrinhos
-
+ Comics will only be deleted from the current label/list. Are you sure?Os quadrinhos serão excluídos apenas do rótulo/lista atual. Tem certeza?
-
+ Library name already existsO nome da biblioteca já existe
-
+ There is another library with the name '%1'.Existe outra biblioteca com o nome '%1'.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1930,6 +2077,39 @@ Arquivos ausentes: %3
Adicione quadrinhos selecionados à lista de favoritos
+
+ ListInfoView
+
+
+ 1 comic
+ 1 quadrinho
+
+
+
+ %1 comics
+ %1 quadrinhos
+
+
+
+ Last day
+ Último dia
+
+
+
+ Last %1 days
+ Últimos %1 dias
+
+
+
+ 1 sublist
+ 1 sublista
+
+
+
+ %1 sublists
+ %1 sublistas
+
+LocalComicListModel
@@ -1972,143 +2152,143 @@ Arquivos ausentes: %3
OptionsDialog
-
+ LanguageIdioma
-
+ Application languageIdioma do aplicativo
-
+ System defaultPadrão do sistema
-
+ Tray icon settings (experimental)Configurações do ícone da bandeja (experimental)
-
+ Close to trayPerto da bandeja
-
+ Start into the system trayComece na bandeja do sistema
-
+ Edit Comic Vine API keyEditar chave da API Comic Vine
-
+ Comic Vine API keyChave de API do Comic Vine
-
+ ComicInfo.xml legacy supportSuporte legado ComicInfo.xml
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsImporte metadados de ComicInfo.xml ao adicionar novos quadrinhos
-
+ Consider 'recent' items added or updated since X days agoConsidere itens 'recentes' adicionados ou atualizados há X dias
-
+ Third party readerLeitor de terceiros
-
+ Write {comic_file_path} where the path should go in the commandEscreva {comic_file_path} onde o caminho deve ir no comando
-
+ ClearClaro
-
+ Update libraries at startupAtualizar bibliotecas na inicialização
-
+ Try to detect changes automaticallyTente detectar alterações automaticamente
-
+ Update libraries periodicallyAtualize bibliotecas periodicamente
-
+ Interval:Intervalo:
-
+ 30 minutes30 minutos
-
+ 1 hour1 hora
-
+ 2 hours2 horas
-
+ 4 hours4 horas
-
+ 8 hours8 horas
-
+ 12 hours12 horas
-
+ dailydiário
-
+ Update libraries at certain timeAtualizar bibliotecas em determinado momento
-
+ Time:Tempo:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2122,60 +2302,75 @@ Durante as atualizações automáticas, o aplicativo bloqueará algumas ações
Para interromper uma atualização automática, toque no indicador de carregamento próximo ao título Bibliotecas.
-
+ Modifications detectionDetecção de modificações
-
+ Compare the modified date of files when updating a library (not recommended)Compare a data de modificação dos arquivos ao atualizar uma biblioteca (não recomendado)
-
+ Enable background imageAtivar imagem de fundo
-
+ Opacity levelNível de opacidade
-
+ Blur levelNível de desfoque
-
+ Use selected comic cover as backgroundUse a capa de quadrinhos selecionada como plano de fundo
-
+ Restore defautlsRestaurar padrões
-
+ BackgroundFundo
-
+ Display continue reading bannerExibir banner para continuar lendo
-
+ Display current comic bannerExibir banner de quadrinhos atual
-
+ Continue readingContinuar lendo
+
+
+ Mix folders and comics
+ Misturar pastas e quadrinhos
+
+
+
+ Start comics on a new row
+ Iniciar quadrinhos em uma nova linha
+
+
+
+ Content
+ Conteúdo
+ Comic Flow
@@ -2183,7 +2378,7 @@ Para interromper uma atualização automática, toque no indicador de carregamen
-
+ LibrariesBibliotecas
@@ -3270,7 +3465,7 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
+ Set portset portDefinir porta
@@ -3292,53 +3487,53 @@ Use quotes to include spaces in a value.
Escolha um endereço IP
-
-
+
+ Server connectivityConectividade do servidor
-
+ Scan to connectDigitalize para ligar
-
+ Devices on this network can reach your library at the address below.Os dispositivos nesta rede podem aceder à sua biblioteca através do endereço abaixo.
-
+ IP addressEndereço IP
-
+ PortPorta
-
+ Web interfaceInterface web
-
+ Copy linkCopiar ligação
-
+ Open web UIAbrir interface web
-
+ Enable the serverAtivar o servidor
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.O YACReader está disponível para iOS e Android. Descubra-o para <a href='https://ios.yacreader.com'>iOS</a> ou <a href='https://android.yacreader.com'>Android</a>.
diff --git a/YACReaderLibrary/yacreaderlibrary_ru.ts b/YACReaderLibrary/yacreaderlibrary_ru.ts
index fc6cbf292..0bb444409 100644
--- a/YACReaderLibrary/yacreaderlibrary_ru.ts
+++ b/YACReaderLibrary/yacreaderlibrary_ru.ts
@@ -425,6 +425,14 @@
Получение информации...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Продолжить чтение...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
В этой папке еще нет комиксов
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Ничего не выбрано
+
+
+
+ Select a comic or folder to see its information.
+ Выберите комикс или папку, чтобы просмотреть информацию.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Продолжить чтение...
+ Продолжить чтение...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Неизвестно
+
+
+
+ Items
+ Элементы
+
+
+
+ Type
+ Тип
+
+
+
+ Reading status
+ Статус чтения
+
+
+
+ Read
+ Прочитано
+
+
+
+ Unread
+ Непрочитанные
+
+
+
+ Collection status
+ Статус коллекции
+
+
+
+ Completed
+ Завершено
+
+
+
+ In progress
+ В процессе
+
+
+
+ Added
+ Добавлено
+
+
+
+ Updated
+ ОбновленоGridComicsView
-
+ Show infoПоказать информацию
+
+ Library
+ Библиотека
+
+
+ Folder
+ Папка
+
+
+ Favorites
+ Избранное
+
+
+ Recently added
+ Недавно добавленные
+
+
+
+ Manga
+ Манга
+
+
+
+ Western manga
+ Западная манга
+
+
+
+ Web comic
+ Веб-комикс
+
+
+
+ Yonkoma
+ Ёнкома
+
+
+
+ Comic
+ Комикс
+
+
+
+ Unknown
+ Неизвестно
+ HelpAboutDialog
@@ -805,51 +929,74 @@
<p>Текущая библиотека проверяется на отсутствующие обложки и неполные сведения о комиксах.</p><p>Это может занять несколько минут. Процесс можно остановить и запустить снова позже.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Информация о библиотеке
+
+
+
+ Number of folders
+ Количество папок
+
+
+
+ Number of comics
+ Количество комиксов
+
+
+
+ Number of read comics
+ Количество прочитанных комиксов
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.Выбранная папка не содержит ни одной библиотеки.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Эта библиотека была создана с предыдущей версией YACReaderLibrary. Она должна быть обновлена. Обновить сейчас?
-
+ ComicКомикс
-
+ Folder name:Имя папки:
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?Выбранная папка и все ее содержимое будет удалено с вашего жёсткого диска. Вы уверены?
-
+ Error opening the libraryОшибка открытия библиотеки
-
-
+
+ YACReader not foundYACReader не найден
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Возникла проблема при удалении выбранных папок. Пожалуйста, проверьте права на запись и убедитесь что другие приложения не используют эти папки или файлы.
-
+ Rename list nameИзменить имя списка
@@ -858,110 +1005,110 @@
Удаление метаданных
-
+ Old libraryБиблиотека из старой версии YACreader
-
+ Set as completedОтметить как завершено
-
+ There was an error accessing the folder's pathОшибка доступа к пути папки
-
+ LibraryБиблиотека
-
+ Comics will only be deleted from the current label/list. Are you sure?Комиксы будут удалены только из выбранного списка/ярлыка. Вы уверены?
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Эта библиотека была создана новой версией YACReaderLibrary. Скачать новую версию сейчас?
-
-
+
+ Moving comics...Переместить комиксы...
-
-
+
+ Copying comics...Скопировать комиксы...
-
+ Library '%1' is no longer available. Do you want to remove it?Библиотека '%1' больше не доступна. Вы хотите удалить ее?
-
+ Open folder...Открыть папку...
-
+ Do you want remove Вы хотите удалить библиотеку
-
+ Set as uncompletedОтметить как не завершено
-
+ Error in pathОшибка в пути
-
+ Error updating the libraryОшибка обновления библиотеки
-
+ FolderПапка
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?Выбранные элементы будут удалены, ваши комиксы или папки НЕ БУДУТ удалены с вашего жёсткого диска. Вы уверены?
-
-
+
+ List name:Имя списка:
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?Библиотека '%1' была создана старой версией YACReaderLibrary. Она должна быть вновь создана. Вы хотите создать библиотеку сейчас?
-
+ Save coversСохранить обложки
-
+ Add new reading listsДобавить новый список чтения
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -974,32 +1121,32 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
YACReaderLibrary не помешает вам создать больше библиотек, но вы должны иметь не большое количество библиотек.
-
+ Set as readОтметить как прочитано
-
+ Library infoИнформация о библиотеке
-
+ Assign comics numbersПорядковый номер
-
+ Please, select a folder firstПожалуйста, сначала выберите папку
-
+ Library not availableБиблиотека не доступна
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Возникла проблема при удалении выбранных комиксов. Пожалуйста, проверьте права на запись для выбранных файлов или содержащую их папку.
@@ -1009,293 +1156,293 @@ YACReaderLibrary не помешает вам создать больше биб
Библиотека YACReader
-
+ Error creating the libraryОшибка создания библиотеки
-
+ You are adding too many libraries.Вы добавляете слишком много библиотек.
-
+ Update folderОбновить папку
-
+ Update neededНеобходимо обновление
-
+ Library name already existsИмя папки уже используется
-
+ There is another library with the name '%1'.Уже существует другая папка с именем '%1'.
-
+ Delete folderУдалить папку
-
+ Assign numbers starting in:Назначить порядковый номер начиная с:
-
+ Download new versionЗагрузить новую версию
-
+ Remove and delete metadata and backupsУдалить библиотеку, метаданные и резервные копии
-
+ Invalid imageНеверное изображение
-
+ The selected file is not a valid image.Выбранный файл не является допустимым изображением.
-
+ Error saving coverНе удалось сохранить обложку.
-
+ There was an error saving the cover image.Не удалось сохранить изображение обложки.
-
+ Delete comicsУдалить комиксы
-
+ Add new folderДобавить новую папку
-
+ Delete list/labelУдалить список/ярлык
-
+ No folder selectedНи одна папка не была выбрана
-
+ All the selected comics will be deleted from your disk. Are you sure?Все выбранные комиксы будут удалены с вашего жёсткого диска. Вы уверены?
-
+ Remove comicsУбрать комиксы
-
-
+
+ Set as unreadОтметить как не прочитано
-
+ Library not foundБиблиотека не найдена
-
-
-
+
+
+ mangaманга
-
-
-
+
+
+ comicкомикс
-
-
-
+
+
+ web comicвеб-комикс
-
-
-
+
+
+ western manga (left to right)западная манга (слева направо)
-
-
+
+ Unable to deleteНе удалось удалить
-
-
-
+
+
+ 4koma (top to botom)4кома (сверху вниз)
-
+ Search filtersФильтры поиска
-
+ UnreadНепрочитанные
-
+ In progressВ процессе
-
+ Highly ratedС высокой оценкой
-
+ Recently addedНедавно добавленные
-
+ Search syntax…Синтаксис поиска…
-
-
-
-
+
+
+
+ Set typeТип установки
-
+ A repair of this library is already running (%1). Wait for it to finish.Восстановление этой библиотеки уже выполняется (%1). Дождитесь его завершения.
-
+ The library is locked by a repair that did not finish.Библиотека заблокирована незавершённым восстановлением.
-
+ The library is locked by a repair started by %1.Библиотека заблокирована восстановлением, запущенным %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Если вы уверены, что никакое другое восстановление не выполняется, блокировку можно снять. Снять блокировку и продолжить?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedНе удалось восстановиться после прерванного восстановления
-
+ Set custom coverУстановить собственную обложку
-
+ Delete custom coverУдалить пользовательскую обложку
-
+ ErrorОшибка
-
+ Error opening comic with third party reader.Ошибка при открытии комикса с помощью сторонней программы чтения.
-
-
+
+ YACReader library database (*.ydb)База данных библиотеки YACReader (*.ydb)
-
+ The library database backup was created at:
%1Резервная копия базы данных библиотеки создана здесь:
%1
-
+ Unable to create the library database backup:
%1Не удалось создать резервную копию базы данных библиотеки:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Перед восстановлением закройте YACReaderLibraryServer и все другие приложения YACReader, использующие эту библиотеку. Продолжить?
-
+ Restoring library database...Восстановление базы данных библиотеки...
-
+ The current library database is invalid. Restore the selected backup anyway?Текущая база данных библиотеки повреждена. Всё равно восстановить выбранную резервную копию?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Файл блокировки обслуживания библиотеки может быть устаревшим. Удалить его и повторить попытку?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1304,71 +1451,71 @@ Restart YACReaderLibrary before attempting recovery again.
Перезапустите YACReaderLibrary перед следующей попыткой восстановления.
-
+ The library database was restored successfully. Update the library now?База данных библиотеки успешно восстановлена. Обновить библиотеку сейчас?
-
+ Library database damagedБаза данных библиотеки повреждена
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.База данных библиотеки «%1» повреждена, поэтому обычные обновления, обслуживание и резервное копирование недоступны. YACReader может попытаться восстановить базу данных. Некоторые повреждённые данные могут быть утрачены. Существующие резервные копии не будут изменены.
-
+ Attempt repairПопытаться восстановить
-
+ Restore a backup...Восстановить резервную копию...
-
+ Repairing library database...Восстановление базы данных библиотеки...
-
-
-
+
+
+ Library database repairВосстановление базы данных библиотеки
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Сейчас эту библиотеку использует другая операция обслуживания. Повторите попытку после её завершения.
-
+ The library database is already valid.База данных библиотеки уже исправна.
-
+ Library database repairedБаза данных библиотеки восстановлена
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1База данных библиотеки восстановлена путём перестроения индексов. Повреждённый оригинал сохранён здесь:
%1
-
+ Library database rebuiltБаза данных библиотеки перестроена
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1379,7 +1526,7 @@ Update the library now?
Обновить библиотеку сейчас?
-
+
The damaged original was preserved at:
@@ -1390,12 +1537,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failedНе удалось восстановить базу данных библиотеки
-
+ The library database could not be repaired:
%1%2
@@ -1406,42 +1553,42 @@ You can restore a backup from the Library menu or recreate the library.
Можно восстановить резервную копию из меню «Библиотека» или создать библиотеку заново.
-
+ library??
-
+ Are you sure?Вы уверены?
-
+ Rescan library for XML infoПовторное сканирование библиотеки для получения информации XML
-
+ Upgrade failedОбновление не удалось
-
+ There were errors during library upgrade in: При обновлении библиотеки возникли ошибки:
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader не найден. YACReader должен быть установлен в ту же папку, что и YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader не найден. Возможно, возникла проблема с установкой YACReader.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1929,6 +2076,39 @@ Missing files: %3
Добавить выбранные комиксы в список избранного
+
+ ListInfoView
+
+
+ 1 comic
+ 1 комикс
+
+
+
+ %1 comics
+ %1 комиксов
+
+
+
+ Last day
+ Последний день
+
+
+
+ Last %1 days
+ Последние %1 дней
+
+
+
+ 1 sublist
+ 1 вложенный список
+
+
+
+ %1 sublists
+ %1 вложенных списков
+
+LocalComicListModel
@@ -1971,22 +2151,22 @@ Missing files: %3
OptionsDialog
-
+ Restore defautlsВернуть к первоначальным значениям
-
+ BackgroundФоновое изображение
-
+ Blur levelУровень размытия
-
+ Enable background imageВключить фоновое изображение
@@ -1996,17 +2176,17 @@ Missing files: %3
Настройки
-
+ Comic Vine API keyComic Vine API ключ
-
+ Edit Comic Vine API keyРедактировать Comic Vine API ключ
-
+ Opacity levelУровень непрозрачности
@@ -2016,7 +2196,7 @@ Missing files: %3
Основные
-
+ Use selected comic cover as backgroundОбложка комикса фоновое изображение
@@ -2027,7 +2207,7 @@ Missing files: %3
-
+ LibrariesБиблиотеки
@@ -2042,133 +2222,133 @@ Missing files: %3
Появление
-
+ LanguageЯзык
-
+ Application languageЯзык приложения
-
+ System defaultСистемный по умолчанию
-
+ Tray icon settings (experimental)Настройки значков в трее (экспериментально)
-
+ Close to trayРядом с лотком
-
+ Start into the system trayЗапустите в системном трее
-
+ ComicInfo.xml legacy supportПоддержка устаревших версий ComicInfo.xml
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsИмпортируйте метаданные из ComicInfo.xml при добавлении новых комиксов.
-
+ Consider 'recent' items added or updated since X days agoУчитывайте «недавние» элементы, добавленные или обновленные X дней назад.
-
+ Third party readerСторонний читатель
-
+ Write {comic_file_path} where the path should go in the commandНапишите {comic_file_path}, где должен идти путь в команде.
-
+ ClearОчистить
-
+ Update libraries at startupОбновлять библиотеки при запуске
-
+ Try to detect changes automaticallyПопробуйте обнаружить изменения автоматически
-
+ Update libraries periodicallyПериодически обновляйте библиотеки
-
+ Interval:Интервал:
-
+ 30 minutes30 минут
-
+ 1 hour1 час
-
+ 2 hours2 часа
-
+ 4 hours4 часа
-
+ 8 hours8 часов
-
+ 12 hours12 часов
-
+ dailyежедневно
-
+ Update libraries at certain timeОбновлять библиотеки в определенное время
-
+ Time:Время:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2182,30 +2362,45 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
Чтобы остановить автоматическое обновление, нажмите на индикатор загрузки рядом с названием «Библиотеки».
-
+ Modifications detectionОбнаружение модификаций
-
+ Compare the modified date of files when updating a library (not recommended)Сравните дату изменения файлов при обновлении библиотеки (не рекомендуется)
-
+ Display continue reading bannerОтображение баннера продолжения чтения
-
+ Display current comic bannerОтображать текущий комикс-баннер
-
+ Continue readingПродолжить чтение
+
+
+ Mix folders and comics
+ Смешивать папки и комиксы
+
+
+
+ Start comics on a new row
+ Начинать комиксы с новой строки
+
+
+
+ Content
+ Содержимое
+ Restart is needed
@@ -3269,53 +3464,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivityПодключение к серверу
-
+ Scan to connectОтсканируйте для подключения
-
+ Devices on this network can reach your library at the address below.Устройства в этой сети могут получить доступ к вашей библиотеке по указанному ниже адресу.
-
+ IP addressIP-адрес
-
+ PortПорт
-
+ Web interfaceВеб-интерфейс
-
+ Copy linkКопировать ссылку
-
+ Open web UIОткрыть веб-интерфейс
-
+ Enable the serverВключить сервер
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader доступен для iOS и Android. Установите его для <a href='https://ios.yacreader.com'>iOS</a> или <a href='https://android.yacreader.com'>Android</a>.
@@ -3332,7 +3527,7 @@ Use quotes to include spaces in a value.
Сканируйте!
-
+ Set portset portУстановить порт
diff --git a/YACReaderLibrary/yacreaderlibrary_source.ts b/YACReaderLibrary/yacreaderlibrary_source.ts
index d9b1cbdc8..566798f1a 100644
--- a/YACReaderLibrary/yacreaderlibrary_source.ts
+++ b/YACReaderLibrary/yacreaderlibrary_source.ts
@@ -421,6 +421,14 @@
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+
+
+CreateLibraryDialog
@@ -500,6 +508,19 @@
+
+ EmptyInfoView
+
+
+ Nothing selected
+
+
+
+
+ Select a comic or folder to see its information.
+
+
+EmptyLabelWidget
@@ -639,20 +660,100 @@
- FolderContentView
+ FolderInfoView
-
- Continue Reading...
+
+ Unknown
+
+
+
+
+ Items
+
+
+
+
+ Type
+
+
+
+
+ Reading status
+
+
+
+
+ Read
+
+
+
+
+ Unread
+
+
+
+
+ Collection status
+
+
+
+
+ Completed
+
+
+
+
+ In progress
+
+
+
+
+ Added
+
+
+
+
+ UpdatedGridComicsView
-
+ Show info
+
+
+ Manga
+
+
+
+
+ Western manga
+
+
+
+
+ Web comic
+
+
+
+
+ Yonkoma
+
+
+
+
+ Comic
+
+
+
+
+ Unknown
+
+ HelpAboutDialog
@@ -801,35 +902,58 @@
+
+ LibraryInfoView
+
+
+ Library info
+
+
+
+
+ Number of folders
+
+
+
+
+ Number of comics
+
+
+
+
+ Number of read comics
+
+
+LibraryWindow
-
+ Library
-
+ Open folder...
-
-
-
+
+
+ western manga (left to right)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom
-
+ Do you want remove
@@ -839,306 +963,306 @@
-
-
-
+
+
+ manga
-
-
-
+
+
+ comic
-
+ Are you sure?
-
+ Rescan library for XML info
-
+ Set as read
-
-
+
+ Set as unread
-
-
-
+
+
+ web comic
-
+ Add new folder
-
+ Delete folder
-
+ Set as uncompleted
-
+ Set as completed
-
+ Update folder
-
+ Folder
-
+ Comic
-
+ Upgrade failed
-
+ There were errors during library upgrade in:
-
+ Restore recovery failed
-
+ Update needed
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?
-
+ Download new version
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?
-
+ Library not available
-
+ Library '%1' is no longer available. Do you want to remove it?
-
+ Old library
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?
-
-
+
+ Copying comics...
-
-
+
+ Moving comics...
-
+ Folder name:
-
+ No folder selected
-
+ Please, select a folder first
-
+ Error in path
-
+ There was an error accessing the folder's path
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?
-
-
+
+ Unable to delete
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.
-
+ Add new reading lists
-
-
+
+ List name:
-
+ Delete list/label
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?
-
+ Rename list name
-
-
-
-
+
+
+
+ Set type
-
+ Search filters
-
+ Unread
-
+ In progress
-
+ Highly rated
-
+ Recently added
-
+ Search syntax…
-
+ A repair of this library is already running (%1). Wait for it to finish.
-
+ The library is locked by a repair that did not finish.
-
+ The library is locked by a repair started by %1.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Set custom cover
-
+ Delete custom cover
-
+ Save covers
-
+ You are adding too many libraries.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1147,152 +1271,152 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
-
-
+
+ YACReader not found
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.
-
+ YACReader not found. There might be a problem with your YACReader installation.
-
+ Error
-
+ Error opening comic with third party reader.
-
+ Library not found
-
+ The selected folder doesn't contain any library.
-
-
+
+ YACReader library database (*.ydb)
-
+ The library database backup was created at:
%1
-
+ Unable to create the library database backup:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?
-
+ Restoring library database...
-
+ The current library database is invalid. Restore the selected backup anyway?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?
-
+
Restart YACReaderLibrary before attempting recovery again.
-
+ The library database was restored successfully. Update the library now?
-
+ Library database damaged
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.
-
+ Attempt repair
-
+ Restore a backup...
-
+ Repairing library database...
-
-
-
+
+
+ Library database repair
-
+ Another maintenance operation is currently using this library. Try again after it finishes.
-
+ The library database is already valid.
-
+ Library database repaired
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1
-
+ Library database rebuilt
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1300,7 +1424,7 @@ Update the library now?
-
+
The damaged original was preserved at:
@@ -1308,12 +1432,12 @@ The damaged original was preserved at:
-
+ Library database repair failed
-
+ The library database could not be repaired:
%1%2
@@ -1321,102 +1445,102 @@ You can restore a backup from the Library menu or recreate the library.
-
+ library?
-
+ Remove and delete metadata and backups
-
+ Library info
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.
-
+ Assign comics numbers
-
+ Assign numbers starting in:
-
+ Invalid image
-
+ The selected file is not a valid image.
-
+ Error saving cover
-
+ There was an error saving the cover image.
-
+ Error creating the library
-
+ Error updating the library
-
+ Error opening the library
-
+ Delete comics
-
+ All the selected comics will be deleted from your disk. Are you sure?
-
+ Remove comics
-
+ Comics will only be deleted from the current label/list. Are you sure?
-
+ Library name already exists
-
+ There is another library with the name '%1'.
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1902,6 +2026,39 @@ Missing files: %3
+
+ ListInfoView
+
+
+ 1 comic
+
+
+
+
+ %1 comics
+
+
+
+
+ Last day
+
+
+
+
+ Last %1 days
+
+
+
+
+ 1 sublist
+
+
+
+
+ %1 sublists
+
+
+LocalComicListModel
@@ -1944,143 +2101,143 @@ Missing files: %3
OptionsDialog
-
+ Language
-
+ Application language
-
+ System default
-
+ Tray icon settings (experimental)
-
+ Close to tray
-
+ Start into the system tray
-
+ Edit Comic Vine API key
-
+ Comic Vine API key
-
+ ComicInfo.xml legacy support
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comics
-
+ Consider 'recent' items added or updated since X days ago
-
+ Third party reader
-
+ Write {comic_file_path} where the path should go in the command
-
+ Clear
-
+ Update libraries at startup
-
+ Try to detect changes automatically
-
+ Update libraries periodically
-
+ Interval:
-
+ 30 minutes
-
+ 1 hour
-
+ 2 hours
-
+ 4 hours
-
+ 8 hours
-
+ 12 hours
-
+ daily
-
+ Update libraries at certain time
-
+ Time:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2091,60 +2248,75 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ Modifications detection
-
+ Compare the modified date of files when updating a library (not recommended)
-
+ Enable background image
-
+ Opacity level
-
+ Blur level
-
+ Use selected comic cover as background
-
+ Restore defautls
-
+ Background
-
+ Display continue reading banner
-
+ Display current comic banner
-
+ Continue reading
+
+
+ Mix folders and comics
+
+
+
+
+ Start comics on a new row
+
+
+
+
+ Content
+
+ Comic Flow
@@ -2152,7 +2324,7 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ Libraries
@@ -3239,59 +3411,59 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivity
-
+ Scan to connect
-
+ Devices on this network can reach your library at the address below.
-
+ IP address
-
+ Port
-
+ Set portset port
-
+ Web interface
-
+ Copy link
-
+ Open web UI
-
+ Enable the server
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.
diff --git a/YACReaderLibrary/yacreaderlibrary_tr.ts b/YACReaderLibrary/yacreaderlibrary_tr.ts
index 686de1618..77b2eaccb 100644
--- a/YACReaderLibrary/yacreaderlibrary_tr.ts
+++ b/YACReaderLibrary/yacreaderlibrary_tr.ts
@@ -425,6 +425,14 @@
Çizgi romanlar aranıyor...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ Okumaya Devam Et...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
Bu klasör henüz çizgi roman içermiyor
+
+ EmptyInfoView
+
+
+ Nothing selected
+ Hiçbir şey seçilmedi
+
+
+
+ Select a comic or folder to see its information.
+ Bilgilerini görmek için bir çizgi roman veya klasör seçin.
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- Okumaya Devam Et...
+ Okumaya Devam Et...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ Bilinmiyor
+
+
+
+ Items
+ Öğeler
+
+
+
+ Type
+ Tür
+
+
+
+ Reading status
+ Okuma durumu
+
+
+
+ Read
+ Oku
+
+
+
+ Unread
+ Okunmamış
+
+
+
+ Collection status
+ Koleksiyon durumu
+
+
+
+ Completed
+ Tamamlandı
+
+
+
+ In progress
+ Devam eden
+
+
+
+ Added
+ Eklendi
+
+
+
+ Updated
+ GüncellendiGridComicsView
-
+ Show infoBilgi göster
+
+ Library
+ Kütüphane
+
+
+ Folder
+ Klasör
+
+
+ Favorites
+ Favoriler
+
+
+ Recently added
+ Yakın zamanda eklenen
+
+
+
+ Manga
+ Manga
+
+
+
+ Western manga
+ Batı mangası
+
+
+
+ Web comic
+ Web çizgi romanı
+
+
+
+ Yonkoma
+ Yonkoma
+
+
+
+ Comic
+ Çizgi roman
+
+
+
+ Unknown
+ Bilinmiyor
+ HelpAboutDialog
@@ -805,20 +929,43 @@
<p>Geçerli kitaplıkta eksik kapaklar ve tamamlanmamış çizgi roman bilgileri denetleniyor.</p><p>Bu işlem birkaç dakika sürebilir. İşlemi durdurup daha sonra yeniden çalıştırabilirsiniz.</p>
+
+ LibraryInfoView
+
+
+ Library info
+ Kütüphane bilgisi
+
+
+
+ Number of folders
+ Klasör sayısı
+
+
+
+ Number of comics
+ Çizgi roman sayısı
+
+
+
+ Number of read comics
+ Okunan çizgi roman sayısı
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.Seçilen dosya kütüphanede yok.
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?Bu kütüphane YACReaderKütüphabenin bir önceki versiyonun oluşturulmuş, güncellemeye ihtiyacın var. Şimdi güncellemek ister misin ?
-
+ Error opening the libraryHaa kütüphanesini aç
@@ -827,53 +974,53 @@
Metadata'yı kaldır ve sil
-
+ Old libraryEski kütüphane
-
+ LibraryKütüphane
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?Bu kütüphane YACRKütüphanenin üst bir versiyonunda oluşturulmu. Yeni versiyonu indirmek ister misiniz ?
-
+ Library '%1' is no longer available. Do you want to remove it?Kütüphane '%1'ulaşılabilir değil. Kaldırmak ister misin?
-
+ Open folder...Dosyayı aç...
-
+ Do you want remove Kaldırmak ister misin
-
+ Error updating the libraryKütüphane güncelleme sorunu
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?Kütüphane '%1 YACRKütüphanenin eski bir sürümünde oluşturulmuş, Kütüphaneyi yeniden oluşturmak ister misin?
-
+ Set as readOkundu olarak işaretle
-
+ Library not availableKütüphane ulaşılabilir değil
@@ -883,321 +1030,321 @@
YACReader Kütüphane
-
+ Error creating the libraryKütüphane oluşturma sorunu
-
+ Update neededGüncelleme gerekli
-
+ Library name already existsKütüphane ismi zaten alınmış
-
+ There is another library with the name '%1'.Bu başka bir kütüphanenin adı '%1'.
-
+ Download new versionYeni versiyonu indir
-
+ Delete comicsÇizgi romanları sil
-
+ All the selected comics will be deleted from your disk. Are you sure?Seçilen tüm çizgi romanlar diskten silinecek emin misin ?
-
-
+
+ Set as unreadHepsini okunmadı işaretle
-
+ Library not foundKütüphane bulunamadı
-
-
-
+
+
+ mangamanga t?r?
-
-
-
+
+
+ comickomik
-
-
-
+
+
+ western manga (left to right)Batı mangası (soldan sağa)
-
-
-
+
+
+ 4koma (top to botom)4koma (top to botom4koma (yukarıdan aşağıya)
-
+ library? kütüphane?
-
+ Are you sure?Emin misin?
-
+ Rescan library for XML infoXML bilgisi için kitaplığı yeniden tarayın
-
-
-
+
+
+ web comicweb çizgi romanı
-
+ Add new folderYeni klasör ekle
-
+ Delete folderKlasörü sil
-
+ Set as uncompletedTamamlanmamış olarak ayarla
-
+ Set as completedTamamlanmış olarak ayarla
-
+ Update folderKlasörü güncelle
-
+ FolderKlasör
-
+ ComicÇizgi roman
-
+ Upgrade failedYükseltme başarısız oldu
-
+ There were errors during library upgrade in: Kütüphane yükseltmesi sırasında hatalar oluştu:
-
-
+
+ Copying comics...Çizgi romanlar kopyalanıyor...
-
-
+
+ Moving comics...Çizgi romanlar taşınıyor...
-
+ Folder name:Klasör adı:
-
+ No folder selectedHiçbir klasör seçilmedi
-
+ Please, select a folder firstLütfen, önce bir klasör seçiniz
-
+ Error in pathYolda hata
-
+ There was an error accessing the folder's pathKlasörün yoluna erişilirken hata oluştu
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?Seçilen klasör ve tüm içeriği diskinizden silinecek. Emin misin?
-
-
+
+ Unable to deleteSilinemedi
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.Seçili klasörleri silmeye çalışırken bir sorun oluştu. Lütfen yazma izinlerini kontrol edin ve herhangi bir uygulamanın bu klasörleri veya içerdiği dosyalardan herhangi birini kullandığından emin olun.
-
+ Add new reading listsYeni okuma listeleri ekle
-
-
+
+ List name:Liste adı:
-
+ Delete list/labelListeyi/Etiketi sil
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?Seçilen öğe silinecek, çizgi romanlarınız veya klasörleriniz diskinizden SİLİNMEYECEKTİR. Emin misin?
-
+ Rename list nameListeyi yeniden adlandır
-
-
-
-
+
+
+
+ Set typeTürü ayarla
-
+ Search filtersArama filtreleri
-
+ UnreadOkunmamış
-
+ In progressDevam eden
-
+ Highly ratedYüksek puanlı
-
+ Recently addedYakın zamanda eklenen
-
+ Search syntax…Arama söz dizimi…
-
+ A repair of this library is already running (%1). Wait for it to finish.Bu kütüphanenin onarımı zaten çalışıyor (%1). Bitmesini bekleyin.
-
+ The library is locked by a repair that did not finish.Kütüphane, tamamlanmamış bir onarım tarafından kilitlendi.
-
+ The library is locked by a repair started by %1.Kütüphane, %1 tarafından başlatılan bir onarım tarafından kilitlendi.
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?Başka bir onarımın çalışmadığından eminseniz kilit kaldırılabilir. Kilit kaldırılıp devam edilsin mi?
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Restore recovery failedGeri yükleme kurtarması başarısız oldu
-
+ Set custom coverÖzel kapak ayarla
-
+ Delete custom coverÖzel kapağı sil
-
+ Save coversKapakları kaydet
-
+ You are adding too many libraries.Çok fazla kütüphane ekliyorsunuz.
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1210,74 +1357,74 @@ Muhtemelen üst düzey çizgi roman klasörünüzde yalnızca bir kütüphaneye
YACReaderLibrary daha fazla kütüphane oluşturmanıza engel olmaz ancak kütüphane sayısını düşük tutmalısınız.
-
-
+
+ YACReader not foundYACReader bulunamadı
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.YACReader bulunamadı. YACReader, YACReaderLibrary ile aynı klasöre kurulmalıdır.
-
+ YACReader not found. There might be a problem with your YACReader installation.YACReader bulunamadı. YACReader kurulumunuzda bir sorun olabilir.
-
+ ErrorHata
-
+ Error opening comic with third party reader.Çizgi roman üçüncü taraf okuyucuyla açılırken hata oluştu.
-
-
+
+ YACReader library database (*.ydb)YACReader kitaplık veritabanı (*.ydb)
-
+ The library database backup was created at:
%1Kitaplık veritabanı yedeği şu konumda oluşturuldu:
%1
-
+ Unable to create the library database backup:
%1Kitaplık veritabanı yedeği oluşturulamadı:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?Geri yüklemeden önce YACReaderLibraryServer'ı ve bu kitaplığı kullanan diğer tüm YACReader uygulamalarını kapatın. Devam edilsin mi?
-
+ Restoring library database...Kitaplık veritabanı geri yükleniyor...
-
+ The current library database is invalid. Restore the selected backup anyway?Geçerli kitaplık veritabanı geçersiz. Seçilen yedek yine de geri yüklensin mi?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?Kitaplık bakım kilidi eski kalmış olabilir. Kaldırıp yeniden denensin mi?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1286,71 +1433,71 @@ Restart YACReaderLibrary before attempting recovery again.
Kurtarmayı yeniden denemeden önce YACReaderLibrary'yi yeniden başlatın.
-
+ The library database was restored successfully. Update the library now?Kitaplık veritabanı başarıyla geri yüklendi. Kitaplık şimdi güncellensin mi?
-
+ Library database damagedKitaplık veritabanı hasarlı
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.'%1' kitaplığının veritabanı hasarlı olduğundan normal güncellemeler, bakım ve yedeklemeler kullanılamıyor. YACReader veritabanını onarmayı deneyebilir. Bazı hasarlı veriler kurtarılamayabilir. Mevcut yedekler değiştirilmeyecektir.
-
+ Attempt repairOnarmayı dene
-
+ Restore a backup...Bir yedeği geri yükle...
-
+ Repairing library database...Kitaplık veritabanı onarılıyor...
-
-
-
+
+
+ Library database repairKitaplık veritabanını onar
-
+ Another maintenance operation is currently using this library. Try again after it finishes.Başka bir bakım işlemi şu anda bu kitaplığı kullanıyor. İşlem bittikten sonra yeniden deneyin.
-
+ The library database is already valid.Kitaplık veritabanı zaten geçerli.
-
+ Library database repairedKitaplık veritabanı onarıldı
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1Kitaplık veritabanı dizinleri yeniden oluşturularak onarıldı. Hasarlı özgün dosya şu konumda korundu:
%1
-
+ Library database rebuiltKitaplık veritabanı yeniden oluşturuldu
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1361,7 +1508,7 @@ Update the library now?
Kitaplık şimdi güncellensin mi?
-
+
The damaged original was preserved at:
@@ -1372,12 +1519,12 @@ Hasarlı özgün dosya şu konumda korundu:
%1
-
+ Library database repair failedKitaplık veritabanı onarılamadı
-
+ The library database could not be repaired:
%1%2
@@ -1388,62 +1535,62 @@ You can restore a backup from the Library menu or recreate the library.
Kitaplık menüsünden bir yedeği geri yükleyebilir veya kitaplığı yeniden oluşturabilirsiniz.
-
+ Remove and delete metadata and backupsMeta verileri ve yedekleri kaldır ve sil
-
+ Library infoKütüphane bilgisi
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.Seçilen çizgi romanlar silinmeye çalışılırken bir sorun oluştu. Lütfen seçilen dosyalarda veya klasörleri içeren yazma izinlerini kontrol edin.
-
+ Assign comics numbersÇizgi roman numaraları ata
-
+ Assign numbers starting in:Şunlardan başlayarak numaralar ata:
-
+ Invalid imageGeçersiz resim
-
+ The selected file is not a valid image.Seçilen dosya geçerli bir resim değil.
-
+ Error saving coverKapak kaydedilirken hata oluştu
-
+ There was an error saving the cover image.Kapak resmi kaydedilirken bir hata oluştu.
-
+ Remove comicsÇizgi romanları kaldır
-
+ Comics will only be deleted from the current label/list. Are you sure?Çizgi romanlar yalnızca mevcut etiketten/listeden silinecektir. Emin misin?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1931,6 +2078,39 @@ Eksik dosyalar: %3
Seçilen çizgi romanları favoriler listesine ekle
+
+ ListInfoView
+
+
+ 1 comic
+ 1 çizgi roman
+
+
+
+ %1 comics
+ %1 çizgi roman
+
+
+
+ Last day
+ Son gün
+
+
+
+ Last %1 days
+ Son %1 gün
+
+
+
+ 1 sublist
+ 1 alt liste
+
+
+
+ %1 sublists
+ %1 alt liste
+
+LocalComicListModel
@@ -1983,143 +2163,143 @@ Eksik dosyalar: %3
Ayarlar
-
+ LanguageDil
-
+ Application languageUygulama dili
-
+ System defaultSistem varsayılanı
-
+ Tray icon settings (experimental)Tepsi simgesi ayarları (deneysel)
-
+ Close to trayTepsiyi kapat
-
+ Start into the system traySistem tepsisinde başlat
-
+ Edit Comic Vine API keyComic Vine API anahtarını düzenle
-
+ Comic Vine API keyComic Vine API anahtarı
-
+ ComicInfo.xml legacy supportComicInfo.xml eski desteği
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comicsYeni çizgi roman eklerken meta verileri ComicInfo.xml'den içe aktarın
-
+ Consider 'recent' items added or updated since X days agoX gün öncesinden bu yana eklenen veya güncellenen 'en son' öğeleri göz önünde bulundurun
-
+ Third party readerÜçüncü taraf okuyucu
-
+ Write {comic_file_path} where the path should go in the commandKomutta yolun gitmesi gereken yere {comic_file_path} yazın
-
+ ClearTemizle
-
+ Update libraries at startupBaşlangıçta kitaplıkları güncelleyin
-
+ Try to detect changes automaticallyDeğişiklikleri otomatik olarak algılamayı deneyin
-
+ Update libraries periodicallyKitaplıkları düzenli aralıklarla güncelleyin
-
+ Interval:Aralık:
-
+ 30 minutes30 dakika
-
+ 1 hour1 saat
-
+ 2 hours2 saat
-
+ 4 hours4 saat
-
+ 8 hours8 saat
-
+ 12 hours12 saat
-
+ dailygünlük
-
+ Update libraries at certain timeKitaplıkları belirli bir zamanda güncelle
-
+ Time:Zaman:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2133,60 +2313,75 @@ Otomatik güncellemeler sırasında uygulama, güncelleme bitene kadar bazı eyl
Otomatik güncellemeyi durdurmak için Kitaplıklar başlığının yanındaki yükleme göstergesine dokunun.
-
+ Modifications detectionDeğişiklik tespiti
-
+ Compare the modified date of files when updating a library (not recommended)Kitaplığı güncellerken dosyaların değiştirilme tarihini karşılaştırın (önerilmez)
-
+ Enable background imageArka plan resmini etkinleştir
-
+ Opacity levelMatlık düzeyi
-
+ Blur levelBulanıklık düzeyi
-
+ Use selected comic cover as backgroundSeçilen çizgi roman kapanığı arka plan olarak kullan
-
+ Restore defautlsVarsayılanları geri yükle
-
+ BackgroundArka plan
-
+ Display continue reading bannerOkuma devam et bannerını göster
-
+ Display current comic bannerMevcut çizgi roman banner'ını görüntüle
-
+ Continue readingOkumaya devam et
+
+
+ Mix folders and comics
+ Klasörleri ve çizgi romanları karıştır
+
+
+
+ Start comics on a new row
+ Çizgi romanları yeni bir satırda başlat
+
+
+
+ Content
+ İçerik
+ Comic Flow
@@ -2194,7 +2389,7 @@ Otomatik güncellemeyi durdurmak için Kitaplıklar başlığının yanındaki y
-
+ LibrariesKütüphaneler
@@ -3271,53 +3466,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivitySunucu bağlantısı
-
+ Scan to connectBağlanmak için tarayın
-
+ Devices on this network can reach your library at the address below.Bu ağdaki cihazlar aşağıdaki adresten kitaplığınıza erişebilir.
-
+ IP addressIP adresi
-
+ PortLiman
-
+ Web interfaceWeb arayüzü
-
+ Copy linkBağlantıyı kopyala
-
+ Open web UIWeb arayüzünü aç
-
+ Enable the serverSunucuyu etkinleştir
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader, iOS ve Android için kullanılabilir. <a href='https://ios.yacreader.com'>iOS</a> veya <a href='https://android.yacreader.com'>Android</a> sürümünü keşfedin.
@@ -3326,7 +3521,7 @@ Use quotes to include spaces in a value.
erişilebilir server
-
+ Set portset portPortu ayarla
diff --git a/YACReaderLibrary/yacreaderlibrary_zh_CN.ts b/YACReaderLibrary/yacreaderlibrary_zh_CN.ts
index b2ae00441..3b44db8f0 100644
--- a/YACReaderLibrary/yacreaderlibrary_zh_CN.ts
+++ b/YACReaderLibrary/yacreaderlibrary_zh_CN.ts
@@ -425,6 +425,14 @@
正在接收卷信息...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ 继续阅读...
+
+CreateLibraryDialog
@@ -504,6 +512,19 @@
该文件夹还没有漫画
+
+ EmptyInfoView
+
+
+ Nothing selected
+ 未选择任何内容
+
+
+
+ Select a comic or folder to see its information.
+ 选择漫画或文件夹以查看其信息。
+
+EmptyLabelWidget
@@ -645,18 +666,121 @@
FolderContentView
- Continue Reading...
- 继续阅读...
+ 继续阅读...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ 未知
+
+
+
+ Items
+ 项目
+
+
+
+ Type
+ 类型
+
+
+
+ Reading status
+ 阅读状态
+
+
+
+ Read
+ 阅读
+
+
+
+ Unread
+ 未读
+
+
+
+ Collection status
+ 收藏状态
+
+
+
+ Completed
+ 已完成
+
+
+
+ In progress
+ 阅读中
+
+
+
+ Added
+ 已添加
+
+
+
+ Updated
+ 已更新GridComicsView
-
+ Show info显示信息
+
+ Library
+ 库
+
+
+ Folder
+ 文件夹
+
+
+ Favorites
+ 收藏夹
+
+
+ Recently added
+ 最近添加
+
+
+
+ Manga
+ 日式漫画
+
+
+
+ Western manga
+ 西式漫画
+
+
+
+ Web comic
+ 网络漫画
+
+
+
+ Yonkoma
+ 四格漫画
+
+
+
+ Comic
+ 漫画
+
+
+
+ Unknown
+ 未知
+ HelpAboutDialog
@@ -805,75 +929,98 @@
<p>正在检查当前漫画库中缺失的封面和不完整的漫画信息。</p><p>这可能需要几分钟。您可以停止该过程,稍后再重新运行。</p>
+
+ LibraryInfoView
+
+
+ Library info
+ 图书馆信息
+
+
+
+ Number of folders
+ 文件夹数量
+
+
+
+ Number of comics
+ 漫画数量
+
+
+
+ Number of read comics
+ 已读漫画数量
+
+LibraryWindow
-
+ The selected folder doesn't contain any library.所选文件夹不包含任何库。
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?此库是使用旧版本的YACReaderLibrary创建的. 它需要更新. 现在更新?
-
+ Upgrade failed更新失败
-
+ Comic漫画
-
-
-
+
+
+ comic漫画
-
-
-
+
+
+ manga日本漫画
-
+ Folder name:文件夹名称:
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?所选文件夹及其所有内容将从磁盘中删除。 你确定吗?
-
+ Rescan library for XML info重新扫描库的 XML 信息
-
+ Error opening the library打开库时出错
-
-
+
+ YACReader not foundYACReader 未找到
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.尝试删除所选文件夹时出现问题。 请检查写入权限,并确保没有其他应用程序在使用这些文件夹或文件。
-
+ Rename list name重命名列表
@@ -882,154 +1029,154 @@
移除并删除元数据
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.未找到YACReader. YACReader应安装在与YACReaderLibrary相同的文件夹中.
-
+ Old library旧的库
-
+ Set as completed设为已完成
-
+ There was an error accessing the folder's path访问文件夹的路径时出错
-
+ Library库
-
+ Comics will only be deleted from the current label/list. Are you sure?漫画只会从当前标签/列表中删除。 你确定吗?
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?此库是使用较新版本的YACReaderLibrary创建的。 立即下载新版本?
-
-
+
+ Moving comics...移动漫画中...
-
-
+
+ Copying comics...复制漫画中...
-
+ Library '%1' is no longer available. Do you want to remove it?库 '%1' 不再可用。 你想删除它吗?
-
-
-
+
+
+ web comic网络漫画
-
+ Open folder...打开文件夹...
-
+ Set custom cover设置自定义封面
-
+ Delete custom cover删除自定义封面
-
+ Error错误
-
+ Error opening comic with third party reader.使用第三方阅读器打开漫画时出错。
-
+ Do you want remove 你想要删除
-
+ Set as uncompleted设为未完成
-
+ Error in path路径错误
-
+ Error updating the library更新库时出错
-
+ Folder文件夹
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?所选项目将被删除,您的漫画或文件夹将不会从您的磁盘中删除。 你确定吗?
-
-
-
+
+
+ western manga (left to right)欧美漫画(从左到右)
-
-
+
+ List name:列表名称:
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?库 '%1' 是通过旧版本的YACReaderLibrary创建的。 必须再次创建。 你想现在创建吗?
-
+ Save covers保存封面
-
+ YACReader not found. There might be a problem with your YACReader installation.未找到YACReader. YACReader的安装可能有问题.
-
+ Add new reading lists添加新的阅读列表
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1042,32 +1189,32 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
YACReaderLibrary不会阻止您创建更多的库,但是您应该保持较低的库数量来提升性能。
-
+ Set as read设为已读
-
+ Assign comics numbers分配漫画编号
-
+ There were errors during library upgrade in: 漫画库更新时出现错误:
-
+ Please, select a folder first请先选择一个文件夹
-
+ Library not available库不可用
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.尝试删除所选漫画时出现问题。 请检查所选文件或包含文件夹中的写入权限。
@@ -1077,166 +1224,166 @@ YACReaderLibrary不会阻止您创建更多的库,但是您应该保持较低
YACReader 库
-
+ Error creating the library创建库时出错
-
+ You are adding too many libraries.您添加的库太多了。
-
+ Update folder更新文件夹
-
+ Update needed需要更新
-
+ Library name already exists库名已存在
-
+ There is another library with the name '%1'.已存在另一个名为'%1'的库。
-
+ Delete folder删除文件夹
-
+ Assign numbers starting in:从以下位置开始分配编号:
-
+ Download new version下载新版本
-
+ Search filters搜索筛选条件
-
+ Unread未读
-
+ In progress阅读中
-
+ Highly rated高评分
-
+ Recently added最近添加
-
+ Search syntax…搜索语法…
-
-
-
-
+
+
+
+ Set type设置类型
-
+ A repair of this library is already running (%1). Wait for it to finish.此库的修复已在运行中(%1)。请等待其完成。
-
+ The library is locked by a repair that did not finish.库已被一个未完成的修复锁定。
-
+ The library is locked by a repair started by %1.库已被 %1 启动的修复锁定。
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?如果您确定没有其他修复正在运行,可以移除该锁定。移除锁定并继续?
-
+ Package operation failed打包操作失败
-
+ The covers package operation could not be completed.封面包操作无法完成。
-
+ Restore recovery failed恢复操作修复失败
-
-
+
+ YACReader library database (*.ydb)YACReader 资料库数据库 (*.ydb)
-
+ The library database backup was created at:
%1资料库数据库备份已创建于:
%1
-
+ Unable to create the library database backup:
%1无法创建资料库数据库备份:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?恢复前请关闭 YACReaderLibraryServer 以及正在使用此资料库的所有其他 YACReader 应用程序。是否继续?
-
+ Restoring library database...正在恢复资料库数据库...
-
+ The current library database is invalid. Restore the selected backup anyway?当前资料库数据库无效。仍要恢复所选备份吗?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?资料库维护锁可能已失效。是否移除并重试?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1245,71 +1392,71 @@ Restart YACReaderLibrary before attempting recovery again.
再次尝试恢复前,请重新启动 YACReaderLibrary。
-
+ The library database was restored successfully. Update the library now?资料库数据库已成功恢复。是否立即更新资料库?
-
+ Library database damaged资料库数据库已损坏
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.资料库“%1”的数据库已损坏,因此无法执行常规更新、维护和备份。YACReader 可以尝试修复数据库。部分损坏的数据可能无法恢复。现有备份不会被更改。
-
+ Attempt repair尝试修复
-
+ Restore a backup...恢复备份...
-
+ Repairing library database...正在修复资料库数据库...
-
-
-
+
+
+ Library database repair修复资料库数据库
-
+ Another maintenance operation is currently using this library. Try again after it finishes.另一个维护操作正在使用此资料库。请在其完成后重试。
-
+ The library database is already valid.资料库数据库已经有效。
-
+ Library database repaired资料库数据库已修复
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1已通过重建索引修复资料库数据库。损坏的原始文件已保存在:
%1
-
+ Library database rebuilt资料库数据库已重建
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1320,7 +1467,7 @@ Update the library now?
是否立即更新资料库?
-
+
The damaged original was preserved at:
@@ -1331,12 +1478,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failed资料库数据库修复失败
-
+ The library database could not be repaired:
%1%2
@@ -1347,101 +1494,101 @@ You can restore a backup from the Library menu or recreate the library.
您可以从“资料库”菜单恢复备份,或重新创建资料库。
-
+ Remove and delete metadata and backups移除并删除元数据和备份
-
+ Library info图书馆信息
-
+ Invalid image图片无效
-
+ The selected file is not a valid image.所选文件不是有效图像。
-
+ Error saving cover保存封面时出错
-
+ There was an error saving the cover image.保存封面图像时出错。
-
+ Delete comics删除漫画
-
+ Add new folder添加新的文件夹
-
+ Delete list/label删除 列表/标签
-
+ No folder selected没有选中的文件夹
-
+ All the selected comics will be deleted from your disk. Are you sure?所有选定的漫画都将从您的磁盘中删除。你确定吗?
-
+ Remove comics移除漫画
-
-
+
+ Set as unread设为未读
-
+ Library not found未找到库
-
-
+
+ Unable to delete无法删除
-
-
-
+
+
+ 4koma (top to botom)四格漫画(从上到下)
-
+ library? 库?
-
+ Are you sure?你确定吗?
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1929,6 +2076,39 @@ Missing files: %3
将所选漫画添加到收藏夹列表
+
+ ListInfoView
+
+
+ 1 comic
+ 1 本漫画
+
+
+
+ %1 comics
+ %1 本漫画
+
+
+
+ Last day
+ 最近 1 天
+
+
+
+ Last %1 days
+ 最近 %1 天
+
+
+
+ 1 sublist
+ 1 个子列表
+
+
+
+ %1 sublists
+ %1 个子列表
+
+LocalComicListModel
@@ -1971,62 +2151,62 @@ Missing files: %3
OptionsDialog
-
+ Modifications detection修改检测
-
+ Time:时间:
-
+ daily每天
-
+ Restore defautls恢复默认值
-
+ Close to tray关闭至托盘
-
+ Background背景
-
+ Update libraries at certain time定时更新库
-
+ 1 hour1小时
-
+ Start into the system tray启动至系统托盘
-
+ Display current comic banner显示当前漫画横幅
-
+ Continue reading继续阅读
-
+ Update libraries at startup启动时更新库
@@ -2036,72 +2216,87 @@ Missing files: %3
外观
-
+ Language语言
-
+ Application language应用程序语言
-
+ System default系统默认
-
+ Third party reader第三方阅读器
-
+ Write {comic_file_path} where the path should go in the command在命令中应将路径写入 {comic_file_path}
-
+ Clear清空
-
+ 30 minutes30分钟
-
+ 2 hours2小时
-
+ 12 hours12小时
-
+ Blur level模糊
-
+
+ Mix folders and comics
+ 混合显示文件夹和漫画
+
+
+
+ Start comics on a new row
+ 从新行开始显示漫画
+
+
+
+ Content
+ 内容
+
+
+ Compare the modified date of files when updating a library (not recommended)更新库时比较文件的修改日期(不推荐)
-
+ Import metadata from ComicInfo.xml when adding new comics添加新漫画时从 ComicInfo.xml 导入元数据
-
+ Enable background image启用背景图片
-
+ 4 hours4小时
@@ -2111,48 +2306,48 @@ Missing files: %3
选项
-
+ Comic Vine API keyComic Vine API 密匙
-
+ Edit Comic Vine API key编辑Comic Vine API 密匙
-
+ Tray icon settings (experimental)托盘图标设置 (实验特性)
-
+ Libraries库
-
+ 8 hours8小时
-
+ Try to detect changes automatically尝试自动检测变化
-
+ Interval:间隔:
-
+ ComicInfo.xml legacy supportComicInfo.xml 旧版支持
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2163,12 +2358,12 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
要停止自动更新,请点击库标题旁边的加载指示器。
-
+ Opacity level透明度
-
+ Display continue reading banner显示继续阅读横幅
@@ -2178,17 +2373,17 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
常规
-
+ Consider 'recent' items added or updated since X days ago参考自 X 天前添加或更新的“最近”项目
-
+ Update libraries periodically定期更新库
-
+ Use selected comic cover as background使用选定的漫画封面做背景
@@ -3265,53 +3460,53 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
-
+
+ Server connectivity服务器连接
-
+ Scan to connect扫描以连接
-
+ Devices on this network can reach your library at the address below.此网络中的设备可通过以下地址访问您的资料库。
-
+ IP addressIP 地址
-
+ Port端口
-
+ Web interface网页界面
-
+ Copy link复制链接
-
+ Open web UI打开网页界面
-
+ Enable the server启用服务器
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader 支持 iOS 和 Android。获取 <a href='https://ios.yacreader.com'>iOS</a> 或 <a href='https://android.yacreader.com'>Android</a> 版本。
@@ -3328,7 +3523,7 @@ Use quotes to include spaces in a value.
扫一扫!
-
+ Set portset port设置端口
diff --git a/YACReaderLibrary/yacreaderlibrary_zh_HK.ts b/YACReaderLibrary/yacreaderlibrary_zh_HK.ts
index f01829b88..5eb56fc9d 100644
--- a/YACReaderLibrary/yacreaderlibrary_zh_HK.ts
+++ b/YACReaderLibrary/yacreaderlibrary_zh_HK.ts
@@ -426,6 +426,14 @@
搜索漫畫中...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ 繼續閱讀...
+
+CreateLibraryDialog
@@ -505,6 +513,19 @@
該資料夾還沒有漫畫
+
+ EmptyInfoView
+
+
+ Nothing selected
+ 未選取任何內容
+
+
+
+ Select a comic or folder to see its information.
+ 選取漫畫或資料夾以查看其資訊。
+
+EmptyLabelWidget
@@ -647,18 +668,121 @@
FolderContentView
- Continue Reading...
- 繼續閱讀...
+ 繼續閱讀...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ 未知
+
+
+
+ Items
+ 項目
+
+
+
+ Type
+ 類型
+
+
+
+ Reading status
+ 閱讀狀態
+
+
+
+ Read
+ 閱讀
+
+
+
+ Unread
+ 未讀
+
+
+
+ Collection status
+ 收藏狀態
+
+
+
+ Completed
+ 已完成
+
+
+
+ In progress
+ 閱讀中
+
+
+
+ Added
+ 已加入
+
+
+
+ Updated
+ 已更新GridComicsView
-
+ Show info顯示資訊
+
+ Library
+ 庫
+
+
+ Folder
+ 檔夾
+
+
+ Favorites
+ 收藏夾
+
+
+ Recently added
+ 最近新增
+
+
+
+ Manga
+ 日式漫畫
+
+
+
+ Western manga
+ 西式漫畫
+
+
+
+ Web comic
+ 網絡漫畫
+
+
+
+ Yonkoma
+ 四格漫畫
+
+
+
+ Comic
+ 漫畫
+
+
+
+ Unknown
+ 未知
+ HelpAboutDialog
@@ -807,6 +931,29 @@
<p>正在檢查目前漫畫庫中遺失的封面及不完整的漫畫資訊。</p><p>這可能需要幾分鐘。你可以停止此程序,稍後再重新執行。</p>
+
+ LibraryInfoView
+
+
+ Library info
+ 圖書館資訊
+
+
+
+ Number of folders
+ 資料夾數量
+
+
+
+ Number of comics
+ 漫畫數量
+
+
+
+ Number of read comics
+ 已讀漫畫數量
+
+LibraryWindow
@@ -815,275 +962,275 @@
YACReader 庫
-
+ Library庫
-
+ Set as read設為已讀
-
-
+
+ Set as unread設為未讀
-
-
-
+
+
+ manga漫畫
-
-
-
+
+
+ comic漫畫
-
-
-
+
+
+ web comic網路漫畫
-
-
-
+
+
+ western manga (left to right)西方漫畫(從左到右)
-
+ Library not availableLibrary '庫不可用
-
+ Rescan library for XML info重新掃描庫的 XML 資訊
-
+ Delete folder刪除檔夾
-
+ Open folder...打開檔夾...
-
+ Set as uncompleted設為未完成
-
+ Set as completed設為已完成
-
+ Update folder更新檔夾
-
+ Folder檔夾
-
+ Comic漫畫
-
+ A repair of this library is already running (%1). Wait for it to finish.此庫的修復已在執行中(%1)。請等待其完成。
-
+ The library is locked by a repair that did not finish.此庫已被一個未完成的修復鎖定。
-
+ The library is locked by a repair started by %1.此庫已被 %1 啟動的修復鎖定。
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?如果您確定沒有其他修復正在執行,可以移除該鎖定。移除鎖定並繼續?
-
+ Upgrade failed更新失敗
-
+ There were errors during library upgrade in: 漫畫庫更新時出現錯誤:
-
+ Restore recovery failed還原復原失敗
-
+ Update needed需要更新
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?此庫是使用舊版本的YACReaderLibrary創建的. 它需要更新. 現在更新?
-
+ Download new version下載新版本
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?此庫是使用較新版本的YACReaderLibrary創建的。 立即下載新版本?
-
+ Library '%1' is no longer available. Do you want to remove it?庫 '%1' 不再可用。 你想刪除它嗎?
-
+ Old library舊的庫
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?庫 '%1' 是通過舊版本的YACReaderLibrary創建的。 必須再次創建。 你想現在創建嗎?
-
-
+
+ Copying comics...複製漫畫中...
-
-
+
+ Moving comics...移動漫畫中...
-
+ Folder name:檔夾名稱:
-
+ No folder selected沒有選中的檔夾
-
+ Please, select a folder first請先選擇一個檔夾
-
+ Error in path路徑錯誤
-
+ There was an error accessing the folder's path訪問檔夾的路徑時出錯
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?所選檔夾及其所有內容將從磁片中刪除。 你確定嗎?
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.嘗試刪除所選檔夾時出現問題。 請檢查寫入許可權,並確保沒有其他應用程式在使用這些檔夾或檔。
-
+ Add new reading lists添加新的閱讀列表
-
-
+
+ List name:列表名稱:
-
+ Delete list/label刪除 列表/標籤
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?所選項目將被刪除,您的漫畫或檔夾將不會從您的磁片中刪除。 你確定嗎?
-
+ Rename list name重命名列表
-
-
-
+
+
+ 4koma (top to botom)4koma(由上至下)
-
-
-
-
+
+
+
+ Set type套裝類型
-
+ Set custom cover設定自訂封面
-
+ Delete custom cover刪除自訂封面
-
+ Save covers保存封面
-
+ You are adding too many libraries.您添加的庫太多了。
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1096,43 +1243,43 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
YACReaderLibrary不會阻止您創建更多的庫,但是您應該保持較低的庫數量來提升性能。
-
-
+
+ YACReader not foundYACReader 未找到
-
+ Error錯誤
-
+ Error opening comic with third party reader.使用第三方閱讀器開啟漫畫時出錯。
-
+ Library not found未找到庫
-
+ The selected folder doesn't contain any library.所選檔夾不包含任何庫。
-
+ Are you sure?你確定嗎?
-
+ Do you want remove 你想要刪除
-
+ library? 庫?
@@ -1141,124 +1288,124 @@ YACReaderLibrary不會阻止您創建更多的庫,但是您應該保持較低
移除並刪除元數據
-
+ Library info圖書館資訊
-
+ Assign comics numbers分配漫畫編號
-
+ Assign numbers starting in:從以下位置開始分配編號:
-
-
+
+ Unable to delete無法刪除
-
+ Search filters搜尋篩選器
-
+ Unread未讀
-
+ In progress閱讀中
-
+ Highly rated高評分
-
+ Recently added最近新增
-
+ Search syntax…搜尋語法…
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Add new folder添加新的檔夾
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.未找到YACReader. YACReader應安裝在與YACReaderLibrary相同的檔夾中.
-
+ YACReader not found. There might be a problem with your YACReader installation.未找到YACReader. YACReader的安裝可能有問題.
-
-
+
+ YACReader library database (*.ydb)YACReader 漫畫庫資料庫 (*.ydb)
-
+ The library database backup was created at:
%1漫畫庫資料庫備份已建立於:
%1
-
+ Unable to create the library database backup:
%1無法建立漫畫庫資料庫備份:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?還原前請關閉 YACReaderLibraryServer 及正在使用此漫畫庫的所有其他 YACReader 應用程式。是否繼續?
-
+ Restoring library database...正在還原漫畫庫資料庫...
-
+ The current library database is invalid. Restore the selected backup anyway?目前的漫畫庫資料庫無效。仍要還原所選備份嗎?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?漫畫庫維護鎖可能已失效。是否移除並重試?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1267,71 +1414,71 @@ Restart YACReaderLibrary before attempting recovery again.
再次嘗試復原前,請重新啟動 YACReaderLibrary。
-
+ The library database was restored successfully. Update the library now?漫畫庫資料庫已成功還原。是否立即更新漫畫庫?
-
+ Library database damaged漫畫庫資料庫已損壞
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.漫畫庫「%1」的資料庫已損壞,因此無法執行一般更新、維護及備份。YACReader 可以嘗試修復資料庫。部分損壞的資料可能無法復原。現有備份不會被更改。
-
+ Attempt repair嘗試修復
-
+ Restore a backup...還原備份...
-
+ Repairing library database...正在修復漫畫庫資料庫...
-
-
-
+
+
+ Library database repair修復漫畫庫資料庫
-
+ Another maintenance operation is currently using this library. Try again after it finishes.另一個維護操作正在使用此漫畫庫。請在操作完成後重試。
-
+ The library database is already valid.漫畫庫資料庫已經有效。
-
+ Library database repaired漫畫庫資料庫已修復
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1已透過重建索引修復漫畫庫資料庫。損壞的原始檔案已保留於:
%1
-
+ Library database rebuilt漫畫庫資料庫已重建
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1342,7 +1489,7 @@ Update the library now?
是否立即更新漫畫庫?
-
+
The damaged original was preserved at:
@@ -1353,12 +1500,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failed漫畫庫資料庫修復失敗
-
+ The library database could not be repaired:
%1%2
@@ -1369,82 +1516,82 @@ You can restore a backup from the Library menu or recreate the library.
您可以從「漫畫庫」選單還原備份,或重新建立漫畫庫。
-
+ Remove and delete metadata and backups移除並刪除中繼資料及備份
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.嘗試刪除所選漫畫時出現問題。 請檢查所選檔或包含檔夾中的寫入許可權。
-
+ Invalid image圖片無效
-
+ The selected file is not a valid image.所選檔案不是有效影像。
-
+ Error saving cover儲存封面時發生錯誤
-
+ There was an error saving the cover image.儲存封面圖片時發生錯誤。
-
+ Error creating the library創建庫時出錯
-
+ Error updating the library更新庫時出錯
-
+ Error opening the library打開庫時出錯
-
+ Delete comics刪除漫畫
-
+ All the selected comics will be deleted from your disk. Are you sure?所有選定的漫畫都將從您的磁片中刪除。你確定嗎?
-
+ Remove comics移除漫畫
-
+ Comics will only be deleted from the current label/list. Are you sure?漫畫只會從當前標籤/列表中刪除。 你確定嗎?
-
+ Library name already exists庫名已存在
-
+ There is another library with the name '%1'.已存在另一個名為'%1'的庫。
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1932,6 +2079,39 @@ Missing files: %3
將所選漫畫添加到收藏夾列表
+
+ ListInfoView
+
+
+ 1 comic
+ 1 本漫畫
+
+
+
+ %1 comics
+ %1 本漫畫
+
+
+
+ Last day
+ 最近 1 天
+
+
+
+ Last %1 days
+ 最近 %1 天
+
+
+
+ 1 sublist
+ 1 個子清單
+
+
+
+ %1 sublists
+ %1 個子清單
+
+LocalComicListModel
@@ -1974,143 +2154,143 @@ Missing files: %3
OptionsDialog
-
+ Language語言
-
+ Application language應用程式語言
-
+ System default系統預設
-
+ Tray icon settings (experimental)託盤圖示設置 (實驗特性)
-
+ Close to tray關閉至託盤
-
+ Start into the system tray啟動至系統託盤
-
+ Edit Comic Vine API key編輯Comic Vine API 密匙
-
+ Comic Vine API keyComic Vine API 密匙
-
+ ComicInfo.xml legacy supportComicInfo.xml 遺留支持
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comics新增漫畫時從 ComicInfo.xml 匯入元數據
-
+ Consider 'recent' items added or updated since X days ago考慮自 X 天前新增或更新的「最近」項目
-
+ Third party reader第三方閱讀器
-
+ Write {comic_file_path} where the path should go in the command在命令中應將路徑寫入 {comic_file_path}
-
+ Clear清空
-
+ Update libraries at startup啟動時更新庫
-
+ Try to detect changes automatically嘗試自動偵測變化
-
+ Update libraries periodically定期更新庫
-
+ Interval:間隔:
-
+ 30 minutes30分鐘
-
+ 1 hour1小時
-
+ 2 hours2小時
-
+ 4 hours4小時
-
+ 8 hours8小時
-
+ 12 hours12小時
-
+ daily日常的
-
+ Update libraries at certain time定時更新庫
-
+ Time:時間:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2124,60 +2304,75 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
若要停止自動更新,請點選庫標題旁的載入指示器。
-
+ Modifications detection修改檢測
-
+ Compare the modified date of files when updating a library (not recommended)更新庫時比較文件的修改日期(不建議)
-
+ Enable background image啟用背景圖片
-
+ Opacity level透明度
-
+ Blur level模糊
-
+ Use selected comic cover as background使用選定的漫畫封面做背景
-
+ Restore defautls恢復默認值
-
+ Background背景
-
+ Display continue reading banner顯示繼續閱讀橫幅
-
+ Display current comic banner顯示目前漫畫橫幅
-
+ Continue reading繼續閱讀
+
+
+ Mix folders and comics
+ 混合顯示資料夾和漫畫
+
+
+
+ Start comics on a new row
+ 從新一行開始顯示漫畫
+
+
+
+ Content
+ 內容
+ Comic Flow
@@ -2185,7 +2380,7 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ Libraries庫
@@ -3273,7 +3468,7 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
+ Set portset port設定連接埠
@@ -3295,53 +3490,53 @@ Use quotes to include spaces in a value.
選擇IP地址
-
-
+
+ Server connectivity伺服器連線
-
+ Scan to connect掃描以連線
-
+ Devices on this network can reach your library at the address below.此網絡中的裝置可透過以下地址存取你的資料庫。
-
+ IP addressIP 地址
-
+ Port端口
-
+ Web interface網頁介面
-
+ Copy link複製連結
-
+ Open web UI開啟網頁介面
-
+ Enable the server啟用伺服器
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader 支援 iOS 及 Android。取得 <a href='https://ios.yacreader.com'>iOS</a> 或 <a href='https://android.yacreader.com'>Android</a> 版本。
diff --git a/YACReaderLibrary/yacreaderlibrary_zh_TW.ts b/YACReaderLibrary/yacreaderlibrary_zh_TW.ts
index 8eae882f7..718c4576e 100644
--- a/YACReaderLibrary/yacreaderlibrary_zh_TW.ts
+++ b/YACReaderLibrary/yacreaderlibrary_zh_TW.ts
@@ -426,6 +426,14 @@
搜索漫畫中...
+
+ ContinueReadingGridHeader
+
+
+ Continue Reading...
+ 繼續閱讀...
+
+CreateLibraryDialog
@@ -505,6 +513,19 @@
該資料夾還沒有漫畫
+
+ EmptyInfoView
+
+
+ Nothing selected
+ 未選取任何內容
+
+
+
+ Select a comic or folder to see its information.
+ 選取漫畫或資料夾以檢視其資訊。
+
+EmptyLabelWidget
@@ -647,18 +668,121 @@
FolderContentView
- Continue Reading...
- 繼續閱讀...
+ 繼續閱讀...
+
+
+
+ FolderInfoView
+
+
+ Unknown
+ 未知
+
+
+
+ Items
+ 項目
+
+
+
+ Type
+ 類型
+
+
+
+ Reading status
+ 閱讀狀態
+
+
+
+ Read
+ 閱讀
+
+
+
+ Unread
+ 未讀
+
+
+
+ Collection status
+ 收藏狀態
+
+
+
+ Completed
+ 已完成
+
+
+
+ In progress
+ 閱讀中
+
+
+
+ Added
+ 已加入
+
+
+
+ Updated
+ 已更新GridComicsView
-
+ Show info顯示資訊
+
+ Library
+ 庫
+
+
+ Folder
+ 檔夾
+
+
+ Favorites
+ 收藏夾
+
+
+ Recently added
+ 最近加入
+
+
+
+ Manga
+ 日式漫畫
+
+
+
+ Western manga
+ 西式漫畫
+
+
+
+ Web comic
+ 網路漫畫
+
+
+
+ Yonkoma
+ 四格漫畫
+
+
+
+ Comic
+ 漫畫
+
+
+
+ Unknown
+ 未知
+ HelpAboutDialog
@@ -807,6 +931,29 @@
<p>正在檢查目前漫畫庫中遺失的封面和不完整的漫畫資訊。</p><p>這可能需要幾分鐘。您可以停止此程序,稍後再重新執行。</p>
+
+ LibraryInfoView
+
+
+ Library info
+ 圖書館資訊
+
+
+
+ Number of folders
+ 資料夾數量
+
+
+
+ Number of comics
+ 漫畫數量
+
+
+
+ Number of read comics
+ 已讀漫畫數量
+
+LibraryWindow
@@ -815,275 +962,275 @@
YACReader 庫
-
+ Library庫
-
+ Set as read設為已讀
-
-
+
+ Set as unread設為未讀
-
-
-
+
+
+ manga漫畫
-
-
-
+
+
+ comic漫畫
-
-
-
+
+
+ web comic網路漫畫
-
-
-
+
+
+ western manga (left to right)西方漫畫(從左到右)
-
+ Library not availableLibrary '庫不可用
-
+ Rescan library for XML info重新掃描庫的 XML 資訊
-
+ Delete folder刪除檔夾
-
+ Open folder...打開檔夾...
-
+ Set as uncompleted設為未完成
-
+ Set as completed設為已完成
-
+ Update folder更新檔夾
-
+ Folder檔夾
-
+ Comic漫畫
-
+ A repair of this library is already running (%1). Wait for it to finish.此庫的修復已在執行中(%1)。請等待其完成。
-
+ The library is locked by a repair that did not finish.此庫已被一個未完成的修復鎖定。
-
+ The library is locked by a repair started by %1.此庫已被 %1 啟動的修復鎖定。
-
+ If you are sure that no other repair is running, the lock can be removed. Remove the lock and continue?如果您確定沒有其他修復正在執行,可以移除該鎖定。移除鎖定並繼續?
-
+ Upgrade failed更新失敗
-
+ There were errors during library upgrade in: 漫畫庫更新時出現錯誤:
-
+ Restore recovery failed還原復原失敗
-
+ Update needed需要更新
-
+ This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?此庫是使用舊版本的YACReaderLibrary創建的. 它需要更新. 現在更新?
-
+ Download new version下載新版本
-
+ This library was created with a newer version of YACReaderLibrary. Download the new version now?此庫是使用較新版本的YACReaderLibrary創建的。 立即下載新版本?
-
+ Library '%1' is no longer available. Do you want to remove it?庫 '%1' 不再可用。 你想刪除它嗎?
-
+ Old library舊的庫
-
+ Library '%1' has been created with an older version of YACReaderLibrary. It must be created again. Do you want to create the library now?庫 '%1' 是通過舊版本的YACReaderLibrary創建的。 必須再次創建。 你想現在創建嗎?
-
-
+
+ Copying comics...複製漫畫中...
-
-
+
+ Moving comics...移動漫畫中...
-
+ Folder name:檔夾名稱:
-
+ No folder selected沒有選中的檔夾
-
+ Please, select a folder first請先選擇一個檔夾
-
+ Error in path路徑錯誤
-
+ There was an error accessing the folder's path訪問檔夾的路徑時出錯
-
+ The selected folder and all its contents will be deleted from your disk. Are you sure?所選檔夾及其所有內容將從磁片中刪除。 你確定嗎?
-
+ There was an issue trying to delete the selected folders. Please, check for write permissions and be sure that any applications are using these folders or any of the contained files.嘗試刪除所選檔夾時出現問題。 請檢查寫入許可權,並確保沒有其他應用程式在使用這些檔夾或檔。
-
+ Add new reading lists添加新的閱讀列表
-
-
+
+ List name:列表名稱:
-
+ Delete list/label刪除 列表/標籤
-
+ The selected item will be deleted, your comics or folders will NOT be deleted from your disk. Are you sure?所選項目將被刪除,您的漫畫或檔夾將不會從您的磁片中刪除。 你確定嗎?
-
+ Rename list name重命名列表
-
-
-
+
+
+ 4koma (top to botom)4koma(由上至下)
-
-
-
-
+
+
+
+ Set type套裝類型
-
+ Set custom cover設定自訂封面
-
+ Delete custom cover刪除自訂封面
-
+ Save covers保存封面
-
+ You are adding too many libraries.您添加的庫太多了。
-
+ You are adding too many libraries.
You probably only need one library in your top level comics folder, you can browse any subfolders using the folders section in the left sidebar.
@@ -1096,43 +1243,43 @@ YACReaderLibrary will not stop you from creating more libraries but you should k
YACReaderLibrary不會阻止您創建更多的庫,但是您應該保持較低的庫數量來提升性能。
-
-
+
+ YACReader not foundYACReader 未找到
-
+ Error錯誤
-
+ Error opening comic with third party reader.使用第三方閱讀器開啟漫畫時出錯。
-
+ Library not found未找到庫
-
+ The selected folder doesn't contain any library.所選檔夾不包含任何庫。
-
+ Are you sure?你確定嗎?
-
+ Do you want remove 你想要刪除
-
+ library? 庫?
@@ -1141,124 +1288,124 @@ YACReaderLibrary不會阻止您創建更多的庫,但是您應該保持較低
移除並刪除元數據
-
+ Library info圖書館資訊
-
+ Assign comics numbers分配漫畫編號
-
+ Assign numbers starting in:從以下位置開始分配編號:
-
-
+
+ Unable to delete無法刪除
-
+ Search filters搜尋篩選條件
-
+ Unread未讀
-
+ In progress閱讀中
-
+ Highly rated高評分
-
+ Recently added最近加入
-
+ Search syntax…搜尋語法…
-
+ Package operation failed
-
+ The covers package operation could not be completed.
-
+ Add new folder添加新的檔夾
-
+ YACReader not found. YACReader should be installed in the same folder as YACReaderLibrary.未找到YACReader. YACReader應安裝在與YACReaderLibrary相同的檔夾中.
-
+ YACReader not found. There might be a problem with your YACReader installation.未找到YACReader. YACReader的安裝可能有問題.
-
-
+
+ YACReader library database (*.ydb)YACReader 漫畫庫資料庫 (*.ydb)
-
+ The library database backup was created at:
%1漫畫庫資料庫備份已建立於:
%1
-
+ Unable to create the library database backup:
%1無法建立漫畫庫資料庫備份:
%1
-
+ Close YACReaderLibraryServer and any other YACReader application using this library before restoring. Continue?還原前請關閉 YACReaderLibraryServer 以及正在使用此漫畫庫的所有其他 YACReader 應用程式。是否繼續?
-
+ Restoring library database...正在還原漫畫庫資料庫...
-
+ The current library database is invalid. Restore the selected backup anyway?目前的漫畫庫資料庫無效。仍要還原所選備份嗎?
-
-
+
+ The library maintenance lock may be stale. Remove it and retry?漫畫庫維護鎖可能已失效。是否移除並重試?
-
+
Restart YACReaderLibrary before attempting recovery again.
@@ -1267,71 +1414,71 @@ Restart YACReaderLibrary before attempting recovery again.
再次嘗試復原前,請重新啟動 YACReaderLibrary。
-
+ The library database was restored successfully. Update the library now?漫畫庫資料庫已成功還原。是否立即更新漫畫庫?
-
+ Library database damaged漫畫庫資料庫已損壞
-
+ The database of library '%1' is damaged, so normal updates, maintenance, and backups are unavailable. YACReader can attempt to repair the database. Some damaged data may not be recoverable. Existing backups will not be changed.漫畫庫「%1」的資料庫已損壞,因此無法執行一般更新、維護與備份。YACReader 可以嘗試修復資料庫。部分損壞的資料可能無法復原。現有備份不會被變更。
-
+ Attempt repair嘗試修復
-
+ Restore a backup...還原備份...
-
+ Repairing library database...正在修復漫畫庫資料庫...
-
-
-
+
+
+ Library database repair修復漫畫庫資料庫
-
+ Another maintenance operation is currently using this library. Try again after it finishes.另一個維護操作正在使用此漫畫庫。請在操作完成後重試。
-
+ The library database is already valid.漫畫庫資料庫已經有效。
-
+ Library database repaired漫畫庫資料庫已修復
-
+ The library database was repaired by rebuilding its indexes. The damaged original was preserved at:
%1已透過重建索引修復漫畫庫資料庫。損壞的原始檔案已保留於:
%1
-
+ Library database rebuilt漫畫庫資料庫已重建
-
+ The library database was rebuilt successfully. The damaged original was preserved at:
%1
@@ -1342,7 +1489,7 @@ Update the library now?
是否立即更新漫畫庫?
-
+
The damaged original was preserved at:
@@ -1353,12 +1500,12 @@ The damaged original was preserved at:
%1
-
+ Library database repair failed漫畫庫資料庫修復失敗
-
+ The library database could not be repaired:
%1%2
@@ -1369,82 +1516,82 @@ You can restore a backup from the Library menu or recreate the library.
您可以從「漫畫庫」選單還原備份,或重新建立漫畫庫。
-
+ Remove and delete metadata and backups移除並刪除中繼資料與備份
-
+ There was an issue trying to delete the selected comics. Please, check for write permissions in the selected files or containing folder.嘗試刪除所選漫畫時出現問題。 請檢查所選檔或包含檔夾中的寫入許可權。
-
+ Invalid image圖片無效
-
+ The selected file is not a valid image.所選檔案不是有效影像。
-
+ Error saving cover儲存封面時發生錯誤
-
+ There was an error saving the cover image.儲存封面圖片時發生錯誤。
-
+ Error creating the library創建庫時出錯
-
+ Error updating the library更新庫時出錯
-
+ Error opening the library打開庫時出錯
-
+ Delete comics刪除漫畫
-
+ All the selected comics will be deleted from your disk. Are you sure?所有選定的漫畫都將從您的磁片中刪除。你確定嗎?
-
+ Remove comics移除漫畫
-
+ Comics will only be deleted from the current label/list. Are you sure?漫畫只會從當前標籤/列表中刪除。 你確定嗎?
-
+ Library name already exists庫名已存在
-
+ There is another library with the name '%1'.已存在另一個名為'%1'的庫。
-
+ Repaired: %1
Failed: %2
Missing files: %3
@@ -1932,6 +2079,39 @@ Missing files: %3
將所選漫畫添加到收藏夾列表
+
+ ListInfoView
+
+
+ 1 comic
+ 1 本漫畫
+
+
+
+ %1 comics
+ %1 本漫畫
+
+
+
+ Last day
+ 最近 1 天
+
+
+
+ Last %1 days
+ 最近 %1 天
+
+
+
+ 1 sublist
+ 1 個子清單
+
+
+
+ %1 sublists
+ %1 個子清單
+
+LocalComicListModel
@@ -1974,143 +2154,143 @@ Missing files: %3
OptionsDialog
-
+ Language語言
-
+ Application language應用程式語言
-
+ System default系統預設
-
+ Tray icon settings (experimental)託盤圖示設置 (實驗特性)
-
+ Close to tray關閉至託盤
-
+ Start into the system tray啟動至系統託盤
-
+ Edit Comic Vine API key編輯Comic Vine API 密匙
-
+ Comic Vine API keyComic Vine API 密匙
-
+ ComicInfo.xml legacy supportComicInfo.xml 遺留支持
-
+ Import metadata from ComicInfo.xml when adding new comicsImport metada from ComicInfo.xml when adding new comics新增漫畫時從 ComicInfo.xml 匯入元數據
-
+ Consider 'recent' items added or updated since X days ago考慮自 X 天前新增或更新的「最近」項目
-
+ Third party reader第三方閱讀器
-
+ Write {comic_file_path} where the path should go in the command在命令中應將路徑寫入 {comic_file_path}
-
+ Clear清空
-
+ Update libraries at startup啟動時更新庫
-
+ Try to detect changes automatically嘗試自動偵測變化
-
+ Update libraries periodically定期更新庫
-
+ Interval:間隔:
-
+ 30 minutes30分鐘
-
+ 1 hour1小時
-
+ 2 hours2小時
-
+ 4 hours4小時
-
+ 8 hours8小時
-
+ 12 hours12小時
-
+ daily日常的
-
+ Update libraries at certain time定時更新庫
-
+ Time:時間:
-
+ WARNING! During library updates writes to the database are disabled!
Don't schedule updates while you may be using the app actively.
During automatic updates the app will block some of the actions until the update is finished.
@@ -2124,60 +2304,75 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
若要停止自動更新,請點選庫標題旁的載入指示器。
-
+ Modifications detection修改檢測
-
+ Compare the modified date of files when updating a library (not recommended)更新庫時比較文件的修改日期(不建議)
-
+ Enable background image啟用背景圖片
-
+ Opacity level透明度
-
+ Blur level模糊
-
+ Use selected comic cover as background使用選定的漫畫封面做背景
-
+ Restore defautls恢復默認值
-
+ Background背景
-
+ Display continue reading banner顯示繼續閱讀橫幅
-
+ Display current comic banner顯示目前漫畫橫幅
-
+ Continue reading繼續閱讀
+
+
+ Mix folders and comics
+ 混合顯示資料夾和漫畫
+
+
+
+ Start comics on a new row
+ 從新的一列開始顯示漫畫
+
+
+
+ Content
+ 內容
+ Comic Flow
@@ -2185,7 +2380,7 @@ To stop an automatic update tap on the loading indicator next to the Libraries t
-
+ Libraries庫
@@ -3273,7 +3468,7 @@ Use quotes to include spaces in a value.
ServerConfigDialog
-
+ Set portset port設定連接埠
@@ -3295,53 +3490,53 @@ Use quotes to include spaces in a value.
選擇IP地址
-
-
+
+ Server connectivity伺服器連線
-
+ Scan to connect掃描以連線
-
+ Devices on this network can reach your library at the address below.此網路中的裝置可透過以下位址存取您的資料庫。
-
+ IP addressIP 位址
-
+ Port端口
-
+ Web interface網頁介面
-
+ Copy link複製連結
-
+ Open web UI開啟網頁介面
-
+ Enable the server啟用伺服器
-
+ YACReader is available for iOS and Android. Discover it for <a href='https://ios.yacreader.com'>iOS</a> or <a href='https://android.yacreader.com'>Android</a>.YACReader 支援 iOS 與 Android。取得 <a href='https://ios.yacreader.com'>iOS</a> 或 <a href='https://android.yacreader.com'>Android</a> 版本。
diff --git a/common/rhi/yacreader_comic_flow_rhi.cpp b/common/rhi/yacreader_comic_flow_rhi.cpp
index bba348df3..1b94e0075 100644
--- a/common/rhi/yacreader_comic_flow_rhi.cpp
+++ b/common/rhi/yacreader_comic_flow_rhi.cpp
@@ -25,6 +25,7 @@ void YACReaderComicFlow3D::setImagePaths(QStringList paths)
}
this->paths = paths;
+ loadingWindowCenter = -1;
}
void YACReaderComicFlow3D::updateImageData()
@@ -32,6 +33,11 @@ void YACReaderComicFlow3D::updateImageData()
if (worker->busy())
return;
+ if (loadingWindowCenter != currentSelected) {
+ failedImageLoads.clear();
+ loadingWindowCenter = currentSelected;
+ }
+
int idx = worker->index();
if (idx >= 0 && !worker->result().isNull()) {
if (!loaded[idx]) {
@@ -56,6 +62,9 @@ void YACReaderComicFlow3D::updateImageData()
}
}
+ if (idx >= 0 && idx < loaded.size() && !loaded[idx])
+ failedImageLoads.insert(idx);
+
int count = 8;
switch (performance) {
case low:
@@ -83,11 +92,9 @@ void YACReaderComicFlow3D::updateImageData()
for (int c = 0; c < 2 * count + 1; c++) {
int i = indexes[c];
if ((i >= 0) && (i < numObjects))
- if (!loaded[i]) {
- if (paths.size() > 0) {
- QString fname = paths.at(i);
- worker->generate(i, fname);
- }
+ if (!loaded[i] && !failedImageLoads.contains(i)) {
+ if (!paths.isEmpty())
+ worker->generate(i, paths.at(i));
delete[] indexes;
return;
}
@@ -104,6 +111,7 @@ void YACReaderComicFlow3D::remove(int item)
if (item >= 0 && item < paths.size()) {
paths.removeAt(item);
}
+ loadingWindowCenter = -1;
worker->unlock();
}
@@ -113,6 +121,7 @@ void YACReaderComicFlow3D::add(const QString &path, int index)
worker->reset();
paths.insert(index, path);
YACReaderFlow3D::add(index);
+ loadingWindowCenter = -1;
worker->unlock();
}
@@ -144,7 +153,7 @@ void YACReaderComicFlow3D::resortCovers(QList newOrder)
loaded = loadedNew;
marks = marksNew;
images = imagesNew;
-
+ loadingWindowCenter = -1;
worker->unlock();
}
@@ -189,7 +198,8 @@ ImageLoader3D::~ImageLoader3D()
bool ImageLoader3D::busy() const
{
- return isRunning() ? working : false;
+ QMutexLocker locker(&mutex);
+ return working;
}
void ImageLoader3D::generate(int index, const QString &fileName)
@@ -198,14 +208,16 @@ void ImageLoader3D::generate(int index, const QString &fileName)
this->idx = index;
this->fileName = fileName;
this->img = QImage();
- mutex.unlock();
-
- if (!isRunning())
- start();
- else {
+ this->working = true;
+ const bool shouldStart = !isRunning();
+ if (!shouldStart) {
restart = true;
condition.wakeOne();
}
+ mutex.unlock();
+
+ if (shouldStart)
+ start();
}
void ImageLoader3D::lock()
@@ -233,6 +245,10 @@ void ImageLoader3D::run()
this->img = image;
mutex.unlock();
+ QMetaObject::invokeMethod(flow, [flow = flow] {
+ flow->startAnimationTimer();
+ });
+
mutex.lock();
if (!this->restart)
condition.wait(&mutex);
@@ -243,5 +259,12 @@ void ImageLoader3D::run()
QImage ImageLoader3D::result()
{
+ QMutexLocker locker(&mutex);
return img;
}
+
+int ImageLoader3D::index() const
+{
+ QMutexLocker locker(&mutex);
+ return idx;
+}
diff --git a/common/rhi/yacreader_comic_flow_rhi.h b/common/rhi/yacreader_comic_flow_rhi.h
index 61d65300e..947c02c35 100644
--- a/common/rhi/yacreader_comic_flow_rhi.h
+++ b/common/rhi/yacreader_comic_flow_rhi.h
@@ -4,6 +4,7 @@
#include "yacreader_flow_rhi.h"
#include
+#include
#include
class ImageLoader3D;
@@ -21,6 +22,8 @@ class YACReaderComicFlow3D : public YACReaderFlow3D
private:
ImageLoader3D *worker;
+ QSet failedImageLoads;
+ int loadingWindowCenter = -1;
protected:
QList paths;
@@ -38,7 +41,7 @@ class ImageLoader3D : public QThread
idx = -1;
fileName = "";
}
- int index() const { return idx; }
+ int index() const;
void lock();
void unlock();
QImage result();
@@ -49,7 +52,7 @@ class ImageLoader3D : public QThread
void run() override;
private:
- QMutex mutex;
+ mutable QMutex mutex;
QWaitCondition condition;
bool restart;
diff --git a/common/rhi/yacreader_flow_rhi.cpp b/common/rhi/yacreader_flow_rhi.cpp
index 7db946660..695296098 100644
--- a/common/rhi/yacreader_flow_rhi.cpp
+++ b/common/rhi/yacreader_flow_rhi.cpp
@@ -20,6 +20,7 @@ YACReaderFlow3D::YACReaderFlow3D(QWidget *parent, struct Preset p)
: QRhiWidget(parent),
numObjects(0),
lazyPopulateObjects(-1),
+ pendingCurrentIndex(-1),
showMarks(true),
hasBeenInitialized(false),
backgroundColor(Qt::black),
@@ -980,6 +981,31 @@ void YACReaderFlow3D::setCurrentIndex(int pos)
viewRotateActive = 1;
}
+void YACReaderFlow3D::setCurrentIndexWithoutAnimation(int pos)
+{
+ if (pos < 0)
+ return;
+
+ if (images.isEmpty() && lazyPopulateObjects > 0) {
+ pendingCurrentIndex = qMin(pos, lazyPopulateObjects - 1);
+ return;
+ }
+
+ if (pos >= images.size())
+ return;
+
+ pendingCurrentIndex = -1;
+ currentSelected = pos;
+ for (auto index = 0; index < images.size(); ++index) {
+ calcVector(images[index].animEnd, index - currentSelected);
+ images[index].current = images[index].animEnd;
+ }
+
+ viewRotate = 0;
+ cleanupAnimation();
+ startAnimationTimer();
+}
+
void YACReaderFlow3D::updatePositions()
{
int count;
@@ -1103,7 +1129,6 @@ void YACReaderFlow3D::populate(int n)
if (hasBeenInitialized) {
clear();
}
- emit centerIndexChanged(0);
float x = 1;
float y = 1 * (700.f / 480.0f);
@@ -1114,6 +1139,14 @@ void YACReaderFlow3D::populate(int n)
}
loaded = QVector(n, false);
+
+ if (pendingCurrentIndex >= 0 && n > 0) {
+ const auto index = qMin(pendingCurrentIndex, n - 1);
+ setCurrentIndexWithoutAnimation(index);
+ emit centerIndexChanged(index);
+ } else {
+ emit centerIndexChanged(0);
+ }
}
void YACReaderFlow3D::reset()
@@ -1139,6 +1172,7 @@ void YACReaderFlow3D::reset()
numObjects = 0;
images.clear();
+ pendingCurrentIndex = -1;
if (!hasBeenInitialized)
lazyPopulateObjects = -1;
diff --git a/common/rhi/yacreader_flow_rhi.h b/common/rhi/yacreader_flow_rhi.h
index a1062bbb3..9a36597b6 100644
--- a/common/rhi/yacreader_flow_rhi.h
+++ b/common/rhi/yacreader_flow_rhi.h
@@ -151,6 +151,7 @@ class YACReaderFlow3D : public QRhiWidget, public ScrollManagement
int numObjects;
int lazyPopulateObjects;
+ int pendingCurrentIndex;
bool showMarks;
QVector loaded;
QVector marks;
@@ -232,6 +233,7 @@ class YACReaderFlow3D : public QRhiWidget, public ScrollManagement
void showPrevious();
void showNext();
void setCurrentIndex(int pos);
+ void setCurrentIndexWithoutAnimation(int pos);
void cleanupAnimation();
void draw();
void updatePositions();
diff --git a/common/yacreader_global_gui.h b/common/yacreader_global_gui.h
index d671b30ea..9cbd7b002 100644
--- a/common/yacreader_global_gui.h
+++ b/common/yacreader_global_gui.h
@@ -75,6 +75,8 @@
#define COMICS_GRID_COVER_SIZES "COMICS_GRID_COVER_SIZES"
#define COMICS_GRID_SHOW_INFO "COMICS_GRID_SHOW_INFO"
#define COMICS_GRID_INFO_WIDTH "COMICS_GRID_INFO_WIDTH"
+#define COMICS_GRID_MIX_FOLDERS_AND_COMICS "COMICS_GRID_MIX_FOLDERS_AND_COMICS"
+#define COMICS_GRID_START_COMICS_ON_NEW_ROW "COMICS_GRID_START_COMICS_ON_NEW_ROW"
#define COMIC_VINE_API_KEY "COMIC_VINE_API_KEY"
#define COMIC_VINE_BASE_URL "COMIC_VINE_BASE_URL"
diff --git a/custom_widgets/whats_new_dialog.cpp b/custom_widgets/whats_new_dialog.cpp
index d67dbd6a5..4eddee35d 100644
--- a/custom_widgets/whats_new_dialog.cpp
+++ b/custom_widgets/whats_new_dialog.cpp
@@ -271,9 +271,7 @@ QString YACReader::WhatsNewDialog::renderHtmlDocument(const QString &content) co
QString YACReader::WhatsNewDialog::renderIntro() const
{
- return "YACReader 10.2 adds a new basic web reader, redesigned settings dialogs, and experimental EPUB support. "
- "It also brings more natural zoom controls, a better magnifying glass with an option to make it round, and more. "
- "Don't forget to check the new built-in search guide so you can make the most of the search engine.";
+ return "YACReader 10.3 brings a much better library navigation experience!";
}
QString YACReader::WhatsNewDialog::renderFooter() const
diff --git a/custom_widgets/yacreader_table_view.cpp b/custom_widgets/yacreader_table_view.cpp
index 9d3b1bffd..c737ad0f2 100644
--- a/custom_widgets/yacreader_table_view.cpp
+++ b/custom_widgets/yacreader_table_view.cpp
@@ -146,10 +146,26 @@ void YACReaderTableView::dragMoveEvent(QDragMoveEvent *event)
void YACReaderTableView::dropEvent(QDropEvent *event)
{
- QTableView::dropEvent(event);
+ if (!model()->canDropMimeData(event->mimeData(), event->proposedAction(), 0, 0, QModelIndex())) {
+ event->ignore();
+ return;
+ }
- if (model()->canDropMimeData(event->mimeData(), event->proposedAction(), 0, 0, QModelIndex()))
- event->acceptProposedAction();
+ const QPoint position = event->position().toPoint();
+ const QModelIndex destination = indexAt(position);
+ int destinationRow = -1;
+ if (destination.isValid()) {
+ destinationRow = destination.row();
+ if (position.y() >= visualRect(destination).center().y())
+ ++destinationRow;
+ }
+
+ if (model()->dropMimeData(event->mimeData(), Qt::MoveAction, destinationRow, 0, QModelIndex())) {
+ event->setDropAction(Qt::MoveAction);
+ event->accept();
+ } else {
+ event->ignore();
+ }
QLOG_DEBUG() << "drop on table";
}