Working on outline metadata
This commit is contained in:
parent
c37b01eb92
commit
71776fa54b
4 changed files with 220 additions and 17 deletions
|
@ -16,12 +16,21 @@ import com.sun.star.beans.UnknownPropertyException;
|
||||||
import com.sun.star.beans.XPropertyContainer;
|
import com.sun.star.beans.XPropertyContainer;
|
||||||
import com.sun.star.beans.XPropertySet;
|
import com.sun.star.beans.XPropertySet;
|
||||||
import com.sun.star.beans.XPropertySetInfo;
|
import com.sun.star.beans.XPropertySetInfo;
|
||||||
|
import com.sun.star.container.NoSuchElementException;
|
||||||
|
import com.sun.star.container.XEnumeration;
|
||||||
|
import com.sun.star.container.XEnumerationAccess;
|
||||||
import com.sun.star.document.XDocumentProperties;
|
import com.sun.star.document.XDocumentProperties;
|
||||||
import com.sun.star.document.XDocumentPropertiesSupplier;
|
import com.sun.star.document.XDocumentPropertiesSupplier;
|
||||||
import com.sun.star.frame.XDesktop;
|
import com.sun.star.frame.XDesktop;
|
||||||
import com.sun.star.lang.IllegalArgumentException;
|
import com.sun.star.lang.IllegalArgumentException;
|
||||||
|
import com.sun.star.lang.WrappedTargetException;
|
||||||
import com.sun.star.lang.XComponent;
|
import com.sun.star.lang.XComponent;
|
||||||
import com.sun.star.lang.XMultiComponentFactory;
|
import com.sun.star.lang.XMultiComponentFactory;
|
||||||
|
import com.sun.star.lang.XServiceInfo;
|
||||||
|
import com.sun.star.text.XText;
|
||||||
|
import com.sun.star.text.XTextContent;
|
||||||
|
import com.sun.star.text.XTextDocument;
|
||||||
|
import com.sun.star.text.XTextRange;
|
||||||
import com.sun.star.uno.UnoRuntime;
|
import com.sun.star.uno.UnoRuntime;
|
||||||
import com.sun.star.uno.XComponentContext;
|
import com.sun.star.uno.XComponentContext;
|
||||||
|
|
||||||
|
@ -40,6 +49,7 @@ public class Document {
|
||||||
private XComponent currentDocument;
|
private XComponent currentDocument;
|
||||||
private XDocumentProperties documentProperties;
|
private XDocumentProperties documentProperties;
|
||||||
private XDocumentPropertiesSupplier documentPropertiesSupplier;
|
private XDocumentPropertiesSupplier documentPropertiesSupplier;
|
||||||
|
private XText text = null;
|
||||||
|
|
||||||
public Document(XComponentContext componentContext) {
|
public Document(XComponentContext componentContext) {
|
||||||
context = componentContext;
|
context = componentContext;
|
||||||
|
@ -48,6 +58,8 @@ public class Document {
|
||||||
Object oDesktop = multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", context);
|
Object oDesktop = multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", context);
|
||||||
xDesktop = UnoRuntime.queryInterface(XDesktop.class, oDesktop);
|
xDesktop = UnoRuntime.queryInterface(XDesktop.class, oDesktop);
|
||||||
getCurrentDocument();
|
getCurrentDocument();
|
||||||
|
getDocumentText();
|
||||||
|
updateChapterMetadata();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("xDesktop inaccessible. Can not proceed.");
|
System.out.println("xDesktop inaccessible. Can not proceed.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -56,6 +68,51 @@ public class Document {
|
||||||
//logProperties();
|
//logProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getDocumentText() {
|
||||||
|
XTextDocument textDocument = UnoRuntime.queryInterface(XTextDocument.class,currentDocument);
|
||||||
|
text = textDocument.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChapterMetadata() {
|
||||||
|
findAllChapters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findAllChapters() {
|
||||||
|
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, text);
|
||||||
|
XEnumeration textEnum = enumAccess.createEnumeration();
|
||||||
|
while (textEnum.hasMoreElements()) {
|
||||||
|
try {
|
||||||
|
XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement());
|
||||||
|
if(isSupported(textContent, "com.sun.star.text.TextTable")) {
|
||||||
|
//TODO: Go over table to check for outline elements
|
||||||
|
} else
|
||||||
|
if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) {
|
||||||
|
Short outlineLevel = null;
|
||||||
|
XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, textContent);
|
||||||
|
try {
|
||||||
|
outlineLevel = (Short) properties.getPropertyValue("OutlineLevel");
|
||||||
|
} catch (UnknownPropertyException e) {
|
||||||
|
System.out.println("Shouldn't be here!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (outlineLevel != null && outlineLevel > 0) {
|
||||||
|
XTextRange textRange = textContent.getAnchor();
|
||||||
|
String name = textRange.getString();
|
||||||
|
System.out.println("Outline element found! " + name);
|
||||||
|
new OutlineElement(textRange);
|
||||||
|
//TODO: outline element found. Save outline element name and anchor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (WrappedTargetException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void getCurrentDocument() throws MetadataInaccessableException {
|
private void getCurrentDocument() throws MetadataInaccessableException {
|
||||||
currentDocument = xDesktop.getCurrentComponent();
|
currentDocument = xDesktop.getCurrentComponent();
|
||||||
if (currentDocument == null) {
|
if (currentDocument == null) {
|
||||||
|
@ -231,6 +288,14 @@ public class Document {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSupported(Object object, String service) {
|
||||||
|
XServiceInfo info = UnoRuntime.queryInterface(XServiceInfo.class, object);
|
||||||
|
if (info == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return info.supportsService(service);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package pro.litvinovg.libreoffice.metadata;
|
||||||
|
|
||||||
|
import static pro.litvinovg.libreoffice.metadata.MetadataElement.METADATA_PREFIX;
|
||||||
|
|
||||||
|
public class MetadataElement {
|
||||||
|
|
||||||
|
public static final String METADATA_START = "## Metadata Editor extension. Outline metadata folllows: ";
|
||||||
|
public static String METADATA_PREFIX = "##";
|
||||||
|
public static String METADATA_END = "## Metadata Editor extension. Outline metadata ends.";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public MetadataElement(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
public MetadataElement(String encodedPair) {
|
||||||
|
//TODO: Parse encoded pair
|
||||||
|
this.name = "";
|
||||||
|
this.value = "";
|
||||||
|
}
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public static boolean isValidMetadataString(String cursorContent) {
|
||||||
|
if (!cursorContent.startsWith(METADATA_PREFIX) ||
|
||||||
|
cursorContent.equals(METADATA_START) ||
|
||||||
|
cursorContent.equals(METADATA_END)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String data = cursorContent.substring(cursorContent.lastIndexOf(METADATA_PREFIX));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package pro.litvinovg.libreoffice.metadata;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.sun.star.text.XParagraphCursor;
|
||||||
|
import com.sun.star.text.XText;
|
||||||
|
import com.sun.star.text.XTextCursor;
|
||||||
|
import com.sun.star.text.XTextRange;
|
||||||
|
import com.sun.star.uno.UnoRuntime;
|
||||||
|
import static pro.litvinovg.libreoffice.metadata.MetadataElement.*;
|
||||||
|
|
||||||
|
public class OutlineElement {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private ArrayList<MetadataElement> metadataElements = null;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private XTextRange textRange;
|
||||||
|
private boolean hasMetadataStorage = false;
|
||||||
|
private XTextRange metadataTextRange = null;
|
||||||
|
|
||||||
|
public OutlineElement(XTextRange textRange) {
|
||||||
|
this.textRange = textRange;
|
||||||
|
this.name = textRange.getString();
|
||||||
|
getMetadataStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getMetadataStorage() {
|
||||||
|
XText curText = textRange.getText();
|
||||||
|
XTextCursor cursor = curText.createTextCursorByRange(textRange);
|
||||||
|
XParagraphCursor paraCursor = UnoRuntime.queryInterface(XParagraphCursor.class, cursor);
|
||||||
|
readMetadataBody(paraCursor);
|
||||||
|
if (metadataElements == null) {
|
||||||
|
metadataElements = new ArrayList<MetadataElement>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readMetadataBody(XParagraphCursor paraCursor) {
|
||||||
|
String cursorContent = getNextParaContent(paraCursor);
|
||||||
|
|
||||||
|
if (! cursorContent.equals(METADATA_START)){
|
||||||
|
System.out.println("Para doesn't have metadata start header" + cursorContent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArrayList<MetadataElement> metadataTempElements = new ArrayList<MetadataElement>();
|
||||||
|
cursorContent = getNextParaContent(paraCursor);
|
||||||
|
while (cursorContent.startsWith(METADATA_PREFIX)) {
|
||||||
|
if (cursorContent.equals(METADATA_END)) {
|
||||||
|
metadataElements = metadataTempElements;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MetadataElement.isValidMetadataString(cursorContent)) {
|
||||||
|
metadataTempElements.add(new MetadataElement(cursorContent));
|
||||||
|
} else {
|
||||||
|
//If reading fails exit immediately
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cursorContent = getNextParaContent(paraCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNextParaContent(XParagraphCursor paraCursor) {
|
||||||
|
boolean moved = paraCursor.gotoNextParagraph(false);
|
||||||
|
if (moved == false) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
moved = paraCursor.gotoEndOfParagraph(true);
|
||||||
|
if (moved == false) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String cursorContent = paraCursor.getString();
|
||||||
|
return cursorContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ import java.awt.event.FocusAdapter;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.LayoutStyle.ComponentPlacement;
|
import javax.swing.LayoutStyle.ComponentPlacement;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
public class EditorGUI extends JFrame {
|
public class EditorGUI extends JFrame {
|
||||||
//Components
|
//Components
|
||||||
|
@ -190,6 +191,7 @@ public class EditorGUI extends JFrame {
|
||||||
tableDocProps.setModel(docPropertiesModel);
|
tableDocProps.setModel(docPropertiesModel);
|
||||||
|
|
||||||
tableDocCustomProps = new JTable();
|
tableDocCustomProps = new JTable();
|
||||||
|
tableDocCustomProps.setColumnSelectionAllowed(true);
|
||||||
tableDocCustomProps.putClientProperty("terminateEditOnFocusLost", true);
|
tableDocCustomProps.putClientProperty("terminateEditOnFocusLost", true);
|
||||||
|
|
||||||
tableDocCustomProps.setSurrendersFocusOnKeystroke(true);
|
tableDocCustomProps.setSurrendersFocusOnKeystroke(true);
|
||||||
|
@ -199,32 +201,49 @@ public class EditorGUI extends JFrame {
|
||||||
|
|
||||||
btnNewButton = new JButton("Save");
|
btnNewButton = new JButton("Save");
|
||||||
|
|
||||||
|
JLabel labelDocProperties = new JLabel("Основные метаданные");
|
||||||
|
|
||||||
|
JLabel labelDocCustomProperties = new JLabel("Дополнительные метаданные");
|
||||||
|
|
||||||
GroupLayout gl_panel = new GroupLayout(panel);
|
GroupLayout gl_panel = new GroupLayout(panel);
|
||||||
gl_panel.setHorizontalGroup(
|
gl_panel.setHorizontalGroup(
|
||||||
gl_panel.createParallelGroup(Alignment.LEADING)
|
gl_panel.createParallelGroup(Alignment.TRAILING)
|
||||||
.addGroup(Alignment.TRAILING, gl_panel.createSequentialGroup()
|
.addGroup(Alignment.LEADING, gl_panel.createSequentialGroup()
|
||||||
.addContainerGap(838, Short.MAX_VALUE)
|
.addGap(378)
|
||||||
.addComponent(btnNewButton)
|
.addComponent(labelDocProperties, GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)
|
||||||
.addGap(58))
|
.addGap(421))
|
||||||
.addGroup(gl_panel.createSequentialGroup()
|
.addGroup(Alignment.LEADING, gl_panel.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
|
||||||
|
.addGroup(gl_panel.createSequentialGroup()
|
||||||
|
.addComponent(tableDocProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE)
|
||||||
|
.addContainerGap())
|
||||||
|
.addGroup(Alignment.TRAILING, gl_panel.createSequentialGroup()
|
||||||
|
.addComponent(btnNewButton)
|
||||||
|
.addGap(294))))
|
||||||
|
.addGroup(Alignment.LEADING, gl_panel.createSequentialGroup()
|
||||||
|
.addGap(350)
|
||||||
|
.addComponent(labelDocCustomProperties, GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE)
|
||||||
|
.addGap(381))
|
||||||
|
.addGroup(Alignment.LEADING, gl_panel.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(tableDocCustomProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE)
|
.addComponent(tableDocCustomProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE)
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
.addGroup(gl_panel.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
|
||||||
.addComponent(tableDocProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE)
|
|
||||||
.addContainerGap())
|
|
||||||
);
|
);
|
||||||
gl_panel.setVerticalGroup(
|
gl_panel.setVerticalGroup(
|
||||||
gl_panel.createParallelGroup(Alignment.LEADING)
|
gl_panel.createParallelGroup(Alignment.LEADING)
|
||||||
.addGroup(gl_panel.createSequentialGroup()
|
.addGroup(gl_panel.createSequentialGroup()
|
||||||
.addGap(86)
|
.addGap(53)
|
||||||
|
.addComponent(labelDocProperties)
|
||||||
|
.addGap(18)
|
||||||
.addComponent(tableDocProps, GroupLayout.PREFERRED_SIZE, 81, GroupLayout.PREFERRED_SIZE)
|
.addComponent(tableDocProps, GroupLayout.PREFERRED_SIZE, 81, GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(ComponentPlacement.UNRELATED)
|
.addPreferredGap(ComponentPlacement.UNRELATED)
|
||||||
.addComponent(tableDocCustomProps, GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE)
|
.addComponent(labelDocCustomProperties, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(81)
|
.addGap(18)
|
||||||
|
.addComponent(tableDocCustomProps, GroupLayout.PREFERRED_SIZE, 322, GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(ComponentPlacement.RELATED, 90, Short.MAX_VALUE)
|
||||||
.addComponent(btnNewButton)
|
.addComponent(btnNewButton)
|
||||||
.addGap(27))
|
.addGap(31))
|
||||||
);
|
);
|
||||||
|
|
||||||
JPopupMenu popupMenu = new JPopupMenu();
|
JPopupMenu popupMenu = new JPopupMenu();
|
||||||
|
@ -241,9 +260,6 @@ public class EditorGUI extends JFrame {
|
||||||
|
|
||||||
JMenu mnFile = new JMenu("Файл");
|
JMenu mnFile = new JMenu("Файл");
|
||||||
menuBar.add(mnFile);
|
menuBar.add(mnFile);
|
||||||
|
|
||||||
JMenu mnEdit = new JMenu("Edit");
|
|
||||||
menuBar.add(mnEdit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDocPropsModel() {
|
private void createDocPropsModel() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue