Files
system-taskbar/ding/app/appChooser.js

249 lines
7.8 KiB
JavaScript

/* DING: Desktop Icons New Generation for GNOME Shell
*
* Gtk4 Port Copyright (C) 2023 Sundeep Mediratta (smedius@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {Gtk, Gdk, Gio, Adw} from '../dependencies/gi.js';
import {_} from '../dependencies/gettext.js';
export {AppChooserDialog};
const AppChooserDialog = class {
constructor(fileItems, activeFileItem = null, dbusUtils, desktopIconsUtil) {
if (!activeFileItem)
activeFileItem = fileItems[0];
if (fileItems.length === 1) {
this.fileName = activeFileItem.displayName;
this.singleContentType = true;
} else {
this.fileName = null;
this.singleContentType = this._detectSingleContentType(fileItems);
}
this._dbusUtils = dbusUtils;
this._desktopIconsUtil = desktopIconsUtil;
this.mimeType = activeFileItem.attributeContentType;
this.mimeTypeIsDirectory = this.mimeType === 'inode/directory';
const appwindow =
this._desktopIconsUtil.getMainApp().get_active_window();
this.builderObject =
Gtk.Builder
.new_from_resource('/com/desktop/ding/ui/ding-app-chooser.ui');
this.builderObject.set_translation_domain('gtk4-ding');
this.appChooserDialog =
this.builderObject.get_object('DingAppChooser');
this.appChooserDialog.set_transient_for(appwindow);
this.appChooserDialog.set_title('DingAppChooser');
this.appChooserDialog.set_name('DingAppChooser');
const modal = true;
this._desktopIconsUtil
.windowHidePagerTaskbarModal(this.appChooserDialog, modal);
this.appChooserBox =
this.builderObject.get_object('app_chooser_widget_box');
this.appChooserBox.set_hexpand(true);
this.appChooserBox.set_halign(Gtk.Align.FILL);
this.appChooserWidget = Gtk.AppChooserWidget.new(this.mimeType);
this.appChooserWidget.set_show_default(true);
this.appChooserWidget.set_show_fallback(true);
this.appChooserWidget.set_show_other(true);
this.appChooserBox.append(this.appChooserWidget);
this.appChooserWidget.set_vexpand(true);
this.appChooserWidget.set_halign(Gtk.Align.FILL);
this.appChooserWidget.set_hexpand(true);
if (this.fileName !== null) {
const description =
_('Choose an application to open <b>{foo}</b>')
.replace('{foo}', this.fileName.replaceAll('&', '&amp;'));
this.appChooserLabel =
this.builderObject.get_object('label_description');
this.appChooserLabel.set_markup(description);
}
let headerTitle;
if (!this.singleContentType)
headerTitle = _('Open Items');
else if (this.mimeTypeIsDirectory)
headerTitle = _('Open Folder');
else
headerTitle = _('Open File');
this.appChooserDialogHeaderBar = this.appChooserDialog.get_header_bar();
this.appChooserDialogHeaderBar
.set_title_widget(Adw.WindowTitle.new(headerTitle, ''));
this.appChooserRowBox =
this.builderObject.get_object('set_default_box');
this.appChooserRow =
this.builderObject.get_object('set_default_row');
this.appChooserRowSwitch =
this.builderObject.get_object('set_as_default_switch');
this.selectedAppInfo = this.appChooserWidget.get_app_info();
if (this.selectedAppInfo !== null) {
this._onApplicationSelected(
this.appChooserWidget,
this.selectedAppInfo
);
}
this.appChooserWidget.connect(
'application-activated',
this._onApplicationActivated.bind(this)
);
this.appChooserWidget.connect(
'application-selected',
this._onApplicationSelected.bind(this)
);
if (this.singleContentType && !this.mimeTypeIsDirectory) {
let description = Gio.content_type_get_description(this.mimeType);
this.appChooserRow.set_subtitle(description);
} else {
this.appChooserRowBox.set_visible(false);
}
this.appChooserDialog.connect('close', () => {
this.appChooserDialog.response(Gtk.ResponseType.CANCEL);
});
this.appChooserDialog.connect('response', (actor, retval) => {
if (retval === Gtk.ResponseType.OK) {
this._checkUpdateDefaultAppForMimeType();
this.applicationSelectionComplete(this.selectedAppInfo);
} else {
this.applicationSelectionComplete(null);
}
});
}
_checkUpdateDefaultAppForMimeType() {
if (!this.singleContentType)
return;
let newAppSelected = false;
if (this.appChooserRowSwitch.get_sensitive())
newAppSelected = this.appChooserRowSwitch.get_active();
if (newAppSelected) {
let success =
this.selectedAppInfo.set_as_default_for_type(this.mimeType);
if (!success) {
let header =
_('Error changing default application');
let message =
_('Error while setting {foo} as default application for {mimetype}');
message =
message.replace(
'{foo}',
this.selectedAppInfo.get_display_name()
);
message =
message
.replace(
'{mimetype}',
Gio.content_type_get_description(this.mimeType)
);
this._dbusUtils.doNotify(header, message);
}
}
}
_onApplicationActivated(actor, appInfo) {
this.selectedAppInfo = appInfo;
this.appChooserDialog.response(Gtk.ResponseType.OK);
}
_onApplicationSelected(actor, appInfo) {
if (!this.appChooserDialog)
return;
this.selectedAppInfo = appInfo;
this.appChooserDialog
.set_response_sensitive(
Gtk.ResponseType.OK,
this.selectedAppInfo !== null
);
let defaultAppInfo =
Gio.AppInfo.get_default_for_type(this.mimeType, false);
let defaultSelected = false;
if (defaultAppInfo)
defaultSelected = defaultAppInfo.equal(this.selectedAppInfo);
this.appChooserRowSwitch.set_state(defaultSelected);
this.appChooserRowSwitch.set_sensitive(!defaultSelected);
}
_detectSingleContentType(fileItems) {
let mimetype = fileItems[0].attributeContentType;
for (let fileItem of fileItems) {
if (fileItem.attributeContentType !== mimetype)
return false;
}
return true;
}
show() {
this.appChooserDialog.show();
this.appChooserDialog.present_with_time(Gdk.CURRENT_TIME);
}
hide() {
this.appChooserDialog.hide();
}
finalize() {
this.appChooserDialog.destroy();
this.appChooserDialog = null;
this.builderObject = null;
}
getApplicationSelected() {
return new Promise(resolve => {
this.applicationSelectionComplete = resolve;
});
}
};