• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #1427

20 Apr 2026 03:04PM UTC coverage: 3.452% (-0.1%) from 3.572%
#1427

push

jiangxincode
add word pages stat

0 of 243 new or added lines in 6 files covered. (0.0%)

1 existing line in 1 file now uncovered.

250 of 7242 relevant lines covered (3.45%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/word/stat/WordStatPanel.java
1
package edu.jiangxin.apktoolbox.word.stat;
2

3
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
4
import edu.jiangxin.apktoolbox.swing.extend.FileListPanel;
5
import edu.jiangxin.apktoolbox.utils.Constants;
6
import edu.jiangxin.apktoolbox.utils.DateUtils;
7
import edu.jiangxin.apktoolbox.utils.FileUtils;
8
import edu.jiangxin.apktoolbox.word.WordUtils;
9

10
import javax.swing.*;
11
import javax.swing.table.DefaultTableModel;
12
import java.awt.event.ActionEvent;
13
import java.awt.event.ActionListener;
14
import java.io.File;
15
import java.io.Serial;
16
import java.util.*;
17
import java.util.List;
18
import java.util.concurrent.ExecutorService;
19
import java.util.concurrent.Executors;
20
import java.util.concurrent.Future;
21
import java.util.concurrent.atomic.AtomicInteger;
22

NEW
23
public class WordStatPanel extends EasyPanel {
×
24

25
    @Serial
26
    private static final long serialVersionUID = 1L;
27

28
    private JTabbedPane tabbedPane;
29

30
    private JPanel mainPanel;
31

32
    private FileListPanel fileListPanel;
33

34
    private JCheckBox isRecursiveSearched;
35

36
    private JPanel resultPanel;
37

38
    private JTable resultTable;
39

40
    private DefaultTableModel resultTableModel;
41

42
    private JLabel statInfoLabel;
43

44
    private JButton statButton;
45
    private JButton cancelButton;
46

47
    private JProgressBar progressBar;
48

49
    private transient SearchThread searchThread;
50

NEW
51
    private long totalFileSize = 0;
×
52

NEW
53
    private int totalPageCount = 0;
×
54

NEW
55
    private transient final List<Vector<Object>> resultFileList = new ArrayList<>();
×
56

57
    @Override
58
    public void initUI() {
NEW
59
        tabbedPane = new JTabbedPane();
×
NEW
60
        add(tabbedPane);
×
61

NEW
62
        createMainPanel();
×
NEW
63
        tabbedPane.addTab("Option", null, mainPanel, "Show Stat Options");
×
64

NEW
65
        createResultPanel();
×
NEW
66
        tabbedPane.addTab("Result", null, resultPanel, "Show Stat Result");
×
NEW
67
    }
×
68

69
    private void createMainPanel() {
NEW
70
        mainPanel = new JPanel();
×
NEW
71
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
×
72

NEW
73
        fileListPanel = new FileListPanel();
×
NEW
74
        fileListPanel.initialize();
×
75

NEW
76
        JPanel searchOptionPanel = new JPanel();
×
NEW
77
        searchOptionPanel.setLayout(new BoxLayout(searchOptionPanel, BoxLayout.X_AXIS));
×
NEW
78
        searchOptionPanel.setBorder(BorderFactory.createTitledBorder("Stat Options"));
×
79

NEW
80
        isRecursiveSearched = new JCheckBox("Recursive");
×
NEW
81
        isRecursiveSearched.setSelected(true);
×
NEW
82
        searchOptionPanel.add(isRecursiveSearched);
×
NEW
83
        searchOptionPanel.add(Box.createHorizontalGlue());
×
84

NEW
85
        JPanel operationPanel = new JPanel();
×
NEW
86
        operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
×
NEW
87
        operationPanel.setBorder(BorderFactory.createTitledBorder("Operations"));
×
88

NEW
89
        statButton = new JButton("Stat");
×
NEW
90
        cancelButton = new JButton("Cancel");
×
NEW
91
        cancelButton.setEnabled(false);
×
NEW
92
        statButton.addActionListener(new OperationButtonActionListener());
×
NEW
93
        cancelButton.addActionListener(new OperationButtonActionListener());
×
NEW
94
        operationPanel.add(statButton);
×
NEW
95
        operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
×
NEW
96
        operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
×
NEW
97
        operationPanel.add(cancelButton);
×
NEW
98
        operationPanel.add(Box.createHorizontalGlue());
×
99

NEW
100
        progressBar = new JProgressBar();
×
NEW
101
        progressBar.setStringPainted(true);
×
NEW
102
        progressBar.setString("Ready");
×
103

NEW
104
        mainPanel.add(fileListPanel);
×
NEW
105
        mainPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
NEW
106
        mainPanel.add(searchOptionPanel);
×
NEW
107
        mainPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
NEW
108
        mainPanel.add(operationPanel);
×
NEW
109
        mainPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
NEW
110
        mainPanel.add(progressBar);
×
NEW
111
    }
×
112

113
    private void createResultPanel() {
NEW
114
        resultPanel = new JPanel();
×
NEW
115
        resultPanel.setLayout(new BoxLayout(resultPanel, BoxLayout.Y_AXIS));
×
116

NEW
117
        resultTableModel = new WordFilesTableModel(new Vector<>(), WordFilesConstants.COLUMN_NAMES);
×
NEW
118
        resultTable = new JTable(resultTableModel);
×
NEW
119
        resultTable.setDefaultRenderer(Vector.class, new WordFilesTableCellRenderer());
×
NEW
120
        for (int i = 0; i < resultTable.getColumnCount(); i++) {
×
NEW
121
            resultTable.getColumn(resultTable.getColumnName(i)).setCellRenderer(new WordFilesTableCellRenderer());
×
122
        }
NEW
123
        resultTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
×
NEW
124
        JScrollPane scrollPane = new JScrollPane(resultTable);
×
125

NEW
126
        JPanel statInfoPanel = new JPanel();
×
NEW
127
        statInfoPanel.setLayout(new BoxLayout(statInfoPanel, BoxLayout.X_AXIS));
×
NEW
128
        statInfoLabel = new JLabel("");
×
NEW
129
        statInfoPanel.add(statInfoLabel);
×
NEW
130
        statInfoPanel.add(Box.createHorizontalGlue());
×
131

NEW
132
        resultPanel.add(scrollPane);
×
NEW
133
        resultPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
NEW
134
        resultPanel.add(statInfoPanel);
×
NEW
135
    }
×
136

137
    private void processFile(File file) {
NEW
138
        Vector<Object> fileVector = getRowVector(file);
×
NEW
139
        resultFileList.add(fileVector);
×
NEW
140
    }
×
141

NEW
142
    class OperationButtonActionListener implements ActionListener {
×
143
        @Override
144
        public void actionPerformed(ActionEvent e) {
NEW
145
            Object source = e.getSource();
×
NEW
146
            if (source.equals(statButton)) {
×
NEW
147
                if (fileListPanel.getFileList().isEmpty()) {
×
NEW
148
                    return;
×
149
                }
NEW
150
                statButton.setEnabled(false);
×
NEW
151
                cancelButton.setEnabled(true);
×
NEW
152
                searchThread = new SearchThread(isRecursiveSearched.isSelected());
×
NEW
153
                searchThread.start();
×
NEW
154
            } else if (source.equals(cancelButton)) {
×
NEW
155
                statButton.setEnabled(true);
×
NEW
156
                cancelButton.setEnabled(false);
×
NEW
157
                if (searchThread.isAlive()) {
×
NEW
158
                    searchThread.interrupt();
×
NEW
159
                    searchThread.executorService.shutdownNow();
×
160
                }
161
            }
NEW
162
        }
×
163
    }
164

165
    private void showResult() {
NEW
166
        SwingUtilities.invokeLater(() -> {
×
NEW
167
            int index = 0;
×
NEW
168
            for (Vector<Object> file : resultFileList) {
×
NEW
169
                file.add(0, ++index);
×
NEW
170
                resultTableModel.addRow(file);
×
NEW
171
            }
×
NEW
172
            tabbedPane.setSelectedIndex(1);
×
NEW
173
            statInfoLabel.setText("Page Count: " + totalPageCount + ", Total Size: " + FileUtils.sizeOfInHumanFormat(totalFileSize));
×
NEW
174
        });
×
NEW
175
    }
×
176

177
    private Vector<Object> getRowVector(File file) {
NEW
178
        Vector<Object> rowData = new Vector<>();
×
NEW
179
        rowData.add(file.getParent());
×
NEW
180
        rowData.add(file.getName());
×
NEW
181
        totalFileSize += file.length();
×
NEW
182
        rowData.add(FileUtils.sizeOfInHumanFormat(file));
×
NEW
183
        rowData.add(DateUtils.millisecondToHumanFormat(file.lastModified()));
×
NEW
184
        int pageCount = WordUtils.getPageCount(file);
×
NEW
185
        totalPageCount += pageCount;
×
NEW
186
        rowData.add(pageCount);
×
NEW
187
        return rowData;
×
188
    }
189

190
    class SearchThread extends Thread {
191
        public final ExecutorService executorService;
NEW
192
        private final AtomicInteger processedFiles = new AtomicInteger(0);
×
NEW
193
        private int totalFiles = 0;
×
194
        private final boolean isRecursiveSearched;
195

NEW
196
        public SearchThread(boolean isRecursiveSearched) {
×
NEW
197
            super();
×
NEW
198
            this.isRecursiveSearched = isRecursiveSearched;
×
NEW
199
            this.executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
×
200

NEW
201
            resultFileList.clear();
×
NEW
202
            totalFileSize = 0;
×
NEW
203
            totalPageCount = 0;
×
204

NEW
205
            SwingUtilities.invokeLater(() -> {
×
NEW
206
                progressBar.setValue(0);
×
NEW
207
                progressBar.setString("Starting search...");
×
NEW
208
                resultTableModel.setRowCount(0);
×
NEW
209
                statInfoLabel.setText("");
×
NEW
210
            });
×
NEW
211
        }
×
212

213
        @Override
214
        public void run() {
215
            try {
NEW
216
                List<File> fileList = fileListPanel.getFileList();
×
NEW
217
                Set<File> fileSet = new TreeSet<>();
×
NEW
218
                String[] extensions = new String[]{"doc", "DOC", "docx", "DOCX"};
×
NEW
219
                for (File file : fileList) {
×
NEW
220
                    fileSet.addAll(FileUtils.listFiles(file, extensions, isRecursiveSearched));
×
NEW
221
                }
×
222

NEW
223
                List<Future<?>> futures = new ArrayList<>();
×
NEW
224
                totalFiles = fileSet.size();
×
NEW
225
                updateProgress();
×
226

NEW
227
                for (File file : fileSet) {
×
NEW
228
                    if (currentThread().isInterrupted()) {
×
NEW
229
                        return;
×
230
                    }
NEW
231
                    futures.add(executorService.submit(() -> {
×
NEW
232
                        if (currentThread().isInterrupted()) {
×
NEW
233
                            return null;
×
234
                        }
NEW
235
                        processFile(file);
×
NEW
236
                        incrementProcessedFiles();
×
NEW
237
                        return null;
×
238
                    }));
NEW
239
                }
×
240

241
                // Wait for all tasks to complete
NEW
242
                for (Future<?> future : futures) {
×
243
                    try {
NEW
244
                        future.get();
×
NEW
245
                    } catch (InterruptedException e) {
×
NEW
246
                        logger.error("Search interrupted", e);
×
NEW
247
                        currentThread().interrupt();
×
NEW
248
                        return;
×
NEW
249
                    }
×
NEW
250
                }
×
251

NEW
252
                showResult();
×
NEW
253
            } catch (Exception e) {
×
NEW
254
                logger.error("Search failed", e);
×
NEW
255
                SwingUtilities.invokeLater(() -> progressBar.setString("Search failed"));
×
256
            } finally {
NEW
257
                executorService.shutdown();
×
NEW
258
                SwingUtilities.invokeLater(() -> {
×
NEW
259
                    statButton.setEnabled(true);
×
NEW
260
                    cancelButton.setEnabled(false);
×
NEW
261
                });
×
262
            }
NEW
263
        }
×
264

265
        private void incrementProcessedFiles() {
NEW
266
            processedFiles.incrementAndGet();
×
NEW
267
            updateProgress();
×
NEW
268
        }
×
269

270
        private void updateProgress() {
NEW
271
            if (totalFiles > 0) {
×
NEW
272
                SwingUtilities.invokeLater(() -> {
×
NEW
273
                    int processed = processedFiles.get();
×
NEW
274
                    int percentage = (int) (processed * 100.0 / totalFiles);
×
NEW
275
                    progressBar.setValue(percentage);
×
NEW
276
                    progressBar.setString(String.format("Processing: %d/%d files (%d%%)", processed, totalFiles, percentage));
×
NEW
277
                });
×
278
            }
NEW
279
        }
×
280
    }
281
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc