public void setSyncTableRow(int tableRowIndex, String status, int progressValue, int totalProgressValue, File file) {
        tblSync.getModel().setValueAt(status, tableRowIndex, 1);

        Component c = (Component) tblSync.getValueAt(tableRowIndex, 2);

        if (c instanceof JProgressBar) {
            ((JProgressBar) c).setMaximum(totalProgressValue);
            ((JProgressBar) c).setValue(progressValue);
        }

        // TODO: determine its thread-safe or not
        if (status.equals("Finished")) {
            this.numFilesSynced++;

            // Just downloaded package, extract it
            if (file.getPath().endsWith(".package")) {
                ExtractingDialog ed = new ExtractingDialog(this, false, file);
                ed.setVisible(true);
            }

            if (file.getName().equals("changelog.txt")) {
                refreshLogoAndChangelog();
            }
        }

        tblSync.repaint();

        pbSync.setValue(this.numFilesSynced);
        pbSync.setString("Done: " + this.numFilesSynced + "/" + this.numFilesToSync);
        if (this.numFilesToSync != 0) {
            float percentage = this.numFilesSynced / (float) this.numFilesToSync * 100;
            tabs.setTitleAt(1, "File sync (" + String.format("%.2f", percentage) + "%)");
        }

        if (this.numFilesSynced == this.numFilesToSync) {
            this.syncState = SyncState.COMPLETE;

            refreshLogoAndChangelog();
        } else {
            this.syncState = SyncState.SYNCING;
        }
    }