From 7b479b4019c36c8a738317dabf6539e6eb04d77e Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 9 May 2022 10:39:32 +0800 Subject: [PATCH] fix: on windows, if DSView move's out off screen, it maybe can not restore success --- DSView/pv/data/logicsnapshot.cpp | 95 ++- DSView/pv/mainframe.cpp | 1051 +++++++++++++++--------------- 2 files changed, 595 insertions(+), 551 deletions(-) diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index cb3b41f8..85aa7f42 100755 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -155,6 +155,7 @@ void LogicSnapshot::first_payload(const sr_datafeed_logic &logic, uint64_t total for (const GSList *l = channels; l; l = l->next) { sr_channel *const probe = (sr_channel*)l->data; assert(probe); + if (probe->type == SR_CHANNEL_LOGIC) { channel_num += probe->enabled; if (!channel_changed && probe->enabled) { @@ -168,6 +169,9 @@ void LogicSnapshot::first_payload(const sr_datafeed_logic &logic, uint64_t total || channel_changed) { free_data(); + + _ch_index.clear(); + _total_sample_count = total_sample_count; _channel_num = channel_num; uint64_t rootnode_count = (_total_sample_count + RootNodeSamples - 1) / RootNodeSamples; @@ -396,64 +400,87 @@ void LogicSnapshot::append_split_payload(const sr_datafeed_logic &logic) uint16_t order = logic.order; assert(order < _ch_data.size()); - if (_sample_cnt[order] >= _total_sample_count) + uint64_t sample_read_num = _sample_cnt[order]; + uint64_t write_block_num = _block_cnt[order]; + + if (sample_read_num >= _total_sample_count) return; - if (_sample_cnt[order] + samples < _total_sample_count) { - _sample_cnt[order] += samples; + if (sample_read_num + samples < _total_sample_count) { + sample_read_num += samples; } else { - samples = _total_sample_count - _sample_cnt[order]; - _sample_cnt[order] = _total_sample_count; + samples = _total_sample_count - sample_read_num; + sample_read_num = _total_sample_count; } - while (_sample_cnt[order] > _block_cnt[order] * LeafBlockSamples) { - uint8_t index0 = _block_cnt[order] / RootScale; - uint8_t index1 = _block_cnt[order] % RootScale; + _sample_cnt[order] = sample_read_num; + + // make buffer + while (sample_read_num > write_block_num * LeafBlockSamples) { + uint8_t index0 = write_block_num / RootScale; + uint8_t index1 = write_block_num % RootScale; - if (_ch_data[order][index0].lbp[index1] == NULL) - _ch_data[order][index0].lbp[index1] = malloc(LeafBlockSpace); + void *pbuf = _ch_data[order][index0].lbp[index1]; - if (_ch_data[order][index0].lbp[index1] == NULL) { - _memory_failed = true; - return; - } + if (pbuf == NULL){ + pbuf = malloc(LeafBlockSpace); - memset(_ch_data[order][index0].lbp[index1], 0, LeafBlockSpace); - _block_cnt[order]++; + if (pbuf == NULL){ + _memory_failed = true; + return; + } + + _ch_data[order][index0].lbp[index1] = pbuf; + } + + memset(pbuf, 0, LeafBlockSpace); + write_block_num++; } + + _block_cnt[order] = write_block_num; - while(samples > 0) { - const uint64_t index0 = _ring_sample_cnt[order] / RootNodeSamples; - const uint64_t index1 = (_ring_sample_cnt[order] >> LeafBlockPower) % RootScale; - const uint64_t offset = (_ring_sample_cnt[order] % LeafBlockSamples) / 8; + uint64_t ring_sample_num = _ring_sample_cnt[order]; + + while(samples > 0) + { + const uint64_t index0 = ring_sample_num / RootNodeSamples; + const uint64_t index1 = (ring_sample_num >> LeafBlockPower) % RootScale; + const uint64_t offset = (ring_sample_num % LeafBlockSamples) / 8; _dest_ptr = (uint8_t *)_ch_data[order][index0].lbp[index1] + offset; - uint64_t bblank = (LeafBlockSamples - (_ring_sample_cnt[order] & LeafMask)); + uint64_t bblank = (LeafBlockSamples - (ring_sample_num & LeafMask)); + if (samples >= bblank) { memcpy((uint8_t*)_dest_ptr, (uint8_t *)logic.data, bblank/8); - _ring_sample_cnt[order] += bblank; + ring_sample_num += bblank; samples -= bblank; // calc mipmap of current block calc_mipmap(order, index0, index1, LeafBlockSamples); + void *pbuf = _ch_data[order][index0].lbp[index1]; + // calc root of current block - if (*((uint64_t *)_ch_data[order][index0].lbp[index1]) != 0) + if (*((uint64_t *)pbuf) != 0) _ch_data[order][index0].value += 1ULL<< index1; - if (*((uint64_t *)_ch_data[order][index0].lbp[index1] + LeafBlockSpace / sizeof(uint64_t) - 1) != 0) { + + if (*((uint64_t *)pbuf + LeafBlockSpace / sizeof(uint64_t) - 1) != 0) { _ch_data[order][index0].tog += 1ULL << index1; } else { // trim leaf to free space - free(_ch_data[order][index0].lbp[index1]); + free(pbuf); _ch_data[order][index0].lbp[index1] = NULL; } + } else { memcpy((uint8_t*)_dest_ptr, (uint8_t *)logic.data, samples/8); - _ring_sample_cnt[order] += samples; + ring_sample_num += samples; samples = 0; } } + _ring_sample_cnt[order] = ring_sample_num; + _sample_count = *min_element(_sample_cnt.begin(), _sample_cnt.end()); _ring_sample_count = *min_element(_ring_sample_cnt.begin(), _ring_sample_cnt.end()); } @@ -1114,16 +1141,14 @@ uint8_t *LogicSnapshot::get_block_buf(int block_index, int sig_index, bool &samp int LogicSnapshot::get_ch_order(int sig_index) { uint16_t order = 0; - for (auto& iter:_ch_index) { - if (iter == sig_index) - break; - order++; - } - if (order >= _ch_index.size()) - return -1; - else - return order; + for (auto iter:_ch_index) { + if (iter == sig_index) + return order; + order++; + } + + return -1; } } // namespace data diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index 229919b0..29c420e9 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -1,516 +1,535 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2016 DreamSourceLab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mainframe.h" - -#include "toolbars/titlebar.h" -#include "dialogs/dsmessagebox.h" -#include "dialogs/dsdialog.h" -#include "mainwindow.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dsvdef.h" -#include "config/appconfig.h" -#include "ui/msgbox.h" -#include "appcontrol.h" - -#include - -namespace pv { - -MainFrame::MainFrame() -{ - _layout = NULL; - _bDraging = false; - _hit_border = None; - _freezing = false; - _titleBar = NULL; - _mainWindow = NULL; - - AppControl::Instance()->SetTopWindow(this); - - setAttribute(Qt::WA_TranslucentBackground); - // Make this a borderless window which can't - // be resized or moved via the window system - #ifdef _WIN32 - setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint); - #else - setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); - #endif - - setMinimumHeight(minHeight); - setMinimumWidth(minWidth); - - // Set the window icon - QIcon icon; - icon.addFile(QString::fromUtf8(":/icons/logo.svg"), QSize(), QIcon::Normal, QIcon::Off); - setWindowIcon(icon); - - // Title - _titleBar = new toolbars::TitleBar(true, this); - - // MainWindow - _mainWindow = new MainWindow(this); - _mainWindow->setWindowFlags(Qt::Widget); - _titleBar->setTitle(_mainWindow->windowTitle()); - - QVBoxLayout *vbox = new QVBoxLayout(); - vbox->setContentsMargins(0,0,0,0); - vbox->setSpacing(0); - vbox->addWidget(_titleBar); - vbox->addWidget(_mainWindow); - - _top_left = new widgets::Border (TopLeft, this); - _top_left->setFixedSize(Margin, Margin); - _top_left->installEventFilter(this); - _top = new widgets::Border (Top, this); - _top->setFixedHeight(Margin); - _top->installEventFilter(this); - _top_right = new widgets::Border (TopRight, this); - _top_right->setFixedSize(Margin, Margin); - _top_right->installEventFilter(this); - - _left = new widgets::Border (Left, this); - _left->setFixedWidth(Margin); - _left->installEventFilter(this); - _right = new widgets::Border (Right, this); - _right->setFixedWidth(Margin); - _right->installEventFilter(this); - - _bottom_left = new widgets::Border (BottomLeft, this); - _bottom_left->setFixedSize(Margin, Margin); - _bottom_left->installEventFilter(this); - _bottom = new widgets::Border (Bottom, this); - _bottom->setFixedHeight(Margin); - _bottom->installEventFilter(this); - _bottom_right = new widgets::Border (BottomRight, this); - _bottom_right->setFixedSize(Margin, Margin); - _bottom_right->installEventFilter(this); - - _layout = new QGridLayout(this); - _layout->setSpacing(0); - _layout->setContentsMargins(0,0,0,0); - _layout->addWidget(_top_left, 0, 0); - _layout->addWidget(_top, 0, 1); - _layout->addWidget(_top_right, 0, 2); - _layout->addWidget(_left, 1, 0); - _layout->addLayout(vbox, 1, 1); - _layout->addWidget(_right, 1, 2); - _layout->addWidget(_bottom_left, 2, 0); - _layout->addWidget(_bottom, 2, 1); - _layout->addWidget(_bottom_right, 2, 2); - -#ifdef _WIN32 - _taskBtn = new QWinTaskbarButton(this); - connect(_mainWindow, SIGNAL(prgRate(int)), this, SLOT(setTaskbarProgress(int))); -#endif - - connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing())); -} - -void MainFrame::resizeEvent(QResizeEvent *event) -{ - QFrame::resizeEvent(event); - - if (_layout == NULL){ - return; - } - - if (isMaximized()) { - hide_border(); - } else { - show_border(); - } - _titleBar->setRestoreButton(isMaximized()); - _layout->update(); -} - -void MainFrame::closeEvent(QCloseEvent *event) -{ - writeSettings(); - _mainWindow->session_save(); - event->accept(); -} - -void MainFrame::unfreezing() -{ - _freezing = false; -} - -void MainFrame::hide_border() -{ - _top_left->setVisible(false); - _top_right->setVisible(false); - _top->setVisible(false); - _left->setVisible(false); - _right->setVisible(false); - _bottom_left->setVisible(false); - _bottom->setVisible(false); - _bottom_right->setVisible(false); -} - -void MainFrame::show_border() -{ - _top_left->setVisible(true); - _top_right->setVisible(true); - _top->setVisible(true); - _left->setVisible(true); - _right->setVisible(true); - _bottom_left->setVisible(true); - _bottom->setVisible(true); - _bottom_right->setVisible(true); -} - -void MainFrame::showNormal() -{ - show_border(); - QFrame::showNormal(); -} - -void MainFrame::showMaximized() -{ - hide_border(); - QFrame::showMaximized(); -} - -void MainFrame::showMinimized() -{ - writeSettings(); - QFrame::showMinimized(); -} - -bool MainFrame::eventFilter(QObject *object, QEvent *event) -{ - const QEvent::Type type = event->type(); - const QMouseEvent *const mouse_event = (QMouseEvent*)event; - int newWidth; - int newHeight; - int newLeft; - int newTop; - - if (type != QEvent::MouseMove - && type != QEvent::MouseButtonPress - && type != QEvent::MouseButtonRelease - && type != QEvent::Leave){ - return QFrame::eventFilter(object, event); - } - - //when window is maximized, or is moving, call return - if (isMaximized() || _titleBar->IsMoving()){ - return QFrame::eventFilter(object, event); - } - - if (!_bDraging && type == QEvent::MouseMove && (!(mouse_event->buttons() | Qt::NoButton))){ - if (object == _top_left) { - _hit_border = TopLeft; - setCursor(Qt::SizeFDiagCursor); - } else if (object == _bottom_right) { - _hit_border = BottomRight; - setCursor(Qt::SizeFDiagCursor); - } else if (object == _top_right) { - _hit_border = TopRight; - setCursor(Qt::SizeBDiagCursor); - } else if (object == _bottom_left) { - _hit_border = BottomLeft; - setCursor(Qt::SizeBDiagCursor); - } else if (object == _left) { - _hit_border = Left; - setCursor(Qt::SizeHorCursor); - } else if (object == _right) { - _hit_border = Right; - setCursor(Qt::SizeHorCursor); - } else if (object == _bottom) { - _hit_border = Bottom; - setCursor(Qt::SizeVerCursor); - } else if (object == _top) { - _hit_border = Top; - setCursor(Qt::SizeVerCursor); - } else { - _hit_border = None; - setCursor(Qt::ArrowCursor); - } - - return QFrame::eventFilter(object, event); - } - - if (type == QEvent::MouseMove) { - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - int x0 = (int)mouse_event->globalPosition().x(); - int y0 = (int)mouse_event->globalPosition().y(); -#else - int x0 = mouse_event->globalX(); - int y0 = mouse_event->globalY(); -#endif - - if(mouse_event->buttons().testFlag(Qt::LeftButton)) { - if (!_freezing) { - switch (_hit_border) { - case TopLeft: - newWidth = std::max(_dragStartGeometry.right() - x0, minimumWidth()); - newHeight = std::max(_dragStartGeometry.bottom() - y0, minimumHeight()); - newLeft = geometry().left(); - newTop = geometry().top(); - if (newWidth > minimumWidth()) - newLeft = x0; - if (newHeight > minimumHeight()) - newTop = y0; - setGeometry(newLeft, newTop, newWidth, newHeight); - saveWindowRegion(); - break; - - case BottomLeft: - newWidth = std::max(_dragStartGeometry.right() - x0, minimumWidth()); - newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight()); - newLeft = geometry().left(); - if (newWidth > minimumWidth()) - newLeft = x0; - setGeometry(newLeft, _dragStartGeometry.top(), newWidth, newHeight); - saveWindowRegion(); - break; - - case TopRight: - newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth()); - newHeight = std::max(_dragStartGeometry.bottom() - y0, minimumHeight()); - newTop = geometry().top(); - if (newHeight > minimumHeight()) - newTop = y0; - setGeometry(_dragStartGeometry.left(), newTop, newWidth, newHeight); - saveWindowRegion(); - break; - - case BottomRight: - newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth()); - newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight()); - setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, newHeight); - saveWindowRegion(); - break; - - case Left: - newWidth = _dragStartGeometry.right() - x0; - if (newWidth > minimumWidth()){ - setGeometry(x0, _dragStartGeometry.top(), newWidth, height()); - saveWindowRegion(); - } - break; - - case Right: - newWidth = x0 - _dragStartGeometry.left(); - if (newWidth > minimumWidth()){ - setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, height()); - saveWindowRegion(); - } - break; - - case Top: - newHeight = _dragStartGeometry.bottom() - y0; - if (newHeight > minimumHeight()){ - setGeometry(_dragStartGeometry.left(), y0,width(), newHeight); - saveWindowRegion(); - } - break; - - case Bottom: - newHeight = y0 - _dragStartGeometry.top(); - if (newHeight > minimumHeight()){ - setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), width(), newHeight); - saveWindowRegion(); - } - break; - - default: - break; - } - _freezing = true; - } - return true; - } - } - else if (type == QEvent::MouseButtonPress) { - if (mouse_event->button() == Qt::LeftButton) - if (_hit_border != None) - _bDraging = true; - _timer.start(50); - _dragStartGeometry = geometry(); - } - else if (type == QEvent::MouseButtonRelease) { - if (mouse_event->button() == Qt::LeftButton) { - _bDraging = false; - _timer.stop(); - } - } else if (!_bDraging && type == QEvent::Leave) { - _hit_border = None; - setCursor(Qt::ArrowCursor); - } - - - return QFrame::eventFilter(object, event); -} - - void MainFrame::saveWindowRegion() - { - AppConfig &app = AppConfig::Instance(); - QRect rc = geometry(); - app._frameOptions.left = rc.left(); - app._frameOptions.top = rc.top(); - app._frameOptions.right = rc.right(); - app._frameOptions.bottom = rc.bottom(); - } - -void MainFrame::writeSettings() -{ - AppConfig &app = AppConfig::Instance(); - app._frameOptions.isMax = isMaximized(); - - if (!isMaximized()){ - saveWindowRegion(); - } - - app.SaveFrame(); -} - -void MainFrame::readSettings() -{ - if (_layout == NULL) - return; - - AppConfig &app = AppConfig::Instance(); - - if (app._frameOptions.language > 0){ - _mainWindow->switchLanguage(app._frameOptions.language); - } - - if (app._frameOptions.right == 0) { - QScreen *screen=QGuiApplication::primaryScreen (); - const QRect availableGeometry = screen->availableGeometry(); - resize(availableGeometry.width() / 2, availableGeometry.height() / 1.5); - const int origX = std::max(0, (availableGeometry.width() - width()) / 2); - const int origY = std::max(0, (availableGeometry.height() - height()) / 2); - move(origX, origY); - - } else { - if (app._frameOptions.isMax){ - showMaximized(); //show max by system api - } - else{ - int left = app._frameOptions.left; - int top = app._frameOptions.top; - int right = app._frameOptions.right; - int bottom = app._frameOptions.bottom; - resize(right-left, bottom-top); - move(left, top); - } - } - - // restore dockwidgets - _mainWindow->restore_dock(); - _titleBar->setRestoreButton(app._frameOptions.isMax); -} - -#ifdef _WIN32 -void MainFrame::showEvent(QShowEvent *event) -{ - // Taskbar Progress Effert for Win7 and Above - if (_taskBtn->window() == NULL) { - _taskBtn->setWindow(windowHandle()); - _taskPrg = _taskBtn->progress(); - } - event->accept(); -} -#endif - -void MainFrame::setTaskbarProgress(int progress) -{ -#ifdef _WIN32 - if (progress > 0) { - _taskPrg->setVisible(true); - _taskPrg->setValue(progress); - } else { - _taskPrg->setVisible(false); - } -#else - (void)progress; -#endif -} - -void MainFrame::show_doc() -{ - AppConfig &app = AppConfig::Instance(); - int lan = app._frameOptions.language; - - if (app._userHistory.showDocuments) { - dialogs::DSDialog dlg(this, true); - dlg.setTitle(tr("Document")); - - QString path = GetAppDataDir() + "/showDoc" + QString::number(lan)+ ".png"; - if (!QFile::exists(path)){ - path = ":/icons/showDoc"+QString::number(lan)+".png"; - } - - QLabel tipsLabel; - tipsLabel.setPixmap(path); - - QMessageBox msg; - msg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); - msg.setContentsMargins(0, 0, 0, 0); - - QPushButton *noMoreButton = msg.addButton(tr("Not Show Again"), QMessageBox::ActionRole); - msg.addButton(tr("Ignore"), QMessageBox::ActionRole); - QPushButton *openButton = msg.addButton(tr("Open"), QMessageBox::ActionRole); - - QVBoxLayout layout; - layout.addWidget(&tipsLabel); - layout.addWidget(&msg, 0, Qt::AlignRight); - layout.setContentsMargins(0, 0, 0, 0); - - dlg.layout()->addLayout(&layout); - connect(&msg, SIGNAL(buttonClicked(QAbstractButton*)), &dlg, SLOT(accept())); - - dlg.exec(); - - if (msg.clickedButton() == openButton) { - _mainWindow->openDoc(); - } - if (msg.clickedButton() == noMoreButton){ - app._userHistory.showDocuments = false; - app.SaveHistory(); - } - } -} - -} // namespace pv +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2016 DreamSourceLab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mainframe.h" + +#include "toolbars/titlebar.h" +#include "dialogs/dsmessagebox.h" +#include "dialogs/dsdialog.h" +#include "mainwindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dsvdef.h" +#include "config/appconfig.h" +#include "ui/msgbox.h" +#include "appcontrol.h" + +#include + +namespace pv { + +MainFrame::MainFrame() +{ + _layout = NULL; + _bDraging = false; + _hit_border = None; + _freezing = false; + _titleBar = NULL; + _mainWindow = NULL; + + AppControl::Instance()->SetTopWindow(this); + + setAttribute(Qt::WA_TranslucentBackground); + // Make this a borderless window which can't + // be resized or moved via the window system + #ifdef _WIN32 + setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint); + #else + setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); + #endif + + setMinimumHeight(minHeight); + setMinimumWidth(minWidth); + + // Set the window icon + QIcon icon; + icon.addFile(QString::fromUtf8(":/icons/logo.svg"), QSize(), QIcon::Normal, QIcon::Off); + setWindowIcon(icon); + + // Title + _titleBar = new toolbars::TitleBar(true, this); + + // MainWindow + _mainWindow = new MainWindow(this); + _mainWindow->setWindowFlags(Qt::Widget); + _titleBar->setTitle(_mainWindow->windowTitle()); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setContentsMargins(0,0,0,0); + vbox->setSpacing(0); + vbox->addWidget(_titleBar); + vbox->addWidget(_mainWindow); + + _top_left = new widgets::Border (TopLeft, this); + _top_left->setFixedSize(Margin, Margin); + _top_left->installEventFilter(this); + _top = new widgets::Border (Top, this); + _top->setFixedHeight(Margin); + _top->installEventFilter(this); + _top_right = new widgets::Border (TopRight, this); + _top_right->setFixedSize(Margin, Margin); + _top_right->installEventFilter(this); + + _left = new widgets::Border (Left, this); + _left->setFixedWidth(Margin); + _left->installEventFilter(this); + _right = new widgets::Border (Right, this); + _right->setFixedWidth(Margin); + _right->installEventFilter(this); + + _bottom_left = new widgets::Border (BottomLeft, this); + _bottom_left->setFixedSize(Margin, Margin); + _bottom_left->installEventFilter(this); + _bottom = new widgets::Border (Bottom, this); + _bottom->setFixedHeight(Margin); + _bottom->installEventFilter(this); + _bottom_right = new widgets::Border (BottomRight, this); + _bottom_right->setFixedSize(Margin, Margin); + _bottom_right->installEventFilter(this); + + _layout = new QGridLayout(this); + _layout->setSpacing(0); + _layout->setContentsMargins(0,0,0,0); + _layout->addWidget(_top_left, 0, 0); + _layout->addWidget(_top, 0, 1); + _layout->addWidget(_top_right, 0, 2); + _layout->addWidget(_left, 1, 0); + _layout->addLayout(vbox, 1, 1); + _layout->addWidget(_right, 1, 2); + _layout->addWidget(_bottom_left, 2, 0); + _layout->addWidget(_bottom, 2, 1); + _layout->addWidget(_bottom_right, 2, 2); + +#ifdef _WIN32 + _taskBtn = new QWinTaskbarButton(this); + connect(_mainWindow, SIGNAL(prgRate(int)), this, SLOT(setTaskbarProgress(int))); +#endif + + connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing())); +} + +void MainFrame::resizeEvent(QResizeEvent *event) +{ + QFrame::resizeEvent(event); + + if (_layout == NULL){ + return; + } + + if (isMaximized()) { + hide_border(); + } else { + show_border(); + } + _titleBar->setRestoreButton(isMaximized()); + _layout->update(); +} + +void MainFrame::closeEvent(QCloseEvent *event) +{ + writeSettings(); + _mainWindow->session_save(); + event->accept(); +} + +void MainFrame::unfreezing() +{ + _freezing = false; +} + +void MainFrame::hide_border() +{ + _top_left->setVisible(false); + _top_right->setVisible(false); + _top->setVisible(false); + _left->setVisible(false); + _right->setVisible(false); + _bottom_left->setVisible(false); + _bottom->setVisible(false); + _bottom_right->setVisible(false); +} + +void MainFrame::show_border() +{ + _top_left->setVisible(true); + _top_right->setVisible(true); + _top->setVisible(true); + _left->setVisible(true); + _right->setVisible(true); + _bottom_left->setVisible(true); + _bottom->setVisible(true); + _bottom_right->setVisible(true); +} + +void MainFrame::showNormal() +{ + show_border(); + QFrame::showNormal(); +} + +void MainFrame::showMaximized() +{ + hide_border(); + QFrame::showMaximized(); +} + +void MainFrame::showMinimized() +{ + writeSettings(); + QFrame::showMinimized(); +} + +bool MainFrame::eventFilter(QObject *object, QEvent *event) +{ + const QEvent::Type type = event->type(); + const QMouseEvent *const mouse_event = (QMouseEvent*)event; + int newWidth; + int newHeight; + int newLeft; + int newTop; + + if (type != QEvent::MouseMove + && type != QEvent::MouseButtonPress + && type != QEvent::MouseButtonRelease + && type != QEvent::Leave){ + return QFrame::eventFilter(object, event); + } + + //when window is maximized, or is moving, call return + if (isMaximized() || _titleBar->IsMoving()){ + return QFrame::eventFilter(object, event); + } + + if (!_bDraging && type == QEvent::MouseMove && (!(mouse_event->buttons() | Qt::NoButton))){ + if (object == _top_left) { + _hit_border = TopLeft; + setCursor(Qt::SizeFDiagCursor); + } else if (object == _bottom_right) { + _hit_border = BottomRight; + setCursor(Qt::SizeFDiagCursor); + } else if (object == _top_right) { + _hit_border = TopRight; + setCursor(Qt::SizeBDiagCursor); + } else if (object == _bottom_left) { + _hit_border = BottomLeft; + setCursor(Qt::SizeBDiagCursor); + } else if (object == _left) { + _hit_border = Left; + setCursor(Qt::SizeHorCursor); + } else if (object == _right) { + _hit_border = Right; + setCursor(Qt::SizeHorCursor); + } else if (object == _bottom) { + _hit_border = Bottom; + setCursor(Qt::SizeVerCursor); + } else if (object == _top) { + _hit_border = Top; + setCursor(Qt::SizeVerCursor); + } else { + _hit_border = None; + setCursor(Qt::ArrowCursor); + } + + return QFrame::eventFilter(object, event); + } + + if (type == QEvent::MouseMove) { + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + int x0 = (int)mouse_event->globalPosition().x(); + int y0 = (int)mouse_event->globalPosition().y(); +#else + int x0 = mouse_event->globalX(); + int y0 = mouse_event->globalY(); +#endif + + if(mouse_event->buttons().testFlag(Qt::LeftButton)) { + if (!_freezing) { + switch (_hit_border) { + case TopLeft: + newWidth = std::max(_dragStartGeometry.right() - x0, minimumWidth()); + newHeight = std::max(_dragStartGeometry.bottom() - y0, minimumHeight()); + newLeft = geometry().left(); + newTop = geometry().top(); + if (newWidth > minimumWidth()) + newLeft = x0; + if (newHeight > minimumHeight()) + newTop = y0; + setGeometry(newLeft, newTop, newWidth, newHeight); + saveWindowRegion(); + break; + + case BottomLeft: + newWidth = std::max(_dragStartGeometry.right() - x0, minimumWidth()); + newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight()); + newLeft = geometry().left(); + if (newWidth > minimumWidth()) + newLeft = x0; + setGeometry(newLeft, _dragStartGeometry.top(), newWidth, newHeight); + saveWindowRegion(); + break; + + case TopRight: + newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth()); + newHeight = std::max(_dragStartGeometry.bottom() - y0, minimumHeight()); + newTop = geometry().top(); + if (newHeight > minimumHeight()) + newTop = y0; + setGeometry(_dragStartGeometry.left(), newTop, newWidth, newHeight); + saveWindowRegion(); + break; + + case BottomRight: + newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth()); + newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight()); + setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, newHeight); + saveWindowRegion(); + break; + + case Left: + newWidth = _dragStartGeometry.right() - x0; + if (newWidth > minimumWidth()){ + setGeometry(x0, _dragStartGeometry.top(), newWidth, height()); + saveWindowRegion(); + } + break; + + case Right: + newWidth = x0 - _dragStartGeometry.left(); + if (newWidth > minimumWidth()){ + setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, height()); + saveWindowRegion(); + } + break; + + case Top: + newHeight = _dragStartGeometry.bottom() - y0; + if (newHeight > minimumHeight()){ + setGeometry(_dragStartGeometry.left(), y0,width(), newHeight); + saveWindowRegion(); + } + break; + + case Bottom: + newHeight = y0 - _dragStartGeometry.top(); + if (newHeight > minimumHeight()){ + setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), width(), newHeight); + saveWindowRegion(); + } + break; + + default: + break; + } + _freezing = true; + } + return true; + } + } + else if (type == QEvent::MouseButtonPress) { + if (mouse_event->button() == Qt::LeftButton) + if (_hit_border != None) + _bDraging = true; + _timer.start(50); + _dragStartGeometry = geometry(); + } + else if (type == QEvent::MouseButtonRelease) { + if (mouse_event->button() == Qt::LeftButton) { + _bDraging = false; + _timer.stop(); + } + } else if (!_bDraging && type == QEvent::Leave) { + _hit_border = None; + setCursor(Qt::ArrowCursor); + } + + + return QFrame::eventFilter(object, event); +} + + void MainFrame::saveWindowRegion() + { + AppConfig &app = AppConfig::Instance(); + QRect rc = geometry(); + app._frameOptions.left = rc.left(); + app._frameOptions.top = rc.top(); + app._frameOptions.right = rc.right(); + app._frameOptions.bottom = rc.bottom(); + } + +void MainFrame::writeSettings() +{ + AppConfig &app = AppConfig::Instance(); + app._frameOptions.isMax = isMaximized(); + + if (!isMaximized()){ + saveWindowRegion(); + } + + app.SaveFrame(); +} + +void MainFrame::readSettings() +{ + if (_layout == NULL) + return; + + AppConfig &app = AppConfig::Instance(); + + if (app._frameOptions.language > 0){ + _mainWindow->switchLanguage(app._frameOptions.language); + } + + int left = app._frameOptions.left; + int top = app._frameOptions.top; + int right = app._frameOptions.right; + int bottom = app._frameOptions.bottom; + + QRect scRect = QApplication::desktop()->screenGeometry(); + bool bReset = false; + + if (right == 0) + { + bReset = true; + } + if (right - left >= scRect.width()) + { + bReset = true; + } + int sp = 70; + if (right < sp || bottom < sp || left + sp >= scRect.width() || top + sp >= scRect.height()){ + bReset = true; + } + + if (app._frameOptions.isMax) + { + showMaximized(); // show max by system api + } + else if (bReset) + { + QScreen *screen = QGuiApplication::primaryScreen(); + const QRect availableGeometry = screen->availableGeometry(); + resize(availableGeometry.width() / 2, availableGeometry.height() / 1.5); + const int origX = std::max(0, (availableGeometry.width() - width()) / 2); + const int origY = std::max(0, (availableGeometry.height() - height()) / 2); + move(origX, origY); + } + else + { + resize(right - left, bottom - top); + move(left, top); + } + + // restore dockwidgets + _mainWindow->restore_dock(); + _titleBar->setRestoreButton(app._frameOptions.isMax); +} + +#ifdef _WIN32 +void MainFrame::showEvent(QShowEvent *event) +{ + // Taskbar Progress Effert for Win7 and Above + if (_taskBtn->window() == NULL) { + _taskBtn->setWindow(windowHandle()); + _taskPrg = _taskBtn->progress(); + } + event->accept(); +} +#endif + +void MainFrame::setTaskbarProgress(int progress) +{ +#ifdef _WIN32 + if (progress > 0) { + _taskPrg->setVisible(true); + _taskPrg->setValue(progress); + } else { + _taskPrg->setVisible(false); + } +#else + (void)progress; +#endif +} + +void MainFrame::show_doc() +{ + AppConfig &app = AppConfig::Instance(); + int lan = app._frameOptions.language; + + if (app._userHistory.showDocuments) { + dialogs::DSDialog dlg(this, true); + dlg.setTitle(tr("Document")); + + QString path = GetAppDataDir() + "/showDoc" + QString::number(lan)+ ".png"; + if (!QFile::exists(path)){ + path = ":/icons/showDoc"+QString::number(lan)+".png"; + } + + QLabel tipsLabel; + tipsLabel.setPixmap(path); + + QMessageBox msg; + msg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); + msg.setContentsMargins(0, 0, 0, 0); + + QPushButton *noMoreButton = msg.addButton(tr("Not Show Again"), QMessageBox::ActionRole); + msg.addButton(tr("Ignore"), QMessageBox::ActionRole); + QPushButton *openButton = msg.addButton(tr("Open"), QMessageBox::ActionRole); + + QVBoxLayout layout; + layout.addWidget(&tipsLabel); + layout.addWidget(&msg, 0, Qt::AlignRight); + layout.setContentsMargins(0, 0, 0, 0); + + dlg.layout()->addLayout(&layout); + connect(&msg, SIGNAL(buttonClicked(QAbstractButton*)), &dlg, SLOT(accept())); + + dlg.exec(); + + if (msg.clickedButton() == openButton) { + _mainWindow->openDoc(); + } + if (msg.clickedButton() == noMoreButton){ + app._userHistory.showDocuments = false; + app.SaveHistory(); + } + } +} + +} // namespace pv