#include "pane.h" // Tnz6 includes #include "tapp.h" #include "mainwindow.h" #include "tenv.h" #include "saveloadqsettings.h" #include "toonzqt/gutil.h" // TnzLib includes #include "toonz/preferences.h" #include "toonz/toonzfolders.h" #include "toonz/tscenehandle.h" // TnzCore includes #include "tsystem.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern TEnv::StringVar EnvSafeAreaName; //============================================================================= // TPanel //----------------------------------------------------------------------------- TPanel::TPanel(QWidget *parent, Qt::WindowFlags flags, TDockWidget::Orientation orientation) : TDockWidget(parent, flags) , m_panelType("") , m_isMaximizable(true) , m_isMaximized(false) , m_isActive(true) , m_panelTitleBar(0) , m_multipleInstancesAllowed(true) { // setFeatures(QDockWidget::DockWidgetMovable | // QDockWidget::DockWidgetFloatable); // setFloating(false); m_panelTitleBar = new TPanelTitleBar(this, orientation); setTitleBarWidget(m_panelTitleBar); // connect(m_panelTitleBar,SIGNAL(doubleClick()),this,SLOT(onDoubleClick())); connect(m_panelTitleBar, SIGNAL(doubleClick(QMouseEvent *)), this, SIGNAL(doubleClick(QMouseEvent *))); connect(m_panelTitleBar, SIGNAL(closeButtonPressed()), this, SLOT(onCloseButtonPressed())); setOrientation(orientation); } //----------------------------------------------------------------------------- TPanel::~TPanel() { // On quitting, save the floating panel's geomtry and state in order to // restore them when opening the floating panel next time if (isFloating()) { TFilePath savePath = ToonzFolder::getMyModuleDir() + TFilePath("popups.ini"); QSettings settings(QString::fromStdWString(savePath.getWideString()), QSettings::IniFormat); settings.beginGroup("Panels"); settings.beginGroup(QString::fromStdString(m_panelType)); settings.setValue("geometry", geometry()); if (SaveLoadQSettings *persistent = dynamic_cast(widget())) persistent->save(settings); } } //----------------------------------------------------------------------------- void TPanel::setActive(bool value) { m_isActive = value; if (m_panelTitleBar) { m_panelTitleBar->setIsActive(m_isActive); } } //----------------------------------------------------------------------------- void TPanel::paintEvent(QPaintEvent *e) { QPainter painter(this); if (widget()) { QRect dockRect = widget()->geometry(); dockRect.adjust(0, 0, -1, -1); painter.fillRect(dockRect, m_bgcolor); painter.setPen(Qt::black); painter.drawRect(dockRect); } if (m_floating && !m_panelTitleBar->isVisible()) { m_panelTitleBar->showTitleBar(true); } painter.end(); } //----------------------------------------------------------------------------- void TPanel::onCloseButtonPressed() { emit closeButtonPressed(); // Currently, Toonz panels that get closed indeed just remain hidden - // ready to reappair if they are needed again. However, the user expects // a new panel to be created - so we just reset the panel here. // reset(); //Moved to panel invocation in floatingpanelcommand.cpp // Also, remove widget from its dock layout control if (parentLayout()) parentLayout()->removeWidget(this); } //----------------------------------------------------------------------------- /*! activate the panel and set focus specified widget when mouse enters */ void TPanel::enterEvent(QEvent *event) { // Only when Toonz application is active QWidget *w = qApp->activeWindow(); // if (m_floating) { // m_panelTitleBar->showTitleBar(true); //} if (w) { // grab the focus, unless a line-edit is focused currently bool shouldSetFocus = true; QWidget *focusWidget = qApp->focusWidget(); if (focusWidget) { QLineEdit *lineEdit = dynamic_cast(focusWidget); if (lineEdit) { shouldSetFocus = false; } } if (shouldSetFocus) { widgetFocusOnEnter(); } // Some panels (e.g. Viewer, StudioPalette, Palette, ColorModel) are // activated when mouse enters. Viewer is activatable only when being // docked. // Active windows will NOT switch when the current active window is dialog. if (qobject_cast(w) == 0 && isActivatableOnEnter()) activateWindow(); event->accept(); } else event->accept(); } //----------------------------------------------------------------------------- /*! clear focus when mouse leaves */ void TPanel::leaveEvent(QEvent *event) { widgetClearFocusOnLeave(); } //----------------------------------------------------------------------------- /*! load and restore previous geometry and state of the floating panel. called from the function OpenFloatingPanel::getOrOpenFloatingPanel() in floatingpanelcommand.cpp */ void TPanel::restoreFloatingPanelState() { TFilePath savePath = ToonzFolder::getMyModuleDir() + TFilePath("popups.ini"); QSettings settings(QString::fromStdWString(savePath.getWideString()), QSettings::IniFormat); settings.beginGroup("Panels"); if (!settings.childGroups().contains(QString::fromStdString(m_panelType))) return; settings.beginGroup(QString::fromStdString(m_panelType)); QRect geom = settings.value("geometry", saveGeometry()).toRect(); // check if it can be visible in the current screen if (!(geom & QApplication::desktop()->availableGeometry(this)).isEmpty()) setGeometry(geom); // load optional settings if (SaveLoadQSettings *persistent = dynamic_cast(widget())) persistent->load(settings); } //============================================================================= // TPanelTitleBarButton //----------------------------------------------------------------------------- TPanelTitleBarButton::TPanelTitleBarButton(QWidget *parent, const QString &standardPixmapName) : QWidget(parent) , m_standardPixmap(standardPixmapName) , m_standardPixmapName(standardPixmapName) , m_rollover(false) , m_pressed(false) , m_buttonSet(0) , m_id(0) { setFixedSize(m_standardPixmap.size()); } //----------------------------------------------------------------------------- TPanelTitleBarButton::TPanelTitleBarButton(QWidget *parent, const QPixmap &standardPixmap) : QWidget(parent) , m_standardPixmap(standardPixmap) , m_rollover(false) , m_pressed(false) , m_buttonSet(0) , m_id(0) { setFixedSize(m_standardPixmap.size() / m_standardPixmap.devicePixelRatio()); } //----------------------------------------------------------------------------- void TPanelTitleBarButton::setButtonSet(TPanelTitleBarButtonSet *buttonSet, int id) { m_buttonSet = buttonSet; m_id = id; m_buttonSet->add(this); } //----------------------------------------------------------------------------- void TPanelTitleBarButton::setPressed(bool pressed) { if (pressed != m_pressed) { m_pressed = pressed; update(); } } //----------------------------------------------------------------------------- void TPanelTitleBarButton::paintEvent(QPaintEvent *event) { QPainter painter(this); // create color states for the button QPixmap standard_pm(m_standardPixmap.size()); QPixmap rollover_pm(m_standardPixmap.size()); QPixmap pressed_pm(m_standardPixmap.size()); standard_pm.fill(Qt::transparent); rollover_pm.fill(QColor(getRolloverColor())); pressed_pm.fill(QColor(getPressedColor())); // set unique colors if filename contains string if (m_standardPixmapName.contains("freeze", Qt::CaseInsensitive)) { pressed_pm.fill(QColor(getFreezeColor())); } if (m_standardPixmapName.contains("preview", Qt::CaseInsensitive)) { pressed_pm.fill(QColor(getPreviewColor())); } // compose the state colors painter.drawPixmap( 0, 0, m_pressed ? pressed_pm : m_rollover ? rollover_pm : standard_pm); // compose the icon painter.drawPixmap(0, 0, m_standardPixmap); painter.end(); } //----------------------------------------------------------------------------- void TPanelTitleBarButton::mouseMoveEvent(QMouseEvent *event) {} //----------------------------------------------------------------------------- void TPanelTitleBarButton::enterEvent(QEvent *) { if (!m_rollover) { m_rollover = true; if (!m_pressed) update(); } } //----------------------------------------------------------------------------- void TPanelTitleBarButton::leaveEvent(QEvent *) { if (m_rollover) { m_rollover = false; if (!m_pressed) update(); } } //----------------------------------------------------------------------------- void TPanelTitleBarButton::mousePressEvent(QMouseEvent *e) { if (m_buttonSet) { if (m_pressed) return; m_buttonSet->select(this); } else { m_pressed = !m_pressed; emit toggled(m_pressed); update(); } } //============================================================================= // TPanelTitleBarButtonForSafeArea //----------------------------------------------------------------------------- void TPanelTitleBarButtonForSafeArea::getSafeAreaNameList( QList &nameList) { TFilePath fp = TEnv::getConfigDir(); QString currentSafeAreaName = QString::fromStdString(EnvSafeAreaName); std::string safeAreaFileName = "safearea.ini"; while (!TFileStatus(fp + safeAreaFileName).doesExist() && !fp.isRoot() && fp.getParentDir() != TFilePath()) fp = fp.getParentDir(); fp = fp + safeAreaFileName; if (TFileStatus(fp).doesExist()) { QSettings settings(toQString(fp), QSettings::IniFormat); // find the current safearea name from the list QStringList groups = settings.childGroups(); for (int g = 0; g < groups.size(); g++) { settings.beginGroup(groups.at(g)); nameList.push_back(settings.value("name", "").toString()); settings.endGroup(); } } } //----------------------------------------------------------------------------- void TPanelTitleBarButtonForSafeArea::mousePressEvent(QMouseEvent *e) { if (e->button() != Qt::RightButton) { m_pressed = !m_pressed; emit toggled(m_pressed); update(); } } //----------------------------------------------------------------------------- void TPanelTitleBarButtonForSafeArea::contextMenuEvent(QContextMenuEvent *e) { QMenu menu(this); QList safeAreaNameList; getSafeAreaNameList(safeAreaNameList); for (int i = 0; i < safeAreaNameList.size(); i++) { QAction *action = new QAction(safeAreaNameList.at(i), this); action->setData(safeAreaNameList.at(i)); connect(action, SIGNAL(triggered()), this, SLOT(onSetSafeArea())); if (safeAreaNameList.at(i) == QString::fromStdString(EnvSafeAreaName)) { action->setCheckable(true); action->setChecked(true); } menu.addAction(action); } menu.exec(e->globalPos()); } //----------------------------------------------------------------------------- void TPanelTitleBarButtonForSafeArea::onSetSafeArea() { QString safeAreaName = qobject_cast(sender())->data().toString(); // change safearea if the different one is selected if (QString::fromStdString(EnvSafeAreaName) != safeAreaName) { EnvSafeAreaName = safeAreaName.toStdString(); // emit sceneChanged without setting dirty flag TApp::instance()->getCurrentScene()->notifySceneChanged(false); } } //----------------------------------------------------------------------------- //============================================================================= // TPanelTitleBarButtonSet //----------------------------------------------------------------------------- TPanelTitleBarButtonSet::TPanelTitleBarButtonSet() {} TPanelTitleBarButtonSet::~TPanelTitleBarButtonSet() {} void TPanelTitleBarButtonSet::add(TPanelTitleBarButton *button) { m_buttons.push_back(button); } void TPanelTitleBarButtonSet::select(TPanelTitleBarButton *button) { int i; for (i = 0; i < (int)m_buttons.size(); i++) m_buttons[i]->setPressed(button == m_buttons[i]); emit selected(button->getId()); } //============================================================================= // PaneTitleBar //----------------------------------------------------------------------------- TPanelTitleBar::TPanelTitleBar(QWidget *parent, TDockWidget::Orientation orientation) : QFrame(parent), m_isActive(true), m_closeButtonHighlighted(false) { setMouseTracking(true); setFocusPolicy(Qt::NoFocus); } //----------------------------------------------------------------------------- void TPanelTitleBar::setIsActive(bool value) { if (m_isActive == value) return; m_isActive = value; } //----------------------------------------------------------------------------- QSize TPanelTitleBar::minimumSizeHint() const { return QSize(20, 18); } //----------------------------------------------------------------------------- void TPanelTitleBar::paintEvent(QPaintEvent *) { QPainter painter(this); QRect rect = this->rect(); bool isPanelActive; TPanel *dw = qobject_cast(parentWidget()); Q_ASSERT(dw != 0); // docked panel if (!dw->isFloating()) { isPanelActive = dw->widgetInThisPanelIsFocused(); qDrawBorderPixmap(&painter, rect, QMargins(3, 3, 3, 3), (isPanelActive) ? m_activeBorderPm : m_borderPm); } // floating panel else { isPanelActive = isActiveWindow(); qDrawBorderPixmap( &painter, rect, QMargins(3, 3, 3, 3), (isPanelActive) ? m_floatActiveBorderPm : m_floatBorderPm); } if (dw->getOrientation() == TDockWidget::vertical) { QString titleText = painter.fontMetrics().elidedText( dw->windowTitle(), Qt::ElideRight, rect.width() - 50); painter.setBrush(Qt::NoBrush); painter.setPen(isPanelActive ? m_activeTitleColor : m_titleColor); painter.drawText(QPointF(10, 15), titleText); } if (dw->isFloating()) { const static QPixmap closeButtonPixmap( svgToPixmap(":/Resources/pane_close.svg", QSize(18, 18))); const static QPixmap closeButtonPixmapOver( svgToPixmap(":/Resources/pane_close_rollover.svg", QSize(18, 18))); QPoint closeButtonPos(rect.right() - 18, rect.top() + 1); if (m_closeButtonHighlighted) painter.drawPixmap(closeButtonPos, closeButtonPixmapOver); else painter.drawPixmap(closeButtonPos, closeButtonPixmap); } painter.end(); } //----------------------------------------------------------------------------- void TPanelTitleBar::mousePressEvent(QMouseEvent *event) { TDockWidget *dw = static_cast(parentWidget()); QPoint pos = event->pos(); if (dw->isFloating()) { QRect rect = this->rect(); QRect closeButtonRect(rect.right() - 18, rect.top() + 1, 18, 18); if (closeButtonRect.contains(pos) && dw->isFloating()) { event->accept(); dw->hide(); m_closeButtonHighlighted = false; emit closeButtonPressed(); return; } } event->ignore(); } //----------------------------------------------------------------------------- void TPanelTitleBar::mouseMoveEvent(QMouseEvent *event) { TDockWidget *dw = static_cast(parentWidget()); if (dw->isFloating()) { QPoint pos = event->pos(); QRect rect = this->rect(); QRect closeButtonRect(rect.right() - 18, rect.top() + 1, 18, 18); if (closeButtonRect.contains(pos) && dw->isFloating()) m_closeButtonHighlighted = true; else m_closeButtonHighlighted = false; } update(); event->ignore(); } //----------------------------------------------------------------------------- void TPanelTitleBar::mouseDoubleClickEvent(QMouseEvent *me) { emit doubleClick(me); me->ignore(); } //----------------------------------------------------------------------------- void TPanelTitleBar::add(const QPoint &pos, QWidget *widget) { m_buttons.push_back(std::make_pair(pos, widget)); } //----------------------------------------------------------------------------- void TPanelTitleBar::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); int i; for (i = 0; i < (int)m_buttons.size(); i++) { QPoint p = m_buttons[i].first; QWidget *w = m_buttons[i].second; if (p.x() < 0) p.setX(p.x() + width()); w->move(p); } } //============================================================================= // TPanelFactory //----------------------------------------------------------------------------- TPanelFactory::TPanelFactory(QString panelType) : m_panelType(panelType) { assert(tableInstance().count(panelType) == 0); tableInstance()[m_panelType] = this; } //----------------------------------------------------------------------------- TPanelFactory::~TPanelFactory() { tableInstance().remove(m_panelType); } //----------------------------------------------------------------------------- QMap &TPanelFactory::tableInstance() { static QMap table; return table; } //----------------------------------------------------------------------------- TPanel *TPanelFactory::createPanel(QWidget *parent, QString panelType) { TPanel *panel = 0; QMap::iterator it = tableInstance().find(panelType); if (it == tableInstance().end()) { TPanel *panel = new TPanel(parent); panel->setPanelType(panelType.toStdString()); return panel; } else { TPanelFactory *factory = it.value(); TPanel *panel = factory->createPanel(parent); panel->setPanelType(panelType.toStdString()); return panel; } } //----------------------------------------------------------------------------- TPanel *TPanelFactory::createPanel(QWidget *parent) { TPanel *panel = new TPanel(parent); panel->setObjectName(getPanelType()); panel->setWindowTitle(getPanelType()); initialize(panel); return panel; } //-----------------------------------------------------------------------------