Add "Save as" option in Quick GUI
This commit is contained in:
parent
dd77f56a40
commit
0e2af9ff2e
|
@ -12,16 +12,16 @@ import java.io.FileNotFoundException;
|
|||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
public class Activity extends QtActivity {
|
||||
private final int REQUEST_CODE_PICK_DIR = 1;
|
||||
private final int REQUEST_CODE_PICK_EXISTING_FILE = 2;
|
||||
private final int REQUEST_CODE_PICK_NEW_FILE = 3;
|
||||
private final int REQUEST_CODE_OPEN_EXISTING_FILE = 1;
|
||||
private final int REQUEST_CODE_CREATE_NEW_FILE = 2;
|
||||
private final int REQUEST_CODE_SAVE_FILE_AS = 3;
|
||||
|
||||
/*!
|
||||
* \brief Shows the native Android file dialog. Results are handled in onActivityResult().
|
||||
*/
|
||||
public boolean showAndroidFileDialog(boolean existing) {
|
||||
public boolean showAndroidFileDialog(boolean existing, boolean createNew) {
|
||||
String action = existing ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT;
|
||||
int requestCode = existing ? REQUEST_CODE_PICK_EXISTING_FILE : REQUEST_CODE_PICK_NEW_FILE;
|
||||
int requestCode = existing ? REQUEST_CODE_OPEN_EXISTING_FILE : (createNew ? REQUEST_CODE_CREATE_NEW_FILE : REQUEST_CODE_SAVE_FILE_AS);
|
||||
Intent intent = new Intent(action);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
|
@ -51,9 +51,12 @@ public class Activity extends QtActivity {
|
|||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PICK_EXISTING_FILE:
|
||||
case REQUEST_CODE_PICK_NEW_FILE:
|
||||
boolean existingFile = requestCode == REQUEST_CODE_PICK_EXISTING_FILE;
|
||||
case REQUEST_CODE_OPEN_EXISTING_FILE:
|
||||
case REQUEST_CODE_CREATE_NEW_FILE:
|
||||
case REQUEST_CODE_SAVE_FILE_AS:
|
||||
boolean createNew = requestCode == REQUEST_CODE_CREATE_NEW_FILE;
|
||||
boolean existingFile = requestCode == REQUEST_CODE_OPEN_EXISTING_FILE;
|
||||
boolean saveAs = requestCode == REQUEST_CODE_SAVE_FILE_AS;
|
||||
|
||||
if (resultCode != RESULT_OK) {
|
||||
onAndroidFileDialogRejected();
|
||||
|
@ -65,7 +68,7 @@ public class Activity extends QtActivity {
|
|||
try {
|
||||
DocumentFile file = DocumentFile.fromSingleUri(this, uri);
|
||||
ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(file.getUri(), existingFile ? "r" : "wt");
|
||||
onAndroidFileDialogAcceptedDescriptor(file.getUri().toString(), file.getName(), fd.detachFd(), existingFile);
|
||||
onAndroidFileDialogAcceptedDescriptor(file.getUri().toString(), file.getName(), fd.detachFd(), existingFile, createNew);
|
||||
} catch (FileNotFoundException e) {
|
||||
onAndroidError("Failed to find selected file.");
|
||||
}
|
||||
|
@ -74,7 +77,7 @@ public class Activity extends QtActivity {
|
|||
|
||||
String fileName = data.getDataString();
|
||||
if (fileName != null) {
|
||||
onAndroidFileDialogAccepted(fileName, existingFile);
|
||||
onAndroidFileDialogAccepted(fileName, existingFile, createNew);
|
||||
return;
|
||||
}
|
||||
onAndroidError("Failed to read result from Android's file dialog.");
|
||||
|
@ -85,7 +88,7 @@ public class Activity extends QtActivity {
|
|||
}
|
||||
|
||||
public static native void onAndroidError(String message);
|
||||
public static native void onAndroidFileDialogAccepted(String fileName, boolean existing);
|
||||
public static native void onAndroidFileDialogAcceptedDescriptor(String nativeUrl, String fileName, int fileDescriptor, boolean existing);
|
||||
public static native void onAndroidFileDialogAccepted(String fileName, boolean existing, boolean createNew);
|
||||
public static native void onAndroidFileDialogAcceptedDescriptor(String nativeUrl, String fileName, int fileDescriptor, boolean existing, boolean createNew);
|
||||
public static native void onAndroidFileDialogRejected();
|
||||
}
|
||||
|
|
40
qml/main.qml
40
qml/main.qml
|
@ -128,6 +128,13 @@ Kirigami.ApplicationWindow {
|
|||
onTriggered: nativeInterface.save()
|
||||
shortcut: StandardKey.Save
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: qsTr("Save as")
|
||||
enabled: nativeInterface.fileOpen
|
||||
iconName: "document-save-as"
|
||||
onTriggered: fileDialog.saveAs()
|
||||
shortcut: StandardKey.SaveAs
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: nativeInterface.passwordSet ? qsTr("Change password") : qsTr(
|
||||
"Add password")
|
||||
|
@ -250,19 +257,21 @@ Kirigami.ApplicationWindow {
|
|||
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
title: selectExisting ? qsTr("Select an existing file") : qsTr(
|
||||
"Select path for new file")
|
||||
property bool createNewFile: false
|
||||
title: selectExisting ? qsTr("Select an existing file") : (saveAs ? qsTr("Select path to save file") : qsTr("Select path for new file"))
|
||||
onAccepted: {
|
||||
if (fileUrls.length < 1) {
|
||||
return
|
||||
}
|
||||
nativeInterface.handleFileSelectionAccepted(fileUrls[0],
|
||||
this.selectExisting)
|
||||
nativeInterface.handleFileSelectionAccepted(fileUrls[0], "",
|
||||
this.selectExisting,
|
||||
this.createNewFile)
|
||||
}
|
||||
onRejected: nativeInterface.handleFileSelectionCanceled()
|
||||
|
||||
function show() {
|
||||
if (nativeInterface.showNativeFileDialog(this.selectExisting)) {
|
||||
if (nativeInterface.showNativeFileDialog(this.selectExisting,
|
||||
this.createNewFile)) {
|
||||
return
|
||||
}
|
||||
// fallback to the Qt Quick file dialog if a native implementation is not available
|
||||
|
@ -270,10 +279,17 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
function openExisting() {
|
||||
this.selectExisting = true
|
||||
this.createNewFile = false
|
||||
this.show()
|
||||
}
|
||||
function createNew() {
|
||||
this.selectExisting = false
|
||||
this.createNewFile = true
|
||||
this.show()
|
||||
}
|
||||
function saveAs() {
|
||||
this.selectExisting = false
|
||||
this.createNewFile = false
|
||||
this.show()
|
||||
}
|
||||
}
|
||||
|
@ -325,12 +341,16 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
onFileError: {
|
||||
if (retryAction.length === 0) {
|
||||
var retryMethod = null
|
||||
if (retryAction === "load" || retryAction === "save") {
|
||||
retryMethod = retryAction
|
||||
}
|
||||
if (retryMethod) {
|
||||
showPassiveNotification(errorMessage)
|
||||
} else {
|
||||
showPassiveNotification(errorMessage, 2500, qsTr("Retry"),
|
||||
function () {
|
||||
nativeInterface[retryAction]()
|
||||
nativeInterface[retryMethod]()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +416,11 @@ Kirigami.ApplicationWindow {
|
|||
Kirigami.Action {
|
||||
property string filePath
|
||||
text: filePath.substring(filePath.lastIndexOf('/') + 1)
|
||||
onTriggered: nativeInterface.load(filePath)
|
||||
onTriggered: {
|
||||
nativeInterface.clear()
|
||||
nativeInterface.filePath = filePath
|
||||
nativeInterface.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,9 +50,9 @@ void registerControllerForAndroid(Controller *controller)
|
|||
controllerForAndroid = controller;
|
||||
}
|
||||
|
||||
bool showAndroidFileDialog(bool existing)
|
||||
bool showAndroidFileDialog(bool existing, bool createNew)
|
||||
{
|
||||
return QtAndroid::androidActivity().callMethod<jboolean>("showAndroidFileDialog", "(Z)Z", existing);
|
||||
return QtAndroid::androidActivity().callMethod<jboolean>("showAndroidFileDialog", "(ZZ)Z", existing, createNew);
|
||||
}
|
||||
|
||||
int openFileDescriptorFromAndroidContentUrl(const QString &url, const QString &mode)
|
||||
|
@ -105,17 +105,17 @@ static void onAndroidError(JNIEnv *, jobject, jstring message)
|
|||
QtGui::controllerForAndroid, "newNotification", Qt::QueuedConnection, Q_ARG(QString, QAndroidJniObject::fromLocalRef(message).toString()));
|
||||
}
|
||||
|
||||
static void onAndroidFileDialogAccepted(JNIEnv *, jobject, jstring fileName, jboolean existing)
|
||||
static void onAndroidFileDialogAccepted(JNIEnv *, jobject, jstring fileName, jboolean existing, jboolean createNew)
|
||||
{
|
||||
QMetaObject::invokeMethod(QtGui::controllerForAndroid, "handleFileSelectionAccepted", Qt::QueuedConnection,
|
||||
Q_ARG(QString, QAndroidJniObject::fromLocalRef(fileName).toString()), Q_ARG(bool, existing));
|
||||
Q_ARG(QString, QAndroidJniObject::fromLocalRef(fileName).toString()), Q_ARG(bool, existing), Q_ARG(bool, createNew));
|
||||
}
|
||||
|
||||
static void onAndroidFileDialogAcceptedDescriptor(JNIEnv *, jobject, jstring nativeUrl, jstring fileName, jint fileHandle, jboolean existing)
|
||||
static void onAndroidFileDialogAcceptedDescriptor(JNIEnv *, jobject, jstring nativeUrl, jstring fileName, jint fileHandle, jboolean existing, jboolean createNew)
|
||||
{
|
||||
QMetaObject::invokeMethod(QtGui::controllerForAndroid, "handleFileSelectionAcceptedDescriptor", Qt::QueuedConnection,
|
||||
Q_ARG(QString, QAndroidJniObject::fromLocalRef(nativeUrl).toString()), Q_ARG(QString, QAndroidJniObject::fromLocalRef(fileName).toString()),
|
||||
Q_ARG(int, fileHandle), Q_ARG(bool, existing));
|
||||
Q_ARG(int, fileHandle), Q_ARG(bool, existing), Q_ARG(bool, createNew));
|
||||
}
|
||||
|
||||
static void onAndroidFileDialogRejected(JNIEnv *, jobject)
|
||||
|
@ -144,8 +144,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *)
|
|||
// register native methods
|
||||
static const JNINativeMethod methods[] = {
|
||||
{ "onAndroidError", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onAndroidError) },
|
||||
{ "onAndroidFileDialogAccepted", "(Ljava/lang/String;Z)V", reinterpret_cast<void *>(onAndroidFileDialogAccepted) },
|
||||
{ "onAndroidFileDialogAcceptedDescriptor", "(Ljava/lang/String;Ljava/lang/String;IZ)V",
|
||||
{ "onAndroidFileDialogAccepted", "(Ljava/lang/String;ZZ)V", reinterpret_cast<void *>(onAndroidFileDialogAccepted) },
|
||||
{ "onAndroidFileDialogAcceptedDescriptor", "(Ljava/lang/String;Ljava/lang/String;IZZ)V",
|
||||
reinterpret_cast<void *>(onAndroidFileDialogAcceptedDescriptor) },
|
||||
{ "onAndroidFileDialogRejected", "()V", reinterpret_cast<void *>(onAndroidFileDialogRejected) },
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ class Controller;
|
|||
|
||||
void applyThemingForAndroid();
|
||||
void registerControllerForAndroid(Controller *controller);
|
||||
bool showAndroidFileDialog(bool existing);
|
||||
bool showAndroidFileDialog(bool existing, bool createNew);
|
||||
int openFileDescriptorFromAndroidContentUrl(const QString &url, const QString &mode);
|
||||
void writeToAndroidLog(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||
void setupAndroidSpecifics();
|
||||
|
|
|
@ -77,25 +77,21 @@ void Controller::setFilePath(const QString &filePath)
|
|||
if (filePath.startsWith(QLatin1String("file:"))) {
|
||||
actualFilePath = filePath.midRef(5);
|
||||
}
|
||||
while (filePath.startsWith(QLatin1String("//"))) {
|
||||
while (actualFilePath.startsWith(QLatin1String("//"))) {
|
||||
actualFilePath = actualFilePath.mid(1);
|
||||
}
|
||||
|
||||
// skip if this path is already set
|
||||
if (m_filePath == actualFilePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
// assign full file path and file name
|
||||
m_file.clear();
|
||||
m_file.setPath(filePath.toLocal8Bit().data());
|
||||
m_fileName = QString::fromLocal8Bit(CppUtilities::fileName(m_file.path()).data());
|
||||
emit filePathChanged(m_filePath = filePath);
|
||||
|
||||
// clear password so we don't use the password from the previous file
|
||||
m_password.clear();
|
||||
m_filePath = actualFilePath.toString();
|
||||
m_file.setPath(m_filePath.toLocal8Bit().toStdString());
|
||||
const auto fileName = CppUtilities::fileName(m_file.path());
|
||||
m_fileName = QString::fromLocal8Bit(fileName.data(), static_cast<int>(fileName.size()));
|
||||
emit filePathChanged(m_filePath);
|
||||
|
||||
// handle recent files
|
||||
if (m_filePath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto index = m_recentFiles.indexOf(m_filePath);
|
||||
if (!index) {
|
||||
return;
|
||||
|
@ -127,13 +123,8 @@ void Controller::init()
|
|||
}
|
||||
}
|
||||
|
||||
void Controller::load(const QString &filePath)
|
||||
void Controller::load()
|
||||
{
|
||||
if (!filePath.isEmpty()) {
|
||||
setFilePath(filePath);
|
||||
}
|
||||
|
||||
resetFileStatus();
|
||||
try {
|
||||
m_file.load();
|
||||
m_entryModel.setRootEntry(m_file.rootEntry());
|
||||
|
@ -158,17 +149,9 @@ void Controller::load(const QString &filePath)
|
|||
}
|
||||
}
|
||||
|
||||
void Controller::create(const QString &filePath)
|
||||
void Controller::create()
|
||||
{
|
||||
if (!filePath.isEmpty()) {
|
||||
setFilePath(filePath);
|
||||
}
|
||||
|
||||
resetFileStatus();
|
||||
try {
|
||||
if (filePath.isEmpty()) {
|
||||
m_file.clear();
|
||||
}
|
||||
m_file.create();
|
||||
} catch (...) {
|
||||
emitFileError(tr("creating"));
|
||||
|
@ -190,9 +173,20 @@ void Controller::close()
|
|||
}
|
||||
}
|
||||
|
||||
void Controller::clear()
|
||||
{
|
||||
try {
|
||||
m_file.close();
|
||||
} catch (...) {
|
||||
emitFileError(tr("closing"));
|
||||
}
|
||||
m_file.clear();
|
||||
resetFileStatus();
|
||||
}
|
||||
|
||||
PasswordFileSaveFlags Controller::prepareSaving()
|
||||
{
|
||||
auto flags = PasswordFileSaveFlags::Compression | PasswordFileSaveFlags::PasswordHashing;
|
||||
auto flags = PasswordFileSaveFlags::Compression | PasswordFileSaveFlags::PasswordHashing | PasswordFileSaveFlags::AllowToCreateNewFile;
|
||||
if (!m_password.isEmpty()) {
|
||||
flags |= PasswordFileSaveFlags::Encryption;
|
||||
const auto passwordUtf8(m_password.toUtf8());
|
||||
|
@ -216,7 +210,7 @@ void Controller::save()
|
|||
qDebug() << "Opening new fd for saving, native url: " << m_nativeUrl;
|
||||
const auto newFileDescriptor = openFileDescriptorFromAndroidContentUrl(m_nativeUrl, QStringLiteral("wt"));
|
||||
if (newFileDescriptor < 0) {
|
||||
emit fileError(tr("Unable to open file descriptor for saving the file."));
|
||||
emit fileError(tr("Unable to open file descriptor for saving the file."), QStringLiteral("save"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,43 +237,69 @@ void Controller::save()
|
|||
* \brief Shows a native file dialog if supported; otherwise returns false.
|
||||
* \remarks If supported, this method will load/create the selected file (according to \a existing).
|
||||
*/
|
||||
bool Controller::showNativeFileDialog(bool existing)
|
||||
bool Controller::showNativeFileDialog(bool existing, bool createNew)
|
||||
{
|
||||
#if defined(Q_OS_ANDROID) && defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
|
||||
if (!m_useNativeFileDialog) {
|
||||
return false;
|
||||
}
|
||||
return showAndroidFileDialog(existing);
|
||||
return showAndroidFileDialog(existing, createNew);
|
||||
#else
|
||||
Q_UNUSED(existing)
|
||||
Q_UNUSED(createNew)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Controller::handleFileSelectionAccepted(const QString &filePath, bool existing)
|
||||
void Controller::handleFileSelectionAccepted(const QString &filePath, const QString &nativeUrl, bool existing, bool createNew)
|
||||
{
|
||||
m_nativeUrl.clear();
|
||||
m_nativeUrl = nativeUrl;
|
||||
|
||||
// assign the "ordinary" file path if one has been passed; otherwise the caller is responsible for handling this
|
||||
const auto saveAs = !existing && !createNew;
|
||||
if (!filePath.isEmpty()) {
|
||||
// clear leftovers from possibly previously opened file unless we want to save the current file under a different location
|
||||
if (!saveAs) {
|
||||
m_file.clear();
|
||||
}
|
||||
setFilePath(filePath);
|
||||
}
|
||||
cout << "path is still " << m_file.path() << " (2)" << endl;
|
||||
|
||||
if (!saveAs) {
|
||||
resetFileStatus();
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
load(filePath);
|
||||
} else {
|
||||
create(filePath);
|
||||
load();
|
||||
} else if (createNew) {
|
||||
create();
|
||||
} else if (saveAs) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(Q_OS_ANDROID) && defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
|
||||
void Controller::handleFileSelectionAcceptedDescriptor(const QString &nativeUrl, const QString &fileName, int fileDescriptor, bool existing)
|
||||
void Controller::handleFileSelectionAcceptedDescriptor(
|
||||
const QString &nativeUrl, const QString &fileName, int fileDescriptor, bool existing, bool createNew)
|
||||
{
|
||||
qDebug() << "Opening file descriptor for native url: " << nativeUrl;
|
||||
qDebug() << "(existing: " << existing << ", create new: " << createNew << ")";
|
||||
|
||||
try {
|
||||
qDebug() << "Opening fd for native url: " << nativeUrl;
|
||||
// clear leftovers from possibly previously opened file unless we want to save the current file under a different location
|
||||
if (existing || createNew) {
|
||||
m_file.clear();
|
||||
}
|
||||
m_file.setPath(fileName.toStdString());
|
||||
m_file.fileStream().open(fileDescriptor, ios_base::in | ios_base::binary);
|
||||
m_file.opened();
|
||||
} catch (...) {
|
||||
emitFileError(tr("opening from native file descriptor"));
|
||||
emitFileError(existing ? QStringLiteral("load") : (createNew ? QStringLiteral("create") : QStringLiteral("save")));
|
||||
}
|
||||
|
||||
emit filePathChanged(m_filePath = m_fileName = fileName);
|
||||
handleFileSelectionAccepted(QString(), existing);
|
||||
m_nativeUrl = nativeUrl;
|
||||
handleFileSelectionAccepted(QString(), nativeUrl, existing, createNew);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ class Controller : public QObject {
|
|||
Q_PROPERTY(EntryModel *entryModel READ entryModel NOTIFY entryModelChanged)
|
||||
Q_PROPERTY(EntryFilterModel *entryFilterModel READ entryFilterModel NOTIFY entryFilterModelChanged)
|
||||
Q_PROPERTY(FieldModel *fieldModel READ fieldModel NOTIFY fieldModelChanged)
|
||||
Q_PROPERTY(Io::AccountEntry *currentAccount READ currentAccount WRITE setCurrentAccount NOTIFY currentAccountChanged)
|
||||
//Q_PROPERTY(Io::AccountEntry *currentAccount READ currentAccount WRITE setCurrentAccount NOTIFY currentAccountChanged)
|
||||
Q_PROPERTY(QModelIndex currentAccountIndex READ currentAccountIndex WRITE setCurrentAccountIndex NOTIFY currentAccountChanged)
|
||||
Q_PROPERTY(QString currentAccountName READ currentAccountName NOTIFY currentAccountChanged)
|
||||
Q_PROPERTY(bool hasCurrentAccount READ hasCurrentAccount NOTIFY currentAccountChanged)
|
||||
Q_PROPERTY(QList<QPersistentModelIndex> cutEntries READ cutEntries WRITE setCutEntries NOTIFY cutEntriesChanged)
|
||||
//Q_PROPERTY(QList<QPersistentModelIndex> cutEntries READ cutEntries WRITE setCutEntries NOTIFY cutEntriesChanged)
|
||||
Q_PROPERTY(bool canPaste READ canPaste NOTIFY cutEntriesChanged)
|
||||
Q_PROPERTY(QStringList recentFiles READ recentFiles RESET clearRecentFiles NOTIFY recentFilesChanged)
|
||||
Q_PROPERTY(bool useNativeFileDialog READ useNativeFileDialog WRITE setUseNativeFileDialog NOTIFY useNativeFileDialogChanged)
|
||||
|
@ -88,14 +88,15 @@ public:
|
|||
|
||||
public slots:
|
||||
void init();
|
||||
void load(const QString &filePath = QString());
|
||||
void create(const QString &filePath = QString());
|
||||
void load();
|
||||
void create();
|
||||
void close();
|
||||
void clear();
|
||||
void save();
|
||||
bool showNativeFileDialog(bool existing);
|
||||
void handleFileSelectionAccepted(const QString &filePath, bool existing);
|
||||
bool showNativeFileDialog(bool existing, bool createNew);
|
||||
void handleFileSelectionAccepted(const QString &filePath, const QString &nativeUrl, bool existing, bool createNew);
|
||||
#if defined(Q_OS_ANDROID) && defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
|
||||
void handleFileSelectionAcceptedDescriptor(const QString &nativeUrl, const QString &fileName, int fileDescriptor, bool existing);
|
||||
void handleFileSelectionAcceptedDescriptor(const QString &nativeUrl, const QString &fileName, int fileDescriptor, bool existing, bool createNew);
|
||||
#endif
|
||||
void handleFileSelectionCanceled();
|
||||
void undo();
|
||||
|
@ -109,7 +110,7 @@ signals:
|
|||
void passwordRequired(const QString &filePath);
|
||||
void windowTitleChanged(const QString &windowTitle);
|
||||
void fileOpenChanged(bool fileOpen);
|
||||
void fileError(const QString &errorMessage, const QString &retryAction = QString());
|
||||
void fileError(const QString &errorMessage, const QString &retryAction);
|
||||
void fileSaved();
|
||||
void entryModelChanged();
|
||||
void entryFilterModelChanged();
|
||||
|
|
Loading…
Reference in New Issue