From ca9cb3b25d659ef66e1d937b979a795dda4e9f13 Mon Sep 17 00:00:00 2001 From: An Bui <91354810+AnBui2004@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:01:49 +0700 Subject: [PATCH] 4.0.6 - Fixed the crash issue when dragging and dropping files. - Added the Use default BIOS/UEFI option in the virtual machine editing and creation settings. - Added a restriction when selecting the output save directory as the virtual machine's own directory. - Fixed the issue of the virtual machine control panel dialog freezing. - Fixed the issue of creating unused virtual machine directories. - Added automatic cleanup of empty directories and files in the virtual machine directory. - Removed the Hard drive interface, Boot from, Custom params, and Use default BIOS/UEFI options in the general Qemu settings. --- app/build.gradle | 4 +- .../com/vectras/vm/ExportRomActivity.java | 29 ++++++-- .../java/com/vectras/vm/SplashActivity.java | 2 +- app/src/main/java/com/vectras/vm/StartVM.java | 10 ++- .../main/java/com/vectras/vm/VMManager.java | 5 +- .../vectras/vm/creator/SetArchActivity.java | 33 ++++++--- .../vectras/vm/creator/VMCreatorActivity.java | 28 +++++-- .../com/vectras/vm/main/vms/DataMainRoms.java | 4 +- .../com/vectras/vm/main/vms/VmsFragment.java | 73 ++++--------------- .../vm/manager/VmControllerDialog.java | 47 ++++++++++-- .../com/vectras/vm/manager/VmFileManager.java | 16 ++++ .../java/com/vectras/vm/utils/FileUtils.java | 11 +++ .../com/vectras/vm/view/CheckBoxView.java | 2 +- .../main/res/layout/activity_vm_creator.xml | 13 +++- app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/qemu.xml | 12 +-- web/data/UpdateConfig.json | 8 +- web/data/vroms-store.json | 36 +++++++++ 20 files changed, 223 insertions(+), 113 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index eb15065..da811c5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "com.vectras.vm" minSdk minApi targetSdk targetApi - versionCode 109 - versionName "4.0.5" + versionCode 110 + versionName "4.0.6" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true diff --git a/app/src/main/java/com/vectras/vm/ExportRomActivity.java b/app/src/main/java/com/vectras/vm/ExportRomActivity.java index 4d4f13b..9e7d80e 100644 --- a/app/src/main/java/com/vectras/vm/ExportRomActivity.java +++ b/app/src/main/java/com/vectras/vm/ExportRomActivity.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -142,8 +143,9 @@ public class ExportRomActivity extends AppCompatActivity { vmConfigMap.put("bootFrom", current.bootFrom); vmConfigMap.put("isShowBootMenu", current.isShowBootMenu); - vmConfigMap.put("isUseUefi", current.isUseUefi); vmConfigMap.put("isUseLocalTime", current.isUseLocalTime); + vmConfigMap.put("isUseUefi", current.isUseUefi); + vmConfigMap.put("isUseDefaultBios", current.isUseDefaultBios); vmConfigMap.put("qemu", VmFileManager.pathToTextMark(current.vmID, current.itemExtra)); vmConfigMap.put("arch", current.itemArch); @@ -231,6 +233,21 @@ public class ExportRomActivity extends AppCompatActivity { } }*/ + String outputPath = FileUtils.getPath(this, uri); + + if (outputPath != null) { + if (outputPath.startsWith(VmFileManager.quickGetPath(current.vmID))) { + if (!new File(outputPath).isDirectory()) FileUtils.delete(outputPath); + runOnUiThread(() -> { + DialogUtils.oopsDialog(this, getString(R.string.cannot_save_here_please_choose_another_location)); + DialogUtils.safeDismiss(this, progressDialog); + }); + return; + } + } else { + outputPath = ""; + } + final boolean[] result = {ZipUtils.compress( this, finalFilePaths, @@ -238,32 +255,30 @@ public class ExportRomActivity extends AppCompatActivity { progressText, progressBar )}; + String finalOutputPath = outputPath; runOnUiThread(() -> { isExporting = false; DialogUtils.safeDismiss(this, progressDialog); - String finalOutputPath = ""; try { //FileUtils.delete(new File(outputPath)); VmFileManager.removeTemp(this, current.vmID); - finalOutputPath = FileUtils.getPath(this, uri); } catch (Exception e) { Log.e(TAG, "startCreate: ", e); } - String finalOutputPath1 = finalOutputPath != null ? finalOutputPath : ""; String title; String content; if (result[0]) { title = getString(R.string.done); - content = finalOutputPath1.isEmpty() ? getString(R.string.rom_successfully_exported) : getString(R.string.saved_in) + ": " + finalOutputPath1 + "."; + content = finalOutputPath.isEmpty() ? getString(R.string.rom_successfully_exported) : getString(R.string.saved_in) + ": " + finalOutputPath + "."; } else { title = getString(R.string.oops); content = getString(R.string.something_went_wrong) + ":\n\n" + ZipUtils.lastErrorContent; } - File file = new File(finalOutputPath1); - boolean isShowInFolder = !finalOutputPath1.isEmpty() && result[0] && file.getParent() != null && FileUtils.isFileExists(file.getParent()); + File file = new File(finalOutputPath); + boolean isShowInFolder = !finalOutputPath.isEmpty() && result[0] && file.getParent() != null && FileUtils.isFileExists(file.getParent()); DialogUtils.twoDialog(this, title, diff --git a/app/src/main/java/com/vectras/vm/SplashActivity.java b/app/src/main/java/com/vectras/vm/SplashActivity.java index d3011bd..62e7602 100644 --- a/app/src/main/java/com/vectras/vm/SplashActivity.java +++ b/app/src/main/java/com/vectras/vm/SplashActivity.java @@ -117,7 +117,7 @@ public class SplashActivity extends AppCompatActivity { private void cleanUp() { FileUtils.delete(AppConfig.vmFolder + "QuickRun"); - VmFileManager.removeTemp(this, ""); + VmFileManager.quickCleanUp(this); } private void finishSplash() { diff --git a/app/src/main/java/com/vectras/vm/StartVM.java b/app/src/main/java/com/vectras/vm/StartVM.java index 30a55ed..0e1fbd5 100644 --- a/app/src/main/java/com/vectras/vm/StartVM.java +++ b/app/src/main/java/com/vectras/vm/StartVM.java @@ -34,7 +34,8 @@ public class StartVM { snapshotParams = getQmpParams() + " " + snapshotParams; snapshotParams = getQemuSystem(activity) + " " + snapshotParams; snapshotParams += " " + getDisplayParams(activity); - if (!snapshotParams.contains("-incoming defer")) snapshotParams += " -incoming defer"; + if (!snapshotParams.contains("-incoming defer")) + snapshotParams += " -incoming defer"; Log.d("StartVM.env", snapshotParams); return snapshotParams; } @@ -82,7 +83,7 @@ public class StartVM { params.add(getQmpParams()); String ifType; - ifType= MainSettingsManager.getIfType(activity); + ifType = MainSettingsManager.getIfType(activity); String cdrom = ""; String hdd0; @@ -208,7 +209,7 @@ public class StartVM { //params.add(soundDevice); - if (MainSettingsManager.useDefaultBios(activity)) { + if (vmConfigs.isUseDefaultBios) { if (MainSettingsManager.getArch(activity).equals("PPC")) { bios = "-L "; bios += "pc-bios"; @@ -217,7 +218,7 @@ public class StartVM { bios += "file=" + AppConfig.basefiledir + "QEMU_EFI.img,format=raw,readonly=on,if=pflash"; bios += " -drive "; bios += "file=" + AppConfig.basefiledir + "QEMU_VARS.img,format=raw,if=pflash"; - } else if (MainSettingsManager.getArch(activity).equals("X86_64") && (vmConfigs.isUseUefi)) { + } else if (vmConfigs.isUseUefi) { bios = "-drive "; bios += "file=" + AppConfig.basefiledir + "RELEASEX64_OVMF.fd,format=raw,readonly=on,if=pflash"; bios += " -drive "; @@ -310,6 +311,7 @@ public class StartVM { public static String getQmpParams() { return "-qmp unix:" + Config.getLocalQMPSocketPath() + ",server,nowait"; } + public static String removeQmpParams(String params) { return params.replaceAll("(?<=\\s|^)-qmp\\s+(\"[^\"]+\"|\\S+)", ""); } diff --git a/app/src/main/java/com/vectras/vm/VMManager.java b/app/src/main/java/com/vectras/vm/VMManager.java index 64fcccf..88f99be 100644 --- a/app/src/main/java/com/vectras/vm/VMManager.java +++ b/app/src/main/java/com/vectras/vm/VMManager.java @@ -454,7 +454,10 @@ public class VMManager { result.append(random.nextInt(2) > 0 ? TextUtils.randomALetter() : String.valueOf(random.nextInt(10))); } - return result.toString(); + long millis = System.currentTimeMillis(); + long days = millis / 1000 / 60 / 60 / 24; + + return result.toString() + days; } // TODO: This can be removed because QMP currently uses sockets instead of open ports. diff --git a/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java b/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java index 4fa6eec..3c6a055 100644 --- a/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java +++ b/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java @@ -17,6 +17,7 @@ import com.vectras.qemu.MainSettingsManager; import com.vectras.vm.R; import com.vectras.vm.databinding.ActivitySetArchBinding; import com.vectras.vm.main.MainActivity; +import com.vectras.vm.utils.DialogUtils; import com.vectras.vm.utils.FileUtils; import com.vectras.vm.utils.IntentUtils; import com.vectras.vm.utils.UIUtils; @@ -77,18 +78,28 @@ public class SetArchActivity extends AppCompatActivity implements View.OnClickLi Uri uri = clipData.getItemAt(0).getUri(); String filePath = FileUtils.getFilePathFromUri(getApplicationContext(), uri); - File file = new File(filePath); + new Thread (() -> { + if (filePath == null) FileUtils.getPath(this, uri); - Intent intent = new Intent(); - intent.setClass(getApplicationContext(), VMCreatorActivity.class); - intent.putExtra("addromnow", ""); - intent.putExtra("romextra", ""); - intent.putExtra("romname", ""); - intent.putExtra("romicon", ""); - intent.putExtra("rompath", filePath); - intent.putExtra("romfilename", file.getName()); - startActivity(intent); - finish(); + File file = filePath != null ? new File(filePath) : null; + + runOnUiThread(() -> { + if (file != null) { + Intent intent = new Intent(); + intent.setClass(getApplicationContext(), VMCreatorActivity.class); + intent.putExtra("addromnow", ""); + intent.putExtra("romextra", ""); + intent.putExtra("romname", ""); + intent.putExtra("romicon", ""); + intent.putExtra("rompath", filePath); + intent.putExtra("romfilename", file.getName()); + startActivity(intent); + finish(); + } else { + DialogUtils.oopsDialog(this, getString(R.string.invalid_file_path_content)); + } + }); + }).start(); } return true; } diff --git a/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java b/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java index 0f88376..093b66d 100644 --- a/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java +++ b/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java @@ -77,8 +77,9 @@ public class VMCreatorActivity extends AppCompatActivity { private String thumbnailPath = ""; private String vmID = VMManager.idGenerator(); private boolean isShowBootMenu = false; - private boolean isUseUefi = false; private boolean isUseLocalTime = true; + private boolean isUseUefi = false; + private boolean isUseDefaultBios = true; private int bootFrom = 0; @Override @@ -278,9 +279,14 @@ public class VMCreatorActivity extends AppCompatActivity { binding.cbvShowbootmenu.setOnCheckedChangeListener((v, isChecked) -> isShowBootMenu = isChecked); + binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> isUseLocalTime = isChecked); + binding.cbvUseuefi.setOnCheckedChangeListener((v, isChecked) -> isUseUefi = isChecked); - binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> isUseLocalTime = isChecked); + binding.cbvUseDefaultBios.setOnCheckedChangeListener((v, isChecked) -> { + isUseDefaultBios = isChecked; + binding.cbvUseuefi.setEnabled(isChecked); + }); if (!MainSettingsManager.getArch(this).equals("X86_64")) binding.cbvUseuefi.setVisibility(View.GONE); @@ -574,6 +580,11 @@ public class VMCreatorActivity extends AppCompatActivity { private void loadConfig(DataMainRoms vmConfig) { if (vmConfig != null) current = vmConfig; if (binding != null && current != null) { + if (!current.vmID.isEmpty()) { + vmID = current.vmID; + checkVMID(); + } + if (current.itemArch != null) { VMManager.setArch(current.itemArch, this); binding.collapsingToolbarLayout.setSubtitle(MainSettingsManager.getArch(this)); @@ -624,6 +635,11 @@ public class VMCreatorActivity extends AppCompatActivity { binding.cbvUseuefi.setVisibility(View.GONE); } + isUseDefaultBios = current.isUseDefaultBios; + binding.cbvUseDefaultBios.setChecked(isUseDefaultBios); + + binding.cbvUseuefi.setEnabled(isUseDefaultBios); + isUseLocalTime = current.isUseLocalTime; binding.cbvUselocaltime.setChecked(isUseLocalTime); } @@ -657,13 +673,14 @@ public class VMCreatorActivity extends AppCompatActivity { } private void checkVMID() { - if (FileUtils.isFileExists(AppConfig.maindirpath + "/roms/" + vmID) || vmID.isEmpty()) { + if (vmID.isEmpty() || (!modify && VmFileManager.isInUse(vmID))) { vmID = VMManager.idGenerator(); + Log.d(TAG, "Changed to ID:" + vmID); } } private boolean createVMFolder(boolean isShowDialog) { - File romDir = new File(VmFileManager.getPath(vmID)); + File romDir = new File(VmFileManager.quickGetPath(vmID)); if (!romDir.exists()) { if (!romDir.mkdirs()) { if (isShowDialog) DialogUtils.oneDialog(this, @@ -758,6 +775,7 @@ public class VMCreatorActivity extends AppCompatActivity { vmConfigMap.put("bootFrom", bootFrom); vmConfigMap.put("isShowBootMenu", isShowBootMenu); vmConfigMap.put("isUseUefi", isUseUefi); + vmConfigMap.put("isUseDefaultBios", isUseDefaultBios); vmConfigMap.put("isUseLocalTime", isUseLocalTime); vmConfigMap.put("vmID", vmID); vmConfigMap.put("qmpPort", 8080); @@ -971,7 +989,7 @@ public class VMCreatorActivity extends AppCompatActivity { showProgressDialog(getString(R.string.importing) + "\n" + getString(R.string.please_stay_here)); - Log.i(TAG, "importRom: Extracting with " + (isUseUri ? "uri" : "path") + " from " + filePath + " to " + VmFileManager.getPath(vmID)); + Log.i(TAG, "importRom: Extracting with " + (isUseUri ? "uri" : "path") + " from " + filePath + " to " + VmFileManager.quickGetPath(vmID)); new Thread(() -> { boolean result = isUseUri ? ZipUtils.extract( diff --git a/app/src/main/java/com/vectras/vm/main/vms/DataMainRoms.java b/app/src/main/java/com/vectras/vm/main/vms/DataMainRoms.java index 11120c4..2b3f2fd 100644 --- a/app/src/main/java/com/vectras/vm/main/vms/DataMainRoms.java +++ b/app/src/main/java/com/vectras/vm/main/vms/DataMainRoms.java @@ -51,7 +51,9 @@ public class DataMainRoms { public boolean isShowBootMenu = false; + public boolean isUseLocalTime = true; + public boolean isUseUefi = false; - public boolean isUseLocalTime = true; + public boolean isUseDefaultBios = true; } diff --git a/app/src/main/java/com/vectras/vm/main/vms/VmsFragment.java b/app/src/main/java/com/vectras/vm/main/vms/VmsFragment.java index dba2960..72bbfea 100644 --- a/app/src/main/java/com/vectras/vm/main/vms/VmsFragment.java +++ b/app/src/main/java/com/vectras/vm/main/vms/VmsFragment.java @@ -14,6 +14,8 @@ import android.view.View; import android.view.ViewGroup; import com.google.android.material.transition.MaterialFadeThrough; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import com.vectras.vm.AppConfig; import com.vectras.vm.R; import com.vectras.vm.VMManager; @@ -30,6 +32,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.File; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -111,83 +114,33 @@ public class VmsFragment extends Fragment implements CallbackInterface.HomeCallT try { if (!isAdded()) return; - jArray = new JSONArray(FileUtils.readFromFile(requireActivity(), new File(AppConfig.maindirpath - + "roms-data.json"))); + Gson gson = new Gson(); + Type listType = new TypeToken>(){}.getType(); - // Extract data from json and store into ArrayList as class objects - for (int i = 0; i < jArray.length(); i++) { - JSONObject json_data = jArray.getJSONObject(i); - DataMainRoms romsMainData = new DataMainRoms(); - romsMainData.itemName = json_data.getString("imgName"); - romsMainData.itemIcon = json_data.getString("imgIcon"); - try { - romsMainData.itemArch = json_data.getString("imgArch"); - } catch (JSONException ignored) { - romsMainData.itemArch = "unknown"; - } - romsMainData.itemPath = json_data.getString("imgPath"); - try { - romsMainData.imgCdrom = json_data.getString("imgCdrom"); - } catch (JSONException ignored) { - romsMainData.imgCdrom = ""; - } - try { - romsMainData.vmID = json_data.getString("vmID"); - } catch (JSONException ignored) { - romsMainData.vmID = ""; - } - try { - romsMainData.qmpPort = json_data.getInt("qmpPort"); - } catch (JSONException ignored) { - romsMainData.qmpPort = 0; - } - try { - romsMainData.itemDrv1 = json_data.getString("imgDrv1"); - } catch (JSONException ignored) { - romsMainData.itemDrv1 = ""; - } - try { - romsMainData.bootFrom = json_data.getInt("bootFrom"); - } catch (JSONException ignored) { - romsMainData.bootFrom = 0; - } - try { - romsMainData.isShowBootMenu = json_data.getBoolean("isShowBootMenu"); - } catch (JSONException ignored) { - romsMainData.isShowBootMenu = false; - } - try { - romsMainData.isUseUefi = json_data.getBoolean("isUseUefi"); - } catch (JSONException ignored) { - romsMainData.isUseUefi = false; - } - try { - romsMainData.isUseLocalTime = json_data.getBoolean("isUseLocalTime"); - } catch (JSONException ignored) { - romsMainData.isUseLocalTime = true; - } + String json = FileUtils.readFromFile(requireActivity(), + new File(AppConfig.romsdatajson)); + + tempdata = gson.fromJson(json, listType); - romsMainData.itemExtra = json_data.getString("imgExtra"); - tempdata.add(romsMainData); - } if (!isAdded()) return; requireActivity().runOnUiThread(() -> binding.lnError.setVisibility(View.GONE)); - } catch (JSONException e) { + } catch (Exception e) { if (!isAdded()) return; requireActivity().runOnUiThread(() -> binding.lnError.setVisibility(View.VISIBLE)); Log.e(TAG, "loadDataVbi: ", e); } if (!isAdded()) return; + List finalTempdata = tempdata; requireActivity().runOnUiThread(() -> { binding.lnLoad.setVisibility(View.GONE); - if (tempdata.isEmpty()) { + if (finalTempdata.isEmpty()) { binding.rvRomlist.setVisibility(View.GONE); binding.lnNothinghere.setVisibility(View.VISIBLE); } else { binding.rvRomlist.setVisibility(View.VISIBLE); binding.lnNothinghere.setVisibility(View.GONE); - vmsHomeAdapter.updateData(tempdata); + vmsHomeAdapter.updateData(finalTempdata); } }); }); diff --git a/app/src/main/java/com/vectras/vm/manager/VmControllerDialog.java b/app/src/main/java/com/vectras/vm/manager/VmControllerDialog.java index dd9210b..661cd9e 100644 --- a/app/src/main/java/com/vectras/vm/manager/VmControllerDialog.java +++ b/app/src/main/java/com/vectras/vm/manager/VmControllerDialog.java @@ -37,6 +37,11 @@ import com.vectras.vm.utils.StreamAudio; import java.io.File; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; public class VmControllerDialog extends DialogFragment { @@ -54,10 +59,34 @@ public class VmControllerDialog extends DialogFragment { AlertDialog dialog = new AlertDialog.Builder(requireActivity()).create(); dialog.setView(binding.getRoot()); - new Thread(() -> { - infoBlock = QmpSender.getAllDevice(); + AtomicBoolean isGotInfo = new AtomicBoolean(false); + ProgressDialog progressDialog = new ProgressDialog(requireActivity()); + progressDialog.setText(getString(R.string.just_a_sec)); + new Handler(Looper.getMainLooper()).postDelayed(() -> { + if (isGotInfo.get()) { + progressDialog.reset(); + } else { + progressDialog.show(); + } + }, 1000); + + + new Thread(() -> { + try { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future getInfoBlock = executor.submit(QmpSender::getAllDevice); + infoBlock = getInfoBlock.get(3, TimeUnit.SECONDS); + } catch (Exception e) { + infoBlock = ""; + } + + long audioFileSize = FileUtils.getFileSize(VmFileManager.findAudioRaw(requireContext(), Config.vmID)); + + isGotInfo.set(true); new Handler(Looper.getMainLooper()).post(() -> { + progressDialog.reset(); + if (position > -1) { binding.lnConnect.setOnClickListener(v -> { if (isAdded()) DisplaySystem.launch(requireActivity()); @@ -112,13 +141,14 @@ public class VmControllerDialog extends DialogFragment { }); if (isAdded() && (!(requireActivity() instanceof MainVNCActivity))) { - if (streamAudio == null) streamAudio = new StreamAudio(requireActivity().getApplicationContext()); + if (streamAudio == null) + streamAudio = new StreamAudio(requireActivity().getApplicationContext()); if (!streamAudio.isPlaying()) VmAudioManager.set(Config.vmID); } if (streamAudio == null || !isAdded() || - FileUtils.getFileSize(VmFileManager.findAudioRaw(requireContext(), Config.vmID)) == 0 || + audioFileSize == 0 || (isAdded() && (!(requireActivity() instanceof MainVNCActivity)) && !VmAudioManager.currentVmId.equals(Config.vmID)) ) { binding.lnMute.setVisibility(View.GONE); @@ -297,7 +327,8 @@ public class VmControllerDialog extends DialogFragment { } binding.ivScreenOneToOne.setOnClickListener(v -> { - if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.oneToOne) return; + if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.oneToOne) + return; MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.oneToOne); requireActivity().recreate(); @@ -305,7 +336,8 @@ public class VmControllerDialog extends DialogFragment { }); binding.ivScreenFit.setOnClickListener(v -> { - if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.fitToScreen) return; + if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.fitToScreen) + return; MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.fitToScreen); requireActivity().recreate(); @@ -313,7 +345,8 @@ public class VmControllerDialog extends DialogFragment { }); binding.ivScreenScale.setOnClickListener(v -> { - if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.scaleToFitScreen) return; + if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.scaleToFitScreen) + return; MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.scaleToFitScreen); requireActivity().recreate(); diff --git a/app/src/main/java/com/vectras/vm/manager/VmFileManager.java b/app/src/main/java/com/vectras/vm/manager/VmFileManager.java index 6f50846..c2a89e6 100644 --- a/app/src/main/java/com/vectras/vm/manager/VmFileManager.java +++ b/app/src/main/java/com/vectras/vm/manager/VmFileManager.java @@ -7,6 +7,7 @@ import com.vectras.vm.AppConfig; import com.vectras.vm.utils.FileUtils; import java.io.File; +import java.util.ArrayList; public class VmFileManager { private static final String TAG = "VmFileManager"; @@ -43,6 +44,21 @@ public class VmFileManager { return FileUtils.rename(getPath(HIDE_VM_SUFFIX + vmId), vmId); } + public static void quickCleanUp(Context context) { + ArrayList fileList = new ArrayList<>(); + FileUtils.getAListOfAllFilesAndFoldersInADirectory(AppConfig.vmFolder, fileList); + for (int position = 0; position < fileList.size(); position++) { + if (FileUtils.isEmpty(fileList.get(position))) FileUtils.delete(fileList.get(position)); + } + + removeTemp(context, ""); + } + + public static boolean isInUse(String vmId) { + if (!FileUtils.isFileExists(quickGetPath(vmId))) return true; + return !FileUtils.isEmpty(quickGetPath(vmId)); + } + public static String getPath(String vmId, String childFilePath) { return new File(getPath(vmId), childFilePath).getAbsolutePath(); } diff --git a/app/src/main/java/com/vectras/vm/utils/FileUtils.java b/app/src/main/java/com/vectras/vm/utils/FileUtils.java index ebe6e98..c368e60 100644 --- a/app/src/main/java/com/vectras/vm/utils/FileUtils.java +++ b/app/src/main/java/com/vectras/vm/utils/FileUtils.java @@ -722,6 +722,17 @@ public class FileUtils { } } + public static boolean isEmpty(String path) { + File file = new File(path); + + if (file.isDirectory()) { + File[] files = file.listFiles(); + return files != null && files.length == 0; + } + + return file.length() == 0; + } + public static int getFileSize(String _path) { try { File file = new File(_path); diff --git a/app/src/main/java/com/vectras/vm/view/CheckBoxView.java b/app/src/main/java/com/vectras/vm/view/CheckBoxView.java index 728656b..77ae2e3 100644 --- a/app/src/main/java/com/vectras/vm/view/CheckBoxView.java +++ b/app/src/main/java/com/vectras/vm/view/CheckBoxView.java @@ -70,7 +70,7 @@ public class CheckBoxView extends LinearLayout { public void setEnabled(boolean isEnabled) { findViewById(R.id.root).setEnabled(isEnabled); - findViewById(R.id.root).setAlpha(0.5f); + findViewById(R.id.root).setAlpha(isEnabled ? 1f : 0.5f); checkBox.setEnabled(isEnabled); } } diff --git a/app/src/main/res/layout/activity_vm_creator.xml b/app/src/main/res/layout/activity_vm_creator.xml index 7aca321..005c5a3 100644 --- a/app/src/main/res/layout/activity_vm_creator.xml +++ b/app/src/main/res/layout/activity_vm_creator.xml @@ -279,6 +279,13 @@ android:layout_height="wrap_content" app:setText="@string/show_boot_menu"/> + + + app:setText="@string/use_default_bios_uefi" + app:setChecked="true" /> diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index fe12f25..59d77b2 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -555,6 +555,7 @@ Quản lý Kết nối Đang tắt… + Không thể lưu ở đây, hãy chọn một nơi khác. Vterm diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index a734760..bb565f0 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -45,6 +45,7 @@ + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4077d1c..f483868 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -566,6 +566,7 @@ Manage Connect Shutting down… + Cannot save here, please choose another location. diff --git a/app/src/main/res/xml/qemu.xml b/app/src/main/res/xml/qemu.xml index 8ca0aaa..d5bfb71 100644 --- a/app/src/main/res/xml/qemu.xml +++ b/app/src/main/res/xml/qemu.xml @@ -47,7 +47,7 @@ app:isPreferenceVisible="false" app:icon="@drawable/round_volume_up_24" app:useSimpleSummaryProvider="true" /> - - - -