Compare commits
	
		
			2 Commits
		
	
	
		
			cherry-pic
			...
			wip/folder
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					1167230e5f | ||
| 
						 | 
					2298ca8283 | 
@@ -5,7 +5,6 @@ const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const GMenu = imports.gi.GMenu;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -47,25 +46,6 @@ const INDICATORS_ANIMATION_MAX_TIME = 0.75;
 | 
			
		||||
const PAGE_SWITCH_TRESHOLD = 0.2;
 | 
			
		||||
const PAGE_SWITCH_TIME = 0.3;
 | 
			
		||||
 | 
			
		||||
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
 | 
			
		||||
function _loadCategory(dir, view) {
 | 
			
		||||
    let iter = dir.iter();
 | 
			
		||||
    let appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
    let nextType;
 | 
			
		||||
    while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
 | 
			
		||||
        if (nextType == GMenu.TreeItemType.ENTRY) {
 | 
			
		||||
            let entry = iter.get_entry();
 | 
			
		||||
            let appInfo = entry.get_app_info();
 | 
			
		||||
            let app = appSystem.lookup_app(entry.get_desktop_file_id());
 | 
			
		||||
            if (appInfo.should_show())
 | 
			
		||||
                view.addApp(app);
 | 
			
		||||
        } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
 | 
			
		||||
            let itemDir = iter.get_directory();
 | 
			
		||||
            _loadCategory(itemDir, view);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const BaseAppView = new Lang.Class({
 | 
			
		||||
    Name: 'BaseAppView',
 | 
			
		||||
    Abstract: true,
 | 
			
		||||
@@ -97,40 +77,22 @@ const BaseAppView = new Lang.Class({
 | 
			
		||||
        this._allItems = [];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getItemId: function(item) {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createItemIcon: function(item) {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _compareItems: function(a, b) {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addItem: function(item) {
 | 
			
		||||
        let id = this._getItemId(item);
 | 
			
		||||
    addItem: function(icon) {
 | 
			
		||||
        let id = icon.id;
 | 
			
		||||
        if (this._items[id] !== undefined)
 | 
			
		||||
            return null;
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let itemIcon = this._createItemIcon(item);
 | 
			
		||||
        this._allItems.push(item);
 | 
			
		||||
        this._items[id] = itemIcon;
 | 
			
		||||
 | 
			
		||||
        return itemIcon;
 | 
			
		||||
        this._allItems.push(icon);
 | 
			
		||||
        this._items[id] = icon;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    loadGrid: function() {
 | 
			
		||||
        this._allItems.sort(Lang.bind(this, this._compareItems));
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._allItems.length; i++) {
 | 
			
		||||
            let id = this._getItemId(this._allItems[i]);
 | 
			
		||||
            if (!id)
 | 
			
		||||
                continue;
 | 
			
		||||
            this._grid.addItem(this._items[id]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._allItems.sort(Lang.bind(this, function(a, b) {
 | 
			
		||||
            return a.name.localeCompare(b.name);
 | 
			
		||||
        }));
 | 
			
		||||
        this._allItems.forEach(Lang.bind(this, function(item) {
 | 
			
		||||
            this._grid.addItem(item);
 | 
			
		||||
        }));
 | 
			
		||||
        this.emit('view-loaded');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -281,7 +243,7 @@ const AllView = new Lang.Class({
 | 
			
		||||
        this._pageIndicators.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
 | 
			
		||||
        this.actor.add_actor(this._pageIndicators.actor);
 | 
			
		||||
 | 
			
		||||
        this._folderIcons = [];
 | 
			
		||||
        this.folderIcons = [];
 | 
			
		||||
 | 
			
		||||
        this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        let box = new St.BoxLayout({ vertical: true });
 | 
			
		||||
@@ -467,52 +429,11 @@ const AllView = new Lang.Class({
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getItemId: function(item) {
 | 
			
		||||
        if (item instanceof Shell.App)
 | 
			
		||||
            return item.get_id();
 | 
			
		||||
        else if (item instanceof GMenu.TreeDirectory)
 | 
			
		||||
            return item.get_menu_id();
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createItemIcon: function(item) {
 | 
			
		||||
        if (item instanceof Shell.App)
 | 
			
		||||
            return new AppIcon(item);
 | 
			
		||||
        else if (item instanceof GMenu.TreeDirectory)
 | 
			
		||||
            return new FolderIcon(item, this);
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _compareItems: function(itemA, itemB) {
 | 
			
		||||
        // bit of a hack: rely on both ShellApp and GMenuTreeDirectory
 | 
			
		||||
        // having a get_name() method
 | 
			
		||||
        let nameA = GLib.utf8_collate_key(itemA.get_name(), -1);
 | 
			
		||||
        let nameB = GLib.utf8_collate_key(itemB.get_name(), -1);
 | 
			
		||||
        return (nameA > nameB) ? 1 : (nameA < nameB ? -1 : 0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeAll: function() {
 | 
			
		||||
        this._folderIcons = [];
 | 
			
		||||
        this.folderIcons = [];
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addApp: function(app) {
 | 
			
		||||
        let appIcon = this._addItem(app);
 | 
			
		||||
        if (appIcon)
 | 
			
		||||
            appIcon.actor.connect('key-focus-in',
 | 
			
		||||
                                  Lang.bind(this, this._ensureIconVisible));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addFolder: function(dir) {
 | 
			
		||||
        let folderIcon = this._addItem(dir);
 | 
			
		||||
        this._folderIcons.push(folderIcon);
 | 
			
		||||
        if (folderIcon)
 | 
			
		||||
            folderIcon.actor.connect('key-focus-in',
 | 
			
		||||
                                     Lang.bind(this, this._ensureIconVisible));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addFolderPopup: function(popup) {
 | 
			
		||||
        this._stack.add_actor(popup.actor);
 | 
			
		||||
        popup.connect('open-state-changed', Lang.bind(this,
 | 
			
		||||
@@ -577,8 +498,8 @@ const AllView = new Lang.Class({
 | 
			
		||||
        this._availWidth = availWidth;
 | 
			
		||||
        this._availHeight = availHeight;
 | 
			
		||||
        // Update folder views
 | 
			
		||||
        for (let i = 0; i < this._folderIcons.length; i++)
 | 
			
		||||
            this._folderIcons[i].adaptToSize(availWidth, availHeight);
 | 
			
		||||
        for (let i = 0; i < this.folderIcons.length; i++)
 | 
			
		||||
            this.folderIcons[i].adaptToSize(availWidth, availHeight);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AllView.prototype);
 | 
			
		||||
@@ -701,8 +622,9 @@ const AppDisplay = new Lang.Class({
 | 
			
		||||
        Main.overview.connect('showing', Lang.bind(this, function() {
 | 
			
		||||
            Main.queueDeferredWork(this._frequentAppsWorkId);
 | 
			
		||||
        }));
 | 
			
		||||
        global.settings.connect('changed::app-folder-categories', Lang.bind(this, function() {
 | 
			
		||||
            Main.queueDeferredWork(this._allAppsWorkId);
 | 
			
		||||
        this._softwareSettings = new Gio.Settings({ schema: 'org.gnome.software' });
 | 
			
		||||
        this._softwareSettings.connect('changed::app-folders', Lang.bind(this, function() {
 | 
			
		||||
            Main.queueDeferredWork(this._frequentAppsWorkId);
 | 
			
		||||
        }));
 | 
			
		||||
        this._privacySettings = new Gio.Settings({ schema: 'org.gnome.desktop.privacy' });
 | 
			
		||||
        this._privacySettings.connect('changed::remember-app-usage',
 | 
			
		||||
@@ -816,23 +738,26 @@ const AppDisplay = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        view.removeAll();
 | 
			
		||||
 | 
			
		||||
        let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
 | 
			
		||||
        tree.load_sync();
 | 
			
		||||
        let root = tree.get_root_directory();
 | 
			
		||||
        let apps = Gio.AppInfo.get_all();
 | 
			
		||||
 | 
			
		||||
        let iter = root.iter();
 | 
			
		||||
        let nextType;
 | 
			
		||||
        let folderCategories = global.settings.get_strv('app-folder-categories');
 | 
			
		||||
        while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
 | 
			
		||||
            if (nextType == GMenu.TreeItemType.DIRECTORY) {
 | 
			
		||||
                let dir = iter.get_directory();
 | 
			
		||||
 | 
			
		||||
                if (folderCategories.indexOf(dir.get_menu_id()) != -1)
 | 
			
		||||
                    view.addFolder(dir);
 | 
			
		||||
                else
 | 
			
		||||
                    _loadCategory(dir, view);
 | 
			
		||||
            }
 | 
			
		||||
        let folders = this._softwareSettings.get_value('app-folders').deep_unpack();
 | 
			
		||||
        for (let id in folders) {
 | 
			
		||||
            let folderApps = folders[id];
 | 
			
		||||
            let icon = new FolderIcon(id, id, folderApps, view);
 | 
			
		||||
            view.addItem(icon);
 | 
			
		||||
            view.folderIcons.push(icon);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        apps.forEach(Lang.bind(this, function(appInfo) {
 | 
			
		||||
            if (!appInfo.should_show())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            let app = appSys.lookup_app(appInfo.get_id());
 | 
			
		||||
            let icon = new AppIcon(app);
 | 
			
		||||
            view.addItem(icon);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        view.loadGrid();
 | 
			
		||||
 | 
			
		||||
        if (this._focusDummy) {
 | 
			
		||||
@@ -956,22 +881,6 @@ const FolderView = new Lang.Class({
 | 
			
		||||
        this.actor.add_action(action);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getItemId: function(item) {
 | 
			
		||||
        return item.get_id();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createItemIcon: function(item) {
 | 
			
		||||
        return new AppIcon(item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _compareItems: function(a, b) {
 | 
			
		||||
        return a.compare_by_name(b);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addApp: function(app) {
 | 
			
		||||
        this._addItem(app);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createFolderIcon: function(size) {
 | 
			
		||||
        let icon = new St.Widget({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                   style_class: 'app-folder-icon',
 | 
			
		||||
@@ -980,7 +889,7 @@ const FolderView = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let aligns = [ Clutter.ActorAlign.START, Clutter.ActorAlign.END ];
 | 
			
		||||
        for (let i = 0; i < Math.min(this._allItems.length, 4); i++) {
 | 
			
		||||
            let texture = this._allItems[i].create_icon_texture(subSize);
 | 
			
		||||
            let texture = this._allItems[i].app.create_icon_texture(subSize);
 | 
			
		||||
            let bin = new St.Bin({ child: texture,
 | 
			
		||||
                                   x_expand: true, y_expand: true });
 | 
			
		||||
            bin.set_x_align(aligns[i % 2]);
 | 
			
		||||
@@ -1057,8 +966,9 @@ const FolderView = new Lang.Class({
 | 
			
		||||
const FolderIcon = new Lang.Class({
 | 
			
		||||
    Name: 'FolderIcon',
 | 
			
		||||
 | 
			
		||||
    _init: function(dir, parentView) {
 | 
			
		||||
        this._dir = dir;
 | 
			
		||||
    _init: function(id, name, apps, parentView) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        this.name = name;
 | 
			
		||||
        this._parentView = parentView;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'app-well-app app-folder',
 | 
			
		||||
@@ -1071,14 +981,21 @@ const FolderIcon = new Lang.Class({
 | 
			
		||||
        // whether we need to update arrow side, position etc.
 | 
			
		||||
        this._popupInvalidated = false;
 | 
			
		||||
 | 
			
		||||
        let label = this._dir.get_name();
 | 
			
		||||
        this.icon = new IconGrid.BaseIcon(label,
 | 
			
		||||
        this.icon = new IconGrid.BaseIcon(this.name,
 | 
			
		||||
                                          { createIcon: Lang.bind(this, this._createIcon), setSizeManually: true });
 | 
			
		||||
        this.actor.set_child(this.icon.actor);
 | 
			
		||||
        this.actor.label_actor = this.icon.label;
 | 
			
		||||
 | 
			
		||||
        this.view = new FolderView();
 | 
			
		||||
        _loadCategory(dir, this.view);
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        apps.forEach(Lang.bind(this, function(appId) {
 | 
			
		||||
            let app = appSys.lookup_app(appId + '.desktop');
 | 
			
		||||
            if (!app)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            let icon = new AppIcon(app);
 | 
			
		||||
            this.view.addItem(icon);
 | 
			
		||||
        }));
 | 
			
		||||
        this.view.loadGrid();
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this,
 | 
			
		||||
@@ -1288,6 +1205,9 @@ const AppIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _init : function(app, iconParams) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.id = app.get_id();
 | 
			
		||||
        this.name = app.get_name();
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'app-well-app',
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user