summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Studio/Application
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Studio/Application')
-rw-r--r--src/Authoring/Studio/Application/DataInputDlg.cpp34
-rw-r--r--src/Authoring/Studio/Application/DataInputDlg.h4
-rw-r--r--src/Authoring/Studio/Application/DataInputDlg.ui42
-rw-r--r--src/Authoring/Studio/Application/DataInputListDlg.cpp41
-rw-r--r--src/Authoring/Studio/Application/DurationEditDlg.cpp214
-rw-r--r--src/Authoring/Studio/Application/DurationEditDlg.h35
-rw-r--r--src/Authoring/Studio/Application/DurationEditDlg.ui59
-rw-r--r--src/Authoring/Studio/Application/ProjectFile.cpp677
-rw-r--r--src/Authoring/Studio/Application/ProjectFile.h25
-rw-r--r--src/Authoring/Studio/Application/StudioApp.cpp13
-rw-r--r--src/Authoring/Studio/Application/TimeEditDlg.cpp210
-rw-r--r--src/Authoring/Studio/Application/TimeEditDlg.h29
-rw-r--r--src/Authoring/Studio/Application/TimeEditDlg.ui68
13 files changed, 1044 insertions, 407 deletions
diff --git a/src/Authoring/Studio/Application/DataInputDlg.cpp b/src/Authoring/Studio/Application/DataInputDlg.cpp
index 0a31424d..9bfec2a0 100644
--- a/src/Authoring/Studio/Application/DataInputDlg.cpp
+++ b/src/Authoring/Studio/Application/DataInputDlg.cpp
@@ -28,6 +28,7 @@
#include "DataInputDlg.h"
#include "ui_DataInputDlg.h"
+#include "Qt3DSMessageBox.h"
#include <QtWidgets/qabstractbutton.h>
#include <QtGui/qstandarditemmodel.h>
@@ -43,6 +44,8 @@ CDataInputDlg::CDataInputDlg(CDataInputDialogItem **datainput, QStandardItemMode
, m_type(0)
, m_min(0.0)
, m_max(10.0)
+ , m_metadataKey(m_dataInput->metaDataKey)
+ , m_metadata(m_dataInput->metaData)
, m_acceptedTypes(acceptedTypes)
{
m_ui->setupUi(this);
@@ -87,6 +90,10 @@ CDataInputDlg::CDataInputDlg(CDataInputDialogItem **datainput, QStandardItemMode
this, &CDataInputDlg::onMaxChanged);
connect(m_ui->lineEditInputName, &QLineEdit::textChanged, this, &CDataInputDlg::onNameChanged);
connect(m_ui->lineEditEvaluation, &QLineEdit::textChanged, this, &CDataInputDlg::onTextChanged);
+ connect(m_ui->lineEditMetadata, &QLineEdit::textChanged, this,
+ &CDataInputDlg::onMetadataChanged);
+ connect(m_ui->lineEditMetadataKey, &QLineEdit::textChanged, this,
+ &CDataInputDlg::onMetadataKeyChanged);
}
CDataInputDlg::~CDataInputDlg()
@@ -127,11 +134,20 @@ void CDataInputDlg::initDialog()
m_ui->doubleSpinBoxMax->setValue(m_dataInput->maxValue);
}
+ m_metadata = m_dataInput->metaData;
+ m_metadataKey = m_dataInput->metaDataKey;
+ m_ui->lineEditMetadata->setText(m_metadata);
+ m_ui->lineEditMetadataKey->setText(m_metadataKey);
updateVisibility(m_dataInput->type);
}
void CDataInputDlg::accept()
{
+ if (m_metadataKey.isEmpty() && !m_metadata.isEmpty()) {
+ Qt3DSMessageBox::Show(tr("Metadata Error"), tr("Metadata key cannot be empty."),
+ Qt3DSMessageBox::ICON_WARNING, false, this);
+ return;
+ }
if (m_dataInput->name != m_name)
m_dataInput->name = getUniqueId(m_name);
@@ -145,6 +161,8 @@ void CDataInputDlg::accept()
m_dataInput->valueString = m_text;
}
#endif
+ m_dataInput->metaData = m_metadata;
+ m_dataInput->metaDataKey = m_metadataKey;
QDialog::accept();
}
@@ -181,6 +199,22 @@ void CDataInputDlg::onTextChanged(const QString &text)
m_text = text;
}
+void CDataInputDlg::onMetadataChanged(const QString &metadata)
+{
+ int cursorPos = m_ui->lineEditMetadata->cursorPosition();
+ m_metadata = metadata;
+ m_ui->lineEditMetadata->setText(metadata);
+ m_ui->lineEditMetadata->setCursorPosition(cursorPos);
+}
+
+void CDataInputDlg::onMetadataKeyChanged(const QString &metadataKey)
+{
+ int cursorPos = m_ui->lineEditMetadataKey->cursorPosition();
+ m_metadataKey = metadataKey;
+ m_ui->lineEditMetadataKey->setText(metadataKey);
+ m_ui->lineEditMetadataKey->setCursorPosition(cursorPos);
+}
+
QString CDataInputDlg::getUniqueId(const QString &id)
{
QString retval = QStringLiteral("%1").arg(id);
diff --git a/src/Authoring/Studio/Application/DataInputDlg.h b/src/Authoring/Studio/Application/DataInputDlg.h
index b560c7cc..49593cd4 100644
--- a/src/Authoring/Studio/Application/DataInputDlg.h
+++ b/src/Authoring/Studio/Application/DataInputDlg.h
@@ -99,6 +99,8 @@ private Q_SLOTS:
void onMaxChanged(float max);
void onNameChanged(const QString &name);
void onTextChanged(const QString &text);
+ void onMetadataChanged(const QString &metadata);
+ void onMetadataKeyChanged(const QString &metadataKey);
private:
Ui::DataInputDlg *m_ui;
@@ -109,6 +111,8 @@ private:
float m_min;
int m_type;
QString m_text;
+ QString m_metadataKey;
+ QString m_metadata;
QVector<EDataType> m_acceptedTypes;
};
diff --git a/src/Authoring/Studio/Application/DataInputDlg.ui b/src/Authoring/Studio/Application/DataInputDlg.ui
index b27218c4..982e2d4f 100644
--- a/src/Authoring/Studio/Application/DataInputDlg.ui
+++ b/src/Authoring/Studio/Application/DataInputDlg.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>533</width>
- <height>244</height>
+ <height>300</height>
</rect>
</property>
<property name="windowTitle">
@@ -133,6 +133,32 @@
</spacer>
</item>
<item>
+ <widget class="QLabel" name="labelMetadataKey">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Metadata Key</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelMetadata">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Metadata</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="labelEvaluation">
<property name="minimumSize">
<size>
@@ -261,6 +287,20 @@
</spacer>
</item>
<item>
+ <widget class="QLineEdit" name="lineEditMetadataKey">
+ <property name="toolTip">
+ <string>Key for accessing the metadata for this Data Input</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditMetadata">
+ <property name="toolTip">
+ <string>Metadata associated with this Data Input</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLineEdit" name="lineEditEvaluation">
<property name="toolTip">
<string/>
diff --git a/src/Authoring/Studio/Application/DataInputListDlg.cpp b/src/Authoring/Studio/Application/DataInputListDlg.cpp
index 4ba31ca9..dbf8d5e5 100644
--- a/src/Authoring/Studio/Application/DataInputListDlg.cpp
+++ b/src/Authoring/Studio/Application/DataInputListDlg.cpp
@@ -141,7 +141,7 @@ void CDataInputListDlg::initDialog()
m_ui->elementInfo->setFocusPolicy(Qt::NoFocus);
m_ui->elementInfo->resizeColumnsToContents();
m_ui->elementInfo->horizontalHeader()->setStretchLastSection(true);
- m_ui->elementInfo->horizontalHeader()->setMinimumSectionSize(125);
+ m_ui->elementInfo->horizontalHeader()->setMinimumSectionSize(140);
m_ui->elementInfo->setModel(m_infoContents);
m_ui->elementInfo->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
@@ -190,7 +190,7 @@ void CDataInputListDlg::updateContents()
for (auto &it : qAsConst(m_dataInputs)) {
dataInput.clear();
- int dataInputType = it->type;
+ EDataType dataInputType = (EDataType)it->type;
if ((dataInputType == m_typeFilter || m_typeFilter == -1)
&& it->name.contains(m_searchString)){
@@ -235,6 +235,26 @@ void CDataInputListDlg::updateContents()
// highlight datainputs that are in use
if (it->ctrldElems.size() || it->externalPresBoundTypes.size())
dataInput.first()->setForeground(QBrush(CStudioPreferences::dataInputColor()));
+
+ // warn if any datainputs have mismatching datatype with an icon after datatype
+ // indicator
+ static QString warning(tr("Data Input type is not matching with one "
+ "or several bound properties"));
+ for (const auto &ctrlElem : qAsConst(it->ctrldElems)) {
+ if (!CDataInputDlg::getAcceptedTypes(ctrlElem.dataType.first)
+ .contains(dataInputType)) {
+ dataInput[1]->setIcon(QIcon(":/images/warning.png"));
+ dataInput[1]->setToolTip(warning);
+ }
+ }
+
+ for (const auto &extBoundType : qAsConst(it->externalPresBoundTypes)) {
+ if (!CDataInputDlg::getAcceptedTypes(extBoundType.first).contains(dataInputType)) {
+ dataInput[1]->setIcon(QIcon(":/images/warning.png"));
+ dataInput[1]->setToolTip(warning);
+ }
+ }
+
m_tableContents->appendRow(dataInput);
}
}
@@ -260,6 +280,7 @@ void CDataInputListDlg::updateInfo()
if (m_ui->tableView->selectionModel()->selectedRows(0).size() == 1) {
for (auto allCtrldElemsIt = m_dataInputs[m_currentDataInputName]->ctrldElems.begin();
allCtrldElemsIt != m_dataInputs[m_currentDataInputName]->ctrldElems.end();) {
+ bool typeNotMatching = false;
QStandardItem *item = new QStandardItem(
g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()
->GetClientDataModelBridge()->GetName(
@@ -297,6 +318,13 @@ void CDataInputListDlg::updateInfo()
}
count++;
+
+ // Check if there is a non-matching datatype binding with one or several
+ // properties for this element.
+ if (!CDataInputDlg::getAcceptedTypes(allCtrldElemsIt->dataType.first).contains(
+ (EDataType)(m_dataInputs[m_currentDataInputName]->type))) {
+ typeNotMatching = true;
+ }
// Advance main iterator so that after the inner loop we end up
// at the start of next instance's batch of controlleditems.
allCtrldElemsIt++;
@@ -310,6 +338,15 @@ void CDataInputListDlg::updateInfo()
QStandardItem *item3 = new QStandardItem(propNames);
item3->setToolTip(propNames);
item3->setEditable(false);
+
+ // Highlight the entire property name item if a non-match was found.
+ if (typeNotMatching) {
+ item3->setForeground(
+ QBrush(CStudioPreferences::invalidDataInputIndicatorColor()));
+ static QString warning(tr("\n\nData Input type is not matching with one or "
+ "several bound properties"));
+ item3->setToolTip(propNames + warning);
+ }
m_infoContents->appendRow(QList<QStandardItem *>({item, item2, item3}));
}
}
diff --git a/src/Authoring/Studio/Application/DurationEditDlg.cpp b/src/Authoring/Studio/Application/DurationEditDlg.cpp
index 0d7c4899..f0707a56 100644
--- a/src/Authoring/Studio/Application/DurationEditDlg.cpp
+++ b/src/Authoring/Studio/Application/DurationEditDlg.cpp
@@ -29,33 +29,15 @@
#include "ui_DurationEditDlg.h"
#include "DurationEditDlg.h"
-#include "IDoc.h"
-#include "Bindings/ITimelineKeyframesManager.h"
-
+#include "TimeEnums.h"
#include <QtGui/qvalidator.h>
-//=============================================================================
-/**
- * Constructor
- */
-CDurationEditDlg::CDurationEditDlg(QWidget *pParent)
- : QDialog(pParent)
+CDurationEditDlg::CDurationEditDlg(QWidget *parent)
+ : QDialog(parent)
, m_ui(new Ui::DurationEditDlg)
- , m_Doc(nullptr)
- , m_KeyframesManager(nullptr)
- , m_Callback(nullptr)
- , m_MaxTime(0)
- , m_MaxTimeDisplay(0)
- , m_MinTimeDisplay(0)
- , m_InitialTimeStart(0)
- , m_InitialTimeEnd(0)
- , m_minStart(-1)
- , m_secStart(-1)
- , m_minEnd(-1)
- , m_secEnd(-1)
{
m_ui->setupUi(this);
- setAutoFillBackground(true);
+ setWindowFlag(Qt::WindowContextHelpButtonHint, false); // remove '?' from the dialog title bar
QIntValidator *minValidator = new QIntValidator(this);
minValidator->setRange(0, 9999);
@@ -83,8 +65,6 @@ CDurationEditDlg::CDurationEditDlg(QWidget *pParent)
this, &CDurationEditDlg::onEndTimeChanged);
connect(m_ui->lineEditEndMilliseconds, &QLineEdit::textEdited,
this, &CDurationEditDlg::onEndTimeChanged);
-
- window()->setFixedSize(size());
}
CDurationEditDlg::~CDurationEditDlg()
@@ -92,72 +72,50 @@ CDurationEditDlg::~CDurationEditDlg()
delete m_ui;
}
-void CDurationEditDlg::setKeyframesManager(ITimelineKeyframesManager *inKeyframesManager)
-{
- m_KeyframesManager = inKeyframesManager;
-}
-
-//=============================================================================
/**
- * showDialog: Initializes and shows the Duration Edit Dialog Box.
+ * Initializes and shows the Duration Edit Dialog Box.
* @param startTime is the initial start time, which will be shown when the time edit
* dialog box pops up
* @param endTime is the initial end time, which will be shown when the time edit
* dialog box pops up
- * @param inDoc this can be nullptr where its not applicable
* @param inCallback is the target object for the callbacks
*/
-void CDurationEditDlg::showDialog(long startTime, long endTime, IDoc *inDoc,
- ITimeChangeCallback *inCallback)
+void CDurationEditDlg::showDialog(long startTime, long endTime, ITimeChangeCallback *inCallback)
{
- m_InitialTimeStart = startTime;
- m_InitialTimeEnd = endTime;
- m_Doc = inDoc;
m_Callback = inCallback;
- m_MinTimeDisplay = 0;
- // if it is a Timebar, this will be adjusted, else this should be initialized to some value at
- // least, for OverflowHandling to work correctly
- m_MaxTimeDisplay = LONG_MAX;
-
- // 9999:59:999 converted to milliseconds
- m_MaxTime = timeConversion(9999, CONVERT_MIN_TO_MSEC)
- + timeConversion(59, CONVERT_SEC_TO_MSEC) + 999;
-
// Set initial values to dialog
- formatTime(m_InitialTimeStart, true);
- formatTime(m_InitialTimeEnd, false);
+ formatTime(startTime, true);
+ formatTime(endTime, false);
- // Present the dialog
exec();
}
void CDurationEditDlg::formatTime(long inTime, bool startTime)
{
- long theTime = inTime;
- long min = 0;
- long sec = 0;
- long msec = 0;
+ long mins = 0;
+ long secs = 0;
+ long mils = 0;
- // Translates the m_initialTime (in milliseconds) into Minutes, Seconds and Milliseconds
if (inTime != 0) {
- min = timeConversion(theTime, CONVERT_MSEC_TO_MIN);
- theTime = theTime - timeConversion(min, CONVERT_MIN_TO_MSEC);
- sec = timeConversion(theTime, CONVERT_MSEC_TO_SEC);
- theTime = theTime - timeConversion(sec, CONVERT_SEC_TO_MSEC);
- msec = theTime;
+ mins = inTime % 3600000 / 60000;
+ secs = inTime % 60000 / 1000;
+ mils = inTime % 1000;
}
+ // display milliseconds in 3 digits (5 -> 005)
+ QString milsStr = QString("%1").arg(mils, 3, 10, QChar('0'));
+
if (startTime) {
- m_ui->lineEditMinutes->setText(QString::number(min));
- m_ui->lineEditSeconds->setText(QString::number(sec));
- m_ui->lineEditMilliseconds->setText(QString::number(msec));
+ m_ui->lineEditMinutes->setText(QString::number(mins));
+ m_ui->lineEditSeconds->setText(QString::number(secs));
+ m_ui->lineEditMilliseconds->setText(milsStr);
// Select the biggest non-zero unit
- if (min > 0) {
+ if (mins > 0) {
m_ui->lineEditMinutes->setFocus();
m_ui->lineEditMinutes->selectAll();
- } else if (sec > 0) {
+ } else if (secs > 0) {
m_ui->lineEditSeconds->setFocus();
m_ui->lineEditSeconds->selectAll();
} else {
@@ -165,17 +123,12 @@ void CDurationEditDlg::formatTime(long inTime, bool startTime)
m_ui->lineEditMilliseconds->selectAll();
}
} else {
- m_ui->lineEditEndMinutes->setText(QString::number(min));
- m_ui->lineEditEndSeconds->setText(QString::number(sec));
- m_ui->lineEditEndMilliseconds->setText(QString::number(msec));
+ m_ui->lineEditEndMinutes->setText(QString::number(mins));
+ m_ui->lineEditEndSeconds->setText(QString::number(secs));
+ m_ui->lineEditEndMilliseconds->setText(milsStr);
}
}
-void CDurationEditDlg::showEvent(QShowEvent *ev)
-{
- QDialog::showEvent(ev);
-}
-
void CDurationEditDlg::accept()
{
m_Callback->Commit();
@@ -188,94 +141,6 @@ void CDurationEditDlg::reject()
QDialog::reject();
}
-long CDurationEditDlg::numberOfDigits(long number)
-{
- long theNumberOfDigits = 0;
- for (long theNumber = number; theNumber >= 1; theNumber = theNumber / 10)
- theNumberOfDigits++;
- return theNumberOfDigits;
-}
-
-//==============================================================================
-/**
- * timeConversion: Converts inTime to the format specified by inFlags.
- * For example:
- * inTime = 5 sec inFlags = CONVERT_SEC_TO_MSEC
- * The method will convert 5 sec into 5000 msec and
- * returns the result.
- * @param inTime stores the time to be converted.
- * inOperationCode determines the type of time conversion to be done on the
- * inTime.
- * @return theResult stores the result of the time conversion.
- */
-long CDurationEditDlg::timeConversion(long inTime, long inOperationCode)
-{
- long theResult = 0;
- switch (inOperationCode) {
- case CONVERT_MIN_TO_MSEC:
- theResult = inTime * 60 * 1000;
- break;
- case CONVERT_SEC_TO_MSEC:
- theResult = inTime * 1000;
- break;
- case CONVERT_MSEC_TO_MIN:
- theResult = inTime / (60 * 1000);
- break;
- case CONVERT_MSEC_TO_SEC:
- theResult = inTime / 1000;
- break;
- }
- return theResult;
-}
-
-//==============================================================================
-/**
- * timeConversion: Takes in the time in mins:secs:msec and convert it to
- * the corresponding time in msec.
- * @param inMin stores the minutes to be converted.
- * inSec stores the seconds to be converted.
- * inMsec stores the milliseconds to be converted.
- * inOperationCode determines the type of time conversion to be done on the
- * inMin, inSec and inMsec.
- * @return theResult stores the result of the time conversion.
- */
-long CDurationEditDlg::timeConversion(long inMin, long inSec, long inMsec, long inOperationCode)
-{
- long theResult = 0;
- switch (inOperationCode) {
- case CONVERT_TIME_TO_MSEC:
- theResult = timeConversion(inMin, CONVERT_MIN_TO_MSEC)
- + timeConversion(inSec, CONVERT_SEC_TO_MSEC) + inMsec;
- break;
- }
- return theResult;
-}
-
-//==============================================================================
-/**
- * timeConversion: Takes in the time in milliseconds and converts them
- * to min : sec : msec.
- * @param inTotalTime stores the total time in msec.
- * ioMin stores the mins result of the time conversion
- * ioSec stores the secs result of the time conversion
- * ioMsec stores the msecs result of the time conversion
- * inOperationCode determines the type of time conversion to be done on the
- * inTotalTime.
- */
-void CDurationEditDlg::timeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
- long inOperationCode)
-{
- switch (inOperationCode) {
- case CONVERT_MSEC_TO_MIN_SEC_MSEC:
- *ioMin = timeConversion(inTotalTime, CONVERT_MSEC_TO_MIN);
- *ioSec = inTotalTime - timeConversion(*ioMin, CONVERT_MIN_TO_MSEC);
- *ioSec = timeConversion(*ioSec, CONVERT_MSEC_TO_SEC);
- *ioMsec = inTotalTime - timeConversion(*ioMin, CONVERT_MIN_TO_MSEC)
- - timeConversion(*ioSec, CONVERT_SEC_TO_MSEC);
- break;
- }
-}
-
void CDurationEditDlg::updateObjectTime(long inTime, bool startTime)
{
if (m_Callback) {
@@ -288,59 +153,42 @@ void CDurationEditDlg::updateObjectTime(long inTime, bool startTime)
void CDurationEditDlg::onStartTimeChanged()
{
- // Making sure that the start time is not greater than the end time, when
- // the user modifies the start time of the timebar
- m_MaxTimeDisplay = m_InitialTimeEnd; // the initial end time
- m_MinTimeDisplay = 0;
-
long min = m_ui->lineEditMinutes->text().toInt();
long sec = m_ui->lineEditSeconds->text().toInt();
long msec = m_ui->lineEditMilliseconds->text().toInt();
- long theGoToTime = timeConversion(min, CONVERT_MIN_TO_MSEC)
- + timeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ long theGoToTime = min * 60000 + sec * 1000 + msec;
// Go to the time specified in the start time edit display
updateObjectTime(theGoToTime, true);
// If max number of digits reached in a number field, select the next
- if (m_minStart != min && numberOfDigits(min) == 4) {
+ if (m_ui->lineEditMinutes->hasFocus() && min > 999) {
m_ui->lineEditSeconds->setFocus();
m_ui->lineEditSeconds->selectAll();
- } else if (m_secStart != sec && numberOfDigits(sec) == 2) {
+ } else if (m_ui->lineEditSeconds->hasFocus() && sec > 9) {
m_ui->lineEditMilliseconds->setFocus();
m_ui->lineEditMilliseconds->selectAll();
}
-
- m_minStart = min;
- m_secStart = sec;
}
void CDurationEditDlg::onEndTimeChanged()
{
- // Let the end time of the time bar go as far as possible
- m_MaxTimeDisplay = m_MaxTime;
- m_MinTimeDisplay = m_InitialTimeStart; // the initial start time
-
long min = m_ui->lineEditEndMinutes->text().toInt();
long sec = m_ui->lineEditEndSeconds->text().toInt();
long msec = m_ui->lineEditEndMilliseconds->text().toInt();
- long theGoToTime = timeConversion(min, CONVERT_MIN_TO_MSEC)
- + timeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ long theGoToTime = min * 60000 + sec * 1000 + msec;
// Go to the time specified in the end time edit display
updateObjectTime(theGoToTime, false);
// If max number of digits reached in a number field, select the next
- if (m_minEnd != min && numberOfDigits(min) == 4) {
+ if (m_ui->lineEditEndMinutes->hasFocus() && min > 999) {
m_ui->lineEditEndSeconds->setFocus();
m_ui->lineEditEndSeconds->selectAll();
- } else if (m_secEnd != sec && numberOfDigits(sec) == 2) {
+ } else if (m_ui->lineEditEndSeconds->hasFocus() && sec > 9) {
m_ui->lineEditEndMilliseconds->setFocus();
m_ui->lineEditEndMilliseconds->selectAll();
}
-
- m_minEnd = min;
- m_secEnd = sec;
}
diff --git a/src/Authoring/Studio/Application/DurationEditDlg.h b/src/Authoring/Studio/Application/DurationEditDlg.h
index 7630b02a..ddb42ec0 100644
--- a/src/Authoring/Studio/Application/DurationEditDlg.h
+++ b/src/Authoring/Studio/Application/DurationEditDlg.h
@@ -30,12 +30,9 @@
#ifndef DURATION_EDIT_DIALOG_H
#define DURATION_EDIT_DIALOG_H
-#include "TimeEnums.h"
#include <QtWidgets/qdialog.h>
-class CTimebarControl;
class IDoc;
-class ITimelineKeyframesManager;
class ITimeChangeCallback
{
@@ -62,43 +59,23 @@ class CDurationEditDlg : public QDialog
Q_OBJECT
public:
- CDurationEditDlg(QWidget *pParent = nullptr); // standard constructor
- virtual ~CDurationEditDlg();
- void setKeyframesManager(ITimelineKeyframesManager *inKeyframeManager);
- void showDialog(long startTime, long endTime, IDoc *inDoc,
- ITimeChangeCallback *inCallback = nullptr);
+ CDurationEditDlg(QWidget *parent = nullptr);
+ ~CDurationEditDlg() override;
+
+ void showDialog(long startTime, long endTime, ITimeChangeCallback *inCallback = nullptr);
public Q_SLOTS:
void accept() override;
void reject() override;
-protected:
- void showEvent(QShowEvent *) override;
-
+private:
void onStartTimeChanged();
void onEndTimeChanged();
void formatTime(long inTime, bool startTime);
- long numberOfDigits(long number);
- long timeConversion(long inTime, long inOperationCode);
- long timeConversion(long inMin, long inSec, long inMsec, long inOperationCode);
- void timeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
- long inOperationCode);
void updateObjectTime(long inTime, bool startTime);
-protected:
Ui::DurationEditDlg *m_ui;
- IDoc *m_Doc;
- ITimelineKeyframesManager *m_KeyframesManager;
- ITimeChangeCallback *m_Callback;
- long m_MaxTime;
- long m_MaxTimeDisplay;
- long m_MinTimeDisplay;
- long m_InitialTimeStart;
- long m_InitialTimeEnd;
- int m_minStart;
- int m_secStart;
- int m_minEnd;
- int m_secEnd;
+ ITimeChangeCallback *m_Callback = nullptr;
};
#endif // DURATION_EDIT_DIALOG_H
diff --git a/src/Authoring/Studio/Application/DurationEditDlg.ui b/src/Authoring/Studio/Application/DurationEditDlg.ui
index 062a5051..4f6bb7de 100644
--- a/src/Authoring/Studio/Application/DurationEditDlg.ui
+++ b/src/Authoring/Studio/Application/DurationEditDlg.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>300</width>
+ <width>343</width>
<height>152</height>
</rect>
</property>
@@ -14,6 +14,9 @@
<string>Set Timebar Start / End Time</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetFixedSize</enum>
+ </property>
<property name="leftMargin">
<number>0</number>
</property>
@@ -70,7 +73,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditMinutes"/>
+ <widget class="QLineEdit" name="lineEditMinutes">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_2">
@@ -80,7 +90,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditSeconds"/>
+ <widget class="QLineEdit" name="lineEditSeconds">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_3">
@@ -90,7 +107,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditMilliseconds"/>
+ <widget class="QLineEdit" name="lineEditMilliseconds">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
</layout>
</widget>
@@ -124,7 +148,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditEndMinutes"/>
+ <widget class="QLineEdit" name="lineEditEndMinutes">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_7">
@@ -134,7 +165,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditEndSeconds"/>
+ <widget class="QLineEdit" name="lineEditEndSeconds">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_8">
@@ -144,7 +182,14 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditEndMilliseconds"/>
+ <widget class="QLineEdit" name="lineEditEndMilliseconds">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
</layout>
</widget>
diff --git a/src/Authoring/Studio/Application/ProjectFile.cpp b/src/Authoring/Studio/Application/ProjectFile.cpp
index a2792049..a4b5b9c0 100644
--- a/src/Authoring/Studio/Application/ProjectFile.cpp
+++ b/src/Authoring/Studio/Application/ProjectFile.cpp
@@ -43,6 +43,8 @@
#include <QtCore/qdiriterator.h>
#include <QtCore/qsavefile.h>
#include <QtCore/qtimer.h>
+#include <QtCore/qrandom.h>
+#include <QtWidgets/qmessagebox.h>
ProjectFile::ProjectFile()
{
@@ -493,6 +495,8 @@ void ProjectFile::parseDataInputElem(const QDomElement &elem,
item->valueString = elem.attribute(QStringLiteral("evaluator"));
}
#endif
+ item->metaDataKey = elem.attribute((QStringLiteral("metadatakey")));
+ item->metaData = elem.attribute((QStringLiteral("metadata")));
dataInputs.insert(item->name, item);
}
}
@@ -926,3 +930,676 @@ ProjectFile::getDiBindingtypesFromSubpresentations() const
return map;
}
+
+/**
+ * Load variants data to m_variantsDef
+ *
+ * @param filePath the file path to load the variants from. If empty, variants are loaded from the
+ * project file and replace m_variantsDef. If a filePath is specified, the loaded
+ * variants are merged with m_variantsDef
+ */
+void ProjectFile::loadVariants(const QString &filePath)
+{
+ if (!m_fileInfo.exists())
+ return;
+
+ bool isProj = filePath.isEmpty() || filePath == getProjectFilePath();
+ QFile file(isProj ? getProjectFilePath() : filePath);
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
+ qWarning() << file.errorString();
+ return;
+ }
+
+ if (isProj)
+ m_variantsDef.clear();
+
+ QXmlStreamReader reader(&file);
+ reader.setNamespaceProcessing(false);
+
+ VariantGroup *currentGroup = nullptr;
+ while (!reader.atEnd()) {
+ if (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("variantgroup")) {
+ QString groupId = reader.attributes().value(QLatin1String("id")).toString();
+ QString groupColor = reader.attributes().value(QLatin1String("color")).toString();
+ currentGroup = &m_variantsDef[groupId];
+ currentGroup->m_color = groupColor;
+ } else if (reader.name() == QLatin1String("variant")) {
+ if (currentGroup) {
+ QString tagId = reader.attributes().value(QLatin1String("id")).toString();
+ if (!currentGroup->m_tags.contains(tagId))
+ currentGroup->m_tags.append(tagId);
+ } else {
+ qWarning() << "Error parsing variant tags.";
+ }
+ } else if (currentGroup) {
+ break;
+ }
+ }
+ }
+
+ if (!isProj) {
+ // if loading variants from a file, update the uia
+ QDomDocument domDoc;
+ QSaveFile fileProj(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(fileProj, domDoc))
+ return;
+
+ QDomElement vElem = domDoc.documentElement().firstChildElement(QStringLiteral("variants"));
+ if (!vElem.isNull())
+ domDoc.documentElement().removeChild(vElem);
+
+ vElem = domDoc.createElement(QStringLiteral("variants"));
+ domDoc.documentElement().appendChild(vElem);
+
+ const auto keys = m_variantsDef.keys();
+ for (auto &g : keys) {
+ QDomElement gElem = domDoc.createElement(QStringLiteral("variantgroup"));
+ gElem.setAttribute(QStringLiteral("id"), g);
+ gElem.setAttribute(QStringLiteral("color"), m_variantsDef[g].m_color);
+ vElem.appendChild(gElem);
+
+ for (auto &t : qAsConst(m_variantsDef[g].m_tags)) {
+ QDomElement tElem = domDoc.createElement(QStringLiteral("variant"));
+ tElem.setAttribute(QStringLiteral("id"), t);
+ gElem.appendChild(tElem);
+ }
+ }
+
+ StudioUtils::commitDomDocumentSave(fileProj, domDoc);
+ }
+}
+
+// Add a new tag to a variants group
+void ProjectFile::addVariantTag(const QString &group, const QString &newTag)
+{
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomElement newTagElem = domDoc.createElement(QStringLiteral("variant"));
+ newTagElem.setAttribute(QStringLiteral("id"), newTag);
+
+ QDomNodeList groupsElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"))
+ .elementsByTagName(QStringLiteral("variantgroup"));
+
+ // update and save the uia
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == group) {
+ gElem.appendChild(newTagElem);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ break;
+ }
+ }
+
+ // update m_variantsDef
+ m_variantsDef[group].m_tags.append(newTag);
+}
+
+// Add a new group, it is assumes that the new group name is unique
+void ProjectFile::addVariantGroup(const QString &newGroup)
+{
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomElement variantsElem = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"));
+
+ if (variantsElem.isNull()) {
+ QDomElement newVariantsElem = domDoc.createElement(QStringLiteral("variants"));
+ domDoc.documentElement().appendChild(newVariantsElem);
+ variantsElem = newVariantsElem;
+ }
+
+ // generate random semi-bright color
+ int r = 0x555555 + QRandomGenerator::global()->generate() % 0x555555; // 0x555555 = 0xffffff / 3
+ QString newColor = QLatin1Char('#') + QString::number(r, 16);
+
+ QDomElement newGroupElem = domDoc.createElement(QStringLiteral("variantgroup"));
+ newGroupElem.setAttribute(QStringLiteral("id"), newGroup);
+ newGroupElem.setAttribute(QStringLiteral("color"), newColor);
+ variantsElem.appendChild(newGroupElem);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+
+ // update m_variantsDef
+ VariantGroup g;
+ g.m_color = newColor;
+ m_variantsDef[newGroup] = g;
+}
+
+void ProjectFile::renameVariantTag(const QString &group, const QString &oldTag,
+ const QString &newTag)
+{
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ // rename the tag in all uip files
+ QDomNodeList presElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("assets"))
+ .elementsByTagName(QStringLiteral("presentation"));
+ for (int i = 0; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ renameTagInUip(pPath, group, oldTag, newTag);
+ }
+
+ // update and save the uia
+ QDomNodeList groupsElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"))
+ .elementsByTagName(QStringLiteral("variantgroup"));
+
+ bool renamed = false;
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == group) {
+ QDomNodeList tagsElems = gElem.childNodes();
+ for (int j = 0; j < tagsElems.count(); ++j) {
+ QDomElement tElem = tagsElems.at(j).toElement();
+ if (tElem.attribute(QStringLiteral("id")) == oldTag) {
+ tElem.setAttribute(QStringLiteral("id"), newTag);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ renamed = true;
+ break;
+ }
+ }
+ if (renamed)
+ break;
+ }
+ }
+
+ // update the property
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+ const auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ const auto layers = doc->getLayers();
+ auto property = bridge->GetLayer().m_variants;
+ for (auto layer : layers) {
+ qt3dsdm::SValue sValue;
+ if (propertySystem->GetInstancePropertyValue(layer, property, sValue)) {
+ QString propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
+ ->GetData());
+ QString oldGroupTagPair = QStringLiteral("%1:%2").arg(group).arg(oldTag);
+ if (propVal.contains(oldGroupTagPair)) {
+ propVal.replace(oldGroupTagPair, QStringLiteral("%1:%2").arg(group).arg(newTag));
+ qt3dsdm::SValue sVal
+ = std::make_shared<qt3dsdm::CDataStr>(Q3DStudio::CString::fromQString(propVal));
+ propertySystem->SetInstancePropertyValue(layer, property, sVal);
+ }
+ }
+ }
+
+ // update m_variantsDef
+ for (auto &t : m_variantsDef[group].m_tags) {
+ if (t == oldTag) {
+ t = newTag;
+ renamed = true;
+ break;
+ }
+ }
+}
+
+// rename a variant group, newGroup is assumed to be unique
+void ProjectFile::renameVariantGroup(const QString &oldGroup, const QString &newGroup)
+{
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ // rename the group in all uip files
+ QDomNodeList presElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("assets"))
+ .elementsByTagName(QStringLiteral("presentation"));
+ for (int i = 0; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ renameGroupInUip(pPath, oldGroup, newGroup);
+ }
+
+ // update and save the uia
+ QDomNodeList groupsElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"))
+ .elementsByTagName(QStringLiteral("variantgroup"));
+
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == oldGroup) {
+ gElem.setAttribute(QStringLiteral("id"), newGroup);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ break;
+ }
+ }
+
+ // update the property
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+ const auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ const auto layers = doc->getLayers();
+ auto property = bridge->GetLayer().m_variants;
+ for (auto layer : layers) {
+ qt3dsdm::SValue sValue;
+ if (propertySystem->GetInstancePropertyValue(layer, property, sValue)) {
+ QString propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
+ ->GetData());
+ QString oldGroupWithColon = QStringLiteral("%1:").arg(oldGroup);
+ if (propVal.contains(oldGroupWithColon)) {
+ propVal.replace(oldGroupWithColon, QStringLiteral("%1:").arg(newGroup));
+ qt3dsdm::SValue sVal = std::make_shared<qt3dsdm::CDataStr>(
+ Q3DStudio::CString::fromQString(propVal));
+ propertySystem->SetInstancePropertyValue(layer, property, sVal);
+ }
+ }
+ }
+
+ // update m_variantsDef
+ m_variantsDef[newGroup] = m_variantsDef[oldGroup];
+ m_variantsDef.remove(oldGroup);
+}
+
+void ProjectFile::deleteVariantGroup(const QString &group)
+{
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ // check if group is in use in other presentations in the porject
+ int inUseIdx = -1; // index of first presentation that has the group in-use
+ QDomNodeList presElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("assets"))
+ .elementsByTagName(QStringLiteral("presentation"));
+ for (int i = 0; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ if (pPath != doc->GetDocumentPath() && groupExistsInUip(pPath, group)) {
+ inUseIdx = i;
+ break;
+ }
+ }
+
+ if (inUseIdx != -1) {
+ QMessageBox box;
+ box.setWindowTitle(tr("Group tags in use"));
+ box.setText(tr("Some tags in the Group '%1' are in use in the project, are you sure you"
+ " want to delete the group?").arg(group));
+ box.setIcon(QMessageBox::Warning);
+ box.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+ box.setButtonText(QMessageBox::Yes, QStringLiteral("Delete"));
+ switch (box.exec()) {
+ case QMessageBox::Yes:
+ // delete the group from all uips that use it
+ for (int i = inUseIdx; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ if (pPath != doc->GetDocumentPath())
+ deleteGroupFromUip(pPath, group);
+ }
+ break;
+
+ default:
+ // abort deletion
+ return;
+ }
+ }
+
+ // delete the group from current uip, if exists
+ deleteGroupFromUip(doc->GetDocumentPath(), group);
+
+ // delete the group from the property (if set)
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+ const auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ const auto layers = doc->getLayers();
+ auto property = bridge->GetLayer().m_variants;
+ for (auto layer : layers) {
+ qt3dsdm::SValue sValue;
+ if (propertySystem->GetInstancePropertyValue(layer, property, sValue)) {
+ QString propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
+ ->GetData());
+ if (propVal.contains(QStringLiteral("%1:").arg(group))) {
+ // property has the deleted group, need to update it, else the deleted group
+ // will be saved the uip if the user saves the presentation.
+ QRegExp rgx(QStringLiteral("%1:\\w*,*|,%1:\\w*").arg(group));
+ propVal.replace(rgx, {});
+ qt3dsdm::SValue sVal = std::make_shared<qt3dsdm::CDataStr>(
+ Q3DStudio::CString::fromQString(propVal));
+ propertySystem->SetInstancePropertyValue(layer, property, sVal);
+ }
+ }
+ }
+
+ // update and save the uia
+ QDomElement variantsElem = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"));
+ QDomNodeList groupsElems = variantsElem.elementsByTagName(QStringLiteral("variantgroup"));
+
+ bool deleted = false;
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == group) {
+ variantsElem.removeChild(gElem);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ deleted = true;
+ break;
+ }
+ }
+
+ // update m_variantsDef
+ m_variantsDef.remove(group);
+}
+
+void ProjectFile::changeVariantGroupColor(const QString &group, const QString &newColor)
+{
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ // update and save the uia
+ QDomNodeList groupsElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"))
+ .elementsByTagName(QStringLiteral("variantgroup"));
+
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == group) {
+ gElem.setAttribute(QStringLiteral("color"), newColor);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ break;
+ }
+ }
+
+ // update m_variantsDef
+ m_variantsDef[group].m_color = newColor;
+}
+
+bool ProjectFile::tagExistsInUip(const QString &src, const QString &group, const QString &tag) const
+{
+ QFile file(src);
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
+ qWarning() << file.errorString();
+ return false;
+ }
+
+ QXmlStreamReader reader(&file);
+ reader.setNamespaceProcessing(false);
+
+ while (!reader.atEnd()) {
+ if (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Layer")
+ && reader.attributes().hasAttribute(QLatin1String("variants"))) {
+ QStringRef v = reader.attributes().value(QLatin1String("variants"));
+ if (v.contains(group + QLatin1Char(':') + tag))
+ return true;
+ } else if (reader.name() == QLatin1String("Logic")) {
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ProjectFile::groupExistsInUip(const QString &src, const QString &group) const
+{
+ QFile file(src);
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
+ qWarning() << file.errorString();
+ return false;
+ }
+
+ QXmlStreamReader reader(&file);
+ reader.setNamespaceProcessing(false);
+
+ while (!reader.atEnd()) {
+ if (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Layer")
+ && reader.attributes().hasAttribute(QLatin1String("variants"))) {
+ QStringRef v = reader.attributes().value(QLatin1String("variants"));
+ if (v.contains(group + QLatin1Char(':')))
+ return true;
+ } else if (reader.name() == QLatin1String("Logic")) {
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+// renames a tag (if exists) in all layers in a uip file
+void ProjectFile::renameTagInUip(const QString &src, const QString &group, const QString &tag,
+ const QString &newName)
+{
+ QDomDocument domDoc;
+ QSaveFile file(src);
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomNodeList layerElems = domDoc.documentElement()
+ .elementsByTagName(QStringLiteral("Layer"));
+ bool needSave = false;
+ for (int i = 0; i < layerElems.count(); ++i) {
+ QDomElement lElem = layerElems.at(i).toElement();
+ if (lElem.hasAttribute(QStringLiteral("variants"))) {
+ QStringList tagPairs = lElem.attribute(QStringLiteral("variants"))
+ .split(QLatin1Char(','));
+ QString tagFrom = group + QLatin1Char(':') + tag;
+ QString tagTo = group + QLatin1Char(':') + newName;
+
+ if (tagPairs.contains(tagFrom)) {
+ tagPairs.replaceInStrings(tagFrom, tagTo);
+ lElem.setAttribute(QStringLiteral("variants"), tagPairs.join(QLatin1Char(',')));
+ needSave = true;
+ }
+ }
+ }
+
+ if (needSave)
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+}
+
+void ProjectFile::renameGroupInUip(const QString &src, const QString &group, const QString &newName)
+{
+ QDomDocument domDoc;
+ QSaveFile file(src);
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomNodeList layerElems = domDoc.documentElement()
+ .elementsByTagName(QStringLiteral("Layer"));
+ bool needSave = false;
+ for (int i = 0; i < layerElems.count(); ++i) {
+ QDomElement lElem = layerElems.at(i).toElement();
+ if (lElem.hasAttribute(QStringLiteral("variants"))) {
+ QString variants = lElem.attribute(QStringLiteral("variants"));
+ if (variants.contains(group + QLatin1Char(':'))) {
+ variants.replace(group + QLatin1Char(':'), newName + QLatin1Char(':'));
+ lElem.setAttribute(QStringLiteral("variants"), variants);
+ needSave = true;
+ }
+ }
+ }
+
+ if (needSave)
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+}
+
+// deletes a tag (if exists) from all layers in a uip file
+void ProjectFile::deleteTagFromUip(const QString &src, const QString &group, const QString &tag)
+{
+ QDomDocument domDoc;
+ QSaveFile file(src);
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomNodeList layerElems = domDoc.documentElement()
+ .elementsByTagName(QStringLiteral("Layer"));
+ bool needSave = false;
+ for (int i = 0; i < layerElems.count(); ++i) {
+ QDomElement lElem = layerElems.at(i).toElement();
+ if (lElem.hasAttribute(QStringLiteral("variants"))) {
+ QStringList tagPairs = lElem.attribute(QStringLiteral("variants"))
+ .split(QLatin1Char(','));
+ QString tagPair = group + QLatin1Char(':') + tag;
+ if (tagPairs.contains(tagPair)) {
+ tagPairs.removeOne(tagPair);
+ lElem.setAttribute(QStringLiteral("variants"), tagPairs.join(QLatin1Char(',')));
+ needSave = true;
+ }
+ }
+ }
+
+ if (needSave)
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+}
+
+// deletes a group (if exists) from all layers in a uip file
+void ProjectFile::deleteGroupFromUip(const QString &src, const QString &group)
+{
+ QDomDocument domDoc;
+ QSaveFile file(src);
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ QDomNodeList layerElems = domDoc.documentElement()
+ .elementsByTagName(QStringLiteral("Layer"));
+ bool needSave = false;
+ QRegExp rgx(group + ":\\w*,*|," + group + ":\\w*");
+ for (int i = 0; i < layerElems.count(); ++i) {
+ QDomElement lElem = layerElems.at(i).toElement();
+ if (lElem.hasAttribute(QStringLiteral("variants"))) {
+ QString val = lElem.attribute(QStringLiteral("variants"));
+ if (rgx.indexIn(val) != -1) {
+ val.replace(rgx, "");
+ lElem.setAttribute(QStringLiteral("variants"), val);
+ needSave = true;
+ }
+ }
+ }
+
+ if (needSave)
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+}
+
+bool ProjectFile::isVariantGroupUnique(const QString &group) const
+{
+ return !m_variantsDef.contains(group);
+}
+
+bool ProjectFile::isVariantTagUnique(const QString &group, const QString &tag) const
+{
+ if (!m_variantsDef.contains(group))
+ return true;
+
+ return !m_variantsDef[group].m_tags.contains(tag);
+}
+
+void ProjectFile::deleteVariantTag(const QString &group, const QString &tag)
+{
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ QDomDocument domDoc;
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
+
+ // check if tag is in use in other presentations in the porject
+ int inUseIdx = -1; // list of presentations that has the tag in use
+ QDomNodeList presElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("assets"))
+ .elementsByTagName(QStringLiteral("presentation"));
+ for (int i = 0; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ if (pPath != doc->GetDocumentPath()
+ && tagExistsInUip(pPath, group, tag)) {
+ inUseIdx = i;
+ break;
+ }
+ }
+
+ if (inUseIdx != -1) {
+ QMessageBox box;
+ box.setWindowTitle(tr("Tag in use"));
+ box.setText(tr("The tag '%1' is in use in another presentation, are you sure you want to"
+ " delete it?").arg(tag));
+ box.setIcon(QMessageBox::Warning);
+ box.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+ box.setButtonText(QMessageBox::Yes, QStringLiteral("Delete"));
+ switch (box.exec()) {
+ case QMessageBox::Yes:
+ // delete the tag from all uips that use it
+ for (int i = inUseIdx; i < presElems.count(); ++i) {
+ QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ + presElems.at(i).toElement().attribute(QStringLiteral("src"));
+ if (pPath != doc->GetDocumentPath())
+ deleteTagFromUip(pPath, group, tag);
+ }
+ break;
+
+ default:
+ // abort deletion
+ return;
+ }
+ }
+
+ // delete the tag from current doc, if exists
+ deleteTagFromUip(doc->GetDocumentPath(), group, tag);
+
+ QDomNodeList groupsElems = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("variants"))
+ .elementsByTagName(QStringLiteral("variantgroup"));
+
+ // delete the tag from the property (if set)
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+ const auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ const auto layers = doc->getLayers();
+ auto property = bridge->GetLayer().m_variants;
+ for (auto layer : layers) {
+ qt3dsdm::SValue sValue;
+ if (propertySystem->GetInstancePropertyValue(layer, property, sValue)) {
+ QString propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
+ ->GetData());
+ if (propVal.contains(QStringLiteral("%1:%2").arg(group).arg(tag))) {
+ // property has the deleted tag, need to update it, else the deleted tag will be
+ // saved in the uip if the user saves the presentation.
+ QRegExp rgx(QStringLiteral("%1:%2,*|,%1:%2").arg(group).arg(tag));
+ propVal.replace(rgx, {});
+ qt3dsdm::SValue sVal = std::make_shared<qt3dsdm::CDataStr>(
+ Q3DStudio::CString::fromQString(propVal));
+ propertySystem->SetInstancePropertyValue(layer, property, sVal);
+ }
+ }
+ }
+
+ // update and save the uia
+ bool deleted = false;
+ for (int i = 0; i < groupsElems.count(); ++i) {
+ QDomElement gElem = groupsElems.at(i).toElement();
+ if (gElem.attribute(QStringLiteral("id")) == group) {
+ QDomNodeList tagsElems = gElem.childNodes();
+ for (int j = 0; j < tagsElems.count(); ++j) {
+ QDomElement tElem = tagsElems.at(j).toElement();
+ if (tElem.attribute(QStringLiteral("id")) == tag) {
+ gElem.removeChild(tElem);
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ deleted = true;
+ break;
+ }
+ }
+ if (deleted)
+ break;
+ }
+ }
+
+ // update m_variantsDef
+ m_variantsDef[group].m_tags.removeOne(tag);
+}
diff --git a/src/Authoring/Studio/Application/ProjectFile.h b/src/Authoring/Studio/Application/ProjectFile.h
index 3e47da28..78ecc6d6 100644
--- a/src/Authoring/Studio/Application/ProjectFile.h
+++ b/src/Authoring/Studio/Application/ProjectFile.h
@@ -46,6 +46,11 @@ class ProjectFile : public QObject
public:
ProjectFile();
+ struct VariantGroup {
+ QString m_color;
+ QStringList m_tags;
+ };
+
void create(const QString &uiaPath);
void ensureProjectFile();
void initProjectFile(const QString &presPath);
@@ -81,6 +86,18 @@ public:
void deletePresentationFile(const QString &filePath);
void renameMaterial(const QString &oldName, const QString &newName);
bool duplicatePresentation(const QString &oldPres, const QString &newPres);
+ void loadVariants(const QString &filePath = {});
+ void addVariantTag(const QString &group, const QString &newTag);
+ void renameVariantTag(const QString &group, const QString &oldTag, const QString &newTag);
+ void deleteVariantTag(const QString &group, const QString &tag);
+ void addVariantGroup(const QString &newGroup);
+ void renameVariantGroup(const QString &oldGroup, const QString &newGroup);
+ void deleteVariantGroup(const QString &group);
+ void changeVariantGroupColor(const QString &group, const QString &newColor);
+ bool isVariantGroupUnique(const QString &group) const;
+ bool isVariantTagUnique(const QString &group, const QString &tag) const;
+
+ QHash<QString, VariantGroup> variantsDef() const { return m_variantsDef; }
Q_SIGNALS:
void presentationIdChanged(const QString &path, const QString &id);
@@ -88,9 +105,17 @@ Q_SIGNALS:
private:
QString ensureUniquePresentationId(const QString &id) const;
+ bool tagExistsInUip(const QString &src, const QString &group, const QString &tag) const;
+ bool groupExistsInUip(const QString &src, const QString &group) const;
+ void deleteTagFromUip(const QString &src, const QString &group, const QString &tag);
+ void deleteGroupFromUip(const QString &src, const QString &group);
+ void renameTagInUip(const QString &src, const QString &group, const QString &tag,
+ const QString &newName);
+ void renameGroupInUip(const QString &src, const QString &group, const QString &newName);
QFileInfo m_fileInfo; // uia file info
QString m_initialPresentation;
+ QHash<QString, VariantGroup> m_variantsDef; // definition of variants
};
#endif // PROJECTFILE_H
diff --git a/src/Authoring/Studio/Application/StudioApp.cpp b/src/Authoring/Studio/Application/StudioApp.cpp
index d6e589a4..c0fa435e 100644
--- a/src/Authoring/Studio/Application/StudioApp.cpp
+++ b/src/Authoring/Studio/Application/StudioApp.cpp
@@ -84,11 +84,15 @@ int main(int argc, char *argv[])
bool isOpenGLES = false;
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if !defined(Q_OS_MACOS)
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
#endif
SharedTools::QtSingleApplication guiApp(QStringLiteral("Qt3DStudio"), argc, argv);
+ // Fix for uia and uip file attribute random ordering (see QTBUG-8158)
+ qSetGlobalQHashSeed(1720419);
+
#if defined(Q_OS_MACOS)
QSurfaceFormat openGL33Format;
openGL33Format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -1726,6 +1730,8 @@ bool CStudioApp::OnLoadDocument(const QString &inDocument, bool inShowStartupDia
m_core->getProjectFile().updateDocPresentationId();
m_core->getProjectFile().loadSubpresentationsAndDatainputs(m_subpresentations,
m_dataInputDialogItems);
+ m_core->getProjectFile().loadVariants();
+ GetViews()->getMainFrame()->getSlideView()->refreshVariants();
getRenderer().RegisterSubpresentations(m_subpresentations);
m_authorZoom = false;
@@ -1786,6 +1792,13 @@ void CStudioApp::saveDataInputsToProjectFile()
diNode.setAttribute(QStringLiteral("evaluator"), item->valueString);
}
#endif
+ // Let's allow storing key even if actual metadata is empty, as we
+ // do not know how the user code is going to interpret metadata contents.
+ if (!item->metaDataKey.isEmpty()) {
+ diNode.setAttribute(QStringLiteral("metadatakey"), item->metaDataKey);
+ if (!item->metaData.isEmpty())
+ diNode.setAttribute(QStringLiteral("metadata"), item->metaData);
+ }
assetsNode.appendChild(diNode);
}
StudioUtils::commitDomDocumentSave(file, doc);
diff --git a/src/Authoring/Studio/Application/TimeEditDlg.cpp b/src/Authoring/Studio/Application/TimeEditDlg.cpp
index 499d6d57..eb9d0324 100644
--- a/src/Authoring/Studio/Application/TimeEditDlg.cpp
+++ b/src/Authoring/Studio/Application/TimeEditDlg.cpp
@@ -29,24 +29,17 @@
#include "ui_TimeEditDlg.h"
#include "TimeEditDlg.h"
+#include "KeyframeManager.h"
#include "IDoc.h"
-#include "Bindings/ITimelineKeyframesManager.h"
-
+#include "TimeEnums.h"
#include <QtGui/qvalidator.h>
-CTimeEditDlg::CTimeEditDlg(QWidget *pParent)
- : QDialog(pParent)
- , m_ui(new Ui::TimeEditDlg)
- , m_Doc(nullptr)
- , m_KeyframesManager(nullptr)
- , m_InitialTime(0)
- , m_ObjectAssociation(0)
- , m_OffsetFromInitialTime(0)
- , m_min(-1)
- , m_sec(-1)
+CTimeEditDlg::CTimeEditDlg(KeyframeManager *keyframeManager)
+ : m_ui(new Ui::TimeEditDlg)
+ , m_keyframeManager(keyframeManager)
{
m_ui->setupUi(this);
- setAutoFillBackground(true);
+ setWindowFlag(Qt::WindowContextHelpButtonHint, false); // remove '?' from the dialog title bar
QIntValidator *minValidator = new QIntValidator(this);
minValidator->setRange(0, 9999);
@@ -61,8 +54,6 @@ CTimeEditDlg::CTimeEditDlg(QWidget *pParent)
connect(m_ui->lineEditMinutes, &QLineEdit::textEdited, this, &CTimeEditDlg::onTimeChanged);
connect(m_ui->lineEditSeconds, &QLineEdit::textEdited, this, &CTimeEditDlg::onTimeChanged);
connect(m_ui->lineEditMilliseconds, &QLineEdit::textEdited, this, &CTimeEditDlg::onTimeChanged);
-
- window()->setFixedSize(size());
}
CTimeEditDlg::~CTimeEditDlg()
@@ -70,57 +61,48 @@ CTimeEditDlg::~CTimeEditDlg()
delete m_ui;
}
-void CTimeEditDlg::setKeyframesManager(ITimelineKeyframesManager *inKeyframesManager)
-{
- m_KeyframesManager = inKeyframesManager;
-}
-
-//=============================================================================
/**
- * showDialog: Initializes and shows the Time Edit Dialog Box.
- * @param inTime is the initial time, which will be shown when the time edit
- * dialog box pops up
+ * Initializes and shows the dialog
+ * @param inTime the initial time which will be shown when the dialog pops up
* @param inDoc this can be nullptr where its not applicable
- * @param inObjectAssociation is the identifier for that identifies the object
- * associated with the time edit dialog
- * (e.g. playhead, keyframe)
+ * @param inObjectAssociation the identifier for the object associated with the dialog (playhead
+ * or keyframe)
*/
void CTimeEditDlg::showDialog(long inTime, IDoc *inDoc, long inObjectAssociation)
{
- m_InitialTime = inTime;
- m_ObjectAssociation = inObjectAssociation;
+ m_initialTime = inTime;
+ m_objectAssociation = inObjectAssociation;
m_Doc = inDoc;
// Set initial values to dialog
- formatTime(m_InitialTime);
+ formatTime(m_initialTime);
exec();
}
void CTimeEditDlg::formatTime(long inTime)
{
- long theTime = inTime;
- long min = 0;
- long sec = 0;
- long msec = 0;
+ long mins = 0;
+ long secs = 0;
+ long mils = 0;
- // Translates the m_initialTime (in milliseconds) into Minutes, Seconds and Milliseconds
if (inTime != 0) {
- min = timeConversion(theTime, CONVERT_MSEC_TO_MIN);
- theTime = theTime - timeConversion(min, CONVERT_MIN_TO_MSEC);
- sec = timeConversion(theTime, CONVERT_MSEC_TO_SEC);
- theTime = theTime - timeConversion(sec, CONVERT_SEC_TO_MSEC);
- msec = theTime;
+ mins = inTime % 3600000 / 60000;
+ secs = inTime % 60000 / 1000;
+ mils = inTime % 1000;
}
- m_ui->lineEditMinutes->setText(QString::number(min));
- m_ui->lineEditSeconds->setText(QString::number(sec));
- m_ui->lineEditMilliseconds->setText(QString::number(msec));
+
+ // display milliseconds in 3 digits (5 -> 005)
+ QString milsStr = QString("%1").arg(mils, 3, 10, QChar('0'));
+ m_ui->lineEditMinutes->setText(QString::number(mins));
+ m_ui->lineEditSeconds->setText(QString::number(secs));
+ m_ui->lineEditMilliseconds->setText(milsStr);
// Select the biggest non-zero unit
- if (min > 0) {
+ if (mins > 0) {
m_ui->lineEditMinutes->setFocus();
m_ui->lineEditMinutes->selectAll();
- } else if (sec > 0) {
+ } else if (secs > 0) {
m_ui->lineEditSeconds->setFocus();
m_ui->lineEditSeconds->selectAll();
} else {
@@ -129,22 +111,23 @@ void CTimeEditDlg::formatTime(long inTime)
}
}
-void CTimeEditDlg::showEvent(QShowEvent *ev)
+void CTimeEditDlg::showEvent(QShowEvent *e)
{
onInitDialog();
- QDialog::showEvent(ev);
+ QDialog::showEvent(e);
}
void CTimeEditDlg::onInitDialog()
{
QString title;
// Display the window captions for the correct object type
- switch (m_ObjectAssociation) {
+ switch (m_objectAssociation) {
case PLAYHEAD:
title = QObject::tr("Go To Time");
break;
case ASSETKEYFRAME:
title = QObject::tr("Set Keyframe Time");
+ Q_ASSERT(m_keyframeManager != nullptr);
break;
}
setWindowTitle(title);
@@ -154,11 +137,11 @@ void CTimeEditDlg::onInitDialog()
void CTimeEditDlg::accept()
{
// Only commit here, cos dup keyframes will be deleted.
- if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager) {
- if (m_OffsetFromInitialTime == 0)
- m_KeyframesManager->RollbackChangedKeyframes();
+ if (m_objectAssociation == ASSETKEYFRAME && m_Doc) {
+ if (m_endTime == m_initialTime)
+ m_keyframeManager->RollbackChangedKeyframes();
else
- m_KeyframesManager->CommitChangedKeyframes();
+ m_keyframeManager->CommitChangedKeyframes();
}
QDialog::accept();
@@ -167,119 +150,26 @@ void CTimeEditDlg::accept()
void CTimeEditDlg::reject()
{
// Only commit here, cos dup keyframes will be deleted.
- if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager)
- m_KeyframesManager->RollbackChangedKeyframes();
+ if (m_objectAssociation == ASSETKEYFRAME && m_Doc)
+ m_keyframeManager->RollbackChangedKeyframes();
QDialog::reject();
}
-int CTimeEditDlg::numberOfDigits(long number)
-{
- long theNumberOfDigits = 0;
- for (long theNumber = number; theNumber >= 1; theNumber = theNumber / 10)
- theNumberOfDigits++;
- return theNumberOfDigits;
-}
-
-//==============================================================================
/**
- * timeConversion: Converts inTime to the format specified by inFlags.
- * For example:
- * inTime = 5 sec inFlags = CONVERT_SEC_TO_MSEC
- * The method will convert 5 sec into 5000 msec and
- * returns the result.
- * @param inTime stores the time to be converted.
- * inOperationCode determines the type of time conversion to be done on the
- * inTime.
- * @return theResult stores the result of the time conversion.
- */
-long CTimeEditDlg::timeConversion(long inTime, long inOperationCode)
-{
- long theResult = 0;
- switch (inOperationCode) {
- case CONVERT_MIN_TO_MSEC:
- theResult = inTime * 60 * 1000;
- break;
- case CONVERT_SEC_TO_MSEC:
- theResult = inTime * 1000;
- break;
- case CONVERT_MSEC_TO_MIN:
- theResult = inTime / (60 * 1000);
- break;
- case CONVERT_MSEC_TO_SEC:
- theResult = inTime / 1000;
- break;
- }
- return theResult;
-}
-
-//==============================================================================
-/**
- * timeConversion: Takes in the time in mins:secs:msec and convert it to
- * the corresponding time in msec.
- * @param inMin stores the minutes to be converted.
- * inSec stores the seconds to be converted.
- * inMsec stores the milliseconds to be converted.
- * inOperationCode determines the type of time conversion to be done on the
- * inMin, inSec and inMsec.
- * @return theResult stores the result of the time conversion.
- */
-long CTimeEditDlg::timeConversion(long inMin, long inSec, long inMsec, long inOperationCode)
-{
- long theResult = 0;
- switch (inOperationCode) {
- case CONVERT_TIME_TO_MSEC:
- theResult = timeConversion(inMin, CONVERT_MIN_TO_MSEC)
- + timeConversion(inSec, CONVERT_SEC_TO_MSEC) + inMsec;
- break;
- }
- return theResult;
-}
-
-//==============================================================================
-/**
- * timeConversion: Takes in the time in milliseconds and converts them
- * to min : sec : msec.
- * @param inTotalTime stores the total time in msec.
- * ioMin stores the mins result of the time conversion
- * ioSec stores the secs result of the time conversion
- * ioMsec stores the msecs result of the time conversion
- * inOperationCode determines the type of time conversion to be done on the
- * inTotalTime.
- */
-void CTimeEditDlg::timeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
- long inOperationCode)
-{
- switch (inOperationCode) {
- case CONVERT_MSEC_TO_MIN_SEC_MSEC:
- *ioMin = timeConversion(inTotalTime, CONVERT_MSEC_TO_MIN);
- *ioSec = inTotalTime - timeConversion(*ioMin, CONVERT_MIN_TO_MSEC);
- *ioSec = timeConversion(*ioSec, CONVERT_MSEC_TO_SEC);
- *ioMsec = inTotalTime - timeConversion(*ioMin, CONVERT_MIN_TO_MSEC)
- - timeConversion(*ioSec, CONVERT_SEC_TO_MSEC);
- break;
- }
-}
-
-//==============================================================================
-/**
- * updateObjectTime: It updates the playhead or keyframe time according
- * to the time displayed in the time edit dialogue.
- * @param inTime is the time that will be updated.
+ * Updates the playhead or keyframe time according to the time displayed in the time edit dialogue.
+ * @param inTime the time that will be updated.
*/
void CTimeEditDlg::updateObjectTime(long inTime)
{
- long theDiff = 0;
- switch (m_ObjectAssociation) {
+ switch (m_objectAssociation) {
case PLAYHEAD: // Update the playhead time
if (m_Doc)
m_Doc->NotifyTimeChanged(inTime);
break;
case ASSETKEYFRAME: // Update the keyframe time
if (m_Doc) {
- theDiff = inTime - m_OffsetFromInitialTime - m_InitialTime;
- m_OffsetFromInitialTime = m_OffsetFromInitialTime + theDiff;
- if (theDiff != 0 && m_KeyframesManager)
- m_KeyframesManager->OffsetSelectedKeyframes(theDiff);
+ m_endTime = inTime;
+ m_keyframeManager->moveSelectedKeyframes(inTime);
}
break;
}
@@ -291,21 +181,23 @@ void CTimeEditDlg::onTimeChanged()
long sec = m_ui->lineEditSeconds->text().toInt();
long msec = m_ui->lineEditMilliseconds->text().toInt();
- long theGoToTime = timeConversion(min, CONVERT_MIN_TO_MSEC)
- + timeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ long theGoToTime = min * 60000 + sec * 1000 + msec;
+ // make sure min keyframe time doesn't go below zero
+ long offset = m_keyframeManager->getPressedKeyframeOffset();
+ if (theGoToTime - offset < 0) {
+ theGoToTime = offset;
+ formatTime(theGoToTime);
+ }
// Go to the time specified in the time edit display
updateObjectTime(theGoToTime);
// If max number of digits reached in a number field, select the next
- if (m_min != min && numberOfDigits(min) == 4) {
+ if (m_ui->lineEditMinutes->hasFocus() && min > 999) {
m_ui->lineEditSeconds->setFocus();
m_ui->lineEditSeconds->selectAll();
- } else if (m_sec != sec && numberOfDigits(sec) == 2) {
+ } else if (m_ui->lineEditSeconds->hasFocus() && sec > 9) {
m_ui->lineEditMilliseconds->setFocus();
m_ui->lineEditMilliseconds->selectAll();
}
-
- m_min = min;
- m_sec = sec;
}
diff --git a/src/Authoring/Studio/Application/TimeEditDlg.h b/src/Authoring/Studio/Application/TimeEditDlg.h
index 8d8ed08f..ef4f8d1a 100644
--- a/src/Authoring/Studio/Application/TimeEditDlg.h
+++ b/src/Authoring/Studio/Application/TimeEditDlg.h
@@ -30,12 +30,11 @@
#ifndef TIME_EDIT_DIALOG_H
#define TIME_EDIT_DIALOG_H
-#include "TimeEnums.h"
#include <QtWidgets/qdialog.h>
class CTimebarControl;
class IDoc;
-class ITimelineKeyframesManager;
+class KeyframeManager;
#ifdef QT_NAMESPACE
using namespace QT_NAMESPACE;
@@ -52,9 +51,8 @@ class CTimeEditDlg : public QDialog
Q_OBJECT
public:
- CTimeEditDlg(QWidget *pParent = nullptr); // standard constructor
- virtual ~CTimeEditDlg();
- void setKeyframesManager(ITimelineKeyframesManager *inKeyframeManager);
+ CTimeEditDlg(KeyframeManager *keyframeManager);
+ virtual ~CTimeEditDlg() override;
void showDialog(long inTime, IDoc *inDoc, long inObjectAssociation);
public Q_SLOTS:
@@ -64,25 +62,18 @@ public Q_SLOTS:
protected:
void showEvent(QShowEvent *) override;
+private:
void onInitDialog();
void onTimeChanged();
void formatTime(long inTime);
- int numberOfDigits(long number);
- long timeConversion(long inTime, long inOperationCode);
- long timeConversion(long inMin, long inSec, long inMsec, long inOperationCode);
- void timeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
- long inOperationCode);
void updateObjectTime(long inTime);
-protected:
- Ui::TimeEditDlg *m_ui;
- IDoc *m_Doc;
- ITimelineKeyframesManager *m_KeyframesManager;
- long m_InitialTime;
- long m_ObjectAssociation;
- long m_OffsetFromInitialTime;
- int m_min;
- int m_sec;
+ Ui::TimeEditDlg *m_ui = nullptr;
+ IDoc *m_Doc = nullptr;
+ KeyframeManager *m_keyframeManager = nullptr;
+ long m_initialTime = 0;
+ long m_endTime = 0;
+ long m_objectAssociation = 0;
};
#endif // TIME_EDIT_DIALOG_H
diff --git a/src/Authoring/Studio/Application/TimeEditDlg.ui b/src/Authoring/Studio/Application/TimeEditDlg.ui
index 6bcb11b3..54a8dbd7 100644
--- a/src/Authoring/Studio/Application/TimeEditDlg.ui
+++ b/src/Authoring/Studio/Application/TimeEditDlg.ui
@@ -6,14 +6,29 @@
<rect>
<x>0</x>
<y>0</y>
- <width>300</width>
- <height>114</height>
+ <width>343</width>
+ <height>119</height>
</rect>
</property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>535</width>
+ <height>119</height>
+ </size>
+ </property>
<property name="windowTitle">
<string>Set Keyframe Time</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetFixedSize</enum>
+ </property>
<property name="leftMargin">
<number>0</number>
</property>
@@ -70,7 +85,20 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditMinutes"/>
+ <widget class="QLineEdit" name="lineEditMinutes">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_2">
@@ -80,7 +108,20 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditSeconds"/>
+ <widget class="QLineEdit" name="lineEditSeconds">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="label_3">
@@ -90,7 +131,20 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditMilliseconds"/>
+ <widget class="QLineEdit" name="lineEditMilliseconds">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
</item>
</layout>
</widget>
@@ -152,7 +206,7 @@
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
- <width>40</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -174,7 +228,7 @@
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
- <width>40</width>
+ <width>0</width>
<height>0</height>
</size>
</property>