mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-22 03:45:51 +08:00
copy just enough gstreamer plugins and handle deps for Windows build
- Added custom command to copy libZUpdater.dll for deployment - Updated win-deploy.cmake to copy specific GStreamer plugins - Introduced install scripts for Apple drivers and WinFsp - Improved DiagnoseWidget UI with scroll area and process indicators - Adjusted WelcomeWidget to include DiagnoseWidget on non-Apple platforms
This commit is contained in:
@@ -28,10 +28,6 @@
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "platform/windows/diagnose_widget.h"
|
||||
#endif
|
||||
|
||||
void handleCallback(const idevice_event_t *event, void *userData)
|
||||
{
|
||||
printf("Device event received: ");
|
||||
@@ -79,7 +75,6 @@ void handleCallback(const idevice_event_t *event, void *userData)
|
||||
default:
|
||||
qDebug() << "Unhandled event: " << event->event;
|
||||
}
|
||||
// return;
|
||||
}
|
||||
|
||||
void handleCallbackRecovery(const irecv_device_event_t *event, void *userData)
|
||||
@@ -117,10 +112,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
const QSize minSize(900, 600);
|
||||
setMinimumSize(minSize);
|
||||
resize(minSize);
|
||||
// TODO
|
||||
// setWindowIcon(QIcon(":/resources/icons/icon.png"));
|
||||
|
||||
// Create custom tab widget
|
||||
m_ZTabWidget = new ZTabWidget(this);
|
||||
m_ZTabWidget->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
|
||||
|
||||
@@ -131,31 +123,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
#endif
|
||||
setCentralWidget(m_ZTabWidget);
|
||||
|
||||
// Create device manager and stacked widget for main tab
|
||||
m_mainStackedWidget = new QStackedWidget();
|
||||
|
||||
// Welcome page (shown when no devices are connected)
|
||||
WelcomeWidget *welcomePage = new WelcomeWidget(this);
|
||||
// No devices page
|
||||
QWidget *noDevicesPage = new QWidget();
|
||||
QVBoxLayout *noDeviceLayout = new QVBoxLayout(noDevicesPage);
|
||||
noDeviceLayout->addStretch();
|
||||
QHBoxLayout *labelLayout = new QHBoxLayout();
|
||||
labelLayout->addStretch();
|
||||
QLabel *noDeviceLabel = new QLabel("No devices detected");
|
||||
noDeviceLabel->setAlignment(Qt::AlignCenter);
|
||||
labelLayout->addWidget(noDeviceLabel);
|
||||
labelLayout->addStretch();
|
||||
noDeviceLayout->addLayout(labelLayout);
|
||||
|
||||
#ifdef WIN32
|
||||
// Add diagnose widget to check dependencies
|
||||
// DiagnoseWidget *diagnoseWidget = new DiagnoseWidget();
|
||||
// noDeviceLayout->addWidget(diagnoseWidget);
|
||||
#endif
|
||||
|
||||
noDeviceLayout->addStretch();
|
||||
|
||||
m_deviceManager = new DeviceManagerWidget(this);
|
||||
|
||||
m_mainStackedWidget->addWidget(welcomePage);
|
||||
|
||||
@@ -16,10 +16,15 @@ DiagnoseDialog::DiagnoseDialog(QWidget *parent) : QDialog(parent)
|
||||
void DiagnoseDialog::setupUI()
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
QScrollArea *scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10);
|
||||
|
||||
// Add the main diagnose widget
|
||||
m_diagnoseWidget = new DiagnoseWidget();
|
||||
scrollArea->setWidget(m_diagnoseWidget);
|
||||
|
||||
// Close button
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||
@@ -33,7 +38,7 @@ void DiagnoseDialog::setupUI()
|
||||
buttonLayout->addWidget(m_closeButton);
|
||||
|
||||
// Layout assembly
|
||||
mainLayout->addWidget(m_diagnoseWidget, 1);
|
||||
mainLayout->addWidget(scrollArea);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include "diagnose_widget.h"
|
||||
#ifdef WIN32
|
||||
#include "check_deps.h"
|
||||
#endif
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
|
||||
DependencyItem::DependencyItem(const QString &name, const QString &description,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), m_name(name)
|
||||
@@ -37,7 +40,8 @@ DependencyItem::DependencyItem(const QString &name, const QString &description,
|
||||
m_statusLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
// Right side - actions
|
||||
QVBoxLayout *actionLayout = new QVBoxLayout();
|
||||
QHBoxLayout *actionLayout = new QHBoxLayout();
|
||||
actionLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_installButton = new QPushButton("Install");
|
||||
m_installButton->setMinimumWidth(80);
|
||||
@@ -45,13 +49,13 @@ DependencyItem::DependencyItem(const QString &name, const QString &description,
|
||||
connect(m_installButton, &QPushButton::clicked, this,
|
||||
&DependencyItem::onInstallClicked);
|
||||
|
||||
m_progressBar = new QProgressBar();
|
||||
m_progressBar->setRange(0, 0); // Indeterminate
|
||||
m_progressBar->setVisible(false);
|
||||
m_progressBar->setMaximumHeight(20);
|
||||
m_processIndicator = new QProcessIndicator();
|
||||
m_processIndicator->setType(QProcessIndicator::line_rotate);
|
||||
m_processIndicator->setFixedSize(24, 24);
|
||||
m_processIndicator->setVisible(false);
|
||||
|
||||
actionLayout->addWidget(m_processIndicator);
|
||||
actionLayout->addWidget(m_installButton);
|
||||
actionLayout->addWidget(m_progressBar);
|
||||
actionLayout->addStretch();
|
||||
|
||||
layout->addLayout(infoLayout, 1);
|
||||
@@ -80,28 +84,47 @@ void DependencyItem::setChecking(bool checking)
|
||||
m_statusLabel->setText("Checking...");
|
||||
m_statusLabel->setStyleSheet("color: gray;");
|
||||
m_installButton->setVisible(false);
|
||||
m_progressBar->setVisible(false);
|
||||
m_processIndicator->setVisible(false);
|
||||
m_processIndicator->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyItem::setInstalling(bool installing)
|
||||
{
|
||||
if (installing) {
|
||||
m_statusLabel->setText("Installing...");
|
||||
m_statusLabel->setStyleSheet("color: gray;");
|
||||
m_installButton->setVisible(false);
|
||||
m_processIndicator->setVisible(true);
|
||||
m_processIndicator->start();
|
||||
} else {
|
||||
m_processIndicator->stop();
|
||||
m_processIndicator->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyItem::onInstallClicked() { emit installRequested(m_name); }
|
||||
|
||||
DiagnoseWidget::DiagnoseWidget(QWidget *parent) : QWidget(parent)
|
||||
DiagnoseWidget::DiagnoseWidget(QWidget *parent)
|
||||
: QWidget(parent), m_isExpanded(false)
|
||||
{
|
||||
setupUI();
|
||||
|
||||
#ifdef WIN32
|
||||
// Add dependency items
|
||||
addDependencyItem("Apple Mobile Device Support",
|
||||
"Required for iOS device communication");
|
||||
addDependencyItem("WinFsp",
|
||||
"Required for filesystem operations and mounting");
|
||||
#endif
|
||||
|
||||
// Auto-check on startup
|
||||
QTimer::singleShot(100, this, &DiagnoseWidget::checkDependencies);
|
||||
QTimer::singleShot(100, this, [this]() { checkDependencies(); });
|
||||
}
|
||||
|
||||
void DiagnoseWidget::setupUI()
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
m_mainLayout = new QVBoxLayout(this);
|
||||
m_mainLayout->setSpacing(10);
|
||||
|
||||
@@ -115,40 +138,43 @@ void DiagnoseWidget::setupUI()
|
||||
m_summaryLabel = new QLabel("Checking system dependencies...");
|
||||
|
||||
// Check button
|
||||
m_checkButton = new QPushButton("Refresh Check");
|
||||
m_checkButton = new QPushButton("Refresh Check(s)");
|
||||
m_checkButton->setMaximumWidth(150);
|
||||
connect(m_checkButton, &QPushButton::clicked, this,
|
||||
&DiagnoseWidget::checkDependencies);
|
||||
[this]() { checkDependencies(false); });
|
||||
|
||||
// Scroll area for dependency items
|
||||
m_scrollArea = new QScrollArea();
|
||||
m_scrollArea->setWidgetResizable(true);
|
||||
// m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarNever);
|
||||
m_scrollArea->setMinimumHeight(200);
|
||||
// Toggle button
|
||||
m_toggleButton = new QPushButton("▼");
|
||||
m_toggleButton->setFixedSize(24, 24);
|
||||
m_toggleButton->setCheckable(true);
|
||||
connect(m_toggleButton, &QPushButton::clicked, this,
|
||||
&DiagnoseWidget::onToggleExpand);
|
||||
|
||||
m_itemsWidget = new QWidget();
|
||||
// m_itemsWidget->setSizePolicy(QSizePolicy::Expanding,
|
||||
// QSizePolicy::Preferred);
|
||||
m_itemsWidget->setFixedHeight(400);
|
||||
m_itemsLayout = new QVBoxLayout(m_itemsWidget);
|
||||
m_itemsLayout->setSpacing(5);
|
||||
m_itemsLayout->addStretch();
|
||||
|
||||
m_scrollArea->setWidget(m_itemsWidget);
|
||||
m_itemsWidget->setVisible(m_isExpanded);
|
||||
|
||||
// Layout assembly
|
||||
QHBoxLayout *headerLayout = new QHBoxLayout();
|
||||
headerLayout->addWidget(titleLabel);
|
||||
headerLayout->addStretch();
|
||||
headerLayout->addWidget(m_checkButton);
|
||||
headerLayout->addWidget(m_toggleButton);
|
||||
|
||||
m_mainLayout->addLayout(headerLayout);
|
||||
m_mainLayout->addWidget(m_summaryLabel);
|
||||
m_mainLayout->addWidget(m_scrollArea, 1);
|
||||
m_mainLayout->addWidget(m_itemsWidget);
|
||||
}
|
||||
|
||||
void DiagnoseWidget::addDependencyItem(const QString &name,
|
||||
const QString &description)
|
||||
{
|
||||
DependencyItem *item = new DependencyItem(name, description);
|
||||
item->setProperty("name", name); // Set the name property for identification
|
||||
item->setProperty("name", name);
|
||||
connect(item, &DependencyItem::installRequested, this,
|
||||
&DiagnoseWidget::onInstallRequested);
|
||||
|
||||
@@ -158,18 +184,16 @@ void DiagnoseWidget::addDependencyItem(const QString &name,
|
||||
m_itemsLayout->insertWidget(m_itemsLayout->count() - 1, item);
|
||||
}
|
||||
|
||||
void DiagnoseWidget::checkDependencies()
|
||||
void DiagnoseWidget::checkDependencies(bool autoExpand)
|
||||
{
|
||||
m_summaryLabel->setText("Checking system dependencies...");
|
||||
m_checkButton->setEnabled(false);
|
||||
|
||||
// Reset all items to checking state
|
||||
for (DependencyItem *item : m_dependencyItems) {
|
||||
item->setChecking(true);
|
||||
}
|
||||
|
||||
// Simulate async checking with timer
|
||||
QTimer::singleShot(500, [this]() {
|
||||
QTimer::singleShot(500, [this, autoExpand]() {
|
||||
int installedCount = 0;
|
||||
int totalCount = m_dependencyItems.size();
|
||||
|
||||
@@ -177,30 +201,37 @@ void DiagnoseWidget::checkDependencies()
|
||||
bool installed = false;
|
||||
QString itemName = item->property("name").toString();
|
||||
|
||||
#ifdef WIN32
|
||||
if (itemName == "Apple Mobile Device Support") {
|
||||
installed = IsAppleMobileDeviceSupportInstalled();
|
||||
} else if (itemName == "WinFsp") {
|
||||
installed = IsWinFspInstalled();
|
||||
}
|
||||
#endif
|
||||
|
||||
item->setInstalled(installed);
|
||||
if (installed)
|
||||
installedCount++;
|
||||
}
|
||||
|
||||
// Update summary
|
||||
if (installedCount == totalCount) {
|
||||
m_summaryLabel->setText(
|
||||
QString("All dependencies are installed (%1/%2)")
|
||||
.arg(installedCount)
|
||||
.arg(totalCount));
|
||||
m_summaryLabel->setStyleSheet("color: green; font-weight: bold;");
|
||||
if (m_isExpanded && autoExpand) {
|
||||
onToggleExpand();
|
||||
}
|
||||
} else {
|
||||
m_summaryLabel->setText(
|
||||
QString("Missing dependencies (%1/%2 installed)")
|
||||
.arg(installedCount)
|
||||
.arg(totalCount));
|
||||
m_summaryLabel->setStyleSheet("color: red; font-weight: bold;");
|
||||
if (!m_isExpanded && autoExpand) {
|
||||
onToggleExpand();
|
||||
}
|
||||
}
|
||||
|
||||
m_checkButton->setEnabled(true);
|
||||
@@ -209,26 +240,125 @@ void DiagnoseWidget::checkDependencies()
|
||||
|
||||
void DiagnoseWidget::onInstallRequested(const QString &name)
|
||||
{
|
||||
QString url;
|
||||
QString message;
|
||||
|
||||
#ifdef WIN32
|
||||
if (name == "Apple Mobile Device Support") {
|
||||
url = "https://support.apple.com/downloads/itunes";
|
||||
message = "Apple Mobile Device Support is typically installed with "
|
||||
"iTunes.\n\n"
|
||||
"Would you like to open the iTunes download page?";
|
||||
} else if (name == "WinFsp") {
|
||||
url = "https://winfsp.dev/rel/";
|
||||
message = "WinFsp can be downloaded from the official website.\n\n"
|
||||
"Would you like to open the WinFsp download page?";
|
||||
}
|
||||
|
||||
if (!url.isEmpty()) {
|
||||
int ret = QMessageBox::question(this, "Install " + name, message,
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
if (ret == QMessageBox::Yes) {
|
||||
QDesktopServices::openUrl(QUrl(url));
|
||||
DependencyItem *itemToInstall = nullptr;
|
||||
for (DependencyItem *item : m_dependencyItems) {
|
||||
if (item->property("name").toString() == name) {
|
||||
itemToInstall = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itemToInstall)
|
||||
return;
|
||||
|
||||
itemToInstall->setInstalling(true);
|
||||
|
||||
QString scriptPath = QCoreApplication::applicationDirPath() +
|
||||
"/install-apple-drivers.ps1";
|
||||
|
||||
QProcess *installProcess = new QProcess(this);
|
||||
connect(
|
||||
installProcess, &QProcess::finished, this,
|
||||
[this, installProcess,
|
||||
itemToInstall](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
if (exitStatus != QProcess::NormalExit || exitCode != 0) {
|
||||
QString errorOutput =
|
||||
installProcess->readAllStandardError();
|
||||
if (errorOutput.isEmpty()) {
|
||||
errorOutput = installProcess->readAllStandardOutput();
|
||||
}
|
||||
QMessageBox::warning(
|
||||
this, "Installation Failed",
|
||||
"Failed to launch the installation script. This "
|
||||
"might be a "
|
||||
"permissions issue or an internal error.\n\n"
|
||||
"Details: " +
|
||||
errorOutput.trimmed());
|
||||
checkDependencies(false); // Revert UI on failure
|
||||
} else {
|
||||
// FIXME: we need to track process completion
|
||||
QMessageBox::information(
|
||||
this, "Installation Started",
|
||||
"The installation process has been started.\n"
|
||||
"Please approve the administrator prompt (UAC) if it "
|
||||
"appears.\n"
|
||||
"After installation, please re-run the dependency "
|
||||
"check");
|
||||
|
||||
itemToInstall->setInstalling(false);
|
||||
}
|
||||
installProcess->deleteLater();
|
||||
});
|
||||
|
||||
// Correctly launch powershell.exe elevated, and pass the script to it.
|
||||
// The -Wait parameter is removed as it does not work with -Verb RunAs.
|
||||
QString command =
|
||||
QString("Start-Process -FilePath powershell.exe -Verb RunAs "
|
||||
"-ArgumentList '-NoProfile -ExecutionPolicy Bypass -File "
|
||||
"\"%1\"'")
|
||||
.arg(scriptPath);
|
||||
|
||||
QStringList args;
|
||||
args << "-NoProfile"
|
||||
<< "-ExecutionPolicy"
|
||||
<< "Bypass"
|
||||
<< "-Command" << command;
|
||||
|
||||
installProcess->start("powershell.exe", args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "WinFsp") {
|
||||
DependencyItem *itemToInstall = nullptr;
|
||||
for (DependencyItem *item : m_dependencyItems) {
|
||||
if (item->property("name").toString() == name) {
|
||||
itemToInstall = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itemToInstall)
|
||||
return;
|
||||
|
||||
itemToInstall->setInstalling(true);
|
||||
|
||||
QString scriptPath = QCoreApplication::applicationDirPath() +
|
||||
"/install-win-fsp.silent.bat";
|
||||
|
||||
QProcess *installProcess = new QProcess(this);
|
||||
connect(
|
||||
installProcess, &QProcess::finished, this,
|
||||
[this, installProcess](int exitCode,
|
||||
QProcess::ExitStatus exitStatus) {
|
||||
if (exitStatus != QProcess::NormalExit || exitCode != 0) {
|
||||
QMessageBox::warning(
|
||||
this, "Installation Failed",
|
||||
"The installation script failed to run correctly. "
|
||||
"This might be because the action was cancelled or an "
|
||||
"error occurred.\n\nPlease try again.");
|
||||
}
|
||||
checkDependencies(false);
|
||||
installProcess->deleteLater();
|
||||
});
|
||||
|
||||
QStringList args;
|
||||
args << "-NoProfile"
|
||||
<< "-ExecutionPolicy"
|
||||
<< "Bypass"
|
||||
<< "-Command"
|
||||
<< QString("Start-Process -FilePath \"%1\" -Verb RunAs -Wait;")
|
||||
.arg(scriptPath);
|
||||
|
||||
installProcess->start("powershell.exe", args);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DiagnoseWidget::onToggleExpand()
|
||||
{
|
||||
m_isExpanded = !m_isExpanded;
|
||||
m_itemsWidget->setVisible(m_isExpanded);
|
||||
m_toggleButton->setText(m_isExpanded ? "▲" : "▼");
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "../../qprocessindicator.h"
|
||||
|
||||
class DependencyItem : public QWidget
|
||||
{
|
||||
@@ -20,6 +21,7 @@ public:
|
||||
QWidget *parent = nullptr);
|
||||
void setInstalled(bool installed);
|
||||
void setChecking(bool checking);
|
||||
void setInstalling(bool installing);
|
||||
|
||||
signals:
|
||||
void installRequested(const QString &name);
|
||||
@@ -33,7 +35,7 @@ private:
|
||||
QLabel *m_descriptionLabel;
|
||||
QLabel *m_statusLabel;
|
||||
QPushButton *m_installButton;
|
||||
QProgressBar *m_progressBar;
|
||||
QProcessIndicator *m_processIndicator;
|
||||
};
|
||||
|
||||
class DiagnoseWidget : public QWidget
|
||||
@@ -44,10 +46,11 @@ public:
|
||||
explicit DiagnoseWidget(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void checkDependencies();
|
||||
void checkDependencies(bool autoExpand = true);
|
||||
|
||||
private slots:
|
||||
void onInstallRequested(const QString &name);
|
||||
void onToggleExpand();
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
@@ -56,9 +59,10 @@ private:
|
||||
QVBoxLayout *m_mainLayout;
|
||||
QVBoxLayout *m_itemsLayout;
|
||||
QPushButton *m_checkButton;
|
||||
QPushButton *m_toggleButton;
|
||||
QLabel *m_summaryLabel;
|
||||
QScrollArea *m_scrollArea;
|
||||
QWidget *m_itemsWidget;
|
||||
bool m_isExpanded;
|
||||
|
||||
QList<DependencyItem *> m_dependencyItems;
|
||||
};
|
||||
|
||||
+11
-5
@@ -9,13 +9,17 @@
|
||||
#include <QPalette>
|
||||
#include <QUrl>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "platform/windows/diagnose_widget.h"
|
||||
#endif
|
||||
|
||||
WelcomeWidget::WelcomeWidget(QWidget *parent) : QWidget(parent) { setupUI(); }
|
||||
|
||||
void WelcomeWidget::setupUI()
|
||||
{
|
||||
// Main layout with proper spacing and margins
|
||||
m_mainLayout = new QVBoxLayout(this);
|
||||
m_mainLayout->setContentsMargins(5, 5, 5, 5);
|
||||
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_mainLayout->setSpacing(0);
|
||||
|
||||
// Add top stretch
|
||||
@@ -85,11 +89,13 @@ void WelcomeWidget::setupUI()
|
||||
|
||||
m_mainLayout->addWidget(m_githubLabel);
|
||||
|
||||
// Add bottom stretch
|
||||
m_mainLayout->addStretch(1);
|
||||
// no additional deps needed on macOS
|
||||
#ifndef __APPLE__
|
||||
DiagnoseWidget *diagnoseWidget = new DiagnoseWidget();
|
||||
m_mainLayout->addWidget(diagnoseWidget);
|
||||
#endif
|
||||
|
||||
// Set minimum size
|
||||
// setMinimumSize(600, 500);
|
||||
m_mainLayout->addStretch(1);
|
||||
}
|
||||
|
||||
ZLabel *WelcomeWidget::createStyledLabel(const QString &text, int fontSize,
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
ZTab::ZTab(const QString &text, QWidget *parent) : QPushButton(text, parent)
|
||||
{
|
||||
setCheckable(true);
|
||||
#ifndef WIN32
|
||||
setFixedHeight(50);
|
||||
#else
|
||||
setFixedHeight(40);
|
||||
#endif
|
||||
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
}
|
||||
|
||||
@@ -21,7 +26,11 @@ ZTabWidget::ZTabWidget(QWidget *parent) : QWidget(parent), m_currentIndex(0)
|
||||
|
||||
// Create tab bar container
|
||||
m_tabBar = new QWidget();
|
||||
#ifndef WIN32
|
||||
m_tabBar->setFixedHeight(50);
|
||||
#else
|
||||
m_tabBar->setFixedHeight(40);
|
||||
#endif
|
||||
m_tabBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_tabLayout = new QHBoxLayout(m_tabBar);
|
||||
m_tabLayout->setSpacing(0);
|
||||
|
||||
Reference in New Issue
Block a user