konfigurace, parser CLI parametrů v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 15 Dec 2023 01:36:17 +0100
branchv_0
changeset 311ab5ce94a146
parent 30 d511e4bf7d8f
child 32 ca064ecf3ca3
konfigurace, parser CLI parametrů
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParser.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParserException.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Konfigurace.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java
java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParser.java	Fri Dec 15 01:36:17 2023 +0100
     1.3 @@ -0,0 +1,173 @@
     1.4 +/**
     1.5 + * Rozšířené atributy – program na správu rozšířených atributů souborů
     1.6 + * Copyright © 2023 František Kučera (frantovo.cz)
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, either version 3 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.19 + */
    1.20 +package cz.frantovo.rozsireneatributy;
    1.21 +
    1.22 +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu;
    1.23 +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceHodnoty;
    1.24 +import java.io.File;
    1.25 +import java.util.Arrays;
    1.26 +import java.util.Collection;
    1.27 +import java.util.ResourceBundle;
    1.28 +
    1.29 +/**
    1.30 + * Converts command line arguments from String array to object. Checks basic
    1.31 + * constraints (if only supported options are used and if they have correct
    1.32 + * number of parameters)
    1.33 + *
    1.34 + * @author Ing. František Kučera (frantovo.cz)
    1.35 + */
    1.36 +public class CLIParser {
    1.37 +
    1.38 +	private static final ResourceBundle překlady = ResourceBundle
    1.39 +		.getBundle(Atribut.class.getPackageName() + ".Překlady");
    1.40 +
    1.41 +	public Konfigurace parsujParametry(String[] parametry)
    1.42 +		throws CLIParserException {
    1.43 +		Konfigurace k = new Konfigurace();
    1.44 +
    1.45 +		for (int i = 0; i < parametry.length; i++) {
    1.46 +			String parametr = parametry[i];
    1.47 +
    1.48 +			boolean odpovídá = false;
    1.49 +
    1.50 +			for (Token t : Token.values()) {
    1.51 +				if (t.odpovídá(parametr)) {
    1.52 +					int parsedArgs = t.parsuj(parametry, i, k);
    1.53 +					i = i + parsedArgs;
    1.54 +					odpovídá = true;
    1.55 +				}
    1.56 +			}
    1.57 +
    1.58 +			if (!odpovídá) {
    1.59 +				throw new CLIParserException(
    1.60 +					překlady.getString("chyba.cli.neznámýParametr") + parametr);
    1.61 +			}
    1.62 +		}
    1.63 +
    1.64 +		if (k.getSoubor() == null)
    1.65 +			throw new CLIParserException(
    1.66 +					překlady.getString("chyba.cli.chybíSoubor"));
    1.67 +		
    1.68 +		return k;
    1.69 +	}
    1.70 +
    1.71 +	private static String načtiDalší(String[] parametry, int index)
    1.72 +		throws CLIParserException {
    1.73 +		if (index < parametry.length) {
    1.74 +			return parametry[index];
    1.75 +		} else {
    1.76 +			throw new CLIParserException("Expecting value for option: "
    1.77 +				+ parametry[index - 1]);
    1.78 +		}
    1.79 +	}
    1.80 +
    1.81 +	private static boolean načtiDalšíBoolean(String[] parametry, int index)
    1.82 +		throws CLIParserException {
    1.83 +		String s = načtiDalší(parametry, index);
    1.84 +		switch (s) {
    1.85 +			case "true":
    1.86 +			case "ano":
    1.87 +				return true;
    1.88 +			case "false":
    1.89 +			case "ne":
    1.90 +				return false;
    1.91 +			default:
    1.92 +				throw new CLIParserException("Neplatná logická hodnota: " + s);
    1.93 +		}
    1.94 +	}
    1.95 +
    1.96 +	private static enum Token {
    1.97 +
    1.98 +		SOUBOR("--soubor", "--file") {
    1.99 +			@Override
   1.100 +			public int parsuj(String[] parametry, int index, Konfigurace k)
   1.101 +				throws CLIParserException {
   1.102 +				int originalIndex = index;
   1.103 +				k.setSoubor(new File(načtiDalší(parametry, ++index)));
   1.104 +				return index - originalIndex;
   1.105 +			}
   1.106 +		},
   1.107 +		POVINNÉ_ZAMYKÁNÍ("--povinné-zamykání", "--mandatory-locking") {
   1.108 +			@Override
   1.109 +			public int parsuj(String[] parametry, int index, Konfigurace k)
   1.110 +				throws CLIParserException {
   1.111 +				int originalIndex = index;
   1.112 +				k.setPovinnéZamykání(načtiDalšíBoolean(parametry, ++index));
   1.113 +				return index - originalIndex;
   1.114 +			}
   1.115 +		},
   1.116 +		DEFINICE_ATRIBUTU("--definice-atributu", "--attribute-definition") {
   1.117 +			@Override
   1.118 +			public int parsuj(String[] parametry, int index, Konfigurace k)
   1.119 +				throws CLIParserException {
   1.120 +				int originalIndex = index;
   1.121 +				String název = načtiDalší(parametry, ++index);
   1.122 +				String popis = načtiDalší(parametry, ++index);
   1.123 +				k.addAtribut(new DefiniceAtributu(název, popis));
   1.124 +				return index - originalIndex;
   1.125 +			}
   1.126 +		},
   1.127 +		HODNOTA_ATRIBUTU("--hodnota", "--value") {
   1.128 +			@Override
   1.129 +			public int parsuj(String[] parametry, int index, Konfigurace k)
   1.130 +				throws CLIParserException {
   1.131 +				int originalIndex = index;
   1.132 +				String hodnota = načtiDalší(parametry, ++index);
   1.133 +				String popis = načtiDalší(parametry, ++index);
   1.134 +
   1.135 +				if (k.getAtributy().isEmpty())
   1.136 +					throw new CLIParserException(
   1.137 +						překlady.getString("chyba.cli.chybíDefiniceAtributu"));
   1.138 +
   1.139 +				k.getAtributy()
   1.140 +					.get(k.getAtributy().size() - 1)
   1.141 +					.addHodnota(new DefiniceHodnoty(hodnota, popis));
   1.142 +
   1.143 +				return index - originalIndex;
   1.144 +			}
   1.145 +		};
   1.146 +
   1.147 +		private final Collection<String> parametry;
   1.148 +
   1.149 +		private Token(String... parametry) {
   1.150 +			this.parametry = Arrays.asList(parametry);
   1.151 +		}
   1.152 +
   1.153 +		/**
   1.154 +		 * @param parametr e.g. „--input-file“
   1.155 +		 * @return whether option is this token
   1.156 +		 */
   1.157 +		public boolean odpovídá(String parametr) {
   1.158 +			return parametry.contains(parametr);
   1.159 +		}
   1.160 +
   1.161 +		/**
   1.162 +		 * Parse String arguments and fill values into the options object.
   1.163 +		 *
   1.164 +		 * @param parametry CLI arguments
   1.165 +		 * @param index index of the option matched by this token, like
   1.166 +		 * „--input-file“
   1.167 +		 * @param k object to be filled
   1.168 +		 * @return number of parsed arguments – if option has no arguments (just
   1.169 +		 * boolean flag), return 0, otherwise return positive integer: number of
   1.170 +		 * eaten arguments.
   1.171 +		 * @throws CLIParserException
   1.172 +		 */
   1.173 +		public abstract int parsuj(String[] parametry, int index, Konfigurace k)
   1.174 +			throws CLIParserException;
   1.175 +	}
   1.176 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParserException.java	Fri Dec 15 01:36:17 2023 +0100
     2.3 @@ -0,0 +1,39 @@
     2.4 +/**
     2.5 + * Rozšířené atributy – program na správu rozšířených atributů souborů
     2.6 + * Copyright © 2023 František Kučera (frantovo.cz)
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, either version 3 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    2.19 + */
    2.20 +package cz.frantovo.rozsireneatributy;
    2.21 +
    2.22 +/**
    2.23 + *
    2.24 + * @author Ing. František Kučera (frantovo.cz)
    2.25 + */
    2.26 +public class CLIParserException extends Exception {
    2.27 +
    2.28 +	public CLIParserException() {
    2.29 +	}
    2.30 +
    2.31 +	public CLIParserException(String message) {
    2.32 +		super(message);
    2.33 +	}
    2.34 +
    2.35 +	public CLIParserException(Throwable cause) {
    2.36 +		super(cause);
    2.37 +	}
    2.38 +
    2.39 +	public CLIParserException(String message, Throwable cause) {
    2.40 +		super(message, cause);
    2.41 +	}
    2.42 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Konfigurace.java	Fri Dec 15 01:36:17 2023 +0100
     3.3 @@ -0,0 +1,122 @@
     3.4 +/**
     3.5 + * Rozšířené atributy – program na správu rozšířených atributů souborů
     3.6 + * Copyright © 2023 František Kučera (frantovo.cz)
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, either version 3 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    3.19 + */
    3.20 +package cz.frantovo.rozsireneatributy;
    3.21 +
    3.22 +import java.io.File;
    3.23 +import java.util.LinkedList;
    3.24 +import java.util.List;
    3.25 +
    3.26 +/**
    3.27 + * @author Ing. František Kučera (frantovo.cz)
    3.28 + */
    3.29 +public class Konfigurace {
    3.30 +
    3.31 +	public static class DefiniceAtributu {
    3.32 +
    3.33 +		private String název;
    3.34 +		private String popis;
    3.35 +		private final List<DefiniceHodnoty> hodnoty = new LinkedList<>();
    3.36 +
    3.37 +		public DefiniceAtributu(String název, String popis) {
    3.38 +			this.název = název;
    3.39 +			this.popis = popis;
    3.40 +		}
    3.41 +
    3.42 +		public String getNázev() {
    3.43 +			return název;
    3.44 +		}
    3.45 +
    3.46 +		public void setNázev(String název) {
    3.47 +			this.název = název;
    3.48 +		}
    3.49 +
    3.50 +		public String getPopis() {
    3.51 +			return popis;
    3.52 +		}
    3.53 +
    3.54 +		public void setPopis(String popis) {
    3.55 +			this.popis = popis;
    3.56 +		}
    3.57 +
    3.58 +		public List<DefiniceHodnoty> getHodnoty() {
    3.59 +			return hodnoty;
    3.60 +		}
    3.61 +
    3.62 +		public void addHodnota(DefiniceHodnoty hodnota) {
    3.63 +			this.hodnoty.add(hodnota);
    3.64 +		}
    3.65 +
    3.66 +	}
    3.67 +
    3.68 +	public static class DefiniceHodnoty {
    3.69 +
    3.70 +		private String název;
    3.71 +		private String popis;
    3.72 +
    3.73 +		public DefiniceHodnoty(String název, String popis) {
    3.74 +			this.název = název;
    3.75 +			this.popis = popis;
    3.76 +		}
    3.77 +
    3.78 +		public String getNázev() {
    3.79 +			return název;
    3.80 +		}
    3.81 +
    3.82 +		public void setNázev(String název) {
    3.83 +			this.název = název;
    3.84 +		}
    3.85 +
    3.86 +		public String getPopis() {
    3.87 +			return popis;
    3.88 +		}
    3.89 +
    3.90 +		public void setPopis(String popis) {
    3.91 +			this.popis = popis;
    3.92 +		}
    3.93 +	}
    3.94 +
    3.95 +	private File soubor;
    3.96 +
    3.97 +	private boolean povinnéZamykání = false;
    3.98 +
    3.99 +	private final List<DefiniceAtributu> atributy = new LinkedList<>();
   3.100 +
   3.101 +	public File getSoubor() {
   3.102 +		return soubor;
   3.103 +	}
   3.104 +
   3.105 +	public void setSoubor(File soubor) {
   3.106 +		this.soubor = soubor;
   3.107 +	}
   3.108 +
   3.109 +	public boolean isPovinnéZamykání() {
   3.110 +		return povinnéZamykání;
   3.111 +	}
   3.112 +
   3.113 +	public void setPovinnéZamykání(boolean povinnéZamykání) {
   3.114 +		this.povinnéZamykání = povinnéZamykání;
   3.115 +	}
   3.116 +
   3.117 +	public List<DefiniceAtributu> getAtributy() {
   3.118 +		return atributy;
   3.119 +	}
   3.120 +
   3.121 +	public void addAtribut(DefiniceAtributu atribut) {
   3.122 +		this.atributy.add(atribut);
   3.123 +	}
   3.124 +
   3.125 +}
     4.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties	Tue Dec 12 21:19:11 2023 +0100
     4.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties	Fri Dec 15 01:36:17 2023 +0100
     4.3 @@ -1,12 +1,15 @@
     4.4  titulek=Roz\u0161\u00ed\u0159en\u00e9 stributy souboru: {0}
     4.5  
     4.6 +chyba=Chyba:
     4.7  chyba.titulek=Chyba
     4.8  chyba.souborNeexistuje=Soubor neexistuje: {0}
     4.9 -chyba.chyb\u00edParametr=O\u010dek\u00e1v\u00e1m pr\u00e1v\u011b jeden parametr \u2013 n\u00e1zev souboru.
    4.10  chyba.nepoda\u0159iloSeSmazat=Nepoda\u0159ilo se smazat atribut.
    4.11  chyba.nepoda\u0159iloSeNa\u010d\u00edst=Nepoda\u0159ilo se na\u010d\u00edst atributy.
    4.12  chyba.nepoda\u0159iloSeNastavitZ\u00e1mek=Nepoda\u0159ilo se nastavit z\u00e1mek.
    4.13  chyba.lzeZamknoutJenSoubor=Je podporov\u00e1no zamyk\u00e1n\u00ed pouze norm\u00e1ln\u00edch sobour\u016f ne adres\u00e1\u0159\u016f atd.
    4.14 +chyba.cli.nezn\u00e1m\u00fdParametr=Nezn\u00e1m\u00fd parametr: 
    4.15 +chyba.cli.chyb\u00edDefiniceAtributu=Chyb\u00ed definice atributu (hodnota se vztahuje k n\u00ed).
    4.16 +chyba.cli.chyb\u00edSoubor=Nebyl uveden soubor.
    4.17  
    4.18  tabulka.n\u00e1zev=N\u00e1zev
    4.19  tabulka.hodnota=Hodnota
     5.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties	Tue Dec 12 21:19:11 2023 +0100
     5.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties	Fri Dec 15 01:36:17 2023 +0100
     5.3 @@ -1,12 +1,15 @@
     5.4  titulek=Extended Attributes of file: {0}
     5.5  
     5.6 +chyba=Error:
     5.7  chyba.titulek=Error
     5.8  chyba.souborNeexistuje=File does not exist: {0}
     5.9 -chyba.chyb\u00edParametr=Expecting one parameter \u2013 file name.
    5.10  chyba.nepoda\u0159iloSeSmazat=Failed to delete the attribute.
    5.11  chyba.nepoda\u0159iloSeNa\u010d\u00edst=Failed to load attributes.
    5.12  chyba.nepoda\u0159iloSeNastavitZ\u00e1mek=Unable to lock the file.
    5.13  chyba.lzeZamknoutJenSoubor=File locking is supported only for regular files, not for directories or specials.
    5.14 +chyba.cli.nezn\u00e1m\u00fdParametr=Unknown option: 
    5.15 +chyba.cli.chyb\u00edDefiniceAtributu=Missing attribute definition (value is associated with it).
    5.16 +chyba.cli.chyb\u00edSoubor=File name was not specified.
    5.17  
    5.18  tabulka.n\u00e1zev=Name
    5.19  tabulka.hodnota=Value
     6.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java	Tue Dec 12 21:19:11 2023 +0100
     6.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java	Fri Dec 15 01:36:17 2023 +0100
     6.3 @@ -23,7 +23,6 @@
     6.4  import java.awt.event.ActionListener;
     6.5  import java.awt.event.KeyEvent;
     6.6  import java.io.File;
     6.7 -import java.io.IOException;
     6.8  import java.text.MessageFormat;
     6.9  import java.util.ResourceBundle;
    6.10  import java.util.logging.Level;
    6.11 @@ -39,11 +38,11 @@
    6.12   * http://freedesktop.org/wiki/CommonExtendedAttributes
    6.13   * http://download.oracle.com/javase/tutorial/essential/io/fileAttr.html#user
    6.14   * http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html
    6.15 - *   #so-what-is-a-path-really
    6.16 + * #so-what-is-a-path-really
    6.17   *
    6.18 - * $ setfattr -n "user.franta.pozdrav" -v 'Dobrý den!' pokus.txt
    6.19 - * (v javě pak pracujeme s klíči bez předpony „user.“)
    6.20 - * 
    6.21 + * $ setfattr -n "user.franta.pozdrav" -v 'Dobrý den!' pokus.txt (v javě pak
    6.22 + * pracujeme s klíči bez předpony „user.“)
    6.23 + *
    6.24   * @author Ing. František Kučera (frantovo.cz)
    6.25   */
    6.26  public class Startér {
    6.27 @@ -55,18 +54,20 @@
    6.28  
    6.29  	/**
    6.30  	 * @param args název souboru
    6.31 -	 * @throws IOException TODO: ošetřit výjimku
    6.32  	 */
    6.33 -	public static void main(String[] args) throws IOException {
    6.34 +	public static void main(String[] args) {
    6.35  
    6.36 +		try {
    6.37 +			// TODO: načítat konfiguraci i z XML souboru
    6.38 +			CLIParser parser = new CLIParser();
    6.39 +			Konfigurace konfigurace = parser.parsujParametry(args);
    6.40  
    6.41 -		if (args.length == 1 && args[0].length() > 0) {
    6.42 -			File soubor = new File(args[0]);
    6.43 +			File soubor = konfigurace.getSoubor();
    6.44  
    6.45  			if (soubor.exists()) {
    6.46  				log.log(Level.INFO, "Pracuji se souborem: {0}", soubor);
    6.47  
    6.48 -				Model model = new Model(soubor);
    6.49 +				Model model = new Model(konfigurace);
    6.50  
    6.51  				final JFrame f = new JFrame();
    6.52  				Panel p = new Panel(model);
    6.53 @@ -74,9 +75,10 @@
    6.54  				f.setLayout(new BorderLayout());
    6.55  				f.add(p, BorderLayout.CENTER);
    6.56  
    6.57 -				/** Ukončení programu klávesou Escape */
    6.58 +				// Ukončení programu klávesou Escape:
    6.59  				f.getRootPane().registerKeyboardAction(new ActionListener() {
    6.60  
    6.61 +					@Override
    6.62  					public void actionPerformed(ActionEvent ae) {
    6.63  						f.dispose();
    6.64  					}
    6.65 @@ -94,8 +96,9 @@
    6.66  				ukončiChybou(MessageFormat.format(překlady
    6.67  					.getString("chyba.souborNeexistuje"), soubor));
    6.68  			}
    6.69 -		} else {
    6.70 -			ukončiChybou(překlady.getString("chyba.chybíParametr"));
    6.71 +		} catch (Exception e) {
    6.72 +			log.log(Level.SEVERE, překlady.getString("chyba"), e);
    6.73 +			ukončiChybou(e.getLocalizedMessage());
    6.74  		}
    6.75  	}
    6.76  
     7.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java	Tue Dec 12 21:19:11 2023 +0100
     7.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java	Fri Dec 15 01:36:17 2023 +0100
     7.3 @@ -16,6 +16,8 @@
     7.4   */
     7.5  package cz.frantovo.rozsireneatributy.gui;
     7.6  
     7.7 +import cz.frantovo.rozsireneatributy.Konfigurace;
     7.8 +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu;
     7.9  import java.awt.Component;
    7.10  import java.awt.event.ActionEvent;
    7.11  import java.awt.event.ActionListener;
    7.12 @@ -37,11 +39,13 @@
    7.13  	extends JComboBox<String>
    7.14  	implements TableCellEditor {
    7.15  
    7.16 +	private final Konfigurace konfigurace;
    7.17  	protected EventListenerList posluchače = new EventListenerList();
    7.18  	protected ChangeEvent událost = new ChangeEvent(this);
    7.19  
    7.20 -	public EditorNázvůAtributů() {
    7.21 +	public EditorNázvůAtributů(Konfigurace konfigurace) {
    7.22  		super();
    7.23 +		this.konfigurace = konfigurace;
    7.24  		setEditable(true);
    7.25  		addActionListener(new ActionListener() {
    7.26  
    7.27 @@ -71,7 +75,7 @@
    7.28  	/**
    7.29  	 * TODO:
    7.30  	 * - další standardní atributy
    7.31 -	 * - konfigurovatelnost
    7.32 +	 * - načítat z XML souboru
    7.33  	 *
    7.34  	 * @see http://www.freedesktop.org/wiki/CommonExtendedAttributes
    7.35  	 */
    7.36 @@ -85,7 +89,12 @@
    7.37  		}
    7.38  		addItem((String) názevAtributu);
    7.39  		setSelectedItem(názevAtributu);
    7.40 -
    7.41 +		
    7.42 +		for (DefiniceAtributu da : konfigurace.getAtributy()) {
    7.43 +			addItem(da.getNázev());
    7.44 +		}
    7.45 +		
    7.46 +		if (!konfigurace.getAtributy().isEmpty()) return;
    7.47  
    7.48  		// General attributes in current use
    7.49  		addItem("mime_type");
     8.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java	Tue Dec 12 21:19:11 2023 +0100
     8.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java	Fri Dec 15 01:36:17 2023 +0100
     8.3 @@ -1,22 +1,23 @@
     8.4  /**
     8.5   * Rozšířené atributy – program na správu rozšířených atributů souborů
     8.6   * Copyright © 2012 František Kučera (frantovo.cz)
     8.7 - * 
     8.8 + *
     8.9   * This program is free software: you can redistribute it and/or modify
    8.10   * it under the terms of the GNU General Public License as published by
    8.11   * the Free Software Foundation, either version 3 of the License.
    8.12 - * 
    8.13 + *
    8.14   * This program is distributed in the hope that it will be useful,
    8.15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.17   * GNU General Public License for more details.
    8.18 - * 
    8.19 + *
    8.20   * You should have received a copy of the GNU General Public License
    8.21   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    8.22   */
    8.23  package cz.frantovo.rozsireneatributy.gui;
    8.24  
    8.25  import cz.frantovo.rozsireneatributy.Atribut;
    8.26 +import cz.frantovo.rozsireneatributy.Konfigurace;
    8.27  import java.io.File;
    8.28  import java.io.IOException;
    8.29  import java.io.RandomAccessFile;
    8.30 @@ -46,28 +47,32 @@
    8.31  		.getLogger(Model.class.getSimpleName());
    8.32  	private static final ResourceBundle překlady = ResourceBundle
    8.33  		.getBundle(Atribut.class.getPackageName() + ".Překlady");
    8.34 -	private String[] sloupečky = {
    8.35 +	private final String[] sloupečky = {
    8.36  		překlady.getString("tabulka.název"),
    8.37  		překlady.getString("tabulka.hodnota")
    8.38  	};
    8.39 -	private Set<TableModelListener> posluchače = new HashSet<>();
    8.40 -	private File soubor;
    8.41 -	private UserDefinedFileAttributeView souborovýSystém;
    8.42 -	private List<Atribut> atributy = new ArrayList<>();
    8.43 +	private final Set<TableModelListener> posluchače = new HashSet<>();
    8.44 +	private final Konfigurace konfigurace;
    8.45 +	private final UserDefinedFileAttributeView souborovýSystém;
    8.46 +	private final List<Atribut> atributy = new ArrayList<>();
    8.47  
    8.48  	private RandomAccessFile zámekSoubor;
    8.49  	private FileChannel zámekKanál;
    8.50  	private FileLock zámek;
    8.51  
    8.52 -	public Model(File soubor) throws IOException {
    8.53 -		this.soubor = soubor;
    8.54 -		Path cesta = soubor.toPath();
    8.55 +	public Model(Konfigurace konfigurace) throws IOException {
    8.56 +		this.konfigurace = konfigurace;
    8.57 +		Path cesta = konfigurace.getSoubor().toPath();
    8.58  		FileSystemProvider posyktovatelFS = cesta.getFileSystem().provider();
    8.59  		souborovýSystém = posyktovatelFS
    8.60  			.getFileAttributeView(cesta, UserDefinedFileAttributeView.class);
    8.61  		načtiAtributy();
    8.62  	}
    8.63  
    8.64 +	public Konfigurace getKonfigurace() {
    8.65 +		return konfigurace;
    8.66 +	}
    8.67 +
    8.68  	@Override
    8.69  	public int getRowCount() {
    8.70  		return atributy.size();
    8.71 @@ -95,12 +100,13 @@
    8.72  
    8.73  	@Override
    8.74  	public Object getValueAt(int m, int n) {
    8.75 -		if (n == 0) {
    8.76 -			return atributy.get(m).getKlíč();
    8.77 -		} else if (n == 1) {
    8.78 -			return atributy.get(m).getHodnota();
    8.79 -		} else {
    8.80 -			return null;
    8.81 +		switch (n) {
    8.82 +			case 0:
    8.83 +				return atributy.get(m).getKlíč();
    8.84 +			case 1:
    8.85 +				return atributy.get(m).getHodnota();
    8.86 +			default:
    8.87 +				return null;
    8.88  		}
    8.89  	}
    8.90  
    8.91 @@ -109,7 +115,9 @@
    8.92  		Atribut a = atributy.get(m);
    8.93  		try {
    8.94  			if (n == 0) {
    8.95 -				/** Měníme klíč – název atributu */
    8.96 +				/**
    8.97 +				 * Měníme klíč – název atributu
    8.98 +				 */
    8.99  				String novýKlíč = String.valueOf(hodnota);
   8.100  				if (!novýKlíč.equals(a.getKlíč())) {
   8.101  					if (a.isPlatnýKlíč()) {
   8.102 @@ -121,7 +129,9 @@
   8.103  					}
   8.104  				}
   8.105  			} else if (n == 1) {
   8.106 -				/** Měníme hodnotu atributu */
   8.107 +				/**
   8.108 +				 * Měníme hodnotu atributu
   8.109 +				 */
   8.110  				a.setHodnota(String.valueOf(hodnota));
   8.111  				if (a.isPlatnýKlíč() && a.isPlatnáHodnota()) {
   8.112  					souborovýSystém.write(a.getKlíč(), a.getHodnotaBajty());
   8.113 @@ -182,7 +192,7 @@
   8.114  	}
   8.115  
   8.116  	public boolean isZámekPodporovaný() {
   8.117 -		return soubor.isFile();
   8.118 +		return konfigurace.getSoubor().isFile();
   8.119  	}
   8.120  
   8.121  	public void nastavZámek(boolean zamknout) throws IOException {
   8.122 @@ -192,7 +202,7 @@
   8.123  		}
   8.124  
   8.125  		if (zamknout && zámekSoubor == null) {
   8.126 -			zámekSoubor = new RandomAccessFile(soubor, "rw");
   8.127 +			zámekSoubor = new RandomAccessFile(konfigurace.getSoubor(), "rw");
   8.128  			zámekKanál = zámekSoubor.getChannel();
   8.129  			zámek = zámekKanál.lock();
   8.130  		} else if (!zamknout && zámekSoubor != null) {
     9.1 --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java	Tue Dec 12 21:19:11 2023 +0100
     9.2 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java	Fri Dec 15 01:36:17 2023 +0100
     9.3 @@ -75,7 +75,7 @@
     9.4  
     9.5  	private void nastavEditor() {
     9.6  		tabulka.getColumnModel().getColumn(SLOUPEC_NÁZVU)
     9.7 -			.setCellEditor(new EditorNázvůAtributů());
     9.8 +			.setCellEditor(new EditorNázvůAtributů(model.getKonfigurace()));
     9.9  	}
    9.10  
    9.11  	private Model getModel() {