[win] add native buttons to window titile from web editor

This commit is contained in:
Maxim Kadushkin
2019-10-04 16:52:26 +03:00
parent ff95c3ef1b
commit e71eb3865a
15 changed files with 276 additions and 32 deletions

View File

@ -67,7 +67,8 @@ HEADERS += \
$$PWD/src/ceditorwindow_p.h \
$$PWD/src/ceditortools.h \
$$PWD/src/cwindowsqueue.h \
$$PWD/src/ceventdriver.h
$$PWD/src/ceventdriver.h \
$$PWD/src/csvgpushbutton.h
# src/ctabbar_p.h \
# src/ctabstyle.h \
# src/ctabstyle_p.h
@ -102,7 +103,8 @@ SOURCES += \
$$PWD/src/ceditorwindow.cpp \
$$PWD/src/ccefeventsgate.cpp \
$$PWD/src/ceditortools.cpp \
$$PWD/src/ceventdriver.cpp
$$PWD/src/ceventdriver.cpp \
$$PWD/src/csvgpushbutton.cpp
# src/ctabstyle.cpp
# src/casclabel.cpp

View File

@ -147,21 +147,17 @@ CAscTabWidget::CAscTabWidget(QWidget *parent)
QObject::connect(this, &QTabWidget::currentChanged, [=](){
updateIcons();
setFocusedView();
m_dragIndex = -1;
});
QObject::connect(tabs, &CTabBar::tabUndock, [=](int index){
if ( m_dragIndex != index ) {
CTabPanel * _panel = panel(index);
CTabPanel * _panel = panel(index);
if ( _panel->data()->viewType() == cvwtEditor ) {
CTabUndockEvent event(index);
QObject * obj = qobject_cast<QObject *>(
static_cast<CAscApplicationManagerWrapper *>(&AscAppManager::getInstance()));
if ( QApplication::sendEvent(obj, &event) && event.isAccepted() ) {
if ( _panel->data()->viewType() == cvwtEditor ) {
CTabUndockEvent event(index);
QObject * obj = qobject_cast<QObject *>(
static_cast<CAscApplicationManagerWrapper *>(&AscAppManager::getInstance()));
if ( QApplication::sendEvent(obj, &event) && event.isAccepted() ) {
m_dragIndex = index;
}
}
}
});

View File

@ -127,8 +127,6 @@ private:
bool m_isCustomStyle;
CTabIconSet m_mapTabIcons;
QSize m_tabIconSize;
int m_dragIndex = -1;
signals:
// void sendAddEditor();

View File

@ -322,6 +322,13 @@ bool CAscApplicationManagerWrapper::processCommonEvent(NSEditorApi::CAscCefMenuE
return true;
} else
if ( cmd.compare(L"title:changed") == 0 ) {
map<int, CCefEventsGate *>::const_iterator it = m_receivers.find(event->get_SenderId());
if ( it != m_receivers.cend() ) {
QMetaObject::invokeMethod(it->second, "onWebTitleChanged", Qt::QueuedConnection, Q_ARG(int, event->get_SenderId()), Q_ARG(std::wstring, pData->get_Param()));
return true;
}
} else
if ( !(cmd.find(L"go:folder") == std::wstring::npos) ) {
if ( pData->get_Param() == L"offline" ) {}
else {
@ -1034,7 +1041,7 @@ bool CAscApplicationManagerWrapper::event(QEvent *event)
QRect rect = _main_window->windowRect();
CEditorWindow * editor_win = new CEditorWindow(QRect(rect.left() + 150, rect.top() + 50, rect.width(), rect.height()), _editor);
editor_win->show(_main_window->isMaximized());
editor_win->show(_main_window->isMaximized(), true);
m_vecEditors.push_back( size_t(editor_win) );
}

View File

@ -71,6 +71,8 @@ public slots:
virtual void onEditorAllowedClose(int) = 0;
virtual void onKeyDown(void *);
virtual void onFullScreen(int id, bool apply) = 0;
virtual void onWebTitleChanged(int, std::wstring json) = 0;
};
#endif // CCEFEVENTSGATE_H

View File

@ -150,6 +150,14 @@ bool CEditorWindow::holdView(const wstring& portal) const
return qobject_cast<CTabPanel *>(m_pMainView)->data()->url().find(portal) != wstring::npos;
}
void CEditorWindow::show(bool maximaized, bool capturemouse)
{
CSingleWindowPlatform::show(maximaized);
if ( !maximaized && capturemouse )
CSingleWindowPlatform::captureMouse();
}
int CEditorWindow::closeWindow()
{
d_ptr.get()->onFullScreen(false);
@ -353,7 +361,7 @@ void CEditorWindow::recalculatePlaces()
// if ( contentH < 1 ) contentH = 1;
// int nCaptionR = 200;
int nCaptionL = d_ptr.get()->titleLeftOffset * m_dpiRatio;
int nCaptionL = 0 /*d_ptr.get()->titleLeftOffset * m_dpiRatio*/;
QSize _s{TOOLBTN_WIDTH * 3, TOOLBTN_HEIGHT};
_s *= m_dpiRatio;
@ -368,7 +376,7 @@ void CEditorWindow::recalculatePlaces()
// m_pMainView->setGeometry(cbw, captionH + cbw, windowW, contentH);
QRegion reg(0, captionH, windowW, windowH - captionH);
reg = reg.united(QRect(0, 0, nCaptionL, captionH));
// reg = reg.united(QRect(0, 0, nCaptionL, captionH));
// reg = reg.united(QRect(windowW - nCaptionR, 0, nCaptionR, captionH));
m_pMainView->clearMask();
m_pMainView->setMask(reg);

View File

@ -55,6 +55,7 @@ public:
bool holdView(int id) const override;
bool holdView(const wstring& portal) const;
void show(bool maximaized, bool capturemouse = false);
int closeWindow();
CTabPanel * mainView() const;
CTabPanel * releaseEditorView() const;

View File

@ -43,10 +43,12 @@
#include "cmessage.h"
#include "qascprinter.h"
#include "ceditortools.h"
#include "csvgpushbutton.h"
#include <QPrinterInfo>
#include <QDesktopWidget>
#include <QJsonDocument>
#include <QJsonArray>
#ifdef _WIN32
#include "win/cprintdialog.h"
@ -73,18 +75,48 @@ class CEditorWindowPrivate : public CCefEventsGate
QPushButton * btndock = nullptr;
bool isPrinting = false;
QMap<QString, CSVGPushButton*> m_mapTitleButtons;
public:
int titleLeftOffset = 168;
int titleLeftOffset = 0;
bool isReporterMode = false;
public:
CEditorWindowPrivate(CEditorWindow * w) : window(w)
{}
QPushButton * cloneEditorHeaderButton(const QJsonObject& jsonobj)
{
QString action = jsonobj["action"].toString();
CSVGPushButton * btn = new CSVGPushButton;
btn->setProperty("class", "normal");
btn->setProperty("act", "tool");
btn->setFixedSize(jsonobj["width"].toInt(40)*window->m_dpiRatio,jsonobj["height"].toInt(28)*window->m_dpiRatio);
btn->setDisabled(jsonobj["disabled"].toBool());
btn->setIconSize(QSize(20,20) * window->m_dpiRatio);
m_mapTitleButtons[action] = btn;
connect(btn, &QPushButton::clicked, [=]{
QJsonObject _json_obj{{"action", action}};
AscAppManager::sendCommandTo(panel()->cef(), L"button:click", Utils::encodeJson(_json_obj).toStdWString());
});
if ( jsonobj.contains("icon") ) {
QString _si = jsonobj["icon"].toString();
if (!_si.isEmpty() && _si.contains(QRegularExpression("^svg://"))) {
btn->setIcon( QByteArray::fromBase64(_si.mid(6).toLocal8Bit()) );
}
}
btn->setToolTip(jsonobj["hint"].toString());
return btn;
}
void onEditorConfig(int, std::wstring cfg)
{
// if ( id == window->holdView(id) )
QJsonParseError jerror;
QJsonDocument jdoc = QJsonDocument::fromJson(QString::fromStdWString(cfg).toUtf8(), &jerror);
if( jerror.error == QJsonParseError::NoError ) {
@ -94,13 +126,21 @@ public:
iconuser->setToolTip(objRoot["user"].toObject().value("name").toString());
}
if ( objRoot.contains("extraleft") ) {
titleLeftOffset = objRoot["extraleft"].toInt();
if ( objRoot.contains("title") ) {
QJsonArray _btns = objRoot["title"].toObject().value("buttons").toArray();
int diffW = (titleLeftOffset - (TOOLBTN_WIDTH * 5)) * window->m_dpiRatio; // 5 right tool buttons: close, min, max, drop, user icon
QString _label_styles = diffW > 0 ? QString("padding:0 %1px 0 0;").arg(diffW) : QString("padding:0 0 0 %1px;").arg(abs(diffW));
window->m_labelTitle->setStyleSheet(_label_styles);
QPushButton * _btn;
for (int i = _btns.size(); i --> 0; ) {
_btn = cloneEditorHeaderButton(_btns.at(i).toObject());
qobject_cast<QHBoxLayout *>(window->m_boxTitleBtns->layout())->insertWidget(0, _btn);
titleLeftOffset += _btn->width();
}
}
int diffW = (titleLeftOffset - (TOOLBTN_WIDTH * 4)) * window->m_dpiRatio; // 4 right tool buttons: close, min, max, user icon
QString _label_styles = diffW > 0 ? QString("padding:0 %1px 0 0;").arg(diffW) : QString("padding:0 0 0 %1px;").arg(abs(diffW));
window->m_labelTitle->setStyleSheet(_label_styles);
}
}
@ -256,6 +296,11 @@ public:
if ( btndock )
btndock->setFixedSize(QSize(TOOLBTN_WIDTH*f, TOOLBTN_HEIGHT*f));
for (auto btn: m_mapTitleButtons) {
btn->setFixedSize(QSize(TOOLBTN_WIDTH*f, TOOLBTN_HEIGHT*f));
btn->setIconSize(QSize(20,20) * f);
}
}
void onFullScreen(bool apply)
@ -375,6 +420,20 @@ public:
return btndock;
}
void onWebTitleChanged(int, std::wstring json)
{
QJsonParseError jerror;
QJsonDocument jdoc = QJsonDocument::fromJson(QString::fromStdWString(json).toUtf8(), &jerror);
if( jerror.error == QJsonParseError::NoError ) {
QJsonObject objRoot = jdoc.object();
QString action = objRoot["button"].toString();
if ( !action.isEmpty() && m_mapTitleButtons.contains(action) ) {
m_mapTitleButtons[action]->setDisabled(objRoot["disabled"].toBool(false));
}
}
}
};
#endif // CEDITORWINDOW_P_H

View File

@ -145,6 +145,7 @@ public slots:
void onOutsideAuth(QString);
void onEditorAllowedClose(int);
void onWebTitleChanged(int, std::wstring json){}
void onFileChecked(const QString&, int, bool);

View File

@ -0,0 +1,85 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "csvgpushbutton.h"
#include <QtSvg>
#include <QSvgRenderer>
#include <QPainter>
#include <QDebug>
CSVGPushButton::CSVGPushButton(QWidget * parent)
: QPushButton(parent)
{
}
void CSVGPushButton::setIcon(const QByteArray& svgstr)
{
m_svglayout = svgstr;
updateIcon();
}
void CSVGPushButton::setIconSize(const QSize& size)
{
QPushButton::setIconSize(size);
updateIcon();
}
void CSVGPushButton::setDisabled(bool status)
{
QPushButton::setDisabled(status);
updateIcon();
}
void CSVGPushButton::updateIcon()
{
if ( !m_svglayout.isEmpty() ) {
QSize size = iconSize();
QImage img(size, QImage::Format_ARGB32);
img.fill(Qt::transparent);
QPixmap pixmap = QPixmap::fromImage(img, Qt::NoFormatConversion);
qDebug() << "update icon: " << size;
QPainter painter(&pixmap);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
QSvgRenderer r(m_svglayout);
r.render(&painter, QRect(QPoint(0,0),size));
if ( !isEnabled() ) {
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.fillRect(pixmap.rect(), QColor(255,255,255,150));
painter.end();
}
QPushButton::setIcon(QIcon(pixmap));
}
}

View File

@ -0,0 +1,54 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#ifndef CSVGPUSHBUTTON_H
#define CSVGPUSHBUTTON_H
#include <QPushButton>
class CSVGPushButton : public QPushButton
{
public:
CSVGPushButton(QWidget * parent = nullptr);
void setIcon(const QByteArray&);
void setIconSize(const QSize&);
void setDisabled(bool);
private:
QByteArray m_svglayout;
void updateIcon();
using QPushButton::setDisabled;
};
#endif // CSVGPUSHBUTTON_H

View File

@ -334,10 +334,16 @@ void CTabBar::mousePressEvent(QMouseEvent * e)
{
if ( e->button() == Qt::LeftButton ) {
QTabBar::mousePressEvent(e);
if ( count() == 1 ) e->ignore();
// if ( count() == 1 ) e->ignore();
} else e->ignore();
}
void CTabBar::mouseReleaseEvent(QMouseEvent * e)
{
QTabBar::mouseReleaseEvent(e);
releaseMouse();
}
void CTabBar::drawTabCaption(QPainter * p, const QString& s, const QStyleOptionTab& t)
{
if ( m_usePalette ) {

View File

@ -68,8 +68,9 @@ public:
protected:
bool event(QEvent * e);
void mousePressEvent (QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent (QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
void mouseReleaseEvent (QMouseEvent *) override;
void paintEvent(QPaintEvent *);
void tabInserted(int);
void tabRemoved(int index);

View File

@ -120,14 +120,37 @@ LRESULT CALLBACK CSingleWindowPlatform::WndProc(HWND hWnd, UINT message, WPARAM
}
case WM_ACTIVATE: {
static bool is_mainwindow_prev;
is_mainwindow_prev = false;
if ( !IsWindowEnabled(hWnd) && window->m_modalHwnd > 0 && window->m_modalHwnd != hWnd )
{
if ( LOWORD(wParam) != WA_INACTIVE ) {
SetWindowPos(hWnd, window->m_modalHwnd, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
return 0;
}
}
} else {
if ( LOWORD(wParam) != WA_INACTIVE ) {
static HWND top_window;
top_window = NULL;
EnumWindows([](HWND hw, LPARAM lp){
if (!IsWindowVisible(hw) || GetWindowTextLength(hw) == 0) {
return TRUE;
}
if (hw == (HWND)lp) {
top_window = hw;
} else
if ( top_window ) {
top_window = NULL;
if ( hw == AscAppManager::topWindow()->handle() )
is_mainwindow_prev = true;
}
return TRUE;
}, (LPARAM)hWnd);
}
}
break;
}
@ -341,9 +364,6 @@ void CSingleWindowPlatform::show(bool maximized)
ShowWindow(m_hWnd, maximized ? SW_MAXIMIZE : SW_SHOW);
// UpdateWindow(m_hWnd);
m_visible = true;
if ( !maximized && GetCapture() != NULL )
captureMouse();
}
void CSingleWindowPlatform::hide()

View File

@ -879,7 +879,11 @@ void CMainWindow::captureMouse(int tabindex)
QPoint gpt = mainPanel()->tabWidget()->tabBar()->mapToGlobal(spt);
SetCursorPos(gpt.x(), gpt.y());
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(gpt.x(), gpt.y()));
QTimer::singleShot(0,[=] {
QMouseEvent event(QEvent::MouseButtonPress, spt, Qt::LeftButton, Qt::MouseButton::NoButton, Qt::NoModifier);
QCoreApplication::sendEvent((QWidget *)mainPanel()->tabWidget()->tabBar(), &event);
mainPanel()->tabWidget()->tabBar()->grabMouse();
});
}
}