@Override
  public void startUp() throws Exception {
    // do a DB backup, and keep last 15 copies
    File db = new File(Settings.getInstance().getSettingsFolder(), MOVIE_DB);
    Utils.createBackupFile(db);
    Utils.deleteOldBackupFile(db, 15);

    // configure database
    mvStore =
        new MVStore.Builder()
            .fileName(Settings.getInstance().getSettingsFolder() + File.separatorChar + MOVIE_DB)
            .compressHigh()
            .open();
    mvStore.setAutoCommitDelay(2000); // 2 sec
    mvStore.setRetentionTime(0);
    mvStore.setReuseSpace(true);

    // configure JSON
    objectMapper = new ObjectMapper();
    objectMapper.configure(MapperFeature.AUTO_DETECT_GETTERS, false);
    objectMapper.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false);
    objectMapper.configure(MapperFeature.AUTO_DETECT_SETTERS, false);
    objectMapper.configure(MapperFeature.AUTO_DETECT_FIELDS, false);
    objectMapper.setTimeZone(TimeZone.getDefault());
    objectMapper.setSerializationInclusion(Include.NON_DEFAULT);

    movieObjectWriter = objectMapper.writerFor(Movie.class);
    movieSetObjectWriter = objectMapper.writerFor(MovieSet.class);

    movieMap = mvStore.openMap("movies");
    movieSetMap = mvStore.openMap("movieSets");

    MovieList.getInstance().loadMoviesFromDatabase(movieMap, objectMapper);
    MovieList.getInstance().loadMovieSetsFromDatabase(movieSetMap, objectMapper);
    MovieList.getInstance().initDataAfterLoading();
    enabled = true;
  }
  private void buildAndInstallDatasourceArray() {
    // remember old value and remove listener
    Object oldValue = cbDatasource.getSelectedItem();
    cbDatasource.removeActionListener(actionFilter);

    // build up the new cb
    cbDatasource.removeAllItems();
    List<String> datasources =
        new ArrayList<String>(Settings.getInstance().getMovieSettings().getMovieDataSource());
    Collections.sort(datasources);
    for (String datasource : datasources) {
      cbDatasource.addItem(datasource);
    }

    // re-set the value and readd action listener
    if (oldValue != null) {
      cbDatasource.setSelectedItem(oldValue);
    }
    cbDatasource.addActionListener(actionFilter);
  }
 @Override
 public void initializeDatabase() throws Exception {
   FileUtils.deleteQuietly(new File(Settings.getInstance().getSettingsFolder(), MOVIE_DB));
 }
/**
 * The Class TvShowSettingsPanel.
 *
 * @author Manuel Laggner
 */
public class TvShowSettingsPanel extends ScrollablePanel {
  private static final long serialVersionUID = -675729644848101096L;
  /** @wbp.nls.resourceBundle messages */
  private static final ResourceBundle BUNDLE =
      ResourceBundle.getBundle("messages", new UTF8Control()); // $NON-NLS-1$

  private Settings settings = Settings.getInstance();

  /** UI components */
  private JTable tableTvShowSources;

  private JLabel lblImageCache;
  private JCheckBox chckbxImageCache;
  private JLabel lblImageCacheHint;
  private JCheckBox chckbxTraktTv;
  private final JButton btnClearTraktTvShows;
  private JCheckBox cbDvdOrder;

  /** Instantiates a new tv show settings panel. */
  public TvShowSettingsPanel() {
    setLayout(
        new FormLayout(
            new ColumnSpec[] {
              FormFactory.RELATED_GAP_COLSPEC,
              ColumnSpec.decode("default:grow"),
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
            },
            new RowSpec[] {
              FormFactory.RELATED_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.RELATED_GAP_ROWSPEC,
              RowSpec.decode("default:grow"),
            }));

    {
      JPanel panelTvShowDataSources = new JPanel();

      panelTvShowDataSources.setBorder(
          new TitledBorder(
              null,
              BUNDLE.getString("Settings.tvshowdatasource"),
              TitledBorder.LEADING,
              TitledBorder.TOP,
              null,
              null)); //$NON-NLS-1$
      add(panelTvShowDataSources, "2, 2, fill, top");
      panelTvShowDataSources.setLayout(
          new FormLayout(
              new ColumnSpec[] {
                FormFactory.RELATED_GAP_COLSPEC,
                FormFactory.DEFAULT_COLSPEC,
                FormFactory.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("max(40dlu;default)"),
                FormFactory.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("max(44dlu;default):grow"),
                FormFactory.RELATED_GAP_COLSPEC,
                FormFactory.DEFAULT_COLSPEC,
                FormFactory.RELATED_GAP_COLSPEC,
              },
              new RowSpec[] {
                FormFactory.RELATED_GAP_ROWSPEC,
                RowSpec.decode("160px:grow"),
                FormFactory.RELATED_GAP_ROWSPEC,
                FormFactory.DEFAULT_ROWSPEC,
                FormFactory.RELATED_GAP_ROWSPEC,
                FormFactory.DEFAULT_ROWSPEC,
                FormFactory.RELATED_GAP_ROWSPEC,
              }));

      JScrollPane scrollPane = new JScrollPane();
      panelTvShowDataSources.add(scrollPane, "2, 2, 5, 1, fill, fill");

      tableTvShowSources = new JTable();
      tableTvShowSources.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      scrollPane.setViewportView(tableTvShowSources);

      JPanel panelTvShowSourcesButtons = new JPanel();
      panelTvShowDataSources.add(panelTvShowSourcesButtons, "8, 2, default, top");
      panelTvShowSourcesButtons.setLayout(
          new FormLayout(
              new ColumnSpec[] {
                FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,
              },
              new RowSpec[] {
                FormFactory.DEFAULT_ROWSPEC,
                FormFactory.RELATED_GAP_ROWSPEC,
                FormFactory.DEFAULT_ROWSPEC,
              }));

      JButton btnAdd = new JButton(BUNDLE.getString("Button.add")); // $NON-NLS-1$
      btnAdd.addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
              File file =
                  TmmUIHelper.selectDirectory(
                      BUNDLE.getString("Settings.tvshowdatasource.folderchooser")); // $NON-NLS-1$
              if (file != null && file.exists() && file.isDirectory()) {
                settings.getTvShowSettings().addTvShowDataSources(file.getAbsolutePath());
              }
            }
          });

      panelTvShowSourcesButtons.add(btnAdd, "2, 1, fill, top");

      JButton btnRemove = new JButton(BUNDLE.getString("Button.remove")); // $NON-NLS-1$
      btnRemove.addActionListener(
          new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
              int row =
                  tableTvShowSources.convertRowIndexToModel(tableTvShowSources.getSelectedRow());
              if (row != -1) { // nothing selected
                String path = Globals.settings.getTvShowSettings().getTvShowDataSource().get(row);
                String[] choices = {
                  BUNDLE.getString("Button.continue"), BUNDLE.getString("Button.abort")
                }; //$NON-NLS-1$
                int decision =
                    JOptionPane.showOptionDialog(
                        null,
                        String.format(
                            BUNDLE.getString("Settings.tvshowdatasource.remove.info"), path),
                        BUNDLE.getString("Settings.datasource.remove"),
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.PLAIN_MESSAGE,
                        null,
                        choices,
                        BUNDLE.getString("Button.abort")); // $NON-NLS-1$
                if (decision == 0) {
                  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                  Globals.settings.getTvShowSettings().removeTvShowDataSources(path);
                  setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                }
              }
            }
          });
      panelTvShowSourcesButtons.add(btnRemove, "2, 3, fill, top");

      JLabel lblDvdOrder = new JLabel(BUNDLE.getString("Settings.dvdorder")); // $NON-NLS-1$
      panelTvShowDataSources.add(lblDvdOrder, "2, 4, right, default");

      cbDvdOrder = new JCheckBox("");
      panelTvShowDataSources.add(cbDvdOrder, "4, 4");

      lblImageCache = new JLabel(BUNDLE.getString("Settings.imagecacheimport")); // $NON-NLS-1$
      panelTvShowDataSources.add(lblImageCache, "2, 6, right, default");

      chckbxImageCache = new JCheckBox("");
      panelTvShowDataSources.add(chckbxImageCache, "4, 6");

      lblImageCacheHint =
          new JLabel(BUNDLE.getString("Settings.imagecacheimporthint")); // $NON-NLS-1$
      TmmFontHelper.changeFont(lblImageCacheHint, 0.833);
      panelTvShowDataSources.add(lblImageCacheHint, "6, 6, 3, 1");
    }

    JPanel panel = new JPanel();
    add(panel, "2, 4, fill, fill");
    panel.setLayout(
        new FormLayout(
            new ColumnSpec[] {
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
              FormFactory.RELATED_GAP_COLSPEC,
            },
            new RowSpec[] {
              FormFactory.RELATED_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.RELATED_GAP_ROWSPEC,
            }));

    JLabel lblTraktTv = new JLabel(BUNDLE.getString("Settings.trakt")); // $NON-NLS-1$
    panel.add(lblTraktTv, "2, 2");

    chckbxTraktTv = new JCheckBox("");
    panel.add(chckbxTraktTv, "4, 2");
    btnClearTraktTvShows =
        new JButton(BUNDLE.getString("Settings.trakt.cleartvshows")); // $NON-NLS-1$
    btnClearTraktTvShows.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            int confirm =
                JOptionPane.showOptionDialog(
                    null,
                    BUNDLE.getString("Settings.trakt.cleartvshows.hint"),
                    BUNDLE.getString("Settings.trakt.cleartvshows"),
                    JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    null,
                    null); //$NON-NLS-1$
            if (confirm == JOptionPane.YES_OPTION) {
              TmmTask task = new ClearTraktTvTask(false, true);
              TmmTaskManager.getInstance().addUnnamedTask(task);
            }
          }
        });
    panel.add(btnClearTraktTvShows, "6, 2");

    initDataBindings();

    // column headings
    tableTvShowSources
        .getColumnModel()
        .getColumn(0)
        .setHeaderValue(BUNDLE.getString("Settings.source")); // $NON-NLS-1$

    if (!Globals.isDonator()) {
      chckbxTraktTv.setSelected(false);
      chckbxTraktTv.setEnabled(false);
      btnClearTraktTvShows.setEnabled(false);
    }
  }

  protected void initDataBindings() {
    BeanProperty<Settings, List<String>> settingsBeanProperty_4 =
        BeanProperty.create("tvShowSettings.tvShowDataSource");
    JTableBinding<String, Settings, JTable> jTableBinding =
        SwingBindings.createJTableBinding(
            UpdateStrategy.READ, settings, settingsBeanProperty_4, tableTvShowSources);
    //
    ObjectProperty<String> stringObjectProperty = ObjectProperty.create();
    jTableBinding.addColumnBinding(stringObjectProperty);
    //
    jTableBinding.bind();
    //
    BeanProperty<Settings, Boolean> settingsBeanProperty =
        BeanProperty.create("tvShowSettings.syncTrakt");
    BeanProperty<JCheckBox, Boolean> jCheckBoxBeanProperty = BeanProperty.create("selected");
    AutoBinding<Settings, Boolean, JCheckBox, Boolean> autoBinding =
        Bindings.createAutoBinding(
            UpdateStrategy.READ_WRITE,
            settings,
            settingsBeanProperty,
            chckbxTraktTv,
            jCheckBoxBeanProperty);
    autoBinding.bind();
    //
    BeanProperty<Settings, Boolean> settingsBeanProperty_1 =
        BeanProperty.create("tvShowSettings.dvdOrder");
    AutoBinding<Settings, Boolean, JCheckBox, Boolean> autoBinding_1 =
        Bindings.createAutoBinding(
            UpdateStrategy.READ_WRITE,
            settings,
            settingsBeanProperty_1,
            cbDvdOrder,
            jCheckBoxBeanProperty);
    autoBinding_1.bind();
  }
}
  /**
   * Instantiates a new movie extended search
   *
   * @param model the model
   */
  public MovieExtendedSearchPanel(MovieSelectionModel model) {
    super();
    setOpaque(false);
    shadowAlpha = 100;
    arcs = new Dimension(10, 10);

    this.movieSelectionModel = model;
    Map<MovieSearchOptions, Object> savedSearchOptions =
        MovieModuleManager.MOVIE_SETTINGS.getUiFilters();

    // add a dummy mouse listener to prevent clicking through
    addMouseListener(new MouseAdapter() {});

    setLayout(
        new FormLayout(
            new ColumnSpec[] {
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
              FormFactory.RELATED_GAP_COLSPEC,
              ColumnSpec.decode("default:grow"),
              FormFactory.RELATED_GAP_COLSPEC,
              ColumnSpec.decode("default:grow"),
              FormFactory.UNRELATED_GAP_COLSPEC,
            },
            new RowSpec[] {
              FormFactory.RELATED_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.UNRELATED_GAP_ROWSPEC,
            }));

    JLabel lblFilterBy =
        new JLabel(BUNDLE.getString("movieextendedsearch.filterby")); // $NON-NLS-1$
    setComponentFont(lblFilterBy);
    add(lblFilterBy, "2, 2, 3, 1");

    cbFilterDuplicates = new JCheckBox("");
    cbFilterDuplicates.setUI(CHECKBOX_UI); // $hide$
    cbFilterDuplicates.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.DUPLICATES));
    cbFilterDuplicates.setAction(actionFilter);
    add(cbFilterDuplicates, "2, 4");

    JLabel lblShowDuplicates =
        new JLabel(BUNDLE.getString("movieextendedsearch.duplicates")); // $NON-NLS-1$
    setComponentFont(lblShowDuplicates);
    add(lblShowDuplicates, "4, 4, right, default");

    cbFilterWatched = new JCheckBox("");
    cbFilterWatched.setUI(CHECKBOX_UI); // $hide$
    cbFilterWatched.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.WATCHED));
    cbFilterWatched.setAction(actionFilter);
    add(cbFilterWatched, "2, 5");

    JLabel lblWatchedFlag =
        new JLabel(BUNDLE.getString("movieextendedsearch.watched")); // $NON-NLS-1$
    setComponentFont(lblWatchedFlag);
    add(lblWatchedFlag, "4, 5, right, default");

    cbWatched = new SmallComboBox(WatchedFlag.values());
    setComponentFont(cbWatched);
    cbWatched.setAction(actionFilter);
    add(cbWatched, "6, 5, fill, default");

    cbFilterGenre = new JCheckBox("");
    cbFilterGenre.setUI(CHECKBOX_UI); // $hide$
    cbFilterGenre.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.GENRE));
    cbFilterGenre.setAction(actionFilter);
    add(cbFilterGenre, "2, 6");

    JLabel lblGenre = new JLabel(BUNDLE.getString("movieextendedsearch.genre")); // $NON-NLS-1$
    setComponentFont(lblGenre);
    add(lblGenre, "4, 6, right, default");

    cbGenre = new SmallComboBox(MediaGenres.values());
    setComponentFont(cbGenre);
    cbGenre.setAction(actionFilter);
    add(cbGenre, "6, 6, fill, default");

    cbFilterCertification = new JCheckBox("");
    cbFilterCertification.setUI(CHECKBOX_UI); // $hide$
    cbFilterCertification.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.CERTIFICATION));
    cbFilterCertification.setAction(actionFilter);
    add(cbFilterCertification, "2, 7");

    lblCertification = new JLabel(BUNDLE.getString("metatag.certification")); // $NON-NLS-1$
    setComponentFont(lblCertification);
    add(lblCertification, "4, 7, right, default");

    cbCertification = new SmallComboBox();
    setComponentFont(cbCertification);
    cbCertification.setAction(actionFilter);
    add(cbCertification, "6, 7, fill, default");

    cbFilterYear = new JCheckBox("");
    cbFilterYear.setUI(CHECKBOX_UI); // $hide$
    cbFilterYear.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.YEAR));
    cbFilterYear.setAction(actionFilter);
    add(cbFilterYear, "2, 8");

    lblYear = new JLabel(BUNDLE.getString("metatag.year")); // $NON-NLS-1$
    setComponentFont(lblYear);
    add(lblYear, "4, 8, right, default");

    int year = Calendar.getInstance().get(Calendar.YEAR);
    spYear = new JSpinner();
    setComponentFont(spYear);
    spYear.setUI(new SmallSpinnerUI());
    spYear.setModel(new SpinnerNumberModel(year, 0, 3000, 1));
    spYear.setEditor(new JSpinner.NumberEditor(spYear, "#"));
    spYear.addChangeListener(
        new ChangeListener() {
          @Override
          public void stateChanged(ChangeEvent e) {
            actionFilter.actionPerformed(null);
          }
        });
    add(spYear, "6, 8");

    cbFilterCast = new JCheckBox("");
    cbFilterCast.setUI(CHECKBOX_UI); // $hide$
    cbFilterCast.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.CAST));
    cbFilterCast.setAction(actionFilter);
    add(cbFilterCast, "2, 9");

    JLabel lblCastMember = new JLabel(BUNDLE.getString("movieextendedsearch.cast")); // $NON-NLS-1$
    setComponentFont(lblCastMember);
    add(lblCastMember, "4, 9, right, default");

    tfCastMember = new JTextField();
    setComponentFont(tfCastMember);
    tfCastMember.setBorder(new SmallTextFieldBorder());
    add(tfCastMember, "6, 9, fill, default");
    tfCastMember.setColumns(10);
    tfCastMember
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {
              public void changedUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }

              public void insertUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }

              public void removeUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }
            });

    cbFilterTag = new JCheckBox("");
    cbFilterTag.setUI(CHECKBOX_UI); // $hide$
    cbFilterTag.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.TAG));
    cbFilterTag.setAction(actionFilter);
    add(cbFilterTag, "2, 10");

    JLabel lblTag = new JLabel(BUNDLE.getString("movieextendedsearch.tag")); // $NON-NLS-1$
    setComponentFont(lblTag);
    add(lblTag, "4, 10, right, default");

    cbTag = new SmallComboBox();
    setComponentFont(cbTag);
    cbTag.setAction(actionFilter);

    add(cbTag, "6, 10, fill, default");

    cbFilterMovieset = new JCheckBox("");
    cbFilterMovieset.setUI(CHECKBOX_UI); // $hide$
    cbFilterMovieset.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.MOVIESET));
    cbFilterMovieset.setAction(actionFilter);
    add(cbFilterMovieset, "2, 11");

    JLabel lblMoviesInMovieset =
        new JLabel(BUNDLE.getString("movieextendedsearch.movieset")); // $NON-NLS-1$
    setComponentFont(lblMoviesInMovieset);
    add(lblMoviesInMovieset, "4, 11, right, default");

    cbMovieset = new SmallComboBox(MovieInMovieSet.values());
    setComponentFont(cbMovieset);
    cbMovieset.setAction(actionFilter);
    add(cbMovieset, "6, 11, fill, default");

    cbFilterVideoFormat = new JCheckBox("");
    cbFilterVideoFormat.setUI(CHECKBOX_UI); // $hide$
    cbFilterVideoFormat.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.VIDEO_FORMAT));
    cbFilterVideoFormat.setAction(actionFilter);
    add(cbFilterVideoFormat, "2, 12");

    JLabel lblVideoFormat = new JLabel(BUNDLE.getString("metatag.resolution")); // $NON-NLS-1$
    setComponentFont(lblVideoFormat);
    add(lblVideoFormat, "4, 12, right, default");

    cbVideoFormat = new SmallComboBox(getVideoFormats());
    setComponentFont(cbVideoFormat);
    cbVideoFormat.setAction(actionFilter);
    add(cbVideoFormat, "6, 12, fill, default");

    cbFilterVideoCodec = new JCheckBox("");
    cbFilterVideoCodec.setUI(CHECKBOX_UI); // $hide$
    cbFilterVideoCodec.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.VIDEO_CODEC));
    cbFilterVideoCodec.setAction(actionFilter);
    add(cbFilterVideoCodec, "2, 13");

    JLabel lblVideoCodec = new JLabel(BUNDLE.getString("metatag.videocodec")); // $NON-NLS-1$
    setComponentFont(lblVideoCodec);
    add(lblVideoCodec, "4, 13, right, default");

    cbVideoCodec = new SmallComboBox();
    setComponentFont(cbVideoCodec);
    cbVideoCodec.setAction(actionFilter);
    add(cbVideoCodec, "6, 13, fill, default");

    cbFilterAudioCodec = new JCheckBox("");
    cbFilterAudioCodec.setUI(CHECKBOX_UI); // $hide$
    cbFilterAudioCodec.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.AUDIO_CODEC));
    cbFilterAudioCodec.setAction(actionFilter);
    add(cbFilterAudioCodec, "2, 14");

    JLabel lblAudioCodec = new JLabel(BUNDLE.getString("metatag.audiocodec")); // $NON-NLS-1$
    setComponentFont(lblAudioCodec);
    add(lblAudioCodec, "4, 14, right, default");

    cbAudioCodec = new SmallComboBox();
    setComponentFont(cbAudioCodec);
    cbAudioCodec.setAction(actionFilter);
    add(cbAudioCodec, "6, 14, fill, default");

    cbFilterDatasource = new JCheckBox("");
    cbFilterDatasource.setUI(CHECKBOX_UI); // $hide$
    cbFilterDatasource.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.DATASOURCE));
    cbFilterDatasource.setAction(actionFilter);
    add(cbFilterDatasource, "2, 15");

    JLabel lblDatasource = new JLabel(BUNDLE.getString("metatag.datasource")); // $NON-NLS-1$
    setComponentFont(lblDatasource);
    add(lblDatasource, "4, 15, right, default");

    cbDatasource = new SmallComboBox();
    setComponentFont(cbDatasource);
    cbDatasource.setAction(actionFilter);
    add(cbDatasource, "6, 15, fill, default");

    cbFilterMediaSource = new JCheckBox("");
    cbFilterMediaSource.setUI(CHECKBOX_UI); // $hide$
    cbFilterMediaSource.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MEDIA_SOURCE));
    cbFilterMediaSource.addActionListener(actionFilter);
    add(cbFilterMediaSource, "2, 16");

    JLabel lblMediaSource = new JLabel(BUNDLE.getString("metatag.source")); // $NON-NLS-1$
    setComponentFont(lblMediaSource);
    add(lblMediaSource, "4, 16, right, default");

    cbMediaSource = new SmallComboBox(MovieMediaSource.values());
    setComponentFont(cbMediaSource);
    cbMediaSource.setAction(actionFilter);
    add(cbMediaSource, "6, 16, fill, default");

    cbFilterMissingMetadata = new JCheckBox("");
    cbFilterMissingMetadata.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingMetadata.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_METADATA));
    cbFilterMissingMetadata.setAction(actionFilter);
    add(cbFilterMissingMetadata, "2, 17");

    JLabel lblMissingMetadata =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingmetadata")); // $NON-NLS-1$
    setComponentFont(lblMissingMetadata);
    add(lblMissingMetadata, "4, 17, right, default");

    cbFilterMissingArtwork = new JCheckBox("");
    cbFilterMissingArtwork.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingArtwork.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_ARTWORK));
    cbFilterMissingArtwork.setAction(actionFilter);
    add(cbFilterMissingArtwork, "2, 18");

    JLabel lblMissingArtwork =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingartwork")); // $NON-NLS-1$
    setComponentFont(lblMissingArtwork);
    add(lblMissingArtwork, "4, 18, right, default");

    cbFilterMissingSubtitles = new JCheckBox("");
    cbFilterMissingSubtitles.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingSubtitles.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_SUBTITLES));
    cbFilterMissingSubtitles.setAction(actionFilter);
    add(cbFilterMissingSubtitles, "2, 19");

    JLabel lblMissingSubtitles =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingsubtitles")); // $NON-NLS-1$
    setComponentFont(lblMissingSubtitles);
    add(lblMissingSubtitles, "4, 19, right, default");

    cbFilterNewMovies = new JCheckBox("");
    cbFilterNewMovies.setUI(CHECKBOX_UI); // $hide$
    cbFilterNewMovies.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.NEW_MOVIES));
    cbFilterNewMovies.setAction(actionFilter);
    add(cbFilterNewMovies, "2, 20");

    lblNewMovies = new JLabel(BUNDLE.getString("movieextendedsearch.newmovies")); // $NON-NLS-1$
    setComponentFont(lblNewMovies);
    add(lblNewMovies, "4, 20, right, default");

    JSeparator separator = new JSeparator();
    add(separator, "2, 22, 5, 1");

    JLabel lblSortBy = new JLabel(BUNDLE.getString("movieextendedsearch.sortby")); // $NON-NLS-1$
    setComponentFont(lblSortBy);
    add(lblSortBy, "2, 24, 3, 1");

    cbSortColumn = new SmallComboBox(SortColumn.values());
    setComponentFont(cbSortColumn);
    cbSortColumn.setAction(actionSort);
    add(cbSortColumn, "2, 26, 3, 1, fill, default");

    cbSortOrder = new SmallComboBox(SortOrder.values());
    setComponentFont(cbSortOrder);
    cbSortOrder.setAction(actionSort);
    add(cbSortOrder, "6, 26, fill, default");

    PropertyChangeListener propertyChangeListener =
        new PropertyChangeListener() {
          @Override
          public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getSource() instanceof MovieList && "tag".equals(evt.getPropertyName())) {
              buildAndInstallTagsArray();
            }
            if (evt.getSource() instanceof MovieList
                && "videoCodec".equals(evt.getPropertyName())) {
              buildAndInstallCodecArray();
            }
            if (evt.getSource() instanceof MovieList
                && "audioCodec".equals(evt.getPropertyName())) {
              buildAndInstallCodecArray();
            }
            if (evt.getSource() instanceof MovieSettings
                && "movieDataSource".equals(evt.getPropertyName())) {
              buildAndInstallDatasourceArray();
            }
            if (evt.getSource() instanceof MovieList
                && "certification".equals(evt.getPropertyName())) {
              buildAndInstallCertificationArray();
            }
          }
        };
    movieList.addPropertyChangeListener(propertyChangeListener);
    Settings.getInstance().getMovieSettings().addPropertyChangeListener(propertyChangeListener);
    buildAndInstallTagsArray();
    buildAndInstallCodecArray();
    buildAndInstallDatasourceArray();
    buildAndInstallCertificationArray();
  }