Index: AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 631)
@@ -1,2 +1,2 @@
 appname=AE Installer 2
-appversion=0.89
+appversion=0.90
Index: AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java	(revision 631)
@@ -216,4 +216,8 @@
 	}
 
+	private String getSanitizedPathName() {
+		return name.replaceAll("[^a-zA-Z0-9_.-]", "_");
+	}
+
 	/**
 	 * @return Path to local mod folder
@@ -233,5 +237,6 @@
 		}
 
-		return new File(Paths.getModsPath(), folderStart);
+		return new File(Paths.getModsPath(), folderStart
+				+ getSanitizedPathName());
 	}
 
@@ -254,4 +259,11 @@
 
 	/**
+	 * @return Is mod installed?
+	 */
+	public boolean isInstalled() {
+		return ModManager.getInstance().isModInstalled(this);
+	}
+
+	/**
 	 * @return Name of mod
 	 */
@@ -376,4 +388,5 @@
 		return exeFile;
 	}
+
 	/**
 	 * @return Icon file of this tool
Index: AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java	(revision 631)
@@ -334,5 +334,5 @@
 	 * @return Is mod installed?
 	 */
-	public boolean isModInstalled(Mod m) {
+	boolean isModInstalled(Mod m) {
 		return currentlyInstalled.contains(m.getPackageNumber());
 	}
Index: AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java	(revision 631)
@@ -8,4 +8,5 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -19,4 +20,5 @@
 import java.util.Vector;
 
+import net.oni2.aeinstaller.AEInstaller2;
 import net.oni2.aeinstaller.backend.Paths;
 import net.oni2.aeinstaller.backend.Settings;
@@ -244,36 +246,8 @@
 		combineBSLFolders(mods, listener);
 
-		if (Settings.getInstance().get("copyintro", false)) {
-			File src = new File(Paths.getVanillaGDF(), "intro.bik");
-			if (src.exists()) {
-				try {
-					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-			}
-		}
-		if (Settings.getInstance().get("copyoutro", true)) {
-			File src = new File(Paths.getVanillaGDF(), "outro.bik");
-			if (src.exists()) {
-				try {
-					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-			}
-		}
+		copyVideos();
 
 		if (unlockLevels.size() > 0) {
-			File dat = new File(Paths.getEditionBasePath(), "persist.dat");
-			if (dat.exists()) {
-				PersistDat save = new PersistDat(dat);
-				HashSet<Integer> currentlyUnlocked = save.getUnlockedLevels();
-				currentlyUnlocked.addAll(unlockLevels);
-				save.setUnlockedLevels(currentlyUnlocked);
-				save.close();
-			} else {
-				// TODO: what if persist.dat does not exist?
-			}
+			unlockLevels(unlockLevels);
 		}
 	}
@@ -445,4 +419,45 @@
 	}
 
+	private static void copyVideos() {
+		if (Settings.getInstance().get("copyintro", false)) {
+			File src = new File(Paths.getVanillaGDF(), "intro.bik");
+			if (src.exists()) {
+				try {
+					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		if (Settings.getInstance().get("copyoutro", true)) {
+			File src = new File(Paths.getVanillaGDF(), "outro.bik");
+			if (src.exists()) {
+				try {
+					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	private static void unlockLevels(HashSet<Integer> unlockLevels) {
+		File dat = new File(Paths.getEditionBasePath(), "persist.dat");
+		if (!dat.exists()) {
+			InputStream is = AEInstaller2.class.getResourceAsStream("/net/oni2/aeinstaller/resources/persist.dat");
+			try {
+				FileUtils.copyInputStreamToFile(is, dat);
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		PersistDat save = new PersistDat(dat);
+		HashSet<Integer> currentlyUnlocked = save.getUnlockedLevels();
+		currentlyUnlocked.addAll(unlockLevels);
+		save.setUnlockedLevels(currentlyUnlocked);
+		save.close();
+	}
+
 	/**
 	 * Initializes the Edition core
Index: AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.java	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.java	(revision 631)
@@ -4,16 +4,11 @@
 import java.awt.Desktop;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.ResourceBundle;
 import java.util.TreeMap;
@@ -27,5 +22,4 @@
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
-import javax.swing.JComponent;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
@@ -35,16 +29,9 @@
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
 import javax.swing.JRadioButton;
 import javax.swing.JSplitPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.RowSorter;
-import javax.swing.SortOrder;
 import javax.swing.SwingUtilities;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
+import javax.swing.ToolTipManager;
 import javax.swing.filechooser.FileFilter;
-import javax.swing.table.TableRowSorter;
 
 import net.oni2.aeinstaller.AEInstaller2;
@@ -68,6 +55,6 @@
 import net.oni2.aeinstaller.gui.downloadwindow.Downloader;
 import net.oni2.aeinstaller.gui.modtable.DownloadSizeListener;
-import net.oni2.aeinstaller.gui.modtable.ModTableFilter;
-import net.oni2.aeinstaller.gui.modtable.ModTableModel;
+import net.oni2.aeinstaller.gui.modtable.ModSelectionListener;
+import net.oni2.aeinstaller.gui.modtable.ModTable;
 import net.oni2.aeinstaller.gui.settings.SettingsDialog;
 import net.oni2.aeinstaller.gui.toolmanager.ToolManager;
@@ -84,5 +71,5 @@
  */
 public class MainWin extends JFrame implements ApplicationListener,
-		DownloadSizeListener {
+		DownloadSizeListener, ModSelectionListener {
 	private static final long serialVersionUID = -4027395051382659650L;
 
@@ -103,7 +90,5 @@
 	private JRadioButton radOnline;
 	private JRadioButton radLocal;
-	private JTable tblMods;
-	private ModTableModel model;
-	private TableRowSorter<ModTableModel> sorter;
+	private ModTable tblMods;
 	private JLabel lblDownloadSizeVal;
 
@@ -136,12 +121,18 @@
 
 		contents.setDividerLocation(400);
+		contents.setResizeWeight(0.4);
 
 		if (Settings.getPlatform() == Platform.MACOS) {
 			mainMenu.setVisible(false);
 		}
+
+		ToolTipManager.sharedInstance().setInitialDelay(250);
 
 		getRootPane().setDefaultButton(btnInstall);
 		lblDownloadSizeVal.setText(SizeFormatter.format(0, 2));
 		radAll.setSelected(true);
+
+		tblMods.addModSelectionListener(this);
+		tblMods.addDownloadSizeListener(this);
 	}
 
@@ -158,93 +149,4 @@
 		}
 		cmbModTypes.setSelectedIndex(0);
-	}
-
-	private void initTable() {
-		tblMods.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-		tblMods.getSelectionModel().addListSelectionListener(
-				new ListSelectionListener() {
-					@Override
-					public void valueChanged(ListSelectionEvent e) {
-						int viewRow = tblMods.getSelectedRow();
-						if (viewRow < 0) {
-							modSelection(null);
-						} else {
-							int modelRow = tblMods
-									.convertRowIndexToModel(viewRow);
-							Mod mod = (Mod) model.getValueAt(modelRow, -1);
-							modSelection(mod);
-						}
-					}
-				});
-		tblMods.addMouseListener(new MouseAdapter() {
-			private void common(MouseEvent e) {
-				int r = tblMods.rowAtPoint(e.getPoint());
-				if (r >= 0 && r < tblMods.getRowCount())
-					tblMods.setRowSelectionInterval(r, r);
-				else
-					tblMods.clearSelection();
-
-				int rowindex = tblMods.getSelectedRow();
-				if (rowindex >= 0) {
-					if (e.isPopupTrigger()
-							&& e.getComponent() instanceof JTable) {
-						int modelRow = tblMods.convertRowIndexToModel(rowindex);
-						final Mod mod = (Mod) model.getValueAt(modelRow, -1);
-
-						if (mod.isLocalAvailable()) {
-							JPopupMenu popup = new JPopupMenu();
-							JMenuItem openModFolder = new JMenuItem(bundle
-									.getString("openModFolder.text"));
-							openModFolder
-									.addActionListener(new ActionListener() {
-										@Override
-										public void actionPerformed(
-												ActionEvent arg0) {
-											try {
-												Desktop.getDesktop().open(
-														mod.getLocalPath());
-											} catch (IOException e) {
-												e.printStackTrace();
-											}
-										}
-									});
-							popup.add(openModFolder);
-							popup.show(e.getComponent(), e.getX(), e.getY());
-						}
-					}
-				}
-			}
-
-			@Override
-			public void mousePressed(MouseEvent e) {
-				common(e);
-			}
-
-			@Override
-			public void mouseReleased(MouseEvent e) {
-				common(e);
-			}
-		});
-		// To get checkbox-cells with background of row
-		((JComponent) tblMods.getDefaultRenderer(Boolean.class))
-				.setOpaque(true);
-
-		model = new ModTableModel();
-		model.addDownloadSizeListener(this);
-
-		tblMods.setModel(model);
-
-		sorter = new TableRowSorter<ModTableModel>(model);
-		tblMods.setRowSorter(sorter);
-
-		sorter.setRowFilter(new ModTableFilter(null, 0));
-
-		List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
-		sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
-		sorter.setSortKeys(sortKeys);
-
-		for (int i = 0; i < model.getColumnCount(); i++) {
-			model.setColumnConstraints(i, tblMods.getColumnModel().getColumn(i));
-		}
 	}
 
@@ -279,5 +181,5 @@
 		}
 		ModManager.getInstance().init();
-		initTable();
+		tblMods.reloadData();
 		initModTypeBox();
 
@@ -430,5 +332,5 @@
 		if (res == JFileChooser.APPROVE_OPTION) {
 			if (fc.getSelectedFile().exists())
-				model.reloadSelection(fc.getSelectedFile());
+				tblMods.reloadSelection(fc.getSelectedFile());
 		}
 	}
@@ -443,5 +345,5 @@
 				f = new File(f.getParentFile(), f.getName() + ".xml");
 			ModManager.getInstance().saveModSelection(f,
-					model.getSelectedMods());
+					tblMods.getSelectedMods());
 		}
 	}
@@ -500,5 +402,5 @@
 	@SuppressWarnings("unused")
 	private void revertSelection() {
-		model.revertSelection();
+		tblMods.revertSelection();
 	}
 
@@ -548,5 +450,5 @@
 		TreeSet<Mod> mods = new TreeSet<Mod>();
 		mods.addAll(ModManager.getInstance().getMandatoryMods());
-		mods.addAll(model.getSelectedMods());
+		mods.addAll(tblMods.getSelectedMods());
 
 		boolean instReady = false;
@@ -644,5 +546,6 @@
 	}
 
-	private void modSelection(Mod m) {
+	@Override
+	public void modSelectionChanged(ModTable source, Mod m) {
 		lblSubmitterVal.setText("");
 		lblCreatorVal.setText("");
@@ -678,5 +581,5 @@
 		if (radLocal.isSelected())
 			downloadState = 2;
-		sorter.setRowFilter(new ModTableFilter(t, downloadState));
+		tblMods.setFilter(t, downloadState);
 	}
 
Index: AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/gui/MainWin.yml	(revision 631)
@@ -56,5 +56,5 @@
             - ButtonGroup: [radAll,radOnline,radLocal]
             - JScrollPane(name=scrollMods, vScrollBar=always, hScrollBar=never):
-                JTable(name=tblMods, visible=false)
+                ModTable(name=tblMods, visible=false)
             - JButton(name=btnRevertSelection, icon=img.undo16, text=btnRevertSelection.text, toolTipText=btnRevertSelection.tooltip, onAction=[revertSelection])
             - JButton(name=btnInstall, icon=img.install, text=btnInstall.text, toolTipText=btnInstall.tooltip, onAction=[install,installDone])
Index: AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModSelectionListener.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModSelectionListener.java	(revision 631)
+++ AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModSelectionListener.java	(revision 631)
@@ -0,0 +1,18 @@
+package net.oni2.aeinstaller.gui.modtable;
+
+import net.oni2.aeinstaller.backend.mods.Mod;
+
+/**
+ * @author Christian Illy
+ */
+public interface ModSelectionListener {
+	/**
+	 * Called on changes to the mod selection
+	 * 
+	 * @param source
+	 *            Source of event
+	 * @param mod
+	 *            New selected mod
+	 */
+	public void modSelectionChanged(ModTable source, Mod mod);
+}
Index: AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTable.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTable.java	(revision 631)
+++ AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTable.java	(revision 631)
@@ -0,0 +1,238 @@
+package net.oni2.aeinstaller.gui.modtable;
+
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.TreeSet;
+
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.RowSorter;
+import javax.swing.SortOrder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableRowSorter;
+
+import net.oni2.aeinstaller.backend.mods.Mod;
+import net.oni2.aeinstaller.backend.mods.Type;
+
+/**
+ * @author Christian Illy
+ */
+public class ModTable extends JTable {
+	private static final long serialVersionUID = 1L;
+
+	private ResourceBundle bundle = ResourceBundle
+			.getBundle("net.oni2.aeinstaller.localization.ModTable");
+
+	private HashSet<ModSelectionListener> modSelListeners = new HashSet<ModSelectionListener>();
+
+	private ModTableModel model;
+	private TableRowSorter<ModTableModel> sorter;
+
+	/**
+	 * Create a new ModTable
+	 */
+	public ModTable() {
+		super();
+
+		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		getSelectionModel().addListSelectionListener(
+				new ListSelectionListener() {
+					@Override
+					public void valueChanged(ListSelectionEvent e) {
+						int viewRow = getSelectedRow();
+						if (viewRow < 0) {
+							notifyModSelectionListeners(null);
+						} else {
+							Mod mod = (Mod) getValueAt(viewRow, -1);
+							notifyModSelectionListeners(mod);
+						}
+					}
+				});
+		addMouseListener(new MouseAdapter() {
+			private void common(MouseEvent e) {
+				int r = rowAtPoint(e.getPoint());
+				if (r >= 0 && r < getRowCount())
+					setRowSelectionInterval(r, r);
+				else
+					clearSelection();
+
+				int rowindex = getSelectedRow();
+				if (rowindex >= 0) {
+					if (e.isPopupTrigger()
+							&& e.getComponent() instanceof JTable) {
+						final Mod mod = (Mod) getValueAt(rowindex, -1);
+
+						if (mod.isLocalAvailable()) {
+							JPopupMenu popup = new JPopupMenu();
+							JMenuItem openModFolder = new JMenuItem(
+									bundle.getString("openModFolder.text"));
+							openModFolder
+									.addActionListener(new ActionListener() {
+										@Override
+										public void actionPerformed(
+												ActionEvent arg0) {
+											try {
+												Desktop.getDesktop().open(
+														mod.getLocalPath());
+											} catch (IOException e) {
+												e.printStackTrace();
+											}
+										}
+									});
+							popup.add(openModFolder);
+							popup.show(e.getComponent(), e.getX(), e.getY());
+						}
+					}
+				}
+			}
+
+			@Override
+			public void mousePressed(MouseEvent e) {
+				common(e);
+			}
+
+			@Override
+			public void mouseReleased(MouseEvent e) {
+				common(e);
+			}
+		});
+		// To get checkbox-cells with background of row
+		((JComponent) getDefaultRenderer(Boolean.class)).setOpaque(true);
+
+		model = new ModTableModel();
+
+		setModel(model);
+
+		sorter = new TableRowSorter<ModTableModel>(model);
+		setRowSorter(sorter);
+
+		setFilter(null, 0);
+
+		List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
+		sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
+		sorter.setSortKeys(sortKeys);
+
+		for (int i = 0; i < model.getColumnCount(); i++) {
+			model.setColumnConstraints(i, getColumnModel().getColumn(i));
+		}
+	}
+
+	@Override
+	public String getToolTipText(MouseEvent e) {
+		int r = rowAtPoint(e.getPoint());
+		int c = columnAtPoint(e.getPoint());
+		if (r >= 0 && r < getRowCount()) {
+			int modelCol = convertColumnIndexToModel(c);
+			if (modelCol == 4) {
+				final Mod mod = (Mod) getValueAt(r, -1);
+
+				String tt = "<html>";
+				tt += String.format("%s: %s<br>",
+						bundle.getString("state.installed"),
+						bundle.getString((mod.isInstalled() ? "yes" : "no")));
+				tt += String.format(
+						"%s: %s<br>",
+						bundle.getString("state.updatable"),
+						bundle.getString((mod.isLocalAvailable()
+								&& mod.isNewerAvailable() ? "yes" : "no")));
+				tt += String.format("%s: %s</html>", bundle
+						.getString("state.downloaded"), bundle.getString((mod
+						.isLocalAvailable() ? "yes" : "no")));
+				return tt;
+			}
+		}
+		return super.getToolTipText(e);
+	}
+
+	/**
+	 * @param listener
+	 *            Listener to add
+	 */
+	public void addModSelectionListener(ModSelectionListener listener) {
+		modSelListeners.add(listener);
+	}
+
+	/**
+	 * @param listener
+	 *            Listener to remove
+	 */
+	public void removeModSelectionListener(ModSelectionListener listener) {
+		modSelListeners.remove(listener);
+	}
+
+	private void notifyModSelectionListeners(Mod m) {
+		for (ModSelectionListener l : modSelListeners) {
+			l.modSelectionChanged(this, m);
+		}
+	}
+
+	/**
+	 * @param listener
+	 *            Listener to add
+	 */
+	public void addDownloadSizeListener(DownloadSizeListener listener) {
+		model.addDownloadSizeListener(listener);
+	}
+
+	/**
+	 * @param listener
+	 *            Listener to remove
+	 */
+	public void removeDownloadSizeListener(DownloadSizeListener listener) {
+		model.removeDownloadSizeListener(listener);
+	}
+
+	/**
+	 * Reload the nodes data after an update to the cache
+	 */
+	public void reloadData() {
+		model.reloadData();
+	}
+
+	/**
+	 * Revert the selection to the mods that are currently installed
+	 */
+	public void revertSelection() {
+		model.revertSelection();
+	}
+
+	/**
+	 * Reload the selection after a config was loaded
+	 * 
+	 * @param config
+	 *            Config to load
+	 */
+	public void reloadSelection(File config) {
+		model.reloadSelection(config);
+	}
+
+	/**
+	 * @return Mods selected for installation
+	 */
+	public TreeSet<Mod> getSelectedMods() {
+		return model.getSelectedMods();
+	}
+
+	/**
+	 * @param type
+	 *            Type of mods to show (null for all)
+	 * @param downloadState
+	 *            Show only: 0 = all, 1 = online, 2 = downloaded
+	 */
+	public void setFilter(Type type, int downloadState) {
+		sorter.setRowFilter(new ModTableFilter(type, downloadState));
+	}
+}
Index: AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTableModel.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTableModel.java	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/gui/modtable/ModTableModel.java	(revision 631)
@@ -21,6 +21,5 @@
 
 	private ResourceBundle bundle = ResourceBundle
-			.getBundle("net.oni2.aeinstaller.localization."
-					+ getClass().getSimpleName());
+			.getBundle("net.oni2.aeinstaller.localization.ModTable");
 
 	private Vector<Mod> items = new Vector<Mod>();
@@ -33,5 +32,4 @@
 	 */
 	public ModTableModel() {
-		reloadData();
 	}
 
@@ -50,4 +48,11 @@
 			case 3:
 				return mod.getCreator();
+			case 4:
+				String res = "";
+				res += (install.get(row) ? "I" : "_");
+				res += (mod.isLocalAvailable() && mod.isNewerAvailable() ? "U"
+						: "_");
+				res += (mod.isLocalAvailable() ? "D" : "_");
+				return res;
 		}
 		return null;
@@ -65,4 +70,6 @@
 			case 3:
 				return bundle.getString("mod.creator");
+			case 4:
+				return bundle.getString("mod.state");
 		}
 		return null;
@@ -76,5 +83,5 @@
 	@Override
 	public int getColumnCount() {
-		return 4;
+		return 5;
 	}
 
@@ -89,4 +96,6 @@
 				return String.class;
 			case 3:
+				return String.class;
+			case 4:
 				return String.class;
 		}
@@ -123,4 +132,10 @@
 				col.setPreferredWidth(90);
 				break;
+			case 4:
+				w = 55;
+				col.setPreferredWidth(w);
+				col.setMinWidth(w);
+				col.setMaxWidth(w);
+				break;
 		}
 	}
@@ -141,6 +156,5 @@
 		install.clear();
 		for (int i = 0; i < items.size(); i++) {
-			install.add(i, ModManager.getInstance()
-					.isModInstalled(items.get(i)));
+			install.add(i, items.get(i).isInstalled());
 		}
 		fireTableDataChanged();
Index: AE/installer2/src/net/oni2/aeinstaller/localization/MainWin.properties
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/localization/MainWin.properties	(revision 630)
+++ AE/installer2/src/net/oni2/aeinstaller/localization/MainWin.properties	(revision 631)
@@ -42,6 +42,4 @@
 lblDownloadSize.text=Size of files to download: 
 
-openModFolder.text=Open mod folder
-
 lblSubmitter.text=Submitter:
 lblCreator.text=Creator:
Index: AE/installer2/src/net/oni2/aeinstaller/localization/ModTable.properties
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/localization/ModTable.properties	(revision 631)
+++ AE/installer2/src/net/oni2/aeinstaller/localization/ModTable.properties	(revision 631)
@@ -0,0 +1,13 @@
+mod.name=Name
+mod.package_number=Pkg#
+mod.install=Install
+mod.creator=Creator
+mod.state=State
+
+state.installed=Is <b>I</b>nstalled
+state.updatable=<b>U</b>pdate available
+state.downloaded=Is <b>D</b>ownloaded
+yes=Yes
+no=No
+
+openModFolder.text=Open mod folder
Index: AE/installer2/src/net/oni2/aeinstaller/localization/ModTableModel.properties
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/localization/ModTableModel.properties	(revision 630)
+++ 	(revision )
@@ -1,4 +1,0 @@
-mod.name=Name
-mod.package_number=Pkg#
-mod.install=Install
-mod.creator=Creator
