Make Folder View screen aware
ClosedPublic

Authored by amantia on Oct 26 2017, 11:19 AM.

Details

Summary

When using multiple screen with a Folder View as a desktop containment, we need to make sure a file belongs only to one screen. The patch adds support for this by:

  1. Introducing a ScreenMapper object shared acrossed all Folder Views
  2. FolderModel registers the screen it resides on if used as a containment
  3. FolderModel filters out items not on the current screen (if used as a containment)
  4. FolderModel adds mapping for the newly appeared files. The new files will go to the registered screen having the smallest id. This also means by default all files appear on the screen with the smallest id.
  5. url/screen mapping is stored in the configuration of each folder view applet. This means duplication of the information, and although they should be in sync unless manually modified, the logic is that the last view's mapping option is used.
  6. When removing a screen, the list of items from the removed screen is stored and items get moved to the first screen
  7. When a screen is added back, the items are moved back there based on the above list

So far missing:

  • correct handling of D&D between folderviews on different screens
  • forgetting the saved position from a removed screen if the items are reorganized on the primary (visible) screen

Depends on D8566
Depends on D8567

Diff Detail

Repository
R119 Plasma Desktop
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
There are a very large number of changes, so older changes are hidden. Show Older Changes
amantia added inline comments.Nov 1 2017, 2:53 PM
containments/desktop/plugins/folder/screenmapper.cpp
98

Done, but as in the other cases, this should be called only once.

amantia edited the summary of this revision. (Show Details)Nov 1 2017, 2:53 PM
ngraham added a subscriber: ngraham.Nov 1 2017, 3:14 PM

The code depends on:
https://phabricator.kde.org/D8566
https://phabricator.kde.org/D8567

The correct way to write this is:

Depends on D8566
Depends on D8567

That way, those patches will be automatically added to the "stack" and those patches will be required first before this can be committed.

mwolff added inline comments.Nov 1 2017, 3:24 PM
containments/desktop/plugins/folder/foldermodel.cpp
1683

an assert would be valid in such a scenario

1716

then add an Q_ASSERT(!m_appletInterface), this documents your intent and does not pollute the code

containments/desktop/plugins/folder/screenmapper.cpp
98

use an assert then

mwolff added a comment.Nov 1 2017, 3:28 PM

small nits, plus the asserts from the previous review. otherwise lgtm - the plasma people should chime in

containments/desktop/plugins/folder/foldermodel.cpp
1324

double spaces after =

1688

remove {, you don't use them above either

amantia updated this revision to Diff 21711.Nov 1 2017, 4:06 PM

Added unit test for ScreenMapper and improve the code to cover all the cases tested.
Added asserts instead of disconnects.
Change the ScreenMapper API completely to QString (from QUrl) as that is what is more natural (we store QStrings anyway in the config file).

mwolff requested changes to this revision.Nov 2 2017, 5:35 PM
mwolff added inline comments.
containments/desktop/plugins/folder/foldermodel.cpp
546

this should not be required, since addScreen calls screensChanged and that is connected to invalidateFilter already.

1688

this should also connect to screenMappingChanged. Once we handle DND across views, we will update the mapping to point to a different screen. As a reaction, both FolderModel instances (source and target of the DND action) need to update their filter. The easiest is via this signal.

This revision now requires changes to proceed.Nov 2 2017, 5:35 PM
amantia updated this revision to Diff 21837.Nov 3 2017, 2:28 PM
  • add unit tests for different scenarios of foldermodel and screenmapper usage on multiple screens
  • connect screenMappingChanged to invalidateFilter
  • as addMapping is called from withing filterAcceptRows, make it possible to emit screenMappingChanged in a delayed way and compressed to avoid

multiple and recursive calls to filterAcceptRows

  • do not call invalidateFilter from setScreen as it is called via screensChanged
  • store firstscreen usage per configured folderview path. This is needed if the two screens are configured to show different folders. There is a

unit test for it, but needs to be tested also visually (quick test shows some problems I need to debug before this is accepted).

amantia updated this revision to Diff 21838.Nov 3 2017, 2:34 PM

remove unimplemented method

mlaurent added inline comments.Nov 3 2017, 5:33 PM
containments/desktop/plugins/folder/autotests/foldermodeltest.cpp
61

m_folderDir = nullptr

285

remove extra space before +

anthonyfieroni added inline comments.
containments/desktop/plugins/folder/foldermodel.cpp
163–164

When QObject dies it's disconnected to all signal/slots. In this case if you want to not notify FolderModel you can use

m_screenMapper->disconnect(this);
1681–1682

{} braces even on one line, done it on all places.

containments/desktop/plugins/folder/screenmapper.cpp
33–37

When you use singleton it's better to make variable construction in one line

static ScreenMapper *s_instance = new ScreenMapper();
return s_instance;

or

static ScreenMapper s_instance;
return &s_instance;

In this way you don't have unwanted check for creation and variable at class scope.

amantia added inline comments.Nov 4 2017, 2:33 PM
containments/desktop/plugins/folder/foldermodel.cpp
163–164

Yes, I know, indeed this might be more clear.

containments/desktop/plugins/folder/screenmapper.cpp
33–37

Ok, although I don't see this commonly used in KDE (or Qt). If you really want, I can change it of course.

amantia updated this revision to Diff 22312.Nov 14 2017, 8:10 AM

Handle the case when the folder view's path changes on one of the desktops

amantia updated this revision to Diff 22313.Nov 14 2017, 8:14 AM
amantia marked 2 inline comments as done.

Implement changes requested by anthonyfieroni

amantia updated this revision to Diff 22342.Nov 14 2017, 1:36 PM
  • WIP: Multiscreen drag and drop support in folder view
amantia updated this revision to Diff 22344.Nov 14 2017, 1:44 PM

Restoring previous version overwritten by mistake.

mwolff added inline comments.Nov 15 2017, 9:23 AM
containments/desktop/plugins/folder/autotests/foldermodeltest.cpp
47

remove the init and cleanup if both are empty?

containments/desktop/plugins/folder/autotests/screenmappertest.cpp
37

remove if empty

46

dito

containments/desktop/plugins/folder/foldermodel.cpp
163

can you add a comment why this explicit disconnect is needed? is it b/c removeScreen would otherwise emit a signal that we'd try to handle but don't want to? otherwise the QObject dtor would disconnect us

containments/desktop/plugins/folder/foldermodel.h
294

ws only, unneeded change, can be unset

containments/desktop/plugins/folder/screenmapper.cpp
42

this is a pretty arbitrary timer, can you add a comment on why 100ms is better than going through the eventloop once via QMetaObject::invokeMethod with the delayed flag set?

53

should this maybe be QUrl::fromUserInput with a prefer local file flag set?

70

could be rewritten/simplified:

const auto it = std::min_element(...);
m_firstScreenForPath[path] = it == m_availableScreens.constEnd() ? -1 : *it;
83

so if path is empty, this adjusts all paths? can you add a comment on when this happens and what it's for?

99

these three lines are shared with above, introduce a helper function in an anon namespace for it: QUrl screenUrlForPath(const QString &path);

109

m_itemsOnDisabledScreensMap stores "names" from the m_screenItemMap, so I think this line here is wrong and should also use the proposed screenUrlForPath above, or QUrl::fromUserInput, no? Otherwise you may end up with relative urls for file paths?

125

again, seems like an empty path has a special meaning, can you document that somewhere please?

141

is name also a path?

151

dito

containments/desktop/plugins/folder/screenmapper.h
44

this needs to be documented, i.e. why and when is it required to distinguish between these signal behaviors?

amantia updated this revision to Diff 22387.Nov 15 2017, 11:09 AM
amantia marked 2 inline comments as done.

Fix for some of Milian's comments (rest later, need to move to different computer)

amantia added inline comments.Nov 15 2017, 11:11 AM
containments/desktop/plugins/folder/screenmapper.cpp
42

Done. InvokeMethod would not help, as the idea here is to get only one screenMappingChanged instead of e.g 50 when FolderModel gets the entries on startup.

amantia updated this revision to Diff 22428.Nov 16 2017, 8:14 AM
amantia marked 2 inline comments as done.

Add a code comment

containments/desktop/plugins/folder/screenmapper.cpp
109

I don't understand the problem. Yes m_itemsOnDisabledScreensMap is storing the names (well, paths) from m_screenItemMap. They will be in a format like file://foo or desktop://foo or similar. screenPathWithScheme is the base path for the screen which is either file://SOMEPATH (or some other scheme) or desktop:/ . The check is to see if the items from the disabled screen map are under this path or not. I don't see where we can get relative paths. I might miss something though, but I don't know what. :)

141

Basically yes, it is a path with scheme, but I renamed from "url" to "name" to be clear this is not a QUrl. I can change to path, although that is not exactly correct either, as the scheme is included.

amantia updated this revision to Diff 22434.Nov 16 2017, 10:45 AM

Remove unused var

mwolff added inline comments.Nov 16 2017, 10:45 AM
containments/desktop/plugins/folder/screenmapper.cpp
83

personally I'd make this code explicit. i.e. this here is somewhat harder to grasp I think (and also slower, due to the repeated lookups) to something like this:

const auto newFirstScreen = std::min_element(m_availableScreens.constBegin(), m_availableScreens.constEnd());
for (auto &screen : m_firstScreenForPath) {
    if (screen == screenId) {
        screen = newFirstScreen;
    }
}

potentially we also need to update m_screensPerPath though, which the current code doesn't do either. The branch above does write to pathIt though, is this missing here?

106

unused variable, remove

amantia updated this revision to Diff 22438.Nov 16 2017, 11:21 AM

Handle screen removal correctly:

  • adjust the first screen per path in a more efficient way
  • adjust the number of screens per path properly
mwolff requested changes to this revision.Nov 16 2017, 12:13 PM

some more nits, sorry for that ;-)

containments/desktop/plugins/folder/screenmapper.cpp
70

this could now be inlined below since it's only being used in one of the branches

85

this could be moved outside the branch and reused above, once the lambda is inlined

86

this should imo be a for loop to make it clear that it is iterating over all items (more ideomatic). Also, couldn't you use range-based for here even?

92

this is actually shared with above, so that could be in a lambda

This revision now requires changes to proceed.Nov 16 2017, 12:13 PM
amantia updated this revision to Diff 22444.Nov 16 2017, 12:19 PM

Some code reogranization per Milian's request

containments/desktop/plugins/folder/screenmapper.cpp
86

range based loop: I need access to both key and value

92

I don't see what can be extracted

mwolff accepted this revision.Nov 16 2017, 1:06 PM

lgtm from my side. Anyone from the plasma team care to chime in?

Fine with me.

Would be good if Eike could comment

[14:24] <kbroulik> andris: milian umm, how do I actually move files between screens?
[14:26] <kbroulik> the fact that you can actually resize it with Alt+right-click is a bug
[14:27] <milian> kbroulik: dnd, which is WIP
[14:28] <kbroulik> milian: okay because right now the screen-aware FV does not work at all. other than that I dont have any icons on my second screen anymore :)
[14:28] <kbroulik> you mean the "position files at drop event"?
[14:28] <milian> yes, but that is only one step
[14:29] <milian> I'm working on the second, more important one
[14:29] <milian> can you tell me what you mean by no icons on the second screen?
[14:29] <milian> did you have some on the second screen and by applying the patch they got moved to the first screen?
[14:29] <milian> i.e. some kind of config porting?
[14:29] <kbroulik> yes
[14:29] <milian> andris: ^ that is useful important feedback, we need to handle that somehow
[14:29] <milian> but kbroulik - how did you have icons on your second screen before?
[14:29] <kbroulik> milian: I have a FV on both screens, both pointing to desktop:/
[14:29] <milian> did you use the same folder?
[14:30] <kbroulik> yes
[14:30] <milian> then both used to show the same icons, no?
[14:30] <kbroulik> they don't
[14:30] <kbroulik> err
[14:30] <kbroulik> yes, they *used to*
[14:30] <kbroulik> so this is somewhat to be expected I guess
[14:30] <milian> right so nothing to be ported after all
[14:30] <kbroulik> yans: well, that's how it is
[14:30] <yans> So i just asking, kbroulik thx for info.
[14:30] <milian> what's missing is the DND to allow people to move files actually
[14:30] <milian> I'm working on that, keep getting sidetracked by other projects
[14:30] <milian> let me sit down on it again
[14:35] <kbroulik> milian: ah, okay, because right now DND is unchanged, ie. I drag files over and it says "would overwrite" :)
[14:36] <milian> yes that is broken as before
[14:36] <milian> I'm working on that and have a local WIP for that though
[14:36] <kbroulik> oki :)
[14:36] <kbroulik> so I cannot really comment on D8493 let's have Sho_ decide

so I guess we may need to keep this one open until the two follow-up DND patches are ready to allow this to be tested in full-depth

Ok, let's wait for Eike and for the DND patches to be ready.

hein added a comment.Nov 22 2017, 1:01 PM

Modulo above edge-casey comments it looks good to me.

containments/desktop/plugins/folder/foldermodel.cpp
1324

You're not testing m_screenMapper!=nullptr here.

1688

I know it's a very theoretical case, but you're not disconnecting from an old non-null ScreenMapper here.

You're also not calling invalidateFilter even though filterAcceptsRow uses the mapper. It's all a bit non-hygienic in the sense of "allow stuff to be set and reset in any order". Which can be somewhat important, especially as FolderModel doesn't inherit from QQmlParserStatus (hint: would be a great follow-up patch) and sometimes things can fall apart in config-dependent ways during initialization.

I'd appreciate a pass through this code for that concern for good Qt Quick hygiene.

amantia updated this revision to Diff 22795.Nov 23 2017, 6:43 AM
amantia marked 2 inline comments as done.

Handle Eike's comments

containments/desktop/plugins/folder/foldermodel.cpp
1688

As it ScreenMapper is a singleton, this will never happen, but nevertheless I added the disconnect.

hein accepted this revision.Nov 24 2017, 9:01 AM

@davidedmundson Any comments? If not, I will push this tomorrow.

This revision is now accepted and ready to land.Nov 28 2017, 7:25 AM
This revision was automatically updated to reflect the committed changes.