Merge lp:~jeremywootten/pantheon-files/fix-network-browsing into lp:~elementary-apps/pantheon-files/trunk

Proposed by Jeremy Wootten
Status: Merged
Approved by: Danielle Foré
Approved revision: 1704
Merged at revision: 1733
Proposed branch: lp:~jeremywootten/pantheon-files/fix-network-browsing
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 3997 lines (+1190/-604)
37 files modified
libcore/AbstractSlot.vala (+3/-1)
libcore/gof-callwhenready.vala (+3/-6)
libcore/gof-directory-async.vala (+171/-43)
libcore/gof-file.c (+187/-86)
libcore/gof-file.h (+5/-0)
libcore/marlin-file-operations.c (+35/-12)
libcore/marlin-file-operations.h (+3/-2)
libcore/marlin-trash-monitor.c (+0/-2)
libcore/marlin-undostack-manager.c (+7/-10)
libcore/marlin-undostack-manager.h (+2/-2)
libcore/pantheon-files-core-C.vapi (+18/-13)
libwidgets/LocationBar.vala (+47/-51)
plugins/contractor/plugin.vala (+5/-2)
plugins/network-places/plugin.vala (+0/-26)
plugins/pantheon-files-trash/plugin.vala (+2/-2)
src/Application.vala (+13/-0)
src/BookmarkList.vala (+4/-4)
src/DndHandler.vala (+1/-3)
src/MimeActions.vala (+8/-5)
src/MultiLineEditableLabel.vala (+3/-0)
src/View/AbstractDirectoryView.vala (+325/-144)
src/View/ColumnView.vala (+1/-1)
src/View/DiskRenderer.vala (+8/-3)
src/View/LocationBar.vala (+27/-21)
src/View/OverlayBar.vala (+2/-3)
src/View/PropertiesWindow.vala (+15/-9)
src/View/Resources.vala (+52/-0)
src/View/Sidebar.vala (+51/-44)
src/View/Slot.vala (+16/-17)
src/View/ViewContainer.vala (+101/-57)
src/View/Window.vala (+30/-10)
src/View/directory_view_popup.ui (+10/-0)
src/ZeitgeistManager.vala (+1/-1)
src/gtk+-3.0.vapi (+16/-1)
src/marlin-clipboard-manager.c (+16/-21)
src/marlin-clipboard-manager.h (+1/-1)
src/marlin.vapi (+1/-1)
To merge this branch: bzr merge lp:~jeremywootten/pantheon-files/fix-network-browsing
Reviewer Review Type Date Requested Status
Danielle Foré Approve
PerfectCarl Pending
Review via email: mp+243919@code.launchpad.net

Commit message

Fix several issues affecting use of Samba shares.

Description of the change

This branch fixes several issues preventing basic use Files for network files and folders using the smb protocol. It is not intended to fix any other protocol,

TO TEST:
Testing of network browsing branch.

Create public and a password-protected shares with read/write access on a Samba server (preferably other than the test machine).

 Open Entire Network then HOME: The Samba shares and Windows Network are displayed.
Navigate to the public share. A new entry in the sidebar (under Devices) appears with an eject icon.

Create a folder in the share. Rename the folder. Bookmark the folder by drag/drop onto the sidebar. Navigate away from the network using the sidebar. Click on the bookmarked network folder. Folder opens in view.

Navigate away from the network. Eject the public share using the sidebar. Click on the bookmarked network folder - the share remounts and the folder opens.

Select the bookmarked folder and delete it by pressing "Delete" or using the context menu (the "Trash" option is replaced by "Delete pernanently"). Click on the bookmark - the "folder does not exist" view is shown; the option to create the folder functions as expected.

Create a new file in the public share. Drag and drop it onto the new folder. The file is copied into the folder (This is because the Gdk suggested action in this situation is Gdk.DragAction.COPY). To move the file into the folder, drag while holding down the Shift key. To get a choice menu, drag using the secondary (right) button (The option to link is not supported on smb).

Bookmark a file in a samba share folder, using the context menu. Bookmark appears in sidebar. Navigate away from the folder. Click the bookmark. Folder opens in view with file selected.
Open a new window and navigate to a folder containing movable files. Drag and drop files and folders between this window and the public share.

Navigate to the password protected share - a dialog requesting entry of the password appears. On entry of the correct password the share is mounted and opens. File creation, renaming, bookmarking and drag/drop should work as for the public share.

Password can be remembered by selecting the required option in the dialog.
A bookmark to a folder on password protected shared folder will bring up the password dialog if the password has not been remembered. This does not work properly with bookmarked files on password protected shares and will fixed if possible in a different branch.

Type "network://" or "network:///" into pathbar - the Entire Network view opens.

Type "smb://" or "smb:///" into pathbar. Samba root location loads.

Type "smb://workgroup" into pathbar. Windows workgroup folder opens.

Set the "restore-tabs" preference to true. Navigate to a public smb share location and close the application. Re-open to application - the smb shared folder loads. Close the application. Log out of the smb share using a different app or otherwise. Re-open FIles - the smb share is remounted and the folder displayed.

Set the "restore-tabs" preference to true. Navigate to a password protected smb share location without saving the password, and close the application. Re-open to application - folder is displayed. Close the application. Log out of the smb share using a different app or otherwise. Re-open Files - the password dialog shows.

Navigation history buttons work as expected when history includes network folders.

Pathbar work as expected, except that network default locations and shares are displayed like folders (with corresponding breadcrumbs) but right clicking on the corresponding breadcrumb does not bring up a context menu as they are not true folders.

Right clicking on network default locations and shares in view brings up a truncated context menu showing only applicable actions (except that plugins may show unapplicable actions)

To post a comment you must log in.
Revision history for this message
PerfectCarl (name-is-carl) wrote :

Here are my remarks.

1) when files starts displaying network (because it was the last folder opened in the last session) it slows down the startup even if no network can be found
  Also it logs the following in the console:
[_LOG_LEVEL_WARN 13:55:55.176021] Couldn't connect to accessibility bus: Failed to connect to socket /tmp/dbus-c9DXGlcvF5: Connection refused

2) When I double click on Windows Network with no server, this is written to the console:
[_LOG_LEVEL_FATAL 14:03:35.490005] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 14:03:35.490060] Files will not function properly.
[_LOG_LEVEL_WARN 14:03:38.563686] gof-directory-async.vala:99: mount_mountable failed: Failed to retrieve share list from server: No such file or directory
[_LOG_LEVEL_WARN 14:03:38.579646] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted
[_LOG_LEVEL_FATAL 14:03:38.692921] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 14:03:38.693035] Files will not function properly.
[_LOG_LEVEL_WARN 14:03:38.715301] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted
[_LOG_LEVEL_WARN 14:03:38.716851] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted
[_LOG_LEVEL_FATAL 14:03:47.079300] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 14:03:47.079349] Files will not function properly.

3) The size of Windows Network is 0 bytes when there is no sever. Shouldn't it be left blank or named "0 server"?
http://i.imgur.com/zXgD1Fn.png

Revision history for this message
PerfectCarl (name-is-carl) wrote :

4) The "Windows network" has a property windows that let the user change the permission (chmod) of the item. Is this really useful/taken into account?

5) The right click menu of "Windows network" shows a "open in terminal" that does nothing (the terminal app is opened though)

6) The error message is not very helpful "invalid argument is very vague"
http://i.imgur.com/9BX6AAE.png

7) Put sample text in the field to help the user to fill out the form. At the moment empty fields are not very helpful.
http://i.imgur.com/SVMLJ3g.png
I would recommend :
  - server: 12.34.56.78
  - folder: nothing
  - Domain name: WORKGROUP

8) The port field must be hidden if it can't be used

9) I have a samba server on my local network but I haven't configured it in Files. Viewing the "Windows server" causes the application to be irresponsive.
The console displays this:
[_LOG_LEVEL_FATAL 14:33:06.441194] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 14:33:06.441324] Files will not function properly.
[_LOG_LEVEL_FATAL 14:33:12.247325] [GLib-GIO] g_app_info_get_all_for_type: assertion 'content_type != NULL' failed
[_LOG_LEVEL_FATAL 14:33:12.247420] Files will not function properly.
[_LOG_LEVEL_WARN 14:33:12.255183] plugin.vala:96: GDBus.Error:org.elementary.ContractorError.NoMimetypesGiven: No mimetypes were provided.
[_LOG_LEVEL_FATAL 14:33:14.680825] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 14:33:14.680882] Files will not function properly.
[_LOG_LEVEL_WARN 14:33:48.733310] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted
[_LOG_LEVEL_WARN 14:34:07.293536] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted
[_LOG_LEVEL_WARN 14:34:07.293807] ZeitgeistManager.vala:15: Fetching file info folder loggin to zeitgeist failed: The specified location is not mounted

After some time, files displays "network://smb:0/" which is empty
Going from a tab displaying local data to "network://smb:0/" is also slow.

10) Failing to connect to the server because of invalid details give one error message "Failed to mount Windows share". If I click to "continue" without changing anything, I get another message "Please verify your user details"
http://i.imgur.com/2sopzoJ.png
http://i.imgur.com/y16DOEH.png
   Note that the button label is changing. Not sure that this is a good idea

Revision history for this message
PerfectCarl (name-is-carl) wrote :

10) there is no way to edit the smb details once the share is mounted

11) once the share is mounted, it does not appear in the "Windows Network"

12) I have the following warnings in the console
[_LOG_LEVEL_WARN 14:49:50.850173] gof-directory-async.vala:193: directory monitor failed: Operation not supported by backend smb://192.168.0.10/sdcard/
[_LOG_LEVEL_WARN 14:49:55.875373] gof-directory-async.vala:193: directory monitor failed: Operation not supported by backend smb://192.168.0.10/sdcard/Download

13) For some reason, some folders can't be listed randomly: all I see is the spinning wheel. That error pops up randomly.
   Note: I'm using "Samba Filesharing for Android" as a samba server

Revision history for this message
PerfectCarl (name-is-carl) wrote :

14) the servers are not remembered in the "Windows network" meaning that I have to enter the details to the server every time

15) the local discovery doesn't work: my samba server that sits on my local network is not discovered

16) when I bookmark the "Windows network" and click on the newly created bookmark it says that folder does not exist (the path bar is "network://Windows Network/")

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Thanks for the comprehensive review, Carl. I think the scope of this branch will have to be restricted to very basic network browsing (essentially the 4 linked bugs and no regressions although the branch does start address some other issues).

I know there are a lot of other issues around the network browsing - some of which I don't know how to fix at the moment. I suspect some separate bugs with a decent bounty on will be required ...

I'll go through your review in detail and fix what I can.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Initial responses to Carl's review:
1) Should we not restore network folders?
2) The "fatal" errors are not really fatal. I'll see if I can quiet them. Do we need a message in the user interface?
3) This is outside the scope of the branch -and also happens on other File Managers (Thunar, Nautilus). Do we need "Properties" dialog for network locations?
4) Do we need "Properties" dialog for network locations?
5) Will not show "Open in Terminal" for network locations.
6) and 7) and 8) Server connection dialog is outside scope of branch
9) Could you give more explanation? I am not sure what steps you carried out.
10a) This is an issue with the connect to server dialog - outside scope of branch.
10b) Could you give more explanation? I am not sure what steps you carried out.
11) Could you give more explanation? Do you mean it doesn't appear in sidebar (in the right place)?
12) Warnings are due to failed attempt to connect a FileMonitor to a network folder that does not support it. It is expected to fail under these circumstances, so the warning is not really required. I'll change to debug.
13) This needs investigating - if you can identify which circumstances cause it please let me know. I'll try to reproduce. I think I saw it in earlier versions of the branch but not recently.
14) Do you mean servers are not remembered in the "Connect to Server" dialog? This is outside the scope of the branch
15) This suddenly stopped working for me too, seemingly after connecting a Windows machine to the network. But it was the same with Thunar and Nautilus. Fixed it by changing the name resolve order in etc/samba/samb.conf [global] section to "name resolve order = bcast host lmhosts wins". It appears to be a quirk/bug in Samba itself.
16) Confirmed. This is because "Windows Network" is not a real folder but the location bar thinks it is. I'll inhibit bookmarking of pseudo folders for now.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

I totally agree with you about keeping the scope tight.

I did report everything that I noticed so I can have your opinion about "bug" or "out of scope".
Not that I have your feedback, I filed the following reports.

3) This is outside the scope of the branch -and also happens on other File Managers (Thunar, Nautilus). Do we need "Properties" dialog for network locations?
-> https://bugs.launchpad.net/pantheon-files/+bug/1400731

6) and 7) and 8) Server connection dialog is outside scope of branch
-> https://bugs.launchpad.net/pantheon-files/+bug/1400735
-> https://bugs.launchpad.net/pantheon-files/+bug/1400738
-> https://bugs.launchpad.net/pantheon-files/+bug/1400740

14) Do you mean servers are not remembered in the "Connect to Server" dialog? This is outside the scope of the branch
-> https://bugs.launchpad.net/pantheon-files/+bug/1400734

All those issues can be found there : https://bugs.launchpad.net/pantheon-files/+bugs?field.tag=networking
(two older issues are not mine)

Revision history for this message
PerfectCarl (name-is-carl) wrote :

1) Should we not restore network folders?
Well I don't know if the network folders should be restored mounted or un-mounted (I would vote for un-mounted though - as it is the case for other drives).

What ever the solution, restoring network folders must be done more asynchronously not to stop the UI thread.

4) Do we need "Properties" dialog for network locations?
Yes very much so.
One because those information are entered by the user. Not offering a way to edit them is akin to data loss to me (not a catastrophic one, I agree).
Second because once I'm connected to the server, there is no way to check what I'm connected to - or how. Suppose I don't remember which server (or user) I entered, I'm stuck.

Again I'm not sure that this is in the scope of this merge proposal but this is very important to make network folders actually usable.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

A blueprint has been filed with suggestion to improve how Files handle network folders
https://blueprints.launchpad.net/pantheon-files/+spec/improve-network-folders

> 4)
See https://blueprints.launchpad.net/pantheon-files/+spec/remember-server-connections
and https://blueprints.launchpad.net/pantheon-files/+spec/files-ftp-bookmark

> 9) Could you give more explanation? I am not sure what steps you carried out.
Well I just set up a SAMBA server on my android phone and I thought I noticed that
Files were not as responsive.

I posited that it could have been due to some SAMBA discovery code that kicked in.
Of course, I might be very wrong.

> 10b) Could you give more explanation? I am not sure what steps you carried out.
Liked to 4) See my explanation in the comment right above

> 11) Could you give more explanation? Do you mean it doesn't appear in sidebar (in the right place)?
Well I would expect the "Windows network" to list all the all the servers that
are around the computer.
Isn't it the point of that item?

In my case, I just added a connection to a Windows server and the server isn't even
listed in that special "Windows network" folder.

Could you confirm me that this is out of scope?

Revision history for this message
PerfectCarl (name-is-carl) wrote :

>> 13) For some reason, some folders can't be listed randomly: all I see is the spinning wheel.
>> That error pops up randomly.
>> Note: I'm using "Samba Filesharing for Android" as a samba server
>
> 13) This needs investigating - if you can identify which circumstances cause it please let me
> know. I'll try to reproduce. I think I saw it in earlier versions of the branch but not recently.

For the time being I can't do anything because some time a folder can be listed. Some other time, the same folder can't be listed.

I can try to set up a a local folder that I would share via SAMBA and connect to it.
Maybe adding some debbuging trace could help me send you a useful report.

>> 15) the local discovery doesn't work: my samba server that sits
>> on my local network is not discovered
>
> 15) This suddenly stopped working for me too, seemingly after connecting a
> Windows machine to the network. But it was the same with Thunar and Nautilus. Fixed
> it by changing the name resolve order in etc/samba/samb.conf [global] section to "name
> resolve order = bcast host lmhosts wins". It appears to be a quirk/bug in Samba itself.

I may be very wrong but isn't something that must be handled one way or another? (either at the
distribution level, or by Files)

Note: the complete path is /etc/samba/smb.conf
My file doesn't have a "name resolver order" entry and has
# wins support = no
So I suppose that is equivalent to "wins support=yes"

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

9) There is certainly a certain delay involved in the discovery process, which will depend on your network setup, but I think this should only occur the first time the network is browsed. Display of network files may also be slower depending on the speed of the connection. The aim is that Files should at least be comparable to Nautilus in speed (but this may not yet always be so ...)
11) On my setup the "Windows Network" 'folder' contains one 'folder' "Workgroup" and this contains 'folders' for each of the Samba servers on the network (One Linux and one Windows). Within each of these are 'folders' for each of the shares on those servers. I am not sure why servers should be missing - unless one is configured not to broadcast its presence? The process of discovery of servers is handled outside Files. I can't think of anything in Files that would effect this.
15) I should have said that the line needs to be added to the [global] section. I agree this is not ideal, but fixing it is definitely outside the scope of this branch (and probably my expertise).

Revision history for this message
PerfectCarl (name-is-carl) wrote :

The smb.conf changes has been filed as lp:1401693

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Re 4) You seem to be referring to the "Connect Server" dialog whereas I was referring to the "Properties Window" (the blueprints you mention are for the connect server dialog). I have suppressed the Properties Window for network locations that are not real files, as at the moment it gives limited and in some cases incorrect information. We need a new way of displaying (and remembering) network connection properties.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

I can confirm that the delay in loading network views is significantly longer than before - and this is creating a bug in the column view where the new view is not filled unless you open it twice. I'll set this branch back to "In progress" while I try to address these issues.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

20) the mount buttons are cut off in the side bar.
http://i.imgur.com/VKoQ5OT.png

21) the application displays the following warnings:
[_LOG_LEVEL_WARN 13:41:07.172015] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
[_LOG_LEVEL_WARN 13:41:07.827718] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
[_LOG_LEVEL_WARN 13:41:07.834263] The specified location is not mounted [code 16]
[_LOG_LEVEL_WARN 13:41:08.686950] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
[_LOG_LEVEL_WARN 13:41:09.826451] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
[_LOG_LEVEL_WARN 13:41:09.832415] The specified location is not mounted [code 16]
[_LOG_LEVEL_WARN 13:41:11.089177] The specified location is not mounted [code 16]

22) when browsing a samba server that doesn't exist, the right click menu displayed is the one for local folders. Along with the new options :)
http://imgur.com/sOtOYwF

Revision history for this message
PerfectCarl (name-is-carl) wrote :

23) My samba domain (WORKGROUP) and samba share are compressable.
http://imgur.com/EFadkb6

Revision history for this message
PerfectCarl (name-is-carl) wrote :

24) when I try to connect to a SAMBA folder that doesn't require a password as guest, the "connect to server" dialog shows me an error asking me for a password. When I try to click the connect button another time (without changing anything or inputting a password) it works

Revision history for this message
PerfectCarl (name-is-carl) wrote :

25) Files let me connect as a non existing user to public share (shared as guest)
I don't know if that's normal but this weird.

I try to connect to smb://WORKGROUP;ZZZZ@192.168.56.101/shared/
Files asks me for a password. I enter a bogus password for this account that doesn't exist and Files displays the folder.
Is it because the SAMBA share is public? Is it because I'm already connected to it via a another tab (see the multiple connections to the same folder in the sidebar)

http://i.imgur.com/OYheNHK.png

Revision history for this message
PerfectCarl (name-is-carl) wrote :

26) when I click on the "CRAN-virtualbox" (my SAMBA server) in Files it doesn't display the shares. On the other hand, when I click on Windows Network/CRAN-virtualbox/ the shares are displayed.

Once the shares got displayed once, I can click on SAMBA server

27) I cannot create a folder in a SAMBA share while I have read/write permission.
The folders are created on the server but not displayed by Files and the following error message is displayed:
[_LOG_LEVEL_WARN 14:08:36.609732] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
[_LOG_LEVEL_WARN 14:08:48.812230] AbstractDirectoryView.vala:790: You do not have permission to rename this file
[_LOG_LEVEL_WARN 14:09:03.537883] AbstractDirectoryView.vala:790: You do not have permission to rename this file

http://i.imgur.com/zujvoOo.png

When I refresh the folder (Ctrl+R) the folder are displayed (and I can rename them)

Revision history for this message
PerfectCarl (name-is-carl) wrote :

28) the first time I open a share that I can write in but that has no files or folder, the right click menu does not show any option to create files.

http://i.imgur.com/4cAOUBi.png

After I work in that folder, the right click menu gets updated.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

29) When I drop a folder from a password protected SAMBA share to the bookmark side bar, the folder gets added. But when I unmount the share, the folder disappears from the sidebar.
When I re-mount the share the bookmark is not added

It works for public SAMBA share folder

Note: I can't do that with the SAMBA share. Only folder contained in the share. I wish I could.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

About 29) it works now. I think there is a tricky case when it doesn't (also at some point the app segfaults but I cannot reproduce it)
Here is the console output:

[_LOG_LEVEL_FATAL 14:24:10.441835] [GLib-GIO] g_file_equal: assertion 'G_IS_FILE (file1)' failed
[_LOG_LEVEL_FATAL 14:24:10.441885] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.442026] [GLib-GIO] g_file_get_uri: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.442070] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.442113] [GLib] g_string_append: assertion 'val != NULL' failed
[_LOG_LEVEL_FATAL 14:24:10.442141] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.443330] [GLib-GIO] g_file_is_native: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.443364] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.443407] [GLib-GIO] g_file_get_uri: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.443436] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.443476] [GLib-GIO] g_file_get_parse_name: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.443504] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.443544] marlin_places_sidebar_real_add_place: assertion 'tooltip != NULL' failed
[_LOG_LEVEL_FATAL 14:24:10.443573] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.517906] [GLib-GIO] g_file_is_native: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.518017] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.520824] [GLib-GIO] g_file_is_native: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.520870] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.520908] [GLib-GIO] g_file_get_uri: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.520932] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.520963] [GLib-GIO] g_file_get_parse_name: assertion 'G_IS_FILE (file)' failed
[_LOG_LEVEL_FATAL 14:24:10.520987] Files will not function properly.
[_LOG_LEVEL_FATAL 14:24:10.521017] marlin_places_sidebar_real_add_place: assertion 'tooltip != NULL' failed
[_LOG_LEVEL_FATAL 14:24:10.521043] Files will not function properly.
[_LOG_LEVEL_WARN 14:24:11.760355] gof-directory-async.vala:166: mount_mountable failed: Location is already mounted
Segmentation fault (core dumped)

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Thanks again Carl for your thorough testing!

20) Mount button truncation also occurs in trunk and is a bug in the sidebar, so will need a separate bug report.
21) I will set the mount_mountable warnings to "debug" so that will not normally appear.
22, 23 & 28) I will try to improve the relevance of the context menus. Its a trickier with network locations. The appearance of inappropriate plugin/contractor entries like "Compress" may have to be dealt with in the plugins/contractors themselves.
24, 25) These are issues with connect server dialog and outside the scope of this branch - I suggest they are added to your networking blueprint. It appears that Samba lets you connect to a public share using any credentials. Each connection with a different set of credentials appears as another entry in the sidebar but you can only distinguish them by looking at the tooltip. I haven't investigated whether there are any problems having multiple connections like this.
26, 27, 28, 29) I can confirm these (except for the segfault) but haven't found the reason yet.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

The latest revisions -

1) Silence non-critical mount_moutable warnings
2) Improve context menu relevance
3) Fix truncation of eject button
4) Less likely to fail to display servers and shares

The problems with bookmarking password protected samba shares and renaming files could not be reproduced. Please confirm still occurring in latest version.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

Hello,

All in all, it feels more stable and faster.
Congratulations!

I haven't tested everything yet but here's my feedback

26, 27, 28 are fixed (nice!)

22 is fixed
23 I added an issue for contractor : https://bugs.launchpad.net/elementaryos/+bug/1405878

30) I still have the following critical warnings:
[_LOG_LEVEL_FATAL 23:16:12.363828] gof_file_is_mountable: assertion 'file->info != NULL' failed
[_LOG_LEVEL_FATAL 23:16:12.363878] Files will not function properly.

31) is it expected that the permission tab in the properties dialog is not shown for files in SAMBA share whether I have read/write permissions or not?

32) is it on purpose that I can't add a samba server (\\CRAN-VIRTUALBOX) or even a samba share (\\CRAN-VIRTUALBOX\share) but only a folder (\\CRAN-VIRTUALBOX\share\folder) to the bookmark?
I find adding at a samba share useful.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Thanks Carl. I need to fix the conflict with current trunk now and make sure there are no regressions.

You are supposed to be able to bookmark a share (using the context menu), but I now notice that this only works if you open the share and right click on the background. If you display the server and right-click on the "folder" representing the share then you only get the minimal menu. I'll try to fix this.

I don't think there is any technical reason why a bookmark to a server should not work but at the moment it is not implemented. I'll try it.

I have deliberately not addressed the properties dialog issues in this branch. The whole issue of getting meta data from network files needs addressing. This branch is targeted mainly at browsing - i.e. connecting to and navigating network locations.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

> I have deliberately not addressed the properties dialog issues in this branch.
> The whole issue of getting meta data from network files needs addressing.
> This branch is targeted mainly at browsing - i.e. connecting to and navigating
> network locations.

Do you want me to file a general bug report for this?
Or is this already on your todo list?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

There are these related bugs:

https://bugs.launchpad.net/pantheon-files/+bug/1386335
https://bugs.launchpad.net/pantheon-files/+bug/1400731

but a more general bug, or series of bugs, requesting a more general overhaul of the properties dialog shown when looking at network entities (including servers), tailored to the particular protocol in use, could be filed. I could then put a bounty on the ones requiring significant effort to try and attract some assistance.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

The new revisions enable the bookmarking of network locations using the context menu and drag/drop.
Only mounted locations should be bookmarked.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

# Test with a SMB share from a luna VM (samba = 2:3.6.3-2ubuntu2.11)

40) the first time I connect to the SMB domain, all the shares are displayed with a red cross.
What is the meaning of the cross?
http://i.imgur.com/EmDkwJw.png

41) Not sure if that's a bug or a feature but when two windows are opened to the same shared folder, any operation done to one window is not synchronized to the other one.
Unlike how it is done to local folders.
Please confirm that this is done on purpose.

(Unmounting the share refreshes both windows though - neat!)

42) when the mouse moves over the samba icon in the sidebar, there is a fuzzy effect on the icon
https://ele.slack.com/files/carl/F039M70J0/files-network-icons.webm
Is this intended?

43) when displaying the property dialog for a shared folder, the free/total space of the current local partition is displayed.
Either display the remote free/total space of the remote share (if available) or either hide the bar

44) question: shouldn't be the tab named 'private' instead of '/' ?
http://i.imgur.com/laMnyGh.png

45) Can't create an archive in a folder where I can create files in.
Not sure if file-roller is to blame here or Files, but that's annoying.
(Same error with Nautilus though so I would say file-roller)

46) Create a shortcut to a file present on a share folder in the sidebar.
Unmount the share.
Click on the shorcut: you will be said that the file doesn't exist.
If you click on the file one more time, the file will become available.

Revision history for this message
PerfectCarl (name-is-carl) wrote :

47) message displayed in the console with a typo:
PropertiesWindow.vala:270: selection sizr update

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

40) I've not seen this, but it looks like a fall-back emblem for the "locked" emblem you get on all unwritable or unreadable files. Are you using the default icon-theme?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

41) This is a consequence of not being able to create a FileMonitor for remote folders. This is what alerts the other windows that something changed for local folders, either as a result of a Files action by another window or externally. Some kind of regular polling of the remote folders would have to be implemented for changes that were initiated outside of Files to be reflected in the Files windows, but it should be possible for internal actions to trigger an update of all Files windows. I'll look into it.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

42) That appears to be due to the icon being changed to the PRELIT state by the TreeView, which is normal behaviour. The fact it appears fuzzy is presumably a theme design issue?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

43) I am getting the correct information for the remote share displayed - which is a real remote machine. Could this be due to the fact you are running the share on a VM locally?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

44) This is because "private" is treated as a share name rather than a folder, so you are displaying the root folder of the share. However, I agree from the users point of view it would be less confusing to name the tab with the share name in this situation.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

45) Compression is offered through a contractor so this needs to be fixed (if possible) there. I think it outside the scope of this branch.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

46) I cannot reproduce this either with public folder or a password protected one. Could be a timing issue? If you just click once, is the share (eventually) remounted (even though the view shows "does not exist"?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

40) I am now getting the red crosses so it may be due to something merged from trunk. It is shown where the user has neither read nor write permissions. Read-only files are shown with a lock. So it looks like the permissions on the smb domain are not correctly determined. The properties window gives them as 000. As a short-term fix the emblems could be suppressed where permissions are 000.

46) I have reproduced this now - it happens for a file but not a folder. I'll try and fix.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

40) Emblems no longer shown on remote files.

46) There is no simple fix for this so I have prevented bookmarking of files on remote locations. When a bookmark is clicked for a file on an unmounted location, there is no simple way of knowing whether it is pointing to a file or folder so it is assumed to be a folder.

Revision history for this message
PerfectCarl (name-is-carl) wrote :
Download full text (4.0 KiB)

50)

It seems that launching files with bookmark that are unmounted produces the following output

10) when I launch the app, I have the following output.

[_LOG_LEVEL_FATAL 22:00:42.019477] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 22:00:42.019547] Files will not function properly.
[_LOG_LEVEL_FATAL 22:00:42.020752] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 22:00:42.020802] Files will not function properly.
[_LOG_LEVEL_FATAL 22:00:42.020901] [GLib-GIO] g_file_info_get_attribute_string: assertion 'G_IS_FILE_INFO (info)' failed
[_LOG_LEVEL_FATAL 22:00:42.020930] Files will not function properly.

Here's the full stacktrace:

#0 g_logv (log_domain=0x7ffff5ab1198 "GLib-GIO", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>,
    args=args@entry=0x7fffffffcf08) at /build/buildd/glib2.0-2.42.1/./glib/gmessages.c:1046
#1 0x00007ffff524ab32 in g_log (log_domain=log_domain@entry=0x7ffff5ab1198 "GLib-GIO",
    log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff529244d "%s: assertion '%s' failed")
    at /build/buildd/glib2.0-2.42.1/./glib/gmessages.c:1079
#2 0x00007ffff524ab59 in g_return_if_fail_warning (log_domain=log_domain@entry=0x7ffff5ab1198 "GLib-GIO",
    pretty_function=pretty_function@entry=0x7ffff5ab85c0 <__FUNCTION__.13927> "g_file_info_get_attribute_string",
    expression=expression@entry=0x7ffff5ab46df "G_IS_FILE_INFO (info)") at /build/buildd/glib2.0-2.42.1/./glib/gmessages.c:1088
#3 0x00007ffff5a086fc in g_file_info_get_attribute_string (info=0x0, attribute=0x7ffff7bcab49 "standard::target-uri")
    at /build/buildd/glib2.0-2.42.1/./gio/gfileinfo.c:887
#4 0x00007ffff7baf2d2 in gof_file_is_location_uri_default (file=0xc15e70)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/libcore/gof-file.c:201
#5 0x00007ffff7baf3ef in gof_file_is_root_network_folder (file=0xc15e70)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/libcore/gof-file.c:231
#6 0x00007ffff7baf359 in gof_file_is_remote_uri_scheme (file=0xc15e70)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/libcore/gof-file.c:218
#7 0x00007ffff7baf509 in gof_file_get_folder_icon_from_uri_or_path (file=0xc15e70)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/libcore/gof-file.c:257
#8 0x000000000042fa25 in marlin_bookmark_get_icon (self=self@entry=0xc174e0)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/src/Bookmark.vala:83
#9 0x000000000046e1a3 in marlin_places_sidebar_add_bookmark (index=7, bm=0xc174e0, iter=<synthetic pointer>, self=0x9fc520)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/src/View/Sidebar.vala:642
#10 marlin_places_sidebar_update_places (self=0x9fc520)
    at /home/cran/Documents/Projects/elementary/pantheon-files/fix-crash-when-trashing/src/View/Sidebar.vala:454
#11 0x00007ffff57761c8 in g_closure_invoke (closure=0xa08060, return_value=0x0, n_param_values=1, param_values=0x7fffffffd600,
...

Read more...

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Then main effects of the latest revisions are to stop thumbnailing remote files and to remove inappropriate context menu entries from workgroups.

Revision history for this message
Danielle Foré (danrabbit) wrote :

When attempting to merge trunk I get:
Text conflict in libcore/gof-directory-async.vala
Text conflict in libwidgets/LocationBar.vala
Text conflict in src/View/LocationBar.vala
3 conflicts encountered.

If we can get those conflicts solved, Cody and I would like to merge this within the next day or so

Revision history for this message
Danielle Foré (danrabbit) wrote :

Right click a breadcrumb in a local path > Open in New Tab > "Unable to mount folder"

Revision history for this message
Danielle Foré (danrabbit) wrote :

Something with the files open is broken. Clicking a local .jpg image gives me a "folder does not exist" error

Revision history for this message
Danielle Foré (danrabbit) wrote :

Probably related to the above error, sorting is now broken. Files doesn't seem to know the difference between folders and files.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

rev 1695 fixes 'Right click a breadcrumb in a local path > Open in New Tab > "Unable to mount folder"'

rev 1696 fixes 'Something with the files open is broken. Clicking a local .jpg image gives me a "folder does not exist" error' and 'sorting is now broken. Files doesn't seem to know the difference between folders and files.'

Revision history for this message
Danielle Foré (danrabbit) wrote :

Great, thanks for addressing those regressions! I'm noticing now, however, that my XDG folders don't seem to have special icons. They only have the default folder icon.

Revision history for this message
Danielle Foré (danrabbit) wrote :

Cody and I have been testing, so we're gonna merge. Thanks Jeremy!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libcore/AbstractSlot.vala'
--- libcore/AbstractSlot.vala 2014-11-01 11:27:38 +0000
+++ libcore/AbstractSlot.vala 2015-02-07 19:01:29 +0000
@@ -69,7 +69,9 @@
69 public virtual void zoom_in () {}69 public virtual void zoom_in () {}
70 public virtual void zoom_normal () {}70 public virtual void zoom_normal () {}
71 public virtual bool set_all_selected (bool all_selected) {return false;}71 public virtual bool set_all_selected (bool all_selected) {return false;}
72 public virtual Gtk.Widget get_content_box () {return content_box as Gtk.Widget;}72 public virtual Gtk.Widget get_content_box () {
73 return content_box as Gtk.Widget;
74 }
73 public virtual string? get_root_uri () {return directory.file.uri;}75 public virtual string? get_root_uri () {return directory.file.uri;}
74 public virtual string? get_tip_uri () {return null;}76 public virtual string? get_tip_uri () {return null;}
75 }77 }
7678
=== modified file 'libcore/gof-callwhenready.vala'
--- libcore/gof-callwhenready.vala 2014-11-21 19:24:45 +0000
+++ libcore/gof-callwhenready.vala 2015-02-07 19:01:29 +0000
@@ -36,10 +36,8 @@
36 if (gof.info == null) {36 if (gof.info == null) {
37 call_when_ready_list.prepend (gof);37 call_when_ready_list.prepend (gof);
38 query_info_async.begin (gof, file_ready);38 query_info_async.begin (gof, file_ready);
39 //message ("cwr %s", gof.uri);39 } else
40 } else {
41 count++;40 count++;
42 }
43 }41 }
4442
45 /* we didn't need to queue anything, all the infos were available */43 /* we didn't need to queue anything, all the infos were available */
@@ -51,7 +49,6 @@
5149
52 private void file_ready (GOF.File gof) {50 private void file_ready (GOF.File gof) {
53 gof.update ();51 gof.update ();
54 //message ("file ready %s", gof.uri);
55 }52 }
5653
57 /* TODO move this to GOF.File */54 /* TODO move this to GOF.File */
@@ -67,7 +64,7 @@
67 if (fqi != null)64 if (fqi != null)
68 fqi (gof);65 fqi (gof);
69 } catch (Error err) {66 } catch (Error err) {
70 warning ("query info failed, %s %s", err.message, gof.uri);67 debug ("query info failed, %s %s", err.message, gof.uri);
71 if (err is IOError.NOT_FOUND)68 if (err is IOError.NOT_FOUND)
72 gof.exists = false;69 gof.exists = false;
73 if (err is IOError.NOT_MOUNTED)70 if (err is IOError.NOT_MOUNTED)
@@ -76,7 +73,7 @@
7673
77 call_when_ready_list.remove (gof);74 call_when_ready_list.remove (gof);
78 if (call_when_ready_list == null) {75 if (call_when_ready_list == null) {
79 message ("call when ready OK - empty list");76 debug ("call when ready OK - empty list");
80 if (f != null)77 if (f != null)
81 f (files);78 f (files);
82 }79 }
8380
=== modified file 'libcore/gof-directory-async.vala'
--- libcore/gof-directory-async.vala 2015-01-26 10:32:04 +0000
+++ libcore/gof-directory-async.vala 2015-02-07 19:01:29 +0000
@@ -22,6 +22,7 @@
2222
23public class GOF.Directory.Async : Object {23public class GOF.Directory.Async : Object {
24 public GLib.File location;24 public GLib.File location;
25 public GLib.File? selected_file = null;
25 public GOF.File file;26 public GOF.File file;
26 public int icon_size = 32;27 public int icon_size = 32;
2728
@@ -64,7 +65,6 @@
6465
65 private unowned string gio_attrs {66 private unowned string gio_attrs {
66 get {67 get {
67 var scheme = location.get_uri_scheme ();
68 if (scheme == "network" || scheme == "computer" || scheme == "smb")68 if (scheme == "network" || scheme == "computer" || scheme == "smb")
69 return "*";69 return "*";
70 else70 else
@@ -72,14 +72,35 @@
72 }72 }
73 }73 }
7474
75 private string scheme;
76 public bool is_local;
77 public bool is_trash;
78 public bool has_trash_dirs;
79 public bool can_load;
80 private bool _is_ready;
81 public bool is_ready {
82 get { return _is_ready;}
83 private set {_is_ready = value;}
84 }
85
86 public bool is_cancelled {
87 get { return cancellable.is_cancelled (); }
88 }
89
75 private Async (GLib.File _file) {90 private Async (GLib.File _file) {
76 location = _file;91 location = _file;
77 file = GOF.File.get (location);92 file = GOF.File.get (location);
78 file.exists = true;
79 cancellable = new Cancellable ();93 cancellable = new Cancellable ();
8094 state = State.NOT_LOADED;
81 if (file.info == null)95 is_ready = false;
82 file.query_update ();96 can_load = true;
97
98 scheme = location.get_uri_scheme ();
99 is_trash = (scheme == "trash");
100 is_local = is_trash || (scheme == "file");
101
102 if (!prepare_directory ())
103 return;
83104
84 assert (directory_cache != null);105 assert (directory_cache != null);
85 directory_cache.insert (location, this);106 directory_cache.insert (location, this);
@@ -92,6 +113,113 @@
92 uri_contain_keypath_icons = "/icons" in file.uri || "/.icons" in file.uri;113 uri_contain_keypath_icons = "/icons" in file.uri || "/.icons" in file.uri;
93 }114 }
94115
116 /* This is also called when reloading the directory so that another attempt to connect to
117 * the network is made */
118 private bool prepare_directory () {
119 if (!get_file_info ()) {
120 is_ready = true;
121 /* local uris are deemed loadable even if they do not exist
122 * If they do not exist an opportunity will be given to create them */
123 can_load = is_local;
124 return false;
125 }
126
127 if (!file.is_folder () && !file.is_root_network_folder () && !try_parent ()) {
128 is_ready = true;
129 can_load = false;
130 return false;
131 }
132 return true;
133 }
134
135 private bool try_parent () {
136 if (file.is_connected) {
137 GLib.File? parent = location.get_parent ();
138 if (parent != null) {
139 file = GOF.File.get (parent);
140 selected_file = location.dup ();
141 location = parent;
142 if (get_file_info ())
143 return true;
144 }
145 }
146 return false;
147 }
148
149 private bool get_file_info () {
150 if (!is_local && !check_network ()) {
151 return false;
152 }
153
154 if (!file.ensure_query_info()) {
155 if (is_local || !file.is_connected)
156 return false;
157 }
158
159 can_load = true;
160 if (!is_local) {
161 mount_mountable.begin ((obj,res) => {
162 can_load = false;
163 try {
164 mount_mountable.end (res);
165 can_load = true;
166 } catch (Error e) {
167 debug ("mount_mountable failed: %s", e.message);
168
169 if (e is IOError.ALREADY_MOUNTED) {
170 can_load = true;
171 } else if (e is IOError.PERMISSION_DENIED ||
172 e is IOError.FAILED_HANDLED) {
173
174 permission_denied = true;
175 }
176 }
177 make_ready ();
178 });
179 } else
180 make_ready ();
181
182 return true;
183 }
184
185 public bool check_network () {
186 var net_mon = GLib.NetworkMonitor.get_default ();
187 var net_available = net_mon.get_network_available ();
188
189 if (!net_available) {
190 SocketConnectable? connectable = null;
191 try {
192 connectable = NetworkAddress.parse_uri (file.uri, 21);
193 }
194 catch (GLib.Error e) {}
195
196 if (connectable != null) {
197 try {
198 if (net_mon.can_reach (connectable))
199 return true;
200 }
201 catch (GLib.Error e) {}
202 }
203
204 return false;
205 }
206
207 return true;
208 }
209
210 private void make_ready () {
211 is_ready = true;
212 unowned GLib.List? trash_dirs = null;
213 file.mount = GOF.File.get_mount_at (location);
214
215 if (file.mount != null) {
216 file.is_mounted = true;
217 trash_dirs = Marlin.FileOperations.get_trash_dirs_for_mount (file.mount);
218 has_trash_dirs = (trash_dirs != null);
219 } else
220 has_trash_dirs = is_local;
221 }
222
95 private static void toggle_ref_notify (void* data, Object object, bool is_last) {223 private static void toggle_ref_notify (void* data, Object object, bool is_last) {
96 return_if_fail (object != null && object is Object);224 return_if_fail (object != null && object is Object);
97 if (is_last) {225 if (is_last) {
@@ -102,7 +230,6 @@
102 dir.remove_dir_from_cache ();230 dir.remove_dir_from_cache ();
103231
104 dir.remove_toggle_ref ((ToggleNotify) toggle_ref_notify);232 dir.remove_toggle_ref ((ToggleNotify) toggle_ref_notify);
105 } else {
106 }233 }
107 }234 }
108235
@@ -122,9 +249,11 @@
122 idle_consume_changes_id = 0;249 idle_consume_changes_id = 0;
123 }250 }
124251
252 if (file_hash != null)
253 file_hash.remove_all ();
254
125 monitor = null;255 monitor = null;
126 sorted_dirs = null;256 sorted_dirs = null;
127 file_hash.remove_all ();
128 files_count = 0;257 files_count = 0;
129 state = State.NOT_LOADED;258 state = State.NOT_LOADED;
130 }259 }
@@ -141,14 +270,11 @@
141 public void load (GOFFileLoadedFunc? file_loaded_func = null) {270 public void load (GOFFileLoadedFunc? file_loaded_func = null) {
142 cancellable.reset ();271 cancellable.reset ();
143 longest_file_name = "";272 longest_file_name = "";
144273 permission_denied = false;
145 if (state == State.LOADING)274 if (state == State.LOADING)
146 return;275 return;
147276
148 if (state != State.LOADED) {277 if (state != State.LOADED) {
149 /* clear directory info if it's not fully loaded */
150 if (state == State.LOADING)
151 clear_directory_info ();
152278
153 list_directory.begin (file_loaded_func);279 list_directory.begin (file_loaded_func);
154280
@@ -159,7 +285,8 @@
159 monitor.changed.connect (directory_changed);285 monitor.changed.connect (directory_changed);
160 } catch (IOError e) {286 } catch (IOError e) {
161 if (!(e is IOError.NOT_MOUNTED)) {287 if (!(e is IOError.NOT_MOUNTED)) {
162 warning ("directory monitor failed: %s %s", e.message, file.uri);288 /* Will fail for remote filesystems - not an error */
289 debug ("directory monitor failed: %s %s", e.message, file.uri);
163 }290 }
164 }291 }
165 }292 }
@@ -200,6 +327,8 @@
200 monitor_blocked = false;327 monitor_blocked = false;
201 monitor.changed.connect (directory_changed);328 monitor.changed.connect (directory_changed);
202 }329 }
330 if (!is_local)
331 need_reload ();
203 }332 }
204333
205 private void update_longest_file_name (GOF.File gof) {334 private void update_longest_file_name (GOF.File gof) {
@@ -208,11 +337,14 @@
208 }337 }
209338
210 public void load_hiddens () {339 public void load_hiddens () {
340 if (!can_load)
341 return;
342
211 if (state != State.LOADED) {343 if (state != State.LOADED) {
212 load ();344 load ();
213 } else {345 } else {
214 foreach (GOF.File gof in file_hash.get_values ()) {346 foreach (GOF.File gof in file_hash.get_values ()) {
215 if (gof != null && gof.info != null && gof.is_hidden) {347 if (gof != null && gof.is_hidden) {
216 if (track_longest_name)348 if (track_longest_name)
217 update_longest_file_name (gof);349 update_longest_file_name (gof);
218350
@@ -220,8 +352,8 @@
220 }352 }
221 }353 }
222 }354 }
223 if (!cancellable.is_cancelled ())355
224 done_loading ();356 done_loading ();
225 }357 }
226358
227 public void update_desktop_files () {359 public void update_desktop_files () {
@@ -229,45 +361,40 @@
229 if (gof != null && gof.info != null361 if (gof != null && gof.info != null
230 && (!gof.is_hidden || Preferences.get_default ().pref_show_hidden_files)362 && (!gof.is_hidden || Preferences.get_default ().pref_show_hidden_files)
231 && gof.is_desktop)363 && gof.is_desktop)
364
232 gof.update_desktop_file ();365 gof.update_desktop_file ();
233 }366 }
234 }367 }
235368
236 public async void mount_mountable () throws Error {369 public async void mount_mountable () throws Error {
237 debug ("mount_mountable %s", file.uri);
238
239 /* TODO pass GtkWindow *parent to Gtk.MountOperation */370 /* TODO pass GtkWindow *parent to Gtk.MountOperation */
240 var mount_op = new Gtk.MountOperation (null);371 var mount_op = new Gtk.MountOperation (null);
241372 yield location.mount_enclosing_volume (0, mount_op, cancellable);
242 if (file.file_type != FileType.MOUNTABLE)
243 yield location.mount_enclosing_volume (0, mount_op, cancellable);
244 else
245 yield location.mount_mountable (0, mount_op, cancellable);
246
247 file.is_mounted = true;
248 yield query_info_async (file, file_info_available);
249 }373 }
250374
251 private async void list_directory (GOFFileLoadedFunc? file_loaded_func = null) {375 private async void list_directory (GOFFileLoadedFunc? file_loaded_func = null) {
376 if (!can_load) {
377 state = State.NOT_LOADED;
378 return;
379 }
380
252 file.exists = true;381 file.exists = true;
253 files_count = 0;382 files_count = 0;
254 state = State.LOADING;383 state = State.LOADING;
255384
256 debug ("list directory %s", file.uri);
257
258 try {385 try {
259 var e = yield this.location.enumerate_children_async (gio_attrs, 0, 0, cancellable);386 var e = yield this.location.enumerate_children_async (gio_attrs, 0, 0, cancellable);
260 while (state == State.LOADING) {387 while (state == State.LOADING) {
261 var files = yield e.next_files_async (200, 0, cancellable);388 var files = yield e.next_files_async (200, 0, cancellable);
262
263 if (files == null)389 if (files == null)
264 break;390 break;
265391
266 bool show_hidden = Preferences.get_default ().pref_show_hidden_files;392 bool show_hidden = Preferences.get_default ().pref_show_hidden_files;
267393
268 foreach (var file_info in files) {394 foreach (var file_info in files) {
269 GLib.File loc = location.get_child ((string) file_info.get_name ());395 string uri = Path.build_filename (location.get_uri (), file_info.get_name ());
270 GOF.File gof = GOF.File.cache_lookup (loc);396 GLib.File loc = GLib.File.new_for_uri (uri);
397 GOF.File? gof = GOF.File.cache_lookup (loc);
271398
272 if (gof == null)399 if (gof == null)
273 gof = new GOF.File (loc, location);400 gof = new GOF.File (loc, location);
@@ -295,22 +422,21 @@
295 file.exists = true;422 file.exists = true;
296 state = State.LOADED;423 state = State.LOADED;
297 } else {424 } else {
298 debug ("WARNING load() has been called again before LOADING finished");425 warning ("WARNING load() has been called again before LOADING finished");
299 return;426 return;
300 }427 }
301 } catch (Error err) {428 } catch (Error err) {
302 warning ("%s %s", err.message, file.uri);429 warning ("Listing directory error: %s %s", err.message, file.uri);
303 state = State.NOT_LOADED;430 state = State.NOT_LOADED;
304431
305 if (err is IOError.NOT_FOUND || err is IOError.NOT_DIRECTORY)432 if (err is IOError.NOT_FOUND || err is IOError.NOT_DIRECTORY)
306 file.exists = false;433 file.exists = false;
307
308 else if (err is IOError.PERMISSION_DENIED)434 else if (err is IOError.PERMISSION_DENIED)
309 permission_denied = true;435 permission_denied = true;
310
311 else if (err is IOError.NOT_MOUNTED)436 else if (err is IOError.NOT_MOUNTED)
312 file.is_mounted = false;437 file.is_mounted = false;
313 }438 }
439
314 if (file_loaded_func == null && !cancellable.is_cancelled ())440 if (file_loaded_func == null && !cancellable.is_cancelled ())
315 done_loading ();441 done_loading ();
316 }442 }
@@ -366,7 +492,7 @@
366492
367 gof.update ();493 gof.update ();
368494
369 if (gof.info != null && (!gof.is_hidden || Preferences.get_default ().pref_show_hidden_files))495 if ((!gof.is_hidden || Preferences.get_default ().pref_show_hidden_files))
370 file_added (gof);496 file_added (gof);
371497
372 if (!gof.is_hidden && gof.is_folder ()) {498 if (!gof.is_hidden && gof.is_folder ()) {
@@ -380,10 +506,6 @@
380 }506 }
381 }507 }
382508
383 private void file_info_available (GOF.File gof) {
384 gof.update ();
385 }
386
387 private void notify_file_changed (GOF.File gof) {509 private void notify_file_changed (GOF.File gof) {
388 query_info_async.begin (gof, changed_and_refresh);510 query_info_async.begin (gof, changed_and_refresh);
389 }511 }
@@ -549,7 +671,11 @@
549671
550 public static Async from_gfile (GLib.File file) {672 public static Async from_gfile (GLib.File file) {
551 /* Note: cache_lookup creates directory_cache if necessary */673 /* Note: cache_lookup creates directory_cache if necessary */
552 return cache_lookup (file) ?? new Async (file);674 Async? dir = cache_lookup (file);
675 if (dir != null && !dir.is_local)
676 dir = null;
677
678 return dir ?? new Async (file);
553 }679 }
554680
555 public static Async from_file (GOF.File gof) {681 public static Async from_file (GOF.File gof) {
@@ -578,7 +704,7 @@
578 cached_dir = directory_cache.lookup (file);704 cached_dir = directory_cache.lookup (file);
579705
580 if (cached_dir != null) {706 if (cached_dir != null) {
581 debug ("found cached dir %s\n", cached_dir.file.uri);707 debug ("found cached dir %s", cached_dir.file.uri);
582 if (cached_dir.file.info == null)708 if (cached_dir.file.info == null)
583 cached_dir.file.query_update ();709 cached_dir.file.query_update ();
584 }710 }
@@ -645,12 +771,11 @@
645 return sorted_dirs;771 return sorted_dirs;
646772
647 foreach (var gof in file_hash.get_values()) {773 foreach (var gof in file_hash.get_values()) {
648 if (gof.info != null && !gof.is_hidden && gof.is_folder ())774 if (!gof.is_hidden && gof.is_folder ())
649 sorted_dirs.prepend (gof);775 sorted_dirs.prepend (gof);
650 }776 }
651777
652 sorted_dirs.sort (GOF.File.compare_by_display_name);778 sorted_dirs.sort (GOF.File.compare_by_display_name);
653
654 return sorted_dirs;779 return sorted_dirs;
655 }780 }
656781
@@ -714,6 +839,9 @@
714 }839 }
715840
716 public void queue_load_thumbnails (int size) {841 public void queue_load_thumbnails (int size) {
842 if (!is_local)
843 return;
844
717 icon_size = size;845 icon_size = size;
718 if (this.state == State.LOADING)846 if (this.state == State.LOADING)
719 return;847 return;
720848
=== modified file 'libcore/gof-file.c'
--- libcore/gof-file.c 2015-01-16 23:04:51 +0000
+++ libcore/gof-file.c 2015-02-07 19:01:29 +0000
@@ -68,7 +68,6 @@
68}68}
6969
70const gchar *gof_file_get_thumbnail_path (GOFFile *file);70const gchar *gof_file_get_thumbnail_path (GOFFile *file);
71static GMount *get_mount_at (GFile *target);
7271
73static GIcon *72static GIcon *
74get_icon_user_special_dirs(char *path)73get_icon_user_special_dirs(char *path)
@@ -175,19 +174,6 @@
175 file->can_unmount = FALSE;174 file->can_unmount = FALSE;
176}175}
177176
178static gboolean
179gof_file_compare_uri_schemes (GOFFile *file, const char **schemes)
180{
181 int iterator;
182
183 for (iterator = 0; iterator < G_N_ELEMENTS (schemes); iterator++) {
184 if (g_file_has_uri_scheme (file->location, schemes[iterator]))
185 return TRUE;
186 }
187
188 return FALSE;
189}
190
191/**177/**
192 * gof_file_is_location_uri_default:178 * gof_file_is_location_uri_default:
193 *179 *
@@ -198,56 +184,130 @@
198static gboolean184static gboolean
199gof_file_is_location_uri_default (GOFFile *file)185gof_file_is_location_uri_default (GOFFile *file)
200{186{
187 g_return_val_if_fail (file->info != NULL, FALSE);
188 gboolean res;
189
201 const char *target_uri = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);190 const char *target_uri = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
202191
203 if (target_uri != NULL) {192 if (target_uri == NULL)
204 gchar **split = g_strsplit (target_uri, "/", 4);193 target_uri = file->uri;
205 if (split[3] == NULL || !strcmp (split[3], "")) {194
206 g_strfreev (split);195 gchar **split = g_strsplit (target_uri, "/", 4);
207 return TRUE;196 res = (split[3] == NULL || !strcmp (split[3], ""));
197 g_strfreev (split);
198
199 return res;
200}
201
202gboolean
203gof_file_is_mountable (GOFFile *file) {
204 g_return_val_if_fail (file->info != NULL, FALSE);
205 return g_file_info_get_file_type(file->info) == G_FILE_TYPE_MOUNTABLE;
206}
207
208guint
209get_number_of_uri_parts (GOFFile *file) {
210 const char *target_uri = NULL;
211 if (file->info != NULL)
212 target_uri = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
213
214 if (target_uri == NULL)
215 target_uri = file->uri;
216
217 gchar **split = g_strsplit (target_uri, "/", 6);
218 guint i, count;
219 count = 0;
220 for (i = 0; i < g_strv_length (split); i++) {
221 if (split [i][0] != NULL) {
222 count++;
208 }223 }
209 g_strfreev (split);224 }
210 }225 g_strfreev (split);
211226 return count;
212 return FALSE;227}
228
229gboolean
230gof_file_is_smb_share (GOFFile *file)
231{
232 gboolean res;
233 res = FALSE;
234
235 if (gof_file_is_smb_uri_scheme (file) || gof_file_is_network_uri_scheme (file)) {
236 res = get_number_of_uri_parts (file) == 3;
237 }
238
239 return res;
240}
241
242gboolean
243gof_file_is_smb_server (GOFFile *file)
244{
245 gboolean res;
246 res = FALSE;
247
248 if (gof_file_is_smb_uri_scheme (file) || gof_file_is_network_uri_scheme (file)){
249 res = get_number_of_uri_parts (file) == 2;
250 }
251
252 return res;
213}253}
214254
215gboolean255gboolean
216gof_file_is_remote_uri_scheme (GOFFile *file)256gof_file_is_remote_uri_scheme (GOFFile *file)
217{257{
218 if (gof_file_is_root_network_folder (file))258 if (gof_file_is_root_network_folder (file) || gof_file_is_other_uri_scheme (file))
219 return TRUE;259 return TRUE;
220
221 const char* SCHEMES[] = { "afp", "dav", "davs", "ftp", "sftp" };
222 return gof_file_compare_uri_schemes (file, SCHEMES);
223}260}
224261
225gboolean262gboolean
226gof_file_is_root_network_folder (GOFFile *file)263gof_file_is_root_network_folder (GOFFile *file)
227{264{
228 if (gof_file_is_network_uri_scheme (file))265 return (gof_file_is_network_uri_scheme (file) || gof_file_is_smb_server (file));
229 return TRUE;
230
231 return (gof_file_is_smb_uri_scheme (file) && gof_file_is_location_uri_default (file));
232}266}
233267
234gboolean268gboolean
235gof_file_is_network_uri_scheme (GOFFile *file)269gof_file_is_network_uri_scheme (GOFFile *file)
236{270{
237 const char* SCHEMES[] = { "network" };271 if (!G_IS_FILE (file->location))
238 return gof_file_compare_uri_schemes (file, SCHEMES);272 return TRUE;
273
274 return g_file_has_uri_scheme (file->location, "network");
239}275}
240276
241gboolean277gboolean
242gof_file_is_smb_uri_scheme (GOFFile *file)278gof_file_is_smb_uri_scheme (GOFFile *file)
243{279{
244 const char* SCHEMES[] = { "smb" };280 if (!G_IS_FILE (file->location))
245 return gof_file_compare_uri_schemes (file, SCHEMES);281 return TRUE;
246}282
247283 return g_file_has_uri_scheme (file->location, "smb");
248void gof_file_get_folder_icon_from_uri_or_path (GOFFile *file)284}
249{285
250 if (!file->is_hidden && file->uri != NULL && file->icon == NULL) {286gboolean
287gof_file_is_other_uri_scheme (GOFFile *file)
288{
289 GFile *loc = file->location;
290 if (!G_IS_FILE (file->location))
291 return TRUE;
292
293 gboolean res;
294
295 res = g_file_has_uri_scheme (loc, "ftp") ||
296 g_file_has_uri_scheme (loc, "sftp") ||
297 g_file_has_uri_scheme (loc, "afp") ||
298 g_file_has_uri_scheme (loc, "dav") ||
299 g_file_has_uri_scheme (loc, "davs");
300
301 return res;
302}
303
304void
305gof_file_get_folder_icon_from_uri_or_path (GOFFile *file)
306{
307 if (file->icon != NULL)
308 return;
309
310 if (!file->is_hidden && file->uri != NULL) {
251 char *path = g_filename_from_uri (file->uri, NULL, NULL);311 char *path = g_filename_from_uri (file->uri, NULL, NULL);
252 file->icon = get_icon_user_special_dirs(path);312 file->icon = get_icon_user_special_dirs(path);
253 _g_free0 (path);313 _g_free0 (path);
@@ -364,8 +424,10 @@
364 file->target_location = g_file_new_for_uri (target_uri);424 file->target_location = g_file_new_for_uri (target_uri);
365 gof_file_target_location_update (file);425 gof_file_target_location_update (file);
366426
367 if (file->file_type == G_FILE_TYPE_MOUNTABLE)427 if (file->file_type == G_FILE_TYPE_MOUNTABLE) {
368 file->mount = get_mount_at (file->target_location);428 file->mount = gof_file_get_mount_at (file->target_location);
429 file->is_mounted = (file->mount != NULL);
430 }
369 }431 }
370 }432 }
371433
@@ -457,10 +519,8 @@
457519
458 /* sizes */520 /* sizes */
459 gof_file_update_size (file);521 gof_file_update_size (file);
460
461 /* modified date */522 /* modified date */
462 file->formated_modified = gof_file_get_formated_time (file, G_FILE_ATTRIBUTE_TIME_MODIFIED);523 file->formated_modified = gof_file_get_formated_time (file, G_FILE_ATTRIBUTE_TIME_MODIFIED);
463
464 /* icon */524 /* icon */
465 if (file->is_directory) {525 if (file->is_directory) {
466 gof_file_get_folder_icon_from_uri_or_path (file);526 gof_file_get_folder_icon_from_uri_or_path (file);
@@ -486,25 +546,30 @@
486 file->permissions = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_MODE);546 file->permissions = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_MODE);
487 const char *owner = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_OWNER_USER);547 const char *owner = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_OWNER_USER);
488 const char *group = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_OWNER_GROUP);548 const char *group = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_OWNER_GROUP);
549
489 if (owner != NULL)550 if (owner != NULL)
490 file->owner = strdup (owner);551 file->owner = strdup (owner);
552
491 if (group != NULL)553 if (group != NULL)
492 file->group = strdup (group);554 file->group = strdup (group);
555
493 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_UNIX_UID)) {556 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_UNIX_UID)) {
494 file->uid = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_UID);557 file->uid = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_UID);
495 if (file->owner == NULL)558 if (file->owner == NULL)
496 file->owner = g_strdup_printf ("%d", file->uid);559 file->owner = g_strdup_printf ("%d", file->uid);
497 }560 }
561
498 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_UNIX_GID)) {562 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_UNIX_GID)) {
499 file->gid = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_GID);563 file->gid = g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_GID);
500 if (file->group == NULL)564 if (file->group == NULL)
501 file->group = g_strdup_printf ("%d", file->gid);565 file->group = g_strdup_printf ("%d", file->gid);
502 }566 }
503567
504 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT)) {568 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT))
505 file->can_unmount = g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT);569 file->can_unmount = g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT);
506 }570
507 gof_file_update_trash_info (file);571 gof_file_update_trash_info (file);
572
508 gof_file_update_emblem (file);573 gof_file_update_emblem (file);
509}574}
510575
@@ -551,7 +616,6 @@
551 if (flags & GOF_FILE_ICON_FLAGS_USE_THUMBNAILS616 if (flags & GOF_FILE_ICON_FLAGS_USE_THUMBNAILS
552 && file->flags == GOF_FILE_THUMB_STATE_LOADING) {617 && file->flags == GOF_FILE_THUMB_STATE_LOADING) {
553 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);618 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
554 //printf ("thumbnail loading\n");
555 } else {619 } else {
556 gicon = _g_object_ref0 (file->icon);620 gicon = _g_object_ref0 (file->icon);
557 }621 }
@@ -645,6 +709,14 @@
645709
646void gof_file_update_emblem (GOFFile *file)710void gof_file_update_emblem (GOFFile *file)
647{711{
712 /* Do not try to add emblems to network and remote files (except smb) - can cause blocking io*/
713 if (gof_file_is_other_uri_scheme (file) || gof_file_is_network_uri_scheme (file))
714 return;
715
716 /* Do not try to add emblems to smb shares either */
717 if (gof_file_is_smb_share (file))
718 return;
719
648 /* erase previous stored emblems */720 /* erase previous stored emblems */
649 if (file->emblems_list != NULL) {721 if (file->emblems_list != NULL) {
650 g_list_free (file->emblems_list);722 g_list_free (file->emblems_list);
@@ -654,6 +726,7 @@
654 if(plugins != NULL)726 if(plugins != NULL)
655 marlin_plugin_manager_update_file_info (plugins, file);727 marlin_plugin_manager_update_file_info (plugins, file);
656728
729
657 if(gof_file_is_symlink(file) || (file->is_desktop && file->target_gof))730 if(gof_file_is_symlink(file) || (file->is_desktop && file->target_gof))
658 {731 {
659 gof_file_add_emblem(file, "emblem-symbolic-link");732 gof_file_add_emblem(file, "emblem-symbolic-link");
@@ -670,10 +743,12 @@
670 else743 else
671 gof_file_add_emblem (file, "emblem-unreadable");744 gof_file_add_emblem (file, "emblem-unreadable");
672 }745 }
746
673 /* TODO update signal on real change */747 /* TODO update signal on real change */
674 //g_warning ("update emblem %s", file.uri);748 //g_warning ("update emblem %s", file.uri);
675 if (file->emblems_list != NULL)749 if (file->emblems_list != NULL)
676 gof_file_icon_changed (file);750 gof_file_icon_changed (file);
751
677}752}
678753
679void gof_file_add_emblem (GOFFile* file, const gchar* emblem)754void gof_file_add_emblem (GOFFile* file, const gchar* emblem)
@@ -694,13 +769,13 @@
694{769{
695 if (error != NULL)770 if (error != NULL)
696 {771 {
697 g_warning ("%s [code %d]\n", error->message, error->code);772 g_debug ("%s [code %d]\n", error->message, error->code);
698 g_clear_error (&error);773 g_clear_error (&error);
699 }774 }
700}775}
701776
702static GMount *777GMount *
703get_mount_at (GFile *target)778gof_file_get_mount_at (GFile *target)
704{779{
705 GVolumeMonitor *monitor;780 GVolumeMonitor *monitor;
706 GFile *root;781 GFile *root;
@@ -738,18 +813,21 @@
738 GFileInfo *info = NULL;813 GFileInfo *info = NULL;
739 GError *err = NULL;814 GError *err = NULL;
740815
741 info = g_file_query_info (file->location, GOF_FILE_GIO_DEFAULT_ATTRIBUTES,816 g_return_val_if_fail (G_IS_FILE (file->location), NULL);
742 0, NULL, &err);817
818 info = g_file_query_info (file->location, "*", 0, NULL, &err);
743819
744 if (err != NULL) {820 if (err != NULL) {
745 if (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED) {821 if (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED) {
746 file->is_mounted = FALSE;822 file->is_mounted = FALSE;
747 }823 } else if (err->code == G_IO_ERROR_NOT_FOUND
748 if (err->code == G_IO_ERROR_NOT_FOUND
749 || err->code == G_IO_ERROR_NOT_DIRECTORY) {824 || err->code == G_IO_ERROR_NOT_DIRECTORY) {
750 file->exists = FALSE;825 file->exists = FALSE;
826 } else if (err->code == G_IO_ERROR_TIMED_OUT) {
827 file->is_connected = FALSE;
751 }828 }
752 print_error (err);829
830 print_error (err); /* also frees error */
753 }831 }
754 return info;832 return info;
755}833}
@@ -853,6 +931,7 @@
853 /* assume the file is mounted by default */931 /* assume the file is mounted by default */
854 file->is_mounted = TRUE;932 file->is_mounted = TRUE;
855 file->exists = TRUE;933 file->exists = TRUE;
934 file->is_connected = TRUE;
856935
857 file->flags = 0;936 file->flags = 0;
858 file->pix_size = -1;937 file->pix_size = -1;
@@ -878,10 +957,8 @@
878#endif957#endif
879958
880 g_clear_object (&file->info);959 g_clear_object (&file->info);
881 if (file->location)960 _g_object_unref0 (file->location);
882 g_object_unref (file->location);961 _g_object_unref0 (file->directory);
883 if (file->directory)
884 g_object_unref (file->directory);
885 _g_free0 (file->uri);962 _g_free0 (file->uri);
886 _g_free0(file->basename);963 _g_free0(file->basename);
887 _g_free0(file->utf8_collation_key);964 _g_free0(file->utf8_collation_key);
@@ -889,8 +966,7 @@
889 _g_free0(file->format_size);966 _g_free0(file->format_size);
890 _g_free0(file->formated_modified);967 _g_free0(file->formated_modified);
891 _g_object_unref0 (file->icon);968 _g_object_unref0 (file->icon);
892 if (file->pix)969 _g_object_unref0 (file->pix);
893 g_object_unref (file->pix);
894 //g_clear_object (&file->pix);970 //g_clear_object (&file->pix);
895971
896 _g_free0 (file->custom_display_name);972 _g_free0 (file->custom_display_name);
@@ -1121,7 +1197,6 @@
1121 }1197 }
11221198
1123 result = gof_file_compare_for_sort_internal (file1, file2, directories_first, reversed);1199 result = gof_file_compare_for_sort_internal (file1, file2, directories_first, reversed);
1124 //g_message ("res %d %s %s\n", result, file1->name, file2->name);
11251200
1126 if (result == 0) {1201 if (result == 0) {
1127 switch (sort_type) {1202 switch (sort_type) {
@@ -1216,15 +1291,19 @@
1216{1291{
1217 g_return_val_if_fail (GOF_IS_FILE (file), FALSE);1292 g_return_val_if_fail (GOF_IS_FILE (file), FALSE);
12181293
1219 if (file->target_gof)1294 /* Take care not to create infinite loop */
1295 if (file->target_gof && !g_file_equal (file->location, file->target_gof->location))
1220 return gof_file_is_writable (file->target_gof);1296 return gof_file_is_writable (file->target_gof);
1297
1221 if (file->info == NULL)1298 if (file->info == NULL)
1222 return FALSE;1299 return FALSE;
1300
1223 if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {1301 if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {
1224 /* For some reason, the trash folder doesn't have this attribute defined.1302 /* Trash folder and network folders do not necessarily have this attribute defined.
1225 * The function must be forced to return TRUE if the folder in question1303 * The function must be forced to return TRUE in these cases. */
1226 * is the trash folder (since it is writable). */1304 if (strncmp (file->uri, "trash:///", 10) == 0 ||
1227 if (strncmp (file->uri, "trash:///", 10) == 0)1305 gof_file_is_smb_uri_scheme (file) ||
1306 gof_file_is_remote_uri_scheme (file))
1228 return TRUE;1307 return TRUE;
12291308
1230 return FALSE;1309 return FALSE;
@@ -1578,16 +1657,20 @@
1578 /* default to whatever GTK+ thinks for the suggested action */1657 /* default to whatever GTK+ thinks for the suggested action */
1579 suggested_action = gdk_drag_context_get_suggested_action (context);1658 suggested_action = gdk_drag_context_get_suggested_action (context);
15801659
1581 char *uri = g_file_get_uri (file_list->data);
1582 g_debug ("%s %s %s\n", G_STRFUNC, file->uri, uri);
1583 _g_free0 (uri);
1584
1585 /* check if we have a writable directory here or an executable file */1660 /* check if we have a writable directory here or an executable file */
1586 if (gof_file_is_folder (file) && gof_file_is_writable (file))1661 if (gof_file_is_folder (file) && gof_file_is_writable (file))
1587 {1662 {
1588 /* determine the possible actions */1663 /* determine the possible actions */
1589 actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);1664 actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
15901665
1666 char *scheme;
1667 scheme = g_file_get_uri_scheme (gof_file_get_target_location (file));
1668 /* do not allow symbolic links to remote filesystems */
1669 if (!g_str_has_prefix (scheme, "file"))
1670 actions &= ~(GDK_ACTION_LINK);
1671
1672 g_free (scheme);
1673
1591 /* cannot create symbolic links in the trash or copy to the trash */1674 /* cannot create symbolic links in the trash or copy to the trash */
1592 if (gof_file_is_trashed (file))1675 if (gof_file_is_trashed (file))
1593 actions &= ~(GDK_ACTION_COPY | GDK_ACTION_LINK);1676 actions &= ~(GDK_ACTION_COPY | GDK_ACTION_LINK);
@@ -1595,12 +1678,16 @@
1595 /* check up to 100 of the paths (just in case somebody tries to1678 /* check up to 100 of the paths (just in case somebody tries to
1596 * drag around his music collection with 5000 files).1679 * drag around his music collection with 5000 files).
1597 */1680 */
1681
1598 for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n)1682 for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n)
1599 {1683 {
1600 uri = g_file_get_uri (lp->data);1684 scheme = g_file_get_uri_scheme (lp->data);
1601 g_debug ("%s %s %s\n", G_STRFUNC, file->uri, uri);1685 if (!g_str_has_prefix (scheme, "file")) {
1602 _g_free0 (uri);1686 /* do not allow symbolic links from remote filesystems */
1687 actions &= ~(GDK_ACTION_LINK);
1688 }
16031689
1690 g_free (scheme);
1604 /* we cannot drop a file on itself */1691 /* we cannot drop a file on itself */
1605 if (G_UNLIKELY (g_file_equal (gof_file_get_target_location (file), lp->data)))1692 if (G_UNLIKELY (g_file_equal (gof_file_get_target_location (file), lp->data)))
1606 return 0;1693 return 0;
@@ -1649,21 +1736,18 @@
1649 && g_file_info_get_attribute_uint32 (ofile->info,1736 && g_file_info_get_attribute_uint32 (ofile->info,
1650 G_FILE_ATTRIBUTE_UNIX_UID) != effective_user_id))1737 G_FILE_ATTRIBUTE_UNIX_UID) != effective_user_id))
1651 {1738 {
1652 //printf ("%s default suggested action GDK_ACTION_COPY\n", G_STRFUNC);
1653 /* default to copy and get outa here */1739 /* default to copy and get outa here */
1654 suggested_action = GDK_ACTION_COPY;1740 suggested_action = GDK_ACTION_COPY;
1655 break;1741 break;
1656 }1742 }
1657 }1743 }
1658 //printf ("%s actions MOVE %d COPY %d suggested %d\n", G_STRFUNC, GDK_ACTION_MOVE, GDK_ACTION_COPY, suggested_action);
1659 }1744 }
1660 }1745 }
1661 else if (!gof_file_is_folder (file) && gof_file_is_executable (file))1746 else if (!gof_file_is_folder (file) && gof_file_is_executable (file))
1662 {1747 {
1663 /* determine the possible actions */1748 /* determine the possible actions */
1664 actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE);1749 actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE);
1665 }1750 } else
1666 else
1667 return 0;1751 return 0;
16681752
1669 /* determine the preferred action based on the context */1753 /* determine the preferred action based on the context */
@@ -1914,7 +1998,7 @@
1914 gfiles = gof_files_get_location_list (files);1998 gfiles = gof_files_get_location_list (files);
19151999
1916 succeed = g_app_info_launch (app_info, gfiles, G_APP_LAUNCH_CONTEXT (context), &error);2000 succeed = g_app_info_launch (app_info, gfiles, G_APP_LAUNCH_CONTEXT (context), &error);
1917 print_error (error);2001 print_error (error); /* also frees error */
19182002
1919 g_list_free_full (gfiles, (GDestroyNotify) eel_g_file_unref);2003 g_list_free_full (gfiles, (GDestroyNotify) eel_g_file_unref);
1920 g_object_unref (context);2004 g_object_unref (context);
@@ -2387,12 +2471,26 @@
2387gboolean2471gboolean
2388gof_file_is_folder (GOFFile *file)2472gof_file_is_folder (GOFFile *file)
2389{2473{
2390 /* TODO check */2474 /* TODO check this works for non-local files and other uri schemes*/
2391 if (file->is_directory)2475 if ((file->is_directory || gof_file_get_ftype (file) == NULL) && !gof_file_is_root_network_folder (file))
2392 return TRUE;2476 return TRUE;
2393 if (file->target_location != NULL2477
2394 && ( (file->file_type == G_FILE_TYPE_MOUNTABLE && g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT)) || (file->target_gof && file->target_gof->is_directory && gof_preferences_get_default ()->pref_interpret_desktop_files) ))2478 if (gof_file_is_smb_share (file))
2395 return TRUE;2479 return TRUE;
2480
2481 if (file->file_type == G_FILE_TYPE_MOUNTABLE &&
2482 file->info != NULL &&
2483 g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT))
2484
2485 return TRUE;
2486
2487 if (file->target_gof && file->target_gof->is_directory) {
2488 /* file->target_gof is directory */
2489 if (gof_preferences_get_default ()->pref_interpret_desktop_files ||
2490 gof_file_is_network_uri_scheme (file->target_gof))
2491
2492 return TRUE;
2493 }
23962494
2397 return FALSE;2495 return FALSE;
2398}2496}
@@ -2400,13 +2498,16 @@
2400const gchar *2498const gchar *
2401gof_file_get_ftype (GOFFile *file)2499gof_file_get_ftype (GOFFile *file)
2402{2500{
2403 g_return_val_if_fail (file->info != NULL, NULL);2501 if (file->info == NULL || gof_file_is_location_uri_default (file))
2502 return NULL;
24042503
2405 const char *ftype = NULL;2504 const char *ftype = NULL;
2406 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))2505 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
2407 return g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);2506 return g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2507
2408 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE))2508 if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE))
2409 ftype = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);2509 ftype = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
2510
2410 if (!g_strcmp0 (ftype, "application/octet-stream") && file->tagstype)2511 if (!g_strcmp0 (ftype, "application/octet-stream") && file->tagstype)
2411 return file->tagstype;2512 return file->tagstype;
24122513
24132514
=== modified file 'libcore/gof-file.h'
--- libcore/gof-file.h 2014-11-21 19:24:45 +0000
+++ libcore/gof-file.h 2015-02-07 19:01:29 +0000
@@ -94,6 +94,7 @@
94 int color;94 int color;
95 gboolean is_mounted;95 gboolean is_mounted;
96 gboolean exists;96 gboolean exists;
97 gboolean is_connected;
9798
98 gboolean has_permissions;99 gboolean has_permissions;
99 guint32 permissions;100 guint32 permissions;
@@ -222,6 +223,7 @@
222 gpointer callback_data);223 gpointer callback_data);
223void gof_file_set_thumb_state (GOFFile *file, GOFFileThumbState state);224void gof_file_set_thumb_state (GOFFile *file, GOFFileThumbState state);
224void gof_file_add_emblem(GOFFile* file, const gchar* emblem);225void gof_file_add_emblem(GOFFile* file, const gchar* emblem);
226GMount* gof_file_get_mount_at (GFile* target);
225227
226/* To provide a wrapper around g_file_get_uri (not sure it is really useful tough) */228/* To provide a wrapper around g_file_get_uri (not sure it is really useful tough) */
227#define gof_file_get_uri(obj) g_file_get_uri(obj->location)229#define gof_file_get_uri(obj) g_file_get_uri(obj->location)
@@ -256,6 +258,9 @@
256gboolean gof_file_is_root_network_folder (GOFFile *file);258gboolean gof_file_is_root_network_folder (GOFFile *file);
257gboolean gof_file_is_network_uri_scheme (GOFFile *file);259gboolean gof_file_is_network_uri_scheme (GOFFile *file);
258gboolean gof_file_is_smb_uri_scheme (GOFFile *file);260gboolean gof_file_is_smb_uri_scheme (GOFFile *file);
261gboolean gof_file_is_smb_share (GOFFile *file);
262gboolean gof_file_is_smb_server (GOFFile *file);
263gboolean gof_file_is_mountable (GOFFile *file);
259gboolean gof_file_thumb_can_frame (GOFFile *file);264gboolean gof_file_thumb_can_frame (GOFFile *file);
260265
261char *gof_file_get_display_target_uri (GOFFile *file);266char *gof_file_get_display_target_uri (GOFFile *file);
262267
=== modified file 'libcore/marlin-file-operations.c'
--- libcore/marlin-file-operations.c 2015-01-16 18:03:50 +0000
+++ libcore/marlin-file-operations.c 2015-02-07 19:01:29 +0000
@@ -2058,6 +2058,7 @@
20582058
2059 common = (CommonJob *)job;2059 common = (CommonJob *)job;
2060 common->io_job = io_job;2060 common->io_job = io_job;
2061
2061#ifdef ENABLE_TASKVIEW2062#ifdef ENABLE_TASKVIEW
2062 taskview_generic_set_state (TASKVIEW_GENERIC (job->common.tv_io), TASKVIEW_RUNNING);2063 taskview_generic_set_state (TASKVIEW_GENERIC (job->common.tv_io), TASKVIEW_RUNNING);
2063#else2064#else
@@ -2074,19 +2075,19 @@
2074 for (l = job->files; l != NULL; l = l->next) {2075 for (l = job->files; l != NULL; l = l->next) {
2075 file = l->data;2076 file = l->data;
20762077
2077 if (job->try_trash &&2078 if (job->try_trash && g_file_has_uri_scheme (file, "trash")) {
2078 g_file_has_uri_scheme (file, "trash")) {
2079 must_confirm_delete_in_trash = TRUE;2079 must_confirm_delete_in_trash = TRUE;
2080 to_delete_files = g_list_prepend (to_delete_files, file);2080 to_delete_files = g_list_prepend (to_delete_files, file);
2081 } else if (can_delete_without_confirm (file)) {2081 } else if (can_delete_without_confirm (file)) {
2082 to_delete_files = g_list_prepend (to_delete_files, file);2082 to_delete_files = g_list_prepend (to_delete_files, file);
2083 } else {2083 } else {
2084 if (job->try_trash) {2084 if (job->try_trash &&
2085 !g_file_has_uri_scheme (file, "smb")) {
2085 to_trash_files = g_list_prepend (to_trash_files, file);2086 to_trash_files = g_list_prepend (to_trash_files, file);
2086 } else {2087 } else {
2087 must_confirm_delete = TRUE;2088 must_confirm_delete = TRUE;
2088 to_delete_files = g_list_prepend (to_delete_files, file);2089 to_delete_files = g_list_prepend (to_delete_files, file);
2089 }2090 }
2090 }2091 }
2091 }2092 }
20922093
@@ -2153,14 +2154,11 @@
2153 inhibit_power_manager ((CommonJob *)job, _("Deleting Files"));2154 inhibit_power_manager ((CommonJob *)job, _("Deleting Files"));
2154 }2155 }
21552156
2156 // Start UNDO-REDO
2157 if (try_trash && !marlin_undo_manager_is_undo_redo (marlin_undo_manager_instance())) {2157 if (try_trash && !marlin_undo_manager_is_undo_redo (marlin_undo_manager_instance())) {
2158 job->common.undo_redo_data = marlin_undo_manager_data_new (MARLIN_UNDO_MOVETOTRASH, g_list_length(files));2158 job->common.undo_redo_data = marlin_undo_manager_data_new (MARLIN_UNDO_MOVETOTRASH, g_list_length(files));
2159 //undotest usefull ??
2160 GFile* src_dir = g_file_get_parent (files->data);2159 GFile* src_dir = g_file_get_parent (files->data);
2161 marlin_undo_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);2160 marlin_undo_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
2162 }2161 }
2163 // End UNDO-REDO
21642162
2165 g_io_scheduler_push_job (delete_job,2163 g_io_scheduler_push_job (delete_job,
2166 job,2164 job,
@@ -4353,6 +4351,10 @@
4353 &error);4351 &error);
4354 }4352 }
43554353
4354 /* NOTE Result is false if file being moved is a folder and the target is on a Samba share even if
4355 * the file is successfully copied, so the change will not be notified to the view.
4356 * The view will need to be refreshed anyway */
4357
4356 if (res) {4358 if (res) {
4357 transfer_info->num_files ++;4359 transfer_info->num_files ++;
4358 report_copy_progress (copy_job, source_info, transfer_info);4360 report_copy_progress (copy_job, source_info, transfer_info);
@@ -4579,8 +4581,9 @@
4579 g_error_free (error);4581 g_error_free (error);
4580 goto out;4582 goto out;
4581 }4583 }
4582 primary = f (_("There was an Error while copying \"%s\"."), g_file_get_uri (src));4584
4583 secondary = f (_("There was an error copying the file into %s."), g_file_get_uri (dest_dir));4585 primary = f (_("Cannot copy \"%B\" here."), src);
4586 secondary = f (_("There was an error copying the file into %B."), dest_dir);
4584 details = error->message;4587 details = error->message;
45854588
4586 response = run_warning (job,4589 response = run_warning (job,
@@ -5466,9 +5469,15 @@
5466 not_local = FALSE;5469 not_local = FALSE;
54675470
5468 path = get_abs_path_for_symlink (src);5471 path = get_abs_path_for_symlink (src);
5469 if (path == NULL) {5472 char *scheme;
5473 scheme = g_file_get_uri_scheme (src);
5474
5475 if (path == NULL || !g_str_has_prefix (scheme, "file"))
5470 not_local = TRUE;5476 not_local = TRUE;
5471 } else if (g_file_make_symbolic_link (dest,5477
5478 g_free (scheme);
5479
5480 if (!not_local && g_file_make_symbolic_link (dest,
5472 path,5481 path,
5473 common->cancellable,5482 common->cancellable,
5474 &error)) {5483 &error)) {
@@ -5478,6 +5487,7 @@
5478 // End UNDO-REDO5487 // End UNDO-REDO
54795488
5480 g_free (path);5489 g_free (path);
5490
5481 if (debuting_files) {5491 if (debuting_files) {
5482 g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE));5492 g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE));
5483 }5493 }
@@ -5946,7 +5956,7 @@
5946 GFile *target_dir,5956 GFile *target_dir,
5947 GdkDragAction copy_action,5957 GdkDragAction copy_action,
5948 GtkWidget *parent_view,5958 GtkWidget *parent_view,
5949 gpointer done_callback,5959 GCallback done_callback,
5950 gpointer done_callback_data)5960 gpointer done_callback_data)
5951{5961{
5952 GList *p;5962 GList *p;
@@ -5981,6 +5991,19 @@
5981 }5991 }
59825992
5983 if (copy_action == GDK_ACTION_COPY) {5993 if (copy_action == GDK_ACTION_COPY) {
5994 if (g_file_has_uri_scheme (target_dir, "trash")) {
5995 char *primary = f (_("Cannot copy into trash."));
5996 char *secondary = f (_("It is not permitted to copy files into the trash"));
5997 eel_show_error_dialog (primary,
5998 secondary,
5999 parent_window);
6000
6001 if (done_callback != NULL)
6002 ((MarlinDeleteCallback)done_callback) (TRUE, done_callback_data);
6003
6004 return;
6005 }
6006
5984 /* done_callback is (or should be) a CopyCallBack or null in this case */6007 /* done_callback is (or should be) a CopyCallBack or null in this case */
5985 src_dir = g_file_get_parent (files->data);6008 src_dir = g_file_get_parent (files->data);
5986 if (target_dir == NULL ||6009 if (target_dir == NULL ||
59876010
=== modified file 'libcore/marlin-file-operations.h'
--- libcore/marlin-file-operations.h 2015-01-07 09:11:24 +0000
+++ libcore/marlin-file-operations.h 2015-02-07 19:01:29 +0000
@@ -33,7 +33,8 @@
33typedef void (* MarlinCreateCallback) (GFile *new_file,33typedef void (* MarlinCreateCallback) (GFile *new_file,
34 gpointer callback_data);34 gpointer callback_data);
35typedef void (* MarlinOpCallback) (gpointer callback_data);35typedef void (* MarlinOpCallback) (gpointer callback_data);
36typedef void (* MarlinDeleteCallback) (gboolean user_cancel, gpointer callback_data);36typedef void (* MarlinDeleteCallback) (gboolean user_cancel,
37 gpointer callback_data);
37typedef void (* MarlinMountCallback) (GVolume *volume,38typedef void (* MarlinMountCallback) (GVolume *volume,
38 GObject *callback_data_object);39 GObject *callback_data_object);
39typedef void (* MarlinUnmountCallback) (gpointer callback_data);40typedef void (* MarlinUnmountCallback) (gpointer callback_data);
@@ -130,7 +131,7 @@
130 GFile *target_dir,131 GFile *target_dir,
131 GdkDragAction copy_action,132 GdkDragAction copy_action,
132 GtkWidget *parent_view,133 GtkWidget *parent_view,
133 gpointer done_callback,134 GCallback done_callback,
134 gpointer done_callback_data);135 gpointer done_callback_data);
135136
136void marlin_file_operations_move (GList *files,137void marlin_file_operations_move (GList *files,
137138
=== modified file 'libcore/marlin-trash-monitor.c'
--- libcore/marlin-trash-monitor.c 2013-12-28 12:07:41 +0000
+++ libcore/marlin-trash-monitor.c 2015-02-07 19:01:29 +0000
@@ -131,7 +131,6 @@
131schedule_update_info (MarlinTrashMonitor *trash_monitor)131schedule_update_info (MarlinTrashMonitor *trash_monitor)
132{132{
133 GFile *location;133 GFile *location;
134
135 location = g_file_new_for_uri (MARLIN_TRASH_URI);134 location = g_file_new_for_uri (MARLIN_TRASH_URI);
136135
137 g_file_query_info_async (location,136 g_file_query_info_async (location,
@@ -150,7 +149,6 @@
150 gpointer user_data)149 gpointer user_data)
151{150{
152 MarlinTrashMonitor *trash_monitor;151 MarlinTrashMonitor *trash_monitor;
153
154 trash_monitor = MARLIN_TRASH_MONITOR (user_data);152 trash_monitor = MARLIN_TRASH_MONITOR (user_data);
155153
156 schedule_update_info (trash_monitor);154 schedule_update_info (trash_monitor);
157155
=== modified file 'libcore/marlin-undostack-manager.c'
--- libcore/marlin-undostack-manager.c 2013-08-10 20:20:23 +0000
+++ libcore/marlin-undostack-manager.c 2015-02-07 19:01:29 +0000
@@ -185,8 +185,7 @@
185static void undo_redo_done_rename_callback (GOFFile * file,185static void undo_redo_done_rename_callback (GOFFile * file,
186 GFile * result_location, GError * error, gpointer callback_data);186 GFile * result_location, GError * error, gpointer callback_data);
187187
188static void undo_redo_done_delete_callback (GHashTable *debuting_uris,188static void undo_redo_done_delete_callback (gboolean user_cancel, gpointer callback_data);
189 gboolean user_cancel, gpointer callback_data);
190189
191static void undo_redo_done_create_callback (GFile * new_file,190static void undo_redo_done_create_callback (GFile * new_file,
192 gpointer callback_data);191 gpointer callback_data);
@@ -402,7 +401,8 @@
402void401void
403marlin_undo_manager_redo (MarlinUndoManager *manager,402marlin_undo_manager_redo (MarlinUndoManager *manager,
404 GtkWidget *parent_view,403 GtkWidget *parent_view,
405 MarlinUndoFinishCallback cb)404 MarlinUndoFinishCallback cb,
405 gpointer callback_data)
406{406{
407 GList *uris;407 GList *uris;
408 GOFFile *file;408 GOFFile *file;
@@ -486,8 +486,6 @@
486 g_object_unref (fparent);486 g_object_unref (fparent);
487 break;487 break;
488 case MARLIN_UNDO_MOVETOTRASH:488 case MARLIN_UNDO_MOVETOTRASH:
489 //amtest
490 //printf ("MARLIN_UNDO_MOVETRASH\n");
491 if (g_hash_table_size (action->trashed) > 0) {489 if (g_hash_table_size (action->trashed) > 0) {
492 GList *uri_to_trash = g_hash_table_get_keys (action->trashed);490 GList *uri_to_trash = g_hash_table_get_keys (action->trashed);
493 uris = uri_list_to_gfile_list (uri_to_trash);491 uris = uri_list_to_gfile_list (uri_to_trash);
@@ -553,7 +551,8 @@
553void551void
554marlin_undo_manager_undo (MarlinUndoManager *manager,552marlin_undo_manager_undo (MarlinUndoManager *manager,
555 GtkWidget *parent_view,553 GtkWidget *parent_view,
556 MarlinUndoFinishCallback cb)554 MarlinUndoFinishCallback cb,
555 gpointer done_callback_data)
557{556{
558 GList *uris = NULL;557 GList *uris = NULL;
559 GHashTable *files_to_restore;558 GHashTable *files_to_restore;
@@ -828,7 +827,6 @@
828{827{
829 GFileInfo *info;828 GFileInfo *info;
830 guint64 mtime;829 guint64 mtime;
831
832 info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,830 info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
833 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, FALSE, NULL);831 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, FALSE, NULL);
834 if (info == NULL) {832 if (info == NULL) {
@@ -1731,10 +1729,9 @@
17311729
1732/** ---------------------------------------------------------------- */1730/** ---------------------------------------------------------------- */
1733static void1731static void
1734undo_redo_done_delete_callback (GHashTable *1732undo_redo_done_delete_callback (gboolean user_cancel, gpointer callback_data)
1735 debuting_uris, gboolean user_cancel, gpointer callback_data)
1736{1733{
1737 undo_redo_done_transfer_callback (debuting_uris, callback_data);1734 undo_redo_done_transfer_callback (NULL, callback_data);
1738}1735}
17391736
1740/** ---------------------------------------------------------------- */1737/** ---------------------------------------------------------------- */
17411738
=== modified file 'libcore/marlin-undostack-manager.h'
--- libcore/marlin-undostack-manager.h 2013-08-10 20:20:23 +0000
+++ libcore/marlin-undostack-manager.h 2015-02-07 19:01:29 +0000
@@ -108,11 +108,11 @@
108108
109void109void
110marlin_undo_manager_undo (MarlinUndoManager* manager,110marlin_undo_manager_undo (MarlinUndoManager* manager,
111 GtkWidget *parent_view, MarlinUndoFinishCallback cb);111 GtkWidget *parent_view, MarlinUndoFinishCallback cb, gpointer done_callback_data);
112112
113void113void
114marlin_undo_manager_redo (MarlinUndoManager* manager,114marlin_undo_manager_redo (MarlinUndoManager* manager,
115 GtkWidget *parent_view, MarlinUndoFinishCallback cb);115 GtkWidget *parent_view, MarlinUndoFinishCallback cb, gpointer done_callback_data);
116116
117MarlinUndoActionData*117MarlinUndoActionData*
118marlin_undo_manager_data_new (MarlinUndoActionType type,118marlin_undo_manager_data_new (MarlinUndoActionType type,
119119
=== modified file 'libcore/pantheon-files-core-C.vapi'
--- libcore/pantheon-files-core-C.vapi 2015-01-16 18:08:07 +0000
+++ libcore/pantheon-files-core-C.vapi 2015-02-07 19:01:29 +0000
@@ -59,7 +59,7 @@
59 static unowned GLib.List<unowned GLib.File> get_trash_dirs_for_mount (GLib.Mount mount);59 static unowned GLib.List<unowned GLib.File> get_trash_dirs_for_mount (GLib.Mount mount);
60 static void empty_trash_dirs (Gtk.Window? parent_window, owned GLib.List<GLib.File> dirs);60 static void empty_trash_dirs (Gtk.Window? parent_window, owned GLib.List<GLib.File> dirs);
61 static void empty_trash (Gtk.Widget? widget);61 static void empty_trash (Gtk.Widget? widget);
62 static void copy_move (GLib.List<GLib.File> files, void* relative_item_points, GLib.File target_dir, Gdk.DragAction copy_action, Gtk.Widget? parent_view = null, void* done_callback = null, void* done_callback_data = null);62 static void copy_move (GLib.List<GLib.File> files, void* relative_item_points, GLib.File target_dir, Gdk.DragAction copy_action, Gtk.Widget? parent_view = null, GLib.Callback? done_callback = null, void* done_callback_data = null);
63 static void new_file (Gtk.Widget parent_view, Gdk.Point? target_point, string parent_dir, string? target_filename, string? initial_contents, int length, Marlin.CreateCallback? create_callback = null, void* done_callback_data = null);63 static void new_file (Gtk.Widget parent_view, Gdk.Point? target_point, string parent_dir, string? target_filename, string? initial_contents, int length, Marlin.CreateCallback? create_callback = null, void* done_callback_data = null);
64 static void new_file_from_template (Gtk.Widget parent_view, Gdk.Point? target_point, GLib.File parent_dir, string? target_filename, GLib.File template, Marlin.CreateCallback? create_callback = null, void* done_callback_data = null);64 static void new_file_from_template (Gtk.Widget parent_view, Gdk.Point? target_point, GLib.File parent_dir, string? target_filename, GLib.File template, Marlin.CreateCallback? create_callback = null, void* done_callback_data = null);
65 }65 }
@@ -70,7 +70,7 @@
70 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]70 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]
71 public delegate void CreateCallback (GLib.File new_file, void* callback_data);71 public delegate void CreateCallback (GLib.File new_file, void* callback_data);
72 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]72 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]
73 public delegate void CopyCallBack (GLib.HashTable<GLib.File, void*> debuting_uris, void* pointer);73 public delegate void CopyCallback (GLib.HashTable<GLib.File, void*> debuting_uris, void* pointer);
74 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]74 [CCode (cheader_filename = "marlin-file-operations.h", has_target = false)]
75 public delegate void DeleteCallback (bool user_cancel, void* callback_data);75 public delegate void DeleteCallback (bool user_cancel, void* callback_data);
76}76}
@@ -102,8 +102,8 @@
102102
103[CCode (cprefix = "Eel", lower_case_cprefix = "eel_", cheader_filename = "eel-stock-dialogs.h")]103[CCode (cprefix = "Eel", lower_case_cprefix = "eel_", cheader_filename = "eel-stock-dialogs.h")]
104namespace Eel {104namespace Eel {
105 public Gtk.Dialog show_warning_dialog (string primary_text, string secondary_text, Gtk.Window? parent);105 public unowned Gtk.Dialog show_warning_dialog (string primary_text, string secondary_text, Gtk.Window? parent);
106 public Gtk.Dialog show_error_dialog (string primary_text, string secondary_text, Gtk.Window? parent);106 public unowned Gtk.Dialog show_error_dialog (string primary_text, string secondary_text, Gtk.Window? parent);
107}107}
108108
109[CCode (cprefix = "Eel", lower_case_cprefix = "eel_", cheader_filename = "eel-fcts.h")]109[CCode (cprefix = "Eel", lower_case_cprefix = "eel_", cheader_filename = "eel-fcts.h")]
@@ -161,19 +161,17 @@
161 }161 }
162162
163 [CCode (cheader_filename = "marlin-undostack-manager.h")]163 [CCode (cheader_filename = "marlin-undostack-manager.h")]
164 public delegate void UndoFinishCallback (UndoManager manager, Gtk.Widget? w);164 public delegate void UndoFinishCallback (void *data);
165 /*public delegate void UndoFinishCallback (void *data);*/
166 /*public delegate void UndoFinishCallback ();*/
167165
168 [CCode (cheader_filename = "marlin-undostack-manager.h")]166 [CCode (cheader_filename = "marlin-undostack-manager.h")]
169 public abstract class UndoManager : GLib.Object167 public class UndoManager : GLib.Object
170 {168 {
171 public static UndoManager instance ();169 public static UndoManager instance ();
172170
173 public signal void request_menu_update (UndoMenuData data);171 public signal void request_menu_update (UndoMenuData data);
174172
175 public void undo (UndoFinishCallback? cb);173 public void undo (Gtk.Widget widget, UndoFinishCallback? cb);
176 public void redo (UndoFinishCallback? cb);174 public void redo (Gtk.Widget widget, UndoFinishCallback? cb);
177 }175 }
178176
179 [CCode (cheader_filename = "marlin-progress-info.h")]177 [CCode (cheader_filename = "marlin-progress-info.h")]
@@ -232,14 +230,16 @@
232230
233 public File(GLib.File location, GLib.File? dir);231 public File(GLib.File location, GLib.File? dir);
234 public static GOF.File @get(GLib.File location);232 public static GOF.File @get(GLib.File location);
235 public static GOF.File get_by_uri (string uri);233 public static GOF.File? get_by_uri (string uri);
236 public static File cache_lookup (GLib.File file);234 public static File cache_lookup (GLib.File file);
237 public static bool launch_files (GLib.List<GOF.File> files, Gdk.Screen screen, GLib.AppInfo app);235 public static bool launch_files (GLib.List<GOF.File> files, Gdk.Screen screen, GLib.AppInfo app);
238 public static void list_free (GLib.List<GOF.File> files);236 public static void list_free (GLib.List<GOF.File> files);
237 public static GLib.Mount? get_mount_at (GLib.File location);
239238
240 public void remove_from_caches ();239 public void remove_from_caches ();
241 public bool is_gone;240 public bool is_gone;
242 public GLib.File location;241 public GLib.File location;
242 public GLib.File target_location;
243 public GLib.File directory; /* parent directory location */243 public GLib.File directory; /* parent directory location */
244 public GLib.Icon? icon;244 public GLib.Icon? icon;
245 public GLib.List<string>? emblems_list;245 public GLib.List<string>? emblems_list;
@@ -267,14 +267,17 @@
267 public bool is_trashed();267 public bool is_trashed();
268 public bool is_writable ();268 public bool is_writable ();
269 public bool is_executable ();269 public bool is_executable ();
270 public bool is_mountable ();
270 public bool link_known_target;271 public bool link_known_target;
272 public bool is_smb_share ();
273 public bool is_smb_server ();
271 public uint flags;274 public uint flags;
272275
273 public Gdk.DragAction accepts_drop (GLib.List<GLib.File> file_list, Gdk.DragContext context, out Gdk.DragAction suggested_action_return);276 public Gdk.DragAction accepts_drop (GLib.List<GLib.File> file_list, Gdk.DragContext context, out Gdk.DragAction suggested_action_return);
274277
275 public unowned string get_display_name ();278 public unowned string get_display_name ();
276 public unowned GLib.File get_target_location ();279 public unowned GLib.File get_target_location ();
277 public unowned string get_ftype ();280 public unowned string? get_ftype ();
278 public string? get_formated_time (string attr);281 public string? get_formated_time (string attr);
279 public Gdk.Pixbuf get_icon_pixbuf (int size, bool forced_size, FileIconFlags flags);282 public Gdk.Pixbuf get_icon_pixbuf (int size, bool forced_size, FileIconFlags flags);
280 public void get_folder_icon_from_uri_or_path ();283 public void get_folder_icon_from_uri_or_path ();
@@ -290,7 +293,7 @@
290 public bool has_permissions;293 public bool has_permissions;
291 public uint32 permissions;294 public uint32 permissions;
292295
293 public void open_single (Gdk.Screen screen, GLib.AppInfo app_info);296 public void open_single (Gdk.Screen screen, GLib.AppInfo? app_info);
294 public void update ();297 public void update ();
295 public void update_type ();298 public void update_type ();
296 public void update_icon (int size);299 public void update_icon (int size);
@@ -304,6 +307,7 @@
304 public bool can_set_group ();307 public bool can_set_group ();
305 public bool can_set_permissions ();308 public bool can_set_permissions ();
306 public bool can_unmount ();309 public bool can_unmount ();
310 public GLib.Mount? mount;
307 public string get_permissions_as_string ();311 public string get_permissions_as_string ();
308 public bool launch (Gdk.Screen screen, GLib.AppInfo app);312 public bool launch (Gdk.Screen screen, GLib.AppInfo app);
309313
@@ -314,6 +318,7 @@
314 public bool is_root_network_folder ();318 public bool is_root_network_folder ();
315 public bool is_network_uri_scheme ();319 public bool is_network_uri_scheme ();
316 public bool is_smb_uri_scheme ();320 public bool is_smb_uri_scheme ();
321 public bool is_connected;
317322
318 public unowned string get_display_target_uri ();323 public unowned string get_display_target_uri ();
319324
320325
=== modified file 'libwidgets/LocationBar.vala'
--- libwidgets/LocationBar.vala 2015-01-26 10:59:26 +0000
+++ libwidgets/LocationBar.vala 2015-02-07 19:01:29 +0000
@@ -191,6 +191,7 @@
191 escape ();191 escape ();
192 return true;192 return true;
193 }193 }
194
194 return base.key_press_event (event);195 return base.key_press_event (event);
195 }196 }
196197
@@ -258,7 +259,7 @@
258 var el = get_element_from_coordinates ((int) event.x, (int) event.y);259 var el = get_element_from_coordinates ((int) event.x, (int) event.y);
259 if (el != null) {260 if (el != null) {
260 selected = elements.index_of (el);261 selected = elements.index_of (el);
261 var newpath = sanitise_path (get_path_from_element (el));262 var newpath = get_path_from_element (el);
262 path_changed (get_file_for_path (newpath));263 path_changed (get_file_for_path (newpath));
263 } else264 } else
264 grab_focus ();265 grab_focus ();
@@ -351,20 +352,13 @@
351 if (search_mode)352 if (search_mode)
352 set_entry_text ("");353 set_entry_text ("");
353 else {354 else {
354 current_path = sanitise_path (GLib.Uri.unescape_string (get_elements_path ()));355 set_entry_text (GLib.Uri.unescape_string (get_elements_path ()));
355 set_entry_text (current_path);
356 show_navigate_icon ();356 show_navigate_icon ();
357 }357 }
358
358 return base.focus_in_event (event);359 return base.focus_in_event (event);
359 }360 }
360361
361 string sanitise_path (string path) {
362 return path.replace ("file:////", "/")
363 .replace ("file:///", "/")
364 .replace ("trash:///", "")
365 .replace ("network:///", "");
366 }
367
368 void on_grab_focus () {362 void on_grab_focus () {
369 select_region (0, 0);363 select_region (0, 0);
370 set_position (-1);364 set_position (-1);
@@ -488,15 +482,25 @@
488 return null;482 return null;
489 }483 }
490484
491 protected string get_path_from_element (BreadcrumbsElement el) {485 protected string get_path_from_element (BreadcrumbsElement? el) {
492 string newpath = protocol;486 /* return path up to the speficied element or, if the parameter is null, the whole path */
487 string newpath = "";
488 bool first = true;
493489
494 foreach (BreadcrumbsElement element in elements) {490 foreach (BreadcrumbsElement element in elements) {
495 if (element.display) {491 string s = element.text;
496 newpath += element.text + "/";492 if (first) {
497 if (element == el)493 if (s == "" || s == "file://")
494 newpath = "/";
495 else
496 newpath = s;
497
498 first = false;
499 } else
500 newpath += (s + "/");
501
502 if (el != null && element == el)
498 break;503 break;
499 }
500 }504 }
501 return newpath;505 return newpath;
502 }506 }
@@ -505,20 +509,13 @@
505 * Get the current path of the PathBar, based on the elements that it contains509 * Get the current path of the PathBar, based on the elements that it contains
506 **/510 **/
507 public string get_elements_path () {511 public string get_elements_path () {
508 string strpath = "";512 return get_path_from_element (null);
509 strpath = protocol;
510
511 foreach (BreadcrumbsElement element in elements) {
512 if (element.display)
513 strpath += element.text + "/";
514 }
515 return strpath;
516 }513 }
517 514
518 /**515 /**
519 * Gets a properly escaped GLib.File for the given path516 * Gets a properly escaped GLib.File for the given path
520 **/517 **/
521 public File get_file_for_path (string path) {518 public File? get_file_for_path (string path) {
522 string reserved_chars = (GLib.Uri.RESERVED_CHARS_GENERIC_DELIMITERS + GLib.Uri.RESERVED_CHARS_SUBCOMPONENT_DELIMITERS + " ").replace("#", "");519 string reserved_chars = (GLib.Uri.RESERVED_CHARS_GENERIC_DELIMITERS + GLib.Uri.RESERVED_CHARS_SUBCOMPONENT_DELIMITERS + " ").replace("#", "");
523 string newpath = GLib.Uri.unescape_string (path ?? "");520 string newpath = GLib.Uri.unescape_string (path ?? "");
524521
@@ -529,12 +526,22 @@
529 if (newpath[0] == '~')526 if (newpath[0] == '~')
530 newpath = newpath.replace("~", Environment.get_home_dir ());527 newpath = newpath.replace("~", Environment.get_home_dir ());
531528
532 if (!newpath.contains("://"))529 if (!newpath.contains("://")) {
530 if (!newpath.has_prefix ("/"))
531 newpath = "/" + newpath;
532
533 newpath = Marlin.ROOT_FS_URI + newpath;533 newpath = Marlin.ROOT_FS_URI + newpath;
534 534 } else {
535 string [] parts = newpath.split ("://", 3);
536 if (parts.length > 2) {
537 warning ("Invalid path");
538 return null;
539 }
540 }
541
535 newpath = newpath.replace("ssh:", "sftp:");542 newpath = newpath.replace("ssh:", "sftp:");
536 newpath = GLib.Uri.escape_string (newpath, reserved_chars, true);543 newpath = GLib.Uri.escape_string (newpath, reserved_chars, true);
537 544
538 File file = File.new_for_commandline_arg (newpath);545 File file = File.new_for_commandline_arg (newpath);
539 return file;546 return file;
540 }547 }
@@ -566,24 +573,21 @@
566 load_right_click_menu (menu_x_root, menu_y_root);573 load_right_click_menu (menu_x_root, menu_y_root);
567 return true;574 return true;
568 }575 }
569
570 return false;576 return false;
571 } 577 }
572578
573 public virtual string? update_breadcrumbs (string newpath, string breadpath) {579 public virtual string? update_breadcrumbs (string newpath, string breadpath) {
574 string strloc;580 string strloc;
575581
576 if (Posix.strncmp (newpath, "./", 2) == 0) {582 if (Posix.strncmp (newpath, "./", 2) == 0)
577 return null;583 return null;
578 }
579584
580 if (newpath[0] == '/') {585 if (newpath[0] == '/')
581 strloc = newpath;586 strloc = newpath;
582 } else if (Posix.strncmp (newpath, "~/", 2) == 0) {587 else if (Posix.strncmp (newpath, "~/", 2) == 0)
583 strloc = Environment.get_home_dir ();588 strloc = Environment.get_home_dir ();
584 } else {589 else
585 strloc = breadpath + newpath;590 strloc = breadpath + newpath;
586 }
587591
588 return strloc;592 return strloc;
589 }593 }
@@ -608,10 +612,9 @@
608 selected = -1;612 selected = -1;
609 var breads = current_path.split ("/");613 var breads = current_path.split ("/");
610 var newelements = new Gee.ArrayList<BreadcrumbsElement> ();614 var newelements = new Gee.ArrayList<BreadcrumbsElement> ();
611 if (breads.length == 0 || breads[0] == "") {615
612 var element = new BreadcrumbsElement (protocol, left_padding, right_padding);616 string s = protocol == Marlin.ROOT_FS_URI ? "" : protocol;
613 newelements.add (element);617 newelements.add (new BreadcrumbsElement (s, left_padding, right_padding));
614 }
615618
616619
617 /* Add every mounted volume in our IconDirectory in order to load them properly in the pathbar if needed */620 /* Add every mounted volume in our IconDirectory in order to load them properly in the pathbar if needed */
@@ -633,17 +636,11 @@
633 }636 }
634637
635 foreach (string dir in breads) {638 foreach (string dir in breads) {
636 if (dir != "") {639 if (dir != "")
637 var element = new BreadcrumbsElement (dir, left_padding, right_padding);640 newelements.add (new BreadcrumbsElement (dir, left_padding, right_padding));
638 newelements.add (element);
639 }
640 }641 }
641642
642 if (protocol == Marlin.ROOT_FS_URI)
643 newelements[0].text = "/";
644
645 int max_path = int.min (elements.size, newelements.size);643 int max_path = int.min (elements.size, newelements.size);
646
647 foreach (IconDirectory icon in icons) {644 foreach (IconDirectory icon in icons) {
648 if (icon.protocol && icon.path == protocol) {645 if (icon.protocol && icon.path == protocol) {
649 newelements[0].set_icon(icon.icon);646 newelements[0].set_icon(icon.icon);
@@ -653,7 +650,7 @@
653 bool found = true;650 bool found = true;
654 int h = 0;651 int h = 0;
655652
656 for (int i = 0; i < icon.exploded.length; i++) {653 for (int i = 1; i < icon.exploded.length; i++) {
657 if (icon.exploded[i] != newelements[i].text) {654 if (icon.exploded[i] != newelements[i].text) {
658 found = false;655 found = false;
659 break;656 break;
@@ -670,10 +667,9 @@
670 newelements[h].display_text = (icon.text_displayed != null) || !icon.break_loop;667 newelements[h].display_text = (icon.text_displayed != null) || !icon.break_loop;
671 newelements[h].text_displayed = icon.text_displayed;668 newelements[h].text_displayed = icon.text_displayed;
672669
673 if (icon.break_loop) {670 if (icon.break_loop)
674 newelements[h].text = icon.path;
675 break;671 break;
676 }672
677 }673 }
678 }674 }
679 }675 }
680676
=== modified file 'plugins/contractor/plugin.vala'
--- plugins/contractor/plugin.vala 2013-05-12 05:49:12 +0000
+++ plugins/contractor/plugin.vala 2015-02-07 19:01:29 +0000
@@ -73,11 +73,14 @@
73 } else {73 } else {
74 files = get_file_array (gof_files);74 files = get_file_array (gof_files);
75 var mimetypes = get_mimetypes (gof_files);75 var mimetypes = get_mimetypes (gof_files);
76 contracts = Granite.Services.ContractorProxy.get_contracts_by_mimelist (mimetypes);76 if (mimetypes.length > 0)
77 contracts = Granite.Services.ContractorProxy.get_contracts_by_mimelist (mimetypes);
77 }78 }
7879
79 assert (files != null);80 assert (files != null);
80 assert (contracts != null);81
82 if (contracts == null)
83 return;
8184
82 for (int i = 0; i < contracts.size; i++) {85 for (int i = 0; i < contracts.size; i++) {
83 var contract = contracts.get (i);86 var contract = contracts.get (i);
8487
=== modified file 'plugins/network-places/plugin.vala'
--- plugins/network-places/plugin.vala 2014-10-29 18:55:55 +0000
+++ plugins/network-places/plugin.vala 2015-02-07 19:01:29 +0000
@@ -17,35 +17,9 @@
17// See src/marlin-connect-server-dialog.c17// See src/marlin-connect-server-dialog.c
18extern void marlin_connect_server_dialog_show (Gtk.Widget widget);18extern void marlin_connect_server_dialog_show (Gtk.Widget widget);
1919
20public class Files.Plugins.NetworkInfobar : Gtk.InfoBar {
21 public NetworkInfobar () {
22 message_type = Gtk.MessageType.INFO;
23 add_button (_("Connect to Server…"), 0);
24 }
25
26 public override void response (int response_id) {
27 marlin_connect_server_dialog_show (this);
28 }
29}
30
31public class Files.Plugins.NetworkPlaces : Marlin.Plugins.Base {20public class Files.Plugins.NetworkPlaces : Marlin.Plugins.Base {
32 private NetworkInfobar? infobar = null;
3321
34 public override void directory_loaded (void* user_data) {22 public override void directory_loaded (void* user_data) {
35 var file = ((Object[]) user_data)[2] as GOF.File;
36
37 if (file.is_network_uri_scheme ()) {
38 if (infobar == null) {
39 var slot = ((Object[]) user_data)[1] as GOF.AbstractSlot;
40 return_if_fail (slot != null);
41 infobar = new NetworkInfobar ();
42 slot.add_extra_widget (infobar);
43 infobar.show_all ();
44 }
45 } else if (infobar != null) {
46 infobar.destroy ();
47 infobar = null;
48 }
49 }23 }
5024
51 public override void update_sidebar (Gtk.Widget widget) {25 public override void update_sidebar (Gtk.Widget widget) {
5226
=== modified file 'plugins/pantheon-files-trash/plugin.vala'
--- plugins/pantheon-files-trash/plugin.vala 2014-12-10 13:19:17 +0000
+++ plugins/pantheon-files-trash/plugin.vala 2015-02-07 19:01:29 +0000
@@ -49,7 +49,6 @@
49 if (file.location.get_uri_scheme () == "trash") {49 if (file.location.get_uri_scheme () == "trash") {
50 /* Only add infobar once */50 /* Only add infobar once */
51 if (!infobars.has_key (slot)) {51 if (!infobars.has_key (slot)) {
52
53 var infobar = new Gtk.InfoBar ();52 var infobar = new Gtk.InfoBar ();
54 (infobar.get_content_area () as Gtk.Box).add (new Gtk.Label (_("These items may be deleted by emptying the trash.")));53 (infobar.get_content_area () as Gtk.Box).add (new Gtk.Label (_("These items may be deleted by emptying the trash.")));
55 infobar.add_button (_("Empty the Trash"), 0);54 infobar.add_button (_("Empty the Trash"), 0);
@@ -58,10 +57,11 @@
58 });57 });
59 infobar.set_message_type (Gtk.MessageType.INFO);58 infobar.set_message_type (Gtk.MessageType.INFO);
60 infobar.set_response_sensitive (0, !TrashMonitor.is_empty ());59 infobar.set_response_sensitive (0, !TrashMonitor.is_empty ());
61 slot.add_extra_widget (infobar);
62 infobar.show_all ();60 infobar.show_all ();
63 infobar.set_visible (!TrashMonitor.is_empty ());61 infobar.set_visible (!TrashMonitor.is_empty ());
62 slot.add_extra_widget (infobar);
64 infobars.@set (slot, infobar);63 infobars.@set (slot, infobar);
64
65 }65 }
66 } else {66 } else {
67 var infobar = infobars.@get (slot);67 var infobar = infobars.@get (slot);
6868
=== modified file 'src/Application.vala'
--- src/Application.vala 2014-12-19 16:24:10 +0000
+++ src/Application.vala 2015-02-07 19:01:29 +0000
@@ -234,6 +234,19 @@
234 });234 });
235 }235 }
236236
237 public void tab_reloaded (Marlin.View.Window source, GLib.File file) {
238 unowned List<Gtk.Window> window_list = this.get_windows ();
239 window_list.@foreach ((window) => {
240 var win = (Marlin.View.Window)window;
241
242 if ((source.window_number != win.window_number) &&
243 file.equal (win.current_tab.get_current_slot ().location))
244
245 win.current_tab.reload (false);
246
247 });
248 }
249
237 private void mount_removed_callback (VolumeMonitor monitor, Mount mount) {250 private void mount_removed_callback (VolumeMonitor monitor, Mount mount) {
238 /* Notify each window */251 /* Notify each window */
239 foreach (var window in this.get_windows ()) {252 foreach (var window in this.get_windows ()) {
240253
=== modified file 'src/BookmarkList.vala'
--- src/BookmarkList.vala 2014-11-13 20:24:33 +0000
+++ src/BookmarkList.vala 2015-02-07 19:01:29 +0000
@@ -83,13 +83,13 @@
83 return instance;83 return instance;
84 }84 }
8585
86 public void insert_uri (string uri, uint index) {86 public void insert_uri (string uri, uint index, string? label = null) {
87 insert_item_internal (new Bookmark.from_uri (uri, null), index);87 insert_item_internal (new Bookmark.from_uri (uri, label), index);
88 save_bookmarks_file ();88 save_bookmarks_file ();
89 }89 }
9090
91 public void insert_uri_at_end (string uri) {91 public void insert_uri_at_end (string uri, string? label = null) {
92 append_internal (new Bookmark.from_uri (uri, null));92 append_internal (new Bookmark.from_uri (uri, label));
93 save_bookmarks_file ();93 save_bookmarks_file ();
94 }94 }
9595
9696
=== modified file 'src/DndHandler.vala'
--- src/DndHandler.vala 2014-11-13 20:24:33 +0000
+++ src/DndHandler.vala 2015-02-07 19:01:29 +0000
@@ -38,7 +38,7 @@
38 drop_target.get_target_location (),38 drop_target.get_target_location (),
39 action,39 action,
40 widget,40 widget,
41 (void*)dnd_done,41 null,
42 null);42 null);
43 return true;43 return true;
44 } else if (drop_target.is_executable ()) {44 } else if (drop_target.is_executable ()) {
@@ -54,8 +54,6 @@
54 return false;54 return false;
55 }55 }
5656
57 private void dnd_done (GLib.List<GLib.File> files, void* data) {}
58
59 public Gdk.DragAction? drag_drop_action_ask (Gtk.Widget dest_widget,57 public Gdk.DragAction? drag_drop_action_ask (Gtk.Widget dest_widget,
60 Gtk.ApplicationWindow win,58 Gtk.ApplicationWindow win,
61 Gdk.DragAction possible_actions) {59 Gdk.DragAction possible_actions) {
6260
=== modified file 'src/MimeActions.vala'
--- src/MimeActions.vala 2014-11-13 20:24:33 +0000
+++ src/MimeActions.vala 2015-02-07 19:01:29 +0000
@@ -76,8 +76,11 @@
76 }76 }
7777
78 public static List<AppInfo>? get_applications_for_file (GOF.File file) {78 public static List<AppInfo>? get_applications_for_file (GOF.File file) {
79 string? type = file.get_ftype ();
80 if (type == null)
81 return null;
7982
80 List<AppInfo> result = AppInfo.get_all_for_type (file.get_ftype ());83 List<AppInfo> result = AppInfo.get_all_for_type (type);
81 string uri_scheme = file.location.get_uri_scheme ();84 string uri_scheme = file.location.get_uri_scheme ();
8285
83 if (uri_scheme != null) {86 if (uri_scheme != null) {
@@ -142,11 +145,12 @@
142145
143 if (result != null)146 if (result != null)
144 result = intersect_application_lists (result, one_result);147 result = intersect_application_lists (result, one_result);
148
145 else149 else
146 result = one_result.copy ();150 result = one_result.copy ();
147151
148 if (result == null)152 if (result == null)
149 break;153 return null;
150154
151 previous_file = file;155 previous_file = file;
152 }156 }
@@ -186,12 +190,11 @@
186 }190 }
187191
188 private static void filter_non_uri_apps (List<AppInfo> apps) {192 private static void filter_non_uri_apps (List<AppInfo> apps) {
189 var non_uri_apps = new List<AppInfo> ();193 List<AppInfo> non_uri_apps = null;
190194
191 foreach (var app in apps) {195 foreach (var app in apps) {
192 if (!app.supports_uris ()) {196 if (!app.supports_uris ())
193 non_uri_apps.append (app);197 non_uri_apps.append (app);
194 }
195 }198 }
196199
197 foreach (var app in non_uri_apps) {200 foreach (var app in non_uri_apps) {
198201
=== modified file 'src/MultiLineEditableLabel.vala'
--- src/MultiLineEditableLabel.vala 2014-12-25 08:43:14 +0000
+++ src/MultiLineEditableLabel.vala 2015-02-07 19:01:29 +0000
@@ -26,6 +26,9 @@
2626
27 public override Gtk.Widget create_editable_widget () {27 public override Gtk.Widget create_editable_widget () {
28 textview = new Gtk.TextView ();28 textview = new Gtk.TextView ();
29 /* Block propagation of button press event to view as this would cause renaming to end */
30 textview.button_press_event.connect_after (() => {return true;});
31
29 scrolled_window = new Gtk.ScrolledWindow (null, null);32 scrolled_window = new Gtk.ScrolledWindow (null, null);
30 scrolled_window.add (textview);33 scrolled_window.add (textview);
31 return scrolled_window as Gtk.Widget;34 return scrolled_window as Gtk.Widget;
3235
=== modified file 'src/View/AbstractDirectoryView.vala'
--- src/View/AbstractDirectoryView.vala 2015-01-28 09:05:34 +0000
+++ src/View/AbstractDirectoryView.vala 2015-02-07 19:01:29 +0000
@@ -198,7 +198,7 @@
198 private GLib.AppInfo default_app;198 private GLib.AppInfo default_app;
199 private Gtk.TreePath? hover_path = null;199 private Gtk.TreePath? hover_path = null;
200200
201 private bool selection_was_removed = false;201 private bool can_trash_or_delete = true;
202202
203 /* Rapid keyboard paste support */203 /* Rapid keyboard paste support */
204 protected bool pasting_files = false;204 protected bool pasting_files = false;
@@ -211,6 +211,7 @@
211 private bool updates_frozen = false;211 private bool updates_frozen = false;
212 protected bool tree_frozen = false;212 protected bool tree_frozen = false;
213 private bool in_trash = false;213 private bool in_trash = false;
214 private bool in_network_root = false;
214 protected bool is_loading;215 protected bool is_loading;
215 protected bool helpers_shown;216 protected bool helpers_shown;
216 private uint select_timeout_id = 0;217 private uint select_timeout_id = 0;
@@ -429,12 +430,13 @@
429430
430 protected void unfreeze_updates () {431 protected void unfreeze_updates () {
431 updates_frozen = false;432 updates_frozen = false;
432 slot.directory.freeze_update = false;;433 slot.directory.freeze_update = false;
433 update_menu_actions ();434 update_menu_actions ();
434 size_allocate.connect (on_size_allocate);435 size_allocate.connect (on_size_allocate);
435 clipboard.changed.connect (on_clipboard_changed);436 clipboard.changed.connect (on_clipboard_changed);
436 view.enter_notify_event.connect (on_enter_notify_event);437 view.enter_notify_event.connect (on_enter_notify_event);
437 view.key_press_event.connect (on_view_key_press_event);438 view.key_press_event.connect (on_view_key_press_event);
439
438 }440 }
439441
440 public new void grab_focus () {442 public new void grab_focus () {
@@ -481,21 +483,27 @@
481 return;483 return;
482484
483 unowned Gdk.Screen screen = Eel.gtk_widget_get_screen (this);485 unowned Gdk.Screen screen = Eel.gtk_widget_get_screen (this);
484 bool only_folders = selection_only_contains_folders (selection);486
485487 if (nb_elem == 1) {
486 if (nb_elem < 10 && (default_app == null || only_folders)) {488 activate_file (selection.data, screen, flag, true);
489 return;
490 }
491
492 if (nb_elem < 10 && (default_app == null)) {
487 /* launch each selected file individually ignoring selections greater than 10 */493 /* launch each selected file individually ignoring selections greater than 10 */
488 bool only_one_file = (nb_elem == 1);
489
490 foreach (unowned GOF.File file in selection) {494 foreach (unowned GOF.File file in selection) {
491 /* Prevent too rapid activation of files - causes New Tab to crash for example */495 /* Prevent too rapid activation of files - causes New Tab to crash for example */
492 GLib.Timeout.add (50, () => {496 if (file.is_folder ()) {
493 activate_file (file, screen, flag, only_one_file);497 GLib.Timeout.add (50, () => {
494 return false;498 activate_file (file, screen, flag, false);
495 });499 return false;
500 });
501 } else
502 file.open_single (screen, null);
496 }503 }
497 } else if (default_app != null)504 } else if (default_app != null) {
498 open_files_with (default_app, selection);505 open_files_with (default_app, selection);
506 }
499 }507 }
500508
501 protected void preview_selected_items () {509 protected void preview_selected_items () {
@@ -582,13 +590,12 @@
582 loaded_subdirectories = null;590 loaded_subdirectories = null;
583 model.clear ();591 model.clear ();
584 unblock_model ();592 unblock_model ();
585593 if (new_dir.can_load);
586 connect_directory_handlers (new_dir);594 connect_directory_handlers (new_dir);
587 update_menu_actions ();
588 model.set_sort_column_id (slot.directory.file.sort_column_id, slot.directory.file.sort_order);
589 }595 }
590596
591 public void reload () {597 public void reload () {
598 slot.directory.clear_directory_info ();
592 change_directory (slot.directory, slot.directory);599 change_directory (slot.directory, slot.directory);
593 }600 }
594601
@@ -631,7 +638,7 @@
631 bool only_folders = true;638 bool only_folders = true;
632639
633 list.@foreach ((file) => {640 list.@foreach ((file) => {
634 if (!file.is_folder ())641 if (!(file.is_folder () || file.is_root_network_folder ()))
635 only_folders = false;642 only_folders = false;
636 });643 });
637644
@@ -700,13 +707,16 @@
700 if (updates_frozen || in_trash)707 if (updates_frozen || in_trash)
701 return;708 return;
702709
703 debug ("activate file %s only one file %s", file.uri, only_one_file.to_string ());710 GLib.File location = file.get_target_location ();
704 GLib.File location = file.location.dup ();
705
706 if (screen == null)711 if (screen == null)
707 screen = Eel.gtk_widget_get_screen (this);712 screen = Eel.gtk_widget_get_screen (this);
708713
709 if (file.is_folder ()) {714 default_app = Marlin.MimeActions.get_default_application_for_file (file);
715
716 if (file.is_folder () ||
717 file.get_ftype () == "inode/directory" ||
718 file.is_root_network_folder ()) {
719
710 switch (flag) {720 switch (flag) {
711 case Marlin.OpenFlag.NEW_TAB:721 case Marlin.OpenFlag.NEW_TAB:
712 window.add_tab (location, Marlin.ViewMode.CURRENT);722 window.add_tab (location, Marlin.ViewMode.CURRENT);
@@ -729,25 +739,27 @@
729 else if (only_one_file && default_app != null)739 else if (only_one_file && default_app != null)
730 file.open_single (screen, default_app);740 file.open_single (screen, default_app);
731 else741 else
732 warning ("Unable to activate this file. Default app is %s", default_app != null ? default_app.get_name () : "null");742 warning ("Unable to activate this file. Default app is %s",
743 default_app != null ? default_app.get_name () : "null");
733 }744 }
734745
735 private void trash_or_delete_files (GLib.List<unowned GOF.File> file_list,746 private void trash_or_delete_files (GLib.List<unowned GOF.File> file_list,
736 bool delete_if_already_in_trash,747 bool delete_if_already_in_trash,
737 bool delete_immediately) {748 bool delete_immediately) {
749
738 GLib.List<GLib.File> locations = null;750 GLib.List<GLib.File> locations = null;
739
740 file_list.@foreach ((file) => {751 file_list.@foreach ((file) => {
741 locations.prepend (file.location);752 locations.prepend (file.location);
742 });753 });
743754
744 if (locations != null) {755 if (locations != null) {
745 locations.reverse ();756 locations.reverse ();
757
746 if (delete_immediately)758 if (delete_immediately)
747 Marlin.FileOperations.delete (locations,759 Marlin.FileOperations.@delete (locations,
748 window as Gtk.Window,760 window as Gtk.Window,
749 after_trash_or_delete,761 after_trash_or_delete,
750 this);762 this);
751 else763 else
752 Marlin.FileOperations.trash_or_delete (locations,764 Marlin.FileOperations.trash_or_delete (locations,
753 window as Gtk.Window,765 window as Gtk.Window,
@@ -787,7 +799,10 @@
787 unselect_all ();799 unselect_all ();
788 select_gof_file (file_to_rename);800 select_gof_file (file_to_rename);
789801
790 if (file_to_rename.is_writable ())802 /* Assume writability on remote locations
803 * TODO Reliably determine writability with various remote protocols.
804 */
805 if (file_to_rename.is_writable () || !slot.directory.is_local)
791 start_renaming_file (file_to_rename, false);806 start_renaming_file (file_to_rename, false);
792 else807 else
793 warning ("You do not have permission to rename this file");808 warning ("You do not have permission to rename this file");
@@ -801,17 +816,32 @@
801816
802 var view = (FM.AbstractDirectoryView)data;817 var view = (FM.AbstractDirectoryView)data;
803 var file_to_rename = GOF.File.@get (new_file);818 var file_to_rename = GOF.File.@get (new_file);
804 /* Allow time for the file to appear in the tree model before renaming */819 bool local = view.slot.directory.is_local;
805 GLib.Timeout.add (250, () => {820 if (!local)
821 view.slot.directory.need_reload ();
822
823 /* Allow time for the file to appear in the tree model before renaming
824 * Wait longer for remote locations to allow for reload.
825 * TODO: Remove need for hard coded delay.
826 */
827 int delay = local ? 250 : 500;
828 GLib.Timeout.add (delay, () => {
806 view.rename_file (file_to_rename);829 view.rename_file (file_to_rename);
807 view.slot.directory.unblock_monitor ();830 view.slot.directory.unblock_monitor ();
808 return false;831 return false;
809 });832 });
810 }833 }
811834
812 public static void after_trash_or_delete (bool user_cancel, void* callback_data) {835 /** Must pass a pointer to an instance of FM.AbstractDirectoryView as 3rd parameter when
813 FM.AbstractDirectoryView view = (FM.AbstractDirectoryView)callback_data;836 * using this callback */
814 view.selection_was_removed = false;837 public static void after_trash_or_delete (bool user_cancel, void* data) {
838 var view = data as FM.AbstractDirectoryView;
839 assert (view is FM.AbstractDirectoryView);
840
841 view.can_trash_or_delete = true;
842
843 if (!view.slot.directory.is_local)
844 view.slot.directory.need_reload ();
815 }845 }
816846
817 private void trash_or_delete_selected_files (bool delete_immediately = false) {847 private void trash_or_delete_selected_files (bool delete_immediately = false) {
@@ -819,16 +849,32 @@
819 * when using keybindings. So we remember if the current selection849 * when using keybindings. So we remember if the current selection
820 * was already removed (but the view doesn't know about it yet).850 * was already removed (but the view doesn't know about it yet).
821 */851 */
822 if (selection_was_removed)852 if (!can_trash_or_delete)
823 return;853 return;
824854
825 unowned GLib.List<unowned GOF.File> selection = get_selected_files_for_transfer ();855 unowned GLib.List<unowned GOF.File> selection = get_selected_files_for_transfer ();
826 if (selection != null) {856 if (selection != null) {
857 can_trash_or_delete = false;
858
827 trash_or_delete_files (selection, true, delete_immediately);859 trash_or_delete_files (selection, true, delete_immediately);
828 selection_was_removed = true;
829 }860 }
830 }861 }
831862
863 private void delete_selected_files () {
864 unowned GLib.List<unowned GOF.File> selection = get_selected_files_for_transfer ();
865 if (selection == null)
866 return;
867
868 GLib.List<GLib.File> locations = null;
869
870 selection.@foreach ((file) => {
871 locations.prepend (file.location);
872 });
873
874 locations.reverse ();
875 Marlin.FileOperations.@delete (locations, window as Gtk.Window, after_trash_or_delete, this);
876 }
877
832/** Signal Handlers */878/** Signal Handlers */
833879
834 /** Menu actions */880 /** Menu actions */
@@ -920,10 +966,13 @@
920 }966 }
921967
922 private void on_common_action_bookmark (GLib.SimpleAction action, GLib.Variant? param) {968 private void on_common_action_bookmark (GLib.SimpleAction action, GLib.Variant? param) {
969 GLib.File location;
923 if (selected_files != null)970 if (selected_files != null)
924 window.sidebar.add_uri (selected_files.data.uri);971 location = selected_files.data.get_target_location ();
925 else972 else
926 window.sidebar.add_uri (slot.directory.file.uri);973 location = slot.directory.file.get_target_location ();
974
975 window.sidebar.add_uri (location.get_uri (), null);
927 }976 }
928977
929 /** Background actions */978 /** Background actions */
@@ -1018,6 +1067,8 @@
1018 }1067 }
10191068
1020 public static void after_pasting_files (GLib.HashTable uris, void* pointer) {1069 public static void after_pasting_files (GLib.HashTable uris, void* pointer) {
1070 assert (pointer != null);
1071
1021 var view = pointer as FM.AbstractDirectoryView; 1072 var view = pointer as FM.AbstractDirectoryView;
1022 if (view.paste_timer == null)1073 if (view.paste_timer == null)
1023 view.paste_timer = new GLib.Timer ();1074 view.paste_timer = new GLib.Timer ();
@@ -1051,14 +1102,27 @@
1051 var file = get_files_for_action ().nth_data (0);1102 var file = get_files_for_action ().nth_data (0);
10521103
1053 if (file != null && clipboard.get_can_paste ()) {1104 if (file != null && clipboard.get_can_paste ()) {
1054 pasting_files = true;1105 GLib.File target;
1055 prepare_to_select_added_files ();1106 GLib.Callback? call_back;
1056 /* Block the async directory file monitor to avoid generating unwanted "add-file" events */1107
1057 slot.directory.block_monitor ();
1058 if (file.is_folder () && !clipboard.has_file (file))1108 if (file.is_folder () && !clipboard.has_file (file))
1059 clipboard.paste_files (file.get_target_location (), this as Gtk.Widget, after_pasting_files);1109 target = file.get_target_location ();
1060 else1110 else
1061 clipboard.paste_files (slot.directory.location, this as Gtk.Widget, after_pasting_files);1111 target = slot.location;
1112
1113 if (target.has_uri_scheme ("trash")) {
1114 /* Pasting files into trash is equivalent to trash or delete action */
1115 pasting_files = false;
1116 call_back = (GLib.Callback)after_trash_or_delete;
1117 } else {
1118 pasting_files = true;
1119 prepare_to_select_added_files ();
1120 /* Block the async directory file monitor to avoid generating unwanted "add-file" events */
1121 slot.directory.block_monitor ();
1122 call_back = (GLib.Callback)after_pasting_files;
1123 }
1124
1125 clipboard.paste_files (target, this as Gtk.Widget, call_back);
1062 }1126 }
1063 }1127 }
10641128
@@ -1076,7 +1140,8 @@
1076 model.file_changed (file, dir);1140 model.file_changed (file, dir);
1077 /* 2nd parameter is for returned request id if required - we do not use it? */1141 /* 2nd parameter is for returned request id if required - we do not use it? */
1078 /* This is required if we need to dequeue the request */1142 /* This is required if we need to dequeue the request */
1079 thumbnailer.queue_file (file, null, false);1143 if (slot.directory.is_local)
1144 thumbnailer.queue_file (file, null, false);
1080 }1145 }
10811146
1082 private void on_directory_file_icon_changed (GOF.Directory.Async dir, GOF.File file) {1147 private void on_directory_file_icon_changed (GOF.Directory.Async dir, GOF.File file) {
@@ -1098,8 +1163,12 @@
1098 private void on_directory_done_loading (GOF.Directory.Async dir) {1163 private void on_directory_done_loading (GOF.Directory.Async dir) {
1099 debug ("DV directory done loading %s", dir.file.uri);1164 debug ("DV directory done loading %s", dir.file.uri);
1100 dir.file_loaded.disconnect (on_directory_file_loaded);1165 dir.file_loaded.disconnect (on_directory_file_loaded);
1101 in_trash = (dir.file.uri == Marlin.TRASH_URI); /* trash cannot be subdirectory */1166 in_trash = slot.directory.is_trash;
1167 in_network_root = slot.directory.file.is_root_network_folder ();
1102 thaw_tree ();1168 thaw_tree ();
1169
1170 model.set_sort_column_id (slot.directory.file.sort_column_id, slot.directory.file.sort_order);
1171
1103 /* This is a workround for a bug (Gtk?) in the drawing of the ListView where the columns1172 /* This is a workround for a bug (Gtk?) in the drawing of the ListView where the columns
1104 * are sometimes not properly aligned when first drawn, only after redrawing the view. */ 1173 * are sometimes not properly aligned when first drawn, only after redrawing the view. */
1105 Idle.add (() => {1174 Idle.add (() => {
@@ -1117,7 +1186,7 @@
1117 model.set_property ("size", icon_size);1186 model.set_property ("size", icon_size);
1118 change_zoom_level ();1187 change_zoom_level ();
11191188
1120 if (get_realized ())1189 if (get_realized () && slot.directory.is_local)
1121 load_thumbnails (slot.directory, zoom);1190 load_thumbnails (slot.directory, zoom);
1122 }1191 }
11231192
@@ -1225,7 +1294,6 @@
12251294
1226/** Handle clipboard signal */1295/** Handle clipboard signal */
1227 private void on_clipboard_changed () {1296 private void on_clipboard_changed () {
1228 update_menu_actions ();
1229 /* show possible change in appearance of cut items */1297 /* show possible change in appearance of cut items */
1230 queue_draw ();1298 queue_draw ();
1231 }1299 }
@@ -1238,7 +1306,6 @@
1238 if (updates_frozen)1306 if (updates_frozen)
1239 return;1307 return;
12401308
1241 update_menu_actions ();
1242 window.selection_changed (get_selected_files ());1309 window.selection_changed (get_selected_files ());
1243 }1310 }
12441311
@@ -1274,7 +1341,7 @@
1274 GLib.StringBuilder sb = new GLib.StringBuilder ("");1341 GLib.StringBuilder sb = new GLib.StringBuilder ("");
12751342
1276 drag_file_list.@foreach ((file) => {1343 drag_file_list.@foreach ((file) => {
1277 sb.append (file.uri);1344 sb.append (file.get_target_location ().get_uri ());
1278 sb.append ("\n");1345 sb.append ("\n");
1279 });1346 });
12801347
@@ -1305,15 +1372,16 @@
1305 int y,1372 int y,
1306 uint timestamp) {1373 uint timestamp) {
1307 /* if we don't have drop data already ... */1374 /* if we don't have drop data already ... */
1308 if (!drop_data_ready) {1375 if (!drop_data_ready && !get_drop_data (context, x, y, timestamp))
1309 get_drop_data (context, x, y, timestamp);1376 return false;
1310 } else1377 else
1311 /* We have the drop data - check whether we can drop here*/1378 /* We have the drop data - check whether we can drop here*/
1312 check_destination_actions_and_target_file (context, x, y, timestamp);1379 check_destination_actions_and_target_file (context, x, y, timestamp);
13131380
1314 if (drag_scroll_timer_id == 0)1381 if (drag_scroll_timer_id == 0)
1315 start_drag_scroll_timer (context);1382 start_drag_scroll_timer (context);
13161383
1384 Gdk.drag_status (context, current_suggested_action, timestamp);
1317 return true;1385 return true;
1318 }1386 }
13191387
@@ -1376,6 +1444,12 @@
1376 if (drop_occurred) {1444 if (drop_occurred) {
1377 drop_occurred = false;1445 drop_occurred = false;
1378 if (current_actions != Gdk.DragAction.DEFAULT) {1446 if (current_actions != Gdk.DragAction.DEFAULT) {
1447 if (!slot.directory.is_local) {
1448 /* Cannot be sure that view will automatically refresh properly
1449 * so we force a refresh after a short delay */
1450 slot.directory.clear_directory_info ();
1451 slot.directory.need_reload ();
1452 }
1379 switch (info) {1453 switch (info) {
1380 case TargetType.XDND_DIRECT_SAVE0:1454 case TargetType.XDND_DIRECT_SAVE0:
1381 success = dnd_handler.handle_xdnddirectsave (context,1455 success = dnd_handler.handle_xdnddirectsave (context,
@@ -1392,6 +1466,7 @@
1392 case TargetType.TEXT_URI_LIST:1466 case TargetType.TEXT_URI_LIST:
1393 if ((current_actions & file_drag_actions) != 0) {1467 if ((current_actions & file_drag_actions) != 0) {
1394 prepare_to_select_added_files ();1468 prepare_to_select_added_files ();
1469
1395 success = dnd_handler.handle_file_drag_actions (get_real_view (),1470 success = dnd_handler.handle_file_drag_actions (get_real_view (),
1396 window,1471 window,
1397 context,1472 context,
@@ -1464,7 +1539,7 @@
1464 return file;1539 return file;
1465 } 1540 }
14661541
1467 private void get_drop_data (Gdk.DragContext context, int x, int y, uint timestamp) {1542 private bool get_drop_data (Gdk.DragContext context, int x, int y, uint timestamp) {
1468 Gdk.DragAction action = Gdk.DragAction.DEFAULT;1543 Gdk.DragAction action = Gdk.DragAction.DEFAULT;
1469 Gtk.TargetList? list = null;1544 Gtk.TargetList? list = null;
1470 Gdk.Atom target = Gtk.drag_dest_find_target (get_real_view (), context, list);1545 Gdk.Atom target = Gtk.drag_dest_find_target (get_real_view (), context, list);
@@ -1497,9 +1572,10 @@
1497 } else if (target != Gdk.Atom.NONE)1572 } else if (target != Gdk.Atom.NONE)
1498 /* request the drag data from the source */1573 /* request the drag data from the source */
1499 Gtk.drag_get_data (get_real_view (), context, target, timestamp); /* emits "drag_data_received" */1574 Gtk.drag_get_data (get_real_view (), context, target, timestamp); /* emits "drag_data_received" */
1575 else
1576 return false;
15001577
1501 /* tell Gdk whether we can drop here */1578 return true;
1502 Gdk.drag_status (context, action, timestamp);
1503 }1579 }
15041580
1505 private void check_destination_actions_and_target_file (Gdk.DragContext context, int x, int y, uint timestamp) {1581 private void check_destination_actions_and_target_file (Gdk.DragContext context, int x, int y, uint timestamp) {
@@ -1508,13 +1584,16 @@
1508 string uri = file != null ? file.uri : "";1584 string uri = file != null ? file.uri : "";
1509 string current_uri = drop_target_file != null ? drop_target_file.uri : "";1585 string current_uri = drop_target_file != null ? drop_target_file.uri : "";
15101586
1587 Gdk.drag_status (context, Gdk.DragAction.MOVE, timestamp);
1511 if (uri != current_uri) {1588 if (uri != current_uri) {
1512 drop_target_file = file;1589 drop_target_file = file;
1513 current_actions = Gdk.DragAction.DEFAULT;1590 current_actions = Gdk.DragAction.DEFAULT;
1514 current_suggested_action = Gdk.DragAction.DEFAULT;1591 current_suggested_action = Gdk.DragAction.DEFAULT;
1592
1515 if (file != null) {1593 if (file != null) {
1516 current_actions = file.accepts_drop (drop_file_list, context, out current_suggested_action);1594 current_actions = file.accepts_drop (drop_file_list, context, out current_suggested_action);
1517 highlight_drop_file (drop_target_file, current_actions, path);1595 highlight_drop_file (drop_target_file, current_actions, path);
1596
1518 if (file.is_folder () && drag_file_list.index (file) == -1) {1597 if (file.is_folder () && drag_file_list.index (file) == -1) {
1519 cancel_timeout (ref drag_enter_timer_id);1598 cancel_timeout (ref drag_enter_timer_id);
1520 drag_enter_timer_id = GLib.Timeout.add_full (GLib.Priority.LOW,1599 drag_enter_timer_id = GLib.Timeout.add_full (GLib.Priority.LOW,
@@ -1526,7 +1605,6 @@
1526 });1605 });
1527 }1606 }
1528 }1607 }
1529 Gdk.drag_status (context, current_suggested_action, timestamp);
1530 }1608 }
1531 }1609 }
15321610
@@ -1584,89 +1662,130 @@
15841662
1585 protected void show_context_menu (Gdk.Event event) {1663 protected void show_context_menu (Gdk.Event event) {
1586 /* select selection or background context menu */1664 /* select selection or background context menu */
1665 update_menu_actions ();
1587 var builder = new Gtk.Builder.from_file (Config.UI_DIR + "directory_view_popup.ui");1666 var builder = new Gtk.Builder.from_file (Config.UI_DIR + "directory_view_popup.ui");
1588 GLib.MenuModel? model;1667 GLib.MenuModel? model = null;
15891668
1590 if (get_selected_files () != null) 1669 if (get_selected_files () != null)
1591 model = build_menu_selection (ref builder, in_trash);1670 model = build_menu_selection (ref builder, in_trash);
1592 else1671 else
1593 model = build_menu_background (ref builder, in_trash);1672 model = build_menu_background (ref builder, in_trash);
15941673
1595 if (model != null) {1674 if (model != null && model is GLib.MenuModel) {
1596 /* add any additional entries from plugins */1675 /* add any additional entries from plugins */
1597 var menu = new Gtk.Menu.from_model (model);1676 var menu = new Gtk.Menu.from_model (model);
1598 plugins.hook_context_menu (menu as Gtk.Widget, get_selected_files ());1677
1678 if (!in_trash)
1679 plugins.hook_context_menu (menu as Gtk.Widget, get_selected_files ());
1680
1599 menu.set_screen (null);1681 menu.set_screen (null);
1600 menu.attach_to_widget (this, null);1682 menu.attach_to_widget (this, null);
1601 Eel.pop_up_context_menu (menu,1683 Eel.pop_up_context_menu (menu,
1602 Eel.DEFAULT_POPUP_MENU_DISPLACEMENT,1684 Eel.DEFAULT_POPUP_MENU_DISPLACEMENT,
1603 Eel.DEFAULT_POPUP_MENU_DISPLACEMENT,1685 Eel.DEFAULT_POPUP_MENU_DISPLACEMENT,
1604 (Gdk.EventButton) event);1686 (Gdk.EventButton) event);
1605 } else1687 }
1606 warning ("Model is null");1688 }
1689
1690 private bool valid_selection_for_edit () {
1691 foreach (GOF.File file in get_selected_files ()) {
1692 if (file.is_root_network_folder ())
1693 return false;
1694 }
1695 return true;
1607 }1696 }
16081697
1609 private GLib.MenuModel? build_menu_selection (ref Gtk.Builder builder, bool in_trash) {1698 private GLib.MenuModel? build_menu_selection (ref Gtk.Builder builder, bool in_trash) {
1610 GLib.Menu menu = new GLib.Menu ();1699 GLib.Menu menu = new GLib.Menu ();
16111700
1612 if (in_trash)1701 var clipboard_menu = builder.get_object ("clipboard-selection") as GLib.Menu;
1702
1703 if (in_trash) {
1613 menu.append_section (null, builder.get_object ("popup-trash-selection") as GLib.Menu);1704 menu.append_section (null, builder.get_object ("popup-trash-selection") as GLib.Menu);
1614 else {
1615 menu.append_section (null, build_menu_open (ref builder));
16161705
1617 var clipboard_menu = builder.get_object ("clipboard-selection") as GLib.Menu;1706 clipboard_menu.remove (1); /* Copy */
1618 /* Do not display the 'Paste into' menuitem if selection is not a folder.1707 clipboard_menu.remove (1); /* Paste (index updated by previous line) */
1619 * We have to hard-code the menuitem index so any change to the clipboard-
1620 * selection menu definition in directory_view_popup.ui may necessitate changing
1621 * the index below.
1622 */
1623 if (!common_actions.get_action_enabled ("paste_into"))
1624 clipboard_menu.remove (2);
16251708
1626 menu.append_section (null, clipboard_menu);1709 menu.append_section (null, clipboard_menu);
16271710 } else {
1628 menu.append_section (null, builder.get_object ("trash") as GLib.MenuModel);1711 var open_menu = build_menu_open (ref builder);
1629 menu.append_section (null, builder.get_object ("rename") as GLib.MenuModel);1712 if (open_menu != null)
1713 menu.append_section (null, open_menu);
1714
1715 if (slot.directory.file.is_smb_server ()) {
1716 if (common_actions.get_action_enabled ("paste_into"))
1717 menu.append_section (null, builder.get_object ("paste") as GLib.MenuModel);
1718 } else if (valid_selection_for_edit ()) {
1719 /* Do not display the 'Paste into' menuitem if selection is not a folder.
1720 * We have to hard-code the menuitem index so any change to the clipboard-
1721 * selection menu definition in directory_view_popup.ui may necessitate changing
1722 * the index below.
1723 */
1724 if (!common_actions.get_action_enabled ("paste_into"))
1725 clipboard_menu.remove (2);
1726
1727 menu.append_section (null, clipboard_menu);
1728
1729 if (slot.directory.has_trash_dirs)
1730 menu.append_section (null, builder.get_object ("trash") as GLib.MenuModel);
1731 else
1732 menu.append_section (null, builder.get_object ("delete") as GLib.MenuModel);
1733
1734 menu.append_section (null, builder.get_object ("rename") as GLib.MenuModel);
1735 }
16301736
1631 if (common_actions.get_action_enabled ("bookmark"))1737 if (common_actions.get_action_enabled ("bookmark"))
1632 menu.append_section (null, builder.get_object ("bookmark") as GLib.MenuModel);1738 menu.append_section (null, builder.get_object ("bookmark") as GLib.MenuModel);
1739
1740 menu.append_section (null, builder.get_object ("properties") as GLib.MenuModel);
1633 }1741 }
1634 menu.append_section (null, builder.get_object ("properties") as GLib.MenuModel);1742
1635 return menu as MenuModel;1743 return menu as MenuModel;
1636 }1744 }
16371745
1638 private GLib.MenuModel? build_menu_background (ref Gtk.Builder builder, bool in_trash) {1746 private GLib.MenuModel? build_menu_background (ref Gtk.Builder builder, bool in_trash) {
1639 if (in_trash)1747 if (in_trash) {
1640 return null;1748 var menu = new GLib.Menu ();
1749 if (common_actions.get_action_enabled ("paste_into")) {
1750 menu.append_section (null, builder.get_object ("paste") as GLib.MenuModel);
1751
1752 return menu as MenuModel;
1753 } else
1754 return null;
1755 }
16411756
1642 var menu = new GLib.Menu ();1757 var menu = new GLib.Menu ();
1643 menu.append_section (null, build_menu_open (ref builder));1758 menu.append_section (null, build_menu_open (ref builder));
16441759
1645 if (common_actions.get_action_enabled ("paste_into"))1760 if (!in_network_root) {
1646 menu.append_section (null, builder.get_object ("paste") as GLib.MenuModel);1761 if (common_actions.get_action_enabled ("paste_into"))
16471762 menu.append_section (null, builder.get_object ("paste") as GLib.MenuModel);
16481763
1649 GLib.MenuModel? template_menu = build_menu_templates ();1764 GLib.MenuModel? template_menu = build_menu_templates ();
1650 var new_menu = builder.get_object ("new") as GLib.Menu;1765 var new_menu = builder.get_object ("new") as GLib.Menu;
16511766
1652 if (template_menu != null) {1767 if (template_menu != null) {
1653 var new_submenu = builder.get_object ("new-submenu") as GLib.Menu;1768 var new_submenu = builder.get_object ("new-submenu") as GLib.Menu;
1654 new_submenu.append_section (null, template_menu);1769 new_submenu.append_section (null, template_menu);
1770 }
1771
1772 menu.append_section (null, new_menu as GLib.MenuModel);
1773
1774 menu.append_section (null, builder.get_object ("sort-by") as GLib.MenuModel);
1655 }1775 }
16561776
1657 menu.append_section (null, new_menu as GLib.MenuModel);
1658 menu.append_section (null, builder.get_object ("sort-by") as GLib.MenuModel);
1659
1660 if (common_actions.get_action_enabled ("bookmark"))1777 if (common_actions.get_action_enabled ("bookmark"))
1661 menu.append_section (null, builder.get_object ("bookmark") as GLib.MenuModel);1778 menu.append_section (null, builder.get_object ("bookmark") as GLib.MenuModel);
16621779
1663 menu.append_section (null, builder.get_object ("hidden") as GLib.MenuModel);1780 menu.append_section (null, builder.get_object ("hidden") as GLib.MenuModel);
1664 menu.append_section (null, builder.get_object ("properties") as GLib.MenuModel);1781 menu.append_section (null, builder.get_object ("properties") as GLib.MenuModel);
1782
1665 return menu as MenuModel;1783 return menu as MenuModel;
1666 }1784 }
16671785
1668 private GLib.MenuModel build_menu_open (ref Gtk.Builder builder) {1786 private GLib.MenuModel build_menu_open (ref Gtk.Builder builder) {
1669 var menu = new GLib.Menu ();1787 var menu = new GLib.Menu ();
1788
1670 string label = _("Invalid");1789 string label = _("Invalid");
1671 unowned GLib.List<unowned GOF.File> selection = get_files_for_action ();1790 unowned GLib.List<unowned GOF.File> selection = get_files_for_action ();
1672 unowned GOF.File selected_file = selection.data;1791 unowned GOF.File selected_file = selection.data;
@@ -1684,8 +1803,14 @@
16841803
1685 GLib.MenuModel? app_submenu = build_submenu_open_with_applications (ref builder, selection);1804 GLib.MenuModel? app_submenu = build_submenu_open_with_applications (ref builder, selection);
16861805
1687 if (app_submenu != null)1806 if (app_submenu != null && app_submenu.get_n_items () > 0) {
1688 menu.append_submenu (_("Open in"), app_submenu);1807 if (selected_file.is_folder () || selected_file.is_root_network_folder ())
1808 label = _("Open in");
1809 else
1810 label = _("Open with");
1811
1812 menu.append_submenu (label, app_submenu);
1813 }
16891814
1690 return menu as MenuModel;1815 return menu as MenuModel;
1691 }1816 }
@@ -1696,32 +1821,39 @@
1696 var open_with_submenu = new GLib.Menu ();1821 var open_with_submenu = new GLib.Menu ();
1697 int index = -1;1822 int index = -1;
16981823
1699 if (common_actions.get_action_enabled ("open_in"))1824 if (common_actions.get_action_enabled ("open_in")) {
1700 open_with_submenu.append_section (null, builder.get_object ("open-in") as GLib.MenuModel);1825 open_with_submenu.append_section (null, builder.get_object ("open-in") as GLib.MenuModel);
17011826
1827 if (!selection.data.is_mountable () && !selection.data.is_root_network_folder ())
1828 open_with_submenu.append_section (null, builder.get_object ("open-in-terminal") as GLib.MenuModel);
1829 else
1830 return open_with_submenu;
1831 }
1832
1702 open_with_apps = Marlin.MimeActions.get_applications_for_files (selection);1833 open_with_apps = Marlin.MimeActions.get_applications_for_files (selection);
1703 filter_default_app_from_open_with_apps ();1834 filter_default_app_from_open_with_apps ();
1704 filter_this_app_from_open_with_apps ();1835 filter_this_app_from_open_with_apps ();
17051836
1706 if (open_with_apps.length () > 0) {1837 if (open_with_apps != null) {
1707 var apps_section = new GLib.Menu ();1838 var apps_section = new GLib.Menu ();
1708 string last_label = "";1839 string last_label = "";
1709 open_with_apps.@foreach ((app) => {1840 open_with_apps.@foreach ((app) => {
1710 var label = app.get_display_name ();1841 if (app != null && app is AppInfo) {
17111842 var label = app.get_display_name ();
1712 /* The following mainly applies to Nautilus, whose display name is also "Files" */1843 /* The following mainly applies to Nautilus, whose display name is also "Files" */
1713 if (label == "Files") {1844 if (label == "Files") {
1714 label = app.get_executable ();1845 label = app.get_executable ();
1715 label = label[0].toupper ().to_string () + label.substring (1);1846 label = label[0].toupper ().to_string () + label.substring (1);
1716 }1847 }
17171848
1718 /* Do no show same name twice - some apps have more than one .desktop file1849 /* Do not show same name twice - some apps have more than one .desktop file
1719 * with the same name (e.g. Nautilus)1850 * with the same name (e.g. Nautilus)
1720 */ 1851 */
1721 if (label != last_label) {1852 if (label != last_label) {
1722 index++;1853 index++;
1723 apps_section.append (label, "selection.open_with_app::" + index.to_string ());1854 apps_section.append (label, "selection.open_with_app::" + index.to_string ());
1724 last_label = label.dup ();1855 last_label = label.dup ();
1856 }
1725 }1857 }
1726 });1858 });
17271859
@@ -1781,21 +1913,26 @@
1781 return;1913 return;
17821914
1783 unowned GLib.List<unowned GOF.File> selection = get_files_for_action ();1915 unowned GLib.List<unowned GOF.File> selection = get_files_for_action ();
1916 unowned GOF.File file;
1917
1784 uint selection_count = selection.length ();1918 uint selection_count = selection.length ();
1785 bool more_than_one_selected = (selection_count > 1);1919 bool more_than_one_selected = (selection_count > 1);
1786 bool single_folder = true; /* background is a folder */1920 bool single_folder = false;
1787 bool only_folders = selection_only_contains_folders (selection);1921 bool only_folders = selection_only_contains_folders (selection);
1788 bool can_rename = false;1922 bool can_rename = false;
17891923
1790 update_default_app (selection);1924 update_default_app (selection);
17911925
1792 if (selection_count > 0) {1926 if (selection_count > 0) {
1793 unowned GOF.File? file = selection.data;1927 file = selection.data;
1794 if (file != null) {1928 if (file != null) {
1795 single_folder = (!more_than_one_selected && file.is_folder ());1929 single_folder = (!more_than_one_selected && file.is_folder ());
1796 can_rename = file.is_writable ();1930 can_rename = file.is_writable ();
1797 } else1931 } else
1798 critical ("File in selection is null");1932 critical ("File in selection is null");
1933 } else {
1934 file = slot.directory.file;
1935 single_folder = (!more_than_one_selected && file.is_folder ());
1799 }1936 }
18001937
1801 update_paste_action_enabled (single_folder);1938 update_paste_action_enabled (single_folder);
@@ -1806,8 +1943,18 @@
1806 action_set_enabled (selection_actions, "rename", selection_count == 1 && can_rename);1943 action_set_enabled (selection_actions, "rename", selection_count == 1 && can_rename);
1807 action_set_enabled (selection_actions, "open", selection_count == 1);1944 action_set_enabled (selection_actions, "open", selection_count == 1);
1808 action_set_enabled (selection_actions, "cut", selection_count > 0);1945 action_set_enabled (selection_actions, "cut", selection_count > 0);
1946 action_set_enabled (selection_actions, "trash", slot.directory.has_trash_dirs);
1947
1948 /* Both folder and file can be bookmarked if local, but only remote folders can be bookmarked
1949 * because remote file bookmarks do not work correctly for unmounted locations */
1950 bool can_bookmark = (!more_than_one_selected || single_folder) &&
1951 (slot.directory.is_local ||
1952 (file.get_ftype () != null && file.get_ftype () == "inode/directory") ||
1953 file.is_smb_server ());
1954
1955 action_set_enabled (common_actions, "bookmark", can_bookmark);
1809 /* TODO inhibit copy for unreadable files see bug #1392465*/1956 /* TODO inhibit copy for unreadable files see bug #1392465*/
1810 action_set_enabled (common_actions, "copy", true); 1957 action_set_enabled (common_actions, "copy", !in_trash);
1811 action_set_enabled (common_actions, "bookmark", !more_than_one_selected);1958 action_set_enabled (common_actions, "bookmark", !more_than_one_selected);
1812 }1959 }
18131960
@@ -1915,13 +2062,19 @@
1915 unowned GLib.List<AppInfo> l = open_with_apps;2062 unowned GLib.List<AppInfo> l = open_with_apps;
19162063
1917 while (l != null) {2064 while (l != null) {
1918 exec_name = l.data.get_executable ();2065 if (l.data is AppInfo) {
2066 exec_name = l.data.get_executable ();
19192067
1920 if (exec_name != null && (exec_name == APP_NAME || exec_name == TERMINAL_NAME)) {2068 if (exec_name != null && (exec_name == APP_NAME || exec_name == TERMINAL_NAME)) {
2069 open_with_apps.delete_link (l);
2070 break;
2071 }
2072 } else {
1921 open_with_apps.delete_link (l);2073 open_with_apps.delete_link (l);
1922 break;2074 l = open_with_apps;
2075 if (l == null)
2076 break;
1923 }2077 }
1924
1925 l = l.next;2078 l = l.next;
1926 }2079 }
1927 }2080 }
@@ -1936,7 +2089,7 @@
1936 if (id2 != null) {2089 if (id2 != null) {
1937 unowned GLib.List<AppInfo> l = open_with_apps;2090 unowned GLib.List<AppInfo> l = open_with_apps;
19382091
1939 while (l != null) {2092 while (l != null && l.data is AppInfo) {
1940 id1 = l.data.get_id ();2093 id1 = l.data.get_id ();
19412094
1942 if (id1 != null && id1 == id2) {2095 if (id1 != null && id1 == id2) {
@@ -1975,10 +2128,13 @@
1975 * all items have been added and we've perhaps scrolled to the file remembered2128 * all items have been added and we've perhaps scrolled to the file remembered
1976 * the last time */2129 * the last time */
19772130
1978 if (thumbnail_source_id != 0 || !(slot is GOF.AbstractSlot) || slot.directory == null)2131 if (thumbnail_source_id != 0 ||
2132 !(slot is GOF.AbstractSlot) ||
2133 slot.directory == null ||
2134 !slot.directory.is_local)
2135
1979 return;2136 return;
19802137
1981 cancel_thumbnailing ();
1982 thumbnail_source_id = GLib.Timeout.add (175, () => {2138 thumbnail_source_id = GLib.Timeout.add (175, () => {
1983 if (!(slot is GOF.AbstractSlot) || slot.directory == null)2139 if (!(slot is GOF.AbstractSlot) || slot.directory == null)
1984 return false;2140 return false;
@@ -1986,6 +2142,8 @@
1986 if (slot.directory.is_loading ())2142 if (slot.directory.is_loading ())
1987 return true;2143 return true;
19882144
2145 cancel_thumbnailing ();
2146
1989 /* compute visible item range */2147 /* compute visible item range */
1990 Gtk.TreePath start_path, end_path, path;2148 Gtk.TreePath start_path, end_path, path;
1991 Gtk.TreeIter iter;2149 Gtk.TreeIter iter;
@@ -2036,7 +2194,7 @@
2036 }2194 }
20372195
2038 private void load_thumbnails (GOF.Directory.Async dir, Marlin.ZoomLevel zoom) {2196 private void load_thumbnails (GOF.Directory.Async dir, Marlin.ZoomLevel zoom) {
2039 /* Async function checks dir is not loading */2197 /* Async function checks dir is not loading and dir is local */
2040 dir.queue_load_thumbnails (Marlin.zoom_level_to_icon_size (zoom));2198 dir.queue_load_thumbnails (Marlin.zoom_level_to_icon_size (zoom));
2041 }2199 }
20422200
@@ -2143,6 +2301,7 @@
2143 return;2301 return;
21442302
2145 notify_selection_changed ();2303 notify_selection_changed ();
2304 update_menu_actions ();
2146 }2305 }
21472306
2148 protected virtual bool on_view_key_press_event (Gdk.EventKey event) {2307 protected virtual bool on_view_key_press_event (Gdk.EventKey event) {
@@ -2157,6 +2316,7 @@
2157 bool other_mod_pressed = (((mods & ~Gdk.ModifierType.SHIFT_MASK) & ~Gdk.ModifierType.CONTROL_MASK) != 0);2316 bool other_mod_pressed = (((mods & ~Gdk.ModifierType.SHIFT_MASK) & ~Gdk.ModifierType.CONTROL_MASK) != 0);
2158 bool only_control_pressed = control_pressed && !other_mod_pressed; /* Shift can be pressed */2317 bool only_control_pressed = control_pressed && !other_mod_pressed; /* Shift can be pressed */
2159 bool only_alt_pressed = alt_pressed && ((mods & ~Gdk.ModifierType.MOD1_MASK) == 0);2318 bool only_alt_pressed = alt_pressed && ((mods & ~Gdk.ModifierType.MOD1_MASK) == 0);
2319 bool in_trash = slot.location.has_uri_scheme ("trash");
21602320
2161 switch (event.keyval) {2321 switch (event.keyval) {
2162 case Gdk.Key.F10:2322 case Gdk.Key.F10:
@@ -2167,7 +2327,7 @@
2167 break;2327 break;
21682328
2169 case Gdk.Key.F2:2329 case Gdk.Key.F2:
2170 if (no_mods) {2330 if (no_mods && selection_actions.get_action_enabled ("rename")) {
2171 rename_selected_file ();2331 rename_selected_file ();
2172 return true;2332 return true;
2173 }2333 }
@@ -2176,17 +2336,21 @@
2176 case Gdk.Key.Delete:2336 case Gdk.Key.Delete:
2177 case Gdk.Key.KP_Delete:2337 case Gdk.Key.KP_Delete:
2178 if (no_mods) {2338 if (no_mods) {
2179 trash_or_delete_selected_files (false);2339 /* If already in trash, permanently delete the file */
2340 trash_or_delete_selected_files (in_trash);
2180 return true;2341 return true;
2181 } else if (only_shift_pressed) {2342 } else if (only_shift_pressed) {
2182 trash_or_delete_selected_files (true);2343 trash_or_delete_selected_files (true);
2183 return true;2344 return true;
2345 } else if (only_shift_pressed && !renaming) {
2346 delete_selected_files ();
2347 return true;
2184 }2348 }
2185 break;2349 break;
21862350
2187 case Gdk.Key.space:2351 case Gdk.Key.space:
2188 if (view_has_focus ()) {2352 if (view_has_focus ()) {
2189 if (only_shift_pressed)2353 if (only_shift_pressed && !in_trash)
2190 activate_selected_items (Marlin.OpenFlag.NEW_TAB);2354 activate_selected_items (Marlin.OpenFlag.NEW_TAB);
2191 else if (no_mods)2355 else if (no_mods)
2192 preview_selected_items ();2356 preview_selected_items ();
@@ -2199,7 +2363,9 @@
21992363
2200 case Gdk.Key.Return:2364 case Gdk.Key.Return:
2201 case Gdk.Key.KP_Enter:2365 case Gdk.Key.KP_Enter:
2202 if (only_shift_pressed)2366 if (in_trash)
2367 return false;
2368 else if (only_shift_pressed)
2203 activate_selected_items (Marlin.OpenFlag.NEW_TAB);2369 activate_selected_items (Marlin.OpenFlag.NEW_TAB);
2204 else if (no_mods)2370 else if (no_mods)
2205 activate_selected_items (Marlin.OpenFlag.DEFAULT);2371 activate_selected_items (Marlin.OpenFlag.DEFAULT);
@@ -2209,14 +2375,14 @@
2209 return true;2375 return true;
22102376
2211 case Gdk.Key.T:2377 case Gdk.Key.T:
2212 if (only_control_pressed) {2378 if (only_control_pressed && !in_trash) {
2213 open_selected_in_terminal ();2379 open_selected_in_terminal ();
2214 return true;2380 return true;
2215 }2381 }
2216 break;2382 break;
22172383
2218 case Gdk.Key.N:2384 case Gdk.Key.N:
2219 if (only_control_pressed) {2385 if (only_control_pressed && !in_trash) {
2220 activate_selected_items (Marlin.OpenFlag.NEW_TAB);2386 activate_selected_items (Marlin.OpenFlag.NEW_TAB);
2221 return true;2387 return true;
2222 }2388 }
@@ -2224,7 +2390,16 @@
22242390
2225 case Gdk.Key.c:2391 case Gdk.Key.c:
2226 if (only_control_pressed) {2392 if (only_control_pressed) {
2227 common_actions.activate_action ("copy", null);2393 /* Should not copy files in the trash - cut instead */
2394 if (in_trash) {
2395 Eel.show_warning_dialog (_("Cannot copy files that are in the trash"),
2396 _("Cutting the selection instead"),
2397 window as Gtk.Window);
2398
2399 selection_actions.activate_action ("cut", null);
2400 } else
2401 common_actions.activate_action ("copy", null);
2402
2228 return true;2403 return true;
2229 }2404 }
2230 break;2405 break;
@@ -2235,7 +2410,6 @@
2235 action_set_enabled (common_actions, "paste_into", true);2410 action_set_enabled (common_actions, "paste_into", true);
2236 unselect_all ();2411 unselect_all ();
2237 common_actions.activate_action ("paste_into", null);2412 common_actions.activate_action ("paste_into", null);
2238 update_menu_actions ();
2239 return true;2413 return true;
2240 }2414 }
2241 break;2415 break;
@@ -2331,8 +2505,15 @@
2331 (path == null && hover_path != null) ||2505 (path == null && hover_path != null) ||
2332 (path != null && hover_path != null && path.compare (hover_path) != 0)) {2506 (path != null && hover_path != null && path.compare (hover_path) != 0)) {
23332507
2334 window.item_hovered (file);2508 /* cannot get file info while network disconnected */
2335 hover_path = path;2509 if (slot.directory.is_local || slot.directory.check_network ()) {
2510 /* cannot get file info while network disconnected */
2511 window.item_hovered (file);
2512 hover_path = path;
2513 } else {
2514 slot.reload ();
2515 slot.directory.need_reload ();
2516 }
2336 }2517 }
23372518
2338 return false;2519 return false;
@@ -2388,13 +2569,13 @@
2388 }2569 }
23892570
2390 protected void on_name_editing_canceled () {2571 protected void on_name_editing_canceled () {
2391 if (!renaming)2572 if (!renaming)
2392 return;2573 return;
23932574
2394 renaming = false;2575 renaming = false;
2395 name_renderer.editable = false;2576 name_renderer.editable = false;
2396 unfreeze_updates ();2577 unfreeze_updates ();
2397 grab_focus ();2578 grab_focus ();
2398 }2579 }
23992580
2400 protected void on_name_edited (string path_string, string new_name) {2581 protected void on_name_edited (string path_string, string new_name) {
@@ -2416,9 +2597,11 @@
2416 new_name);2597 new_name);
2417 dialog.run ();2598 dialog.run ();
2418 dialog.destroy ();2599 dialog.destroy ();
2419 on_name_editing_canceled ();2600 new_name = "";
2420 }2601 }
2602 }
24212603
2604 if (new_name != "") {
2422 var path = new Gtk.TreePath.from_string (path_string);2605 var path = new Gtk.TreePath.from_string (path_string);
2423 Gtk.TreeIter? iter = null;2606 Gtk.TreeIter? iter = null;
2424 model.get_iter (out iter, path);2607 model.get_iter (out iter, path);
@@ -2437,6 +2620,9 @@
2437 }2620 }
24382621
2439 on_name_editing_canceled ();2622 on_name_editing_canceled ();
2623
2624 if (!slot.directory.is_local && new_name != original_name)
2625 slot.directory.need_reload ();
2440 }2626 }
24412627
2442 public virtual bool on_view_draw (Cairo.Context cr) {2628 public virtual bool on_view_draw (Cairo.Context cr) {
@@ -2738,8 +2924,6 @@
2738 warning ("Could not set file attributes - %s", e.message);2924 warning ("Could not set file attributes - %s", e.message);
2739 }2925 }
2740 });2926 });
2741
2742 update_menu_actions_sort ();
2743 }2927 }
27442928
2745 protected void cancel_timeout (ref uint id) {2929 protected void cancel_timeout (ref uint id) {
@@ -2810,9 +2994,6 @@
2810 protected abstract void freeze_tree ();2994 protected abstract void freeze_tree ();
2811 protected abstract void thaw_tree ();2995 protected abstract void thaw_tree ();
28122996
2813
2814
2815
2816/** Unimplemented methods2997/** Unimplemented methods
2817 * fm_directory_view_parent_set () - purpose unclear2998 * fm_directory_view_parent_set () - purpose unclear
2818*/ 2999*/
28193000
=== modified file 'src/View/ColumnView.vala'
--- src/View/ColumnView.vala 2014-12-26 14:20:20 +0000
+++ src/View/ColumnView.vala 2015-02-07 19:01:29 +0000
@@ -137,7 +137,7 @@
137 cancel_await_double_click ();137 cancel_await_double_click ();
138138
139 if (selected_folder != null)139 if (selected_folder != null)
140 load_root_location (selected_folder.location);140 load_root_location (selected_folder.get_target_location ());
141141
142 result = true;142 result = true;
143 }143 }
144144
=== modified file 'src/View/DiskRenderer.vala'
--- src/View/DiskRenderer.vala 2014-12-19 17:34:11 +0000
+++ src/View/DiskRenderer.vala 2015-02-07 19:01:29 +0000
@@ -23,10 +23,14 @@
23 public uint64 free_space { set; get; }23 public uint64 free_space { set; get; }
24 public uint64 disk_size { set; get; }24 public uint64 disk_size { set; get; }
2525
26 /* padding to the right of the disk usage graphic */
27 public uint rpad {set; get;}
28
26 /* offset to left align disk usage graphic with the text */29 /* offset to left align disk usage graphic with the text */
27 private int offset = 2;30 private int offset = 2;
2831
29 public CellRendererDisk () {32 public CellRendererDisk () {
33 rpad = 0;
30 }34 }
3135
32 /**36 /**
@@ -54,6 +58,7 @@
54 Gtk.StateFlags state;58 Gtk.StateFlags state;
55 Gtk.StyleContext context = widget.get_parent ().get_style_context ();59 Gtk.StyleContext context = widget.get_parent ().get_style_context ();
56 cr.set_line_width (1.0);60 cr.set_line_width (1.0);
61 uint width = area.width - rpad;
57 if (widget.get_state_flags () != Gtk.StateFlags.BACKDROP) {62 if (widget.get_state_flags () != Gtk.StateFlags.BACKDROP) {
58 state = Gtk.StateFlags.NORMAL;63 state = Gtk.StateFlags.NORMAL;
59 state |= widget.get_state_flags ();64 state |= widget.get_state_flags ();
@@ -62,7 +67,7 @@
62 Gdk.cairo_set_source_rgba (cr, color_border);67 Gdk.cairo_set_source_rgba (cr, color_border);
63 cr.rectangle (area.x,68 cr.rectangle (area.x,
64 area.y + area.height - 3,69 area.y + area.height - 3,
65 area.width,70 width,
66 4);71 4);
67 cr.fill ();72 cr.fill ();
68 }73 }
@@ -71,14 +76,14 @@
71 Gdk.cairo_set_source_rgba (cr, context.get_color (state));76 Gdk.cairo_set_source_rgba (cr, context.get_color (state));
72 cr.rectangle (area.x + 1,77 cr.rectangle (area.x + 1,
73 area.y + area.height - 2,78 area.y + area.height - 2,
74 area.width - 2,79 width - 2,
75 2);80 2);
76 cr.fill ();81 cr.fill ();
7782
78 Gdk.cairo_set_source_rgba (cr, context.get_background_color(state));83 Gdk.cairo_set_source_rgba (cr, context.get_background_color(state));
79 cr.rectangle (area.x + 1,84 cr.rectangle (area.x + 1,
80 area.y + area.height - 2,85 area.y + area.height - 2,
81 area.width - (int)(((double)free_space)/((double)disk_size)*((double)area.width - 2)),86 width - (int)(((double)free_space)/((double)disk_size)*((double)area.width - 2)),
82 2);87 2);
83 cr.stroke ();88 cr.stroke ();
84 }89 }
8590
=== modified file 'src/View/LocationBar.vala'
--- src/View/LocationBar.vala 2015-01-24 13:51:05 +0000
+++ src/View/LocationBar.vala 2015-02-07 19:01:29 +0000
@@ -92,8 +92,8 @@
92 bread.search_mode = true;92 bread.search_mode = true;
93 }93 }
9494
95 private void on_path_changed (File file) {95 private void on_path_changed (File? file) {
96 if (win.freeze_view_changes)96 if (file == null || win.freeze_view_changes)
97 return;97 return;
9898
99 win.grab_focus ();99 win.grab_focus ();
@@ -136,14 +136,15 @@
136 {136 {
137 this.win = win;137 this.win = win;
138 /* FIXME the string split of the path url is kinda too basic, we should use the Gile to split our uris and determine the protocol (if any) with g_uri_parse_scheme or g_file_get_uri_scheme */138 /* FIXME the string split of the path url is kinda too basic, we should use the Gile to split our uris and determine the protocol (if any) with g_uri_parse_scheme or g_file_get_uri_scheme */
139 add_icon ({ "afp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("AFP")});139 add_icon ({ "afp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_AFP});
140 add_icon ({ "dav://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("DAV")});140 add_icon ({ "dav://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_DAV});
141 add_icon ({ "davs://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("DAVS")});141 add_icon ({ "davs://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true,Marlin.PROTOCOL_NAME_DAVS});
142 add_icon ({ "ftp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("FTP")});142 add_icon ({ "ftp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_FTP});
143 add_icon ({ "network://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("Network")});143 add_icon ({ "network://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_NETWORK});
144 add_icon ({ "sftp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("SFTP")});144 add_icon ({ "sftp://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_SFTP});
145 add_icon ({ "smb://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true, _("SMB")});145 add_icon ({ "smb://", Marlin.ICON_FOLDER_REMOTE_SYMBOLIC, true, null, null, null, true,Marlin.PROTOCOL_NAME_SMB});
146 add_icon ({ "trash://", Marlin.ICON_TRASH_SYMBOLIC, true, null, null, null, true, _("Trash")});146 add_icon ({ "trash://", Marlin.ICON_TRASH_SYMBOLIC, true, null, null, null, true, Marlin.PROTOCOL_NAME_TRASH});
147
147148
148 /* music */149 /* music */
149 string dir;150 string dir;
@@ -233,12 +234,12 @@
233 completed.connect (() => {234 completed.connect (() => {
234 string path = "";235 string path = "";
235 string newpath = update_breadcrumbs (get_file_for_path (text).get_uri (), path);236 string newpath = update_breadcrumbs (get_file_for_path (text).get_uri (), path);
236 237
237 foreach (BreadcrumbsElement element in elements) {238 foreach (BreadcrumbsElement element in elements) {
238 if (!element.hidden)239 if (!element.hidden)
239 path += element.text + "/";240 path += element.text + "/";
240 }241 }
241 242
242 if (path != newpath)243 if (path != newpath)
243 change_breadcrumbs (newpath);244 change_breadcrumbs (newpath);
244 245
@@ -320,9 +321,12 @@
320 }321 }
321322
322 public void on_need_completion () {323 public void on_need_completion () {
323 File file = get_file_for_path (text);324 File? file = get_file_for_path (text);
324325
325 // don't use get_basename (), it will return "folder" for "/folder/"326 if (file == null)
327 return;
328
329 /* don't use get_basename (), it will return "folder" for "/folder/" */
326 int last_slash = text.last_index_of_char ('/');330 int last_slash = text.last_index_of_char ('/');
327 if (last_slash > -1 && last_slash < text.length)331 if (last_slash > -1 && last_slash < text.length)
328 to_search = text.slice (last_slash + 1, text.length);332 to_search = text.slice (last_slash + 1, text.length);
@@ -338,20 +342,19 @@
338 return;342 return;
339 343
340 files = GOF.Directory.Async.from_gfile (file);344 files = GOF.Directory.Async.from_gfile (file);
341 if (files.file.exists) {345 if (files.file.exists)
342 files.load (on_file_loaded);346 files.load (on_file_loaded);
343 }
344 }347 }
345348
346 private void on_files_loaded_menu () {349 private void on_files_loaded_menu () {
347 // First the "Open in new tab" menuitem is added to the menu.350 /* First the "Open in new tab" menuitem is added to the menu. */
348 var menuitem_newtab = new Gtk.MenuItem.with_label (_("Open in New Tab"));351 var menuitem_newtab = new Gtk.MenuItem.with_label (_("Open in New Tab"));
349 menu.append (menuitem_newtab);352 menu.append (menuitem_newtab);
350 menuitem_newtab.activate.connect (() => {353 menuitem_newtab.activate.connect (() => {
351 win.add_tab (File.new_for_uri (current_right_click_path), Marlin.ViewMode.CURRENT);354 win.add_tab (File.new_for_commandline_arg (current_right_click_path), Marlin.ViewMode.CURRENT);
352 });355 });
353356
354 // Then the "Open with" menuitem is added to the menu.357 /* Then the "Open with" menuitem is added to the menu. */
355 var menu_open_with = new Gtk.MenuItem.with_label (_("Open with"));358 var menu_open_with = new Gtk.MenuItem.with_label (_("Open with"));
356 menu.append (menu_open_with);359 menu.append (menu_open_with);
357360
@@ -432,12 +435,15 @@
432 }435 }
433436
434 protected override void load_right_click_menu (double x, double y) {437 protected override void load_right_click_menu (double x, double y) {
438 if (current_right_click_root == null)
439 return;
440
435 menu_x_root = x;441 menu_x_root = x;
436 menu_y_root = y;442 menu_y_root = y;
437 menu = new Gtk.Menu ();443 menu = new Gtk.Menu ();
438 menu.cancel.connect (() => { reset_elements_states (); });444 menu.cancel.connect (() => { reset_elements_states (); });
439 menu.deactivate.connect (() => { reset_elements_states (); });445 menu.deactivate.connect (() => { reset_elements_states (); });
440 /* current_right_click_root is parent of the directory named on the breadcrumb. */ 446 /* current_right_click_root is parent of the directory named on the breadcrumb. */
441 var directory = File.new_for_uri (current_right_click_root);447 var directory = File.new_for_uri (current_right_click_root);
442 files_menu = GOF.Directory.Async.from_gfile (directory);448 files_menu = GOF.Directory.Async.from_gfile (directory);
443 files_menu.done_loading.connect (on_files_loaded_menu);449 files_menu.done_loading.connect (on_files_loaded_menu);
444450
=== modified file 'src/View/OverlayBar.vala'
--- src/View/OverlayBar.vala 2015-01-16 17:08:14 +0000
+++ src/View/OverlayBar.vala 2015-02-07 19:01:29 +0000
@@ -130,11 +130,10 @@
130 } else if (!goffile.is_folder ()) {130 } else if (!goffile.is_folder ()) {
131131
132 /* if we have an image, see if we can get its resolution */132 /* if we have an image, see if we can get its resolution */
133 var type = goffile.get_ftype ();133 string? type = goffile.get_ftype ();
134 if (type.substring (0, 6) == "image/" && !(type in SKIP_IMAGES)) {134 if (type != null && type.substring (0, 6) == "image/" && !(type in SKIP_IMAGES)) {
135 load_resolution.begin (goffile);135 load_resolution.begin (goffile);
136 }136 }
137
138 status = "%s (%s)".printf (goffile.formated_type, format_size ((int64) PropertiesWindow.file_real_size (goffile)));137 status = "%s (%s)".printf (goffile.formated_type, format_size ((int64) PropertiesWindow.file_real_size (goffile)));
139 } else {138 } else {
140 status = "%s - %s".printf (goffile.info.get_name (), goffile.formated_type);139 status = "%s - %s".printf (goffile.info.get_name (), goffile.formated_type);
141140
=== modified file 'src/View/PropertiesWindow.vala'
--- src/View/PropertiesWindow.vala 2015-01-17 04:26:34 +0000
+++ src/View/PropertiesWindow.vala 2015-02-07 19:01:29 +0000
@@ -1362,16 +1362,22 @@
1362 }1362 }
13631363
1364 public static uint64 file_real_size (GOF.File gof) {1364 public static uint64 file_real_size (GOF.File gof) {
1365 if (!gof.is_connected)
1366 return 0;
1367
1365 uint64 file_size = gof.size;1368 uint64 file_size = gof.size;
1366 try {1369 if (gof.location is GLib.File) {
1367 var info = gof.location.query_info (FileAttribute.STANDARD_ALLOCATED_SIZE, FileQueryInfoFlags.NONE);1370 try {
1368 uint64 allocated_size = info.get_attribute_uint64 (FileAttribute.STANDARD_ALLOCATED_SIZE);1371 var info = gof.location.query_info (FileAttribute.STANDARD_ALLOCATED_SIZE, FileQueryInfoFlags.NONE);
1369 // Check for sparse file, allocated size will be smaller, for normal files allocated size1372 uint64 allocated_size = info.get_attribute_uint64 (FileAttribute.STANDARD_ALLOCATED_SIZE);
1370 // includes overhead size so we don't use it for those here1373 // Check for sparse file, allocated size will be smaller, for normal files allocated size
1371 if (allocated_size < file_size && !gof.is_directory)1374 // includes overhead size so we don't use it for those here
1372 file_size = allocated_size;1375 if (allocated_size < file_size && !gof.is_directory)
1373 } catch (Error err) {1376 file_size = allocated_size;
1374 warning ("%s", err.message);1377 } catch (Error err) {
1378 warning ("%s", err.message);
1379 gof.is_connected = false;
1380 }
1375 }1381 }
1376 return file_size;1382 return file_size;
1377 }1383 }
13781384
=== modified file 'src/View/Resources.vala'
--- src/View/Resources.vala 2014-11-13 20:24:33 +0000
+++ src/View/Resources.vala 2015-02-07 19:01:29 +0000
@@ -52,4 +52,56 @@
52 public const string NETWORK_URI = "network:///";52 public const string NETWORK_URI = "network:///";
5353
54 public const string OPEN_IN_TERMINAL_DESKTOP_ID = "open-pantheon-terminal-here.desktop";54 public const string OPEN_IN_TERMINAL_DESKTOP_ID = "open-pantheon-terminal-here.desktop";
55
56 public const string PROTOCOL_NAME_AFP = _("AFP");
57 public const string PROTOCOL_NAME_DAV = _("DAV");
58 public const string PROTOCOL_NAME_DAVS = _("DAVS");
59 public const string PROTOCOL_NAME_FTP = _("FTP");
60 public const string PROTOCOL_NAME_NETWORK = _("Network");
61 public const string PROTOCOL_NAME_SFTP = _("SFTP");
62 public const string PROTOCOL_NAME_SMB = _("SMB");
63 public const string PROTOCOL_NAME_TRASH = _("Trash");
64
65 public string protocol_to_name (string protocol) {
66 /* Deal with protocol with or without : or / characters at the end */
67 string s = protocol.delimit (":/", ' ').chomp ();
68
69 switch (s) {
70 case "trash":
71 return Marlin.PROTOCOL_NAME_TRASH;
72 case "network":
73 return Marlin.PROTOCOL_NAME_NETWORK;
74 case "smb":
75 return Marlin.PROTOCOL_NAME_SMB;
76 case "ftp":
77 return Marlin.PROTOCOL_NAME_FTP;
78 case "sftp":
79 return Marlin.PROTOCOL_NAME_SFTP;
80 case "afp":
81 return Marlin.PROTOCOL_NAME_AFP;
82 case "dav":
83 return Marlin.PROTOCOL_NAME_DAV;
84 case "davs":
85 return Marlin.PROTOCOL_NAME_DAVS;
86 default:
87 return protocol;
88 }
89 }
90
91 public string get_smb_share_from_uri (string uri) {
92 if (!(Uri.parse_scheme (uri) == "smb"))
93 return (uri);
94
95 string [] uri_parts = uri.split (Path.DIR_SEPARATOR_S);
96
97 if (uri_parts.length < 4)
98 return uri;
99 else {
100 var sb = new StringBuilder ();
101 for (int i = 0; i < 4; i++)
102 sb.append (uri_parts [i] + Path.DIR_SEPARATOR_S);
103
104 return sb.str;
105 }
106 }
55}107}
56108
=== modified file 'src/View/Sidebar.vala'
--- src/View/Sidebar.vala 2015-01-27 14:20:52 +0000
+++ src/View/Sidebar.vala 2015-02-07 19:01:29 +0000
@@ -33,9 +33,8 @@
3333
34 private const int MAX_BOOKMARKS_DROPPED = 100;34 private const int MAX_BOOKMARKS_DROPPED = 100;
35 private const int ROOT_INDENTATION_XPAD = 2;35 private const int ROOT_INDENTATION_XPAD = 2;
36 private const int EJECT_BUTTON_XPAD = 12;36 private const int EJECT_BUTTON_XPAD = 6;
37 private const int TEXT_XPAD = 5;37 private const int ICON_XPAD = 6 + ROOT_INDENTATION_XPAD;
38 private const int ICON_XPAD = 6;
39 private const int PROP_0 = 0;38 private const int PROP_0 = 0;
40 private const int PROP_ZOOM_LEVEL = 1;39 private const int PROP_ZOOM_LEVEL = 1;
4140
@@ -55,6 +54,7 @@
55 Gtk.IconTheme theme;54 Gtk.IconTheme theme;
56 GLib.Icon eject_icon;55 GLib.Icon eject_icon;
5756
57 int eject_button_size = 20;
58 uint n_builtins_before;58 uint n_builtins_before;
59 string last_selected_uri;59 string last_selected_uri;
60 string slot_location;60 string slot_location;
@@ -125,7 +125,7 @@
125125
126 /* TODO Make it an option in Settings whether or not to show126 /* TODO Make it an option in Settings whether or not to show
127 * bookmarks pointing to non-existent (or unmounted) files. */127 * bookmarks pointing to non-existent (or unmounted) files. */
128 bool display_all_bookmarks = false;128 bool display_all_bookmarks = true;
129129
130 /* Remember vertical adjustment value when lose focus */130 /* Remember vertical adjustment value when lose focus */
131 double adjustment_val = 0.0;131 double adjustment_val = 0.0;
@@ -160,32 +160,30 @@
160 tree_view.set_size_request (Preferences.settings.get_int ("minimum-sidebar-width"), -1);160 tree_view.set_size_request (Preferences.settings.get_int ("minimum-sidebar-width"), -1);
161 tree_view.set_headers_visible (false);161 tree_view.set_headers_visible (false);
162162
163 var col = new Gtk.TreeViewColumn ();163 var cab = new Gtk.CellAreaBox ();
164 var col = new Gtk.TreeViewColumn.with_area (cab);
164 col.max_width = -1;165 col.max_width = -1;
165 col.expand = true;166 col.expand = true;
166 col.spacing = 3;167 col.spacing = 3;
167168
168 var crt = new Gtk.CellRendererText ();169 var crt = new Gtk.CellRendererText ();
169 col.pack_start(crt, false);
170 col.set_cell_data_func (crt, root_indent_cell_data_func);
171
172 crt = new Gtk.CellRendererText ();
173 this.indent_renderer = crt;170 this.indent_renderer = crt;
174 col.pack_start(crt, false);171 cab.pack_start(crt, false, false, false);
175 col.set_cell_data_func (crt, indent_cell_data_func);172 col.set_cell_data_func (crt, indent_cell_data_func);
176173
177 var crpb = new Gtk.CellRendererPixbuf ();174 var crpb = new Gtk.CellRendererPixbuf ();
178 this.icon_cell_renderer = crpb;175 this.icon_cell_renderer = crpb;
179 crpb.follow_state = true;176 crpb.follow_state = true;
180 crpb.stock_size = Gtk.IconSize.MENU;177 crpb.stock_size = Gtk.IconSize.MENU;
181 col.pack_start(crpb, false);178 cab.pack_start(crpb, false, false, false);
182 col.set_attributes (crpb, "gicon", Column.ICON);179 col.set_attributes (crpb, "gicon", Column.ICON);
183 col.set_cell_data_func (crpb, icon_cell_data_func);180 col.set_cell_data_func (crpb, icon_cell_data_func);
184181
185 var crd = new Marlin.CellRendererDisk ();182 var crd = new Marlin.CellRendererDisk ();
186 crd.ellipsize = Pango.EllipsizeMode.END;183 crd.ellipsize = Pango.EllipsizeMode.END;
187 crd.ellipsize_set = true;184 crd.ellipsize_set = true;
188 col.pack_start (crd, true);185 crd.rpad = 12;
186 cab.pack_start (crd, true, false, false);
189 col.set_attributes (crd,187 col.set_attributes (crd,
190 "text", Column.NAME,188 "text", Column.NAME,
191 "visible", Column.EJECT,189 "visible", Column.EJECT,
@@ -196,9 +194,9 @@
196 eject_spinner_cell_renderer = crs;194 eject_spinner_cell_renderer = crs;
197 crs.mode = Gtk.CellRendererMode.ACTIVATABLE;195 crs.mode = Gtk.CellRendererMode.ACTIVATABLE;
198 crs.icon_size = Gtk.IconSize.MENU;196 crs.icon_size = Gtk.IconSize.MENU;
199 crs.xpad = EJECT_BUTTON_XPAD;197 crs.xpad = 0;
200 crs.xalign = (float)1.0;198 crs.xalign = (float)1.0;
201 col.pack_start (crs, false);199 cab.pack_start (crs, false, false, false);
202 col.set_attributes (crs,200 col.set_attributes (crs,
203 "gicon", Column.EJECT_ICON,201 "gicon", Column.EJECT_ICON,
204 "visible", Column.EJECT,202 "visible", Column.EJECT,
@@ -212,7 +210,7 @@
212 name_renderer.ellipsize_set = true;210 name_renderer.ellipsize_set = true;
213 name_renderer.edited.connect (edited);211 name_renderer.edited.connect (edited);
214 name_renderer.editing_canceled.connect (editing_canceled);212 name_renderer.editing_canceled.connect (editing_canceled);
215 col.pack_start (name_renderer,true);213 cab.pack_start (name_renderer,true, false, false);
216 col.set_attributes (name_renderer,214 col.set_attributes (name_renderer,
217 "text", Column.NAME,215 "text", Column.NAME,
218 "visible", Column.NO_EJECT,216 "visible", Column.NO_EJECT,
@@ -225,11 +223,16 @@
225 cre.is_category_expander = true;223 cre.is_category_expander = true;
226 /* this is required to align the eject buttons to the right */224 /* this is required to align the eject buttons to the right */
227 int exp_size = cre.get_arrow_size (tree_view);225 int exp_size = cre.get_arrow_size (tree_view);
228 cre.xpad = (16 - exp_size).abs () + EJECT_BUTTON_XPAD - 2;226 Gtk.icon_size_lookup (Gtk.IconSize.MENU, out eject_button_size, null);
229 cre.xalign = (float)1.0;227 cre.xpad = int.max ((eject_button_size - exp_size)/2, 0);
230 col.pack_end (cre, false);228 cab.pack_start (cre, false, false, false);
231 col.set_cell_data_func (cre, expander_cell_data_func);229 col.set_cell_data_func (cre, expander_cell_data_func);
232230
231 crt = new Gtk.CellRendererText ();
232 crt.xpad = EJECT_BUTTON_XPAD;
233 crt.xalign = (float)1.0;
234 cab.pack_start(crt, false, false, false);
235
233 tree_view.append_column (col);236 tree_view.append_column (col);
234 tree_view.tooltip_column = Column.TOOLTIP;237 tree_view.tooltip_column = Column.TOOLTIP;
235 tree_view.model = this.store;238 tree_view.model = this.store;
@@ -249,7 +252,9 @@
249 tree_view.enable_model_drag_source (Gdk.ModifierType.BUTTON1_MASK,252 tree_view.enable_model_drag_source (Gdk.ModifierType.BUTTON1_MASK,
250 source_targets,253 source_targets,
251 Gdk.DragAction.MOVE);254 Gdk.DragAction.MOVE);
252 Gtk.drag_dest_set (tree_view, Gtk.DestDefaults.MOTION, drop_targets,255 Gtk.drag_dest_set (tree_view,
256 Gtk.DestDefaults.MOTION,
257 drop_targets,
253 Gdk.DragAction.MOVE | Gdk.DragAction.COPY | Gdk.DragAction.LINK);258 Gdk.DragAction.MOVE | Gdk.DragAction.COPY | Gdk.DragAction.LINK);
254 }259 }
255260
@@ -564,13 +569,17 @@
564 if (volume != null)569 if (volume != null)
565 continue;570 continue;
566571
572
567 var root = mount.get_default_location ();573 var root = mount.get_default_location ();
568 if (root.is_native ()) {574 if (root.is_native ()) {
569 string scheme = root.get_uri_scheme ();575 string scheme = root.get_uri_scheme ();
570 if (scheme == "archive") {576 if (scheme == "archive" ) {
571 network_mounts.prepend (mount);577 network_mounts.prepend (mount);
572 continue;578 continue;
573 }579 }
580 } else {
581 network_mounts.prepend (mount);
582 continue;
574 }583 }
575584
576 add_place (Marlin.PlaceType.MOUNTED_VOLUME,585 add_place (Marlin.PlaceType.MOUNTED_VOLUME,
@@ -602,16 +611,23 @@
602 network_mounts.reverse ();611 network_mounts.reverse ();
603 foreach (Mount mount in network_mounts) {612 foreach (Mount mount in network_mounts) {
604 var root = mount.get_default_location ();613 var root = mount.get_default_location ();
614 /* get_smb_share_from_uri will return the uri unaltered if does not have
615 * the smb scheme so we need not test. This is required because the mount
616 * does not return the true root location of the share but the location used
617 * when creating the mount.
618 */
619 string uri = Marlin.get_smb_share_from_uri (root.get_uri ());
620
605 add_place (Marlin.PlaceType.BUILT_IN,621 add_place (Marlin.PlaceType.BUILT_IN,
606 iter,622 iter,
607 mount.get_name (),623 mount.get_name (),
608 mount.get_icon (),624 mount.get_icon (),
609 root.get_uri (),625 uri,
610 null,626 null,
611 null,627 null,
612 mount,628 mount,
613 0,629 0,
614 root.get_parse_name ());630 uri);
615 }631 }
616632
617 /* Add Entire Network BUILTIN */633 /* Add Entire Network BUILTIN */
@@ -913,7 +929,7 @@
913 null,929 null,
914 File.new_for_uri (drop_uri),930 File.new_for_uri (drop_uri),
915 real_action,931 real_action,
916 null, null, null);932 this, null, null);
917 return true;933 return true;
918 case TargetType.GTK_TREE_MODEL_ROW:934 case TargetType.GTK_TREE_MODEL_ROW:
919 return false;935 return false;
@@ -964,12 +980,13 @@
964 if (can_accept_file_as_bookmark (file))980 if (can_accept_file_as_bookmark (file))
965 uris.prepend (file.get_uri ());981 uris.prepend (file.get_uri ());
966 });982 });
983
967 if (uris != null)984 if (uris != null)
968 bookmarks.insert_uris (uris, position);985 bookmarks.insert_uris (uris, position);
969 }986 }
970987
971 public void add_uri (string uri) {988 public void add_uri (string uri, string? label = null) {
972 bookmarks.insert_uri_at_end (uri);989 bookmarks.insert_uri_at_end (uri, label);
973 }990 }
974991
975 private bool drag_scroll_timer () {992 private bool drag_scroll_timer () {
@@ -1388,22 +1405,13 @@
1388 cell.set_visible (!store.iter_has_child (iter));1405 cell.set_visible (!store.iter_has_child (iter));
1389 }1406 }
13901407
1391 private void root_indent_cell_data_func (Gtk.CellLayout layout,
1392 Gtk.CellRenderer cell,
1393 Gtk.TreeModel model,
1394 Gtk.TreeIter iter) {
1395 cell.set_visible (true);
1396 cell.xpad = ROOT_INDENTATION_XPAD;
1397 }
1398
1399 private void indent_cell_data_func (Gtk.CellLayout layout,1408 private void indent_cell_data_func (Gtk.CellLayout layout,
1400 Gtk.CellRenderer cell,1409 Gtk.CellRenderer cell,
1401 Gtk.TreeModel model,1410 Gtk.TreeModel model,
1402 Gtk.TreeIter iter) {1411 Gtk.TreeIter iter) {
1403 var path = store.get_path (iter);1412 var path = store.get_path (iter);
1404 var depth = path.get_depth ();1413 var depth = path.get_depth ();
1405 cell.set_visible (depth > 1);1414 cell.xpad = depth > 1 ? ICON_XPAD : ROOT_INDENTATION_XPAD;
1406 cell.xpad = ICON_XPAD;
1407 }1415 }
14081416
1409 private void expander_cell_data_func (Gtk.CellLayout layout,1417 private void expander_cell_data_func (Gtk.CellLayout layout,
@@ -1460,8 +1468,9 @@
1460 Gtk.CellRenderer renderer,1468 Gtk.CellRenderer renderer,
1461 Gtk.TreeModel model,1469 Gtk.TreeModel model,
1462 Gtk.TreeIter iter) {1470 Gtk.TreeIter iter) {
1471
1472 var crt = renderer as Gtk.CellRendererText;
1463 Marlin.PlaceType type;1473 Marlin.PlaceType type;
1464 Gtk.CellRendererText crt = renderer as Gtk.CellRendererText;
1465 model.@get (iter, Column.ROW_TYPE, out type, -1);1474 model.@get (iter, Column.ROW_TYPE, out type, -1);
14661475
1467 if (type == Marlin.PlaceType.PERSONAL_CATEGORY ||1476 if (type == Marlin.PlaceType.PERSONAL_CATEGORY ||
@@ -1682,7 +1691,7 @@
1682 mount.unmount_with_operation.end (res);1691 mount.unmount_with_operation.end (res);
1683 }1692 }
1684 catch (GLib.Error error) {1693 catch (GLib.Error error) {
1685 warning ("Error while unmounting");1694 debug ("Error while unmounting");
1686 }1695 }
1687 finish_eject_or_unmount (row_ref);1696 finish_eject_or_unmount (row_ref);
1688 });1697 });
@@ -1690,17 +1699,16 @@
16901699
1691 private void empty_trash_on_mount (Mount? mount, Gtk.TreeRowReference? row_ref = null) {1700 private void empty_trash_on_mount (Mount? mount, Gtk.TreeRowReference? row_ref = null) {
1692 if (Marlin.FileOperations.has_trash_files (mount)) {1701 if (Marlin.FileOperations.has_trash_files (mount)) {
1693 unowned GLib.List<unowned GLib.File>? dirs = Marlin.FileOperations.get_trash_dirs_for_mount (mount);1702 unowned GLib.List<unowned GLib.File>? dirs = Marlin.FileOperations.get_trash_dirs_for_mount (mount);
1694 /* Marlin.FileOperations will show a confirm dialog according to settings */1703 /* Marlin.FileOperations will show a confirm dialog according to settings */
1695 if (dirs != null)1704 if (dirs != null)
1696 Marlin.FileOperations.empty_trash_dirs (null, dirs.copy ());1705 Marlin.FileOperations.empty_trash_dirs (null, dirs.copy ());
1697 }1706 }
1698 }1707 }
16991708
1700 private bool over_eject_button (int x, int y, out Gtk.TreePath p) {1709 private bool over_eject_button (int x, int y, out Gtk.TreePath p) {
1701 unowned Gtk.TreeViewColumn column;1710 unowned Gtk.TreeViewColumn column;
1702 int width, x_offset, hseparator;1711 int width, x_offset, hseparator;
1703 int eject_button_size;
1704 bool show_eject;1712 bool show_eject;
1705 Gtk.TreeIter iter;1713 Gtk.TreeIter iter;
1706 Gtk.TreePath path;1714 Gtk.TreePath path;
@@ -1723,8 +1731,7 @@
1723 column.cell_set_cell_data (store, iter, false, false);1731 column.cell_set_cell_data (store, iter, false, false);
1724 column.cell_get_position (eject_spinner_cell_renderer, out x_offset, out width);1732 column.cell_get_position (eject_spinner_cell_renderer, out x_offset, out width);
17251733
1726 eject_button_size = 20;1734 x_offset += width - hseparator - eject_button_size;
1727 x_offset += width - hseparator - EJECT_BUTTON_XPAD - eject_button_size;
1728 if (cell_x - x_offset >= 0 && cell_x - x_offset <= eject_button_size)1735 if (cell_x - x_offset >= 0 && cell_x - x_offset <= eject_button_size)
1729 return true;1736 return true;
1730 }1737 }
17311738
=== modified file 'src/View/Slot.vala'
--- src/View/Slot.vala 2015-01-25 20:40:53 +0000
+++ src/View/Slot.vala 2015-02-07 19:01:29 +0000
@@ -60,6 +60,7 @@
60 set_up_directory (_location);60 set_up_directory (_location);
61 connect_slot_signals ();61 connect_slot_signals ();
62 make_view ();62 make_view ();
63 connect_dir_view_signals ();
63 }64 }
6465
65 ~Slot () {66 ~Slot () {
@@ -107,12 +108,16 @@
107108
108 if (mode == Marlin.ViewMode.MILLER_COLUMNS)109 if (mode == Marlin.ViewMode.MILLER_COLUMNS)
109 autosize_slot ();110 autosize_slot ();
111
112 set_view_updates_frozen (false);
110 });113 });
111114
112 if (mode == Marlin.ViewMode.MILLER_COLUMNS)115 if (mode == Marlin.ViewMode.MILLER_COLUMNS)
113 directory.track_longest_name = true;116 directory.track_longest_name = true;
114117
115 directory.need_reload.connect (ctab.reload);118 directory.need_reload.connect (() => {
119 ctab.reload ();
120 });
116 }121 }
117122
118 private void schedule_path_change_request (GLib.File loc, int flag, bool make_root) {123 private void schedule_path_change_request (GLib.File loc, int flag, bool make_root) {
@@ -123,7 +128,7 @@
123 }128 }
124129
125 private void on_path_change_request (GLib.File loc, int flag, bool make_root) {130 private void on_path_change_request (GLib.File loc, int flag, bool make_root) {
126 if (flag == 0) {131 if (flag == 0) { /* make view in existing container */
127 if (dir_view is FM.ColumnView)132 if (dir_view is FM.ColumnView)
128 miller_slot_request (loc, make_root);133 miller_slot_request (loc, make_root);
129 else134 else
@@ -166,18 +171,13 @@
166171
167 public override void user_path_change_request (GLib.File loc, bool allow_mode_change = true) {172 public override void user_path_change_request (GLib.File loc, bool allow_mode_change = true) {
168 assert (loc != null);173 assert (loc != null);
169174 var old_dir = directory;
170 if (!location.equal (loc)) {175 set_up_directory (loc);
171 var old_dir = directory;176 dir_view.change_directory (old_dir, directory);
172 set_up_directory (loc);177 /* ViewContainer takes care of updating appearance
173 dir_view.change_directory (old_dir, directory);178 * If allow_mode_change is false View Container will not automagically
174 /* ViewContainer takes care of updating appearance179 * switch to icon view for icon folders (needed for Miller View) */
175 * If allow_mode_change is false View Container will not automagically180 ctab.slot_path_changed (directory.location, allow_mode_change);
176 * switch to icon view for icon folders (needed for Miller View) */
177 ctab.slot_path_changed (loc, allow_mode_change);
178 } else {
179 ctab.reload ();
180 }
181 }181 }
182182
183 protected override void make_view () {183 protected override void make_view () {
@@ -203,7 +203,7 @@
203 if (mode != Marlin.ViewMode.MILLER_COLUMNS)203 if (mode != Marlin.ViewMode.MILLER_COLUMNS)
204 content_box.pack_start (dir_view, true, true, 0);204 content_box.pack_start (dir_view, true, true, 0);
205205
206 connect_dir_view_signals ();206 set_view_updates_frozen (true);
207 }207 }
208208
209 public void set_view_updates_frozen (bool freeze) {209 public void set_view_updates_frozen (bool freeze) {
@@ -275,8 +275,7 @@
275 }275 }
276276
277 public override void reload () {277 public override void reload () {
278 if (dir_view != null)278 user_path_change_request (location, false);
279 dir_view.reload ();
280 }279 }
281280
282 public override void cancel () {281 public override void cancel () {
283282
=== modified file 'src/View/ViewContainer.vala'
--- src/View/ViewContainer.vala 2015-01-11 10:25:14 +0000
+++ src/View/ViewContainer.vala 2015-02-07 19:01:29 +0000
@@ -45,10 +45,19 @@
45 return slot != null ? slot.uri : null;45 return slot != null ? slot.uri : null;
46 }46 }
47 }47 }
48
49 public GOF.AbstractSlot? slot {
50 get {
51 return get_current_slot ();
52 }
53 }
54
48 public OverlayBar overlay_statusbar;55 public OverlayBar overlay_statusbar;
49 private Browser browser;56 private Browser browser;
50 private GLib.List<GLib.File>? selected_locations = null;57 private GLib.List<GLib.File>? selected_locations = null;
5158
59 private bool ready = false;
60
52 public signal void tab_name_changed (string tab_name);61 public signal void tab_name_changed (string tab_name);
53 public signal void loading (bool is_loading);62 public signal void loading (bool is_loading);
54 /* To maintain compatibility with existing plugins */63 /* To maintain compatibility with existing plugins */
@@ -137,7 +146,6 @@
137146
138 public void change_view_mode (Marlin.ViewMode mode, GLib.File? loc = null) {147 public void change_view_mode (Marlin.ViewMode mode, GLib.File? loc = null) {
139 if (mode != view_mode) {148 if (mode != view_mode) {
140
141 if (loc == null) /* Only untrue on container creation */149 if (loc == null) /* Only untrue on container creation */
142 loc = this.location;150 loc = this.location;
143151
@@ -158,15 +166,19 @@
158 else166 else
159 view = new Slot (loc, this, mode);167 view = new Slot (loc, this, mode);
160168
169 content = view.get_content_box ();
170
161 view_mode = mode;171 view_mode = mode;
162 set_up_current_slot ();
163 overlay_statusbar.showbar = view_mode != Marlin.ViewMode.LIST;172 overlay_statusbar.showbar = view_mode != Marlin.ViewMode.LIST;
164 overlay_statusbar.reset_selection ();173 overlay_statusbar.reset_selection ();
174
175 load_slot_directory (view);
165 window.update_top_menu ();176 window.update_top_menu ();
166 }177 }
167 }178 }
168179
169 public void user_path_change_request (GLib.File loc) {180 public void user_path_change_request (GLib.File loc) {
181 loading (true);
170 view.user_path_change_request (loc);182 view.user_path_change_request (loc);
171 }183 }
172184
@@ -197,28 +209,39 @@
197 }209 }
198210
199 private void set_up_current_slot () {211 private void set_up_current_slot () {
200 var slot = get_current_slot ();212 ready = false;
201 assert (slot != null);213 load_slot_directory (get_current_slot ());
202 assert (slot.directory != null);
203
204 content = view.get_content_box ();
205 load_slot_directory (slot);
206 }214 }
207215
208 public void load_slot_directory (GOF.AbstractSlot slot) {216 public void load_slot_directory (GOF.AbstractSlot? slot) {
209 can_show_folder = true;217 if (slot == null)
210 loading (true);218 return;
211 /* Allow time for the window to update before starting to load directory so that219
212 * the window is displayed more quickly
213 * when starting the application in, or switching view to, a folder that contains
214 * a large number of files. Also ensures infobars are added correctly by plugins.
215 */
216 Timeout.add (100, () => {
217 slot.directory.load ();
218 plugin_directory_loaded ();
219 return false;
220 });
221 refresh_slot_info (slot);220 refresh_slot_info (slot);
221
222 /* Allow time for the window to update before trying to load directory so that
223 * the window is displayed more quickly when starting the application in,
224 * or switching view to, a folder that contains a large number of files.
225 * Also ensures infobars are added correctly by plugins. Only checking in idle
226 * time allows pathbar animation to complete smoothly.
227
228 * Wait until directory is flagged ready to allow time for network folders to be found
229 * and accessed.
230
231 * Do not try and load directory that is not flagged 'can load'.
232 */
233 Idle.add (() => {
234 if (!slot.directory.is_ready)
235 return true;
236
237 if (slot.directory.can_load) {
238 slot.directory.load ();
239 plugin_directory_loaded ();
240 } else
241 directory_done_loading (slot);
242
243 return false;
244 });
222 }245 }
223246
224 private void plugin_directory_loaded () {247 private void plugin_directory_loaded () {
@@ -235,7 +258,6 @@
235 public void refresh_slot_info (GOF.AbstractSlot aslot) {258 public void refresh_slot_info (GOF.AbstractSlot aslot) {
236 GLib.File loc = aslot.directory.file.location;259 GLib.File loc = aslot.directory.file.location;
237 update_tab_name (loc);260 update_tab_name (loc);
238
239 browser.record_uri (loc.get_parse_name ()); /* will ignore null changes */261 browser.record_uri (loc.get_parse_name ()); /* will ignore null changes */
240262
241 window.loading_uri (loc.get_uri ());263 window.loading_uri (loc.get_uri ());
@@ -246,56 +268,78 @@
246 }268 }
247269
248 public void update_tab_name (GLib.File loc) {270 public void update_tab_name (GLib.File loc) {
249 var slot_path = loc.get_path ();271 string? slot_path = loc.get_path ();
250272 tab_name = "-----";
251 if (slot_path == Environment.get_home_dir ())273 if (slot_path == null) {
274 string [] uri_parts = loc.get_uri ().split (Path.DIR_SEPARATOR_S);
275 uint index = uri_parts.length - 1;
276 string s;
277 while (index >= 0) {
278 s = uri_parts [index];
279 if (s.length >= 1) {
280 if (index == 0) {
281 tab_name = Marlin.protocol_to_name (s);
282 } else
283 tab_name = s;
284 break;
285 }
286 index--;
287 }
288 } else if (slot_path == Environment.get_home_dir ())
252 tab_name = _("Home");289 tab_name = _("Home");
253 else if (slot_path == "/")290 else if (slot_path == "/")
254 tab_name = _("File System");291 tab_name = _("File System");
255 else if (loc.query_exists ()) {292 else {
256 try {293 try {
257 var info = loc.query_info (FileAttribute.STANDARD_DISPLAY_NAME, FileQueryInfoFlags.NONE);294 var info = loc.query_info (FileAttribute.STANDARD_DISPLAY_NAME, FileQueryInfoFlags.NONE);
258 tab_name = info.get_attribute_string (FileAttribute.STANDARD_DISPLAY_NAME);295 tab_name = info.get_attribute_string (FileAttribute.STANDARD_DISPLAY_NAME);
259 }296 }
260 catch (GLib.Error e) {297 catch (GLib.Error e) {
261 warning ("Could not get location display name. %s", e.message);298 warning ("Could not get location display name. %s", e.message);
299 tab_name = loc.get_basename ();
300 can_show_folder = false;
262 }301 }
263
264 } else {
265 tab_name = _("This folder does not exist");
266 can_show_folder = false;
267 }302 }
268303
304 if (tab_name == "-----")
305 tab_name = loc.get_uri ();
306
269 if (Posix.getuid() == 0)307 if (Posix.getuid() == 0)
270 tab_name = tab_name + " " + _("(as Administrator)");308 tab_name = tab_name + " " + _("(as Administrator)");
271
272 }309 }
273310
274 public void directory_done_loading (GOF.AbstractSlot slot) {311 public void directory_done_loading (GOF.AbstractSlot slot) {
275 FileInfo file_info;
276
277 loading (false);312 loading (false);
278313 can_show_folder = true;
279 try {314
280 file_info = slot.location.query_info ("standard::*,access::*", FileQueryInfoFlags.NONE);315 if (slot.directory.permission_denied) {
281316 content = new Granite.Widgets.Welcome (_("This does not belong to you."),
282 /* If not readable, alert the user */
283 if (slot.directory.permission_denied) {
284 content = new Granite.Widgets.Welcome (_("This does not belong to you."),
285 _("You don't have permission to view this folder."));317 _("You don't have permission to view this folder."));
318 can_show_folder = false;
319 } else if (!slot.directory.can_load) {
320 content = new Granite.Widgets.Welcome (_("Unable to mount folder."),
321 _("The server for this folder could not be located."));
322 can_show_folder = false;
323 } else if (!slot.directory.file.exists) {
324 content = new DirectoryNotFound (slot.directory, this);
286 can_show_folder = false;325 can_show_folder = false;
287 } else if (file_info.get_file_type () == FileType.DIRECTORY && selected_locations != null) {326 } else if (selected_locations != null) {
288 view.select_glib_files (selected_locations, null);327 view.select_glib_files (selected_locations, null);
289 selected_locations = null;328 selected_locations = null;
290 }329 } else if (slot.directory.selected_file != null) {
291 } catch (Error err) {330 if (slot.directory.selected_file.query_exists ())
292 /* query_info will throw an exception if it cannot find the file */331 focus_location_if_in_current_directory (slot.directory.selected_file);
293 if (err is IOError.NOT_MOUNTED)
294 slot.reload ();
295 else {332 else {
296 content = new DirectoryNotFound (slot.directory, this);333 content = new Granite.Widgets.Welcome (_("File not found."),
334 _("The file selected no longer exists."));
297 can_show_folder = false;335 can_show_folder = false;
298 }336 }
337 slot.directory.selected_file = null;
338 }
339
340 if (can_show_folder) {
341 ready = true;
342 content = view.get_content_box ();
299 }343 }
300 }344 }
301345
@@ -353,11 +397,8 @@
353 }397 }
354 }398 }
355399
356 if (loc != null) {400 if (loc != null)
357 user_path_change_request (loc);401 user_path_change_request (loc);
358 slot_path_changed (loc);
359 refresh_slot_info (get_current_slot ());
360 }
361 }402 }
362403
363 public void focus_location_if_in_current_directory (GLib.File? file,404 public void focus_location_if_in_current_directory (GLib.File? file,
@@ -382,16 +423,19 @@
382 return path;423 return path;
383 }424 }
384425
385 public void reload () {426 public void reload (bool propagate = true) {
386 if (!can_show_folder) /* Try to display folder again */
387 content = view.get_content_box ();
388
389 loading (true);
390 /* Allow time for the signal to propagate and the tab label to redraw */427 /* Allow time for the signal to propagate and the tab label to redraw */
391 Timeout.add (10, () => {428 Idle.add (() => {
392 var slot = view.get_current_slot ();429 var slot = view.get_current_slot ();
393 slot.reload ();430 slot.reload ();
394 load_slot_directory (slot);431 load_slot_directory (slot);
432 /* For remote folders, make sure any other windows showing the same folder are
433 * also refreshed. Prevent infinite loop with propagate - when called from application,
434 * propagate will be false.
435 */
436 if (propagate)
437 ((Marlin.Application)(window.application)).tab_reloaded (window, slot.location);
438
395 return false;439 return false;
396 });440 });
397 }441 }
398442
=== modified file 'src/View/Window.vala'
--- src/View/Window.vala 2015-01-26 10:59:26 +0000
+++ src/View/Window.vala 2015-02-07 19:01:29 +0000
@@ -58,6 +58,7 @@
58 public Granite.Widgets.DynamicNotebook tabs;58 public Granite.Widgets.DynamicNotebook tabs;
59 public Marlin.Places.Sidebar sidebar;59 public Marlin.Places.Sidebar sidebar;
60 public ViewContainer? current_tab = null;60 public ViewContainer? current_tab = null;
61 public uint window_number;
6162
62 public void set_can_go_forward (bool can) {63 public void set_can_go_forward (bool can) {
63 top_menu.set_can_go_forward (can);64 top_menu.set_can_go_forward (can);
@@ -73,6 +74,7 @@
73 public signal void selection_changed (GLib.List<GOF.File> gof_file);74 public signal void selection_changed (GLib.List<GOF.File> gof_file);
74 public signal void loading_uri (string location);75 public signal void loading_uri (string location);
75 public signal void folder_deleted (GLib.File location);76 public signal void folder_deleted (GLib.File location);
77 public signal void tab_reloaded (GLib.File location);
7678
77 [Signal (action=true)]79 [Signal (action=true)]
78 public virtual signal void go_up () {80 public virtual signal void go_up () {
@@ -86,7 +88,7 @@
8688
87 public Window (Marlin.Application app, Gdk.Screen myscreen) {89 public Window (Marlin.Application app, Gdk.Screen myscreen) {
88 /* Capture application window_count and active_window before they can change */90 /* Capture application window_count and active_window before they can change */
89 var window_number = app.window_count;91 window_number = app.window_count;
90 application = app;92 application = app;
91 screen = myscreen;93 screen = myscreen;
92 is_first_window = (window_number == 0);94 is_first_window = (window_number == 0);
@@ -332,6 +334,9 @@
332 }334 }
333335
334 public void change_tab (int offset) {336 public void change_tab (int offset) {
337 if (freeze_view_changes)
338 return;
339
335 ViewContainer? old_tab = current_tab;340 ViewContainer? old_tab = current_tab;
336 current_tab = (tabs.get_tab_by_index (offset)).page as ViewContainer;341 current_tab = (tabs.get_tab_by_index (offset)).page as ViewContainer;
337342
@@ -582,12 +587,18 @@
582587
583 private void action_undo (GLib.SimpleAction action, GLib.Variant? param) {588 private void action_undo (GLib.SimpleAction action, GLib.Variant? param) {
584 update_undo_actions ();589 update_undo_actions ();
585 undo_manager.undo (null);590 undo_manager.undo (this, after_undo_redo);
591 }
592
593 public static void after_undo_redo (void *data) {
594 var window = data as Marlin.View.Window;
595 if (!window.current_tab.slot.directory.is_local)
596 window.current_tab.reload ();
586 }597 }
587598
588 private void action_redo (GLib.SimpleAction action, GLib.Variant? param) {599 private void action_redo (GLib.SimpleAction action, GLib.Variant? param) {
589 update_undo_actions ();600 update_undo_actions ();
590 undo_manager.redo (null);601 undo_manager.redo (this, after_undo_redo);
591 }602 }
592603
593 private void change_state_select_all (GLib.SimpleAction action) {604 private void change_state_select_all (GLib.SimpleAction action) {
@@ -600,6 +611,7 @@
600 }611 }
601 }612 }
602613
614
603 public void change_state_show_hidden (GLib.SimpleAction action) {615 public void change_state_show_hidden (GLib.SimpleAction action) {
604 bool state = !action.state.get_boolean ();616 bool state = !action.state.get_boolean ();
605 action.set_state (new GLib.Variant.boolean (state));617 action.set_state (new GLib.Variant.boolean (state));
@@ -835,6 +847,14 @@
835 private bool valid_location (GLib.File location) {847 private bool valid_location (GLib.File location) {
836 GLib.FileInfo? info = null;848 GLib.FileInfo? info = null;
837849
850 string scheme = location.get_uri_scheme ();
851 if (scheme == "smb" ||
852 scheme == "ftp" ||
853 scheme == "network")
854 /* Do not restore remote and network locations */
855 //return false;
856 return true;
857
838 try {858 try {
839 info = location.query_info ("standard::*", GLib.FileQueryInfoFlags.NONE);859 info = location.query_info ("standard::*", GLib.FileQueryInfoFlags.NONE);
840 }860 }
@@ -886,6 +906,10 @@
886 }906 }
887907
888 public void update_top_menu () {908 public void update_top_menu () {
909 if (freeze_view_changes)
910 return;
911
912
889 if (current_tab != null) {913 if (current_tab != null) {
890 top_menu.set_back_menu (current_tab.get_go_back_path_list ());914 top_menu.set_back_menu (current_tab.get_go_back_path_list ());
891 top_menu.set_forward_menu (current_tab.get_go_forward_path_list ());915 top_menu.set_forward_menu (current_tab.get_go_forward_path_list ());
@@ -916,13 +940,9 @@
916 }940 }
917941
918 public void file_path_change_request (GLib.File loc) {942 public void file_path_change_request (GLib.File loc) {
919 FileType type = loc.query_file_type (GLib.FileQueryInfoFlags.NONE);943 /* ViewContainer deals with non-existent or unmounted directories
920944 * and locations that are not directories */
921 if (type == FileType.DIRECTORY || type == FileType.UNKNOWN)945 current_tab.user_path_change_request (loc);
922 /* ViewContainer deals with non-existent or unmounted directories */
923 current_tab.user_path_change_request (loc);
924 else
925 current_tab.focus_location (loc);
926 }946 }
927947
928 public void uri_path_change_request (string uri) {948 public void uri_path_change_request (string uri) {
929949
=== modified file 'src/View/directory_view_popup.ui'
--- src/View/directory_view_popup.ui 2014-12-21 10:42:13 +0000
+++ src/View/directory_view_popup.ui 2015-02-07 19:01:29 +0000
@@ -25,6 +25,13 @@
25 </item>25 </item>
26 </menu>26 </menu>
2727
28 <menu id='delete'>
29 <item>
30 <attribute name='label' translatable='yes'>Delete permanently</attribute>
31 <attribute name='action'>selection.delete</attribute>
32 </item>
33 </menu>
34
28 <menu id='new'>35 <menu id='new'>
29 <submenu id='new-submenu'>36 <submenu id='new-submenu'>
30 <attribute name='label' translatable='yes'>New</attribute>37 <attribute name='label' translatable='yes'>New</attribute>
@@ -59,6 +66,9 @@
59 <attribute name='action'>common.open_in</attribute>66 <attribute name='action'>common.open_in</attribute>
60 <attribute name="target">WINDOW</attribute>67 <attribute name="target">WINDOW</attribute>
61 </item>68 </item>
69 </menu>
70
71 <menu id='open-in-terminal'>
62 <item>72 <item>
63 <attribute name='label' translatable='yes'>Terminal</attribute>73 <attribute name='label' translatable='yes'>Terminal</attribute>
64 <attribute name='action'>common.open_in</attribute>74 <attribute name='action'>common.open_in</attribute>
6575
=== modified file 'src/ZeitgeistManager.vala'
--- src/ZeitgeistManager.vala 2014-07-22 02:54:40 +0000
+++ src/ZeitgeistManager.vala 2015-02-07 19:01:29 +0000
@@ -12,7 +12,7 @@
12 try {12 try {
13 info = file.query_info_async.end (res);13 info = file.query_info_async.end (res);
14 } catch (Error e) {14 } catch (Error e) {
15 warning ("Fetching file info folder loggin to zeitgeist failed: %s", e.message);15 debug ("Fetching file info folder loggin to zeitgeist failed: %s", e.message);
16 return;16 return;
17 }17 }
18 var log = Zeitgeist.Log.get_default ();18 var log = Zeitgeist.Log.get_default ();
1919
=== modified file 'src/gtk+-3.0.vapi'
--- src/gtk+-3.0.vapi 2014-10-02 20:52:33 +0000
+++ src/gtk+-3.0.vapi 2015-02-07 19:01:29 +0000
@@ -999,13 +999,28 @@
999 public virtual signal void remove_editable (Gtk.CellRenderer p0, Gtk.CellEditable p1);999 public virtual signal void remove_editable (Gtk.CellRenderer p0, Gtk.CellEditable p1);
1000 }1000 }
1001 [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_box_get_type ()")]1001 [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_box_get_type ()")]
1002 public class CellAreaBox : Gtk.CellArea, Gtk.CellLayout, Gtk.Buildable, Gtk.Orientable {1002 /* We have to remove the reference to the Gtk.CellLayout interface in order to use the new pack_
1003 * start and pack_end functions of Gtk.CellAreaBox, which have a different signature.
1004 * Instead we add the other CellLayout methods explicitly */
1005 //public class CellAreaBox : Gtk.CellArea, Gtk.CellLayout, Gtk.Buildable, Gtk.Orientable {
1006 public class CellAreaBox : Gtk.CellArea, Gtk.Buildable, Gtk.Orientable {
1003 [CCode (has_construct_function = false, type = "GtkCellArea*")]1007 [CCode (has_construct_function = false, type = "GtkCellArea*")]
1004 public CellAreaBox ();1008 public CellAreaBox ();
1005 public int get_spacing ();1009 public int get_spacing ();
1006 public void set_spacing (int spacing);1010 public void set_spacing (int spacing);
1007 public int spacing { get; set; }1011 public int spacing { get; set; }
1012 public void pack_start (Gtk.CellRenderer renderer, bool expand, bool align, bool fixed);
1013 public void pack_end (Gtk.CellRenderer renderer, bool expand, bool align, bool fixed);
1014 public void add_attribute (Gtk.CellRenderer cell, string attribute, int column);
1015 public void clear ();
1016 public void clear_attributes (Gtk.CellRenderer cell);
1017 public unowned Gtk.CellArea get_area ();
1018 public GLib.List<weak Gtk.CellRenderer> get_cells ();
1019 public void reorder (Gtk.CellRenderer cell, int position);
1020 public void set_attributes (Gtk.CellRenderer cell, ...);
1021 public void set_cell_data_func (Gtk.CellRenderer cell, owned Gtk.CellLayoutDataFunc func);
1008 }1022 }
1023
1009 [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_context_get_type ()")]1024 [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_context_get_type ()")]
1010 public class CellAreaContext : GLib.Object {1025 public class CellAreaContext : GLib.Object {
1011 [CCode (has_construct_function = false)]1026 [CCode (has_construct_function = false)]
10121027
=== modified file 'src/marlin-clipboard-manager.c'
--- src/marlin-clipboard-manager.c 2014-12-26 12:01:20 +0000
+++ src/marlin-clipboard-manager.c 2015-02-07 19:01:29 +0000
@@ -279,8 +279,6 @@
279279
280 result = NULL;280 result = NULL;
281 for (i=0; lines[i] != NULL; i++) {281 for (i=0; lines[i] != NULL; i++) {
282 //printf ("lines %d: %s\n", i, lines[i]);
283 //result = g_list_prepend (result, g_strdup (lines[i]));
284 result = g_list_prepend (result, g_file_new_for_uri (lines[i]));282 result = g_list_prepend (result, g_file_new_for_uri (lines[i]));
285 }283 }
286 return g_list_reverse (result);284 return g_list_reverse (result);
@@ -291,11 +289,8 @@
291 GtkSelectionData *selection_data,289 GtkSelectionData *selection_data,
292 gpointer user_data)290 gpointer user_data)
293{291{
294 //amtest
295 printf("%s\n", G_STRFUNC);
296 MarlinClipboardPasteRequest *request = user_data;292 MarlinClipboardPasteRequest *request = user_data;
297 MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (request->manager);293 MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (request->manager);
298 //MarlinApplication *application;
299 gboolean path_copy = TRUE;294 gboolean path_copy = TRUE;
300 GList *file_list = NULL;295 GList *file_list = NULL;
301 char **lines;296 char **lines;
@@ -329,24 +324,25 @@
329 /* perform the action if possible */324 /* perform the action if possible */
330 if (G_LIKELY (file_list != NULL))325 if (G_LIKELY (file_list != NULL))
331 {326 {
332 //application = marlin_application_get ();
333 //TODO
334 if (G_LIKELY (path_copy))327 if (G_LIKELY (path_copy))
335 {328 {
336 //marlin_application_copy_into (application, request->widget, file_list, request->target_file, request->new_files_closure);329 marlin_file_operations_copy_move (file_list,
337 printf ("marlin_application_copy_into\n");330 NULL,
338 /*marlin_file_operations_copy (file_list, NULL, request->target_file,331 request->target_file,
339 NULL, NULL, NULL);*/332 GDK_ACTION_COPY,
340 marlin_file_operations_copy_move (file_list, NULL, request->target_file,333 request->widget,
341 GDK_ACTION_COPY, NULL, request->new_files_closure, request->widget);334 request->new_files_closure,
342335 request->widget);
343 } else {336 } else {
344 printf ("marlin_application_move_into\n");337 marlin_file_operations_copy_move (file_list,
345 //marlin_application_move_into (application, request->widget, file_list, request->target_file, request->new_files_closure);338 NULL,
346 marlin_file_operations_copy_move (file_list, NULL, request->target_file,339 request->target_file,
347 GDK_ACTION_MOVE, NULL, request->new_files_closure, request->widget);340 GDK_ACTION_MOVE,
341 request->widget,
342 request->new_files_closure,
343 request->widget);
348 }344 }
349 //g_object_unref (G_OBJECT (application));345
350 g_list_free_full (file_list, g_object_unref);346 g_list_free_full (file_list, g_object_unref);
351347
352 /* clear the clipboard if it contained "cutted data"348 /* clear the clipboard if it contained "cutted data"
@@ -729,10 +725,9 @@
729marlin_clipboard_manager_paste_files (MarlinClipboardManager *manager,725marlin_clipboard_manager_paste_files (MarlinClipboardManager *manager,
730 GFile *target_file,726 GFile *target_file,
731 GtkWidget *widget,727 GtkWidget *widget,
732 MarlinCopyCallback *new_files_closure)728 GCallback *new_files_closure)
733{729{
734 MarlinClipboardPasteRequest *request;730 MarlinClipboardPasteRequest *request;
735
736 g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));731 g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
737 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));732 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
738733
739734
=== modified file 'src/marlin-clipboard-manager.h'
--- src/marlin-clipboard-manager.h 2014-12-26 12:01:20 +0000
+++ src/marlin-clipboard-manager.h 2015-02-07 19:01:29 +0000
@@ -59,7 +59,7 @@
59void marlin_clipboard_manager_paste_files (MarlinClipboardManager *manager,59void marlin_clipboard_manager_paste_files (MarlinClipboardManager *manager,
60 GFile *target_file,60 GFile *target_file,
61 GtkWidget *widget,61 GtkWidget *widget,
62 MarlinCopyCallback *new_files_closure);62 GCallback *new_files_closure);
6363
6464
65#endif /* !__MARLIN_CLIPBOARD_MANAGER_H__ */65#endif /* !__MARLIN_CLIPBOARD_MANAGER_H__ */
6666
=== modified file 'src/marlin.vapi'
--- src/marlin.vapi 2015-01-18 20:46:03 +0000
+++ src/marlin.vapi 2015-02-07 19:01:29 +0000
@@ -41,7 +41,7 @@
41 public bool has_file (GOF.File file);41 public bool has_file (GOF.File file);
42 public void copy_files (GLib.List files);42 public void copy_files (GLib.List files);
43 public void cut_files (GLib.List files);43 public void cut_files (GLib.List files);
44 public void paste_files (GLib.File target, Gtk.Widget widget, CopyCallBack? new_file_closure);44 public void paste_files (GLib.File target, Gtk.Widget widget, GLib.Callback? new_file_closure);
45 public signal void changed ();45 public signal void changed ();
46 }46 }
4747

Subscribers

People subscribed via source and target branches

to status/vote changes: