Merge tahoma2d master with conflicts resolved

This commit is contained in:
manongjohn 2021-03-01 00:11:49 -05:00
commit ea0358aeea
32 changed files with 583 additions and 254 deletions

View file

@ -10,11 +10,11 @@ I will first review the request, then I'll accept it, add comments for rework, o
### Workflow
0. `fork` Tahoma2D to your GitHub account from `turtletooth/tahoma2d`.
- (use the `fork` button at the https://github.com/turtletooth/tahoma2d)
0. `fork` Tahoma2D to your GitHub account from `tahoma2d/tahoma2d`.
- (use the `fork` button at the https://github.com/tahoma2d/tahoma2d)
0. `clone` the repository.
- `git clone git@github.com:your-github-account/tahoma2d.git`
- `git remote add upstream https://github.com/turtletooth/tahoma2d.git`, additionally.
- `git remote add upstream https://github.com/tahoma2d/tahoma2d.git`, additionally.
0. modify the codes.
- `git checkout -b your-branch-name`
- `your-branch-name` is a name of your modifications, for example,
@ -32,7 +32,7 @@ I will first review the request, then I'll accept it, add comments for rework, o
## Bugs
If you find bugs, please report details about them using [issues](https://github.com/turtletooth/tahoma2d/issues).
If you find bugs, please report details about them using [issues](https://github.com/tahoma2d/tahoma2d/issues).
Please include information needed to reproduce the bug, including the operating system
and information directly relating to the issue. Links to screen captures of what is
observed on screen or video of specific steps to produce the problem are very helpful.

View file

@ -1,7 +1,6 @@
# Tahoma2D
[![](https://ci.appveyor.com/api/projects/status/mnc3mepksux9kvap/branch/master?svg=true)](https://ci.appveyor.com/project/turtletooth/tahoma2d)
[![](https://travis-ci.com/turtletooth/tahoma2d.svg?branch=master)](https://travis-ci.com/turtletooth/tahoma2d)
[![](https://ci.appveyor.com/api/projects/status/mnc3mepksux9kvap/branch/master?svg=true)](https://ci.appveyor.com/project/tahoma2d/tahoma2d)
## What is Tahoma2D?
@ -16,7 +15,7 @@ Please refer to the Tahoma2D site at <https://tahoma2d.org/download>.
## Installation
Please download the latest release at <https://github.com/turtletooth/tahoma2d/releases>.
Please download the latest release at <https://github.com/tahoma2d/tahoma2d/releases>.
## How to Build Locally
@ -31,7 +30,7 @@ Can't develop but still want to help? Help us test individual Pull Requests befo
## Community
- To share tips or to troubleshoot, join the [Google Tahoma2D Users forum](hhttps://groups.google.com/g/tahoma2d)
- If you found a bug with the software after troubleshooting, or are a developer, search the [Github issues](https://github.com/turtletooth/tahoma2d/issues) and post there.
- If you found a bug with the software after troubleshooting, or are a developer, search the [Github issues](https://github.com/tahoma2d/tahoma2d/issues) and post there.
## Licensing

View file

@ -101,7 +101,7 @@ $ cd ..
### Cloning the GIT Tree
```
$ git clone https://github.com/turtletooth/tahoma2d
$ git clone https://github.com/tahoma2d/tahoma2d
```
### Copying the 'stuff' Directory

View file

@ -62,7 +62,7 @@ $ rm /usr/local/lib/cmake/glew
These steps will put the Tahoma2D repository under /Users/yourlogin/Documents.
```
$ cd ~/Documents #or where you want to store the repository#
$ git clone https://github.com/turtletooth/tahoma2d
$ git clone https://github.com/tahoma2d/tahoma2d
$ cd tahoma2d
$ git lfs pull
$ cd thirdparty/boost

View file

@ -4,7 +4,7 @@ Tahoma2D does not directly use FFmpeg libraries or code.
As of July 2020, Tahoma2D is shipping with FFmpeg 4.3 LGPL version from https://ffmpeg.zeranoe.com/builds/
FFmpeg source code can be found at:
https://github.com/turtletooth/FFmpeg
https://github.com/tahoma2d/FFmpeg
or
https://github.com/FFmpeg/FFmpeg

View file

@ -1,36 +0,0 @@
License Agreement For Tahoma2D
[https://github.com/turtletooth/tahoma2d]
- - - - - - - - - - - - - - - -
Tahoma2D
All contributions by Jeremy Bullock:
Copyright (c) 2016 - 2020, Jeremy Bullock
All rights reserved.
All contributions by DWANGO:
Copyright (c) 2016 - 2020, DWANGO Co., Ltd.
All rights reserved.
All other contributions:
Copyright (c) 2016 - 2020, the respective contributors.
All rights reserved.
Each contributor holds copyright over their respective contributions.
The project versioning (Git) records all such contribution source information.
LICENSE
BSD 3-Clause "New" or "Revised" License
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>Tahoma2D.icns</string>
<key>CFBundleIdentifier</key>
<string>io.github.turtletooth.Tahoma2D</string>
<string>io.github.tahoma2d.Tahoma2D</string>
<key>NSCameraUsageDescription</key>
<string>Tahoma2D needs access to the camera in order to use Camera Capture</string>
<key>NSMicrophoneUsageDescription</key>

View file

@ -57,7 +57,7 @@ void TDoubleKeyframe::saveData(TOStream &os) const {
// Dirty resolution. Because the degree sign is converted to unexpected
// string...
if (QString::fromStdWString(L"\u00b0").toStdString() == unitName)
unitName = "\\u00b0";
unitName = "degrees";
switch (m_type) {
case Constant:
case Exponential:
@ -157,6 +157,9 @@ void TDoubleKeyframe::loadData(TIStream &is) {
break;
}
if (!is.matchEndTag()) throw TException(tagName + " : missing endtag");
if (m_unitName == "default") m_unitName = "";
m_isKeyframe = true;
if (m_unitName == "default")
m_unitName = "";
else if (m_unitName == "degrees")
m_unitName = "\u00b0";
m_isKeyframe = true;
}

View file

@ -342,6 +342,9 @@ public:
bool useCtrlAltToResizeBrushEnabled() const {
return getBoolValue(useCtrlAltToResizeBrush);
}
int getTempToolSwitchtimer() const {
return getIntValue(temptoolswitchtimer);
}
// Xsheet tab
QString getXsheetLayoutPreference() const {

View file

@ -107,6 +107,7 @@ enum PreferencesItemId {
cursorOutlineEnabled,
levelBasedToolsDisplay,
useCtrlAltToResizeBrush,
temptoolswitchtimer,
//----------
// Xsheet

View file

@ -20,6 +20,7 @@ class TPaletteHandle;
class TFxHandle;
class PaletteController;
class TColorStyle;
class StatusBar;
//====================================================
@ -51,6 +52,7 @@ public:
virtual int getCurrentLevelStyleIndex() const = 0;
virtual void setCurrentLevelStyleIndex(int index,
bool forceUpdate = false) = 0;
virtual void refreshStatusBar() = 0;
};
#endif // TAPPLICATION_H

View file

@ -1172,6 +1172,7 @@ public:
if (typeCode != m_typeCode) {
m_typeCode = typeCode;
changeType(typeCode);
TTool::getApplication()->refreshStatusBar();
}
} else if (propertyName == m_param.m_edgeCount.getName())
GeometricEdgeCount = m_param.m_edgeCount.getValue();

View file

@ -301,7 +301,8 @@ TImage *TTool::touchImage() {
bool animationSheetEnabled = pref->isAnimationSheetEnabled();
bool isAutoStretchEnabled = pref->isAutoStretchEnabled();
bool isAutoRenumberEnabled = pref->isAutorenumberEnabled();
bool isCreateInHoldCellsEnabled = pref->isCreationInHoldCellsEnabled();
bool isCreateInHoldCellsEnabled =
isAutoCreateEnabled && pref->isCreationInHoldCellsEnabled();
TFrameHandle *currentFrame = m_application->getCurrentFrame();
TXshLevelHandle *currentLevel = m_application->getCurrentLevel();

View file

@ -7,6 +7,7 @@
#include "timage.h"
//#include "tapp.h"
#include "toonzqt/menubarcommand.h"
#include "toonz/preferences.h"
#include <QAction>
#include <QMap>
#include <QDebug>
@ -70,9 +71,10 @@ void ToolHandle::storeTool() {
//-----------------------------------------------------------------------------
void ToolHandle::restoreTool() {
// qDebug() << m_storedToolTime.elapsed();
//qDebug() << m_storedToolTime.elapsed();
if (m_storedToolName != m_toolName && m_storedToolName != "" &&
m_storedToolTime.elapsed() > 500) {
m_storedToolTime.elapsed() >
Preferences::instance()->getTempToolSwitchtimer()) {
setTool(m_storedToolName);
}
}

View file

@ -446,20 +446,20 @@ endif()
if(BUILD_ENV_MSVC)
if(WITH_CANON)
set(EXTRA_LIBS ${EXTRA_LIBS} ${CANON_LIB})
endif()
set(EXTRA_LIBS ${EXTRA_LIBS} ${CANON_LIB})
endif()
if(WITH_CRASHRPT)
set(EXTRA_LIBS ${EXTRA_LIBS} ${CRASHRPT_LIB})
endif()
if(WITH_CRASHRPT)
set(EXTRA_LIBS ${EXTRA_LIBS} ${CRASHRPT_LIB})
endif()
target_link_libraries(Tahoma2D
Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml
Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia Qt5::SerialPort
${GL_LIB} ${GLUT_LIB} ${TURBOJPEG_LIB} ${OpenCV_LIBS} ${EXTRA_LIBS} strmiids
tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm
)
elseif(BUILD_ENV_APPLE)
target_link_libraries(Tahoma2D
Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml
Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia Qt5::SerialPort
${GL_LIB} ${GLUT_LIB} ${TURBOJPEG_LIB} ${OpenCV_LIBS} ${EXTRA_LIBS} strmiids
tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm
)
elseif(BUILD_ENV_APPLE AND WITH_CANON)
find_library(COCOA_LIB Cocoa)
_find_toonz_library(EXTRA_LIBS "tnzcore;tnzbase;toonzlib;colorfx;tnzext;image;sound;toonzqt;tnztools")
@ -467,9 +467,22 @@ elseif(BUILD_ENV_APPLE)
#
set(EXTRA_LIBS ${EXTRA_LIBS} "$<TARGET_FILE:tnzstdfx>" "$<TARGET_FILE:tfarm>")
if(WITH_CANON)
set(EXTRA_LIBS ${EXTRA_LIBS} ${CANON_LIB})
endif()
add_dependencies(Tahoma2D tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm)
target_link_libraries(Tahoma2D
Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml
Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia Qt5::MultimediaWidgets Qt5::SerialPort
${GL_LIB} ${GLUT_LIB} ${CANON_LIB} ${TURBOJPEG_LIB} ${OpenCV_LIBS}
${COCOA_LIB} ${EXTRA_LIBS} mousedragfilter
)
elseif(BUILD_ENV_APPLE)
find_library(COCOA_LIB Cocoa)
_find_toonz_library(EXTRA_LIBS "tnzcore;tnzbase;toonzlib;colorfx;tnzext;image;sound;toonzqt;tnztools")
#
set(EXTRA_LIBS ${EXTRA_LIBS} "$<TARGET_FILE:tnzstdfx>" "$<TARGET_FILE:tfarm>")
add_dependencies(Tahoma2D tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm)

View file

@ -1 +1 @@
Web: https://turtletooth.com/
Web: https://tahoma2d.org

View file

@ -131,6 +131,8 @@ void deleteCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
port->setFx(0);
}
}
xsh->getStageObjectTree()->removeStageObject(
TStageObjectId::ColumnId(c));
}
}
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
@ -156,6 +158,7 @@ void cutCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
TFxPort *port = fx->getOutputConnection(i);
port->setFx(0);
}
xsh->getStageObjectTree()->removeStageObject(TStageObjectId::ColumnId(c));
}
}
@ -242,6 +245,8 @@ class DeleteCellsUndo final : public TUndo {
QMimeData *m_data;
QMap<int, QList<TFxPort *>> m_outputConnections;
QMap<int, TXshColumn *> m_columns;
QMap<TStageObjectId, QList<TStageObjectId>> m_columnObjChildren;
QMap<TStageObjectId, TStageObjectId> m_columnObjParents;
public:
DeleteCellsUndo(TCellSelection *selection, QMimeData *data) : m_data(data) {
@ -263,6 +268,26 @@ public:
m_columns[i] = col;
col->addRef();
}
// Store TStageObject children in case column is emptied and we need to
// restore it
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
TStageObjectId id = TStageObjectId::ColumnId(i);
TStageObject *pegbar = xsh->getStageObject(id);
for (int k = 0; k < pegbarsCount; ++k) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(k);
if (other == pegbar) continue;
if (other->getParent() == id) {
// other->setParent(pegbar->getParent());
m_columnObjChildren[id].append(other->getId());
}
}
// Store TStageObject parent in case column is emptied and we need to
// restore it
m_columnObjParents[id] = pegbar->getParent();
TFx *fx = col->getFx();
if (!fx) continue;
int j;
@ -304,10 +329,35 @@ public:
for (i = 0; i < fxPorts.size(); i++) fxPorts[i]->setFx(col->getFx());
}
// Restore TStageObject parent
QMap<TStageObjectId, TStageObjectId>::const_iterator it2;
for (it2 = m_columnObjParents.begin(); it2 != m_columnObjParents.end();
it2++) { // Parents
TStageObject *obj = xsh->getStageObject(it2.key());
if (obj) {
obj->setParent(it2.value());
}
}
// Restore TStageObject children
QMap<TStageObjectId, QList<TStageObjectId>>::const_iterator it3;
for (it3 = m_columnObjChildren.begin(); it3 != m_columnObjChildren.end();
it3++) { // Children
QList<TStageObjectId> children = it3.value();
int i;
for (i = 0; i < children.size(); i++) {
TStageObject *child = xsh->getStageObject(children[i]);
if (child) {
child->setParent(it3.key());
}
}
}
const TCellData *cellData = dynamic_cast<const TCellData *>(m_data);
pasteCellsWithoutUndo(cellData, r0, c0, r1, c1, false, false);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
TApp::instance()->getCurrentObject()->notifyObjectIdSwitched();
}
void redo() const override {
@ -330,6 +380,8 @@ class CutCellsUndo final : public TUndo {
TCellSelection *m_selection;
TCellData *m_data;
QMap<int, QList<TFxPort *>> m_outputConnections;
QMap<TStageObjectId, QList<TStageObjectId>> m_columnObjChildren;
QMap<TStageObjectId, TStageObjectId> m_columnObjParents;
public:
CutCellsUndo(TCellSelection *selection) : m_data() {
@ -344,6 +396,26 @@ public:
for (i = c0; i <= c1; i++) {
TXshColumn *col = xsh->getColumn(i);
if (!col || col->isEmpty()) continue;
// Store TStageObject children in case column is emptied and we need to
// restore it
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
TStageObjectId id = TStageObjectId::ColumnId(i);
TStageObject *pegbar = xsh->getStageObject(id);
for (int k = 0; k < pegbarsCount; ++k) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(k);
if (other == pegbar) continue;
if (other->getParent() == id) {
// other->setParent(pegbar->getParent());
m_columnObjChildren[id].append(other->getId());
}
}
// Store TStageObject parent in case column is emptied and we need to
// restore it
m_columnObjParents[id] = pegbar->getParent();
TFx *fx = col->getFx();
if (!fx) continue;
int j;
@ -380,8 +452,33 @@ public:
for (i = 0; i < fxPorts.size(); i++) fxPorts[i]->setFx(col->getFx());
}
// Restore TStageObject parent
QMap<TStageObjectId, TStageObjectId>::const_iterator it2;
for (it2 = m_columnObjParents.begin(); it2 != m_columnObjParents.end();
it2++) { // Parents
TStageObject *obj = xsh->getStageObject(it2.key());
if (obj) {
obj->setParent(it2.value());
}
}
// Restore TStageObject children
QMap<TStageObjectId, QList<TStageObjectId>>::const_iterator it3;
for (it3 = m_columnObjChildren.begin(); it3 != m_columnObjChildren.end();
it3++) { // Children
QList<TStageObjectId> children = it3.value();
int i;
for (i = 0; i < children.size(); i++) {
TStageObject *child = xsh->getStageObject(children[i]);
if (child) {
child->setParent(it3.key());
}
}
}
pasteCellsWithoutUndo(m_data, r0, c0, r1, c1, true);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
TApp::instance()->getCurrentObject()->notifyObjectIdSwitched();
}
void redo() const override {
@ -2613,6 +2710,8 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
ToolHandle *toolHandle = TApp::instance()->getCurrentTool();
//----- Going to cheat a little. Use autocreate rules to help create what we
// need
// If autocreate disabled, let's turn it on temporarily
bool isAutoCreateEnabled = Preferences::instance()->isAutoCreateEnabled();
if (!isAutoCreateEnabled)
@ -2622,6 +2721,7 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
Preferences::instance()->isCreationInHoldCellsEnabled();
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, true, false);
//------------------
TImage *img = toolHandle->getTool()->touchImage();
@ -2629,11 +2729,13 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
TXshSimpleLevel *sl = cell.getSimpleLevel();
if (!img || !sl) {
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false,
false);
//------------------
if (!multiple)
DVGui::warning(QObject::tr(
"Unable to create a blank drawing on the current column"));
@ -2641,11 +2743,13 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
}
if (!toolHandle->getTool()->m_isFrameCreated) {
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false,
false);
//------------------
if (!multiple)
DVGui::warning(QObject::tr(
"Unable to replace the current drawing with a blank drawing"));
@ -2663,11 +2767,12 @@ void TCellSelection::createBlankDrawing(int row, int col, bool multiple) {
IconGenerator::instance()->invalidate(sl, frame);
// Reset back to what these were
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false, false);
//------------------
}
//-----------------------------------------------------------------------------
@ -2764,6 +2869,8 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
ToolHandle *toolHandle = TApp::instance()->getCurrentTool();
//----- Going to cheat a little. Use autocreate rules to help create what we
// need
// If autocreate disabled, let's turn it on temporarily
bool isAutoCreateEnabled = Preferences::instance()->isAutoCreateEnabled();
if (!isAutoCreateEnabled)
@ -2773,14 +2880,17 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
Preferences::instance()->isCreationInHoldCellsEnabled();
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, true, false);
//------------------
TImage *img = toolHandle->getTool()->touchImage();
if (!img) {
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false,
false);
//------------------
if (!multiple)
DVGui::warning(
QObject::tr("Unable to duplicate a drawing on the current column"));
@ -2789,11 +2899,13 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
bool frameCreated = toolHandle->getTool()->m_isFrameCreated;
if (!frameCreated) {
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false,
false);
//------------------
if (!multiple)
DVGui::warning(
QObject::tr("Unable to replace the current or next drawing with a "
@ -2815,10 +2927,12 @@ void TCellSelection::duplicateFrame(int row, int col, bool multiple) {
new DuplicateDrawingUndo(sl, srcFrame, targetFrame);
TUndoManager::manager()->add(undo);
//----- Restore previous states of autocreation
if (!isAutoCreateEnabled)
Preferences::instance()->setValue(EnableAutocreation, false, false);
if (!isCreationInHoldCellsEnabled)
Preferences::instance()->setValue(EnableCreationInHoldCells, false, false);
//------------------
}
//-----------------------------------------------------------------------------

View file

@ -488,9 +488,8 @@ void FilmstripFrames::hideEvent(QHideEvent *) {
// if the level strip is floating during shutting down Tahoma2D
// it can cause a crash disconnecting from the viewer which was already
// destroyed. Checking the fps is a janky way to ensure the viewer is
// stil relevant.
if (m_viewer && m_viewer->getFPS() > -100) {
// destroyed.
if (m_viewer && m_viewer->isValid()) {
disconnect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update()));
disconnect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update()));
m_viewer = nullptr;

View file

@ -328,28 +328,8 @@ int main(int argc, char *argv[]) {
argc = 1;
}
// Toonz environment
initToonzEnv(argumentPathValues);
#ifdef WITH_CRASHRPT
CR_INSTALL_INFO pInfo;
memset(&pInfo, 0, sizeof(CR_INSTALL_INFO));
pInfo.cb = sizeof(CR_INSTALL_INFO);
pInfo.pszAppName = convertToLPCWSTR(TEnv::getApplicationName());
pInfo.pszAppVersion = convertToLPCWSTR(TEnv::getApplicationVersion());
TFilePath crashrptCache =
ToonzFolder::getCacheRootFolder() + TFilePath("crashrpt");
pInfo.pszErrorReportSaveDir =
convertToLPCWSTR(crashrptCache.getQString().toStdString());
// Install all available exception handlers.
// Don't send reports automaticall, store locally
pInfo.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS | CR_INST_DONT_SEND_REPORT;
crInstall(&pInfo);
#endif
// Enables high-DPI scaling. This attribute must be set before QApplication is
// constructed. Available from Qt 5.6.
// Enables high-DPI scaling. This attribute must be set before QApplication is
// constructed. Available from Qt 5.6.
#if QT_VERSION >= 0x050600
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
@ -511,6 +491,26 @@ int main(int argc, char *argv[]) {
TBigMemoryManager::instance()->setRunOutOfContiguousMemoryHandler(
&toonzRunOutOfContMemHandler);
// Toonz environment
initToonzEnv(argumentPathValues);
#ifdef WITH_CRASHRPT
CR_INSTALL_INFO pInfo;
memset(&pInfo, 0, sizeof(CR_INSTALL_INFO));
pInfo.cb = sizeof(CR_INSTALL_INFO);
pInfo.pszAppName = convertToLPCWSTR(TEnv::getApplicationName());
pInfo.pszAppVersion = convertToLPCWSTR(TEnv::getApplicationVersion());
TFilePath crashrptCache =
ToonzFolder::getCacheRootFolder() + TFilePath("crashrpt");
pInfo.pszErrorReportSaveDir =
convertToLPCWSTR(crashrptCache.getQString().toStdString());
// Install all available exception handlers.
// Don't send reports automaticall, store locally
pInfo.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS | CR_INST_DONT_SEND_REPORT;
crInstall(&pInfo);
#endif
// Initialize thread components
TThread::init();

View file

@ -1195,7 +1195,7 @@ void MainWindow::onOpenReportABug() {
int ret = DVGui::MsgBox(DVGui::INFORMATION, str, buttons, 1);
if (ret == 1)
QDesktopServices::openUrl(
QUrl("https://github.com/turtletooth/tahoma2d/issues"));
QUrl("https://github.com/tahoma2d/tahoma2d/issues"));
}
//-----------------------------------------------------------------------------
@ -1481,7 +1481,7 @@ void MainWindow::onUpdateCheckerDone(bool error) {
if (ret == 1) {
// Write the new last date to file
QDesktopServices::openUrl(QObject::tr(
"https://github.com/turtletooth/tahoma2d/releases/latest"));
"https://github.com/tahoma2d/tahoma2d/releases/latest"));
}
}

View file

@ -1002,7 +1002,9 @@ void OutputSettingsPopup::updateField() {
if (!m_isPreviewSettings) {
TFilePath path = prop->getPath();
QString name = QString::fromStdWString(path.getWideName());
QString name = path.withoutParentDir().getQString();
name = QString::fromStdString(name.toStdString().substr(
0, name.length() - path.getDottedType().length()));
if (name.isEmpty())
name = QString::fromStdString(scene->getScenePath().getName());
m_saveInFileFld->setPath(toQString(path.getParentDir()));
@ -1204,7 +1206,7 @@ void OutputSettingsPopup::onNameChanged() {
if (fp.getWideName() == wname) return; // Already had the right name
fp = fp.withName(wname);
fp = fp.getParentDir() + TFilePath(wname).withType(fp.getType());
prop->setPath(fp);
TApp::instance()->getCurrentScene()->setDirtyFlag(true);

View file

@ -1082,6 +1082,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
{cursorOutlineEnabled, tr("Show Cursor Size Outlines")},
{levelBasedToolsDisplay, tr("Toolbar Display Behaviour:")},
{useCtrlAltToResizeBrush, tr("Use Ctrl+Alt to Resize Brush")},
{temptoolswitchtimer,
tr("Temporary Tool Switch Shortcut Hold Time (ms):")},
// Xsheet
{xsheetLayoutPreference, tr("Column Header Layout*:")},
@ -1656,13 +1658,16 @@ QWidget* PreferencesPopup::createDrawingPage() {
insertUI(newLevelSizeToCameraSizeEnabled, lay);
insertDualUIs(DefLevelWidth, DefLevelHeight, lay);
// insertUI(DefLevelDpi, lay);
QGridLayout* creationLay = insertGroupBox(
tr("Frame Creation Options"), lay);
{
insertUI(NumberingSystem, creationLay, getComboItemList(NumberingSystem));
insertUI(EnableAutoStretch, creationLay);
insertUI(EnableAutoRenumber, creationLay);
}
QGridLayout* autoCreationLay = insertGroupBoxUI(EnableAutocreation, lay);
{
insertUI(NumberingSystem, autoCreationLay,
getComboItemList(NumberingSystem));
insertUI(EnableAutoStretch, autoCreationLay);
insertUI(EnableCreationInHoldCells, autoCreationLay);
insertUI(EnableAutoRenumber, autoCreationLay);
}
insertUI(vectorSnappingTarget, lay, getComboItemList(vectorSnappingTarget));
insertUI(saveUnpaintedInCleanup, lay);
@ -1716,6 +1721,7 @@ QWidget* PreferencesPopup::createToolsPage() {
insertUI(levelBasedToolsDisplay, lay,
getComboItemList(levelBasedToolsDisplay));
// insertUI(useCtrlAltToResizeBrush, lay);
insertUI(temptoolswitchtimer, lay);
lay->setRowStretch(lay->rowCount(), 1);
widget->setLayout(lay);

View file

@ -15,12 +15,14 @@
#include "toonz/tobjecthandle.h"
#include "toonzqt/tselectionhandle.h"
#include "toonzqt/selection.h"
#include "toonz/tstageobjecttree.h"
#include "toonzqt/gutil.h"
#include "tools/tool.h"
#include "tools/toolhandle.h"
#include "tproperty.h"
#include <QLayout>
#include <QLabel>
@ -32,7 +34,7 @@ StatusBar::StatusBar(QWidget* parent) : QStatusBar(parent) {
m_infoLabel = new StatusLabel(tr("Info goes here."), this);
m_infoLabel->setObjectName("MainWindowPlainLabel");
m_infoLabel->setMinimumWidth(1);
addWidget(m_infoLabel, 0);
addWidget(m_infoLabel, 1);
addPermanentWidget(m_currentFrameLabel, 0);
TApp* app = TApp::instance();
@ -53,7 +55,8 @@ StatusBar::StatusBar(QWidget* parent) : QStatusBar(parent) {
assert(ret);
makeMap();
m_infoMap = makeMap(tr(" "), tr(" - "), tr(" - "));
m_hintMap = makeMap(tr("\n "), tr("\t- "), tr("\t\t- "));
updateInfoText();
}
@ -96,137 +99,273 @@ void StatusBar::updateInfoText() {
if (level) {
type = level->getType();
}
bool isRaster = false;
bool isVector = false;
bool isSmartRaster = false;
bool isEmpty = false;
std::string namePlus = "";
bool isRaster = false;
bool isVector = false;
bool isSmartRaster = false;
std::string nameLevel = "";
std::string nameMode = "";
if (type >= 0) {
if (type == TXshLevelType::PLI_XSHLEVEL) {
isVector = true;
namePlus = "Vector";
isVector = true;
nameLevel = "Vector";
} else if (type == TXshLevelType::TZP_XSHLEVEL) {
isSmartRaster = true;
namePlus = "SmartRaster";
nameLevel = "SmartRaster";
} else if (type == TXshLevelType::OVL_XSHLEVEL) {
isRaster = true;
namePlus = "Raster";
} else if (type == NO_XSHLEVEL)
isEmpty = true;
}
QString text = "";
if (m_infoMap.find(name + namePlus) != m_infoMap.end()) {
text += m_infoMap[name + namePlus];
int i = 0;
i++;
} else if (m_infoMap.find(name) != m_infoMap.end()) {
text += m_infoMap[name];
int i = 0;
i++;
isRaster = true;
nameLevel = "Raster";
}
}
if (name == "T_Geometric") {
TPropertyGroup* props = tool->getProperties(0);
nameMode = props->getProperty("Shape:")->getValueAsString();
}
QString text = "";
if (m_infoMap.find(name + nameLevel + nameMode) != m_infoMap.end())
text += m_infoMap[name + nameLevel + nameMode];
else if (m_infoMap.find(name + nameLevel) != m_infoMap.end())
text += m_infoMap[name + nameLevel];
else if (m_infoMap.find(name + nameMode) != m_infoMap.end())
text += m_infoMap[name + nameMode];
else if (m_infoMap.find(name) != m_infoMap.end())
text += m_infoMap[name];
QString hintText = "";
if (m_hintMap.find(name + nameLevel + nameMode) != m_hintMap.end())
hintText += m_hintMap[name + nameLevel + nameMode];
else if (m_hintMap.find(name + nameLevel) != m_hintMap.end())
hintText += m_hintMap[name + nameLevel];
else if (m_hintMap.find(name + nameMode) != m_hintMap.end())
hintText += m_hintMap[name + nameMode];
else if (m_hintMap.find(name) != m_hintMap.end())
hintText += m_hintMap[name];
m_infoLabel->setToolTip(hintText);
m_infoLabel->setText(text);
}
//-----------------------------------------------------------------------------
QString trModKey(QString key) {
#ifdef MACOSX
// Convert Windows key modifier to macOS modifier
if (key == "Ctrl") // Command
return QString::fromStdWString(L"\u2318");
else if (key == "Shift")
return QString::fromStdWString(L"\u21e7");
else if (key == "Alt")
return QString::fromStdWString(L"\u2325");
// else if (key == "???") // Control
// return QString::fromStdWString(L"\u2303");
#endif
void StatusBar::makeMap() {
QString spacer = " ";
// tools
m_infoMap.insert({"T_Hand", "<b>Hand Tool:</b> Pans the workspace"});
m_infoMap.insert(
{"T_Selection",
"Selection Tool: Select parts of your image to transform it."});
m_infoMap.insert({"T_Edit",
"Animate Tool: Modifies the position, rotation and size of "
"the current column"});
m_infoMap.insert({"T_Brush", "Brush Tool: Draws in the work area freehand"});
m_infoMap.insert(
{"T_BrushVector", "Brush Tool: Draws in the work area freehand" + spacer +
"Shift - Straight Lines" + spacer +
#ifdef MACOSX
"Cmd - Straight Lines Snapped to Angles" + spacer +
"Cmd + Opt - Add / Remove Vanishing Point" +
spacer + "Opt - Draw to Vanishing Point" + spacer +
"Hold Cmd + Shift - Toggle Snapping"});
#else
"Control - Straight Lines Snapped to Angles" +
spacer +
"Ctrl + Alt - Add / Remove Vanishing Point" +
spacer + "Alt - Draw to Vanishing Point" + spacer +
"Hold Ctrl + Shift - Toggle Snapping"});
#endif
m_infoMap.insert({"T_BrushSmartRaster",
"Brush Tool: Draws in the work area freehand" + spacer +
"Shift - Straight Lines" + spacer +
#ifdef MACOSX
"Cmd - Straight Lines Snapped to Angles" + spacer +
"Cmd + Opt - Add / Remove Vanishing Point" + spacer +
"Opt - Draw to Vanishing Point"});
#else
"Control - Straight Lines Snapped to Angles" + spacer +
"Ctrl + Alt - Add / Remove Vanishing Point" + spacer +
"Alt - Draw to Vanishing Point"});
#endif
m_infoMap.insert(
{"T_BrushRaster", "Brush Tool: Draws in the work area freehand" + spacer +
"Shift - Straight Lines" + spacer +
#ifdef MACOSX
"Cmd - Straight Lines Snapped to Angles" + spacer +
"Cmd + Opt - Add / Remove Vanishing Point" +
spacer + "Opt - Draw to Vanishing Point"});
#else
"Control - Straight Lines Snapped to Angles" +
spacer +
"Ctrl + Alt - Add / Remove Vanishing Point" +
spacer + "Alt - Draw to Vanishing Point"});
#endif
m_infoMap.insert({"T_Geometric", "Geometry Tool: Draws geometric shapes"});
m_infoMap.insert(
{"T_GeometricVector", "Geometry Tool: Draws geometric shapes" + spacer +
#ifdef MACOSX
"Hold Cmd + Shift - Toggle Snapping"});
#else
"Hold Ctrl + Shift - Toggle Snapping"});
#endif
m_infoMap.insert({"T_Type", "Type Tool: Adds text"});
m_infoMap.insert(
{"T_PaintBrush",
"Smart Raster Painter: Paints areas in Smart Raster leves"});
m_infoMap.insert(
{"T_Fill", "Fill Tool: Fills drawing areas with the current style"});
m_infoMap.insert({"T_Eraser", "Eraser: Erases lines and areas"});
m_infoMap.insert(
{"T_Tape", "Tape Tool: Closes gaps in raster, joins edges in vector"});
m_infoMap.insert(
{"T_StylePicker", "Style Picker: Selects style on current drawing"});
m_infoMap.insert(
{"T_RGBPicker",
"RGB Picker: Picks color on screen and applies to current style"});
m_infoMap.insert({"T_ControlPointEditor",
"Control Point Editor: Modifies vector lines by editing "
"its control points"});
m_infoMap.insert({"T_Pinch", "Pinch Tool: Pulls vector drawings"});
m_infoMap.insert({"T_Pump", "Pump Tool: Changes vector thickness"});
m_infoMap.insert({"T_Magnet", "Magnet Tool: Deforms vector lines"});
m_infoMap.insert(
{"T_Bender", "Bend Tool: Bends vector shapes around the first click"});
m_infoMap.insert({"T_Iron", "Iron Tool: Smooths vector lines"});
m_infoMap.insert({"T_Cutter", "Cutter Tool: Splits vector lines"});
m_infoMap.insert({"T_Hook", ""});
m_infoMap.insert({"T_Skeleton",
"Skeleton Tool: Allows to build a skeleton and animate in "
"a cut-out workflow"});
m_infoMap.insert(
{"T_Tracker",
"Tracker: Tracks specific regions in a sequence of images"});
m_infoMap.insert({"T_Plastic",
"Plastic Tool: Builds a mesh that allows to deform and "
"animate a level"});
m_infoMap.insert({"T_Zoom", "Zoom Tool: Zooms viewer"});
m_infoMap.insert({"T_Rotate", "Rotate Tool: Rotate the workspace"});
m_infoMap.insert({"T_Ruler", ""});
m_infoMap.insert(
{"T_Finger", "Finger Tool: Smudges small areas to cover with line"});
m_infoMap.insert({"T_Dummy", "This tool doesn't work on this layer type."});
return key;
}
std::unordered_map<std::string, QString> StatusBar::makeMap(
QString spacer, QString cmdTextSeparator, QString cmd2TextSeparator) {
std::unordered_map<std::string, QString> lMap;
#ifdef MACOSX
// on macOS, we display symbols. No need to space differently
cmd2TextSeparator = cmdTextSeparator;
#endif
// tools
lMap.insert({"T_Hand", tr("Hand Tool: Pans the workspace")});
lMap.insert(
{"T_Selection",
tr("Selection Tool: Select parts of your image to transform it") +
spacer +
tr("%1%2Scale / Directional scale")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Distort / Shear")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Scale Symmetrically from Center")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Scale Symmetrically from Center w/ Proportion Lock")
.arg(trModKey("Shift") + "+" + trModKey("Alt"))
.arg(cmdTextSeparator)});
lMap.insert({"T_Edit", tr("Animate Tool: Modifies the position, "
"rotation and size of the current column")});
lMap.insert({"T_Brush", tr("Brush Tool: Draws in the work area freehand")});
lMap.insert({"T_BrushVector",
tr("Brush Tool : Draws in the work area freehand") + spacer +
tr("%1%2Straight Lines")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Straight Lines Snapped to Angles")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl") + "+" + trModKey("Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Allow or Disallow Snapping")
.arg(trModKey("Ctrl") + "+" + trModKey("Shift"))
.arg(cmdTextSeparator)});
lMap.insert({"T_BrushSmartRaster",
tr("Brush Tool : Draws in the work area freehand") + spacer +
tr("%1%2Straight Lines")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Straight Lines Snapped to Angles")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl") + "+" + trModKey("Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator)});
lMap.insert({"T_BrushRaster",
tr("Brush Tool : Draws in the work area freehand") + spacer +
tr("%1%2Straight Lines")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Straight Lines Snapped to Angles")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl") + "+" + trModKey("Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator)});
lMap.insert({"T_Geometric", tr("Geometry Tool: Draws geometric shapes")});
lMap.insert({"T_GeometricRectangle",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Proportion Lock")
.arg(trModKey("Shift"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Create From Center")
.arg(trModKey("Alt"))
.arg(cmdTextSeparator)});
lMap.insert({"T_GeometricEllipse",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Proportion Lock")
.arg(trModKey("Shift"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Create From Center")
.arg(trModKey("Alt"))
.arg(cmdTextSeparator)});
lMap.insert(
{"T_GeometricPolyline",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Create Curve").arg(tr("Click+Drag")).arg(cmdTextSeparator) +
spacer +
tr("%1%2Return to Straight Line")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Snap to Angle")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator)});
lMap.insert({"T_GeometricVector",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Allow or Disallow Snapping")
.arg(trModKey("Ctrl") + "+" + trModKey("Shift"))
.arg(cmdTextSeparator)});
lMap.insert({"T_GeometricVectorRectangle",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Proportion Lock")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Create From Center")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Allow or Disallow Snapping")
.arg(trModKey("Ctrl") + "+" + trModKey("Shift"))
.arg(cmdTextSeparator)});
lMap.insert({"T_GeometricVectorEllipse",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Proportion Lock")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Create From Center")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Allow or Disallow Snapping")
.arg(trModKey("Ctrl") + "+" + trModKey("Shift"))
.arg(cmdTextSeparator)});
lMap.insert(
{"T_GeometricVectorPolyline",
tr("Geometry Tool: Draws geometric shapes") + spacer +
tr("%1%2Create Curve").arg(tr("Click+Drag")).arg(cmdTextSeparator) +
spacer +
tr("%1%2Return to Straight Line")
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Snap to Angle")
.arg(trModKey("Shift"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Allow or Disallow Snapping")
.arg(trModKey("Ctrl") + "+" + trModKey("Shift"))
.arg(cmdTextSeparator)});
lMap.insert({"T_Type", tr("Type Tool: Adds text")});
lMap.insert({"T_PaintBrush",
tr("Smart Raster Painter: Paints areas in Smart Raster leves")});
lMap.insert(
{"T_Fill", tr("Fill Tool: Fills drawing areas with the current style")});
lMap.insert({"T_Eraser", tr("Eraser: Erases lines and areas")});
lMap.insert({"T_Tape",
tr("Tape Tool: Closes gaps in raster, joins edges in vector")});
lMap.insert(
{"T_StylePicker", tr("Style Picker: Selects style on current drawing")});
lMap.insert(
{"T_RGBPicker",
tr("RGB Picker: Picks color on screen and applies to current style")});
lMap.insert(
{"T_ControlPointEditor", tr("Control Point Editor: Modifies vector lines "
"by editing its control points")});
lMap.insert({"T_Pinch", tr("Pinch Tool: Pulls vector drawings")});
lMap.insert({"T_Pump", tr("Pump Tool: Changes vector thickness")});
lMap.insert({"T_Magnet", tr("Magnet Tool: Deforms vector lines")});
lMap.insert({"T_Bender",
tr("Bend Tool: Bends vector shapes around the first click")});
lMap.insert({"T_Iron", tr("Iron Tool: Smooths vector lines")});
lMap.insert({"T_Cutter", tr("Cutter Tool: Splits vector lines")});
lMap.insert({"T_Hook", ""});
lMap.insert(
{"T_Skeleton", tr("Skeleton Tool: Allows to build a skeleton and animate "
"in a cut-out workflow")});
lMap.insert({"T_Tracker",
tr("Tracker: Tracks specific regions in a sequence of images")});
lMap.insert({"T_Plastic", tr("Plastic Tool: Builds a mesh that allows "
"to deform and animate a level")});
lMap.insert({"T_Zoom", tr("Zoom Tool: Zooms viewer")});
lMap.insert({"T_Rotate", tr("Rotate Tool: Rotate the workspace")});
lMap.insert({"T_Ruler", tr("Ruler Tool: Measures distances on the canvas")});
lMap.insert(
{"T_Finger", tr("Finger Tool: Smudges small areas to cover with line")});
lMap.insert({"T_Dummy", tr("This tool doesn't work on this layer type.")});
return lMap;
}

View file

@ -3,7 +3,7 @@
#ifndef STATUSBAR_H
#define STATUSBAR_H
#include <QStatusBar>;
#include <QStatusBar>
#include <unordered_map>
#include <QLabel>
@ -32,11 +32,16 @@ public:
void updateFrameText(QString text);
void refreshStatusBar() { updateInfoText(); }
protected:
StatusLabel *m_currentFrameLabel, *m_infoLabel;
std::unordered_map<std::string, QString> m_infoMap;
std::unordered_map<std::string, QString> m_hintMap;
void showEvent(QShowEvent*) override;
void makeMap();
std::unordered_map<std::string, QString> makeMap(QString spacer,
QString cmdTextSeparator,
QString cmd2TextSeparator);
protected slots:
void updateInfoText();

View file

@ -869,6 +869,12 @@ void TApp::showMessage(QString message) {
//-----------------------------------------------------------------------------
void TApp::refreshStatusBar() {
if (m_statusBar) m_statusBar->refreshStatusBar();
}
//-----------------------------------------------------------------------------
QString TApp::getCurrentRoomName() const {
Room *currentRoom = dynamic_cast<Room *>(getCurrentRoom());
if (!currentRoom) return QString();

View file

@ -216,6 +216,8 @@ public:
void setStatusBar(StatusBar *statusBar);
void setStatusBarFrameInfo(QString text);
void refreshStatusBar() override;
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
bool m_showTitleBars = true;

View file

@ -4,6 +4,7 @@
#include "menubarcommandids.h"
#include "tapp.h"
#include "sceneviewer.h"
#include "stopmotion.h"
// TnzQt includes
#include "toonzqt/menubarcommand.h"
@ -144,6 +145,10 @@ public:
int stopFrame = std::min(currentFrame, maxFrame);
StopMotion *stopMotion = StopMotion::instance();
if (stopMotion->getPlaceOnXSheet() && stopMotion->m_liveViewStatus > 0)
stopFrame = StopMotion::instance()->getXSheetFrameNumber() - 1;
int startFrame = std::max(0, stopFrame - shortPlayFrameCount);
TApp::instance()->getCurrentFrame()->setFrame(startFrame);

View file

@ -76,6 +76,7 @@
#include <QToolTip>
#include <QApplication>
#include <QClipboard>
#include <QKeyEvent>
namespace {
@ -558,7 +559,11 @@ namespace XsheetGUI {
//-----------------------------------------------------------------------------
RenameCellField::RenameCellField(QWidget *parent, XsheetViewer *viewer)
: QLineEdit(parent), m_viewer(viewer), m_row(-1), m_col(-1) {
: QLineEdit(parent)
, m_viewer(viewer)
, m_row(-1)
, m_col(-1)
, m_isRenamingCell(false) {
connect(this, SIGNAL(returnPressed()), SLOT(onReturnPressed()));
setContextMenuPolicy(Qt::PreventContextMenu);
setObjectName("RenameCellField");
@ -884,24 +889,39 @@ void RenameCellField::renameCell() {
//-----------------------------------------------------------------------------
void RenameCellField::onReturnPressed() {
renameCell();
void RenameCellField::moveCellSelection(int direction) {
// move the cell selection
TCellSelection *cellSelection = dynamic_cast<TCellSelection *>(
TApp::instance()->getCurrentSelection()->getSelection());
if (!cellSelection) return;
TCellSelection::Range range = cellSelection->getSelectedCells();
int offset = range.m_r1 - range.m_r0 + 1;
int offset = range.m_r1 - range.m_r0 + direction;
if ((m_row + offset) < 0) return;
cellSelection->selectCells(range.m_r0 + offset, range.m_c0,
range.m_r1 + offset, range.m_c1);
showInRowCol(m_row + offset, m_col, range.getColCount() > 1);
m_viewer->updateCells();
m_viewer->setCurrentRow(m_row);
TApp::instance()->getCurrentSelection()->notifySelectionChanged();
}
//-----------------------------------------------------------------------------
void RenameCellField::onReturnPressed() {
renameCell();
moveCellSelection(1);
}
//-----------------------------------------------------------------------------
void RenameCellField::onTabPressed() { moveCellSelection(1); }
//-----------------------------------------------------------------------------
void RenameCellField::onBacktabPressed() { moveCellSelection(-1); }
//-----------------------------------------------------------------------------
void RenameCellField::focusOutEvent(QFocusEvent *e) {
hide();
@ -912,9 +932,34 @@ void RenameCellField::focusOutEvent(QFocusEvent *e) {
// Override shortcut keys for cell selection commands
bool RenameCellField::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
int key = keyEvent->key();
switch (key) {
case Qt::Key_Tab:
onTabPressed();
return true;
break;
case Qt::Key_Backtab:
onBacktabPressed();
return true;
break;
}
}
if (e->type() != QEvent::ShortcutOverride)
return QLineEdit::eventFilter(obj, e); // return false;
// If we aren't allowing any shortcuts while renaming, use default editing
// commands.
if (!Preferences::instance()->isShortcutCommandsWhileRenamingCellEnabled())
return QLineEdit::eventFilter(obj, e);
// No shortcuts in Note Levels
TXshColumn *col = m_viewer->getXsheet()->getColumn(m_col);
bool noShortcuts = (col && col->getSoundTextColumn()) ? true : false;
if (noShortcuts) return QLineEdit::eventFilter(obj, e);
TCellSelection *cellSelection = dynamic_cast<TCellSelection *>(
TApp::instance()->getCurrentSelection()->getSelection());
if (!cellSelection) return QLineEdit::eventFilter(obj, e);
@ -925,19 +970,13 @@ bool RenameCellField::eventFilter(QObject *obj, QEvent *e) {
QAction *action = CommandManager::instance()->getActionFromShortcut(keyStr);
if (!action) return QLineEdit::eventFilter(obj, e);
std::string actionId = CommandManager::instance()->getIdFromAction(action);
// These are usally standard ctrl/command strokes for text editing.
// Default to standard behavior and don't execute OT's action while renaming
// cell if users prefer to do so.
// Or, always invoke OT's commands when renaming cell even the standard
// command strokes for text editing.
// The latter option is demanded by Japanese animation industry in order to
// gain efficiency for inputting xsheet.
if (!Preferences::instance()->isShortcutCommandsWhileRenamingCellEnabled() &&
(actionId == "MI_Undo" || actionId == "MI_Redo" ||
actionId == "MI_Clear" || actionId == "MI_Copy" ||
actionId == "MI_Paste" || actionId == "MI_Cut"))
std::string actionId = CommandManager::instance()->getIdFromAction(action);
if (actionId == "MI_Undo" || actionId == "MI_Redo" ||
actionId == "MI_Clear" || actionId == "MI_Copy" ||
actionId == "MI_Paste" || actionId == "MI_Cut")
return QLineEdit::eventFilter(obj, e);
return TCellSelection::isEnabledCommand(actionId);
@ -948,6 +987,7 @@ bool RenameCellField::eventFilter(QObject *obj, QEvent *e) {
void RenameCellField::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Escape) {
clearFocus();
m_viewer->setFocus();
return;
}
@ -965,7 +1005,8 @@ void RenameCellField::keyPressEvent(QKeyEvent *event) {
stride.setFrame(cellSelection->getSelectedCells().getRowCount());
CellPosition offset;
switch (int key = event->key()) {
int key = event->key();
switch (key) {
case Qt::Key_Up:
case Qt::Key_Down:
offset = m_viewer->orientation()->arrowShift(key);
@ -973,10 +1014,16 @@ void RenameCellField::keyPressEvent(QKeyEvent *event) {
case Qt::Key_Left:
case Qt::Key_Right:
// ctrl+left/right arrow for moving cursor to the end in the field
if (isCtrlPressed &&
if (!isCtrlPressed ||
!Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled()) {
QLineEdit::keyPressEvent(event);
return;
// Allow left/right movement inside field. If you go too far, you will
// shift cells
int curPos = cursorPosition();
if ((key == Qt::Key_Left && curPos > 0) ||
(key == Qt::Key_Right && curPos < text().size())) {
QLineEdit::keyPressEvent(event);
return;
}
}
offset = m_viewer->orientation()->arrowShift(key);
break;
@ -1019,6 +1066,8 @@ void RenameCellField::showEvent(QShowEvent *) {
bool ret = connect(TApp::instance()->getCurrentXsheet(),
SIGNAL(xsheetChanged()), this, SLOT(onXsheetChanged()));
assert(ret);
m_isRenamingCell = true;
}
//-----------------------------------------------------------------------------
@ -1026,6 +1075,7 @@ void RenameCellField::showEvent(QShowEvent *) {
void RenameCellField::hideEvent(QHideEvent *) {
disconnect(TApp::instance()->getCurrentXsheet(), SIGNAL(xsheetChanged()),
this, SLOT(onXsheetChanged()));
m_isRenamingCell = false;
}
//-----------------------------------------------------------------------------

View file

@ -26,6 +26,7 @@ class RenameCellField final : public QLineEdit {
int m_row;
int m_col;
XsheetViewer *m_viewer;
bool m_isRenamingCell;
public:
RenameCellField(QWidget *parent, XsheetViewer *viewer);
@ -35,6 +36,8 @@ public:
bool isLocatedAt(int row, int col) { return row == m_row && col == m_col; }
bool isRenamingCell() { return m_isRenamingCell; }
protected:
void focusOutEvent(QFocusEvent *) override;
void keyPressEvent(QKeyEvent *event) override;
@ -46,6 +49,10 @@ protected:
void renameCell();
void renameSoundTextColumn(TXshSoundTextColumn *sndTextCol, const QString &s);
void moveCellSelection(int direction);
void onTabPressed();
void onBacktabPressed();
protected slots:
void onReturnPressed();
void onXsheetChanged();
@ -134,6 +141,9 @@ public:
m_renameCell->showInRowCol(row, col, multiColumnSelected);
}
void hideRenameField() { m_renameCell->hide(); }
bool isRenamingCell() {
return m_renameCell && m_renameCell->isRenamingCell();
}
protected:
void paintEvent(QPaintEvent *) override;

View file

@ -1667,8 +1667,8 @@ void XsheetViewer::changeWindowTitle() {
QString sceneName = QString::fromStdWString(scene->getSceneName());
if (sceneName.isEmpty()) sceneName = tr("Untitled");
if (app->getCurrentScene()->getDirtyFlag()) sceneName += QString("*");
QString name = tr("Scene: ") + sceneName;
QString separator = " | ";
QString name = tr("Scene: ") + sceneName;
int frameCount = scene->getFrameCount();
name = name + separator + tr(std::to_string(frameCount).c_str()) +
(frameCount == 1 ? tr(" Frame") : tr(" Frames"));
@ -1682,7 +1682,7 @@ void XsheetViewer::changeWindowTitle() {
TXshLevel *level = app->getCurrentLevel()->getLevel();
if (level) {
QString levelName = QString::fromStdWString(level->getName());
name += separator + tr(" Level: ") + levelName;
name += separator + tr("Level: ") + levelName;
}
// cell selection range
if ((TSelection *)getCellSelection() ==
@ -1690,12 +1690,12 @@ void XsheetViewer::changeWindowTitle() {
!getCellSelection()->isEmpty()) {
int r0, r1, c0, c1;
getCellSelection()->getSelectedCells(r0, c0, r1, c1);
name += separator + tr(" Selected: ") + QString::number(r1 - r0 + 1) +
name += separator + tr("Selected: ") + QString::number(r1 - r0 + 1) +
((r1 - r0 + 1 == 1) ? tr(" frame : ") : tr(" frames * ")) +
QString::number(c1 - c0 + 1) +
((c1 - c0 + 1 == 1) ? tr(" column") : tr(" columns"));
}
TApp::instance()->setStatusBarFrameInfo(name);
TApp::instance()->setStatusBarFrameInfo("| " + name);
parentWidget()->setWindowTitle(name);
}

View file

@ -498,6 +498,8 @@ void Preferences::definePreferenceItems() {
0); // Default
define(useCtrlAltToResizeBrush, "useCtrlAltToResizeBrush", QMetaType::Bool,
true);
define(temptoolswitchtimer, "temptoolswitchtimer", QMetaType::Int, 500, 1,
std::numeric_limits<int>::max());
// Xsheet
define(xsheetLayoutPreference, "xsheetLayoutPreference", QMetaType::QString,

View file

@ -18,7 +18,7 @@
</p>
</description>
<url type="homepage">https://tahoma2d.org</url>
<url type="bugtracker">https://github.com/turtletooth/tahoma2d/issues</url>
<url type="bugtracker">https://github.com/tahoma2d/tahoma2d/issues</url>
<screenshots>
<screenshot type="default">
<image>https://tahoma2d.readthedocs.io/en/latest/_images/interface.png</image>