diff --git a/doc/katarakt.txt b/doc/katarakt.txt index 15ddd1d3147a1acdfabd7ed7118ad415177b0779..adccd230641a260e352b52f25c429b23ef4500e3 100644 --- a/doc/katarakt.txt +++ b/doc/katarakt.txt @@ -26,7 +26,7 @@ pixel) scrolling, zooming and adjusting the column count. Pages keep their correct relative size and are shown in a grid. The 'presenter layout' is for giving a presentation. It opens a second window, -to be viewed on the beamer, and shows the current and next slide in the main +to be viewed on the projector, and shows the current and next slide in the main window. For every file passed on the command line a separate process is spawned. @@ -73,7 +73,7 @@ KEY BINDINGS *3* :: Switch to 'presenter layout'. Views the current page and a smaller preview of the next page. Also, opens a second window that shows only the current - page for displaying on a beamer. + page for displaying on a projector. *Up*, *Down*, *Left*, *Right*, *k*, *j*, *h*, *l* :: Move around (up/down/left/right). @@ -138,6 +138,9 @@ KEY BINDINGS Show a file dialog to save the current document. *F9* :: Toggle the table of contents. +*x* :: + Toggle freezing the slide currently displayed in the projector window. When + frozen, scrolling only affects the main window. VARIABLES --------- diff --git a/share/katarakt.ini b/share/katarakt.ini index 76188c6b9756e11e13bf106e41f2141dc8e56f56..2fb6334d7cb5915b4e4879706df8b4f7133d2a4a 100644 --- a/share/katarakt.ini +++ b/share/katarakt.ini @@ -75,3 +75,4 @@ reload=R open=O save=S toggle_toc=F9 +freeze_presentation=X diff --git a/src/beamerwindow.cpp b/src/beamerwindow.cpp index c77e9de7d138848975578cc08cc80ba041267c47..1d81cb2e69d0ef2af702110fce7f31ccaba9bf9e 100644 --- a/src/beamerwindow.cpp +++ b/src/beamerwindow.cpp @@ -14,6 +14,7 @@ using namespace std; BeamerWindow::BeamerWindow(Viewer *v, QWidget *parent) : QWidget(parent), viewer(v), + frozen(false), valid(false) { setFocusPolicy(Qt::StrongFocus); @@ -38,6 +39,15 @@ BeamerWindow::~BeamerWindow() { delete layout; } +void BeamerWindow::freeze(bool f) { + frozen = f; + viewer->get_canvas()->update_page_overlay(); +} + +bool BeamerWindow::is_frozen() const { + return frozen; +} + bool BeamerWindow::is_valid() const { return valid; } diff --git a/src/beamerwindow.h b/src/beamerwindow.h index b10566e0491b4b5f05ce9f0a8159fa460adcb148..d9b78bc4e34a494c1b25fd9def1194762cc288bb 100644 --- a/src/beamerwindow.h +++ b/src/beamerwindow.h @@ -15,6 +15,9 @@ public: BeamerWindow(Viewer *v, QWidget *parent = 0); ~BeamerWindow(); + void freeze(bool f); + bool is_frozen() const; + bool is_valid() const; Layout *get_layout() const; @@ -43,6 +46,7 @@ private: Qt::MouseButton click_link_button; + bool frozen; bool valid; }; diff --git a/src/canvas.cpp b/src/canvas.cpp index 7f6697bff6f4a270a159d7ebaffeb6c47d70c511..b6b31addcf490efb951d03b49f6d62ad1fe51b0d 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -168,10 +168,14 @@ Layout *Canvas::get_layout() const { } void Canvas::update_page_overlay() { + QString frozen_text; + if (viewer->get_beamer()->is_frozen()) { + frozen_text = QString("Frozen: %1, ").arg(viewer->get_beamer()->get_layout()->get_page() + 1); + } QString overlay_text = CFG::get_instance()->get_value("Settings/page_overlay_text").toString() .arg(cur_layout->get_page() + 1) .arg(viewer->get_res()->get_page_count()); - page_overlay->setText(overlay_text); + page_overlay->setText(frozen_text + overlay_text); page_overlay->adjustSize(); page_overlay->move(width() - page_overlay->width(), height() - page_overlay->height()); } @@ -371,7 +375,9 @@ void Canvas::set_presenter_layout() { // int cur_screen = desktop->screenNumber(viewer); // cout << "primary: " << primary_screen << ", current: " << cur_screen << endl; // } - viewer->get_beamer()->get_layout()->scroll_page(cur_layout->get_page(), false); + if (!viewer->get_beamer()->is_frozen()) { + viewer->get_beamer()->get_layout()->scroll_page(cur_layout->get_page(), false); + } viewer->get_beamer()->show(); viewer->show_progress(true); } diff --git a/src/config.cpp b/src/config.cpp index c027d52db914d3efefb774baba5e52490c96c5c5..a900a2a5deb384817f2573e7bfa2c6609da6dd43 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -101,6 +101,7 @@ void CFG::init_defaults() { vk.push_back("Keys/open"); keys[vk.back()] = QStringList() << "O"; vk.push_back("Keys/save"); keys[vk.back()] = QStringList() << "S"; vk.push_back("Keys/toggle_toc"); keys[vk.back()] = QStringList() << "F9"; + vk.push_back("Keys/freeze_presentation"); keys[vk.back()] = QStringList() << "X"; // tmp values tmp_values["start_page"] = 0; diff --git a/src/layout/gridlayout.cpp b/src/layout/gridlayout.cpp index 9c3d378113a517fccc2d2cff904e3f9154b41bc9..2ec8260f2f0662d9a8bcdb3ff5ab66d24a030b86 100644 --- a/src/layout/gridlayout.cpp +++ b/src/layout/gridlayout.cpp @@ -420,7 +420,7 @@ void GridLayout::render(QPainter *painter) { } last_visible_page = last_page; - res->collect_garbage(page + horizontal_page - grid->get_offset() - prefetch_count * 3, last_page + prefetch_count * 3); + res->collect_garbage(page + horizontal_page - grid->get_offset() - prefetch_count * 3, last_page + prefetch_count * 3, render_index); // prefetch int prefetch_first = page + horizontal_page - grid->get_offset() - 1; diff --git a/src/layout/presenterlayout.cpp b/src/layout/presenterlayout.cpp index f6f59bf3cd27ccb5eafa7a96f6998d8b68303bd3..56f6b0ef3083a0119d84b20fcecf485636d0f7a7 100644 --- a/src/layout/presenterlayout.cpp +++ b/src/layout/presenterlayout.cpp @@ -190,7 +190,9 @@ void PresenterLayout::render(QPainter *painter) { res->unlock_page(page - count); } } - res->collect_garbage(page - prefetch_count * 3, page + 1 + prefetch_count * 3); + for (int i = 0; i < 2; i++) { + res->collect_garbage(page - prefetch_count * 3, page + 1 + prefetch_count * 3, render_index + i); + } } void PresenterLayout::advance_invisible_hit(bool forward) { diff --git a/src/layout/singlelayout.cpp b/src/layout/singlelayout.cpp index 6e0e081006d890b41f04922e5984e73b1710c7e3..458c759c64371b0118bd9e9033183ddea398d81c 100644 --- a/src/layout/singlelayout.cpp +++ b/src/layout/singlelayout.cpp @@ -112,7 +112,7 @@ void SingleLayout::render(QPainter *painter) { res->unlock_page(page - count); } } - res->collect_garbage(page - prefetch_count * 3, page + prefetch_count * 3); + res->collect_garbage(page - prefetch_count * 3, page + prefetch_count * 3, render_index); } void SingleLayout::advance_invisible_hit(bool forward) { diff --git a/src/resourcemanager.cpp b/src/resourcemanager.cpp index 44fcf18d71746eae3750160acbee8f4303eeac29..8c3de19a8869a49b05be4cab1fc56918c9e187db 100644 --- a/src/resourcemanager.cpp +++ b/src/resourcemanager.cpp @@ -132,7 +132,9 @@ void ResourceManager::shutdown() { join_threads(); } garbageMutex.lock(); - garbage.clear(); + for (int i = 0; i < 3; i++) { + garbage[i].clear(); + } garbageMutex.unlock(); requests.clear(); requestSemaphore.acquire(requestSemaphore.available()); @@ -217,29 +219,29 @@ bool ResourceManager::are_colors_inverted() const { return inverted_colors; } -void ResourceManager::collect_garbage(int keep_min, int keep_max) { +void ResourceManager::collect_garbage(int keep_min, int keep_max, int index) { requestMutex.lock(); - center_page = (keep_min + keep_max) / 2; + if (index == 0) { // make a separate center_page for each index? + center_page = (keep_min + keep_max) / 2; + } requestMutex.unlock(); // free distant pages garbageMutex.lock(); - for (set<int>::iterator it = garbage.begin(); it != garbage.end(); /* empty */) { + for (set<int>::iterator it = garbage[index].begin(); it != garbage[index].end(); /* empty */) { int page = *it; if (page >= keep_min && page <= keep_max) { ++it; // move on continue; } - garbage.erase(it++); // erase and move on (iterator becomes invalid) + garbage[index].erase(it++); // erase and move on (iterator becomes invalid) #ifdef DEBUG cerr << " removing page " << page << endl; #endif k_page[page].mutex.lock(); - for (int i = 0; i < 3; i++) { - k_page[page].img[i] = QImage(); - k_page[page].img_other[i] = QImage(); - k_page[page].status[i] = 0; - k_page[page].rotation[i] = 0; - } + k_page[page].img[index] = QImage(); + k_page[page].img_other[index] = QImage(); + k_page[page].status[index] = 0; + k_page[page].rotation[index] = 0; k_page[page].mutex.unlock(); } garbageMutex.unlock(); diff --git a/src/resourcemanager.h b/src/resourcemanager.h index 6211aa363a3343a8c7b99ac381eaf94cd604b289..e83525f01b38edb8b77caf8294c0f4b7654e673b 100644 --- a/src/resourcemanager.h +++ b/src/resourcemanager.h @@ -60,7 +60,7 @@ public: void invert_colors(); bool are_colors_inverted() const; - void collect_garbage(int keep_min, int keep_max); + void collect_garbage(int keep_min, int keep_max, int index); void connect_canvas() const; diff --git a/src/viewer.cpp b/src/viewer.cpp index 328e1c5326cf04f957b8a3602652ddab67942c5e..1d12690e3954e88267e4f14df74cb7f900a2f2a4 100644 --- a/src/viewer.cpp +++ b/src/viewer.cpp @@ -444,6 +444,15 @@ void Viewer::toggle_toc() { toc->setFocus(Qt::OtherFocusReason); // only works if shown } +void Viewer::freeze_presentation() { + if (beamer->is_frozen()) { + beamer->freeze(false); + beamer->get_layout()->scroll_page(canvas->get_layout()->get_page(), false); + } else { + beamer->freeze(true); + } +} + void Viewer::update_info_widget() { if (!res->is_valid() || !search_bar->is_valid()) { QIcon icon; @@ -499,7 +508,7 @@ BeamerWindow *Viewer::get_beamer() const { void Viewer::layout_updated(int new_page, bool page_changed) { if (page_changed) { canvas->get_layout()->scroll_page(new_page, false); - if (beamer->isVisible()) { + if (beamer->isVisible() && !beamer->is_frozen()) { beamer->get_layout()->scroll_page(new_page, false); } // TODO unfold toc tree to show current entry? @@ -584,5 +593,6 @@ void Viewer::setup_keys(QWidget *base) { add_action(base, "Keys/open", SLOT(open()), this); add_action(base, "Keys/save", SLOT(save()), this); add_action(base, "Keys/toggle_toc", SLOT(toggle_toc()), this); + add_action(base, "Keys/freeze_presentation", SLOT(freeze_presentation()), this); } diff --git a/src/viewer.h b/src/viewer.h index cc71381223148ae2f2a216085811ca980891d495..0757477cc7ce0db154bb2c9837e9019793686347 100644 --- a/src/viewer.h +++ b/src/viewer.h @@ -83,6 +83,7 @@ private slots: void open(); // ask user for filename void save(); void toggle_toc(); + void freeze_presentation(); private: void update_info_widget(); diff --git a/src/worker.cpp b/src/worker.cpp index 48beafaadd1fe5ae293a1bd4acf04923e69a4414..d978121c1d0e6de81353456d23736bb61bd78f9d 100644 --- a/src/worker.cpp +++ b/src/worker.cpp @@ -84,7 +84,7 @@ void Worker::run() { // open page #ifdef DEBUG - cerr << " rendering page " << page << " for index " << index << endl; + cerr << " rendering page " << page << " for index " << index << ", center: " << res->center_page << endl; #endif Poppler::Page *p = NULL; if (render_new) { @@ -153,7 +153,7 @@ void Worker::run() { kp.mutex.unlock(); res->garbageMutex.lock(); - res->garbage.insert(page); // TODO add index information? + res->garbage[index].insert(page); res->garbageMutex.unlock(); emit page_rendered(page);