Merge pull request #684 from AnBui2004/master

4.3.5
This commit is contained in:
An Bui 2026-07-13 18:13:06 +07:00 committed by GitHub
commit ff6bbd6bbc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 1988 additions and 1052 deletions

View file

@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id 'com.google.android.gms.oss-licenses-plugin'
}
android {
@ -12,8 +13,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 138
versionName "4.3.4"
versionCode 139
versionName "4.3.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
@ -123,4 +124,6 @@ dependencies {
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
implementation libs.play.services.oss.licenses
}

View file

@ -8,6 +8,7 @@ import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;
import com.vectras.vm.adapters.GithubUserAdapter;
import com.vectras.vm.utils.CommandUtils;
import com.vectras.vm.utils.UIUtils;
@ -100,6 +101,8 @@ public class AboutActivity extends AppCompatActivity implements View.OnClickList
});
});
findViewById(R.id.btn_open_source_licenses).setOnClickListener(v -> startActivity(new Intent(this, OssLicensesMenuActivity.class)));
}
@Override

View file

@ -168,6 +168,7 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("fdb", "");
}
vmConfigMap.put("networkCard", current.networkCard);
vmConfigMap.put("sharedFolder", current.sharedFolder);
vmConfigMap.put("bootFrom", current.bootFrom);
vmConfigMap.put("isShowBootMenu", current.isShowBootMenu);

View file

@ -73,6 +73,11 @@ public class StartVM {
if (!cpuParams.isEmpty()) extraParams = cpuParams + " " + extraParams;
String network = Objects.requireNonNull(VMCreatorSelector.getNetworkCard(activity, vmData.networkCard).get("value")).toString();
if (!network.isEmpty()) {
extraParams = "-device " + network + ",netdev=net0 -netdev user,id=net0 " + extraParams;
}
String bootFromParams = Objects.requireNonNull(VMCreatorSelector.getBootFrom(activity, vmData.bootFrom).get("value")).toString();
String showBootMenuParams = vmData.isShowBootMenu ? "menu=on" : "";
String bootParams = "";

View file

@ -24,14 +24,17 @@ import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.Fragment.CreateImageDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.editor.AdvancedConfigsDialog;
import com.vectras.vm.creator.editor.BoardConfigsDialog;
import com.vectras.vm.creator.editor.NetworkConfigsDialog;
import com.vectras.vm.creator.utils.CreatorUtils;
import com.vectras.vm.creator.editor.FirmwareConfigsDialog;
import com.vectras.vm.creator.editor.StorageConfigsDialog;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.store.RomInfo;
import com.vectras.vm.SplashActivity;
@ -58,14 +61,11 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.vectras.vm.utils.ZipUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vm.utils.PermissionUtils;
import com.vectras.vterm.Terminal2;
@ -76,7 +76,6 @@ public class VMCreatorActivity extends AppCompatActivity {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private DialogProgressStyleBinding dialogProgressStyleBinding;
private AlertDialog progressDialog;
boolean iseditparams = false;
public String previousName = "";
public boolean addromnowdone = false;
private boolean created = false;
@ -85,16 +84,8 @@ public class VMCreatorActivity extends AppCompatActivity {
public static DataMainRoms current = new DataMainRoms();
private String thumbnailPath = "";
private String vmID = VMManager.idGenerator();
private int cpu = 0;
private int cores = 0;
private int threads = 0;
private boolean isUseBattery = false;
private boolean isShowBootMenu = false;
private boolean isUseLocalTime = true;
private boolean isUseUefi = false;
private boolean isUseDefaultBios = true;
private boolean sharedFolder = false;
private int bootFrom = 0;
private CreatorUtils utils;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@ -106,7 +97,7 @@ public class VMCreatorActivity extends AppCompatActivity {
try {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.pick(this, filePickerDialog.TYPE_FILE, (path -> handleAddFile(Uri.fromFile(new File (path)))));
filePickerDialog.pick(this, FilePickerDialog.TYPE_FILE, (path -> handleAddFile(Uri.fromFile(new File (path)))));
} else {
filePicker.launch("*/*");
}
@ -158,24 +149,6 @@ public class VMCreatorActivity extends AppCompatActivity {
binding.btnCreate.setOnClickListener(v -> startCreateVM());
setupStorageUi();
binding.qemu.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(getApplicationContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
binding.qemuField.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(getApplicationContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
TextWatcher afterTextChangedListener = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -197,8 +170,6 @@ public class VMCreatorActivity extends AppCompatActivity {
}
};
binding.title.addTextChangedListener(afterTextChangedListener);
binding.drive.addTextChangedListener(afterTextChangedListener);
binding.qemu.addTextChangedListener(afterTextChangedListener);
binding.ivIcon.setOnClickListener(v -> {
if (thumbnailPath.isEmpty()) {
@ -217,56 +188,57 @@ public class VMCreatorActivity extends AppCompatActivity {
binding.ivAddThubnail.setImageResource(R.drawable.add_24px);
VMManager.setIconWithName(binding.ivIcon, Objects.requireNonNull(binding.title.getText()).toString());
if (FileUtils.isFileExists(VmFileManager.getThumbnail(vmID))) markDelete(VmFileManager.getThumbnail(vmID));
if (FileUtils.isFileExists(VmFileManager.getThumbnail(vmID))) utils.markDelete(VmFileManager.getThumbnail(vmID));
}, null);
}
});
binding.lineardisclaimer.setOnClickListener(v -> DialogUtils.oneDialog(this, getResources().getString(R.string.dont_miss_out), getResources().getString(R.string.disclaimer_when_using_rom), getResources().getString(R.string.i_agree), true, R.drawable.verified_user_24px, true, null, null));
binding.lnBoard.setOnClickListener(v -> {
save();
binding.sbvCpu.setOnClickListener(v -> VMCreatorSelector.cpu(this, MainSettingsManager.getArch(this), cpu, ((position, name, value) -> {
cpu = position;
binding.sbvCpu.setSubtitle(name);
})));
binding.sbvCore.setOnClickListener(v -> VMCreatorSelector.cpuCore(this, MainSettingsManager.getArch(this), cores, ((position, name, value) -> {
cores = position;
binding.sbvCore.setSubtitle(name);
})));
binding.sbvThread.setOnClickListener(v -> VMCreatorSelector.cpuThread(this, MainSettingsManager.getArch(this), threads, ((position, name, value) -> {
threads = position;
binding.sbvThread.setSubtitle(name);
})));
binding.cbvBattery.setOnCheckedChangeListener((v, isChecked) -> isUseBattery = isChecked);
binding.sbvBootfrom.setOnClickListener(v -> VMCreatorSelector.bootFrom(this, bootFrom, ((position, name, value) -> {
bootFrom = position;
binding.sbvBootfrom.setSubtitle(name);
})));
binding.cbvShowbootmenu.setOnCheckedChangeListener((v, isChecked) -> isShowBootMenu = isChecked);
binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> isUseLocalTime = isChecked);
if (!MainSettingsManager.getArch(this).equals("X86_64")) {
binding.cbvUseuefi.setVisibility(View.GONE);
} else {
binding.cbvUseuefi.setOnCheckedChangeListener((v, isChecked) -> isUseUefi = isChecked);
}
binding.cbvUseDefaultBios.setOnCheckedChangeListener((v, isChecked) -> {
isUseDefaultBios = isChecked;
binding.cbvUseuefi.setEnabled(isChecked);
BoardConfigsDialog dialog = new BoardConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "board_configs_dialog");
});
binding.lnStorage.setOnClickListener(v -> {
save();
StorageConfigsDialog dialog = new StorageConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "storage_configs_dialog");
});
VmFileManager.removeTemp(this, vmID, peddingTempFolder);
binding.lnFirmware.setOnClickListener(v -> {
save();
FirmwareConfigsDialog dialog = new FirmwareConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "firmware_configs_dialog");
});
binding.lnNetwork.setOnClickListener(v -> {
save();
NetworkConfigsDialog dialog = new NetworkConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "network_configs_dialog");
});
binding.lnAdvanced.setOnClickListener(v -> {
save();
AdvancedConfigsDialog dialog = new AdvancedConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "advanced_configs_dialog");
});
modify = getIntent().getBooleanExtra("MODIFY", false);
if (modify) {
@ -275,20 +247,23 @@ public class VMCreatorActivity extends AppCompatActivity {
loadConfig(VMManager.getVMConfig(getIntent().getIntExtra("POS", 0)));
vmID = getIntent().getStringExtra("VMID");
if (vmID == null || vmID.isEmpty()) {
vmID = VMManager.idGenerator();
}
// vmID = getIntent().getStringExtra("VMID");
//
// if (vmID == null || vmID.isEmpty()) {
// vmID = VMManager.idGenerator();
// }
previousName = current.itemName;
} else {
checkVMID();
utils = new CreatorUtils(this, vmID);
if (getIntent().hasExtra("addromnow")) {
if (Objects.requireNonNull(getIntent().getStringExtra("romextra")).isEmpty()) {
setDefault();
} else {
binding.qemu.setText(VmFileManager.textMarkToPath(this, vmID, Objects.requireNonNull(getIntent().getStringExtra("romextra"))));
current.itemExtra = VmFileManager.textMarkToPath(this, vmID, Objects.requireNonNull(getIntent().getStringExtra("romextra")));
}
binding.title.setText(getIntent().getStringExtra("romname"));
@ -309,9 +284,9 @@ public class VMCreatorActivity extends AppCompatActivity {
handleDiskFile(Uri.fromFile(new File((Objects.requireNonNull(getIntent().getStringExtra("rompath"))))), false);
}
if (!Objects.requireNonNull(getIntent().getStringExtra("addtodrive")).isEmpty()) {
setDrive(SELECT_DISK_0_FILE_MODE, VmFileManager.getPath(vmID, getIntent().getStringExtra("romfilename")));
current.itemPath = VmFileManager.getPath(vmID, getIntent().getStringExtra("romfilename"));
} else {
setDrive(SELECT_DISK_0_FILE_MODE, null);
current.itemPath = "";
}
}
@ -320,7 +295,7 @@ public class VMCreatorActivity extends AppCompatActivity {
try {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.pick(this, filePickerDialog.ROM_FILE, (path -> importRom(null, path, new File(path).getName())));
filePickerDialog.pick(this, FilePickerDialog.ROM_FILE, (path -> importRom(null, path, new File(path).getName())));
} else {
cvbiPicker.launch("*/*");
}
@ -343,7 +318,7 @@ public class VMCreatorActivity extends AppCompatActivity {
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (status == terminal2.SUCCESS)
binding.drive.setText(VmFileManager.getPath(vmID, "disk.qcow2"));
current.itemPath = VmFileManager.getPath(vmID, "disk.qcow2");
});
}
@ -355,12 +330,14 @@ public class VMCreatorActivity extends AppCompatActivity {
});
}
} else {
setDrive(SELECT_DISK_0_FILE_MODE, null);
current.itemPath = "";
}
}
}
utils.removeTemp();
checkCreateCommandConfig();
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@ -375,10 +352,6 @@ public class VMCreatorActivity extends AppCompatActivity {
public void onResume() {
super.onResume();
PermissionUtils.storagepermission(this, true);
if (iseditparams) {
iseditparams = false;
binding.qemu.setText(QemuParamsEditorActivity.result);
}
}
private void onBack() {
@ -413,94 +386,6 @@ public class VMCreatorActivity extends AppCompatActivity {
handleThumbnail(uri);
});
private final ActivityResultLauncher<String> diskPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
handleDiskFile(uri, true);
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> isoPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(this, uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isOpticalFileFormat(fileName)) {
DialogUtils.twoDialog(this, getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_optical_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.album_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> floppyPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(this, uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isFloppyFileFormat(fileName)) {
DialogUtils.twoDialog(this, getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_floppy_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.save_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
private void handleFile(Uri uri) {
if (MainSettingsManager.copyFile(this)) {
showProgressDialog(getString(R.string.copying_file));
executor.execute(() -> {
try {
isProcessingFile = true;
String path = copyToTemp(uri);
runOnUiThread(() -> setDrive(this.PENDING_SELECT_FILE_MODE, path));
} catch (Exception e) {
runOnUiThread(() -> DialogUtils.oneDialog(this,
getString(R.string.oops),
getString(R.string.unable_to_copy_file_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null));
Log.e(TAG, "isoPicker: " + e.getMessage());
} finally {
isProcessingFile = false;
runOnUiThread(() -> DialogUtils.safeDismiss(this, progressDialog));
}
});
} else {
executor.execute(() -> {
if (!FileUtils.isValidFilePath(this, FileUtils.getPath(this, uri), false)) {
runOnUiThread(() -> DialogUtils.oneDialog(this,
getString(R.string.problem_has_been_detected),
getString(R.string.invalid_file_path_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null)
);
} else {
runOnUiThread(() -> showProgressDialog(getString(R.string.just_a_moment)));
String path = getPath(uri);
runOnUiThread(() -> {
setDrive(this.PENDING_SELECT_FILE_MODE, new File(path).getAbsolutePath());
DialogUtils.safeDismiss(this, progressDialog);
});
}
});
}
}
private final ActivityResultLauncher<String> cvbiPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
@ -533,7 +418,7 @@ public class VMCreatorActivity extends AppCompatActivity {
try {
isProcessingFile = true;
String filePath = copyToTemp(uri);
String filePath = utils.copyToTemp(uri);
runOnUiThread(() -> DialogUtils.twoDialog(this,
getString(R.string.file_added),
@ -572,6 +457,8 @@ public class VMCreatorActivity extends AppCompatActivity {
checkVMID();
}
utils = new CreatorUtils(this, vmID);
if (current.itemArch != null) {
VMManager.setArch(current.itemArch, this);
binding.collapsingToolbarLayout.setSubtitle(MainSettingsManager.getArch(this));
@ -581,77 +468,10 @@ public class VMCreatorActivity extends AppCompatActivity {
binding.title.setText(current.itemName);
}
if (current.itemPath != null && !current.itemPath.isEmpty()) {
setDrive(SELECT_DISK_0_FILE_MODE, (current.itemPath.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.itemPath));
}
if (current.hd1 != null && !current.hd1.isEmpty()) {
setDrive(SELECT_DISK_1_FILE_MODE, (current.hd1.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.hd1));
}
if (MainSettingsManager.getArch(this).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
} else {
if (current.fda!= null && !current.fda.isEmpty()) {
setDrive(SELECT_FLOPPY_A_FILE_MODE, (current.fda.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.fda));
}
if (current.fdb!= null && !current.fdb.isEmpty()) {
setDrive(SELECT_FLOPPY_B_FILE_MODE, (current.fdb.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.fdb));
}
}
if (current.imgCdrom != null && !current.imgCdrom.isEmpty()) {
setDrive(SELECT_CDROM_0_FILE_MODE, (current.imgCdrom.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.imgCdrom));
}
if (current.cdrom1 != null && !current.cdrom1.isEmpty()) {
setDrive(SELECT_CDROM_1_FILE_MODE, (current.cdrom1.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.cdrom1));
}
if (current.itemIcon != null && !current.itemIcon.isEmpty()) {
thumbnailPath = (current.itemIcon.contains("/") ? current.itemIcon : VmFileManager.getPath(vmID, current.itemIcon));
updateThumbnailViewer("");
}
if (current.itemExtra != null) {
binding.qemu.setText(VmFileManager.textMarkToPath(this, vmID, current.itemExtra));
}
cpu = current.cpu;
binding.sbvCpu.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpu(this, MainSettingsManager.getArch(this), current.cpu).get("name")).toString());
cores = current.cores;
binding.sbvCore.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpuCore(MainSettingsManager.getArch(this), cores).get("value")).toString());
threads = current.threads;
binding.sbvThread.setSubtitle(String.valueOf(threads + 1));
isUseBattery = current.battery;
binding.cbvBattery.setChecked(isUseBattery);
bootFrom = current.bootFrom;
binding.sbvBootfrom.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getBootFrom(this, current.bootFrom).get("name")).toString());
isShowBootMenu = current.isShowBootMenu;
binding.cbvShowbootmenu.setChecked(isShowBootMenu);
sharedFolder = current.sharedFolder;
binding.svSharedFolder.setChecked(sharedFolder);
if (MainSettingsManager.getArch(this).equals(MainSettingsManager.X86_64_ARCH)) {
isUseUefi = current.isUseUefi;
binding.cbvUseuefi.setChecked(isUseUefi);
} else {
binding.cbvUseuefi.setVisibility(View.GONE);
}
isUseDefaultBios = current.isUseDefaultBios;
binding.cbvUseDefaultBios.setChecked(isUseDefaultBios);
binding.cbvUseuefi.setEnabled(isUseDefaultBios);
isUseLocalTime = current.isUseLocalTime;
binding.cbvUselocaltime.setChecked(isUseLocalTime);
}
}
@ -660,36 +480,32 @@ public class VMCreatorActivity extends AppCompatActivity {
if (DeviceUtils.is64bit()) {
defQemuParams = switch (MainSettingsManager.getArch(this)) {
case "ARM64" ->
"-M virt,virtualization=true -accel tcg,thread=multi -net nic,model=e1000 -net user -device nec-usb-xhci -device usb-kbd -device usb-mouse -device VGA";
"-M virt,virtualization=true -accel tcg,thread=multi -device nec-usb-xhci -device usb-kbd -device usb-mouse -device VGA";
case "PPC" -> "-M mac99 -accel tcg,thread=multi";
default ->
"-M pc -accel tcg,thread=multi -vga std -netdev user,id=usernet -device e1000,netdev=usernet -usb -device usb-tablet";
"-M pc -accel tcg,thread=multi -vga std -usb -device usb-tablet";
};
} else {
defQemuParams = switch (MainSettingsManager.getArch(this)) {
case "ARM64" ->
"-M virt -net nic,model=e1000 -net user -device nec-usb-xhci -device usb-kbd -device usb-mouse -device VGA";
case "PPC" -> "-M mac99 1";
"-M virt -device nec-usb-xhci -device usb-kbd -device usb-mouse -device VGA";
case "PPC" -> "-M mac99";
default ->
"-M pc -vga std -netdev user,id=usernet -device e1000,netdev=usernet -usb -device usb-tablet";
"-M pc -vga std -usb -device usb-tablet";
};
}
binding.title.setText(getString(R.string.new_vm));
binding.qemu.setText(defQemuParams);
current.itemExtra = defQemuParams;
String currentArch = MainSettingsManager.getArch(this);
if (currentArch.equals(MainSettingsManager.X86_64_ARCH)) {
cores = Math.min(1, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
binding.sbvCore.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpuCore(currentArch, cores).get("value")).toString());
current.cores = Math.min(1, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
} else if (currentArch.equals(MainSettingsManager.ARM64_ARCH)) {
cores = Math.min(2, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
binding.sbvCore.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpuCore(currentArch, cores).get("value")).toString());
} else {
binding.sbvCore.setSubtitle("1");
current.cores = Math.min(2, VMCreatorSelector.getCpuCorePosition(new CpuHelper().getCpuCores() - 1));
}
binding.sbvThread.setSubtitle("1");
current.networkCard = 3; // Intel E1000 (82540EM)
}
private void checkVMID() {
@ -720,16 +536,18 @@ public class VMCreatorActivity extends AppCompatActivity {
}
private void startCreateVM() {
if (Objects.requireNonNull(binding.title.getText()).toString().isEmpty()) {
save();
if (current.itemName.isEmpty()) {
DialogUtils.oneDialog(this, getString(R.string.oops), getString(R.string.need_set_name), getString(R.string.ok), true, R.drawable.error_96px, true, null, null);
} else {
String _contentDialog = "";
if (Objects.requireNonNull(binding.qemu.getText()).toString().isEmpty()) {
if (current.itemExtra.isEmpty()) {
_contentDialog = getResources().getString(R.string.qemu_params_is_empty);
}
if (isAllDriveEmpty()) {
if (!VMManager.isHaveADisk(Objects.requireNonNull(binding.qemu.getText()).toString())) {
if (!current.itemExtra.isEmpty()) {
if (!_contentDialog.isEmpty()) {
_contentDialog += "\n\n";
}
@ -756,7 +574,7 @@ public class VMCreatorActivity extends AppCompatActivity {
FileUtils.writeToFile(AppConfig.maindirpath, "roms-data.json", "[]");
}
if (!VMManager.addVM(finalVmConfig(), modify ? getIntent().getIntExtra("POS", 0) : -1)) {
if (!VMManager.addVM(current, modify ? getIntent().getIntExtra("POS", 0) : -1)) {
DialogUtils.oneDialog(
this,
getString(R.string.oops),
@ -776,7 +594,7 @@ public class VMCreatorActivity extends AppCompatActivity {
showProgressDialog(getString(R.string.just_a_sec));
new Thread(() -> {
moveAllFromTemp();
utils.moveAllFromTemp();
VmFileManager.unMarkAllPendingAdd(vmID);
VmFileManager.removeAllPendingDeleteMarkFiles(vmID);
@ -796,7 +614,7 @@ public class VMCreatorActivity extends AppCompatActivity {
}).start();
}
private DataMainRoms finalVmConfig() {
private void save() {
current.vmID = vmID;
current.itemArch = MainSettingsManager.getArch(this);
@ -804,38 +622,7 @@ public class VMCreatorActivity extends AppCompatActivity {
current.itemIcon = thumbnailPath;
current.cpu = cpu;
current.cores = cores;
current.threads = threads;
current.battery = isUseBattery;
current.itemPath = Objects.requireNonNull(binding.drive.getText()).toString();
current.hd1 = Objects.requireNonNull(binding.tieHd1.getText()).toString();
current.fda = Objects.requireNonNull(binding.tieFda.getText()).toString();
current.fdb = Objects.requireNonNull(binding.tieFdb.getText()).toString();
current.imgCdrom = Objects.requireNonNull(binding.cdrom.getText()).toString();
current.cdrom1 = Objects.requireNonNull(binding.tieCdrom1.getText()).toString();
current.sharedFolder = sharedFolder;
current.bootFrom = bootFrom;
current.isShowBootMenu = isShowBootMenu;
current.isUseLocalTime = isUseLocalTime;
current.isUseUefi = isUseUefi;
current.isUseDefaultBios = isUseDefaultBios;
current.itemExtra = Objects.requireNonNull(binding.qemu.getText()).toString();
current.qmpPort = 8080;
return current;
}
private void handleThumbnail(Uri uri) {
@ -848,7 +635,7 @@ public class VMCreatorActivity extends AppCompatActivity {
if (FileUtils.isFileExists(VmFileManager.getThumbnail(vmID)))
VmFileManager.markPendingDelete(VmFileManager.getThumbnail(vmID));
String tempPath = VmFileManager.getTempPath(this, vmID, peddingTempFolder + VmFileManager.THUMBNAIL_FILE_NAME);
String tempPath = utils.getTempPath(VmFileManager.THUMBNAIL_FILE_NAME);
ImageUtils.convertToPng(this, uri, tempPath);
@ -931,7 +718,7 @@ public class VMCreatorActivity extends AppCompatActivity {
_filename = String.valueOf(System.currentTimeMillis());
}
String path = copyToTemp(_content_describer);
String path = utils.copyToTemp(_content_describer);
String final_filename = _filename;
runOnUiThread(() -> {
@ -941,7 +728,7 @@ public class VMCreatorActivity extends AppCompatActivity {
return;
}
if (_addtodrive) {
setDrive(PENDING_SELECT_FILE_MODE, path);
current.itemPath = path;
}
});
} catch (Exception e) {
@ -977,7 +764,7 @@ public class VMCreatorActivity extends AppCompatActivity {
null,
null);
} else {
setDrive(PENDING_SELECT_FILE_MODE, path);
current.itemPath = path;
}
});
}).start();
@ -1096,13 +883,13 @@ public class VMCreatorActivity extends AppCompatActivity {
addromnowdone = true;
if (Objects.requireNonNull(getIntent().getStringExtra("romextra")).isEmpty()) {
setDefault();
binding.drive.setText(_getDiskFile);
current.itemPath = _getDiskFile;
} else {
if (Objects.requireNonNull(getIntent().getStringExtra("romextra")).contains(Objects.requireNonNull(getIntent().getStringExtra("finalromfilename")))) {
binding.qemu.setText(Objects.requireNonNull(getIntent().getStringExtra("romextra")).replaceAll(Objects.requireNonNull(getIntent().getStringExtra("finalromfilename")), "\"" + _getDiskFile + "\""));
current.itemExtra = Objects.requireNonNull(getIntent().getStringExtra("romextra")).replaceAll(Objects.requireNonNull(getIntent().getStringExtra("finalromfilename")), "\"" + _getDiskFile + "\"");
} else {
binding.drive.setText(_getDiskFile);
binding.qemu.setText(VmFileManager.textMarkToPath(this, vmID, Objects.requireNonNull(getIntent().getStringExtra("romextra"))));
current.itemPath = _getDiskFile;
current.itemExtra = VmFileManager.textMarkToPath(this, vmID, Objects.requireNonNull(getIntent().getStringExtra("romextra")));
}
}
@ -1112,13 +899,11 @@ public class VMCreatorActivity extends AppCompatActivity {
handleThumbnail(Uri.parse(getIntent().getStringExtra("romicon")));
}
} else {
if (Objects.requireNonNull(binding.qemu.getText()).toString().isEmpty()) {
setDefault();
}
if (current.itemExtra.isEmpty()) setDefault();
if (Objects.requireNonNull(binding.title.getText()).toString().isEmpty() || binding.title.getText().toString().equals("New VM")) {
binding.title.setText(_filename.replace(".cvbi", ""));
}
binding.drive.setText(_getDiskFile);
current.itemPath = _getDiskFile;
VMManager.setArch("", this);
}
@ -1202,291 +987,17 @@ public class VMCreatorActivity extends AppCompatActivity {
if (!isFinishing() && !isDestroyed()) progressDialog.show();
}
private String copyToTemp(Uri uri) throws IOException {
String fileName = FileUtils.getFileNameFromUri(this, uri);
if (fileName == null || fileName.isEmpty()) {
fileName = String.valueOf(System.currentTimeMillis());
}
FileUtils.copyFileFromUri(this, uri, VmFileManager.getTempPath(this, vmID, peddingTempFolder + fileName));
return VmFileManager.getPath(vmID, fileName);
}
public String getPath(Uri uri) {
return FileUtils.getPath(this, uri);
}
String peddingTempFolder = "pedding/";
private void onFileChange(String fileName) {
markDelete(VmFileManager.getPath(vmID, fileName));
}
private void markDelete(String path) {
VmFileManager.markPendingDelete(path);
deleteTemp(new File(path).getName());
}
private void deleteTemp(String fileName) {
VmFileManager.removeTemp(this, vmID, peddingTempFolder + fileName);
}
public void moveAllFromTemp() {
ArrayList<String> fileList = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getTempPath(this, vmID, peddingTempFolder), fileList);
for (int position = 0; position < fileList.size(); position++) {
FileUtils.moveToFolder(fileList.get(position), VmFileManager.getPath(vmID));
}
ArrayList<String> fileListInternal = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getInternalTempPath(this, vmID, peddingTempFolder), fileListInternal);
for (int position = 0; position < fileListInternal.size(); position++) {
FileUtils.moveToFolder(fileListInternal.get(position), VmFileManager.getPath(vmID));
}
}
// STORAGE LOGIC CORE
private void setupStorageUi() {
binding.drive.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_0_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_0_FILE_MODE);
}
});
binding.tieHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_1_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_1_FILE_MODE);
}
});
if (MainSettingsManager.getArch(this).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
}
binding.tieFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_A_FILE_MODE, null));
binding.tieFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_B_FILE_MODE, null));
binding.cdrom.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_0_FILE_MODE, null));
binding.tieCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_1_FILE_MODE, null));
binding.svSharedFolder.setSubTitle(AppConfig.sharedFolder);
binding.svSharedFolder.setOnCheckedChangeListener((v, isChecked) -> sharedFolder = isChecked);
}
private final int SELECT_DISK_0_FILE_MODE = 0;
private final int SELECT_DISK_1_FILE_MODE = 1;
public final int SELECT_CDROM_0_FILE_MODE = 2;
public final int SELECT_CDROM_1_FILE_MODE = 3;
public final int SELECT_FLOPPY_A_FILE_MODE = 4;
public final int SELECT_FLOPPY_B_FILE_MODE = 5;
private int PENDING_SELECT_FILE_MODE = 0;
private String PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
private void pickStorageFile(int mode) {
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
try {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
builtInFilePicker(PICK_OPTICAL_FILE_MODE);
} else {
isoPicker.launch("*/*");
}
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
builtInFilePicker(PICK_FLOPPY_FILE_MODE);
} else {
floppyPicker.launch("*/*");
}
} else {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
builtInFilePicker(PICK_DRIVE_FILE_MODE);
} else {
diskPicker.launch("*/*");
}
}
} catch (Exception e) {
Log.e(TAG, "pickStorageFile: ", e);
IntentUtils.showErrorDialog(this);
}
}
private void storageFileOptionDialog(int mode) {
PENDING_SELECT_FILE_MODE = mode;
//TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
DialogUtils.threeDialog(this,
getString(R.string.change_hard_drive),
getString(R.string.do_you_want_to_change_create_or_remove),
getString(R.string.change), getString(R.string.remove),
getString(R.string.create),
true,
R.drawable.hard_drive_24px,
true,
() -> pickStorageFile(mode),
() -> {
String path = new File(Objects.requireNonNull(peddingTextInputEditText.getText()).toString()).getAbsolutePath();
if (path.startsWith(VmFileManager.quickGetPath(vmID))) {
ProgressDialog progressDialog1 = new ProgressDialog(this);
progressDialog1.show();
new Thread(() -> {
markDelete(path);
runOnUiThread(progressDialog1::reset);
}).start();
}
setDrive(mode, "");
},
() -> {
if (createVMFolder(true)) {
callQcow2CreatorDialog(PENDING_SELECT_FILE_MODE);
}
}, null);
}
private void callQcow2CreatorDialog(int mode) {
PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
CreateImageDialogFragment dialogFragment = new CreateImageDialogFragment();
dialogFragment.folder = VmFileManager.getPath(vmID);
dialogFragment.customRom = true;
dialogFragment.filename = Objects.requireNonNull(binding.title.getText()).toString();
dialogFragment.drive = peddingTextInputEditText;
dialogFragment.driveLayout = peddingTextInputLayout;
dialogFragment.isMarkPendingAdd = true;
dialogFragment.show(getSupportFragmentManager(), "CreateImageDialogFragment");
}
private void setRemovableDriveEndIconOnClickListener(int mode, TextInputLayout textInputLayout) {
textInputLayout.setEndIconOnClickListener(v -> {
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
setDrive(mode, null);
});
}
private void setDrive(Integer mode, String path) {
if (isFileReadyinUse(path)) {
DialogUtils.oopsDialog(this, getString(R.string.vm_creator_this_file_is_already_in_use_content));
deleteTemp(new File(path).getName());
return;
}
if (mode != null) PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
peddingTextInputEditText.setText(path != null ? path : "");
if (path == null || path.isEmpty()) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_NONE);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.add_24px);
}
} else {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM);
peddingTextInputLayout.setEndIconDrawable(R.drawable.close_24px);
setRemovableDriveEndIconOnClickListener(PENDING_SELECT_FILE_MODE, peddingTextInputLayout);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.more_vert_24px);
}
}
if (!PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE.isEmpty()) {
onFileChange(new File(PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE).getName());
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
}
}
private TextInputLayout getPeddingStorageInputLayout() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tilHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdromField;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tilCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tilFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tilFdb;
} else {
return binding.driveField;
}
}
private TextInputEditText getPeddingStorageEditText() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tieHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdrom;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tieCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tieFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tieFdb;
} else {
return binding.drive;
}
}
private boolean isAllDriveEmpty() {
return (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.cdrom.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieCdrom1.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieFda.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieFdb.getText()).toString().isEmpty());
}
private boolean isFileReadyinUse(String path) {
if (path == null || path.trim().isEmpty()) return false;
String paramCollection = Objects.requireNonNull(binding.drive.getText()).toString();
paramCollection += "\n" + Objects.requireNonNull(binding.tieHd1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.cdrom.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieCdrom1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFda.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFdb.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.qemu.getText());
return paramCollection.contains(path);
return (current.itemPath.isEmpty() &&
current.hd1.isEmpty() &&
current.imgCdrom.isEmpty() &&
current.cdrom1.isEmpty() &&
current.fda.isEmpty() &&
current.fdb.isEmpty());
}
private void checkCreateCommandConfig() {
@ -1508,23 +1019,4 @@ public class VMCreatorActivity extends AppCompatActivity {
});
}
}
final int PICK_DRIVE_FILE_MODE = 0;
final int PICK_OPTICAL_FILE_MODE = 1;
final int PICK_FLOPPY_FILE_MODE = 2;
private void builtInFilePicker(int mode) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
int finalMode;
if (mode == PICK_DRIVE_FILE_MODE) {
finalMode = filePickerDialog.FIT_PICK_DISK_FILE_MODE;
} else if (mode == PICK_OPTICAL_FILE_MODE) {
finalMode = filePickerDialog.FIT_PICK_OPTICAL_FILE_MODE;
} else {
finalMode = filePickerDialog.FIT_PICK_FLOPPY_FILE_MODE;
}
filePickerDialog.pick(this, finalMode, (path -> handleFile(Uri.fromFile(new File(path)))));
}
}

View file

@ -2,26 +2,13 @@ package com.vectras.vm.creator;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.MaterialColors;
import com.vectras.vm.R;
import com.vectras.vm.databinding.DialogListSelectorLayoutBinding;
import com.vectras.vm.databinding.SimpleLayoutListViewWithCheckBinding;
import com.vectras.vm.creator.configs.ListManager;
import com.vectras.vm.utils.UniversalPickerDialog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
public class VMCreatorSelector {
private static final String TAG = "VMCreatorSelector";
@ -54,6 +41,14 @@ public class VMCreatorSelector {
showDialog(activity, ListManager.threads(arch), position, callback, activity.getString(R.string.thread));
}
public static void networkCard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.networkCards(activity), position, callback, activity.getString(R.string.network_card));
}
public static HashMap<String, Object> getNetworkCard(Context context, int position) {
return ListManager.networkCards(context).get(position);
}
public static HashMap<String, Object> getBootFrom(Context context, int position) {
return ListManager.bootFrom(context).get(position);
}

View file

@ -1,4 +1,4 @@
package com.vectras.vm.creator;
package com.vectras.vm.creator.configs;
import android.content.Context;
@ -145,4 +145,28 @@ public class ListManager {
return list;
}
public static ArrayList<HashMap<String, Object>> networkCards(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.none), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000e_82574l), "e1000e");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_igb_82576), "igb");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82540em), "e1000");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82545em), "e1000-82545em");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82544gc), "e1000-82544gc");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82801), "i82801");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82562), "i82562");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82559er), "i82559er");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82558b), "i82558b");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82557c), "i82557c");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82551), "i82551");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82550), "i82550");
UniversalPickerDialog.putToList(list, context.getString(R.string.realtek_rtl8139), "rtl8139");
UniversalPickerDialog.putToList(list, context.getString(R.string.amd_pcnet), "pcnet");
UniversalPickerDialog.putToList(list, context.getString(R.string.novell_ne2000), "ne2k_pci");
UniversalPickerDialog.putToList(list, context.getString(R.string.vmware_vmxnet3), "vmxnet3");
UniversalPickerDialog.putToList(list, context.getString(R.string.virtio_net), "virtio-net-pci");
UniversalPickerDialog.putToList(list, context.getString(R.string.virtio_net_transitional), "virtio-net-pci-transitional");
return list;
}
}

View file

@ -0,0 +1,108 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.creator.QemuParamsEditorActivity;
import com.vectras.vm.databinding.CreatorAdvancedDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import java.util.Objects;
public class AdvancedConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "AdvancedConfigsDialog";
String vmId;
DataMainRoms configs;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorAdvancedDialogBinding binding;
boolean iseditparams;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
binding = CreatorAdvancedDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
public void onResume() {
super.onResume();
if (iseditparams) {
iseditparams = false;
binding.qemu.setText(QemuParamsEditorActivity.result);
}
}
AdvancedConfigsDialogCallback callback;
public void setOnDismiss(AdvancedConfigsDialogCallback callback) {
this.callback = callback;
}
public interface AdvancedConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
binding.qemu.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(requireContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
binding.qemuField.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(requireContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
load();
}
private void load() {
binding.qemu.setText(configs.itemExtra);
}
private void save() {
configs.itemExtra = Objects.requireNonNull(binding.qemu.getText()).toString();
}
}

View file

@ -0,0 +1,102 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorBoardDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import java.util.Objects;
public class BoardConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "BoardConfigsDialog";
String vmId;
DataMainRoms configs;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorBoardDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
binding = CreatorBoardDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
BoardConfigsDialogCallback callback;
public void setOnDismiss(BoardConfigsDialogCallback callback) {
this.callback = callback;
}
public interface BoardConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
binding.sbvCpu.setOnClickListener(v -> VMCreatorSelector.cpu(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.cpu, ((position, name, value) -> {
configs.cpu = position;
binding.sbvCpu.setSubtitle(name);
})));
binding.sbvCore.setOnClickListener(v -> VMCreatorSelector.cpuCore(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.cores, ((position, name, value) -> {
configs.cores = position;
binding.sbvCore.setSubtitle(name);
})));
binding.sbvThread.setOnClickListener(v -> VMCreatorSelector.cpuThread(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.threads, ((position, name, value) -> {
configs.threads = position;
binding.sbvThread.setSubtitle(name);
})));
load();
}
private void load() {
binding.sbvCpu.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpu(requireContext(), MainSettingsManager.getArch(requireContext()), configs.cpu).get("name")).toString());
binding.sbvCore.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpuCore(MainSettingsManager.getArch(requireContext()), configs.cores).get("value")).toString());
binding.sbvThread.setSubtitle(String.valueOf(configs.threads + 1));
binding.cbvBattery.setChecked(configs.battery);
}
private void save() {
configs.battery = binding.cbvBattery.isChecked();
}
}

View file

@ -0,0 +1,124 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorFirmwareDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import java.util.Objects;
public class FirmwareConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "FirmwareConfigsDialog";
String vmId;
DataMainRoms configs;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorFirmwareDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
binding = CreatorFirmwareDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
FirmwareConfigsDialogCallback callback;
public void setOnDismiss(FirmwareConfigsDialogCallback callback) {
this.callback = callback;
}
public interface FirmwareConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
binding.sbvBootfrom.setOnClickListener(v -> VMCreatorSelector.bootFrom(requireActivity(), configs.bootFrom, ((position, name, value) -> {
configs.bootFrom = position;
binding.sbvBootfrom.setSubtitle(name);
})));
binding.cbvShowbootmenu.setOnCheckedChangeListener((v, isChecked) -> configs.isShowBootMenu = isChecked);
binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> configs.isUseLocalTime = isChecked);
if (!MainSettingsManager.getArch(requireContext()).equals("X86_64")) {
binding.cbvUseuefi.setVisibility(View.GONE);
binding.cbvUseDefaultBios.setBackground(AppCompatResources.getDrawable(requireContext(), R.drawable.object_shape_single_high));
} else {
binding.cbvUseuefi.setOnCheckedChangeListener((v, isChecked) -> configs.isUseUefi = isChecked);
}
binding.cbvUseDefaultBios.setOnCheckedChangeListener((v, isChecked) -> {
configs.isUseDefaultBios = isChecked;
binding.cbvUseuefi.setEnabled(isChecked);
});
load();
}
private void load() {
binding.sbvBootfrom.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getBootFrom(requireActivity(), configs.bootFrom).get("name")).toString());
binding.cbvShowbootmenu.setChecked(configs.isShowBootMenu);
if (MainSettingsManager.getArch(requireContext()).equals(MainSettingsManager.X86_64_ARCH)) {
binding.cbvUseuefi.setChecked(configs.isUseUefi);
} else {
binding.cbvUseuefi.setVisibility(View.GONE);
}
binding.cbvUseDefaultBios.setChecked(configs.isUseDefaultBios);
binding.cbvUseuefi.setEnabled(configs.isUseDefaultBios);
binding.cbvUselocaltime.setChecked(configs.isUseLocalTime);
}
private void save() {
configs.isShowBootMenu = binding.cbvShowbootmenu.isChecked();
configs.isUseUefi = binding.cbvUseuefi.isChecked();
configs.isUseDefaultBios = binding.cbvUseDefaultBios.isChecked();
configs.isUseLocalTime = binding.cbvUselocaltime.isChecked();
}
}

View file

@ -0,0 +1,86 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorNetworkDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import java.util.Objects;
public class NetworkConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "NetworkConfigsDialog";
String vmId;
DataMainRoms configs;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorNetworkDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
binding = CreatorNetworkDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
NetworkConfigsDialogCallback callback;
public void setOnDismiss(NetworkConfigsDialogCallback callback) {
this.callback = callback;
}
public interface NetworkConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
binding.sbvCardType.setOnClickListener(v -> VMCreatorSelector.networkCard(requireActivity(), configs.networkCard, ((position, name, value) -> {
configs.networkCard = position;
binding.sbvCardType.setSubtitle(name);
})));
load();
}
private void load() {
binding.sbvCardType.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getNetworkCard(requireActivity(), configs.networkCard).get("name")).toString());
}
private void save() {
// It may be used in subsequent versions.
}
}

View file

@ -0,0 +1,569 @@
package com.vectras.vm.creator.editor;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.Fragment.CreateImageDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.CreatorUtils;
import com.vectras.vm.databinding.CreatorStorageDialogBinding;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.manager.FormatManager;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.IntentUtils;
import com.vectras.vm.utils.ProgressDialog;
import java.io.File;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class StorageConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "StorageConfigsDialog";
String vmId;
DataMainRoms configs;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
if (isAdded()) utils = new CreatorUtils(requireActivity(), vmId);
}
}
CreatorStorageDialogBinding binding;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private CreatorUtils utils;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
binding = CreatorStorageDialogBinding.inflate(getLayoutInflater());
utils = new CreatorUtils(requireActivity(), vmId);
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
StorageConfigsDialogCallback callback;
public void setOnDismiss(StorageConfigsDialogCallback callback) {
this.callback = callback;
}
public interface StorageConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null) {
save();
callback.onDismiss(configs);
}
}
private final ActivityResultLauncher<String> diskPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
handleDiskFile(uri);
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> isoPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(requireActivity(), uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isOpticalFileFormat(fileName)) {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_optical_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.album_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> floppyPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(requireActivity(), uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isFloppyFileFormat(fileName)) {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_floppy_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.save_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
private void handleFile(Uri uri) {
if (MainSettingsManager.copyFile(requireActivity())) {
utils.showProgressDialog(getString(R.string.copying_file));
executor.execute(() -> {
try {
String path = utils.copyToTemp(uri);
requireActivity().runOnUiThread(() -> setDrive(PENDING_SELECT_FILE_MODE, path));
} catch (Exception e) {
requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.oops),
getString(R.string.unable_to_copy_file_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null));
Log.e(TAG, "isoPicker: " + e.getMessage());
} finally {
requireActivity().runOnUiThread(() -> utils.dissmissProgressDialog());
}
});
} else {
executor.execute(() -> {
CreatorUtils.FilePathData filePathData = utils.getFilePath(uri);
if (!filePathData.isValid) {
requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.problem_has_been_detected),
getString(R.string.invalid_file_path_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null)
);
} else {
requireActivity().runOnUiThread(() -> utils.showProgressDialog(getString(R.string.just_a_moment)));
requireActivity().runOnUiThread(() -> {
setDrive(PENDING_SELECT_FILE_MODE, new File(filePathData.path).getAbsolutePath());
utils.dissmissProgressDialog();
});
}
});
}
}
private void handleDiskFile(Uri uri) {
ProgressDialog progressDialog1 = new ProgressDialog(requireActivity());
progressDialog1.show();
new Thread(() -> {
CreatorUtils.FilePathData filePathData = utils.getFilePath(uri);
if (filePathData.isValid) {
requireActivity().runOnUiThread(() -> {
progressDialog1.reset();
if (FormatManager.isHardDriveFileFormat(filePathData.name)) {
startHandleHardDriveFile(uri);
} else {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_hard_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.hard_drive_24px, true,
() -> startHandleHardDriveFile(uri), null, null);
}
});
} else {
requireActivity().runOnUiThread(() -> startHandleHardDriveFile(uri));
}
}).start();
}
@SuppressLint("SetTextI18n")
private void startHandleHardDriveFile(Uri _content_describer) {
if (MainSettingsManager.copyFile(requireActivity())) {
if (requireActivity().isFinishing() || requireActivity().isDestroyed()) return;
utils.showProgressDialog(getString(R.string.copying_file));
executor.execute(() -> {
try {
String _filename = FileUtils.getFileNameFromUri(requireActivity(), _content_describer);
if (_filename == null || _filename.isEmpty()) {
_filename = String.valueOf(System.currentTimeMillis());
}
String path = utils.copyToTemp(_content_describer);
String final_filename = _filename;
requireActivity().runOnUiThread(() -> {
if (requireActivity().isFinishing() || requireActivity().isDestroyed()) {
if (!vmId.isEmpty())
FileUtils.delete(new File(VmFileManager.getPath(vmId, final_filename)));
return;
}
setDrive(PENDING_SELECT_FILE_MODE, path);
});
} catch (Exception e) {
requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.oops),
getString(R.string.unable_to_copy_hard_drive_file_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null));
} finally {
requireActivity().runOnUiThread(() -> utils.dissmissProgressDialog());
}
});
} else {
ProgressDialog progressDialog1 = new ProgressDialog(requireActivity());
progressDialog1.show();
new Thread(() -> {
String path = FileUtils.getPath(requireContext(), _content_describer);
requireActivity().runOnUiThread(() -> {
progressDialog1.reset();
if (!FileUtils.isValidFilePath(requireActivity(), path, false)) {
DialogUtils.oneDialog(requireActivity(),
getString(R.string.problem_has_been_detected),
getString(R.string.invalid_file_path_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null);
} else {
setDrive(PENDING_SELECT_FILE_MODE, path);
}
});
}).start();
}
}
private void onFileChange(String fileName) {
utils.markDelete(VmFileManager.getPath(vmId, fileName));
}
// STORAGE LOGIC CORE
private void initialize() {
binding.drive.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_0_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_0_FILE_MODE);
}
});
binding.tieHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_1_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_1_FILE_MODE);
}
});
if (MainSettingsManager.getArch(requireActivity()).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
}
binding.tieFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_A_FILE_MODE, null));
binding.tieFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_B_FILE_MODE, null));
binding.cdrom.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_0_FILE_MODE, null));
binding.tieCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_1_FILE_MODE, null));
binding.svSharedFolder.setSubTitle(AppConfig.sharedFolder);
load();
}
private final int SELECT_DISK_0_FILE_MODE = 0;
private final int SELECT_DISK_1_FILE_MODE = 1;
public final int SELECT_CDROM_0_FILE_MODE = 2;
public final int SELECT_CDROM_1_FILE_MODE = 3;
public final int SELECT_FLOPPY_A_FILE_MODE = 4;
public final int SELECT_FLOPPY_B_FILE_MODE = 5;
private int PENDING_SELECT_FILE_MODE = 0;
private String PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
private void pickStorageFile(int mode) {
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
try {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_OPTICAL_FILE_MODE);
} else {
isoPicker.launch("*/*");
}
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_FLOPPY_FILE_MODE);
} else {
floppyPicker.launch("*/*");
}
} else {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_DRIVE_FILE_MODE);
} else {
diskPicker.launch("*/*");
}
}
} catch (Exception e) {
Log.e(TAG, "pickStorageFile: ", e);
IntentUtils.showErrorDialog(requireActivity());
}
}
private void storageFileOptionDialog(int mode) {
PENDING_SELECT_FILE_MODE = mode;
//TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
DialogUtils.threeDialog(requireActivity(),
getString(R.string.change_hard_drive),
getString(R.string.do_you_want_to_change_create_or_remove),
getString(R.string.change), getString(R.string.remove),
getString(R.string.create),
true,
R.drawable.hard_drive_24px,
true,
() -> pickStorageFile(mode),
() -> {
String path = new File(Objects.requireNonNull(peddingTextInputEditText.getText()).toString()).getAbsolutePath();
if (path.startsWith(VmFileManager.quickGetPath(vmId))) {
ProgressDialog progressDialog1 = new ProgressDialog(requireActivity());
progressDialog1.show();
new Thread(() -> {
utils.markDelete(path);
requireActivity().runOnUiThread(progressDialog1::reset);
}).start();
}
setDrive(mode, "");
},
() -> callQcow2CreatorDialog(PENDING_SELECT_FILE_MODE), null);
}
private void callQcow2CreatorDialog(int mode) {
PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
CreateImageDialogFragment dialogFragment = new CreateImageDialogFragment();
dialogFragment.folder = VmFileManager.getPath(vmId);
dialogFragment.customRom = true;
dialogFragment.filename = configs.itemName;
dialogFragment.drive = peddingTextInputEditText;
dialogFragment.driveLayout = peddingTextInputLayout;
dialogFragment.isMarkPendingAdd = true;
dialogFragment.show(requireActivity().getSupportFragmentManager(), "CreateImageDialogFragment");
}
private void setRemovableDriveEndIconOnClickListener(int mode, TextInputLayout textInputLayout) {
textInputLayout.setEndIconOnClickListener(v -> {
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
setDrive(mode, null);
});
}
private void setDrive(Integer mode, String path) {
if (isFileReadyinUse(path)) {
DialogUtils.oopsDialog(requireActivity(), getString(R.string.vm_creator_this_file_is_already_in_use_content));
utils.deleteTemp(new File(path).getName());
return;
}
if (mode != null) PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
peddingTextInputEditText.setText(path != null ? path : "");
if (path == null || path.isEmpty()) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_NONE);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.add_24px);
}
} else {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM);
peddingTextInputLayout.setEndIconDrawable(R.drawable.close_24px);
setRemovableDriveEndIconOnClickListener(PENDING_SELECT_FILE_MODE, peddingTextInputLayout);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.more_vert_24px);
}
}
if (!PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE.isEmpty()) {
onFileChange(new File(PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE).getName());
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
}
}
private TextInputLayout getPeddingStorageInputLayout() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tilHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdromField;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tilCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tilFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tilFdb;
} else {
return binding.driveField;
}
}
private TextInputEditText getPeddingStorageEditText() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tieHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdrom;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tieCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tieFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tieFdb;
} else {
return binding.drive;
}
}
private boolean isFileReadyinUse(String path) {
if (path == null || path.trim().isEmpty()) return false;
String paramCollection = Objects.requireNonNull(binding.drive.getText()).toString();
paramCollection += "\n" + Objects.requireNonNull(binding.tieHd1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.cdrom.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieCdrom1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFda.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFdb.getText());
paramCollection += "\n" + Objects.requireNonNull(configs.itemExtra);
return paramCollection.contains(path);
}
final int PICK_DRIVE_FILE_MODE = 0;
final int PICK_OPTICAL_FILE_MODE = 1;
final int PICK_FLOPPY_FILE_MODE = 2;
private void builtInFilePicker(int mode) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
int finalMode;
if (mode == PICK_DRIVE_FILE_MODE) {
finalMode = FilePickerDialog.FIT_PICK_DISK_FILE_MODE;
} else if (mode == PICK_OPTICAL_FILE_MODE) {
finalMode = FilePickerDialog.FIT_PICK_OPTICAL_FILE_MODE;
} else {
finalMode = FilePickerDialog.FIT_PICK_FLOPPY_FILE_MODE;
}
filePickerDialog.pick(requireActivity(), finalMode, (path -> handleFile(Uri.fromFile(new File(path)))));
}
private void load() {
if (configs.itemPath != null && !configs.itemPath.isEmpty()) {
setDrive(SELECT_DISK_0_FILE_MODE, (configs.itemPath.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.itemPath));
}
if (configs.hd1 != null && !configs.hd1.isEmpty()) {
setDrive(SELECT_DISK_1_FILE_MODE, (configs.hd1.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.hd1));
}
if (MainSettingsManager.getArch(getContext()).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
} else {
if (configs.fda!= null && !configs.fda.isEmpty()) {
setDrive(SELECT_FLOPPY_A_FILE_MODE, (configs.fda.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.fda));
}
if (configs.fdb!= null && !configs.fdb.isEmpty()) {
setDrive(SELECT_FLOPPY_B_FILE_MODE, (configs.fdb.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.fdb));
}
}
if (configs.imgCdrom != null && !configs.imgCdrom.isEmpty()) {
setDrive(SELECT_CDROM_0_FILE_MODE, (configs.imgCdrom.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.imgCdrom));
}
if (configs.cdrom1 != null && !configs.cdrom1.isEmpty()) {
setDrive(SELECT_CDROM_1_FILE_MODE, (configs.cdrom1.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.cdrom1));
}
binding.svSharedFolder.setChecked(configs.sharedFolder);
}
private void save() {
configs.itemPath = Objects.requireNonNull(binding.drive.getText()).toString();
configs.hd1 = Objects.requireNonNull(binding.tieHd1.getText()).toString();
configs.fda = Objects.requireNonNull(binding.tieFda.getText()).toString();
configs.fdb = Objects.requireNonNull(binding.tieFdb.getText()).toString();
configs.imgCdrom = Objects.requireNonNull(binding.cdrom.getText()).toString();
configs.cdrom1 = Objects.requireNonNull(binding.tieCdrom1.getText()).toString();
configs.sharedFolder = binding.svSharedFolder.isChecked();
}
}

View file

@ -0,0 +1,107 @@
package com.vectras.vm.creator.utils;
import android.app.Activity;
import android.net.Uri;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ProgressDialog;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class CreatorUtils {
public static final String PENDING_FOLDER = "pending/";
Activity activity;
String vmId;
ProgressDialog progressDialog;
public CreatorUtils(Activity activity, String vmId) {
this.activity = activity;
this.vmId = vmId;
}
public void showProgressDialog(String message) {
if (progressDialog == null) progressDialog = new ProgressDialog(activity);
progressDialog.setText(message);
if (!activity.isFinishing() && !activity.isDestroyed()) progressDialog.show();
}
public void dissmissProgressDialog() {
if (progressDialog != null && !activity.isFinishing() && !activity.isDestroyed()) {
progressDialog.dismiss();
}
}
public String getTempPath(String fileName) {
return VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER + fileName);
}
public boolean removeTemp() {
return VmFileManager.removeTemp(activity, vmId, PENDING_FOLDER);
}
public String copyToTemp(Uri uri) throws IOException {
String fileName = FileUtils.getFileNameFromUri(activity, uri);
if (fileName == null || fileName.isEmpty()) {
fileName = String.valueOf(System.currentTimeMillis());
}
FileUtils.copyFileFromUri(activity, uri, VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER + fileName));
return VmFileManager.getPath(vmId, fileName);
}
public void moveAllFromTemp() {
ArrayList<String> fileList = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER), fileList);
for (int position = 0; position < fileList.size(); position++) {
FileUtils.moveToFolder(fileList.get(position), VmFileManager.getPath(vmId));
}
ArrayList<String> fileListInternal = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getInternalTempPath(activity, vmId, PENDING_FOLDER), fileListInternal);
for (int position = 0; position < fileListInternal.size(); position++) {
FileUtils.moveToFolder(fileListInternal.get(position), VmFileManager.getPath(vmId));
}
}
public void deleteTemp(String fileName) {
VmFileManager.removeTemp(activity, vmId, PENDING_FOLDER + fileName);
}
public void markDelete(String path) {
VmFileManager.markPendingDelete(path);
deleteTemp(new File(path).getName());
}
public FilePathData getFilePath(Uri uri) {
try {
String filePath = FileUtils.getPath(activity, uri);
if (filePath != null && FileUtils.isFileExists(filePath)) {
return new FilePathData() {
{
isValid = true;
path = filePath;
name = new File(filePath).getName();
}
};
}
} catch (Exception e) {
return new FilePathData();
}
return new FilePathData();
}
public static class FilePathData {
public boolean isValid = false;
public String path;
public String name;
}
}

View file

@ -3,9 +3,15 @@ package com.vectras.vm.main.vms;
import com.google.gson.annotations.SerializedName;
public class DataMainRoms {
public int cpu = 0;
public int cores = 0;
public int threads = 0;
public String vmID = "";
@SerializedName(
value = "arch",
alternate = { "imgArch" }
)
public String itemArch = "";
// Personalize
@SerializedName(
value = "icon",
@ -19,11 +25,15 @@ public class DataMainRoms {
)
public String itemName = "";
@SerializedName(
value = "arch",
alternate = { "imgArch" }
)
public String itemArch = "";
// Board
public int cpu = 0;
public int cores = 0;
public int threads = 0;
public boolean battery = false;
// Storage
@SerializedName(
value = "drive",
@ -33,11 +43,6 @@ public class DataMainRoms {
public String hd1 = "";
@SerializedName(
value = "qemu",
alternate = { "imgExtra" }
)
public String itemExtra = "";
@SerializedName(
value = "cdrom",
@ -47,15 +52,19 @@ public class DataMainRoms {
public String cdrom1 = "";
public String fda = "";
public String fdb = "";
public boolean sharedFolder = false;
public String vmID = "";
// Network
public int qmpPort = 0;
public int networkCard = 0;
// Firmware
public int bootFrom = 0;
@ -67,5 +76,16 @@ public class DataMainRoms {
public boolean isUseDefaultBios = true;
public boolean battery = false;
// Advanced
@SerializedName(
value = "qemu",
alternate = { "imgExtra" }
)
public String itemExtra = "";
// Deprecated
@Deprecated
public int qmpPort = 0;
}

View file

@ -49,7 +49,7 @@ public class CheckBoxView extends LinearLayout {
typedArray.recycle();
}
findViewById(R.id.root).setOnClickListener(v -> checkBox.setChecked(!checkBox.isChecked()));
setOnClickListener(v -> checkBox.setChecked(!checkBox.isChecked()));
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (listener != null) {

View file

@ -52,7 +52,7 @@ public class SwitchView extends LinearLayout {
typedArray.recycle();
}
findViewById(R.id.root).setOnClickListener(v -> switchWidget.setChecked(!switchWidget.isChecked()));
setOnClickListener(v -> switchWidget.setChecked(!switchWidget.isChecked()));
switchWidget.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (listener != null) {

View file

@ -58,87 +58,74 @@
android:orientation="vertical"
android:padding="8dp">
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
android:layout_marginBottom="2dp"
android:orientation="vertical"
android:padding="16dp"
android:background="@drawable/object_shape_top_high">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/personalization" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp">
<RelativeLayout
<ImageView
android:id="@+id/ivIcon"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_computer_180dp_with_padding" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|end">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_computer_180dp_with_padding" />
android:id="@+id/ivAddThubnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/backgroud_round_only_left_25_black_50_style"
android:padding="4dp"
app:srcCompat="@drawable/round_add_24"
app:tint="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|end">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/titleField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/rom_name"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/edit_24px">
<ImageView
android:id="@+id/ivAddThubnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/backgroud_round_only_left_25_black_50_style"
android:padding="4dp"
app:srcCompat="@drawable/round_add_24"
app:tint="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/titleField"
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/rom_name"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/edit_24px">
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/opencqcm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:background="@drawable/object_shape_single_high"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
@ -169,378 +156,171 @@
android:id="@+id/opencqcm_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/keyboard_arrow_right_24px"
android:src="@drawable/open_in_new_24px"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_board"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:paddingTop="16dp">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="8dp"
android:text="@string/board" />
android:text="@string/board"
android:textSize="18sp" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_cpu"
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:title="@string/processor"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_core"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/cores"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_thread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/threads"
app:subtitle="@string/defaulttext" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/battery"/>
android:text="@string/board_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_storage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:paddingTop="16dp">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:text="@string/storage" />
android:text="@string/storage"
android:textSize="18sp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/driveField"
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/drive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"
android:layout_marginHorizontal="16dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/cdromField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/cdrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/ln_floppy_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_a"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_b"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.SwitchView
android:id="@+id/sv_shared_folder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/shared_folder"
app:subtitle="SharedFolder/"/>
android:text="@string/storage_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_network"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:paddingTop="16dp">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="8dp"
android:text="@string/boot" />
android:text="@string/network"
android:textSize="18sp" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_bootfrom"
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:title="@string/boot_from"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_showbootmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/show_boot_menu"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_uselocaltime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_local_time"
app:setChecked="true"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_useuefi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_uefi_for_x64_only"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_use_default_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_default_bios_uefi"
app:setChecked="true" />
android:text="@string/network_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_firmware"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:padding="16dp">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/advanced" />
android:text="@string/firmware"
android:textSize="18sp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/qemuField"
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/qemu_params"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/ic_qemu">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/qemu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="none"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
android:text="@string/firmware_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_advanced"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_bottom_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/advanced"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/advanced_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/lineardisclaimer"
@ -548,13 +328,13 @@
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingVertical="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:src="@drawable/verified_user_24px" />
<TextView

View file

@ -6,8 +6,7 @@
android:paddingVertical="8dp"
android:paddingStart="16dp"
android:paddingEnd="8dp"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
android:gravity="center_vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"

View file

@ -99,6 +99,14 @@
android:text="@string/free_palistine"
android:textSize="16sp" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_open_source_licenses"
style="?attr/buttonBarNegativeButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_source_licenses"/>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:text="@string/advanced" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/qemuField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:hint="@string/qemu_params"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/ic_qemu">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/qemu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="none"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/board" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_cpu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/processor"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_core"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/cores"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_middle_high"/>
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_thread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/threads"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_bottom_high"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/battery"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/firmware" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_bootfrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/boot_from"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_showbootmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/show_boot_menu"
android:background="@drawable/object_shape_middle_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_uselocaltime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/use_local_time"
app:setChecked="true"
android:background="@drawable/object_shape_bottom_high"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_useuefi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/use_uefi_for_x64_only"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_use_default_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_default_bios_uefi"
app:setChecked="true"
android:background="@drawable/object_shape_bottom_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/network" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_card_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/card_type"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/storage" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/driveField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/drive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/cdromField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/cdrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/ln_floppy_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_a"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_b"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"/>
<com.vectras.vm.view.SwitchView
android:id="@+id/sv_shared_folder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/shared_folder"
app:subtitle="SharedFolder/"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -29,8 +29,7 @@
<com.google.android.material.card.MaterialCardView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="?attr/materialCardViewFilledStyle"
app:cardBackgroundColor="?attr/colorSurface">
app:cardBackgroundColor="?attr/colorSurfaceContainerLowest">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="70dp"

View file

@ -5,8 +5,7 @@
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"

View file

@ -4,10 +4,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:paddingStart="16dp"
android:paddingEnd="8dp"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
android:paddingHorizontal="16dp"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"

View file

@ -793,6 +793,15 @@
<string name="the_folder_path_has_been_copied_to_the_clipboard">Đã sap chép đường dẫn thư mục vào bảng tạm.</string>
<string name="divider">Đường phân cách</string>
<string name="file_picker_divier_note">Thêm các đường phân cách giữa các mục.</string>
<string name="storage_note">Các ổ lưu trữ, thư mục được chia sẻ,…</string>
<string name="open_source_licenses">Giấy phép nguồn mở</string>
<string name="board_note">Bộ xử lý, nhân, luồng,…</string>
<string name="firmware">Phần mềm</string>
<string name="firmware_note">UEFI, khởi động từ, tuỳ chọn khởi động,…</string>
<string name="advanced_note">Các tham số mở rộng,…</string>
<string name="card_type">Loại thẻ</string>
<string name="network_card">Thẻ mạng</string>
<string name="none">Trống</string>
<!-- CPUs -->

View file

@ -652,6 +652,16 @@
<string name="the_folder_path_has_been_copied_to_the_clipboard">The folder path has been copied to the clipboard.</string>
<string name="divider">Divider</string>
<string name="file_picker_divier_note">Add dividers between items.</string>
<string name="storage_note">Drives, shared folder,…</string>
<string name="open_source_licenses">Open source licenses</string>
<string name="board_note">Processor, cores, threads,…</string>
<string name="firmware">Firmware</string>
<string name="firmware_note">UEFI, boot from, boot menu,…</string>
<string name="advanced_note">Extra params,…</string>
<string name="network_note">Network card,…</string>
<string name="card_type">Card type</string>
<string name="network_card">Network card</string>
<string name="none">None</string>
<!--======================TERMUX STRINGS====================-->
@ -881,6 +891,27 @@
<string name="g3_cpu" translatable="false">G3</string>
<string name="g2_cpu_workstation">G2 (Workstation)</string>
<string name="g2_cpu_low_power">G2 (Low-Power)</string>
<!-- Network cards -->
<string name="intel_e1000e_82574l" translatable="false">Intel E1000E (82574L)</string>
<string name="intel_igb_82576" translatable="false">Intel IGB (82576)</string>
<string name="intel_e1000_82540em" translatable="false">Intel E1000 (82540EM)</string>
<string name="intel_e1000_82545em" translatable="false">Intel E1000 (82545EM)</string>
<string name="intel_e1000_82544gc" translatable="false">Intel E1000 (82544GC)</string>
<string name="intel_i82801" translatable="false">Intel i82801</string>
<string name="intel_i82562" translatable="false">Intel i82562</string>
<string name="intel_i82559er" translatable="false">Intel i82559ER</string>
<string name="intel_i82558b" translatable="false">Intel i82558B</string>
<string name="intel_i82557c" translatable="false">Intel i82557C</string>
<string name="intel_i82551" translatable="false">Intel i82551</string>
<string name="intel_i82550" translatable="false">Intel i82550</string>
<string name="realtek_rtl8139" translatable="false">Realtek RTL8139</string>
<string name="amd_pcnet" translatable="false">AMD PCNET</string>
<string name="novell_ne2000" translatable="false">Novell NE2000</string>
<string name="vmware_vmxnet3" translatable="false">VMWare (VMXNET3)</string>
<string name="virtio_net" translatable="false">VirtIO Net</string>
<string name="virtio_net_transitional" translatable="false">VirtIO Net (Transitional)</string>
<!-- Feature: User Profile -->
<!-- Feature: Settings -->

View file

@ -15,6 +15,7 @@ buildscript {
// Add other classpaths like Google Services and Firebase Crashlytics if needed here.
classpath libs.google.services // assuming you need it for your project
classpath libs.firebase.crashlytics.gradle
classpath libs.play.services.oss.licenses.plugin
// assuming you need it for project
}
}

View file

@ -1,9 +1,7 @@
[versions]
activityKtx = "1.13.0"
agp = "9.2.1"
annotation = "1.10.0"
appcompat = "1.7.1"
comGoogleFirebase = "firebase-crashlytics"
commonsCompress = "1.28.0"
commonsIo = "2.22.0"
constraintlayout = "2.2.1"
@ -11,16 +9,12 @@ coreKtx = "1.19.0"
documentfile = "1.1.0"
drawerlayout = "1.2.0"
espressoCore = "3.7.0"
firebaseBom = "34.15.0"
firebaseBom = "34.16.0"
firebaseCrashlyticsGradle = "3.0.7"
firebaseMessaging = "25.1.0"
glide = "5.0.7"
googleFirebase = "firebase-analytics"
googleFirebaseCrashlytics = "3.0.7"
googleGmsGoogleServices = "4.5.0"
firebaseMessaging = "25.1.1"
glide = "5.0.9"
googleServices = "4.5.0"
gradle = "9.2.1"
gradleToolchainsFoojayResolverConvention = "1.0.0"
gson = "2.14.0"
guava = "33.6.0-jre"
junit = "4.13.2"
@ -33,6 +27,8 @@ retrofit2 = "3.0.0"
swiperefreshlayout = "1.2.0"
viewpager = "1.1.0"
window = "1.5.1"
playServicesOssLicensesPlugin = "0.12.0"
playServicesOssLicenses = "17.0.0"
[libraries]
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityKtx" }
@ -67,11 +63,5 @@ kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-p
lottie = { group = "com.airbnb.android", name = "lottie", version.ref = "lottie" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit2" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
com-google-firebase = { id = "com.google.firebase", version.ref = "comGoogleFirebase" }
google-firebase = { id = "com.google.firebase", version.ref = "googleFirebase" }
google-firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "googleFirebaseCrashlytics" }
google-gms-google-services = { id = "com.google.gms.google-services", version.ref = "googleGmsGoogleServices" }
foojay-resolver = { id = "org.gradle.toolchains.foojay-resolver-convention", version.ref = "gradleToolchainsFoojayResolverConvention" }
play-services-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "playServicesOssLicensesPlugin" }
play-services-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "playServicesOssLicenses" }

View file

@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "<h2>4.3.0</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"138",
"versionNameBeta":"4.3.4",
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.1,4.2.2,4.2.3,4.2.4,4.2.5,4.2.6,4.2.7,4.2.8,4.2.9,4.3.0,4.3.1,4.3.2,4.3.3,4.3.4",
"versionCodeBeta":"139",
"versionNameBeta":"4.3.5",
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.1,4.2.2,4.2.3,4.2.4,4.2.5,4.2.6,4.2.7,4.2.8,4.2.9,4.3.0,4.3.1,4.3.2,4.3.3,4.3.4,4.3.5",
"sizeBeta": "45 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>4.3.4</h2>Bugs fixed.",
"MessageBeta": "<h2>4.3.5</h2>Bugs fixed.",
"cancellableBeta": true
}