Add individual reset room layout options (#376)
* Add individual reset room layout options * Fix update toolbar crash on room restore * Fix sceneviewer crash on quit after room restore Co-authored-by: manongjohn <manongjohn@users.noreply.github.com>
This commit is contained in:
parent
5850bb75b5
commit
7672e2ebcb
7 changed files with 202 additions and 74 deletions
|
@ -337,6 +337,35 @@ std::pair<DockLayout *, DockLayout::State> Room::load(const TFilePath &fp) {
|
|||
return std::make_pair(layout, state);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Room::reload() {
|
||||
TFilePath fp = getPath();
|
||||
|
||||
QSettings settings(toQString(fp), QSettings::IniFormat);
|
||||
|
||||
DockLayout *layout = dockLayout();
|
||||
std::vector<QRect> geometries;
|
||||
|
||||
hide();
|
||||
QRect lgeo = layout->geometry();
|
||||
|
||||
for (int i = layout->count() - 1; i >= 0; i--) {
|
||||
TPanel *pane = static_cast<TPanel *>(layout->itemAt(i)->widget());
|
||||
removeDockWidget(pane);
|
||||
}
|
||||
|
||||
DockLayout::State state(geometries, "-1 ");
|
||||
layout->restoreState(state);
|
||||
|
||||
load(fp);
|
||||
|
||||
layout->setGeometry(lgeo);
|
||||
layout->redistribute();
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// MainWindow
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1176,33 +1205,46 @@ void MainWindow::autofillToggle() {
|
|||
}
|
||||
|
||||
void MainWindow::resetRoomsLayout() {
|
||||
if (!m_saveSettingsOnQuit) return;
|
||||
|
||||
m_saveSettingsOnQuit = false;
|
||||
QString question(
|
||||
tr("Are you sure you want to reload and restore default rooms?\nCustom "
|
||||
"rooms will not be touched."));
|
||||
int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"));
|
||||
if (ret == 0 || ret == 2) return;
|
||||
|
||||
TFilePath layoutDir = ToonzFolder::getMyRoomsDir();
|
||||
if (layoutDir != TFilePath()) {
|
||||
// TSystem::deleteFile(layoutDir);
|
||||
TSystem::rmDirTree(layoutDir);
|
||||
}
|
||||
/*if (layoutDir != TFilePath()) {
|
||||
try {
|
||||
TFilePathSet fpset;
|
||||
TSystem::readDirectory(fpset, layoutDir, true, false);
|
||||
for (auto const& path : fpset) {
|
||||
QString fn = toQString(path.withoutParentDir());
|
||||
if (fn.startsWith("room") || fn.startsWith("popups"))
|
||||
{
|
||||
TSystem::deleteFile(path);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
TFilePath layoutTemplateDir = ToonzFolder::getTemplateRoomsDir();
|
||||
TFilePathSet room_fpset;
|
||||
try {
|
||||
TSystem::readDirectory(room_fpset, layoutTemplateDir, false, true);
|
||||
TFilePathSet::iterator it = room_fpset.begin();
|
||||
for (int i = 0; it != room_fpset.end(); it++, i++) {
|
||||
TFilePath defaultfp = *it;
|
||||
if (defaultfp.getType() != "ini") continue;
|
||||
TFilePath fp = layoutDir + defaultfp.getLevelName();
|
||||
if (TFileStatus(fp).doesExist()) {
|
||||
for (i = 0; i < m_stackedWidget->count(); i++) {
|
||||
Room *room = getRoom(i);
|
||||
if (room->getPath() == fp) {
|
||||
room->reload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
TSystem::copyFile(fp, defaultfp);
|
||||
|
||||
DVGui::MsgBoxInPopup(
|
||||
DVGui::INFORMATION,
|
||||
QObject::tr("The rooms will be reset the next time you run Tahoma2D."));
|
||||
QTabBar *roomTabWidget = m_topBar->getRoomTabWidget();
|
||||
Room *room = new Room(this);
|
||||
room->hide();
|
||||
m_panelStates.push_back(room->load(fp));
|
||||
m_stackedWidget->addWidget(room);
|
||||
roomTabWidget->addTab(room->getName());
|
||||
room->show();
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::maximizePanel() {
|
||||
|
@ -1294,6 +1336,7 @@ void MainWindow::deleteRoom(int index) {
|
|||
if (index < m_oldRoomIndex) m_oldRoomIndex--;
|
||||
|
||||
m_stackedWidget->removeWidget(room);
|
||||
m_panelStates.erase(m_panelStates.begin() + index);
|
||||
delete room;
|
||||
}
|
||||
|
||||
|
@ -2498,7 +2541,7 @@ void MainWindow::defineActions() {
|
|||
menuAct =
|
||||
createMenuWindowsAction(MI_AudioRecording, tr("Record Audio"), "Alt+A");
|
||||
menuAct->setIcon(createQIcon("recordaudio"));
|
||||
createMenuWindowsAction(MI_ResetRoomLayout, tr("&Reset to Default Rooms"),
|
||||
createMenuWindowsAction(MI_ResetRoomLayout, tr("&Reset All Default Rooms"),
|
||||
"");
|
||||
menuAct = createMenuWindowsAction(MI_MaximizePanel,
|
||||
tr("Toggle Maximize Panel"), "`");
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
|
||||
void save();
|
||||
std::pair<DockLayout *, DockLayout::State> load(const TFilePath &fp);
|
||||
void reload();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -66,6 +66,7 @@ RoomTabWidget::RoomTabWidget(QWidget *parent)
|
|||
: QTabBar(parent)
|
||||
, m_clickedTabIndex(-1)
|
||||
, m_tabToDeleteIndex(-1)
|
||||
, m_tabToResetIndex(-1)
|
||||
, m_renameTabIndex(-1)
|
||||
, m_renameTextField(new DVGui::LineEdit(this))
|
||||
, m_isLocked(LockRoomTabToggle != 0) {
|
||||
|
@ -157,17 +158,46 @@ void RoomTabWidget::contextMenuEvent(QContextMenuEvent *event) {
|
|||
if (m_isLocked) return;
|
||||
m_tabToDeleteIndex = -1;
|
||||
QMenu *menu = new QMenu(this);
|
||||
QAction *newRoom = menu->addAction(tr("New Room"));
|
||||
connect(newRoom, SIGNAL(triggered()), SLOT(addNewTab()));
|
||||
|
||||
int index = tabAt(event->pos());
|
||||
|
||||
if (index >= 0) {
|
||||
m_tabToResetIndex = index;
|
||||
QAction *resetRoomSaved = menu->addAction(
|
||||
tr("Reset Room \"%1\" to Saved Layout").arg(tabText(index)));
|
||||
connect(resetRoomSaved, SIGNAL(triggered()), SLOT(resetTabSaved()));
|
||||
if (m_tabToResetIndex == currentIndex())
|
||||
resetRoomSaved->setEnabled(true);
|
||||
else
|
||||
resetRoomSaved->setEnabled(false);
|
||||
|
||||
QAction *resetRoomDefault = menu->addAction(
|
||||
tr("Reset Room \"%1\" to Default Layout").arg(tabText(index)));
|
||||
connect(resetRoomDefault, SIGNAL(triggered()), SLOT(resetTabDefault()));
|
||||
resetRoomDefault->setEnabled(false);
|
||||
if (m_tabToResetIndex == currentIndex()) {
|
||||
MainWindow *mainWin =
|
||||
dynamic_cast<MainWindow *>(TApp::instance()->getMainWindow());
|
||||
assert(mainWin);
|
||||
Room *room = mainWin->getRoom(index);
|
||||
TFilePath fp = room->getPath();
|
||||
TFilePath defaultfp =
|
||||
ToonzFolder::getTemplateRoomsDir() + TFilePath(fp.getLevelName());
|
||||
if (TFileStatus(defaultfp).doesExist())
|
||||
resetRoomDefault->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
QAction *newRoom = menu->addAction(tr("New Room"));
|
||||
connect(newRoom, SIGNAL(triggered()), SLOT(addNewTab()));
|
||||
|
||||
if (index >= 0) {
|
||||
m_tabToDeleteIndex = index;
|
||||
if (index != currentIndex()) {
|
||||
QAction *deleteRoom =
|
||||
menu->addAction(tr("Delete Room \"%1\"").arg(tabText(index)));
|
||||
connect(deleteRoom, SIGNAL(triggered()), SLOT(deleteTab()));
|
||||
}
|
||||
QAction *deleteRoom =
|
||||
menu->addAction(tr("Delete Room \"%1\"").arg(tabText(index)));
|
||||
connect(deleteRoom, SIGNAL(triggered()), SLOT(deleteTab()));
|
||||
deleteRoom->setEnabled(false);
|
||||
if (index != currentIndex()) deleteRoom->setEnabled(true);
|
||||
}
|
||||
menu->exec(event->globalPos());
|
||||
}
|
||||
|
@ -198,7 +228,7 @@ void RoomTabWidget::addNewTab() {
|
|||
void RoomTabWidget::deleteTab() {
|
||||
assert(m_tabToDeleteIndex != -1);
|
||||
|
||||
QString question(tr("Are you sure you want to remove room %1")
|
||||
QString question(tr("Are you sure you want to remove room \"%1\"?")
|
||||
.arg(tabText(m_tabToDeleteIndex)));
|
||||
int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"));
|
||||
if (ret == 0 || ret == 2) return;
|
||||
|
@ -210,6 +240,57 @@ void RoomTabWidget::deleteTab() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RoomTabWidget::resetTabSaved() {
|
||||
assert(m_tabToResetIndex != -1);
|
||||
|
||||
QString question(
|
||||
tr("Are you sure you want to reset room \"%1\" to the last saved layout?")
|
||||
.arg(tabText(m_tabToResetIndex)));
|
||||
int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"));
|
||||
if (ret == 0 || ret == 2) return;
|
||||
|
||||
MainWindow *mainWin =
|
||||
dynamic_cast<MainWindow *>(TApp::instance()->getMainWindow());
|
||||
assert(mainWin);
|
||||
Room *room = mainWin->getRoom(m_tabToResetIndex);
|
||||
|
||||
room->reload();
|
||||
setTabText(m_tabToResetIndex, room->getName());
|
||||
|
||||
m_tabToResetIndex = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RoomTabWidget::resetTabDefault() {
|
||||
assert(m_tabToResetIndex != -1);
|
||||
|
||||
QString question(
|
||||
tr("Are you sure you want to reset room \"%1\" to the default layout?")
|
||||
.arg(tabText(m_tabToResetIndex)));
|
||||
int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"));
|
||||
if (ret == 0 || ret == 2) return;
|
||||
|
||||
MainWindow *mainWin =
|
||||
dynamic_cast<MainWindow *>(TApp::instance()->getMainWindow());
|
||||
assert(mainWin);
|
||||
Room *room = mainWin->getRoom(m_tabToResetIndex);
|
||||
TFilePath fp = room->getPath();
|
||||
TFilePath defaultfp =
|
||||
ToonzFolder::getTemplateRoomsDir() + TFilePath(fp.getLevelName());
|
||||
try {
|
||||
TSystem::copyFile(fp, defaultfp);
|
||||
room->reload();
|
||||
setTabText(m_tabToResetIndex, room->getName());
|
||||
} catch (...) {
|
||||
DVGui::MsgBoxInPopup(DVGui::CRITICAL, QObject::tr("Failed to reset room!"));
|
||||
}
|
||||
|
||||
m_tabToResetIndex = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RoomTabWidget::setIsLocked(bool lock) {
|
||||
m_isLocked = lock;
|
||||
LockRoomTabToggle = (lock) ? 1 : 0;
|
||||
|
|
|
@ -34,6 +34,7 @@ class RoomTabWidget final : public QTabBar {
|
|||
|
||||
int m_clickedTabIndex;
|
||||
int m_tabToDeleteIndex;
|
||||
int m_tabToResetIndex;
|
||||
int m_renameTabIndex;
|
||||
DVGui::LineEdit *m_renameTextField;
|
||||
bool m_isLocked;
|
||||
|
@ -57,6 +58,8 @@ protected slots:
|
|||
void updateTabName();
|
||||
void addNewTab();
|
||||
void deleteTab();
|
||||
void resetTabSaved();
|
||||
void resetTabDefault();
|
||||
void setIsLocked(bool lock);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -850,11 +850,8 @@ void SceneViewer::setVisual(const ImagePainter::VisualSettings &settings) {
|
|||
SceneViewer::~SceneViewer() {
|
||||
if (m_fbo) delete m_fbo;
|
||||
|
||||
// release all the registered context (once when exit the software)
|
||||
std::set<TGlContext>::iterator ct, cEnd(l_contexts.end());
|
||||
for (ct = l_contexts.begin(); ct != cEnd; ++ct)
|
||||
TGLDisplayListsManager::instance()->releaseContext(*ct);
|
||||
l_contexts.clear();
|
||||
int ret = l_contexts.erase(m_currentContext);
|
||||
if (ret) TGLDisplayListsManager::instance()->releaseContext(m_currentContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
|
@ -3559,4 +3556,5 @@ void SceneViewer::registerContext() {
|
|||
TGlContext tglContext(tglGetCurrentContext());
|
||||
TGLDisplayListsManager::instance()->attachContext(displayListId, tglContext);
|
||||
l_contexts.insert(tglContext);
|
||||
m_currentContext = tglContext;
|
||||
}
|
|
@ -31,29 +31,6 @@
|
|||
|
||||
TEnv::IntVar ShowAllToolsToggle("ShowAllToolsToggle", 1);
|
||||
|
||||
namespace {
|
||||
struct {
|
||||
const char *toolName;
|
||||
bool collapsable;
|
||||
QAction *action;
|
||||
} buttonLayout[] = {{T_Edit, false, 0}, {T_Selection, false, 0},
|
||||
{"Separator_1", false, 0}, {T_Brush, false, 0},
|
||||
{T_Geometric, false, 0}, {T_Type, true, 0},
|
||||
{T_Fill, false, 0}, {T_PaintBrush, false, 0},
|
||||
{"Separator_2", false, 0}, {T_Eraser, false, 0},
|
||||
{T_Tape, false, 0}, //{T_Finger, false, 0},
|
||||
{"Separator_3", false, 0}, {T_StylePicker, false, 0},
|
||||
{T_RGBPicker, false, 0}, {T_Ruler, false, 0},
|
||||
{"Separator_4", false, 0}, {T_ControlPointEditor, false, 0},
|
||||
{T_Pinch, true, 0}, {T_Pump, true, 0},
|
||||
{T_Magnet, true, 0}, {T_Bender, true, 0},
|
||||
{T_Iron, true, 0}, {T_Cutter, true, 0},
|
||||
{"Separator_5", true, 0}, {T_Skeleton, true, 0},
|
||||
{T_Tracker, true, 0}, {T_Hook, true, 0},
|
||||
{T_Plastic, true, 0}, {"Separator_6", false, 0},
|
||||
{T_Zoom, false, 0}, {T_Rotate, true, 0},
|
||||
{T_Hand, false, 0}, {0, false, 0}};
|
||||
} // namespace
|
||||
//=============================================================================
|
||||
// Toolbar
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -164,8 +141,8 @@ void Toolbar::updateToolbar() {
|
|||
}
|
||||
|
||||
// Hide action for now
|
||||
for (int idx = 0; buttonLayout[idx].toolName; idx++) {
|
||||
if (buttonLayout[idx].action) removeAction(buttonLayout[idx].action);
|
||||
for (int idx = 0; m_buttonLayout[idx].toolName; idx++) {
|
||||
if (m_buttonLayout[idx].action) removeAction(m_buttonLayout[idx].action);
|
||||
}
|
||||
|
||||
removeAction(m_expandAction);
|
||||
|
@ -175,36 +152,35 @@ void Toolbar::updateToolbar() {
|
|||
bool actionEnabled = false;
|
||||
ToolHandle *toolHandle = TApp::instance()->getCurrentTool();
|
||||
|
||||
for (int idx = 0; buttonLayout[idx].toolName; idx++) {
|
||||
TTool *tool = TTool::getTool(buttonLayout[idx].toolName, targetType);
|
||||
for (int idx = 0; m_buttonLayout[idx].toolName; idx++) {
|
||||
TTool *tool = TTool::getTool(m_buttonLayout[idx].toolName, targetType);
|
||||
if (tool) tool->updateEnabled(rowIndex, colIndex);
|
||||
bool isSeparator = !strncmp(buttonLayout[idx].toolName, "Separator", 9);
|
||||
bool enable =
|
||||
!levelBasedDisplay ? true : (!tool ? actionEnabled : tool->isEnabled());
|
||||
|
||||
// Plastic tool should always be available so you can create a mesh
|
||||
if (!enable && !strncmp(buttonLayout[idx].toolName, T_Plastic, 9) &&
|
||||
if (!enable && !strncmp(m_buttonLayout[idx].toolName, T_Plastic, 9) &&
|
||||
(m_toolbarLevel & LEVELCOLUMN_XSHLEVEL))
|
||||
enable = true;
|
||||
|
||||
if (!m_isExpanded && buttonLayout[idx].collapsable) continue;
|
||||
if (!m_isExpanded && m_buttonLayout[idx].collapsable) continue;
|
||||
|
||||
if (!buttonLayout[idx].action) {
|
||||
if (isSeparator)
|
||||
buttonLayout[idx].action = addSeparator();
|
||||
if (!m_buttonLayout[idx].action) {
|
||||
if (m_buttonLayout[idx].isSeparator)
|
||||
m_buttonLayout[idx].action = addSeparator();
|
||||
else
|
||||
buttonLayout[idx].action =
|
||||
CommandManager::instance()->getAction(buttonLayout[idx].toolName);
|
||||
m_buttonLayout[idx].action =
|
||||
CommandManager::instance()->getAction(m_buttonLayout[idx].toolName);
|
||||
}
|
||||
|
||||
if (levelBasedDisplay != 2)
|
||||
buttonLayout[idx].action->setEnabled(enable);
|
||||
m_buttonLayout[idx].action->setEnabled(enable);
|
||||
else if (!enable)
|
||||
continue;
|
||||
|
||||
actionEnabled = addAction(buttonLayout[idx].action) || actionEnabled;
|
||||
actionEnabled = addAction(m_buttonLayout[idx].action) || actionEnabled;
|
||||
|
||||
if (isSeparator) actionEnabled = false;
|
||||
if (m_buttonLayout[idx].isSeparator) actionEnabled = false;
|
||||
}
|
||||
|
||||
addAction(m_expandAction);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef TOOLBAR_H
|
||||
#define TOOLBAR_H
|
||||
|
||||
#include "tools/toolcommandids.h"
|
||||
|
||||
#include <QToolBar>
|
||||
|
||||
class QToolButton;
|
||||
|
@ -16,6 +18,30 @@ class Toolbar final : public QToolBar {
|
|||
bool m_isExpanded;
|
||||
int m_toolbarLevel;
|
||||
|
||||
struct {
|
||||
const char *toolName;
|
||||
bool isSeparator;
|
||||
bool collapsable;
|
||||
QAction *action;
|
||||
} m_buttonLayout[33] = {
|
||||
{T_Edit, false, false, 0}, {T_Selection, false, false, 0},
|
||||
{"Separator_1", true, false, 0}, {T_Brush, false, false, 0},
|
||||
{T_Geometric, false, false, 0}, {T_Type, false, true, 0},
|
||||
{T_Fill, false, false, 0}, {T_PaintBrush, false, false, 0},
|
||||
{"Separator_2", true, false, 0}, {T_Eraser, false, false, 0},
|
||||
{T_Tape, false, false, 0}, //{T_Finger, false, false, 0},
|
||||
{"Separator_3", true, false, 0}, {T_StylePicker, false, false, 0},
|
||||
{T_RGBPicker, false, false, 0}, {T_Ruler, false, false, 0},
|
||||
{"Separator_4", true, false, 0}, {T_ControlPointEditor, false, false, 0},
|
||||
{T_Pinch, false, true, 0}, {T_Pump, false, true, 0},
|
||||
{T_Magnet, false, true, 0}, {T_Bender, false, true, 0},
|
||||
{T_Iron, false, true, 0}, {T_Cutter, false, true, 0},
|
||||
{"Separator_5", true, true, 0}, {T_Skeleton, false, true, 0},
|
||||
{T_Tracker, false, true, 0}, {T_Hook, false, true, 0},
|
||||
{T_Plastic, false, true, 0}, {"Separator_6", true, false, 0},
|
||||
{T_Zoom, false, false, 0}, {T_Rotate, false, true, 0},
|
||||
{T_Hand, false, false, 0}, {0, false, false, 0}};
|
||||
|
||||
public:
|
||||
Toolbar(QWidget *parent, bool isVertical = true);
|
||||
~Toolbar();
|
||||
|
|
Loading…
Reference in a new issue