3fd9d8911b8dd03427ead8d203f72064466c7539
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.ui / src / org / eclipse / linuxtools / internal / lttng2 / ui / views / control / dialogs / ImportDialog.java
1 /**********************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Bernd Hufmann - Initial API and implementation
11 * Bernd Hufmann - Added handling of streamed traces
12 * Marc-Andre Laperle - Use common method to get opened tmf projects
13 **********************************************************************/
14 package org.eclipse.linuxtools.internal.lttng2.ui.views.control.dialogs;
15
16 import java.util.ArrayList;
17 import java.util.List;
18
19 import org.eclipse.core.resources.IFolder;
20 import org.eclipse.core.resources.IProject;
21 import org.eclipse.core.runtime.NullProgressMonitor;
22 import org.eclipse.core.runtime.Path;
23 import org.eclipse.jface.dialogs.Dialog;
24 import org.eclipse.jface.dialogs.IDialogConstants;
25 import org.eclipse.jface.dialogs.MessageDialog;
26 import org.eclipse.jface.viewers.CheckStateChangedEvent;
27 import org.eclipse.jface.viewers.CheckboxTreeViewer;
28 import org.eclipse.jface.viewers.ICheckStateListener;
29 import org.eclipse.jface.window.Window;
30 import org.eclipse.linuxtools.internal.lttng2.ui.Activator;
31 import org.eclipse.linuxtools.internal.lttng2.ui.views.control.messages.Messages;
32 import org.eclipse.linuxtools.internal.lttng2.ui.views.control.model.impl.TraceSessionComponent;
33 import org.eclipse.linuxtools.internal.lttng2.ui.views.control.remote.IRemoteSystemProxy;
34 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
35 import org.eclipse.linuxtools.tmf.ui.project.model.TraceUtils;
36 import org.eclipse.rse.core.subsystems.RemoteChildrenContentsType;
37 import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
38 import org.eclipse.rse.subsystems.files.core.servicesubsystem.IFileServiceSubSystem;
39 import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.custom.CCombo;
42 import org.eclipse.swt.events.SelectionAdapter;
43 import org.eclipse.swt.events.SelectionEvent;
44 import org.eclipse.swt.graphics.Point;
45 import org.eclipse.swt.layout.GridData;
46 import org.eclipse.swt.layout.GridLayout;
47 import org.eclipse.swt.widgets.Button;
48 import org.eclipse.swt.widgets.Composite;
49 import org.eclipse.swt.widgets.Control;
50 import org.eclipse.swt.widgets.Group;
51 import org.eclipse.swt.widgets.Shell;
52 import org.eclipse.swt.widgets.Text;
53 import org.eclipse.swt.widgets.Tree;
54 import org.eclipse.ui.model.WorkbenchContentProvider;
55 import org.eclipse.ui.model.WorkbenchLabelProvider;
56
57 /**
58 * <p>
59 * Dialog box for collecting trace import information.
60 * </p>
61 *
62 * @author Bernd Hufmann
63 */
64 public class ImportDialog extends Dialog implements IImportDialog {
65
66 // ------------------------------------------------------------------------
67 // Constants
68 // ------------------------------------------------------------------------
69 /** The icon file for this dialog box. */
70 public static final String IMPORT_ICON_FILE = "icons/elcl16/import_trace.gif"; //$NON-NLS-1$
71
72 /** Parent directory for UST traces */
73 public static final String UST_PARENT_DIRECTORY = "ust"; //$NON-NLS-1$
74
75 /** Name of metadata file of trace */
76 public static final String METADATA_FILE_NAME = "metadata"; //$NON-NLS-1$
77
78 /** Default name of kernel traces */
79 public static final String DEFAULT_KERNEL_TRACE_NAME = "kernel"; //$NON-NLS-1$
80
81 // ------------------------------------------------------------------------
82 // Attributes
83 // ------------------------------------------------------------------------
84 /**
85 * The dialog composite.
86 */
87 private Composite fDialogComposite = null;
88 /**
89 * The checkbox tree viewer for selecting available traces
90 */
91 private CheckboxTreeViewer fFolderViewer;
92 /**
93 * The combo box for selecting a project.
94 */
95 private CCombo fCombo;
96 /**
97 * The overwrite button
98 */
99 private Button fOverwriteButton;
100 /**
101 * List of available LTTng 2.0 projects
102 */
103 private List<IProject> fProjects;
104 /**
105 * The parent where the new node should be added.
106 */
107 private TraceSessionComponent fSession = null;
108
109 /**
110 * The name of the default project name
111 */
112 private String fDefaultProjectName = null;
113 /**
114 * List of traces to import
115 */
116 private final List<ImportFileInfo> fTraces = new ArrayList<>();
117 /**
118 * Selection index in project combo box.
119 */
120 private int fProjectIndex;
121 /**
122 * Flag to indicate that something went wrong when creating the dialog box.
123 */
124 private boolean fIsError = false;
125 /**
126 * Children of the remote folder (can be null)
127 */
128 private Object[] fFolderChildren = null;
129
130 // ------------------------------------------------------------------------
131 // Constructors
132 // ------------------------------------------------------------------------
133 /**
134 * Constructor
135 * @param shell - a shell for the display of the dialog
136 */
137 public ImportDialog(Shell shell) {
138 super(shell);
139 setShellStyle(SWT.RESIZE | getShellStyle());
140 }
141
142 // ------------------------------------------------------------------------
143 // Accessors
144 // ------------------------------------------------------------------------
145
146 @Override
147 public List<ImportFileInfo> getTracePathes() {
148 List<ImportFileInfo> retList = new ArrayList<>();
149 retList.addAll(fTraces);
150 return retList;
151 }
152
153 @Override
154 public IProject getProject() {
155 return fProjects.get(fProjectIndex);
156 }
157
158 @Override
159 public void setSession(TraceSessionComponent session) {
160 fSession = session;
161 }
162
163 @Override
164 public void setDefaultProject(String defaultProject) {
165 fDefaultProjectName = defaultProject;
166 }
167
168 // ------------------------------------------------------------------------
169 // Operations
170 // ------------------------------------------------------------------------
171
172 @Override
173 protected void configureShell(Shell newShell) {
174 super.configureShell(newShell);
175 newShell.setText(Messages.TraceControl_ImportDialogTitle);
176 newShell.setImage(Activator.getDefault().loadIcon(IMPORT_ICON_FILE));
177 }
178
179 @Override
180 protected Control createDialogArea(Composite parent) {
181
182 // Main dialog panel
183 fDialogComposite = new Composite(parent, SWT.NONE);
184 GridLayout layout = new GridLayout(1, true);
185 fDialogComposite.setLayout(layout);
186 fDialogComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
187
188 try {
189 createRemoteComposite();
190 } catch (SystemMessageException e) {
191 createErrorComposite(parent, e.fillInStackTrace());
192 return fDialogComposite;
193 }
194 return fDialogComposite;
195 }
196
197 @Override
198 protected void createButtonsForButtonBar(Composite parent) {
199 Button selectAllButton = createButton(parent, IDialogConstants.SELECT_ALL_ID, Messages.TraceControl_ImportDialog_SelectAll, true);
200 selectAllButton.addSelectionListener(new SelectionAdapter() {
201 @Override
202 public void widgetSelected(SelectionEvent e) {
203 setFolderChildrenChecked(true);
204 }
205 });
206
207 Button deselectAllButton = createButton(parent, IDialogConstants.DESELECT_ALL_ID, Messages.TraceControl_ImportDialog_DeselectAll, true);
208 deselectAllButton.addSelectionListener(new SelectionAdapter() {
209 @Override
210 public void widgetSelected(SelectionEvent e) {
211 setFolderChildrenChecked(false);
212 }
213 });
214 createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
215 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
216 updateOKButtonEnablement();
217 }
218
219 @Override
220 protected void okPressed() {
221 if (!fIsError) {
222
223 // Validate input data
224 fTraces.clear();
225
226 fProjectIndex = fCombo.getSelectionIndex();
227
228 if (fProjectIndex < 0) {
229 MessageDialog.openError(getShell(),
230 Messages.TraceControl_ImportDialogTitle,
231 Messages.TraceControl_ImportDialogNoProjectSelectedError);
232 return;
233 }
234
235 IProject project = fProjects.get(fProjectIndex);
236 IFolder traceFolder = project.getFolder(TmfTraceFolder.TRACE_FOLDER_NAME);
237
238 if (!traceFolder.exists()) {
239 // Invalid LTTng 2.0 project
240 MessageDialog.openError(getShell(),
241 Messages.TraceControl_ImportDialogTitle,
242 Messages.TraceControl_ImportDialogInvalidTracingProject + " (" + TmfTraceFolder.TRACE_FOLDER_NAME + ")"); //$NON-NLS-1$//$NON-NLS-2$
243 return;
244 }
245
246 boolean overwriteAll = fOverwriteButton.getSelection();
247
248 Object[] checked = fFolderViewer.getCheckedElements();
249 for (int i = 0; i < checked.length; i++) {
250 IRemoteFile file = (IRemoteFile) checked[i];
251 if (!file.isDirectory() && file.getName().equals(METADATA_FILE_NAME)) {
252 IRemoteFile trace = file.getParentRemoteFile();
253 IRemoteFile parent = trace.getParentRemoteFile();
254 boolean isKernel = false;
255 if (trace.getName().equals(DEFAULT_KERNEL_TRACE_NAME)) {
256 isKernel = true;
257 }
258 StringBuffer traceName = new StringBuffer();
259 traceName.append(trace.getName());
260 traceName.insert(0, '-');
261
262 String path = fSession.isSnapshotSession() ? fSession.getSnapshotInfo().getSnapshotPath() : fSession.getSessionPath();
263 path = getUnifiedPath(path);
264 String parentPath = getUnifiedPath(parent.getAbsolutePath());
265
266 while (!parentPath.equals(path)) {
267 traceName.insert(0, parent.getName());
268 traceName.insert(0, '-');
269 parent = parent.getParentRemoteFile();
270 parentPath = getUnifiedPath(parent.getAbsolutePath());
271 }
272 traceName.insert(0, parent.getName());
273
274 ImportFileInfo info = new ImportFileInfo(trace, traceName.toString(), overwriteAll, isKernel);
275 IFolder folder = traceFolder.getFolder(traceName.toString());
276
277 // Verify if trace directory already exists (and not overwrite)
278 if (folder.exists() && !overwriteAll) {
279
280 // Ask user for overwrite or new name
281 IImportConfirmationDialog conf = TraceControlDialogFactory.getInstance().getImportConfirmationDialog();
282 conf.setTraceName(traceName.toString());
283
284 // Don't add trace to list if dialog was cancelled.
285 if (conf.open() == Window.OK) {
286 info.setOverwrite(conf.isOverwrite());
287 if (!conf.isOverwrite()) {
288 info.setLocalTraceName(conf.getNewTraceName());
289 }
290 fTraces.add(info);
291 }
292 } else {
293 fTraces.add(info);
294 }
295 }
296 }
297
298 if (fTraces.isEmpty()) {
299 MessageDialog.openError(getShell(),
300 Messages.TraceControl_ImportDialogTitle,
301 Messages.TraceControl_ImportDialogNoTraceSelectedError);
302 return;
303 }
304 }
305
306 // validation successful -> call super.okPressed()
307 super.okPressed();
308 }
309
310 // ------------------------------------------------------------------------
311 // Helper methods and classes
312 // ------------------------------------------------------------------------
313
314 /**
315 * Helper class for the contents of a folder in a tracing project
316 *
317 * @author Bernd Hufmann
318 */
319 public static class FolderContentProvider extends WorkbenchContentProvider {
320 @Override
321 public Object[] getChildren(Object o) {
322 if (o instanceof IRemoteFile) {
323 IRemoteFile element = (IRemoteFile) o;
324 // For our purpose, we need folders + files
325 if (!element.isDirectory()) {
326 return new Object[0];
327 }
328 }
329 return super.getChildren(o);
330 }
331 }
332
333 /**
334 * Creates a dialog composite with an error message which can be used
335 * when an exception occurred during creation time of the dialog box.
336 * @param parent - a parent composite
337 * @param e - a error causing exception
338 */
339 private void createErrorComposite(Composite parent, Throwable e) {
340 fIsError = true;
341 fDialogComposite.dispose();
342
343 fDialogComposite = new Composite(parent, SWT.NONE);
344 GridLayout layout = new GridLayout(1, true);
345 fDialogComposite.setLayout(layout);
346 fDialogComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
347
348 Text errorText = new Text(fDialogComposite, SWT.MULTI);
349 StringBuffer error = new StringBuffer();
350 error.append(Messages.TraceControl_ImportDialogCreationError);
351 error.append(System.getProperty("line.separator")); //$NON-NLS-1$
352 error.append(System.getProperty("line.separator")); //$NON-NLS-1$
353 error.append(e.toString());
354 errorText.setText(error.toString());
355 errorText.setLayoutData(new GridData(GridData.FILL_BOTH));
356 }
357
358 private void createRemoteComposite() throws SystemMessageException{
359 Group contextGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
360 contextGroup.setText(Messages.TraceControl_ImportDialogTracesGroupName);
361 GridLayout layout = new GridLayout(1, true);
362 contextGroup.setLayout(layout);
363 contextGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
364
365 IRemoteSystemProxy proxy = fSession.getTargetNode().getRemoteSystemProxy();
366
367 IFileServiceSubSystem fsss = proxy.getFileServiceSubSystem();
368
369 final String path = fSession.isSnapshotSession() ? fSession.getSnapshotInfo().getSnapshotPath() : fSession.getSessionPath();
370 final IRemoteFile remoteFolder = fsss.getRemoteFileObject(path, new NullProgressMonitor());
371 // make sure that remote directory is read and not cached
372 remoteFolder.markStale(true, true);
373
374 fFolderViewer = new CheckboxTreeViewer(contextGroup, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
375 GridData data = new GridData(GridData.FILL_BOTH);
376 Tree tree = fFolderViewer.getTree();
377 tree.setLayoutData(data);
378 tree.setFont(fDialogComposite.getFont());
379 tree.setToolTipText(Messages.TraceControl_ImportDialogTracesTooltip);
380
381 fFolderViewer.setContentProvider(new FolderContentProvider());
382 fFolderViewer.setLabelProvider(new WorkbenchLabelProvider());
383
384 fFolderViewer.addCheckStateListener(new ICheckStateListener() {
385 @Override
386 public void checkStateChanged(CheckStateChangedEvent event) {
387 Object elem = event.getElement();
388 if (elem instanceof IRemoteFile) {
389 IRemoteFile element = (IRemoteFile) elem;
390 if (!element.isDirectory()) {
391 // A trick to keep selection of a file in sync with the directory
392 boolean p = fFolderViewer.getChecked((element.getParentRemoteFile()));
393 fFolderViewer.setChecked(element, p);
394 } else {
395 fFolderViewer.setSubtreeChecked(event.getElement(), event.getChecked());
396 if (!event.getChecked()) {
397 fFolderViewer.setChecked(element.getParentRemoteFile(), false);
398 }
399 }
400 updateOKButtonEnablement();
401 }
402 }
403 });
404 fFolderViewer.setInput(remoteFolder);
405
406 fFolderChildren = remoteFolder.getContents(RemoteChildrenContentsType.getInstance());
407 // children can be null if there the path doesn't exist. This happens when a trace
408 // session hadn't been started and no output was created.
409 setFolderChildrenChecked(true);
410
411 Group projectGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
412 projectGroup.setText(Messages.TraceControl_ImportDialogProjectsGroupName);
413 layout = new GridLayout(1, true);
414 projectGroup.setLayout(layout);
415 projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
416
417 fProjects = new ArrayList<>();
418 List<String> projectNames = new ArrayList<>();
419
420 for (IProject project : TraceUtils.getOpenedTmfProjects()) {
421 fProjects.add(project);
422 projectNames.add(project.getName());
423 }
424
425 fCombo = new CCombo(projectGroup, SWT.READ_ONLY);
426 fCombo.setToolTipText(Messages.TraceControl_ImportDialogProjectsTooltip);
427 fCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 1, 1));
428 fCombo.setItems(projectNames.toArray(new String[projectNames.size()]));
429
430 if (fDefaultProjectName != null) {
431 int select = projectNames.indexOf(fDefaultProjectName);
432 fCombo.select(select);
433 }
434
435 Group overrideGroup = new Group(fDialogComposite, SWT.SHADOW_NONE);
436 layout = new GridLayout(1, true);
437 overrideGroup.setLayout(layout);
438 overrideGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
439
440 fOverwriteButton = new Button(overrideGroup, SWT.CHECK);
441 fOverwriteButton.setText(Messages.TraceControl_ImportDialogOverwriteButtonText);
442 getShell().setMinimumSize(new Point(500, 400));
443 }
444
445 private void setFolderChildrenChecked(boolean isChecked) {
446 if (fFolderChildren != null) {
447 for (Object child : fFolderChildren) {
448 fFolderViewer.setSubtreeChecked(child, isChecked);
449 }
450 }
451 updateOKButtonEnablement();
452 }
453
454 private void updateOKButtonEnablement() {
455 Object[] checked = fFolderViewer.getCheckedElements();
456 Button okButton = getButton(IDialogConstants.OK_ID);
457 if (okButton != null) {
458 okButton.setEnabled(checked.length > 0);
459 }
460 }
461
462 private static String getUnifiedPath(String path) {
463 // Use Path class to remove unnecessary slashes
464 return new Path(path).removeTrailingSeparator().toString();
465 }
466 }
This page took 0.057206 seconds and 5 git commands to generate.