/* * Copyright 2004 - 2008 Christian Sprajc. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder 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. * * PowerFolder 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 PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id$ */ package de.dal33t.powerfolder.ui.model; import java.awt.MouseInfo; import java.awt.Point; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Date; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.jgoodies.binding.value.ValueHolder; import com.jgoodies.binding.value.ValueModel; import de.dal33t.powerfolder.Controller; import de.dal33t.powerfolder.PreferencesEntry; import de.dal33t.powerfolder.clientserver.ServerClient; import de.dal33t.powerfolder.clientserver.ServerClientEvent; import de.dal33t.powerfolder.clientserver.ServerClientListener; import de.dal33t.powerfolder.disk.Folder; import de.dal33t.powerfolder.disk.FolderRepository; import de.dal33t.powerfolder.disk.SyncProfile; import de.dal33t.powerfolder.event.*; import de.dal33t.powerfolder.message.FileListRequest; import de.dal33t.powerfolder.security.AdminPermission; import de.dal33t.powerfolder.ui.PFUIComponent; import de.dal33t.powerfolder.ui.action.ActionModel; import de.dal33t.powerfolder.ui.dialog.SyncFolderDialog; import de.dal33t.powerfolder.ui.event.SyncStatusEvent; import de.dal33t.powerfolder.ui.event.SyncStatusListener; import de.dal33t.powerfolder.ui.notices.WarningNotice; import de.dal33t.powerfolder.ui.wizard.PFWizard; import de.dal33t.powerfolder.util.Translation; import static de.dal33t.powerfolder.ui.event.SyncStatusEvent.*; /** * Contains all core models for the application. * * @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc</a> * @version $Revision: 1.5 $ */ public class ApplicationModel extends PFUIComponent { private ActionModel actionModel; private FolderRepositoryModel folderRepositoryModel; private NodeManagerModel nodeManagerModel; private TransferManagerModel transferManagerModel; private ServerClientModel serverClientModel; private ValueModel systemNotificationsValueModel; private LicenseModel licenseModel; private NoticesModel noticesModel; private Date lastMouseAction; private Point lastMouseLocation; private final List<SyncStatusListener> syncStatusListeners; private volatile SyncStatusEvent syncStatus; /** * Constructs a non-initialized application model. Before the model can be * used call {@link #initialize()} * * @param controller * @see #initialize() */ public ApplicationModel(final Controller controller) { super(controller); actionModel = new ActionModel(getController()); folderRepositoryModel = new FolderRepositoryModel(getController()); nodeManagerModel = new NodeManagerModel(getController()); transferManagerModel = new TransferManagerModel(getController() .getTransferManager()); serverClientModel = new ServerClientModel(getController(), getController().getOSClient()); systemNotificationsValueModel = new ValueHolder( PreferencesEntry.SHOW_SYSTEM_NOTIFICATIONS .getValueBoolean(controller)); systemNotificationsValueModel .addValueChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { PreferencesEntry.SHOW_SYSTEM_NOTIFICATIONS.setValue( controller, (Boolean) evt.getNewValue()); controller.saveConfig(); } }); licenseModel = new LicenseModel(); noticesModel = new NoticesModel(getController()); syncStatusListeners = new CopyOnWriteArrayList<SyncStatusListener>(); } /** * Initializes this and all submodels */ public void initialize() { transferManagerModel.initialize(); getController().getOSClient().addListener(new MyServerClientListener()); getController().addPausedModeListener(new MyPausedModeListener()); getController().getFolderRepository().addFolderRepositoryListener(new MyFolderRepositoryListener()); getController().getNodeManager().addNodeManagerListener(new MyNodeManagerListener()); getApplicationModel().getFolderRepositoryModel().addOverallFolderStatListener( new MyOverallFolderStatListener()); } // Logic ****************************************************************** public void syncFolder(Folder folder) { // Want to be aware when the scan completes. folderRepositoryModel.addInterestedFolderInfo(folder.getInfo()); if (SyncProfile.MANUAL_SYNCHRONIZATION.equals(folder.getSyncProfile())) { // Ask for more sync options on that folder if on project sync new SyncFolderDialog(getController(), folder).open(); } else { getController().setPaused(false); // Let other nodes scan now! folder.broadcastScanCommand(); folder.broadcastMessages(new FileListRequest(folder.getInfo())); // Recommend scan on this. User request, so recommend with true. folder.recommendScanOnNextMaintenance(true); // Now trigger the scan getController().getFolderRepository().triggerMaintenance(); // Trigger file requesting. getController().getFolderRepository().getFileRequestor() .triggerFileRequesting(folder.getInfo()); } Folder metaFolder = getController().getFolderRepository() .getMetaFolderForParent(folder.getInfo()); metaFolder.scanLocalFiles(true); metaFolder.syncRemoteDeletedFiles(true); metaFolder.getStatistic().scheduleCalculate(); folder.getStatistic().scheduleCalculate(); } public boolean isUserActive() { Point nowMouseLocation = MouseInfo.getPointerInfo().getLocation(); if (lastMouseLocation == null) { // Init lastMouseLocation = nowMouseLocation; lastMouseAction = new Date(); return true; } // Mouse was moved. if (!nowMouseLocation.equals(lastMouseLocation)) { lastMouseLocation = nowMouseLocation; lastMouseAction = new Date(); return true; } // Mouse was not moved. long forSeconds = (System.currentTimeMillis() - lastMouseAction .getTime()) / 1000; return forSeconds <= 10; } // Exposing *************************************************************** public ActionModel getActionModel() { return actionModel; } public FolderRepositoryModel getFolderRepositoryModel() { return folderRepositoryModel; } public NodeManagerModel getNodeManagerModel() { return nodeManagerModel; } public TransferManagerModel getTransferManagerModel() { return transferManagerModel; } public ServerClientModel getServerClientModel() { return serverClientModel; } public ValueModel getSystemNotificationsValueModel() { return systemNotificationsValueModel; } public LicenseModel getLicenseModel() { return licenseModel; } private class MyServerClientListener implements ServerClientListener { public boolean fireInEventDispatchThread() { return true; } public void login(ServerClientEvent event) { handleSyncStatusChange(); if (event.getAccountDetails().getAccount() .hasPermission(AdminPermission.INSTANCE)) { WarningNotice notice = new WarningNotice( Translation.getTranslation("warning_notice.title"), Translation .getTranslation("warning_notice.admin_login.summary"), Translation .getTranslation("warning_notice.admin_login.message")); noticesModel.handleNotice(notice); } } public void accountUpdated(ServerClientEvent event) { handleSyncStatusChange(); } public void serverConnected(ServerClientEvent event) { handleSyncStatusChange(); ServerClient client = event.getClient(); if (client.isPasswordEmpty() && !client.isLoggedIn()) { PFWizard.openLoginWizard(getController(), client); } } public void serverDisconnected(ServerClientEvent event) { handleSyncStatusChange(); } public void nodeServerStatusChanged(ServerClientEvent event) { handleSyncStatusChange(); } } public NoticesModel getNoticesModel() { return noticesModel; } public void addSyncStatusListener(SyncStatusListener l) { syncStatusListeners.add(l); } public void removeSyncStatusListener(SyncStatusListener l) { syncStatusListeners.remove(l); } private void handleSyncStatusChange() { FolderRepository repository = getController().getFolderRepository(); ServerClient client = getController().getOSClient(); boolean connected = client.isConnected(); boolean loggedIn = client.isLoggedIn(); SyncStatusEvent status = SYNC_INCOMPLETE; if (getController().isPaused()) { status = PAUSED; } else if (!getController().getNodeManager().isStarted()) { status = NOT_STARTED; } else if (!connected) { status = NOT_CONNECTED; } else if (!loggedIn) { status = NOT_LOGGED_IN; } else if (repository.getFoldersCount() == 0) { status = NO_FOLDERS; } else if (folderRepositoryModel.isSyncing()) { status = SYNCING; } else if (repository.areAllFoldersInSync()) { status = SYNCHRONIZED; } triggerSyncStatusChange(status); } private void triggerSyncStatusChange(SyncStatusEvent event) { if (isFiner()) { logFiner(event.toString()); } for (SyncStatusListener listener : syncStatusListeners) { listener.syncStatusChanged(event); } } // //////////////// // Inner Classes // // //////////////// private class MyPausedModeListener implements PausedModeListener { public void setPausedMode(PausedModeEvent event) { handleSyncStatusChange(); } public boolean fireInEventDispatchThread() { return true; } } private class MyOverallFolderStatListener implements OverallFolderStatListener { public void statCalculated() { handleSyncStatusChange(); } public boolean fireInEventDispatchThread() { return true; } } private class MyNodeManagerListener extends NodeManagerAdapter { public void startStop(NodeManagerEvent e) { handleSyncStatusChange(); } public boolean fireInEventDispatchThread() { return true; } } private class MyFolderRepositoryListener implements FolderRepositoryListener { public boolean fireInEventDispatchThread() { return true; } public void folderRemoved(FolderRepositoryEvent e) { handleSyncStatusChange(); } public void folderCreated(FolderRepositoryEvent e) { handleSyncStatusChange(); } public void maintenanceStarted(FolderRepositoryEvent e) { // Don't care } public void maintenanceFinished(FolderRepositoryEvent e) { // Don't care } } }