This is an automated email from the git hooks/post-receive script. New commit to branch feature/sync in repository jtimer. See https://gitlab.nuiton.org/chorem/jtimer.git commit df3c9e77661a1bb9162076e99fd477eac10aa4be Author: Freyj <aerandil@gmail.com> Date: Wed Apr 27 15:27:11 2016 +0200 Synchronising URL and time of last synchronisation added to Timer Task Display of synchronising URL added to TimerTaskEditor +events to deal with editing of synchronising URL Parsing and saving to [taskname.task].sync file of synchronising information --- .../org/chorem/jtimer/data/CommonVetoable.java | 8 ++ .../org/chorem/jtimer/data/DataEventListener.java | 8 ++ .../org/chorem/jtimer/data/TimerDataManager.java | 16 +++ .../jtimer/data/VetoableDataEventListener.java | 6 + .../java/org/chorem/jtimer/entities/TimerTask.java | 38 +++++- .../chorem/jtimer/io/GTimerIncrementalSaver.java | 130 +++++++++++++++++++++ src/main/java/org/chorem/jtimer/ui/StatusBar.java | 7 ++ .../java/org/chorem/jtimer/ui/TimerTaskEditor.java | 82 ++++++++++++- .../chorem/jtimer/ui/systray/SystrayManager.java | 7 ++ .../jtimer/ui/treetable/ProjectsAndTasksModel.java | 7 ++ .../ProjectsAndTasksRunningCellRenderer.java | 7 ++ .../jtimer/ui/resources/TimerTaskEditor.properties | 2 + .../ui/resources/TimerTaskEditor_fr.properties | 2 + 13 files changed, 313 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/chorem/jtimer/data/CommonVetoable.java b/src/main/java/org/chorem/jtimer/data/CommonVetoable.java index 0e6914f..493d4f5 100644 --- a/src/main/java/org/chorem/jtimer/data/CommonVetoable.java +++ b/src/main/java/org/chorem/jtimer/data/CommonVetoable.java @@ -265,4 +265,12 @@ public class CommonVetoable implements VetoableDataEventListener { } } + /* + * {@inheritDoc} + */ + @Override + public void checkSetTaskURL(TimerTask task, String newURL) { + + } + } diff --git a/src/main/java/org/chorem/jtimer/data/DataEventListener.java b/src/main/java/org/chorem/jtimer/data/DataEventListener.java index 272dcfd..88a9daf 100644 --- a/src/main/java/org/chorem/jtimer/data/DataEventListener.java +++ b/src/main/java/org/chorem/jtimer/data/DataEventListener.java @@ -157,4 +157,12 @@ public interface DataEventListener extends EventListener { * @param projects projects collection */ void dataLoaded(Collection<TimerProject> projects); + + /** + * Task url changed + * @param task task with url change + * @param newURL new URl to change + */ + void modifyTaskURL(TimerTask task, String newURL); } + diff --git a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java index 1afccff..ef25de9 100644 --- a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java +++ b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java @@ -410,6 +410,22 @@ public class TimerDataManager { } /** + * Edit Task URL + */ + public void editTaskURL(TimerTask task, String newURL) { + + TimerTask newTask = task.clone(); + newTask.setSynchronisingURL(newURL); + for (VetoableDataEventListener vetoableDataEventListener : vetoableDataEventListeners) { + vetoableDataEventListener.checkSetTaskURL(task, newURL); + } + task.setSynchronisingURL(newURL); + // send notification + for (DataEventListener dataEventListener : dataEventListeners) { + dataEventListener.modifyTaskURL(task, newURL); + } + } + /** * Move task. * * @param destination task to move to diff --git a/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java b/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java index 0f8a9da..0bd7224 100644 --- a/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java +++ b/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java @@ -124,4 +124,10 @@ public interface VetoableDataEventListener extends EventListener { */ void checkMergeTasks(TimerTask destinationTask, List<TimerTask> otherTasks); + /** + * Check sync URL ofr a task + * @param task task to change the url + * @param newURL the new URL + */ + void checkSetTaskURL(TimerTask task, String newURL); } diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTask.java b/src/main/java/org/chorem/jtimer/entities/TimerTask.java index fd3e443..fe59e5c 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTask.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTask.java @@ -23,6 +23,7 @@ package org.chorem.jtimer.entities; import java.io.Serializable; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -47,7 +48,7 @@ public class TimerTask implements Cloneable, /** serialVersionUID */ private static final long serialVersionUID = -7590755569706702695L; - /** Task uuid used to managed task equality. */ + /** Task uuid used to managed task equality. */s - protected String uuid = UUID.randomUUID().toString(); /** Task number. */ @@ -89,6 +90,15 @@ public class TimerTask implements Cloneable, protected List<TimerAlert> alerts; /** + * Last synchronisation date + */ + protected LocalDateTime lastSync; + + /** + * URL to synchronise task + */ + protected String synchronisingURL; + /** * Constructor. */ public TimerTask() { @@ -219,6 +229,32 @@ public class TimerTask implements Cloneable, } /** + * Get task's last sync + * @return the date of the sync + */ + public LocalDateTime getLastSync() { return lastSync; } + + /** + * Sets task's last sync + * @param syncDate : date of the sync + */ + public void setLastSync(LocalDateTime syncDate) { + this.lastSync = syncDate; + } + /** + * Get task's sync URL + * @return the URL + */ + public String getSynchronisingURL() { return synchronisingURL; } + + /** + * Sets task's sync URL + * @param synchronisingURL : the sync URL + */ + public void setSynchronisingURL(String synchronisingURL) { + this.synchronisingURL = synchronisingURL; + } + /** * Add task's subtask. * * Also add parent reference. diff --git a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java index 7d57ad5..0b5e741 100644 --- a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java +++ b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java @@ -43,6 +43,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -115,6 +116,9 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, /** Extension alert. */ protected static final String GTIMER_ALERT_EXTENSION = "alert"; + /** Extension sync. */ + protected static final String GTIMER_SYNC_EXTENSION = "sync"; + /** Empty gtimer project name. */ protected static final String GTIMER_EMPTY_PROJECT_NAME = "No project"; @@ -359,6 +363,7 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, parseAnnotations(task); parseAlerts(task); + parseSyncURL(task); } } catch (NumberFormatException e) { if (log.isWarnEnabled()) { @@ -598,6 +603,61 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } } + /** Try and find sync information and load it + * + * @param task task to load sync info + */ + protected void parseSyncURL(TimerTask task) throws IOException { + int taskNumber = task.getNumber(); + File syncTaskFile = new File(dataSaveDirectory + File.separator + taskNumber +"."+ GTIMER_TASK_EXTENSION +"."+ GTIMER_SYNC_EXTENSION); + + if (syncTaskFile.exists()) { + if (log.isDebugEnabled()) { + log.debug("Synchronisation information found for task " + task.getName()); + } + + try (BufferedReader parseIn = new BufferedReader(new FileReader(syncTaskFile))) { + + // first line : "format: 1.2" + String line = parseIn.readLine(); + while ((line = parseIn.readLine()) != null) { + line = line.trim(); + + if (!line.isEmpty()) { + String syncType = line.substring(0, line.indexOf(' ')); + String syncInfo = line.substring(line.indexOf(' ') +1, line.length()); + + + try { + if (syncType.equals("SyncURL:")) { + task.setSynchronisingURL(syncInfo); + + } + else if (syncType.equals("LastSync:")) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"); + LocalDateTime date = LocalDateTime.parse(syncInfo, formatter); + task.setLastSync(date); + } + else { + if (log.isWarnEnabled()) { + log.warn("Unknown synchronisation type " + syncType); + } + } + }catch (DateTimeParseException e) { + if (log.isErrorEnabled()) { + log.error("Can't parse " + syncInfo + + " as synchronisation date"); + } + + } + + } + } + } + } + + } + /** * Find task alert and load it. * @@ -1079,6 +1139,54 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } } + /** + * Save synchronisation info for a task. + * + * @param task task to save annotation + */ + protected void saveSynchronisationInfo(TimerTask task) { + + + int taskNumber = task.getNumber(); + + File synchronisationTaskFile = new File(dataSaveDirectory + File.separator + + taskNumber + "." + GTIMER_TASK_EXTENSION + "." + GTIMER_SYNC_EXTENSION); + + if (task.getSynchronisingURL() != null) { + File backupfile = null; + try (Writer out = new OutputStreamWriter(new FileOutputStream(synchronisationTaskFile), "ISO-8859-1")) { + + // first make backup + backupfile = makeBackupFile(synchronisationTaskFile); + out.write("Format: " + GTIMER_FILE_VERSION + "\n"); + + //save URL + String saveURL = task.getSynchronisingURL(); + out.write("SyncURL: " + saveURL + "\n"); + + //save last sync (if there is one) + if (task.getLastSync() !=null) { + String saveLastSync = task.getLastSync().toString(); + out.write("LastSync: " + saveLastSync + "\n"); + + } + + deleteBackupFile(backupfile); + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.debug("Can't save task synchronisation information", e); + } + + // can be null if backup throws the exception + if (backupfile != null) { + restoreBackupFile(backupfile); + } + } + } else { + synchronisationTaskFile.delete(); + } + + } /** * Save task alerts. @@ -1263,6 +1371,14 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, + alertFileToDelete.getPath() + ")"); } } + //and delete sync information file + File syncFileToDelete = new File(dataSaveDirectory + File.separator + fileNumber+ "."+ GTIMER_TASK_EXTENSION + "." + GTIMER_SYNC_EXTENSION); + if (syncFileToDelete.exists()) { + syncFileToDelete.delete(); + if (log.isDebugEnabled()) { + log.debug("Synchronisation file deleted for " + taskOrProject.getName() + "(" + syncFileToDelete.getPath() +")"); + } + } } // second, go recursively on subtasks @@ -1571,4 +1687,18 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, List<TimerTask> otherTasks) { } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, String newURL) { + saveSynchronisationInfo(task); + } + + /* + * {@inheritDoc} + */ + public void checkSetTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/ui/StatusBar.java b/src/main/java/org/chorem/jtimer/ui/StatusBar.java index 99ff3d3..f1fd9ea 100644 --- a/src/main/java/org/chorem/jtimer/ui/StatusBar.java +++ b/src/main/java/org/chorem/jtimer/ui/StatusBar.java @@ -283,4 +283,11 @@ public class StatusBar extends JPanel implements DataEventListener { List<TimerTask> otherTasks) { } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java index 633a5fc..1fc47eb 100644 --- a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java +++ b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java @@ -26,6 +26,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.GridLayout; +import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -48,6 +49,7 @@ import javax.swing.KeyStroke; import javax.swing.ScrollPaneConstants; import javax.swing.SpinnerNumberModel; import javax.swing.SpringLayout; +import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; @@ -91,6 +93,13 @@ public class TimerTaskEditor extends DialogView { protected JSpinner spinnerS; /** annotation textarea */ protected JTextArea annotationText; + + /** task sync URL */ + protected JTextField synchronizeURL; + + /** change listener on sync URl */ + protected DocumentListener URLChangeListener; + /** change listener on spinners */ protected ChangeListener spinnerListener; @@ -114,6 +123,9 @@ public class TimerTaskEditor extends DialogView { /** did the modified annotation ? */ protected boolean isAnnotationChanged; + /** was the url modified ?*/ + protected boolean isURLChanged; + /** * days modified: You can modify any number of days before you apply changes, * this set keep track of days modified (for time, annotations or title). @@ -219,17 +231,59 @@ public class TimerTaskEditor extends DialogView { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - // text change listener on annotationTextArea and titleTextField + // text change listener on annotationTextArea, titleTextField and SyncURLTextField titleChangeListener = new TextChangeListener(); annotationChangeListener = new TextChangeListener(); + URLChangeListener = new TextChangeListener(); + + panel.add(createTitlePanel(), BorderLayout.NORTH); + panel.add(createJXMonthView(), BorderLayout.CENTER); + panel.add(createEditionPanel(), BorderLayout.SOUTH); + + return panel; + } + + /** + * Create title panel + * @return title panel + */ + protected JPanel createTitlePanel(){ + + SpringLayout layout = new SpringLayout(); + JPanel panel = new JPanel(layout); - // task title + // task title and listener titleText = new JTextField("", 20); // prevent too long task names titleText.getDocument().addDocumentListener(titleChangeListener); + // task syncronizeURL and listener + synchronizeURL = new JTextField("",20); + synchronizeURL.getDocument().addDocumentListener(URLChangeListener); + //labels for title and url + JLabel titleLabel = new JLabel(getResourceMap().getString("label.title.text")); + JLabel URLLabel = new JLabel(getResourceMap().getString("label.syncURL.text")); + + panel.add(titleLabel); + panel.add(titleText); + panel.add(synchronizeURL); + panel.add(URLLabel); + + JLabel largerLabel = titleLabel.getText().length() < URLLabel.getText().length() ? URLLabel : titleLabel; + + layout.putConstraint(SpringLayout.NORTH, titleLabel, 2, SpringLayout.NORTH, panel); + layout.putConstraint(SpringLayout.WEST, titleLabel, 2, SpringLayout.WEST, panel); + + layout.putConstraint(SpringLayout.NORTH, titleText, 2, SpringLayout.NORTH, panel); + layout.putConstraint(SpringLayout.WEST, titleText, 2, SpringLayout.EAST, largerLabel); + + layout.putConstraint(SpringLayout.NORTH, URLLabel, 2, SpringLayout.SOUTH, titleText); + layout.putConstraint(SpringLayout.WEST, URLLabel, 2, SpringLayout.WEST, largerLabel); + + layout.putConstraint(SpringLayout.NORTH, synchronizeURL, 2, SpringLayout.SOUTH, titleText); + layout.putConstraint(SpringLayout.WEST, synchronizeURL, 2, SpringLayout.EAST, largerLabel); + + layout.putConstraint(SpringLayout.SOUTH, panel, 2, SpringLayout.SOUTH, synchronizeURL); + layout.putConstraint(SpringLayout.EAST, panel, 2, SpringLayout.EAST, synchronizeURL); - panel.add(titleText, BorderLayout.NORTH); - panel.add(createJXMonthView(), BorderLayout.CENTER); - panel.add(createEditionPanel(), BorderLayout.SOUTH); return panel; } @@ -522,6 +576,11 @@ public class TimerTaskEditor extends DialogView { titleText.setCaretPosition(0); titleText.getDocument().addDocumentListener(titleChangeListener); + //URL + synchronizeURL.getDocument().removeDocumentListener(URLChangeListener); + synchronizeURL.setText(cloneTask.getSynchronisingURL()); + synchronizeURL.getDocument().addDocumentListener(URLChangeListener); + } /** @@ -534,6 +593,8 @@ public class TimerTaskEditor extends DialogView { isTitleChanged = true; } else if (issuer == annotationChangeListener) { isAnnotationChanged = true; + } else if (issuer == URLChangeListener) { + isURLChanged = true; } updateTask(); } @@ -572,6 +633,11 @@ public class TimerTaskEditor extends DialogView { cloneTask.setName(titleText.getText()); } + // sync URL + if (isURLChanged) { + cloneTask.setSynchronisingURL(synchronizeURL.getText()); + } + dateChanged.add(getSelectedDay().getTime()); setDataChanged(true); @@ -605,7 +671,11 @@ public class TimerTaskEditor extends DialogView { if (isTitleChanged) { dataManager.editTask(task, cloneTask.getName()); } - + // url + if (isURLChanged) { + dataManager.editTaskURL(task, cloneTask.getSynchronisingURL()); + } + for (Date date : dateChanged) { if (log.isDebugEnabled()) { log.debug("Applying changes on: " + date); diff --git a/src/main/java/org/chorem/jtimer/ui/systray/SystrayManager.java b/src/main/java/org/chorem/jtimer/ui/systray/SystrayManager.java index 4a5b5f3..030bc6c 100644 --- a/src/main/java/org/chorem/jtimer/ui/systray/SystrayManager.java +++ b/src/main/java/org/chorem/jtimer/ui/systray/SystrayManager.java @@ -553,4 +553,11 @@ public class SystrayManager implements ActionListener, DataEventListener, public void windowOpened(WindowEvent e) { } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java index e2aeeff..668a22f 100644 --- a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java +++ b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java @@ -548,4 +548,11 @@ public class ProjectsAndTasksModel extends AbstractTreeTableModel implements public void preMergeTasks(TimerTask destinationTask, List<TimerTask> otherTasks) { } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksRunningCellRenderer.java b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksRunningCellRenderer.java index 1ee3b36..9df4a48 100644 --- a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksRunningCellRenderer.java +++ b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksRunningCellRenderer.java @@ -300,4 +300,11 @@ public class ProjectsAndTasksRunningCellRenderer extends ProjectsAndTasksCellRen public void setAnnotation(TimerTask task, Date date, String annotation) { } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties index ddf2b8e..027a244 100644 --- a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties +++ b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties @@ -29,3 +29,5 @@ cancel.Action.shortDescription = Revert changes and quit label.time.text = Time: label.annotation.text = Annotation: +label.syncURL.text = URL: +label.title.text = Title: \ No newline at end of file diff --git a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties index 6cd6223..9f6b39f 100644 --- a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties +++ b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties @@ -29,3 +29,5 @@ cancel.Action.shortDescription = Annuler et quitter label.time.text = Temps: label.annotation.text = Note: +label.syncURL.text = URL: +label.title.text = Titre: \ No newline at end of file -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.