/* * Syncany, www.syncany.org * Copyright (C) 2011-2013 Philipp C. Heckel <philipp.heckel@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, either version 3 of the License, or * (at your option) any later version. * * 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/>. */ package org.syncany.gui.preferences; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.syncany.config.ConfigException; import org.syncany.config.GuiConfigHelper; import org.syncany.config.GuiEventBus; import org.syncany.config.UserConfig; import org.syncany.config.to.GuiConfigTO; import org.syncany.config.to.UserConfigTO; import org.syncany.gui.Panel; import org.syncany.gui.tray.TrayIconFactory; import org.syncany.gui.tray.TrayIconTheme; import org.syncany.gui.tray.TrayIconType; import org.syncany.gui.util.DesktopUtil; import org.syncany.gui.util.I18n; import org.syncany.gui.util.WidgetDecorator; import org.syncany.operations.daemon.messages.GuiConfigChangedGuiInternalEvent; import org.syncany.operations.daemon.messages.PluginManagementResponse; import org.syncany.operations.daemon.messages.UpdateManagementResponse; import org.syncany.operations.gui.UpdateChecker; import org.syncany.operations.gui.UpdateChecker.UpdateCheckListener; import org.syncany.operations.update.AppInfo; import org.syncany.util.EnvironmentUtil; public class GeneralPanel extends Panel { private static final Logger logger = Logger.getLogger(GeneralPanel.class.getSimpleName()); private static final String DOWNLOAD_LINK_MAGIC_STR = "get.syncany.org"; private SelectionListener commonSelectionListener; private Button launchAtStartupButton; private Button displayNotificationsButton; private Button preventStandbyButton; private Button updateCheckButton; private Button useShortLinksButton; private Combo themeCombo; private Combo trayTypeCombo; private Link updatesLabel; private UpdateChecker updateChecker; private AppInfo appInfo; private GuiConfigTO guiConfig; private GuiEventBus eventBus; public GeneralPanel(PreferencesDialog parentDialog, Composite composite, int style) { super(parentDialog, composite, style); initEventBus(); initUpdateChecker(); loadConfig(); createContents(); // Persist changes loaded from gui.xml to the operating // system. The gui.xml is the master config file. This // makes sure that the OS settings are consistent with it. writeOrDeleteStartupScriptFile(); } private void initEventBus() { this.eventBus = GuiEventBus.getAndRegister(this); } private void initUpdateChecker() { this.appInfo = null; this.updateChecker = new UpdateChecker(new UpdateCheckListener() { @Override public void updateResponseReceived(UpdateManagementResponse appResponse, PluginManagementResponse pluginResponse, final String updateResponseText, boolean updatesAvailable) { appInfo = appResponse.getResult().getAppInfo(); updateUpdateLabel(updateResponseText); } }); } protected void updateUpdateLabel(final String updateResponseText) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { String updateTextWithLink = updateResponseText.replace(DOWNLOAD_LINK_MAGIC_STR, "<a>" + DOWNLOAD_LINK_MAGIC_STR + "</a>"); updatesLabel.setText(updateTextWithLink); } }); } private void createContents() { createMainComponents(); createCheckboxes(); createTrayCombos(); createUpdateLabel(); refreshUpdateLabel(); } private void createMainComponents() { // Main composite GridLayout mainCompositeGridLayout = new GridLayout(4, false); mainCompositeGridLayout.marginTop = 15; mainCompositeGridLayout.marginLeft = 10; mainCompositeGridLayout.marginRight = 20; setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); setLayout(mainCompositeGridLayout); // Title and welcome text Label titleLabel = new Label(this, SWT.WRAP); titleLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1)); titleLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.title")); WidgetDecorator.title(titleLabel); // Common selection listener commonSelectionListener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { saveConfig(); } }; } private void createCheckboxes() { // Startup launchAtStartupButton = new Button(this, SWT.CHECK); launchAtStartupButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); if (EnvironmentUtil.isUnixLikeOperatingSystem() || EnvironmentUtil.isWindows()) { launchAtStartupButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.launchAtStartup")); launchAtStartupButton.setSelection(guiConfig.isStartup()); launchAtStartupButton.addSelectionListener(commonSelectionListener); } else { launchAtStartupButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.launchAtStartupNotSupported")); launchAtStartupButton.setSelection(false); launchAtStartupButton.setEnabled(false); } // Notifications displayNotificationsButton = new Button(this, SWT.CHECK); displayNotificationsButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); displayNotificationsButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.displayNotifications")); displayNotificationsButton.setSelection(guiConfig.isNotifications()); displayNotificationsButton.addSelectionListener(commonSelectionListener); // Prevent standby preventStandbyButton = new Button(this, SWT.CHECK); preventStandbyButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); preventStandbyButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.preventStandby")); preventStandbyButton.setSelection(UserConfig.isPreventStandby()); preventStandbyButton.addSelectionListener(commonSelectionListener); // Update check updateCheckButton = new Button(this, SWT.CHECK); updateCheckButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); updateCheckButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.updateCheck")); updateCheckButton.setSelection(guiConfig.isUpdateCheck()); updateCheckButton.addSelectionListener(commonSelectionListener); // Use short links useShortLinksButton = new Button(this, SWT.CHECK); useShortLinksButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); useShortLinksButton.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.shortLinks")); useShortLinksButton.setSelection(guiConfig.isShortLinks()); useShortLinksButton.addSelectionListener(commonSelectionListener); Label spacingLabel = new Label(this, SWT.NONE); spacingLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); } private void createTrayCombos() { // Spacing Label spacingLabel1 = new Label(this, SWT.NONE); spacingLabel1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1)); // Look and feel title Label lookAndFeelTitleLabel = new Label(this, SWT.WRAP); lookAndFeelTitleLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1)); lookAndFeelTitleLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.lookAndFeel.title")); WidgetDecorator.bold(lookAndFeelTitleLabel); // Theme Label themeLabel = new Label(this, SWT.NONE); themeLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.theme.title")); themeCombo = new Combo(this, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); themeCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); themeCombo.addSelectionListener(commonSelectionListener); fillTrayThemeCombo(); // Spacing Label spacingLabel2 = new Label(this, SWT.NONE); spacingLabel2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); // Tray type Label trayTypeLabel = new Label(this, SWT.NONE); trayTypeLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType.title")); trayTypeCombo = new Combo(this, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); trayTypeCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); trayTypeCombo.addSelectionListener(commonSelectionListener); fillTrayTypeCombo(); } private void createUpdateLabel() { // Spacing Label spacingLabel = new Label(this, SWT.NONE); spacingLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1)); // Updates title Label updatesTitleLabel = new Label(this, SWT.WRAP); updatesTitleLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); updatesTitleLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.updates.title")); WidgetDecorator.bold(updatesTitleLabel); // Updates text updatesLabel = new Link(this, SWT.WRAP); updatesLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); updatesLabel.setText(I18n.getText("org.syncany.gui.preferences.GeneralPanel.updates.checkingForUpdates")); updatesLabel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String downloadUrl = appInfo.getDownloadUrl(); logger.log(Level.INFO, "Opening download URL " + downloadUrl + " ..."); DesktopUtil.launch(downloadUrl); } }); } private void refreshUpdateLabel() { updateChecker.check(); } private void fillTrayThemeCombo() { // Determine texts HashMap<TrayIconTheme, String> themeTexts = new LinkedHashMap<>(); TrayIconTheme autoTheme = TrayIconFactory.detectThemeFromOS(); String autoThemeDescription = I18n.getText("org.syncany.gui.preferences.GeneralPanel.theme." + autoTheme.toString()); String autoThemeFullDescription = I18n.getText("org.syncany.gui.preferences.GeneralPanel.theme.autoFormat", autoThemeDescription); themeTexts.put(TrayIconTheme.AUTO, autoThemeFullDescription); themeTexts.put(TrayIconTheme.DEFAULT, I18n.getText("org.syncany.gui.preferences.GeneralPanel.theme." + TrayIconTheme.DEFAULT.toString())); themeTexts.put(TrayIconTheme.MONOCHROME, I18n.getText("org.syncany.gui.preferences.GeneralPanel.theme." + TrayIconTheme.MONOCHROME.toString())); // Add to combo box TrayIconTheme currentTheme = guiConfig.getTheme(); for (Entry<TrayIconTheme, String> themeComboEntry : themeTexts.entrySet()) { themeCombo.add(themeComboEntry.getValue()); themeCombo.setData(themeComboEntry.getValue(), themeComboEntry.getKey()); if (currentTheme == themeComboEntry.getKey()) { themeCombo.select(themeCombo.getItemCount() - 1); } } // Select first item if no value in config file if (currentTheme == null) { themeCombo.select(0); } } private void fillTrayTypeCombo() { // Determine texts HashMap<TrayIconType, String> trayTypeTexts = new LinkedHashMap<>(); TrayIconType autoTrayType = TrayIconFactory.detectTypeFromOS(); String autoTrayTypeDescription = I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType." + autoTrayType.toString()); String autoTrayTypeFullDescription = I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType.autoFormat", autoTrayTypeDescription); trayTypeTexts.put(TrayIconType.AUTO, autoTrayTypeFullDescription); trayTypeTexts.put(TrayIconType.DEFAULT, I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType." + TrayIconType.DEFAULT.toString())); if (EnvironmentUtil.isMacOSX()) { trayTypeTexts.put(TrayIconType.OSX_NOTIFICATION_CENTER, I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType." + TrayIconType.OSX_NOTIFICATION_CENTER.toString())); } else if (EnvironmentUtil.isUnixLikeOperatingSystem()) { trayTypeTexts.put(TrayIconType.APPINDICATOR, I18n.getText("org.syncany.gui.preferences.GeneralPanel.trayType." + TrayIconType.APPINDICATOR.toString())); } // Add to combo box TrayIconType currentTrayType = guiConfig.getTray(); for (Entry<TrayIconType, String> trayTypeComboEntry : trayTypeTexts.entrySet()) { trayTypeCombo.add(trayTypeComboEntry.getValue()); trayTypeCombo.setData(trayTypeComboEntry.getValue(), trayTypeComboEntry.getKey()); if (currentTrayType == trayTypeComboEntry.getKey()) { trayTypeCombo.select(trayTypeCombo.getItemCount() - 1); } } // Select first item if no value in config file if (currentTrayType == null) { trayTypeCombo.select(0); } } private void loadConfig() { guiConfig = GuiConfigHelper.loadOrCreateGuiConfig(); } private void saveConfig() { TrayIconTheme selectedTheme = (TrayIconTheme) themeCombo.getData(themeCombo.getItem(themeCombo.getSelectionIndex())); TrayIconType selectedTrayType = (TrayIconType) trayTypeCombo.getData(trayTypeCombo.getItem(trayTypeCombo.getSelectionIndex())); guiConfig.setStartup(launchAtStartupButton.getSelection()); guiConfig.setNotifications(displayNotificationsButton.getSelection()); guiConfig.setUpdateCheck(updateCheckButton.getSelection()); guiConfig.setShortLinks(useShortLinksButton.getSelection()); guiConfig.setTheme(selectedTheme); guiConfig.setTray(selectedTrayType); writeOrDeleteStartupScriptFile(); saveGuiConfigFile(); saveUserConfigFile(); } private void writeOrDeleteStartupScriptFile() { DesktopUtil.writeAutostart(launchAtStartupButton.getSelection()); } private void saveGuiConfigFile() { try { GuiConfigHelper.saveGuiConfig(guiConfig); eventBus.post(new GuiConfigChangedGuiInternalEvent(guiConfig)); } catch (ConfigException e) { logger.log(Level.WARNING, "Unable to save GUI config.", e); } } private void saveUserConfigFile() { boolean userConfigChanged = UserConfig.isPreventStandby() != preventStandbyButton.getSelection(); if (userConfigChanged) { try { // Load, then save user config TO UserConfigTO userConfigTO = UserConfigTO.load(UserConfig.getUserConfigFile()); userConfigTO.setPreventStandby(preventStandbyButton.getSelection()); userConfigTO.save(UserConfig.getUserConfigFile()); // Apply changes to live user config UserConfig.setPreventStandby(preventStandbyButton.getSelection()); } catch (ConfigException e) { logger.log(Level.WARNING, "Unable to save user config.", e); } } } @Override public boolean validatePanel() { return true; } @Override public void dispose() { updateChecker.dispose(); eventBus.unregister(this); super.dispose(); } }