/** * Created on Oct 21, 2010 * * Copyright 2010 Vuze, Inc. All rights reserved. * 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 2 of the License only. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.eclipse.swt.widgets.Menu; import org.gudy.azureus2.core3.category.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.UIManager; import org.gudy.azureus2.plugins.ui.menus.*; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl; import org.gudy.azureus2.ui.swt.CategoryAdderWindow; import org.gudy.azureus2.ui.swt.TorrentUtil; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT; import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread; import org.gudy.azureus2.ui.swt.views.PeersGeneralView; import org.gudy.azureus2.ui.swt.views.utils.CategoryUIUtils; import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.tag.*; import com.aelitis.azureus.core.torrent.HasBeenOpenedListener; import com.aelitis.azureus.core.torrent.PlatformTorrentUtils; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager; import com.aelitis.azureus.ui.mdi.*; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.mdi.MdiSWTMenuHackListener; import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar; import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT; /** * Transfers Sidebar aka "My Torrents" aka "Files" * @author TuxPaper * @created Oct 21, 2010 * */ public class SB_Transfers { private static final Object AUTO_CLOSE_KEY = new Object(); private static final Object TAG_DATA_KEY = new Object(); private static final String ID_VITALITY_ACTIVE = "image.sidebar.vitality.dl"; private static final String ID_VITALITY_ALERT = "image.sidebar.vitality.alert"; public static class stats { int numSeeding = 0; int numDownloading = 0; int numQueued = 0; int numComplete = 0; int numIncomplete = 0; int numErrorComplete = 0; String errorInCompleteTooltip; int numErrorInComplete = 0; String errorCompleteTooltip; int numUnOpened = 0; int numStoppedAll = 0; int numStoppedIncomplete = 0; boolean includeLowNoise; long newestDownloadTime = 0; }; private static stats statsWithLowNoise = new stats(); private static stats statsNoLowNoise = new stats(); private static CopyOnWriteList<countRefreshListener> listeners = new CopyOnWriteList<countRefreshListener>(); private static boolean first = true; private static long coreCreateTime; static { statsNoLowNoise.includeLowNoise = false; statsWithLowNoise.includeLowNoise = true; } public static void setup(final MultipleDocumentInterface mdi) { MdiEntryCreationListener libraryCreator = new MdiEntryCreationListener() { public MdiEntry createMDiEntry(String id) { MdiEntry entry = mdi.createEntryFromSkinRef( SideBar.SIDEBAR_HEADER_TRANSFERS, SideBar.SIDEBAR_SECTION_LIBRARY, "library", "{sidebar." + SideBar.SIDEBAR_SECTION_LIBRARY + "}", null, null, false, ""); entry.setImageLeftID("image.sidebar.library"); return entry; } }; mdi.registerEntry(SideBar.SIDEBAR_SECTION_LIBRARY, libraryCreator); mdi.registerEntry("library", libraryCreator); mdi.registerEntry("minilibrary", libraryCreator); mdi.registerEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL, new MdiEntryCreationListener() { public MdiEntry createMDiEntry(String id) { return createDownloadingEntry(mdi); } }); mdi.registerEntry(SideBar.SIDEBAR_SECTION_LIBRARY_CD, new MdiEntryCreationListener() { public MdiEntry createMDiEntry(String id) { return createSeedingEntry(mdi); } }); mdi.registerEntry(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED, new MdiEntryCreationListener() { public MdiEntry createMDiEntry(String id) { return createUnopenedEntry(mdi); } }); AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { setupViewTitleWithCore(core); } }); PlatformTorrentUtils.addHasBeenOpenedListener(new HasBeenOpenedListener() { public void hasBeenOpenedChanged(DownloadManager dm, boolean opened) { recountUnopened(); refreshAllLibraries(); } }); addMenuUnwatched(SideBar.SIDEBAR_SECTION_LIBRARY); mdi.addListener(new MdiEntryLoadedListener() { public void mdiEntryLoaded(MdiEntry entry) { if (MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS.equals(entry.getId())) { addHeaderMenu(); } } }); } protected static void addHeaderMenu() { PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); final MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem; menuItem = menuManager.addMenuItem("sidebar." + MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, "MyTorrentsView.menu.setCategory.add"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { new CategoryAdderWindow(null); } }); // cats in sidebar menuItem.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setVisible(COConfigurationManager.getBooleanParameter("Library.CatInSideBar")); } }); menuItem = menuManager.addMenuItem("sidebar." + MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, "ConfigView.section.style.CatInSidebar"); menuItem.setStyle(MenuItem.STYLE_CHECK); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { boolean b = COConfigurationManager.getBooleanParameter("Library.CatInSideBar"); COConfigurationManager.setParameter("Library.CatInSideBar", !b); } }); menuItem.addFillListener(new MenuItemFillListener() { public void menuWillBeShown(MenuItem menu, Object data) { menu.setVisible(CategoryManager.getCategories().length > 0); menu.setData(Boolean.valueOf(COConfigurationManager.getBooleanParameter("Library.CatInSideBar"))); } }); // show tags in sidebar TagUIUtils.setupSideBarMenus( menuManager ); } protected static MdiEntry createUnopenedEntry(MultipleDocumentInterface mdi) { MdiEntry infoLibraryUn = mdi.createEntryFromSkinRef( SideBar.SIDEBAR_HEADER_TRANSFERS, SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED, "library", "{sidebar.LibraryUnopened}", null, null, false, SideBar.SIDEBAR_SECTION_LIBRARY); infoLibraryUn.setImageLeftID("image.sidebar.unopened"); addMenuUnwatched(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED); infoLibraryUn.setViewTitleInfo(new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT && statsNoLowNoise.numUnOpened > 0) { return "" + statsNoLowNoise.numUnOpened; } return null; } }); return infoLibraryUn; } private static void addMenuUnwatched(String id) { PluginInterface pi = PluginInitializer.getDefaultInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem = menuManager.addMenuItem("sidebar." + id, "v3.activity.button.watchall"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { CoreWaiterSWT.waitForCore(TriggerInThread.ANY_THREAD, new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { GlobalManager gm = core.getGlobalManager(); List<?> downloadManagers = gm.getDownloadManagers(); for (Iterator<?> iter = downloadManagers.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!PlatformTorrentUtils.getHasBeenOpened(dm) && dm.getAssumedComplete()) { PlatformTorrentUtils.setHasBeenOpened(dm, true); } } } }); } }); } /** * @param mdi * @return * * @since 4.5.1.1 */ protected static MdiEntry createSeedingEntry(MultipleDocumentInterface mdi) { ViewTitleInfo titleInfoSeeding = new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { return null; //numSeeding + " of " + numComplete; } if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) { return MessageText.getString("sidebar.LibraryCD.tooltip", new String[] { "" + statsNoLowNoise.numComplete, "" + statsNoLowNoise.numSeeding }); } return null; } }; MdiEntry entry = mdi.createEntryFromSkinRef( SideBar.SIDEBAR_HEADER_TRANSFERS, SideBar.SIDEBAR_SECTION_LIBRARY_DL, "library", "{sidebar.LibraryDL}", titleInfoSeeding, null, false, null); entry.setImageLeftID("image.sidebar.downloading"); MdiEntryVitalityImage vitalityImage = entry.addVitalityImage(ID_VITALITY_ALERT); vitalityImage.setVisible(false); entry.setViewTitleInfo(titleInfoSeeding); return entry; } protected static MdiEntry createDownloadingEntry(MultipleDocumentInterface mdi) { final MdiEntry[] entry_holder = { null }; ViewTitleInfo titleInfoDownloading = new ViewTitleInfo() { private long max_dl_time; public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { if ( COConfigurationManager.getBooleanParameter( "Request Attention On New Download" )){ if ( coreCreateTime > 0 ){ if ( max_dl_time == 0 ){ max_dl_time = coreCreateTime; } if ( statsNoLowNoise.newestDownloadTime > max_dl_time ){ MdiEntry entry = entry_holder[0]; if ( entry != null ){ max_dl_time = statsNoLowNoise.newestDownloadTime; entry.requestAttention(); } } } } int current = statsNoLowNoise.numIncomplete; if (current > 0) return current + ""; // + " of " + numIncomplete; } if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) { return MessageText.getString("sidebar.LibraryDL.tooltip", new String[] { "" + statsNoLowNoise.numIncomplete, "" + statsNoLowNoise.numDownloading }); } return null; } }; MdiEntry entry = mdi.createEntryFromSkinRef( SideBar.SIDEBAR_HEADER_TRANSFERS, SideBar.SIDEBAR_SECTION_LIBRARY_DL, "library", "{sidebar.LibraryDL}", titleInfoDownloading, null, false, null); entry_holder[0] = entry; entry.setImageLeftID("image.sidebar.downloading"); MdiEntryVitalityImage vitalityImage = entry.addVitalityImage(ID_VITALITY_ACTIVE); vitalityImage.setVisible(false); vitalityImage = entry.addVitalityImage(ID_VITALITY_ALERT); vitalityImage.setVisible(false); return entry; } protected static void setupViewTitleWithCore(AzureusCore core) { synchronized( SB_Transfers.class ){ if (!first) { return; } first = false; coreCreateTime = core.getCreateTime(); } final CategoryListener categoryListener = new CategoryListener() { public void downloadManagerRemoved(Category cat, DownloadManager removed) { RefreshCategorySideBar(cat); } public void downloadManagerAdded(Category cat, DownloadManager manager) { RefreshCategorySideBar(cat); } }; COConfigurationManager.addAndFireParameterListener("Library.CatInSideBar", new ParameterListener() { private CategoryManagerListener categoryManagerListener; public void parameterChanged(String parameterName) { if (Utils.isAZ2UI()) { return; } Category[] categories = CategoryManager.getCategories(); if (categories.length == 0) { return; } boolean catInSidebar = COConfigurationManager.getBooleanParameter("Library.CatInSideBar"); if (catInSidebar) { if (categoryManagerListener != null) { return; } categoryManagerListener = new CategoryManagerListener() { public void categoryRemoved(Category category) { removeCategory(category); } public void categoryChanged(Category category) { RefreshCategorySideBar(category); } public void categoryAdded(Category category) { Category[] categories = CategoryManager.getCategories(); if (categories.length == 3) { for (Category cat : categories) { setupCategory(cat); } } else { setupCategory(category); } } }; CategoryManager.addCategoryManagerListener(categoryManagerListener); if (categories.length > 2) { for (Category category : categories) { category.addCategoryListener(categoryListener); setupCategory(category); } } } else { if (categoryManagerListener != null) { CategoryManager.removeCategoryManagerListener(categoryManagerListener); categoryManagerListener = null; } for (Category category : categories) { category.removeCategoryListener(categoryListener); removeCategory(category); } } } }); final TagListener tagListener = new TagListener() { public void taggableAdded( Tag tag, Taggable tagged ) { RefreshTagSideBar( tag ); } public void taggableSync( Tag tag ) { RefreshTagSideBar( tag ); } public void taggableRemoved( Tag tag, Taggable tagged ) { RefreshTagSideBar( tag ); } }; COConfigurationManager.addAndFireParameterListener("Library.TagInSideBar", new ParameterListener(){ private TagManagerListener tagManagerListener; private TagTypeListener tagTypeListenerListener; public void parameterChanged(String parameterName) { if (Utils.isAZ2UI()) { return; } boolean tagInSidebar = COConfigurationManager.getBooleanParameter("Library.TagInSideBar"); if ( tagInSidebar ){ if ( tagManagerListener != null ){ return; } tagTypeListenerListener = new TagTypeListener() { public void tagTypeChanged( TagType tag_type ) { for ( Tag tag: tag_type.getTags()){ if ( tag.isVisible()){ setupTag( tag ); }else{ RefreshTagSideBar( tag ); } } } public void tagAdded( Tag tag ) { if ( tag.isVisible()){ setupTag( tag ); tag.addTagListener( tagListener, false ); } } public void tagChanged( Tag tag ) { RefreshTagSideBar( tag ); } public void tagRemoved( Tag tag ) { removeTag( tag ); } }; tagManagerListener = new TagManagerListener() { public void tagTypeAdded( TagManager manager, TagType tag_type ) { if ( tag_type.getTagType() != TagType.TT_DOWNLOAD_CATEGORY ){ tag_type.addTagTypeListener( tagTypeListenerListener, true ); } } public void tagTypeRemoved( TagManager manager, TagType tag_type ) { for ( Tag t: tag_type.getTags()){ removeTag( t ); } } }; TagManagerFactory.getTagManager().addTagManagerListener( tagManagerListener, true ); }else{ if ( tagManagerListener != null ){ TagManagerFactory.getTagManager().removeTagManagerListener( tagManagerListener ); List<TagType> tag_types = TagManagerFactory.getTagManager().getTagTypes(); for ( TagType tt: tag_types ){ if ( tt.getTagType() != TagType.TT_DOWNLOAD_CATEGORY ){ tt.removeTagTypeListener( tagTypeListenerListener ); } for ( Tag t: tt.getTags()){ t.removeTagListener( tagListener ); removeTag( t ); } } tagManagerListener = null; tagTypeListenerListener = null; } } } }); final GlobalManager gm = core.getGlobalManager(); final DownloadManagerListener dmListener = new DownloadManagerAdapter() { public void stateChanged(DownloadManager dm, int state) { stateChanged(dm, state, statsNoLowNoise); stateChanged(dm, state, statsWithLowNoise); } public void stateChanged(DownloadManager dm, int state, stats stats) { if (!stats.includeLowNoise && PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } updateDMCounts(dm); boolean complete = dm.getAssumedComplete(); Boolean wasErrorStateB = (Boolean) dm.getUserData("wasErrorState"); boolean wasErrorState = wasErrorStateB == null ? false : wasErrorStateB.booleanValue(); boolean isErrorState = state == DownloadManager.STATE_ERROR; if (isErrorState != wasErrorState) { int rel = isErrorState ? 1 : -1; if (complete) { stats.numErrorComplete += rel; } else { stats.numErrorInComplete += rel; } updateErrorTooltip(stats); dm.setUserData("wasErrorState", new Boolean(isErrorState)); } refreshAllLibraries(); } public void completionChanged(DownloadManager dm, boolean completed) { completionChanged(dm, completed, statsNoLowNoise); completionChanged(dm, completed, statsWithLowNoise); } public void completionChanged(DownloadManager dm, boolean completed, stats stats) { if (!stats.includeLowNoise && PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } int dm_state = updateDMCounts(dm); if (completed) { stats.numComplete++; stats.numIncomplete--; if (dm_state == DownloadManager.STATE_ERROR) { stats.numErrorComplete++; stats.numErrorInComplete--; } if (dm_state == DownloadManager.STATE_STOPPED) { statsNoLowNoise.numStoppedIncomplete--; } } else { stats.numComplete--; stats.numIncomplete++; if (dm_state == DownloadManager.STATE_ERROR) { stats.numErrorComplete--; stats.numErrorInComplete++; } if (dm_state == DownloadManager.STATE_STOPPED) { statsNoLowNoise.numStoppedIncomplete++; } } recountUnopened(); updateErrorTooltip(stats); refreshAllLibraries(); } protected void updateErrorTooltip(stats stats) { if (stats.numErrorComplete < 0) { stats.numErrorComplete = 0; } if (stats.numErrorInComplete < 0) { stats.numErrorInComplete = 0; } if (stats.numErrorComplete > 0 || stats.numErrorInComplete > 0) { String comp_error = null; String incomp_error = null; List<?> downloads = gm.getDownloadManagers(); for (int i = 0; i < downloads.size(); i++) { DownloadManager download = (DownloadManager) downloads.get(i); if (download.getState() == DownloadManager.STATE_ERROR) { if (download.getAssumedComplete()) { if (comp_error == null) { comp_error = download.getDisplayName() + ": " + download.getErrorDetails(); } else { comp_error += "..."; } } else { if (incomp_error == null) { incomp_error = download.getDisplayName() + ": " + download.getErrorDetails(); } else { incomp_error += "..."; } } } } stats.errorCompleteTooltip = comp_error; stats.errorInCompleteTooltip = incomp_error; } } }; gm.addListener(new GlobalManagerAdapter() { public void downloadManagerRemoved(DownloadManager dm) { downloadManagerRemoved(dm, statsNoLowNoise); downloadManagerRemoved(dm, statsWithLowNoise); } public void downloadManagerRemoved(DownloadManager dm, stats stats) { if (!stats.includeLowNoise && PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } recountUnopened(); if (dm.getAssumedComplete()) { stats.numComplete--; Boolean wasDownloadingB = (Boolean) dm.getUserData("wasDownloading"); if (wasDownloadingB != null && wasDownloadingB.booleanValue()) { stats.numDownloading--; } } else { stats.numIncomplete--; Boolean wasSeedingB = (Boolean) dm.getUserData("wasSeeding"); if (wasSeedingB != null && wasSeedingB.booleanValue()) { stats.numSeeding--; } } Boolean wasStoppedB = (Boolean) dm.getUserData("wasStopped"); boolean wasStopped = wasStoppedB == null ? false : wasStoppedB.booleanValue(); if (wasStopped) { stats.numStoppedAll--; if (!dm.getAssumedComplete()) { stats.numStoppedIncomplete--; } } Boolean wasQueuedB = (Boolean) dm.getUserData("wasQueued"); boolean wasQueued = wasQueuedB == null ? false : wasQueuedB.booleanValue(); if (wasQueued) { stats.numQueued--; } refreshAllLibraries(); dm.removeListener(dmListener); } public void downloadManagerAdded(DownloadManager dm) { dm.addListener(dmListener, false); recountUnopened(); downloadManagerAdded(dm, statsNoLowNoise); downloadManagerAdded(dm, statsWithLowNoise); refreshAllLibraries(); } public void downloadManagerAdded(DownloadManager dm, stats stats) { if (!stats.includeLowNoise && PlatformTorrentUtils.isAdvancedViewOnly(dm)) { return; } boolean assumed_complete = dm.getAssumedComplete(); if ( dm.isPersistent() && dm.getTorrent() != null){ // ignore borked torrents as their create time is inaccurate stats.newestDownloadTime = Math.max( stats.newestDownloadTime, dm.getCreationTime()); } int dm_state = dm.getState(); if (assumed_complete) { stats.numComplete++; if (dm_state == DownloadManager.STATE_SEEDING) { stats.numSeeding++; } } else { stats.numIncomplete++; if (dm_state == DownloadManager.STATE_DOWNLOADING) { dm.setUserData("wasDownloading", Boolean.TRUE); stats.numDownloading++; } else { dm.setUserData("wasDownloading", Boolean.FALSE); } } } }, false); List<DownloadManager> downloadManagers = gm.getDownloadManagers(); for (Iterator<DownloadManager> iter = downloadManagers.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); boolean lowNoise = PlatformTorrentUtils.isAdvancedViewOnly(dm); if ( dm.isPersistent() && dm.getTorrent() != null){ // ignore borked torrents as their create time is inaccurate long createTime = dm.getCreationTime(); statsWithLowNoise.newestDownloadTime = Math.max( statsWithLowNoise.newestDownloadTime, createTime); if (!lowNoise) { statsNoLowNoise.newestDownloadTime = Math.max( statsNoLowNoise.newestDownloadTime, createTime); } } dm.addListener(dmListener, false); int dm_state = dm.getState(); if (dm_state == DownloadManager.STATE_STOPPED) { dm.setUserData("wasStopped", Boolean.TRUE); statsWithLowNoise.numStoppedAll++; if (!dm.getAssumedComplete()) { statsWithLowNoise.numStoppedIncomplete++; } if (!lowNoise) { statsNoLowNoise.numStoppedAll++; if (!dm.getAssumedComplete()) { statsNoLowNoise.numStoppedIncomplete++; } } } else { dm.setUserData("wasStopped", Boolean.FALSE); } if (dm_state == DownloadManager.STATE_QUEUED) { dm.setUserData("wasQueued", Boolean.TRUE); statsWithLowNoise.numQueued++; if (!lowNoise) { statsNoLowNoise.numQueued++; } } else { dm.setUserData("wasQueued", Boolean.FALSE); } if (dm.getAssumedComplete()) { statsWithLowNoise.numComplete++; if (!lowNoise) { statsNoLowNoise.numComplete++; } if (dm_state == DownloadManager.STATE_SEEDING) { dm.setUserData("wasSeeding", Boolean.TRUE); statsWithLowNoise.numSeeding++; if (!lowNoise) { statsNoLowNoise.numSeeding++; } } else { dm.setUserData("wasSeeding", Boolean.FALSE); } } else { statsWithLowNoise.numIncomplete++; if (!lowNoise) { statsNoLowNoise.numIncomplete++; } if (dm_state == DownloadManager.STATE_DOWNLOADING) { statsWithLowNoise.numDownloading++; if (!lowNoise) { statsNoLowNoise.numDownloading++; } } } } recountUnopened(); refreshAllLibraries(); } // category stuff private static void RefreshCategorySideBar(Category category) { MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } MdiEntry entry = mdi.getEntry("Cat." + Base32.encode(category.getName().getBytes())); if (entry == null) { return; } ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo()); } private static void setupCategory(final Category category) { MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } String name = category.getName(); String id = "Cat." + Base32.encode(name.getBytes()); if (category.getType() != Category.TYPE_USER) { name = "{" + name + "}"; } ViewTitleInfo viewTitleInfo = new ViewTitleInfo() { public Object getTitleInfoProperty(int propertyID) { if (propertyID == TITLE_INDICATOR_TEXT) { if (statsNoLowNoise.numIncomplete > 0) { List<?> dms = category.getDownloadManagers(null); if (dms != null) { return "" + dms.size(); } } } return null; } }; MdiEntry entry = mdi.createEntryFromSkinRef( MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, id, "library", name, viewTitleInfo, category, false, null); if (entry != null) { entry.setImageLeftID("image.sidebar.library"); } if (entry instanceof SideBarEntrySWT) { final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry; entrySWT.addListener(new MdiSWTMenuHackListener() { public void menuWillBeShown(MdiEntry entry, Menu menuTree) { CategoryUIUtils.createMenuItems(menuTree, category); } }); } entry.addListener(new MdiEntryDropListener() { public boolean mdiEntryDrop(MdiEntry entry, Object payload) { if (!(payload instanceof String)) { return false; } String dropped = (String) payload; String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped); if (split.length > 1) { String type = split[0]; if (type.startsWith("DownloadManager")) { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); for (int i = 1; i < split.length; i++) { String hash = split[i]; try { DownloadManager dm = gm.getDownloadManager(new HashWrapper( Base32.decode(hash))); if (dm != null) { TorrentUtil.assignToCategory(new Object[] { dm }, category); } } catch (Throwable t) { } } } } return true; } }); } private static void removeCategory(Category category) { MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } MdiEntry entry = mdi.getEntry("Cat." + Base32.encode(category.getName().getBytes())); if (entry != null) { entry.close(true); } } // tag stuff private static void RefreshTagSideBar(Tag tag) { MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } MdiEntry entry = mdi.getEntry("Tag." + tag.getTagType().getTagType() + "." + tag.getTagID()); if ( entry == null ){ if ( tag.isVisible()){ setupTag( tag ); } return; } if ( !tag.isVisible()){ removeTag( tag ); return; } String old_title = entry.getTitle(); String tag_title = tag.getTagName( true ); if ( !old_title.equals( tag_title )){ entry.setTitle( tag_title ); } ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo()); Object[] tag_data = (Object[])entry.getUserData( TAG_DATA_KEY ); if ( tag_data != null ){ boolean auto_tag = tag.isTagAuto(); if ( auto_tag != (Boolean)tag_data[1] ){ tag_data[1] = auto_tag; if ( auto_tag ){ entry.removeListener((MdiEntryDropListener)tag_data[0]); }else{ entry.addListener((MdiEntryDropListener)tag_data[0]); } } } } private static void setupTag( final Tag tag ) { MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT(); if ( mdi == null ){ return; } String id = "Tag." + tag.getTagType().getTagType() + "." + tag.getTagID(); if ( mdi.getEntry( id ) != null ){ return; } String name = tag.getTagName( true ); // find where to locate this in the sidebar TreeMap<String,String> name_map = new TreeMap<String,String>(new FormattersImpl().getAlphanumericComparator( true )); name_map.put( name, id ); for ( Tag t: tag.getTagType().getTags()){ if ( t.isVisible()){ String tid = "Tag." + tag.getTagType().getTagType() + "." + t.getTagID(); if ( mdi.getEntry( tid ) != null ){ name_map.put( t.getTagName( true ), tid ); } } } String prev_id = null; for ( Map.Entry<String,String> entry: name_map.entrySet()){ String this_id = entry.getValue(); if ( this_id == id ){ break; } prev_id = this_id; } if ( prev_id == null && name_map.size() > 1 ){ Iterator<String> it = name_map.values().iterator(); it.next(); prev_id = "~" + it.next(); } boolean auto = tag.getTagType().isTagTypeAuto(); ViewTitleInfo viewTitleInfo = new ViewTitleInfo() { public Object getTitleInfoProperty( int pid ) { if ( pid == TITLE_INDICATOR_TEXT ){ return( String.valueOf( tag.getTaggedCount())); }else if ( pid == TITLE_INDICATOR_COLOR ){ TagType tag_type = tag.getTagType(); int[] def_color = tag_type.getColorDefault(); int[] tag_color = tag.getColor(); if ( tag_color != def_color ){ return( tag_color ); } }else if ( pid == TITLE_INDICATOR_TEXT_TOOLTIP ){ return( TagUIUtils.getTagTooltip( tag )); } return null; } }; MdiEntry entry; boolean closable = auto; if ( tag.getTaggableTypes() == Taggable.TT_DOWNLOAD ){ closable = true; entry = mdi.createEntryFromSkinRef( MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, id, "library", name, viewTitleInfo, tag, closable, prev_id); }else{ entry = mdi.createEntryFromEventListener( MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, new PeersGeneralView( tag ), id, closable, null, prev_id); entry.setViewTitleInfo( viewTitleInfo ); } if ( closable ){ entry.addListener( new MdiCloseListener() { public void mdiEntryClosed( MdiEntry entry, boolean userClosed ) { if ( userClosed && entry.getUserData( AUTO_CLOSE_KEY ) == null ){ // userClosed isn't all we want - it just means we're not closing the app... So to prevent // a deselection of 'show tags in sidebar' 'user-closing' the entries we need this test if ( COConfigurationManager.getBooleanParameter("Library.TagInSideBar")){ tag.setVisible( false ); } } } }); } if (entry != null) { String image_id = tag.getImageID(); if ( image_id != null ){ entry.setImageLeftID( image_id ); }else if ( tag.getTagType().getTagType() == TagType.TT_PEER_IPSET ){ entry.setImageLeftID("image.sidebar.tag-red"); }else if ( tag.getTagType().isTagTypePersistent()){ entry.setImageLeftID("image.sidebar.tag-green"); }else{ entry.setImageLeftID("image.sidebar.tag-blue"); } } if (entry instanceof SideBarEntrySWT) { final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry; entrySWT.addListener(new MdiSWTMenuHackListener() { public void menuWillBeShown(MdiEntry entry, Menu menuTree) { TagUIUtils.createSideBarMenuItems(menuTree, tag); } }); } if ( !auto ){ MdiEntryDropListener dl = new MdiEntryDropListener() { public boolean mdiEntryDrop(MdiEntry entry, Object payload) { if (!(payload instanceof String)) { return false; } if ( tag.isTagAuto()){ return( false ); } String dropped = (String) payload; String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped); if (split.length > 1) { String type = split[0]; if (type.startsWith("DownloadManager") || type.startsWith( "DiskManagerFileInfo" )) { GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); for (int i = 1; i < split.length; i++) { String hash = split[i]; int sep = hash.indexOf( ";" ); // for files if ( sep != -1 ){ hash = hash.substring( 0, sep ); } try { DownloadManager dm = gm.getDownloadManager(new HashWrapper( Base32.decode(hash))); if ( dm != null ){ if ( tag.hasTaggable( dm )){ tag.removeTaggable( dm ); }else{ tag.addTaggable( dm ); } } }catch ( Throwable t ){ } } } } return true; } }; boolean tag_auto = tag.isTagAuto(); entry.setUserData( TAG_DATA_KEY, new Object[]{ dl, tag_auto }); if ( !tag_auto ){ entry.addListener( dl ); } } } private static void removeTag(Tag tag) { MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } MdiEntry entry = mdi.getEntry("Tag." + tag.getTagType().getTagType() + "." + tag.getTagID()); if (entry != null) { entry.setUserData( AUTO_CLOSE_KEY, "" ); entry.close( true ); } } // ------------------- private static int updateDMCounts(DownloadManager dm) { boolean isSeeding; boolean isDownloading; boolean isQueued; boolean isStopped; Boolean wasSeedingB = (Boolean) dm.getUserData("wasSeeding"); boolean wasSeeding = wasSeedingB == null ? false : wasSeedingB.booleanValue(); Boolean wasDownloadingB = (Boolean) dm.getUserData("wasDownloading"); boolean wasDownloading = wasDownloadingB == null ? false : wasDownloadingB.booleanValue(); Boolean wasStoppedB = (Boolean) dm.getUserData("wasStopped"); boolean wasStopped = wasStoppedB == null ? false : wasStoppedB.booleanValue(); Boolean wasQueuedB = (Boolean) dm.getUserData("wasQueued"); boolean wasQueued = wasQueuedB == null ? false : wasQueuedB.booleanValue(); int dm_state = dm.getState(); if (dm.getAssumedComplete()) { isSeeding = dm_state == DownloadManager.STATE_SEEDING; isDownloading = false; } else { isDownloading = dm_state == DownloadManager.STATE_DOWNLOADING; isSeeding = false; } isStopped = dm_state == DownloadManager.STATE_STOPPED; isQueued = dm_state == DownloadManager.STATE_QUEUED; boolean lowNoise = PlatformTorrentUtils.isAdvancedViewOnly(dm); if (isDownloading != wasDownloading) { if (isDownloading) { statsWithLowNoise.numDownloading++; if (!lowNoise) { statsNoLowNoise.numDownloading++; } } else { statsWithLowNoise.numDownloading--; if (!lowNoise) { statsNoLowNoise.numDownloading--; } } dm.setUserData("wasDownloading", new Boolean(isDownloading)); } if (isSeeding != wasSeeding) { if (isSeeding) { statsWithLowNoise.numSeeding++; if (!lowNoise) { statsNoLowNoise.numSeeding++; } } else { statsWithLowNoise.numSeeding--; if (!lowNoise) { statsNoLowNoise.numSeeding--; } } dm.setUserData("wasSeeding", new Boolean(isSeeding)); } if (isStopped != wasStopped) { if (isStopped) { statsWithLowNoise.numStoppedAll++; if (!dm.getAssumedComplete()) { statsWithLowNoise.numStoppedIncomplete++; } if (!lowNoise) { statsNoLowNoise.numStoppedAll++; if (!dm.getAssumedComplete()) { statsNoLowNoise.numStoppedIncomplete++; } } } else { statsWithLowNoise.numStoppedAll--; if (!dm.getAssumedComplete()) { statsWithLowNoise.numStoppedIncomplete--; } if (!lowNoise) { statsNoLowNoise.numStoppedAll--; if (!dm.getAssumedComplete()) { statsNoLowNoise.numStoppedIncomplete--; } } } dm.setUserData("wasStopped", new Boolean(isStopped)); } if (isQueued != wasQueued) { if (isQueued) { statsWithLowNoise.numQueued++; if (!lowNoise) { statsNoLowNoise.numQueued++; } } else { statsWithLowNoise.numQueued--; if (!lowNoise) { statsNoLowNoise.numQueued--; } } dm.setUserData("wasQueued", new Boolean(isQueued)); } return( dm_state ); } private static void recountUnopened() { if (!AzureusCoreFactory.isCoreRunning()) { return; } GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager(); List<?> dms = gm.getDownloadManagers(); statsNoLowNoise.numUnOpened = 0; for (Iterator<?> iter = dms.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!PlatformTorrentUtils.getHasBeenOpened(dm) && dm.getAssumedComplete()) { statsNoLowNoise.numUnOpened++; } } statsWithLowNoise.numUnOpened = statsNoLowNoise.numUnOpened; } protected static void addCountRefreshListener(countRefreshListener l) { l.countRefreshed(statsWithLowNoise, statsNoLowNoise); listeners.add(l); } public static void triggerCountRefreshListeners() { for (countRefreshListener l : listeners) { l.countRefreshed(statsWithLowNoise, statsNoLowNoise); } } /** * * * @since 3.1.1.1 */ private static FrequencyLimitedDispatcher refresh_limiter = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { refreshAllLibrariesSupport(); } }, 250); static { refresh_limiter.setSingleThreaded(); } private static void refreshAllLibraries() { refresh_limiter.dispatch(); } private static void refreshAllLibrariesSupport() { for (countRefreshListener l : listeners) { l.countRefreshed(statsWithLowNoise, statsNoLowNoise); } MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI(); if (mdi == null) { return; } if (statsNoLowNoise.numIncomplete > 0) { MdiEntry entry = mdi.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); if (entry == null) { mdi.loadEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY_DL, false); } } else { MdiEntry entry = mdi.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); if (entry != null) { entry.close(true); } } MdiEntry entry = mdi.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_DL); if (entry != null) { MdiEntryVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { MdiEntryVitalityImage vitalityImage = vitalityImages[i]; String imageID = vitalityImage.getImageID(); if (imageID == null) { continue; } if (imageID.equals(ID_VITALITY_ACTIVE)) { vitalityImage.setVisible(statsNoLowNoise.numDownloading > 0); } else if (imageID.equals(ID_VITALITY_ALERT)) { vitalityImage.setVisible(statsNoLowNoise.numErrorInComplete > 0); if (statsNoLowNoise.numErrorInComplete > 0) { vitalityImage.setToolTip(statsNoLowNoise.errorInCompleteTooltip); } } } ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo()); } entry = mdi.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_CD); if (entry != null) { MdiEntryVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { MdiEntryVitalityImage vitalityImage = vitalityImages[i]; String imageID = vitalityImage.getImageID(); if (imageID == null) { continue; } if (imageID.equals(ID_VITALITY_ALERT)) { vitalityImage.setVisible(statsNoLowNoise.numErrorComplete > 0); if (statsNoLowNoise.numErrorComplete > 0) { vitalityImage.setToolTip(statsNoLowNoise.errorCompleteTooltip); } } } } entry = mdi.getEntry(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED); if (entry != null) { ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo()); } } public static String getTableIdFromFilterMode(int torrentFilterMode, boolean big) { if (torrentFilterMode == SBC_LibraryView.TORRENTS_COMPLETE) { return big ? TableManager.TABLE_MYTORRENTS_COMPLETE_BIG : TableManager.TABLE_MYTORRENTS_COMPLETE; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE) { return big ? TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG : TableManager.TABLE_MYTORRENTS_INCOMPLETE; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) { return TableManager.TABLE_MYTORRENTS_ALL_BIG; } else if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) { return big ? TableManager.TABLE_MYTORRENTS_UNOPENED_BIG : TableManager.TABLE_MYTORRENTS_UNOPENED; } return null; } protected static interface countRefreshListener { public void countRefreshed(stats statsWithLowNoise, stats statsNoLowNoise); } }