mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-02 16:49:02 +00:00
Convert variables in converted profiles. Small snackbar changes
This commit is contained in:
@@ -249,25 +249,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
OutputStream out = getContentResolver().openOutputStream(data.getData());
|
||||
out.write(w.serialize().getBytes(StandardCharsets.UTF_8));
|
||||
out.close();
|
||||
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(R.string.MenuFileExportProfilesSuccess));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (requestCode == MainActivity.REQUEST_CODE_IMPORT_PROFILES) {
|
||||
Uri uri = data.getData();
|
||||
ContentResolver resolver = getContentResolver();
|
||||
|
||||
String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
|
||||
Cursor metaCursor = resolver.query(uri, projection, null, null, null);
|
||||
String fileName = null;
|
||||
if (metaCursor != null) {
|
||||
try {
|
||||
if (metaCursor.moveToFirst()) {
|
||||
fileName = metaCursor.getString(0);
|
||||
}
|
||||
} finally {
|
||||
metaCursor.close();
|
||||
}
|
||||
}
|
||||
String fileName = IOUtils.getDisplayName(uri);
|
||||
|
||||
if (fileName == null) {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
@@ -279,136 +268,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
if (fileName.endsWith(".orca_printer")) {
|
||||
Toast.makeText(MainActivity.this, R.string.OrcaConversionPleaseWait, Toast.LENGTH_SHORT).show();
|
||||
|
||||
File f = new File(SliceBeam.getModelCacheDir(), "orca_conv.zip");
|
||||
new Thread(()->{
|
||||
try {
|
||||
InputStream in = resolver.openInputStream(uri);
|
||||
FileOutputStream fos = new FileOutputStream(f);
|
||||
byte[] buffer = new byte[10240]; int c;
|
||||
while ((c = in.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, c);
|
||||
}
|
||||
fos.close();
|
||||
in.close();
|
||||
|
||||
ZipFile zf = new ZipFile(f);
|
||||
JSONObject bundle = new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry("bundle_structure.json"))));
|
||||
if (!bundle.get("bundle_type").equals("printer config bundle")) {
|
||||
zf.close();
|
||||
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(R.string.OrcaConversionNotAConfigBundle)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Slic3rConfigWrapper w = new Slic3rConfigWrapper();
|
||||
if (bundle.has("process_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("process_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1, v.length() - 5));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.printConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "process", Slic3rConfigWrapper.PRINT_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.printConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findPrint(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bundle.has("filament_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("filament_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1, v.length() - 5));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.filamentConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "filament", Slic3rConfigWrapper.FILAMENT_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.filamentConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findFilament(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bundle.has("printer_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("printer_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.printerConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "machine", Slic3rConfigWrapper.PRINTER_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.printerConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findPrinter(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zf.close();
|
||||
|
||||
loadIniForImport(new ByteArrayInputStream(w.serialize().getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (Exception e) {
|
||||
ViewUtils.postOnMainThread(() -> {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(e.toString())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
loadConvertedProfile(uri);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -421,6 +281,164 @@ public class MainActivity extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loadIniForImport(getContentResolver().openInputStream(uri));
|
||||
} catch (FileNotFoundException e) {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(e.toString())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConvertedProfile(Uri uri) {
|
||||
String tag = UUID.randomUUID().toString();
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.LOADING, R.string.OrcaConversionPleaseWait).tag(tag));
|
||||
File f = new File(SliceBeam.getModelCacheDir(), "orca_conv.zip");
|
||||
IOUtils.IO_POOL.submit(()->{
|
||||
try {
|
||||
InputStream in = getContentResolver().openInputStream(uri);
|
||||
FileOutputStream fos = new FileOutputStream(f);
|
||||
byte[] buffer = new byte[10240];
|
||||
int c;
|
||||
while ((c = in.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, c);
|
||||
}
|
||||
fos.close();
|
||||
in.close();
|
||||
|
||||
ZipFile zf = new ZipFile(f);
|
||||
JSONObject bundle = new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry("bundle_structure.json"))));
|
||||
if (!bundle.get("bundle_type").equals("printer config bundle")) {
|
||||
zf.close();
|
||||
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(R.string.OrcaConversionNotAConfigBundle)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Slic3rConfigWrapper w = new Slic3rConfigWrapper();
|
||||
if (bundle.has("process_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("process_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1, v.length() - 5));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.printConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "process", Slic3rConfigWrapper.PRINT_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.printConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findPrint(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bundle.has("filament_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("filament_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1, v.length() - 5));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.filamentConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "filament", Slic3rConfigWrapper.FILAMENT_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.filamentConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findFilament(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bundle.has("printer_config")) {
|
||||
JSONArray arr = bundle.getJSONArray("printer_config");
|
||||
List<String> names = new ArrayList<>();
|
||||
List<String> stripped = new ArrayList<>();
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
String v = arr.getString(i);
|
||||
names.add(v);
|
||||
stripped.add(v.substring(v.indexOf('/') + 1));
|
||||
}
|
||||
|
||||
for (String name : names) {
|
||||
w.printerConfigs.add(IOUtils.configJsonToIni(new JSONObject(IOUtils.readString(zf.getInputStream(zf.getEntry(name)))), "machine", Slic3rConfigWrapper.PRINTER_CONFIG_KEYS, stripped));
|
||||
}
|
||||
for (ConfigObject obj : w.printerConfigs) {
|
||||
String inherit = obj.get("inherits");
|
||||
while (inherit != null) {
|
||||
ConfigObject _obj = w.findPrinter(inherit);
|
||||
if (_obj == null) throw new IOUtils.MissingProfileException(inherit);
|
||||
|
||||
obj.values.remove("inherits");
|
||||
HashMap<String, String> newMap = new HashMap<>();
|
||||
newMap.putAll(_obj.values);
|
||||
newMap.putAll(obj.values);
|
||||
obj.values = newMap;
|
||||
|
||||
inherit = obj.values.get("inherits");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zf.close();
|
||||
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
loadIniForImport(new ByteArrayInputStream(w.serialize().getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (IOUtils.MissingProfileException ep) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(getString(R.string.MenuFileImportProfilesFailedBaseProfileNotFound, ep.profile))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
} catch (Exception e) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(e.toString())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
}
|
||||
});
|
||||
}
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loadIniForImport(resolver.openInputStream(uri));
|
||||
} catch (FileNotFoundException e) {
|
||||
@@ -435,7 +453,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void loadIniForImport(InputStream in) {
|
||||
new Thread(()->{
|
||||
IOUtils.IO_POOL.submit(()->{
|
||||
try {
|
||||
Slic3rConfigWrapper w = new Slic3rConfigWrapper(in);
|
||||
|
||||
@@ -461,39 +479,68 @@ public class MainActivity extends AppCompatActivity {
|
||||
enabledPrinters[i] = true;
|
||||
}
|
||||
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesPrints)
|
||||
.setMultiChoiceItems(prints, enabledPrints, (dialog, which, isChecked) -> enabledPrints[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d1, w1) -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesFilaments)
|
||||
.setMultiChoiceItems(filaments, enabledFilaments, (dialog, which, isChecked) -> enabledFilaments[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d2, w2) -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesPrinters)
|
||||
.setMultiChoiceItems(printers, enabledPrinters, (dialog, which, isChecked) -> enabledPrinters[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d3, w3) -> {
|
||||
for (int i = 0; i < enabledPrints.length; i++) {
|
||||
if (enabledPrints[i]) {
|
||||
SliceBeam.CONFIG.importPrint(w.printConfigs.get(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < enabledFilaments.length; i++) {
|
||||
if (enabledFilaments[i]) {
|
||||
SliceBeam.CONFIG.importFilament(w.filamentConfigs.get(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < enabledPrinters.length; i++) {
|
||||
if (enabledPrinters[i]) {
|
||||
SliceBeam.CONFIG.importPrinter(w.printerConfigs.get(i));
|
||||
}
|
||||
}
|
||||
SliceBeam.saveConfig();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
if (prints.length == 0 && filaments.length == 0 && printers.length == 0) {
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(R.string.MenuFileImportProfilesFailedEmpty)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable finish = () -> {
|
||||
for (int i = 0; i < enabledPrints.length; i++) {
|
||||
if (enabledPrints[i]) {
|
||||
SliceBeam.CONFIG.importPrint(w.printConfigs.get(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < enabledFilaments.length; i++) {
|
||||
if (enabledFilaments[i]) {
|
||||
SliceBeam.CONFIG.importFilament(w.filamentConfigs.get(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < enabledPrinters.length; i++) {
|
||||
if (enabledPrinters[i]) {
|
||||
SliceBeam.CONFIG.importPrinter(w.printerConfigs.get(i));
|
||||
}
|
||||
}
|
||||
SliceBeam.saveConfig();
|
||||
};
|
||||
Runnable printersRun = () -> {
|
||||
if (printers.length == 0) {
|
||||
finish.run();
|
||||
return;
|
||||
}
|
||||
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesPrinters)
|
||||
.setMultiChoiceItems(printers, enabledPrinters, (dialog, which, isChecked) -> enabledPrinters[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d3, w3) -> finish.run())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
};
|
||||
Runnable filamentsRun = () -> {
|
||||
if (filaments.length == 0) {
|
||||
printersRun.run();
|
||||
return;
|
||||
}
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesFilaments)
|
||||
.setMultiChoiceItems(filaments, enabledFilaments, (dialog, which, isChecked) -> enabledFilaments[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d2, w2) -> printersRun.run())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
};
|
||||
if (prints.length == 0) {
|
||||
filamentsRun.run();
|
||||
} else {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileExportProfilesPrints)
|
||||
.setMultiChoiceItems(prints, enabledPrints, (dialog, which, isChecked) -> enabledPrints[which] = isChecked)
|
||||
.setPositiveButton(android.R.string.ok, (d1, w1) -> filamentsRun.run())
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e("MainActivity", "Failed to read file", e);
|
||||
@@ -504,7 +551,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
|
||||
private void loadFile(File f, boolean autoorient) {
|
||||
@@ -521,27 +568,36 @@ public class MainActivity extends AppCompatActivity {
|
||||
} else {
|
||||
fragment.loadModel(f);
|
||||
}
|
||||
fragment.getGlView().queueEvent(() -> {
|
||||
if (!gcode) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new ObjectsListChangedEvent());
|
||||
}
|
||||
Model model = fragment.getGlView().getRenderer().getModel();
|
||||
int i = model.getObjectsCount() - 1;
|
||||
if (autoorient) {
|
||||
model.autoOrient(i);
|
||||
fragment.getGlView().getRenderer().invalidateGlModel(i);
|
||||
fragment.getGlView().requestRender();
|
||||
}
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(R.string.MenuFileOpenFileLoaded));
|
||||
if (model.isBigObject(i)) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.WARNING, R.string.MenuFileOpenFileBigObject));
|
||||
fragment.getGlView().queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Model model = fragment.getGlView().getRenderer().getModel();
|
||||
if (model == null || fragment.getGlView().getRenderer().getBed() == null) {
|
||||
fragment.getGlView().queueEvent(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gcode) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new ObjectsListChangedEvent());
|
||||
}
|
||||
int i = model.getObjectsCount() - 1;
|
||||
if (autoorient) {
|
||||
model.autoOrient(i);
|
||||
fragment.getGlView().getRenderer().invalidateGlModel(i);
|
||||
fragment.getGlView().requestRender();
|
||||
}
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(R.string.MenuFileOpenFileLoaded));
|
||||
if (model.isBigObject(i)) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.WARNING, R.string.MenuFileOpenFileBigObject));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Slic3rRuntimeError e) {
|
||||
Log.e("MainActivity", "Failed to load model", e);
|
||||
f.delete();
|
||||
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileOpenFileFailed)
|
||||
.setMessage(e.toString())
|
||||
@@ -556,20 +612,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (uri == null) return;
|
||||
|
||||
ContentResolver resolver = getContentResolver();
|
||||
|
||||
String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
|
||||
Cursor metaCursor = resolver.query(uri, projection, null, null, null);
|
||||
String fileName = null;
|
||||
if (metaCursor != null) {
|
||||
try {
|
||||
if (metaCursor.moveToFirst()) {
|
||||
fileName = metaCursor.getString(0);
|
||||
}
|
||||
} finally {
|
||||
metaCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = IOUtils.getDisplayName(uri);
|
||||
if (fileName == null) {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileOpenFileFailed)
|
||||
@@ -578,9 +621,26 @@ public class MainActivity extends AppCompatActivity {
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
if (fileName.endsWith(".orca_printer")) {
|
||||
loadConvertedProfile(uri);
|
||||
return;
|
||||
}
|
||||
if (fileName.endsWith(".ini")) {
|
||||
try {
|
||||
loadIniForImport(resolver.openInputStream(uri));
|
||||
} catch (FileNotFoundException e) {
|
||||
new BeamAlertDialogBuilder(this)
|
||||
.setTitle(R.string.MenuFileImportProfilesFailed)
|
||||
.setMessage(e.toString())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
File f = new File(SliceBeam.getModelCacheDir(), fileName);
|
||||
// TODO: Check if file already exists
|
||||
new Thread(()->{
|
||||
IOUtils.IO_POOL.submit(()->{
|
||||
try {
|
||||
InputStream in = resolver.openInputStream(uri);
|
||||
FileOutputStream fos = new FileOutputStream(f);
|
||||
@@ -601,7 +661,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -204,10 +204,13 @@ public abstract class UnfoldMenu {
|
||||
}
|
||||
fragment.getGlView().invalidate();
|
||||
}
|
||||
});
|
||||
})
|
||||
.addEndListener((animation, canceled, value, velocity) -> onShown());
|
||||
spring.start();
|
||||
}
|
||||
|
||||
protected void onShown() {}
|
||||
|
||||
public void relayout() {
|
||||
FrameLayout into = containerLayout;
|
||||
boolean portrait = into.getWidth() < into.getHeight();
|
||||
|
||||
@@ -124,10 +124,10 @@ public class CameraMenu extends ListBedMenu {
|
||||
animateTo(toOrigin, toPosition);
|
||||
}),
|
||||
new SpaceItem(portrait ? ViewUtils.dp(8) : 0, portrait ? 0 : ViewUtils.dp(8)),
|
||||
new BedMenuItem(R.string.MenuCameraControlMode, R.drawable.hand_point_up_outline_28).onClick(v -> {
|
||||
new BedMenuItem(R.string.MenuCameraControlMode, R.drawable.rectangle_hand_point_up_28).onClick(v -> {
|
||||
Context ctx = v.getContext();
|
||||
new BeamAlertDialogBuilder(v.getContext())
|
||||
.setTitle(R.string.MenuCameraControlMode)
|
||||
.setTitle(R.string.MenuCameraControlModeFull)
|
||||
.setSingleChoiceItems(new CharSequence[] {
|
||||
ctx.getString(R.string.MenuCameraControlModeOne),
|
||||
ctx.getString(R.string.MenuCameraControlModeTwo),
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import cz.msebera.android.httpclient.entity.ContentType;
|
||||
@@ -52,6 +53,7 @@ import ru.ytkab0bp.slicebeam.SliceBeam;
|
||||
import ru.ytkab0bp.slicebeam.components.BeamAlertDialogBuilder;
|
||||
import ru.ytkab0bp.slicebeam.components.UnfoldMenu;
|
||||
import ru.ytkab0bp.slicebeam.config.ConfigObject;
|
||||
import ru.ytkab0bp.slicebeam.events.NeedDismissSnackbarEvent;
|
||||
import ru.ytkab0bp.slicebeam.events.NeedSnackbarEvent;
|
||||
import ru.ytkab0bp.slicebeam.fragment.BedFragment;
|
||||
import ru.ytkab0bp.slicebeam.recycler.SimpleRecyclerItem;
|
||||
@@ -64,13 +66,14 @@ import ru.ytkab0bp.slicebeam.utils.ViewUtils;
|
||||
import ru.ytkab0bp.slicebeam.view.DividerView;
|
||||
import ru.ytkab0bp.slicebeam.view.PositionScrollView;
|
||||
import ru.ytkab0bp.slicebeam.view.SegmentsView;
|
||||
import ru.ytkab0bp.slicebeam.view.SnackbarsLayout;
|
||||
|
||||
public class SliceMenu extends ListBedMenu {
|
||||
private AsyncHttpClient client = new AsyncHttpClient();
|
||||
|
||||
{
|
||||
client.setLoggingEnabled(true);
|
||||
client.setMaxRetriesAndTimeout(0, 5000);
|
||||
client.setMaxRetriesAndTimeout(0, 10000);
|
||||
}
|
||||
|
||||
private final static List<String> SUPPORTED_SEND = Collections.singletonList("octoprint");
|
||||
@@ -132,7 +135,8 @@ public class SliceMenu extends ListBedMenu {
|
||||
if (!host.startsWith("http://")) {
|
||||
host = "http://" + host;
|
||||
}
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(R.string.MenuSliceSendToPrinterStarted));
|
||||
String tag = UUID.randomUUID().toString();
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.LOADING, R.string.MenuSliceSendToPrinterLoading).tag(tag));
|
||||
Header[] headers = TextUtils.isEmpty(apiKey) ? new Header[0] : new Header[] {new BasicHeader("X-Api-Key", apiKey)};
|
||||
RequestParams params = new RequestParams();
|
||||
try {
|
||||
@@ -151,7 +155,8 @@ public class SliceMenu extends ListBedMenu {
|
||||
if (!obj.has("action") && !obj.has("files")) {
|
||||
throw new JSONException(obj.toString());
|
||||
}
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(print ? R.string.MenuSliceSendToPrinterPrintStarted : R.string.MenuSliceSendToPrinterOK));
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedSnackbarEvent(print ? SnackbarsLayout.Type.INFO : SnackbarsLayout.Type.DONE, print ? R.string.MenuSliceSendToPrinterPrintStarted : R.string.MenuSliceSendToPrinterOK));
|
||||
} catch (JSONException e) {
|
||||
onFailure(statusCode, headers, responseBody, e);
|
||||
}
|
||||
@@ -159,6 +164,7 @@ public class SliceMenu extends ListBedMenu {
|
||||
|
||||
@Override
|
||||
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
|
||||
SliceBeam.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(tag));
|
||||
ViewUtils.postOnMainThread(() -> new BeamAlertDialogBuilder(fragment.getContext())
|
||||
.setTitle(R.string.MenuSliceSendToPrinterFailed)
|
||||
.setMessage(error.toString())
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package ru.ytkab0bp.slicebeam.utils;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@@ -9,21 +13,39 @@ import org.json.JSONObject;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import ru.ytkab0bp.slicebeam.SliceBeam;
|
||||
import ru.ytkab0bp.slicebeam.config.ConfigObject;
|
||||
|
||||
public class IOUtils {
|
||||
public static ExecutorService IO_POOL = Executors.newCachedThreadPool();
|
||||
|
||||
public static String getDisplayName(Uri uri) {
|
||||
ContentResolver resolver = SliceBeam.INSTANCE.getContentResolver();
|
||||
|
||||
String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
|
||||
Cursor metaCursor = resolver.query(uri, projection, null, null, null);
|
||||
String fileName = null;
|
||||
if (metaCursor != null) {
|
||||
try {
|
||||
if (metaCursor.moveToFirst()) {
|
||||
fileName = metaCursor.getString(0);
|
||||
}
|
||||
} finally {
|
||||
metaCursor.close();
|
||||
}
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
public static String readString(InputStream in) throws IOException {
|
||||
return readString(in, false);
|
||||
}
|
||||
@@ -54,10 +76,13 @@ public class IOUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static ConfigObject downloadProfilesRecursively(String vendor, String type, String profile, List<String> supportedKeys) throws IOException, JSONException {
|
||||
private static ConfigObject downloadProfilesRecursively(String vendor, String type, String profile, List<String> supportedKeys) throws IOException, JSONException, MissingProfileException {
|
||||
ConfigObject cfg = new ConfigObject();
|
||||
|
||||
URLConnection con = new URL(String.format("https://raw.githubusercontent.com/SoftFever/OrcaSlicer/main/resources/profiles/%s/%s/%s.json", vendor, type, profile)).openConnection();
|
||||
HttpURLConnection con = (HttpURLConnection) new URL(String.format("https://raw.githubusercontent.com/SoftFever/OrcaSlicer/main/resources/profiles/%s/%s/%s.json", vendor, type, profile)).openConnection();
|
||||
if (con.getResponseCode() == 404) {
|
||||
throw new MissingProfileException(profile);
|
||||
}
|
||||
JSONObject obj = new JSONObject(readString(con.getInputStream()));
|
||||
if (!TextUtils.isEmpty(obj.optString("inherits", null))) {
|
||||
ConfigObject o = downloadProfilesRecursively(vendor, type, obj.getString("inherits"), supportedKeys);
|
||||
@@ -116,19 +141,103 @@ public class IOUtils {
|
||||
|
||||
ConfigObject _obj = downloadProfilesRecursively(vendor, type, inherit, supportedKeys);
|
||||
for (Map.Entry<String, String> en : _obj.values.entrySet()) {
|
||||
if (supportedKeys.contains(en.getKey())) {
|
||||
if (en.getKey().equals("printable_area")) {
|
||||
cfg.values.put("bed_shape", en.getValue());
|
||||
} else if (en.getKey().equals("ironing_type") && en.getValue().equals("no ironing")) {
|
||||
String key = en.getKey();
|
||||
switch (key) {
|
||||
case "machine_start_gcode":
|
||||
key = "start_gcode";
|
||||
break;
|
||||
case "machine_end_gcode":
|
||||
key = "end_gcode";
|
||||
break;
|
||||
case "printable_area":
|
||||
key = "bed_shape";
|
||||
break;
|
||||
case "printable_height":
|
||||
key = "max_print_height";
|
||||
break;
|
||||
case "layer_change_gcode":
|
||||
key = "layer_gcode";
|
||||
break;
|
||||
case "before_layer_change_gcode":
|
||||
key = "before_layer_gcode";
|
||||
break;
|
||||
case "filament_start_gcode":
|
||||
key = "start_filament_gcode";
|
||||
break;
|
||||
case "filament_end_gcode":
|
||||
key = "end_filament_gcode";
|
||||
break;
|
||||
case "retraction_minimum_level":
|
||||
key = "retract_before_travel";
|
||||
break;
|
||||
case "retraction_length":
|
||||
key = "retract_length";
|
||||
break;
|
||||
case "retraction_speed":
|
||||
key = "retract_speed";
|
||||
break;
|
||||
case "deretraction_speed":
|
||||
key = "deretract_speed";
|
||||
break;
|
||||
case "change_filament_gcode":
|
||||
key = "pause_print_gcode";
|
||||
break;
|
||||
case "nozzle_temperature":
|
||||
key = "temperature";
|
||||
break;
|
||||
case "nozzle_temperature_initial_layer":
|
||||
key = "first_layer_temperature";
|
||||
break;
|
||||
case "filament_flow_ratio":
|
||||
key = "extrusion_multiplier";
|
||||
break;
|
||||
case "chamber_temperatures":
|
||||
key = "chamber_temperature";
|
||||
break;
|
||||
case "fan_max_speed":
|
||||
key = "max_fan_speed";
|
||||
break;
|
||||
case "fan_min_speed":
|
||||
key = "min_fan_speed";
|
||||
break;
|
||||
case "overhang_fan_speed":
|
||||
key = "bridge_fan_speed";
|
||||
break;
|
||||
case "slow_down_layer_time":
|
||||
key = "slowdown_below_layer_time";
|
||||
break;
|
||||
case "slow_down_min_speed":
|
||||
key = "min_print_speed";
|
||||
break;
|
||||
}
|
||||
|
||||
if (key.equals("pressure_advance")) {
|
||||
StringBuilder sb = new StringBuilder("SET_PRESSURE_ADVANCE ADVANCE=").append(en.getValue());
|
||||
if (cfg.values.containsKey("start_filament_gcode")) {
|
||||
sb.append("\n").append(cfg.get("start_filament_gcode"));
|
||||
}
|
||||
cfg.values.put("start_filament_gcode", sb.toString());
|
||||
}
|
||||
|
||||
if (supportedKeys.contains(key)) {
|
||||
if (key.equals("ironing_type") && en.getValue().equals("no ironing")) {
|
||||
cfg.values.put("ironing", "0");
|
||||
cfg.values.put("ironing_type", "top");
|
||||
} if (en.getKey().equals("start_filament_gcode") || en.getKey().equals("end_filament_gcode") ||
|
||||
en.getKey().equals("start_gcode") || en.getKey().equals("end_gcode")) {
|
||||
}
|
||||
if (key.equals("start_filament_gcode") || key.equals("end_filament_gcode") ||
|
||||
key.equals("start_gcode") || key.equals("end_gcode")) {
|
||||
|
||||
cfg.values.put(en.getKey(), en.getValue().replaceAll("(\\{|\\[)nozzle_temperature_initial_layer(\\[\\d+]|)(}|])", "$1first_layer_temperature$2$3")
|
||||
String val = en.getValue();
|
||||
if (key.equals("start_filament_gcode")) {
|
||||
if (cfg.values.containsKey("start_filament_gcode")) {
|
||||
val = cfg.get("start_filament_gcode") + "\n" + val;
|
||||
}
|
||||
}
|
||||
|
||||
cfg.values.put(key, val.replaceAll("(\\{|\\[)nozzle_temperature_initial_layer(\\[\\d+]|)(}|])", "$1first_layer_temperature$2$3")
|
||||
.replaceAll("(\\{|\\[)bed_temperature_initial_layer_single(\\[\\d+]|)(}|])", "$1first_layer_bed_temperature$2$3"));
|
||||
} else if (!en.getKey().equals("thumbnails")) {
|
||||
cfg.values.put(en.getKey(), en.getValue());
|
||||
} else if (!key.equals("thumbnails")) {
|
||||
cfg.values.put(key, en.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ import ru.ytkab0bp.slicebeam.R;
|
||||
import ru.ytkab0bp.slicebeam.SetupActivity;
|
||||
|
||||
public class Prefs {
|
||||
public final static int CAMERA_CONTROL_MODE_ROTATE_MOVE = 0,
|
||||
CAMERA_CONTROL_MODE_MOVE_ROTATE = 1,
|
||||
CAMERA_CONTROL_MODE_MOVE_ONLY = 2;
|
||||
|
||||
private static SharedPreferences mPrefs;
|
||||
|
||||
public static void init(Application ctx) {
|
||||
|
||||
@@ -215,7 +215,7 @@ public class SnackbarsLayout extends FrameLayout {
|
||||
}
|
||||
})
|
||||
.addEndListener((animation, canceled, value, velocity) -> {
|
||||
if (remove) {
|
||||
if (remove && getParent() != null) {
|
||||
((ViewGroup) getParent()).removeView(SnackbarView.this);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="28dp"
|
||||
android:height="28dp"
|
||||
android:viewportWidth="28"
|
||||
android:viewportHeight="28">
|
||||
<path
|
||||
android:pathData="M5.07,4.801C6.164,4.216 7.243,4 9.691,4h8.616c2.448,0 3.527,0.216 4.622,0.801A5.465,5.465 0,0 1,25.2 7.07c0.585,1.096 0.801,2.175 0.801,4.623v1.848c0,0.666 0,1.226 -0.037,1.683 -0.04,0.48 -0.124,0.934 -0.345,1.366a3.5,3.5 0,0 1,-1.529 1.53c-0.478,0.243 -0.988,0.322 -1.528,0.355a1,1 0,0 1,-0.122 -1.996c0.44,-0.027 0.626,-0.083 0.742,-0.142a1.5,1.5 0,0 0,0.655 -0.655c0.053,-0.103 0.104,-0.265 0.133,-0.62 0.03,-0.367 0.031,-0.844 0.031,-1.561v-1.808c0,-2.335 -0.212,-3.019 -0.565,-3.68a3.466,3.466 0,0 0,-1.448 -1.447C21.327,6.212 20.643,6 18.308,6L9.692,6c-2.335,0 -3.019,0.212 -3.68,0.565a3.466,3.466 0,0 0,-1.447 1.448C4.212,8.673 4,9.357 4,11.692L4,13.5c0,0.717 0,1.194 0.03,1.56 0.03,0.356 0.081,0.518 0.133,0.621a1.5,1.5 0,0 0,0.656 0.656c0.116,0.058 0.302,0.114 0.742,0.14a1,1 0,1 1,-0.122 1.997c-0.54,-0.033 -1.05,-0.112 -1.528,-0.355a3.5,3.5 0,0 1,-1.53 -1.53c-0.22,-0.432 -0.304,-0.887 -0.344,-1.366C2,14.766 2,14.206 2,13.54v-1.848c0,-2.448 0.216,-3.527 0.801,-4.623A5.466,5.466 0,0 1,5.07 4.801ZM18.059,23.263 L18.083,22.203a0.974,0.974 0,0 0,-0.025 0.219v0.84Z"
|
||||
android:fillColor="#000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="m16.942,18.55 l-0.03,-0.541a0.994,0.994 0,0 0,-1.987 0.049l0.004,-0.43a0.97,0.97 0,0 0,-1.916 -0.227l-0.024,1.06v-0.84c0,-0.076 0.008,-0.15 0.024,-0.22l0.077,-3.385a1.001,1.001 0,0 0,-2.002 -0.049l-0.155,6.095 -0.914,-1.596a0.935,0.935 0,0 0,-1.67 0.83l1.614,3.787s1.179,2.369 4.544,2.573c2.928,0.178 4.536,-1.946 4.45,-4.533l0.078,-2.6a1.048,1.048 0,1 0,-2.093 0.028Z"
|
||||
android:fillColor="#000"/>
|
||||
</vector>
|
||||
@@ -33,12 +33,15 @@
|
||||
<string name="MenuFileCalibrationsModelsSphere">Сфера</string>
|
||||
<string name="MenuFileImportProfiles">Импорт. профилей</string>
|
||||
<string name="MenuFileImportProfilesFailed">Не удалось импортировать</string>
|
||||
<string name="MenuFileImportProfilesFailedBaseProfileNotFound">Родительский профиль не найден: %s</string>
|
||||
<string name="MenuFileImportProfilesFailedNotIni">Не файл .ini</string>
|
||||
<string name="MenuFileImportProfilesFailedEmpty">Файл не содержит профилей</string>
|
||||
<string name="MenuFileExportProfiles">Экспорт. профилей</string>
|
||||
<string name="MenuFileExportProfilesPrints">Профили печати</string>
|
||||
<string name="MenuFileExportProfilesFilaments">Филаменты</string>
|
||||
<string name="MenuFileExportProfilesPrinters">Принтеры</string>
|
||||
<string name="MenuFileExportProfilesNoProfiles">Не выбрано ни одного профиля.</string>
|
||||
<string name="MenuFileExportProfilesSuccess">Профили успешно экспортированы.</string>
|
||||
<string name="MenuCamera">Камера</string>
|
||||
<string name="MenuCameraIsometric">Изомет.\nвид</string>
|
||||
<string name="MenuCameraTop">Вид\nсверху</string>
|
||||
@@ -48,7 +51,8 @@
|
||||
<string name="MenuCameraLeft">Вид\nслева</string>
|
||||
<string name="MenuCameraRight">Вид\nсправа</string>
|
||||
<string name="MenuCameraOrtho">Ортог. проекц.</string>
|
||||
<string name="MenuCameraControlMode">Режим управ.</string>
|
||||
<string name="MenuCameraControlMode">Режим управл.</string>
|
||||
<string name="MenuCameraControlModeFull">Режим управления</string>
|
||||
<string name="MenuCameraControlModeOne">Один палец - поворот, два пальца - перемещение</string>
|
||||
<string name="MenuCameraControlModeTwo">Один палец - перемещение, два пальца - поворот</string>
|
||||
<string name="MenuCameraControlModeThree">Только перемещение</string>
|
||||
@@ -99,7 +103,7 @@
|
||||
<string name="MenuSliceShare">Отправка</string>
|
||||
<string name="MenuSliceSendToPrinter">Отправ. на принтер</string>
|
||||
<string name="MenuSliceSendToPrinterAndPrint">Отправ. на печать</string>
|
||||
<string name="MenuSliceSendToPrinterStarted">Загрузка началась…</string>
|
||||
<string name="MenuSliceSendToPrinterLoading">Отправка…</string>
|
||||
<string name="MenuSliceSendToPrinterOK">Файл отправлен на принтер.</string>
|
||||
<string name="MenuSliceSendToPrinterPrintStarted">Файл отправлен, начало печати…</string>
|
||||
<string name="MenuSliceSendToPrinterFailed">Не удалось отправить файл</string>
|
||||
|
||||
@@ -35,12 +35,15 @@
|
||||
<string name="MenuFileCalibrationsModelsSphere">Sphere</string>
|
||||
<string name="MenuFileImportProfiles">Import profiles</string>
|
||||
<string name="MenuFileImportProfilesFailed">Import failed</string>
|
||||
<string name="MenuFileImportProfilesFailedBaseProfileNotFound">Parent profile not found: %s</string>
|
||||
<string name="MenuFileImportProfilesFailedNotIni">Not an .ini file</string>
|
||||
<string name="MenuFileImportProfilesFailedEmpty">File does not contain profiles</string>
|
||||
<string name="MenuFileExportProfiles">Export profiles</string>
|
||||
<string name="MenuFileExportProfilesPrints">Print configs</string>
|
||||
<string name="MenuFileExportProfilesFilaments">Filaments</string>
|
||||
<string name="MenuFileExportProfilesPrinters">Printers</string>
|
||||
<string name="MenuFileExportProfilesNoProfiles">No profiles selected.</string>
|
||||
<string name="MenuFileExportProfilesSuccess">Exported profiles successfully.</string>
|
||||
<string name="MenuCamera">Camera</string>
|
||||
<string name="MenuCameraIsometric">Isom. view</string>
|
||||
<string name="MenuCameraTop">Top view</string>
|
||||
@@ -51,6 +54,7 @@
|
||||
<string name="MenuCameraRight">Right view</string>
|
||||
<string name="MenuCameraOrtho">Orth. project.</string>
|
||||
<string name="MenuCameraControlMode">Control mode</string>
|
||||
<string name="MenuCameraControlModeFull">Control mode</string>
|
||||
<string name="MenuCameraControlModeOne">One finger - rotation, two fingers - movement</string>
|
||||
<string name="MenuCameraControlModeTwo">One finger - movement, two fingers - rotation</string>
|
||||
<string name="MenuCameraControlModeThree">Only movement</string>
|
||||
@@ -101,7 +105,7 @@
|
||||
<string name="MenuSliceShare">Share</string>
|
||||
<string name="MenuSliceSendToPrinter">Send to printer</string>
|
||||
<string name="MenuSliceSendToPrinterAndPrint">Send and print</string>
|
||||
<string name="MenuSliceSendToPrinterStarted">Upload started…</string>
|
||||
<string name="MenuSliceSendToPrinterLoading">Uploading…</string>
|
||||
<string name="MenuSliceSendToPrinterOK">File sent to printer.</string>
|
||||
<string name="MenuSliceSendToPrinterPrintStarted">File sent, starting print…</string>
|
||||
<string name="MenuSliceSendToPrinterFailed">Failed to send file</string>
|
||||
|
||||
Reference in New Issue
Block a user