/* * Created on 30 juin 2003 * * Copyright (C) 2004, 2005, 2006 Aelitis SAS, 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; either version 2 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 ( see the LICENSE file ). * * 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 * * AELITIS, SAS au capital de 46,603.30 euros, * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.ui.swt.views; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.*; import java.util.List; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; 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.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.*; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.logging.LogEvent; import org.gudy.azureus2.core3.logging.LogIDs; import org.gudy.azureus2.core3.logging.Logger; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.PluginManager; import org.gudy.azureus2.plugins.download.DownloadTypeComplete; import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete; import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener; import org.gudy.azureus2.plugins.ui.tables.TableManager; import org.gudy.azureus2.plugins.ui.tables.TableRow; import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener; import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener; import org.gudy.azureus2.ui.swt.*; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.components.CompositeMinSize; import org.gudy.azureus2.ui.swt.help.HealthHelpWindow; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.minibar.DownloadBar; import org.gudy.azureus2.ui.swt.plugins.UISWTInstance; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent; import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore; import org.gudy.azureus2.ui.swt.views.piece.PieceInfoView; import org.gudy.azureus2.ui.swt.views.table.TableViewSWT; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener; import org.gudy.azureus2.ui.swt.views.table.TableViewSWTPanelCreator; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewFactory; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWT_TabsCommon; import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab; import org.gudy.azureus2.ui.swt.views.table.painted.TableRowPainted; import org.gudy.azureus2.ui.swt.views.utils.CategoryUIUtils; import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.tag.Tag; import com.aelitis.azureus.core.tag.TagListener; import com.aelitis.azureus.core.tag.Taggable; import com.aelitis.azureus.core.util.RegExUtil; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.ToolBarItem; import com.aelitis.azureus.ui.common.table.*; import com.aelitis.azureus.ui.selectedcontent.ISelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContent; import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager; import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT; import com.aelitis.azureus.ui.swt.UIFunctionsSWT; /** Displays a list of torrents in a table view. * * @author Olivier * @author TuxPaper * 2004/Apr/18: Use TableRowImpl instead of PeerRow * 2004/Apr/20: Remove need for tableItemToObject * 2004/Apr/21: extends TableView instead of IAbstractView * 2005/Oct/01: Column moving in SWT >= 3.1 */ public class MyTorrentsView extends TableViewTab<DownloadManager> implements GlobalManagerListener, ParameterListener, DownloadManagerListener, CategoryManagerListener, CategoryListener, TagListener, KeyListener, TableLifeCycleListener, TableViewSWTPanelCreator, TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener, TableViewFilterCheck.TableViewFilterCheckEx<DownloadManager>, TableRowRefreshListener, TableCountChangeListener, TableExpansionChangeListener { private static final LogIDs LOGID = LogIDs.GUI; public static volatile Set<String> preferred_tracker_names; public static volatile boolean eta_absolute; public static volatile boolean progress_eta_absolute; static{ COConfigurationManager.addAndFireParameterListeners( new String[]{ "mtv.trackername.pref.hosts", "mtv.eta.show_absolute", "mtv.progress_eta.show_absolute", }, new ParameterListener() { public void parameterChanged( String name ) { String prefs = COConfigurationManager.getStringParameter( "mtv.trackername.pref.hosts", null ); Set<String> new_vals = new HashSet<String>(); if ( prefs != null ){ String[] bits = prefs.split( ";" ); for ( String s: bits ){ s = s.trim(); if ( s.length() > 0 ){ new_vals.add( s ); } } } preferred_tracker_names = new_vals; eta_absolute = COConfigurationManager.getBooleanParameter( "mtv.eta.show_absolute", false ); progress_eta_absolute = COConfigurationManager.getBooleanParameter( "mtv.progress_eta.show_absolute", false ); } }); } private AzureusCore azureus_core; private GlobalManager globalManager; // keep this listener separate class as there is confusion within the globalmanager // if the same instance is registered as both a GlobalManagerListener and a GlobalManagerEventListener // yes, I know private GlobalManagerEventListener gm_event_listener = new GlobalManagerEventListener() { public void eventOccurred( GlobalManagerEvent event ) { if ( event.getEventType() == GlobalManagerEvent.ET_REQUEST_ATTENTION ){ DownloadManager dm = event.getDownload(); if ( isOurDownloadManager( dm )){ TableRowCore row = tv.getRow( dm ); if ( row != null ){ TableRowCore[] existing = tv.getSelectedRows(); if ( existing != null ){ for ( TableRowCore e: existing ){ if ( e != row ){ e.setSelected( false ); } } } if ( !row.isSelected()){ row.setSelected( true ); } } } } } }; protected boolean isSeedingView; private boolean supportsTabs; private Composite cTablePanel; private Font fontButton = null; protected Composite cCategories; private DragSource dragSource = null; private DropTarget dropTarget = null; protected Text txtFilter = null; private TimerEventPeriodic txtFilterUpdateEvent; private Category currentCategory; private Tag currentTag; // table item index, where the drag has started private int drag_drop_line_start = -1; private TableRowCore[] drag_drop_rows = null; private boolean bDNDalwaysIncomplete; private TableViewSWT<DownloadManager> tv; private Composite cTableParentPanel; protected boolean viewActive; private TableSelectionListener defaultSelectedListener; private Composite filterParent; private boolean neverShowCatButtons; private boolean rebuildListOnFocusGain = false; public MyTorrentsView( boolean supportsTabs ) { super("MyTorrentsView"); this.supportsTabs = supportsTabs; } /** * Initialize * * @param _azureus_core * @param isSeedingView * @param basicItems * @param cCats */ public MyTorrentsView( AzureusCore _azureus_core, String tableID, boolean isSeedingView, TableColumnCore[] basicItems, Text txtFilter, Composite cCats, boolean supportsTabs ) { super("MyTorrentsView"); this.txtFilter = txtFilter; this.cCategories = cCats; this.supportsTabs = supportsTabs; init(_azureus_core, tableID, isSeedingView, isSeedingView ? DownloadTypeComplete.class : DownloadTypeIncomplete.class, basicItems); } // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView() public TableViewSWT<DownloadManager> initYourTableView() { return tv; } public void init(AzureusCore _azureus_core, String tableID, boolean isSeedingView, Class<?> forDataSourceType, TableColumnCore[] basicItems) { this.isSeedingView = isSeedingView; tv = createTableView(forDataSourceType, tableID, basicItems); tv.setRowDefaultHeight(17); /* * 'Big' table has taller row height */ if (getRowDefaultHeight() > 0) { tv.setRowDefaultHeight(getRowDefaultHeight()); } azureus_core = _azureus_core; this.globalManager = azureus_core.getGlobalManager(); if (currentCategory == null) { currentCategory = CategoryManager.getCategory(Category.TYPE_ALL); } tv.addLifeCycleListener(this); tv.setMainPanelCreator(this); tv.addSelectionListener(this, false); tv.addMenuFillListener(this); tv.addRefreshListener(this, false); if (tv.canHaveSubItems()) { tv.addRefreshListener(this); tv.addCountChangeListener(this); tv.addExpansionChangeListener(this); } tv.addTableDataSourceChangedListener(new TableDataSourceChangedListener() { public void tableDataSourceChanged(Object newDataSource) { if (newDataSource instanceof Category) { neverShowCatButtons = true; activateCategory((Category) newDataSource); }else if ( newDataSource instanceof Tag ){ neverShowCatButtons = true; activateTag((Tag) newDataSource); } } }, true); if (txtFilter != null) { filterParent = txtFilter.getParent(); if (Constants.isWindows) { // dirty hack because window's filter box is within a bubble of it's own filterParent = filterParent.getParent(); } Menu menuFilterHeader = new Menu(filterParent); // show uptime final MenuItem menuItemShowUptime = new MenuItem(menuFilterHeader, SWT.CHECK); Messages.setLanguageText( menuItemShowUptime, "ConfigView.label.showuptime" ); menuItemShowUptime.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { COConfigurationManager.setParameter( "MyTorrentsView.showuptime", menuItemShowUptime.getSelection()); } public void widgetDefaultSelected(SelectionEvent e) { } }); // hooks menuFilterHeader.addMenuListener(new MenuListener() { public void menuShown(MenuEvent e) { menuItemShowUptime.setSelection(COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" )); } public void menuHidden(MenuEvent e) { } }); filterParent.setMenu(menuFilterHeader); Control[] children = filterParent.getChildren(); for (Control control : children) { if (control != txtFilter) { control.setMenu(menuFilterHeader); } } } //tv.setEnableTabViews(true); //IView views[] = { new GeneralView(), new PeersView(), // new PeersGraphicView(), new PiecesView(), new FilesView(), // new LoggerView() }; //tv.setCoreTabViews(views); } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized() public void tableViewInitialized() { tv.addKeyListener(this); createTabs(); if (txtFilter == null) { tv.enableFilterCheck(null, this); } createDragDrop(); Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { COConfigurationManager.addAndFireParameterListeners(new String[] { "DND Always In Incomplete", "User Mode" }, MyTorrentsView.this); // can get an activate prior to this running so need to guard against adding the category listener twice if (currentCategory != null && !currentCategory.hasCategoryListener( MyTorrentsView.this)) { currentCategory.addCategoryListener(MyTorrentsView.this); } if ( currentTag != null ){ currentTag.removeTagListener(MyTorrentsView.this); // avoid double addition if already present currentTag.addTagListener(MyTorrentsView.this,false); } CategoryManager.addCategoryManagerListener(MyTorrentsView.this); globalManager.addListener(MyTorrentsView.this, false); globalManager.addEventListener( gm_event_listener ); DownloadManager[] dms = globalManager.getDownloadManagers().toArray(new DownloadManager[0]); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; dm.addListener(MyTorrentsView.this); if (!isOurDownloadManager(dm)) { dms[i] = null; } } tv.addDataSources(dms); tv.processDataSourceQueue(); } }); cTablePanel.layout(); } // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed() public void tableViewDestroyed() { tv.removeKeyListener(this); Utils.execSWTThread(new AERunnable() { public void runSupport() { try { Utils.disposeSWTObjects(new Object[] { dragSource, dropTarget, fontButton }); dragSource = null; dropTarget = null; fontButton = null; } catch (Exception e) { Debug.out(e); } } }); Object[] dms = globalManager.getDownloadManagers().toArray(); for (int i = 0; i < dms.length; i++) { DownloadManager dm = (DownloadManager) dms[i]; dm.removeListener(this); } if (currentCategory != null) { currentCategory.removeCategoryListener(this); } CategoryManager.removeCategoryManagerListener(this); if ( currentTag != null ){ currentTag.removeTagListener(this); } globalManager.removeListener(this); globalManager.removeEventListener( gm_event_listener ); COConfigurationManager.removeParameterListener("DND Always In Incomplete", this); COConfigurationManager.removeParameterListener("User Mode", this); } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTPanelCreator#createTableViewPanel(org.eclipse.swt.widgets.Composite) public Composite createTableViewPanel(Composite composite) { GridData gridData; cTableParentPanel = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; cTableParentPanel.setLayout(layout); if (composite.getLayout() instanceof GridLayout) { cTableParentPanel.setLayoutData(new GridData(GridData.FILL_BOTH)); } cTablePanel = new Composite(cTableParentPanel, SWT.NULL); cTablePanel.addListener(SWT.Activate, new Listener() { public void handleEvent(Event event) { viewActive = true; updateSelectedContent(); //refreshIconBar(); } }); cTablePanel.addListener(SWT.Deactivate, new Listener() { public void handleEvent(Event event) { viewActive = false; // don't updateSelectedContent() because we may have switched // to a button or a text field, and we still want out content to be // selected } }); gridData = new GridData(GridData.FILL_BOTH); cTablePanel.setLayoutData(gridData); layout = new GridLayout(1, false); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; layout.horizontalSpacing = 0; cTablePanel.setLayout(layout); cTablePanel.layout(); return cTablePanel; } private void createTabs() { Utils.execSWTThread(new AERunnable() { public void runSupport() { swt_createTabs(); } }); } private void swt_createTabs() { Category[] categories = CategoryManager.getCategories(); Arrays.sort(categories); boolean showCat = false; if (!neverShowCatButtons) { for(int i = 0; i < categories.length; i++) { if(categories[i].getType() == Category.TYPE_USER) { showCat = true; break; } } } buildHeaderArea(); if (cCategories != null && !cCategories.isDisposed()) { Control[] controls = cCategories.getChildren(); for (int i = 0; i < controls.length; i++) { controls[i].dispose(); } } if (showCat) { buildCat(categories); } else if (cTableParentPanel != null && !cTableParentPanel.isDisposed()) { cTableParentPanel.layout(); } } private void buildHeaderArea() { if (cCategories == null) { cCategories = new CompositeMinSize(cTableParentPanel, SWT.NONE); ((CompositeMinSize) cCategories).setMinSize(new Point(SWT.DEFAULT, 24)); GridData gridData = new GridData(SWT.RIGHT, SWT.TOP, true, false); cCategories.setLayoutData(gridData); cCategories.moveAbove(null); }else if ( cCategories.isDisposed()){ return; } if (!(cCategories.getLayout() instanceof RowLayout)) { RowLayout rowLayout = new RowLayout(); rowLayout.marginTop = 0; rowLayout.marginBottom = 0; rowLayout.marginLeft = 3; rowLayout.marginRight = 0; rowLayout.spacing = 0; rowLayout.wrap = true; cCategories.setLayout(rowLayout); } tv.enableFilterCheck(txtFilter, this); } /** * * * @param categories * @since 3.1.1.1 */ private void buildCat(Category[] categories) { int iFontPixelsHeight = 10; int iFontPointHeight = (iFontPixelsHeight * 72) / cCategories.getDisplay().getDPI().y; for (int i = 0; i < categories.length; i++) { final Category category = categories[i]; final Button catButton = new Button(cCategories, SWT.TOGGLE); catButton.addKeyListener(this); if (i == 0 && fontButton == null) { Font f = catButton.getFont(); FontData fd = f.getFontData()[0]; fd.setHeight(iFontPointHeight); fontButton = new Font(cCategories.getDisplay(), fd); } catButton.setText("|"); catButton.setFont(fontButton); catButton.pack(true); if (catButton.computeSize(100, SWT.DEFAULT).y > 0) { RowData rd = new RowData(); rd.height = catButton.computeSize(100, SWT.DEFAULT).y - 2 + catButton.getBorderWidth() * 2; catButton.setLayoutData(rd); } final String name = category.getName(); if (category.getType() == Category.TYPE_USER) catButton.setText(name); else Messages.setLanguageText(catButton, name); catButton.setData("Category", category); if (category == currentCategory) { catButton.setSelection(true); } catButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Button curButton = (Button) e.widget; boolean isEnabled = curButton.getSelection(); Control[] controls = cCategories.getChildren(); if (!isEnabled) { for (int i = 0; i < controls.length; i++) { if (controls[i] instanceof Button) { curButton = (Button) controls[i]; break; } } } for (int i = 0; i < controls.length; i++) { if (!(controls[i] instanceof Button)) { continue; } Button b = (Button) controls[i]; if (b != curButton && b.getSelection()) b.setSelection(false); else if (b == curButton && !b.getSelection()) b.setSelection(true); } activateCategory((Category) curButton.getData("Category")); } }); catButton.addListener(SWT.MouseHover, new Listener() { public void handleEvent(Event event) { Button curButton = (Button) event.widget; Category curCategory = (Category) curButton.getData("Category"); List<DownloadManager> dms = curCategory.getDownloadManagers(globalManager.getDownloadManagers()); long ttlActive = 0; long ttlSize = 0; long ttlRSpeed = 0; long ttlSSpeed = 0; int count = 0; for (DownloadManager dm : dms) { if (!isInCategory(dm, currentCategory)) continue; count++; if (dm.getState() == DownloadManager.STATE_DOWNLOADING || dm.getState() == DownloadManager.STATE_SEEDING){ ttlActive++; } ttlSize += dm.getSize(); ttlRSpeed += dm.getStats().getDataReceiveRate(); ttlSSpeed += dm.getStats().getDataSendRate(); } String up_details = ""; String down_details = ""; if (category.getType() != Category.TYPE_ALL) { String up_str = MessageText.getString("GeneralView.label.maxuploadspeed"); String down_str = MessageText.getString("GeneralView.label.maxdownloadspeed"); String unlimited_str = MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited"); int up_speed = category.getUploadSpeed(); int down_speed = category.getDownloadSpeed(); up_details = up_str + ": " + (up_speed == 0 ? unlimited_str : DisplayFormatters.formatByteCountToKiBEtc(up_speed)); down_details = down_str + ": " + (down_speed == 0 ? unlimited_str : DisplayFormatters.formatByteCountToKiBEtc(down_speed)); } if (count == 0) { curButton.setToolTipText(down_details + "\n" + up_details + "\nTotal: 0"); return; } curButton.setToolTipText((up_details.length() == 0 ? "" : (down_details + "\n" + up_details + "\n")) + "Total: " + count + "\n" + "Downloading/Seeding: " + ttlActive + "\n" + "\n" + "Total Speed: " + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlRSpeed) + " / " + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlSSpeed) + "\n" + "Average Speed: " + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlRSpeed / (ttlActive==0?1:ttlActive)) + " / " + DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlSSpeed / (ttlActive==0?1:ttlActive)) + "\n" + "Size: " + DisplayFormatters.formatByteCountToKiBEtc(ttlSize)); } }); final DropTarget tabDropTarget = new DropTarget(catButton, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; tabDropTarget.setTransfer(types); tabDropTarget.addDropListener(new DropTargetAdapter() { public void dragOver(DropTargetEvent e) { //System.out.println("dragging over: " + drag_drop_line_start); if (drag_drop_line_start >= 0) { e.detail = DND.DROP_MOVE; } else { e.detail = DND.DROP_NONE; } } public void drop(DropTargetEvent e) { e.detail = DND.DROP_NONE; //System.out.println("DragDrop on Button:" + drag_drop_line_start); if (drag_drop_line_start >= 0) { drag_drop_line_start = -1; drag_drop_rows = null; TorrentUtil.assignToCategory(tv.getSelectedDataSources().toArray(), (Category) catButton.getData("Category")); } } }); catButton.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (!tabDropTarget.isDisposed()) { tabDropTarget.dispose(); } } }); final Menu menu = new Menu(catButton.getShell(), SWT.POP_UP); catButton.setMenu(menu); CategoryUIUtils.setupCategoryMenu(menu, category); } cCategories.getParent().layout(true, true); } public boolean isOurDownloadManager(DownloadManager dm) { if (!isInCategory(dm, currentCategory)) { return false; } if ( !isInTag( dm, currentTag )){ return( false ); } boolean bCompleted = dm.isDownloadComplete(bDNDalwaysIncomplete); boolean bOurs = (bCompleted && isSeedingView) || (!bCompleted && !isSeedingView); // System.out.println("ourDM? " + sTableID + "; " + dm.getDisplayName() // + "; Complete=" + bCompleted + ";Ours=" + bOurs + ";bc" // + dm.getStats().getDownloadCompleted(false) + ";" // + dm.getStats().getDownloadCompleted(true)); return bOurs; } public boolean filterCheck(DownloadManager dm, String sLastSearch, boolean bRegexSearch) { boolean bOurs; if (sLastSearch.length() > 0) { try { String comment = dm.getDownloadState().getUserComment(); if ( comment == null ){ comment = ""; } String[][] name_mapping = { { "", dm.getDisplayName() }, { "t:", "", // defer (index = 1)this as costly dm.getTorrent().getAnnounceURL().getHost() }, { "st:", "" + dm.getState() }, { "c:", comment }, { "f:", "", //defer (index = 4) } }; Object o_name = name_mapping[0][1]; String tmpSearch = sLastSearch; for ( int i = 1; i < name_mapping.length; i++ ){ if ( tmpSearch.startsWith(name_mapping[i][0])) { tmpSearch = tmpSearch.substring(name_mapping[i][0].length()); if ( i == 1 ){ List<String> names = new ArrayList<String>(); o_name = names; TOTorrent t = dm.getTorrent(); names.add( t.getAnnounceURL().getHost()); TOTorrentAnnounceURLSet[] sets = t.getAnnounceURLGroup().getAnnounceURLSets(); for ( TOTorrentAnnounceURLSet set: sets ){ URL[] urls = set.getAnnounceURLs(); for ( URL u: urls ){ names.add( u.getHost()); } } }else if ( i == 4 ){ List<String> names = new ArrayList<String>(); o_name = names; DiskManagerFileInfoSet file_set = dm.getDiskManagerFileInfoSet(); DiskManagerFileInfo[] files = file_set.getFiles(); for ( DiskManagerFileInfo f: files ){ File file = f.getFile(true); String name = tmpSearch.contains( File.separator )?file.getAbsolutePath():file.getName(); names.add( name ); } }else{ o_name = name_mapping[i][1]; } } } String s = bRegexSearch ? tmpSearch : "\\Q" + tmpSearch.replaceAll("[|;]", "\\\\E|\\\\Q") + "\\E"; boolean match_result = true; if ( bRegexSearch && s.startsWith( "!" )){ s = s.substring(1); match_result = false; } Pattern pattern = RegExUtil.getCachedPattern( "tv:search", s, Pattern.CASE_INSENSITIVE); if ( o_name instanceof String ){ bOurs = pattern.matcher((String)o_name).find() == match_result; }else{ List<String> names = (List<String>)o_name; // match_result: true -> at least one match; false -> any fail bOurs = !match_result; for ( String name: names ){ if ( pattern.matcher( name ).find()){ bOurs = match_result; break; } } } } catch (Exception e) { // Future: report PatternSyntaxException message to user. bOurs = true; } }else{ bOurs = true; } return bOurs; } // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterSet(java.lang.String) public void filterSet(final String filter) { Utils.execSWTThread(new AERunnable() { public void runSupport() { if (txtFilter != null) { Object x = filterParent.getData( "ViewUtils:ViewTitleExtraInfo" ); if ( x instanceof ViewUtils.ViewTitleExtraInfo ){ boolean enabled = filter.length() > 0; if ( enabled ){ if ( txtFilterUpdateEvent == null ){ txtFilterUpdateEvent = SimpleTimer.addPeriodicEvent( "MTV:updater", 1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { Utils.execSWTThread( new AERunnable() { public void runSupport() { if ( txtFilterUpdateEvent != null ){ if ( tv.isDisposed()){ txtFilterUpdateEvent.cancel(); txtFilterUpdateEvent = null; }else{ viewChanged( tv ); } } } }); } }); } }else{ if ( txtFilterUpdateEvent != null ){ txtFilterUpdateEvent.cancel(); txtFilterUpdateEvent = null; } } ((ViewUtils.ViewTitleExtraInfo)x).setEnabled( tv.getComposite(), isSeedingView, enabled ); } } } }); } public void viewChanged( final TableView<DownloadManager> view ) { Utils.execSWTThread(new AERunnable() { public void runSupport() { swt_viewChanged(view); } }); } private void swt_viewChanged(final TableView<DownloadManager> view) { if ( filterParent != null && !filterParent.isDisposed()){ Object x = filterParent.getData( "ViewUtils:ViewTitleExtraInfo" ); if ( x instanceof ViewUtils.ViewTitleExtraInfo ){ TableRowCore[] rows = view.getRows(); int active = 0; for ( TableRowCore row: rows ){ DownloadManager dm = (DownloadManager)row.getDataSource( true ); int state = dm.getState(); if ( state == DownloadManager.STATE_DOWNLOADING || state == DownloadManager.STATE_SEEDING ){ active++; } } ((ViewUtils.ViewTitleExtraInfo)x).update( tv.getComposite(), isSeedingView, rows.length, active ); } } } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void selected(TableRowCore[] rows) { updateSelectedContent(); refreshTorrentMenu(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#deselected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void deselected(TableRowCore[] rows) { updateSelectedContent(); refreshTorrentMenu(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#focusChanged(com.aelitis.azureus.ui.common.table.TableRowCore) public void focusChanged(TableRowCore focus) { updateSelectedContent(); refreshTorrentMenu(); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseEnter(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseEnter(TableRowCore row) { } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#mouseExit(com.aelitis.azureus.ui.common.table.TableRowCore) public void mouseExit(TableRowCore row) { } private FrequencyLimitedDispatcher refresh_limiter = new FrequencyLimitedDispatcher( new AERunnable() { public void runSupport() { Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { updateSelectedContent(); } }); } }, 250 ); { refresh_limiter.setSingleThreaded(); } private void updateSelectedContentRateLimited() { // we can get a lot of these in succession when lots of rows are selected and we, for example, right-click or stop the torrents etc refresh_limiter.dispatch(); } public void updateSelectedContent() { updateSelectedContent( false ); } public void updateSelectedContent( boolean force ) { if (cTablePanel == null || cTablePanel.isDisposed()) { return; } // if we're not active then ignore this update as we don't want invisible components // updating the toolbar with their invisible selection. Note that unfortunately the // call we get here when activating a view does't yet have focus if ( !isTableFocus()){ if ( !force ){ return; } } Object[] dataSources = tv.getSelectedDataSources(true); List<SelectedContent> listSelected = new ArrayList<SelectedContent>(dataSources.length); for (Object ds : dataSources) { if (ds instanceof DownloadManager) { listSelected.add(new SelectedContent((DownloadManager) ds)); } else if (ds instanceof DiskManagerFileInfo) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds; listSelected.add(new SelectedContent(fileInfo.getDownloadManager(), fileInfo.getIndex())); } } SelectedContent[] content = listSelected.toArray(new SelectedContent[0]); SelectedContentManager.changeCurrentlySelectedContent(tv.getTableID(), content, tv); } private void refreshTorrentMenu() { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null && uiFunctions instanceof UIFunctionsSWT) { ((UIFunctionsSWT)uiFunctions).refreshTorrentMenu(); } } public DownloadManager[] getSelectedDownloads() { Object[] data_sources = tv.getSelectedDataSources().toArray(); List<DownloadManager> list = new ArrayList<DownloadManager>(); for (Object ds : data_sources) { if (ds instanceof DownloadManager) { list.add((DownloadManager) ds); } } return list.toArray(new DownloadManager[0]); } // @see com.aelitis.azureus.ui.common.table.TableSelectionListener#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[]) public void defaultSelected(TableRowCore[] rows, int keyMask) { if (defaultSelectedListener != null) { defaultSelectedListener.defaultSelected(rows, keyMask); return; } showSelectedDetails(); } private void showSelectedDetails() { Object[] dm_sources = tv.getSelectedDataSources().toArray(); UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); for (int i = 0; i < dm_sources.length; i++) { if (!(dm_sources[i] instanceof DownloadManager)) { continue; } if (uiFunctions != null) { uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm_sources[i]); } } } public void overrideDefaultSelected(TableSelectionListener defaultSelectedListener) { this.defaultSelectedListener = defaultSelectedListener; } /* SubMenu for column specific tasks. */ // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener#addThisColumnSubMenu(java.lang.String, org.eclipse.swt.widgets.Menu) public void addThisColumnSubMenu(String sColumnName, Menu menuThisColumn) { if (sColumnName.equals("health")) { MenuItem item = new MenuItem(menuThisColumn, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.health"); Utils.setMenuItemImage(item, "st_explain"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { HealthHelpWindow.show(Display.getDefault()); } }); }else if (sColumnName.equals("trackername")) { MenuItem item = new MenuItem(menuThisColumn, SWT.PUSH); Messages.setLanguageText(item, "MyTorrentsView.menu.trackername.editprefs"); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "trackername.prefs.title", "trackername.prefs.message"); entryWindow.setPreenteredText( COConfigurationManager.getStringParameter( "mtv.trackername.pref.hosts", "" ), true ); entryWindow.selectPreenteredText( false ); entryWindow.prompt(); if (entryWindow.hasSubmittedInput()) { String text = entryWindow.getSubmittedInput(); COConfigurationManager.setParameter( "mtv.trackername.pref.hosts", text.trim()); } } }); }else if (sColumnName.equals("eta") || sColumnName.equals("smootheta")) { final MenuItem item = new MenuItem(menuThisColumn, SWT.CHECK ); Messages.setLanguageText(item, "MyTorrentsView.menu.eta.abs"); item.setSelection( eta_absolute ); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { eta_absolute = item.getSelection(); tv.columnInvalidate("eta"); tv.refreshTable(false); COConfigurationManager.setParameter( "mtv.eta.show_absolute", eta_absolute ); } }); }else if ( sColumnName.equals( "ProgressETA" )) { final MenuItem item = new MenuItem(menuThisColumn, SWT.CHECK ); Messages.setLanguageText(item, "MyTorrentsView.menu.eta.abs"); item.setSelection( progress_eta_absolute ); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { progress_eta_absolute = item.getSelection(); tv.columnInvalidate("ProgressETA"); tv.refreshTable(false); COConfigurationManager.setParameter( "mtv.progress_eta.show_absolute", progress_eta_absolute ); } }); } } // @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener#fillMenu(java.lang.String, org.eclipse.swt.widgets.Menu) public void fillMenu(String sColumnName, final Menu menu) { Object[] dataSources = tv.getSelectedDataSources(true); DownloadManager[] dms = getSelectedDownloads(); if (dms.length == 0 && dataSources.length > 0) { List<DiskManagerFileInfo> listFileInfos = new ArrayList<DiskManagerFileInfo>(); DownloadManager firstFileDM = null; for (Object ds : dataSources) { if (ds instanceof DiskManagerFileInfo) { DiskManagerFileInfo info = (DiskManagerFileInfo) ds; // for now, FilesViewMenuUtil.fillmenu can only handle one DM if (firstFileDM != null && !firstFileDM.equals(info.getDownloadManager())) { break; } firstFileDM = info.getDownloadManager(); listFileInfos.add(info); } } if (listFileInfos.size() > 0) { FilesViewMenuUtil.fillMenu(tv, menu, firstFileDM, listFileInfos.toArray(new DiskManagerFileInfo[0])); return; } } boolean hasSelection = (dms.length > 0); if (hasSelection) { TorrentUtil.fillTorrentMenu(menu, dms, azureus_core, cTablePanel, true, (isSeedingView) ? 2 : 1, tv); // --- new MenuItem(menu, SWT.SEPARATOR); } } private void createDragDrop() { try { Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; if (dragSource != null && !dragSource.isDisposed()) { dragSource.dispose(); } if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } dragSource = tv.createDragSource(DND.DROP_MOVE | DND.DROP_COPY); if (dragSource != null) { dragSource.setTransfer(types); dragSource.addDragListener(new DragSourceAdapter() { private String eventData; public void dragStart(DragSourceEvent event) { TableRowCore[] rows = tv.getSelectedRows(); if (rows.length != 0) { event.doit = true; //System.out.println("DragStart"); drag_drop_line_start = rows[0].getIndex(); drag_drop_rows = rows; } else { event.doit = false; drag_drop_line_start = -1; drag_drop_rows = null; } // Build eventData here because on OSX, selection gets cleared // by the time dragSetData occurs boolean onlyDMs = true; StringBuffer sb = new StringBuffer(); Object[] selectedDataSources = tv.getSelectedDataSources(true); for (Object ds : selectedDataSources) { if (ds instanceof DownloadManager) { DownloadManager dm = (DownloadManager) ds; TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { sb.append(torrent.getHashWrapper().toBase32String()); sb.append('\n'); } catch (TOTorrentException e) { } } } else if (ds instanceof DiskManagerFileInfo) { DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds; DownloadManager dm = fileInfo.getDownloadManager(); TOTorrent torrent = dm.getTorrent(); if (torrent != null) { try { sb.append(torrent.getHashWrapper().toBase32String()); sb.append(';'); sb.append(fileInfo.getIndex()); sb.append('\n'); onlyDMs = false; } catch (TOTorrentException e) { } } } } eventData = (onlyDMs ? "DownloadManager\n" : "DiskManagerFileInfo\n") + sb.toString(); } public void dragSetData(DragSourceEvent event) { // System.out.println("DragSetData"); event.data = eventData; } }); } dropTarget = tv.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); if (dropTarget != null) { dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(), URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetAdapter() { Point enterPoint = null; public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } public void dragEnter(DropTargetEvent event) { // no event.data on dragOver, use drag_drop_line_start to determine // if ours if (drag_drop_line_start < 0) { if (event.detail != DND.DROP_COPY) { if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; } } else if (TextTransfer.getInstance().isSupportedType( event.currentDataType)) { event.detail = tv.getTableRowWithCursor() == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL; enterPoint = new Point(event.x, event.y); } } // @see org.eclipse.swt.dnd.DropTargetAdapter#dragLeave(org.eclipse.swt.dnd.DropTargetEvent) public void dragLeave(DropTargetEvent event) { super.dragLeave(event); tv.getComposite().redraw(); } public void dragOver(DropTargetEvent event) { if (drag_drop_line_start >= 0) { if (drag_drop_rows.length > 0 && !(drag_drop_rows[0].getDataSource(true) instanceof DownloadManager)) { event.detail = DND.DROP_NONE; return; } TableRowCore row = tv.getTableRowWithCursor(); if (row instanceof TableRowPainted) { Rectangle bounds = ((TableRowPainted) row).getBounds(); tv.getComposite().redraw(); tv.getComposite().update(); GC gc = new GC(tv.getComposite()); gc.setLineWidth(2); gc.drawLine(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y); gc.dispose(); } event.detail = row == null ? DND.DROP_NONE : DND.DROP_MOVE; event.feedback = DND.FEEDBACK_SCROLL | ((enterPoint != null && enterPoint.y > event.y) ? DND.FEEDBACK_INSERT_BEFORE : DND.FEEDBACK_INSERT_AFTER); } } public void drop(DropTargetEvent event) { if (!(event.data instanceof String)) { TorrentOpener.openDroppedTorrents(event, true); return; } String data = (String) event.data; if (data.startsWith("DiskManagerFileInfo\n")) { return; } if (!data.startsWith("DownloadManager\n")) { TorrentOpener.openDroppedTorrents(event, true); return; } event.detail = DND.DROP_NONE; // Torrent file from shell dropped if (drag_drop_line_start >= 0) { // event.data == null event.detail = DND.DROP_NONE; TableRowCore row = tv.getRow(event); if (row == null) return; if (row.getParentRowCore() != null) { row = row.getParentRowCore(); } int drag_drop_line_end = row.getIndex(); if (drag_drop_line_end != drag_drop_line_start) { DownloadManager dm = (DownloadManager) row.getDataSource(true); moveRowsTo(drag_drop_rows, dm.getPosition()); event.detail = DND.DROP_MOVE; } drag_drop_line_start = -1; drag_drop_rows = null; } } }); } } catch (Throwable t) { Logger.log(new LogEvent(LOGID, "failed to init drag-n-drop", t)); } } private void moveRowsTo(TableRowCore[] rows, int iNewPos) { if (rows == null || rows.length == 0) { return; } TableColumnCore sortColumn = tv.getSortColumn(); boolean isSortAscending = sortColumn == null ? true : sortColumn.isSortAscending(); for (int i = 0; i < rows.length; i++) { TableRowCore row = rows[i]; Object ds = row.getDataSource(true); if (!(ds instanceof DownloadManager)) { continue; } DownloadManager dm = (DownloadManager) ds; int iOldPos = dm.getPosition(); globalManager.moveTo(dm, iNewPos); if (isSortAscending) { if (iOldPos > iNewPos) iNewPos++; } else { if (iOldPos < iNewPos) iNewPos--; } } boolean bForceSort = sortColumn == null ? false : sortColumn.getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } // @see com.aelitis.azureus.ui.common.table.TableRefreshListener#tableRefresh() public void tableRefresh() { if (tv.isDisposed()) return; refreshTorrentMenu(); } // @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) public void keyPressed(KeyEvent e) { int key = e.character; if (key <= 26 && key > 0) key += 'a' - 1; if (e.stateMask == (SWT.CTRL | SWT.SHIFT)) { // CTRL+SHIFT+S stop all Torrents if (key == 's') { ManagerUtils.asyncStopAll(); e.doit = false; return; } // Can't capture Ctrl-PGUP/DOWN for moving up/down in chunks // (because those keys move through tabs), so use shift-ctrl-up/down if (e.keyCode == SWT.ARROW_DOWN) { moveSelectedTorrents(10); e.doit = false; return; } if (e.keyCode == SWT.ARROW_UP) { moveSelectedTorrents(-10); e.doit = false; return; } } if (e.stateMask == SWT.MOD1) { switch (key) { case 'a': // CTRL+A select all Torrents if (e.widget != txtFilter) { tv.selectAll(); e.doit = false; } break; case 'c': // CTRL+C if (e.widget != txtFilter) { tv.clipboardSelected(); e.doit = false; } break; case 'i': // CTRL+I Info/Details showSelectedDetails(); e.doit = false; break; } if (!e.doit) return; } if (e.stateMask == SWT.CTRL) { switch (e.keyCode) { case SWT.ARROW_UP: moveSelectedTorrentsUp(); e.doit = false; break; case SWT.ARROW_DOWN: moveSelectedTorrentsDown(); e.doit = false; break; case SWT.HOME: moveSelectedTorrentsTop(); e.doit = false; break; case SWT.END: moveSelectedTorrentsEnd(); e.doit = false; break; } if (!e.doit) return; switch (key) { case 'r': // CTRL+R resume/start selected Torrents TorrentUtil.resumeTorrents(tv.getSelectedDataSources().toArray()); e.doit = false; break; case 's': // CTRL+S stop selected Torrents Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { TorrentUtil.stopDataSources(tv.getSelectedDataSources().toArray()); } }); e.doit = false; break; } if (!e.doit) return; } if (e.keyCode == SWT.F2 && (e.stateMask & SWT.MODIFIER_MASK) == 0) { FilesViewMenuUtil.rename(tv, null,tv.getSelectedDataSources(true), true, false); e.doit = false; return; } // DEL remove selected Torrents if (e.stateMask == 0 && e.keyCode == SWT.DEL && e.widget != txtFilter) { Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { TorrentUtil.removeDataSources(tv.getSelectedDataSources().toArray()); } }); e.doit = false; return; } if (e.keyCode != SWT.BS) { if ((e.stateMask & (~SWT.SHIFT)) != 0 || e.character < 32) return; } } public void keyReleased(KeyEvent e) { // ignore } private void moveSelectedTorrentsDown() { // Don't use runForSelectDataSources to ensure the order we want DownloadManager[] dms = getSelectedDownloads(); Arrays.sort(dms, new Comparator<DownloadManager>() { public int compare(DownloadManager a, DownloadManager b) { return a.getPosition() - b.getPosition(); } }); for (int i = dms.length - 1; i >= 0; i--) { DownloadManager dm = dms[i]; if (dm.getGlobalManager().isMoveableDown(dm)) { dm.getGlobalManager().moveDown(dm); } } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrentsUp() { // Don't use runForSelectDataSources to ensure the order we want DownloadManager[] dms = getSelectedDownloads(); Arrays.sort(dms, new Comparator<DownloadManager>() { public int compare(DownloadManager a, DownloadManager b) { return a.getPosition() - b.getPosition(); } }); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; if (dm.getGlobalManager().isMoveableUp(dm)) { dm.getGlobalManager().moveUp(dm); } } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrents(int by) { // Don't use runForSelectDataSources to ensure the order we want DownloadManager[] dms = getSelectedDownloads(); if (dms.length <= 0) return; int[] newPositions = new int[dms.length]; if (by < 0) { Arrays.sort(dms, new Comparator<DownloadManager>() { public int compare(DownloadManager a, DownloadManager b) { return a.getPosition() - b.getPosition(); } }); } else { Arrays.sort(dms, new Comparator<DownloadManager>() { public int compare(DownloadManager a, DownloadManager b) { return b.getPosition() - a.getPosition(); } }); } int count = globalManager.downloadManagerCount(isSeedingView); for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; int pos = dm.getPosition() + by; if (pos < i + 1) pos = i + 1; else if (pos > count - i) pos = count - i; newPositions[i] = pos; } for (int i = 0; i < dms.length; i++) { DownloadManager dm = dms[i]; globalManager.moveTo(dm, newPositions[i]); } boolean bForceSort = tv.getSortColumn().getName().equals("#"); tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } private void moveSelectedTorrentsTop() { moveSelectedTorrentsTopOrEnd(true); } private void moveSelectedTorrentsEnd() { moveSelectedTorrentsTopOrEnd(false); } private void moveSelectedTorrentsTopOrEnd(boolean moveToTop) { DownloadManager[] dms = getSelectedDownloads(); if (dms.length == 0) return; if(moveToTop) globalManager.moveTop(dms); else globalManager.moveEnd(dms); boolean bForceSort = tv.getSortColumn().getName().equals("#"); if (bForceSort) { tv.columnInvalidate("#"); tv.refreshTable(bForceSort); } } /** * @param parameterName the name of the parameter that has changed * @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String) */ public void parameterChanged(String parameterName) { if (parameterName == null || parameterName.equals("DND Always In Incomplete")) { bDNDalwaysIncomplete = COConfigurationManager.getBooleanParameter("DND Always In Incomplete"); } } private UISWTViewCore getActiveView() { TableViewSWT_TabsCommon tabsCommon = tv.getTabsCommon(); if (tabsCommon != null) { return tabsCommon.getActiveSubView(); } return null; } public void refreshToolBarItems(Map<String, Long> list) { super.refreshToolBarItems(list); ISelectedContent[] datasource = SelectedContentManager.getCurrentlySelectedContent(); boolean hasMultiple = datasource.length > 1; // Most subviews can only handle one datasource. I'm lazy, so instead of // fixing each view up, disable toolbar handling for them when we have // multiple selection if (!hasMultiple) { UISWTViewCore active_view = getActiveView(); if (active_view != null) { UIPluginViewToolBarListener l = active_view.getToolBarListener(); if (l != null) { l.refreshToolBarItems(list); // don't return here, we want to merge in any potential operations // from the selected content calculation below } } } Map<String, Long> states = TorrentUtil.calculateToolbarStates(datasource, tv.getTableID()); list.putAll(states); } public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource) { boolean hasMultiple = datasource instanceof Object[] && ((Object[])datasource).length > 1; // Most subviews can only handle one datasource. I'm lazy, so instead of // fixing each view up, disable toolbar handling for them when we have // multiple selection if (!hasMultiple) { UISWTViewCore active_view = getActiveView(); if (active_view != null) { UIPluginViewToolBarListener l = active_view.getToolBarListener(); if (l != null && l.toolBarItemActivated(item, activationType, datasource)) { return true; } } } String itemKey = item.getID(); if (activationType == UIToolBarActivationListener.ACTIVATIONTYPE_HELD) { if(itemKey.equals("up")) { moveSelectedTorrentsTop(); return true; } if(itemKey.equals("down")){ moveSelectedTorrentsEnd(); return true; } return false; } if (activationType != UIToolBarActivationListener.ACTIVATIONTYPE_NORMAL) { return false; } if(itemKey.equals("top")) { moveSelectedTorrentsTop(); return true; } if(itemKey.equals("bottom")){ moveSelectedTorrentsEnd(); return true; } if(itemKey.equals("up")) { moveSelectedTorrentsUp(); return true; } if(itemKey.equals("down")){ moveSelectedTorrentsDown(); return true; } if(itemKey.equals("run")){ TorrentUtil.runDataSources(tv.getSelectedDataSources().toArray()); return true; } if(itemKey.equals("start")){ TorrentUtil.queueDataSources(tv.getSelectedDataSources().toArray(), true); return true; } if(itemKey.equals("stop")){ TorrentUtil.stopDataSources(tv.getSelectedDataSources().toArray()); return true; } if (itemKey.equals("startstop")) { TorrentUtil.stopOrStartDataSources(tv.getSelectedDataSources().toArray()); return true; } if(itemKey.equals("remove")){ TorrentUtil.removeDataSources(tv.getSelectedDataSources().toArray()); return true; } return super.toolBarItemActivated(item, activationType, datasource); } // categorymanagerlistener Functions public void downloadManagerAdded(Category category, final DownloadManager manager) { if (isOurDownloadManager(manager)) { tv.addDataSource(manager); } } public void downloadManagerRemoved(Category category, DownloadManager removed) { tv.removeDataSource(removed); } // DownloadManagerListener Functions public void stateChanged(DownloadManager manager, int state) { final TableRowCore row = tv.getRow(manager); if (row != null) { Utils.getOffOfSWTThread(new AERunnable() { public void runSupport() { row.refresh(true); if (row.isSelected()) { updateSelectedContentRateLimited(); } } }); } } // DownloadManagerListener public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { if (isOurDownloadManager(download)) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { updateSelectedContent(); } }); } } // DownloadManagerListener public void filePriorityChanged(DownloadManager download, DiskManagerFileInfo file) { } // DownloadManagerListener public void completionChanged(final DownloadManager manager, boolean bCompleted) { // manager has moved lists if (isOurDownloadManager(manager)) { // only make the download visible if it satisfies the category selection if (currentCategory == null || currentCategory.getType() == Category.TYPE_ALL) { tv.addDataSource(manager); } else { int catType = currentCategory.getType(); Category manager_category = manager.getDownloadState().getCategory(); if (manager_category == null) { if (catType == Category.TYPE_UNCATEGORIZED) { tv.addDataSource(manager); } } else { if (currentCategory.getName().equals(manager_category.getName())) tv.addDataSource(manager); } } } else if ((isSeedingView && !bCompleted) || (!isSeedingView && bCompleted)) { tv.removeDataSource(manager); } } // DownloadManagerListener public void downloadComplete(DownloadManager manager) { } /** * Rebuild the table based on the category activated * * @param category */ private void activateCategory(Category category) { if (category != currentCategory) { if (currentCategory != null) currentCategory.removeCategoryListener(this); if (category != null) category.addCategoryListener(this); currentCategory = category; } tv.processDataSourceQueue(); Object[] managers = globalManager.getDownloadManagers().toArray(); List<DownloadManager> listRemoves = new ArrayList<DownloadManager>(); List<DownloadManager> listAdds = new ArrayList<DownloadManager>(); for (int i = 0; i < managers.length; i++) { DownloadManager dm = (DownloadManager) managers[i]; boolean bHave = tv.isUnfilteredDataSourceAdded(dm); if (!isOurDownloadManager(dm)) { if (bHave) { listRemoves.add(dm); } } else { if (!bHave) { listAdds.add(dm); } } } tv.removeDataSources(listRemoves.toArray(new DownloadManager[0])); tv.addDataSources(listAdds.toArray(new DownloadManager[0])); tv.processDataSourceQueue(); //tv.refreshTable(false); } public boolean isInCurrentCategory(DownloadManager manager) { return isInCategory(manager, currentCategory); } private boolean isInCategory(DownloadManager manager, Category category) { if (category == null) { return true; } int type = category.getType(); if (type == Category.TYPE_ALL) { return true; } Category dmCategory = manager.getDownloadState().getCategory(); if (dmCategory == null) { return type == Category.TYPE_UNCATEGORIZED; } return category.equals(dmCategory); } // CategoryManagerListener Functions public void categoryAdded(Category category) { createTabs(); } public void categoryRemoved(Category category) { if (currentCategory == category) { activateCategory(CategoryManager.getCategory(Category.TYPE_ALL)); } else { // always activate as deletion of this one might have // affected the current view activateCategory(currentCategory); } createTabs(); } public void categoryChanged(Category category) { } // tags private void activateTag( Tag tag) { if ( tag != currentTag ){ if ( currentTag != null ){ currentTag.removeTagListener(this); } if ( tag != null ){ tag.addTagListener(this,false); } currentTag = tag; } tv.processDataSourceQueue(); Object[] managers = globalManager.getDownloadManagers().toArray(); List<DownloadManager> listRemoves = new ArrayList<DownloadManager>(); List<DownloadManager> listAdds = new ArrayList<DownloadManager>(); for (int i = 0; i < managers.length; i++) { DownloadManager dm = (DownloadManager) managers[i]; boolean bHave = tv.isUnfilteredDataSourceAdded(dm); if (!isOurDownloadManager(dm)) { if (bHave) { listRemoves.add(dm); } } else { if (!bHave) { listAdds.add(dm); } } } tv.removeDataSources(listRemoves.toArray(new DownloadManager[0])); tv.addDataSources(listAdds.toArray(new DownloadManager[0])); tv.processDataSourceQueue(); //tv.refreshTable(false); } private boolean isInTag( DownloadManager manager, Tag tag ) { if ( tag == null ){ return true; } return( tag.hasTaggable( manager )); } public boolean isInCurrentTag( DownloadManager manager ) { return( isInTag(manager, currentTag )); } public void taggableAdded( Tag tag, Taggable tagged ) { DownloadManager manager = (DownloadManager)tagged; if ( isOurDownloadManager(manager)){ tv.addDataSource( manager ); } } public void taggableSync( Tag tag ) { if ( tag.getTagName( true ).equals( "rrr" )){ System.out.println( "a" ); } Set<DownloadManager> dms_in_tag = new HashSet<DownloadManager>(); for ( Taggable t: tag.getTagged()){ DownloadManager manager = (DownloadManager)t; if ( isOurDownloadManager( manager )){ dms_in_tag.add( manager ); } } if ( tv.getRowCount() != dms_in_tag.size()){ Set<DownloadManager> dms_in_table = new HashSet<DownloadManager>(tv.getDataSources()); for ( DownloadManager dm: dms_in_table ){ if ( !dms_in_tag.contains( dm )){ tv.removeDataSource( dm ); } } for ( DownloadManager dm: dms_in_tag ){ if ( !dms_in_table.contains( dm )){ tv.addDataSource( dm ); } } } } public void taggableRemoved( Tag tag, Taggable tagged ) { DownloadManager manager = (DownloadManager)tagged; tv.removeDataSource( manager ); } // globalmanagerlistener Functions public void downloadManagerAdded( DownloadManager dm ) { dm.addListener( this ); downloadManagerAdded(null, dm); } public void downloadManagerRemoved( DownloadManager dm ) { dm.removeListener( this ); DownloadBar.close(dm); downloadManagerRemoved(null, dm); } public void destroyInitiated() { } public void destroyed() { } public void seedingStatusChanged( boolean seeding_only_mode, boolean b ){} // End of globalmanagerlistener Functions public void updateLanguage() { super.updateLanguage(); getComposite().layout(true, true); } public boolean isTableFocus() { return viewActive; //return tv.isTableFocus(); } public Image obfusticatedImage(final Image image) { return tv.obfusticatedImage(image); } /** * Creates and return an <code>TableViewSWT</code> * Subclasses my override to return a different TableViewSWT if needed * @param basicItems * @return */ private static boolean registeredCoreSubViews = false; protected TableViewSWT<DownloadManager> createTableView( Class<?> forDataSourceType, String tableID, TableColumnCore[] basicItems ) { int tableExtraStyle = COConfigurationManager.getIntParameter("MyTorrentsView.table.style"); TableViewSWT<DownloadManager> table = TableViewFactory.createTableViewSWT(forDataSourceType, tableID, getPropertiesPrefix(), basicItems, "#", tableExtraStyle | SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.CASCADE); // config?? boolean enable_tab_views = !Utils.isAZ2UI() && supportsTabs && COConfigurationManager.getBooleanParameter( "Library.ShowTabsInTorrentView" ); List<String> restrictTo = new ArrayList<String>(); restrictTo.addAll(Arrays.asList( GeneralView.MSGID_PREFIX, TrackerView.MSGID_PREFIX, PeersView.MSGID_PREFIX, PeersGraphicView.MSGID_PREFIX, PiecesView.MSGID_PREFIX, DownloadActivityView.MSGID_PREFIX, PieceInfoView.MSGID_PREFIX, FilesView.MSGID_PREFIX )); // discoveries sub-tab hack PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager(); PluginInterface pi = pm.getPluginInterfaceByID("aercm", true); if (pi != null) { String pluginInfo = pi.getPluginconfig().getPluginStringParameter( "plugin.info", ""); if (pluginInfo.equals("e")) { restrictTo.add("rcm.subview.torrentdetails.name"); } } if ( Logger.isEnabled()){ restrictTo.add( LoggerView.MSGID_PREFIX ); } table.setEnableTabViews(enable_tab_views, false, restrictTo.toArray(new String[0])); UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT(); if (uiFunctions != null) { UISWTInstance pluginUI = uiFunctions.getUISWTInstance(); registerPluginViews( pluginUI ); } return( table ); } public static void registerPluginViews( UISWTInstance pluginUI ) { if ( pluginUI != null && !registeredCoreSubViews ){ String[] views_with_tabs = { TableManager.TABLE_MYTORRENTS_ALL_BIG, // all simple views TableManager.TABLE_MYTORRENTS_INCOMPLETE, // downloading view TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG, // downloading view TableManager.TABLE_MYTORRENTS_COMPLETE, // bottom part of split views (hack of course) }; for ( String id: views_with_tabs ){ pluginUI.addView( id, GeneralView.MSGID_PREFIX, GeneralView.class, null); pluginUI.addView( id, TrackerView.MSGID_PREFIX, TrackerView.class, null); pluginUI.addView( id, PeersView.MSGID_PREFIX, PeersView.class, null); pluginUI.addView( id, PeersGraphicView.MSGID_PREFIX, PeersGraphicView.class, null); pluginUI.addView( id, PiecesView.MSGID_PREFIX, PiecesView.class, null); pluginUI.addView( id, PieceInfoView.MSGID_PREFIX, PieceInfoView.class, null); pluginUI.addView( id, DownloadActivityView.MSGID_PREFIX, DownloadActivityView.class, null); pluginUI.addView( id, FilesView.MSGID_PREFIX, FilesView.class, null); pluginUI.addView( id, TorrentInfoView.MSGID_PREFIX, TorrentInfoView.class, null); pluginUI.addView( id, TorrentOptionsView.MSGID_PREFIX, TorrentOptionsView.class, null); if (Logger.isEnabled()) { pluginUI.addView( id, LoggerView.MSGID_PREFIX, LoggerView.class, null); } } registeredCoreSubViews = true; } } /** * Returns the default row height for the table * Subclasses my override to return a different height if needed; a height of -1 means use default * @return */ protected int getRowDefaultHeight(){ return -1; } // @see org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener#rowRefresh(org.gudy.azureus2.plugins.ui.tables.TableRow) public void rowRefresh(TableRow row) { if (!(row instanceof TableRowCore)) { return; } TableRowCore rowCore = (TableRowCore) row; Object ds = rowCore.getDataSource(true); if (!(ds instanceof DownloadManager)) { return; } DownloadManager dm = (DownloadManager) ds; if (rowCore.getSubItemCount() == 0 && dm.getTorrent() != null && !dm.getTorrent().isSimpleTorrent() && rowCore.isVisible() && dm.getNumFileInfos() > 0) { DiskManagerFileInfoSet fileInfos = dm.getDiskManagerFileInfoSet(); if (fileInfos != null) { DiskManagerFileInfo[] files = fileInfos.getFiles(); boolean copied = false; int pos = 0; for (int i = 0; i < files.length; i++) { DiskManagerFileInfo fileInfo = files[i]; if (fileInfo.isSkipped() && (fileInfo.getStorageType() == DiskManagerFileInfo.ST_COMPACT || fileInfo.getStorageType() == DiskManagerFileInfo.ST_REORDER_COMPACT)) { continue; } if (pos != i) { if ( !copied ){ // we *MUSTN'T* modify the returned array!!!! DiskManagerFileInfo[] oldFiles = files; files = new DiskManagerFileInfo[files.length]; System.arraycopy(oldFiles, 0, files, 0, files.length); copied = true; } files[pos] = files[i]; } pos++; } if (pos != files.length) { DiskManagerFileInfo[] oldFiles = files; files = new DiskManagerFileInfo[pos]; System.arraycopy(oldFiles, 0, files, 0, pos); } rowCore.setSubItems(files); } } } public boolean eventOccurred(UISWTViewEvent event) { boolean b = super.eventOccurred(event); if (event.getType() == UISWTViewEvent.TYPE_FOCUSGAINED) { if (rebuildListOnFocusGain) { List<?> dms = globalManager.getDownloadManagers(); List<DownloadManager> listAdds = new ArrayList(); List<DownloadManager> listRemoves = new ArrayList(); for (Iterator<?> iter = dms.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if (!isOurDownloadManager(dm)) { listRemoves.add(dm); } else { listAdds.add(dm); } } tv.removeDataSources(listRemoves.toArray(new DownloadManager[0])); tv.addDataSources(listAdds.toArray(new DownloadManager[0])); } updateSelectedContent(true); } else if (event.getType() == UISWTViewEvent.TYPE_FOCUSLOST) { } return b; } public void setRebuildListOnFocusGain(boolean rebuildListOnFocusGain) { this.rebuildListOnFocusGain = rebuildListOnFocusGain; } public void rowAdded(TableRowCore row) { if (row.getParentRowCore() == null) { DownloadManager dm = (DownloadManager) row.getDataSource(true); if ( dm.getDownloadState().getBooleanAttribute( DownloadManagerState.AT_FILES_EXPANDED )){ row.setExpanded(true); } } //if (getRowDefaultHeight() > 0 && row.getParentRowCore() != null) { // row.setHeight(20); //} } public void rowRemoved(TableRowCore row) { } public void rowExpanded( TableRowCore row ) { if ( row.getParentRowCore() == null ){ DownloadManager dm = (DownloadManager) row.getDataSource(true); dm.getDownloadState().setBooleanAttribute( DownloadManagerState.AT_FILES_EXPANDED, true ); } } public void rowCollapsed( TableRowCore row ) { if ( row.getParentRowCore() == null ){ DownloadManager dm = (DownloadManager) row.getDataSource(true); dm.getDownloadState().setBooleanAttribute( DownloadManagerState.AT_FILES_EXPANDED, false ); } } }