Convert variables in converted profiles. Small snackbar changes

This commit is contained in:
utkabobr
2025-04-02 14:14:35 +03:00
parent 8b200e689c
commit df09f8ef39
10 changed files with 435 additions and 232 deletions
@@ -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>
+6 -2
View File
@@ -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>
+5 -1
View File
@@ -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>