Only advance one page in Two-Page-Mode

Asked by Tim Wischmeier on 2019-01-27


currently, when in Two-Page-Mode, the Next-Page-Command will show the next two pages (i.e if you start seeing pages 1-2 side-by-side, after the Next-Page-Command you see pages 3-4).

However, I would like to only advance 1 page (i.e. see pages 2-3 from the example above).

I think there are no settings for this, so I already started digging through the source code. I managed to compile it myself, even making it fullscreen and hiding the menu bar on start (programmatically).

For my use case I guess I need to modify the TwoPagesLayout in documentlayout.cpp, more specifically the functions currentPage, previousPage, nextPage, leftIndex, RightIndex and possibly prepareLayout.

To my own dismay I could not understand these functions enough to make it work on my own (even though I am a software engineer...). I get that the TwoPagesLayout basically calculates based on even and odd pages. And if I understand the prepareLayout function correctly, it basically "just" places all pages in a big area, where only a bit of the area is visible at a time. So it should work if I just layout all pages "in one horizontal line" (basically what SinglePageLayout::prepareLayout does, just orthogonally), but I can not manage to make it work.

Some input on this will be very much appreciated.

Best Regards,

PS: On my use case: I am building a digital note stand for my piano, where I can flip the pages by using a pedal. It is especially useful to always have a preview of sorts when playing, that is why I would like to only advance one page at a time.

Question information

English Edit question
qpdfview Edit question
No assignee Edit question
Last query:
Last reply:
Adam Reichold (adamreichold) said : #1

Hello Tim,

I think you description of how "prepareLayout" works is somewhat accurate. IMHO, the problem is that DocumentView::prepareView assumes that for a given current page, the pages between DocumentLayout::leftIndex and DocumentLayout::rightIndex are visible and that these intervals do not overlap, i.e. any given page is visible for exactly one current page. Hence what you describe will be difficult to accomplish without increasing the separate of concerns between DocumentLayout and DocumentView further. (DocumetLayout is a post-facto refactoring to remove some but not all layout-related code from DocumentView, but it is by no means a principled approach to the problem.)

While it would be rather welcome if someone tried to this shortcoming of the qpdfview code base, your immediate use case might be better served if you just transform the PDF in question to produce a version with duplicate pages like 1, 2, 2, 3, 3, ... so that a two-page layout would look like 1 2|2 3|3 4|...?

Best regards,

Tim Wischmeier (zeeocho) said : #2

Hello Adam,

I am sorry for going awol on you, there has been some personal stuff I needed to deal with... Well, I have some days off from work and had the time to get back to this project.

Thank you very much for your detailed and quick answer, and for a recommendation on how to quickly solve my use case.

I am somehow a bit uncomfortable with duplicating pages, so I would like to try a refactor stuff a bit. I don't know if the result will be push-worthy, but I will see. I think I have a better feeling on how DocumentView and DocumentLayout interact (I hope):

DocumentLayout is expected to layout it's pages once, ordering them "row-wise" vertically in "flick order", while each row will be displayed by the DocumentView. The View will set the top of the clipping rectangle (called sceneRect) to the last page that matches leftIndex.

My first thought is that the View might be putting a constraint on the Layout that it shouldn't. That way, the view has (assumed) knowledge about the Layout, because it wants to determine the clipping rectangle. One could let the Layout determine the clipping rectangle (area to be viewed). Of course you would need to tell it what the user wants to view (e.g. the selected page). The view would then still be responsible on setting the pages inide that rectangle visible (and those outside invisible).

This sounds fine in my head as long as the user can only flip from one page to the next. It gets a bit complicated when the user wanted to flip horizontally or vertically (imagine you arranged 81 pages in a 9x9 grid, and 2x1 are visible at any time). Or even more when there is continuous scrolling involved.

So, we might consider abstracting the layout a bit more. I could see a base class which accepts the following parameters:
- Vertical or Horizontal Layout (right now the DocumentView basically expects a vertical layout, I think)
- Number of Pages per Screen
- Coninuous Mode (on/off; you want to space out pages differently in horizontal mode)
- Number of Pages on first Screen

The view can then
- ask it to layout the pages (as it can now), providing the current screenRect
- ask for next / previous page (as it can now)
- ask the origin for the screenRect for a given page

This would eliminate the need for left and right indices. The DocumentView knows the size of the screenRect. It can eihter move it freely (continuous mode) or snap it to different pages. For the latter, it can ask the Layout where it needs to go for a certain page.

We should be able to map the current layouts to this and probably also horizontal continuous scrolling (Question #679376). there are still some constraints: the pages are expected to only exists once on the whole layout. So you still have a fixed layout, are you just move the clipping rectangle around; the layout does not change depending on what you view, and you basically expect the layout to produce "view clusters".

Ok, so this turned out to be more of a brainstorming :). I think I might be able to implement what I have in mind. I am new to developing in linux, c++, and git, though. Just to have the right keywords: would I push my changes to a branch, or what would be the right way to do it?

Best regards,

Can you help with this problem?

Provide an answer of your own, or ask Tim Wischmeier for more information if necessary.

To post a message you must log in.