Move common Qt utility functions & JSON I/O together in a single place

This commit is contained in:
baldurk
2016-11-09 13:23:53 +01:00
parent 66298ea1ce
commit bb2f3a205c
16 changed files with 460 additions and 387 deletions
+2 -132
View File
@@ -24,6 +24,7 @@
#include "CaptureContext.h"
#include <QApplication>
#include <QDir>
#include <QFileInfo>
#include <QLabel>
#include <QMenu>
@@ -33,6 +34,7 @@
#include <QStandardPaths>
#include <QTimer>
#include "Windows/MainWindow.h"
#include "QRDUtils.h"
CaptureContext::CaptureContext(QString paramFilename, QString remoteHost, uint32_t remoteIdent,
bool temp, PersistantConfig &cfg)
@@ -377,135 +379,3 @@ void *CaptureContext::FillWindowingData(WId widget)
#endif
}
void GUIInvoke::call(const std::function<void()> &f)
{
if(qApp->thread() == QThread::currentThread())
{
f();
return;
}
// TODO: could maybe do away with string compare here via caching
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
GUIInvoke *invoke = new GUIInvoke(f);
invoke->moveToThread(qApp->thread());
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::QueuedConnection);
}
void GUIInvoke::blockcall(const std::function<void()> &f)
{
if(qApp->thread() == QThread::currentThread())
{
f();
return;
}
// TODO: could maybe do away with string compare here via caching
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
GUIInvoke *invoke = new GUIInvoke(f);
invoke->moveToThread(qApp->thread());
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::BlockingQueuedConnection);
}
void RDDialog::show(QMenu *menu, QPoint pos)
{
menu->setWindowModality(Qt::ApplicationModal);
menu->popup(pos);
QEventLoop loop;
while(menu->isVisible())
{
loop.processEvents(QEventLoop::WaitForMoreEvents);
QCoreApplication::sendPostedEvents();
}
}
int RDDialog::show(QDialog *dialog)
{
dialog->setWindowModality(Qt::ApplicationModal);
dialog->show();
QEventLoop loop;
while(dialog->isVisible())
{
loop.processEvents(QEventLoop::WaitForMoreEvents);
QCoreApplication::sendPostedEvents();
}
return dialog->result();
}
QMessageBox::StandardButton RDDialog::messageBox(QMessageBox::Icon icon, QWidget *parent,
const QString &title, const QString &text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton defaultButton)
{
QMessageBox mb(icon, title, text, buttons, parent);
mb.setDefaultButton(defaultButton);
show(&mb);
return mb.standardButton(mb.clickedButton());
}
QString RDDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, QString());
fd.setAcceptMode(QFileDialog::AcceptOpen);
fd.setFileMode(QFileDialog::DirectoryOnly);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
QString RDDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter, QString *selectedFilter,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, filter);
fd.setAcceptMode(QFileDialog::AcceptOpen);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
if(selectedFilter)
*selectedFilter = fd.selectedNameFilter();
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
QString RDDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter, QString *selectedFilter,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, filter);
fd.setAcceptMode(QFileDialog::AcceptSave);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
if(selectedFilter)
*selectedFilter = fd.selectedNameFilter();
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
-161
View File
@@ -25,7 +25,6 @@
#pragma once
#include <QDebug>
#include <QFileDialog>
#include <QList>
#include <QMap>
#include <QMessageBox>
@@ -194,163 +193,3 @@ private:
QProgressDialog *m_Progress;
MainWindow *m_MainWindow;
};
// implementation of QOverload, to avoid depending on 5.7.
// From: http://stackoverflow.com/a/16795664/4070143
template <typename... Args>
struct OverloadedSlot
{
template <typename C, typename R>
static constexpr auto of(R (C::*pmf)(Args...)) -> decltype(pmf)
{
return pmf;
}
};
// Utility class for invoking a lambda on the GUI thread.
// This is supported by QTimer::singleShot on Qt 5.4 but it's probably
// wise not to require a higher version that necessary.
#include <functional>
class GUIInvoke : public QObject
{
private:
Q_OBJECT
GUIInvoke(const std::function<void()> &f) : func(f) {}
std::function<void()> func;
public:
static void call(const std::function<void()> &f);
static void blockcall(const std::function<void()> &f);
protected slots:
void doInvoke()
{
func();
deleteLater();
}
};
// Utility class for calling a lambda on a new thread.
#include <QThread>
class LambdaThread : public QObject
{
private:
Q_OBJECT
std::function<void()> m_func;
QThread *m_Thread;
QSemaphore completed;
bool m_SelfDelete = false;
public slots:
void process()
{
m_func();
m_Thread->quit();
m_Thread->deleteLater();
m_Thread = NULL;
if(m_SelfDelete)
deleteLater();
completed.acquire();
}
void selfDelete(bool d) { m_SelfDelete = d; }
public:
explicit LambdaThread(std::function<void()> f)
{
completed.release();
m_Thread = new QThread();
m_func = f;
moveToThread(m_Thread);
QObject::connect(m_Thread, &QThread::started, this, &LambdaThread::process);
}
void start(QThread::Priority prio = QThread::InheritPriority) { m_Thread->start(prio); }
bool isRunning() { return completed.available(); }
bool wait(unsigned long time = ULONG_MAX)
{
if(m_Thread)
return m_Thread->wait(time);
return true;
}
};
class QMenu;
// helper for doing a manual blocking invoke of a dialog
struct RDDialog
{
static void show(QMenu *menu, QPoint pos);
static int show(QDialog *dialog);
static QMessageBox::StandardButton messageBox(
QMessageBox::Icon, QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
static QMessageBox::StandardButton information(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Information, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton question(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes |
QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Question, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton warning(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Warning, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton critical(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Critical, parent, title, text, buttons, defaultButton);
}
static QString getExistingDirectory(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
static QString getOpenFileName(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = NULL,
QFileDialog::Options options = QFileDialog::Options());
static QString getSaveFileName(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = NULL,
QFileDialog::Options options = QFileDialog::Options());
};
// useful delegate for enforcing a given size
#include <QItemDelegate>
class SizeDelegate : public QItemDelegate
{
private:
Q_OBJECT
QSize m_Size;
public:
SizeDelegate(QSize size) : m_Size(size) {}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return m_Size;
}
};
+9 -46
View File
@@ -25,9 +25,12 @@
#include "PersistantConfig.h"
#include <QDebug>
#include <QDir>
#include <QJsonDocument>
#include "QRDUtils.h"
#include "renderdoc_replay.h"
#define JSON_ID "rdocConfigData"
#define JSON_VER 1
// helper templates to convert some more complex types to/from appropriate variants
template <typename variantType, typename origType>
variantType convertToVariant(const origType &val)
@@ -93,29 +96,12 @@ bool PersistantConfig::Deserialize(QString filename)
if(f.open(QIODevice::ReadOnly | QIODevice::Text))
{
QByteArray json = f.readAll();
QVariantMap values;
if(json.isEmpty())
{
qCritical() << "Read invalid empty JSON data from file " << f.errorString();
bool success = LoadFromJSON(values, f, JSON_ID, JSON_VER);
if(!success)
return false;
}
QJsonDocument doc = QJsonDocument::fromJson(json);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert file to JSON document";
return false;
}
QVariantMap values = doc.toVariant().toMap();
if(values.isEmpty() || !values.contains("renderdocConfigData"))
{
qCritical() << "Converted config data is invalid or unrecognised";
return false;
}
applyValues(values);
@@ -131,32 +117,9 @@ bool PersistantConfig::Serialize(QString filename)
{
QVariantMap values = storeValues();
// marker that this is indeed a valid config to load from
values["renderdocConfigData"] = 1;
QFile f(filename);
if(f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
QJsonDocument doc = QJsonDocument::fromVariant(values);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert config data to JSON document";
return false;
}
QByteArray jsontext = doc.toJson(QJsonDocument::Indented);
qint64 ret = f.write(jsontext);
if(ret != jsontext.size())
{
qCritical() << "Failed to write JSON data to file: " << ret << " " << f.errorString();
return false;
}
return true;
}
return SaveToJSON(values, f, JSON_ID, JSON_VER);
qWarning() << "Couldn't write to " << filename << " " << f.errorString();
+221
View File
@@ -0,0 +1,221 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "QRDUtils.h"
#include <QGuiApplication>
#include <QJsonDocument>
#include <QMenu>
bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion)
{
// marker that this data is valid
data[magicIdentifier] = magicVersion;
QJsonDocument doc = QJsonDocument::fromVariant(data);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert data to JSON document";
return false;
}
QByteArray jsontext = doc.toJson(QJsonDocument::Indented);
qint64 ret = f.write(jsontext);
if(ret != jsontext.size())
{
qCritical() << "Failed to write JSON data: " << ret << " " << f.errorString();
return false;
}
return true;
}
bool LoadFromJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion)
{
QByteArray json = f.readAll();
if(json.isEmpty())
{
qCritical() << "Read invalid empty JSON data from file " << f.errorString();
return false;
}
QJsonDocument doc = QJsonDocument::fromJson(json);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert file to JSON document";
return false;
}
data = doc.toVariant().toMap();
if(data.isEmpty() || !data.contains(magicIdentifier))
{
qCritical() << "Converted config data is invalid or unrecognised";
return false;
}
if(data[magicIdentifier].toUInt() != magicVersion)
{
qCritical() << "Converted config data is not the right version";
return false;
}
return true;
}
void GUIInvoke::call(const std::function<void()> &f)
{
if(qApp->thread() == QThread::currentThread())
{
f();
return;
}
// TODO: could maybe do away with string compare here via caching
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
GUIInvoke *invoke = new GUIInvoke(f);
invoke->moveToThread(qApp->thread());
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::QueuedConnection);
}
void GUIInvoke::blockcall(const std::function<void()> &f)
{
if(qApp->thread() == QThread::currentThread())
{
f();
return;
}
// TODO: could maybe do away with string compare here via caching
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
GUIInvoke *invoke = new GUIInvoke(f);
invoke->moveToThread(qApp->thread());
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::BlockingQueuedConnection);
}
void RDDialog::show(QMenu *menu, QPoint pos)
{
menu->setWindowModality(Qt::ApplicationModal);
menu->popup(pos);
QEventLoop loop;
while(menu->isVisible())
{
loop.processEvents(QEventLoop::WaitForMoreEvents);
QCoreApplication::sendPostedEvents();
}
}
int RDDialog::show(QDialog *dialog)
{
dialog->setWindowModality(Qt::ApplicationModal);
dialog->show();
QEventLoop loop;
while(dialog->isVisible())
{
loop.processEvents(QEventLoop::WaitForMoreEvents);
QCoreApplication::sendPostedEvents();
}
return dialog->result();
}
QMessageBox::StandardButton RDDialog::messageBox(QMessageBox::Icon icon, QWidget *parent,
const QString &title, const QString &text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton defaultButton)
{
QMessageBox mb(icon, title, text, buttons, parent);
mb.setDefaultButton(defaultButton);
show(&mb);
return mb.standardButton(mb.clickedButton());
}
QString RDDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, QString());
fd.setAcceptMode(QFileDialog::AcceptOpen);
fd.setFileMode(QFileDialog::DirectoryOnly);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
QString RDDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter, QString *selectedFilter,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, filter);
fd.setAcceptMode(QFileDialog::AcceptOpen);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
if(selectedFilter)
*selectedFilter = fd.selectedNameFilter();
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
QString RDDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter, QString *selectedFilter,
QFileDialog::Options options)
{
QFileDialog fd(parent, caption, dir, filter);
fd.setAcceptMode(QFileDialog::AcceptSave);
fd.setOptions(options);
show(&fd);
if(fd.result() == QFileDialog::Accepted)
{
if(selectedFilter)
*selectedFilter = fd.selectedNameFilter();
QStringList files = fd.selectedFiles();
if(!files.isEmpty())
return files[0];
}
return QString();
}
+194
View File
@@ -0,0 +1,194 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include <QDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <QSemaphore>
bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion);
bool LoadFromJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier,
uint32_t magicVersion);
// implementation of QOverload, to avoid depending on 5.7.
// From: http://stackoverflow.com/a/16795664/4070143
template <typename... Args>
struct OverloadedSlot
{
template <typename C, typename R>
static constexpr auto of(R (C::*pmf)(Args...)) -> decltype(pmf)
{
return pmf;
}
};
// Utility class for invoking a lambda on the GUI thread.
// This is supported by QTimer::singleShot on Qt 5.4 but it's probably
// wise not to require a higher version that necessary.
#include <functional>
class GUIInvoke : public QObject
{
private:
Q_OBJECT
GUIInvoke(const std::function<void()> &f) : func(f) {}
std::function<void()> func;
public:
static void call(const std::function<void()> &f);
static void blockcall(const std::function<void()> &f);
protected slots:
void doInvoke()
{
func();
deleteLater();
}
};
// Utility class for calling a lambda on a new thread.
#include <QThread>
class LambdaThread : public QObject
{
private:
Q_OBJECT
std::function<void()> m_func;
QThread *m_Thread;
QSemaphore completed;
bool m_SelfDelete = false;
public slots:
void process()
{
m_func();
m_Thread->quit();
m_Thread->deleteLater();
m_Thread = NULL;
if(m_SelfDelete)
deleteLater();
completed.acquire();
}
void selfDelete(bool d) { m_SelfDelete = d; }
public:
explicit LambdaThread(std::function<void()> f)
{
completed.release();
m_Thread = new QThread();
m_func = f;
moveToThread(m_Thread);
QObject::connect(m_Thread, &QThread::started, this, &LambdaThread::process);
}
void start(QThread::Priority prio = QThread::InheritPriority) { m_Thread->start(prio); }
bool isRunning() { return completed.available(); }
bool wait(unsigned long time = ULONG_MAX)
{
if(m_Thread)
return m_Thread->wait(time);
return true;
}
};
class QMenu;
// helper for doing a manual blocking invoke of a dialog
struct RDDialog
{
static void show(QMenu *menu, QPoint pos);
static int show(QDialog *dialog);
static QMessageBox::StandardButton messageBox(
QMessageBox::Icon, QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
static QMessageBox::StandardButton information(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Information, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton question(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes |
QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Question, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton warning(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Warning, parent, title, text, buttons, defaultButton);
}
static QMessageBox::StandardButton critical(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton)
{
return messageBox(QMessageBox::Critical, parent, title, text, buttons, defaultButton);
}
static QString getExistingDirectory(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
static QString getOpenFileName(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = NULL,
QFileDialog::Options options = QFileDialog::Options());
static QString getSaveFileName(QWidget *parent = NULL, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = NULL,
QFileDialog::Options options = QFileDialog::Options());
};
// useful delegate for enforcing a given size
#include <QItemDelegate>
class SizeDelegate : public QItemDelegate
{
private:
Q_OBJECT
QSize m_Size;
public:
SizeDelegate(QSize size) : m_Size(size) {}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return m_Size;
}
};
+1
View File
@@ -25,6 +25,7 @@
#include "RenderManager.h"
#include <QMutexLocker>
#include "CaptureContext.h"
#include "QRDUtils.h"
RenderManager::RenderManager()
{
+1
View File
@@ -28,6 +28,7 @@
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include "Code/CaptureContext.h"
#include "Code/QRDUtils.h"
#include "Windows/MainWindow.h"
void sharedLogOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
@@ -24,7 +24,9 @@
#include "TextureSaveDialog.h"
#include <QColorDialog>
#include <QFileInfo>
#include "Code/CaptureContext.h"
#include "Code/QRDUtils.h"
#include "ui_TextureSaveDialog.h"
TextureSaveDialog::TextureSaveDialog(const FetchTexture &t, const TextureSave &s, QWidget *parent)
+1
View File
@@ -25,6 +25,7 @@
#include "EventBrowser.h"
#include <QTimer>
#include "Code/CaptureContext.h"
#include "Code/QRDUtils.h"
#include "ui_EventBrowser.h"
enum
+1
View File
@@ -35,6 +35,7 @@ class EventBrowser;
class QTreeWidgetItem;
class QTimer;
class SizeDelegate;
class EventBrowser : public QFrame, public ILogViewerForm
{
+9 -46
View File
@@ -25,14 +25,17 @@
#include "MainWindow.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QJsonDocument>
#include <QProgressBar>
#include "Code/CaptureContext.h"
#include "Code/QRDUtils.h"
#include "Windows/Dialogs/AboutDialog.h"
#include "EventBrowser.h"
#include "TextureViewer.h"
#include "ui_MainWindow.h"
#define JSON_ID "rdocLayoutData"
#define JSON_VER 1
MainWindow::MainWindow(CaptureContext *ctx) : QMainWindow(NULL), ui(new Ui::MainWindow), m_Ctx(ctx)
{
ui->setupUi(this);
@@ -790,32 +793,9 @@ bool MainWindow::SaveLayout(int layout)
QVariantMap state = saveState();
// marker that this is indeed a valid state to load from
state["renderdocLayoutData"] = 1;
QFile f(path);
if(f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
QJsonDocument doc = QJsonDocument::fromVariant(state);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert state data to JSON document";
return false;
}
QByteArray jsontext = doc.toJson(QJsonDocument::Indented);
qint64 ret = f.write(jsontext);
if(ret != jsontext.size())
{
qCritical() << "Failed to write JSON data to file: " << ret << " " << f.errorString();
return false;
}
return true;
}
return SaveToJSON(state, f, JSON_ID, JSON_VER);
qWarning() << "Couldn't write to " << path << " " << f.errorString();
@@ -829,29 +809,12 @@ bool MainWindow::LoadLayout(int layout)
QFile f(path);
if(f.open(QIODevice::ReadOnly | QIODevice::Text))
{
QByteArray json = f.readAll();
QVariantMap state;
if(json.isEmpty())
{
qCritical() << "Read invalid empty JSON data from file " << f.errorString();
bool success = LoadFromJSON(state, f, JSON_ID, JSON_VER);
if(!success)
return false;
}
QJsonDocument doc = QJsonDocument::fromJson(json);
if(doc.isEmpty() || doc.isNull())
{
qCritical() << "Failed to convert file to JSON document";
return false;
}
QVariantMap state = doc.toVariant().toMap();
if(state.isEmpty() || !state.contains("renderdocLayoutData"))
{
qCritical() << "Converted state data is invalid or unrecognised";
return false;
}
return restoreState(state);
}
+2
View File
@@ -27,12 +27,14 @@
#include <math.h>
#include <QClipboard>
#include <QColorDialog>
#include <QItemDelegate>
#include <QJsonDocument>
#include <QMenu>
#include <QPainter>
#include <QStyledItemDelegate>
#include "3rdparty/toolwindowmanager/ToolWindowManagerArea.h"
#include "Code/CaptureContext.h"
#include "Code/QRDUtils.h"
#include "Dialogs/TextureSaveDialog.h"
#include "Widgets/ResourcePreview.h"
#include "Widgets/TextureGoto.h"
+1
View File
@@ -25,6 +25,7 @@
#pragma once
#include <QFrame>
#include <QMenu>
#include <QMouseEvent>
#include "Code/CaptureContext.h"
+4 -2
View File
@@ -95,7 +95,8 @@ SOURCES += 3rdparty/toolwindowmanager/ToolWindowManager.cpp \
Widgets/ThumbnailStrip.cpp \
Widgets/TextureGoto.cpp \
Widgets/RangeHistogram.cpp \
Windows/Dialogs/TextureSaveDialog.cpp
Windows/Dialogs/TextureSaveDialog.cpp \
Code/QRDUtils.cpp
HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
3rdparty/toolwindowmanager/ToolWindowManagerArea.h \
@@ -118,7 +119,8 @@ HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
Widgets/ThumbnailStrip.h \
Widgets/TextureGoto.h \
Widgets/RangeHistogram.h \
Windows/Dialogs/TextureSaveDialog.h
Windows/Dialogs/TextureSaveDialog.h \
Code/QRDUtils.h
FORMS += Windows/Dialogs/AboutDialog.ui \
Windows/MainWindow.ui \
+3
View File
@@ -278,10 +278,12 @@
<ItemGroup>
<ClCompile Include="Code\CommonPipelineState.cpp" />
<ClCompile Include="Code\PersistantConfig.cpp" />
<ClCompile Include="Code\QRDUtils.cpp" />
<ClCompile Include="generated\moc_AboutDialog.cpp" />
<ClCompile Include="generated\moc_CaptureContext.cpp" />
<ClCompile Include="generated\moc_CustomPaintWidget.cpp" />
<ClCompile Include="generated\moc_EventBrowser.cpp" />
<ClCompile Include="generated\moc_QRDUtils.cpp" />
<ClCompile Include="generated\moc_RangeHistogram.cpp" />
<ClCompile Include="generated\moc_RDDoubleSpinBox.cpp" />
<ClCompile Include="generated\moc_RDLabel.cpp" />
@@ -330,6 +332,7 @@
<ItemGroup>
<ClInclude Include="Code\CommonPipelineState.h" />
<ClInclude Include="Code\PersistantConfig.h" />
<ClInclude Include="Code\QRDUtils.h" />
<ClInclude Include="generated\ui_AboutDialog.h" />
<ClInclude Include="generated\ui_EventBrowser.h" />
<ClInclude Include="generated\ui_MainWindow.h" />
@@ -169,6 +169,12 @@
<ClCompile Include="generated\moc_TextureSaveDialog.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="Code\QRDUtils.cpp">
<Filter>Code</Filter>
</ClCompile>
<ClCompile Include="generated\moc_QRDUtils.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
@@ -246,6 +252,9 @@
<ClInclude Include="generated\ui_TextureSaveDialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="Code\QRDUtils.h">
<Filter>Code</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="resources.qrc">