diff --git "a/.\346\234\254\351\241\271\347\233\256\345\267\262\347\273\217\346\255\243\345\274\217\350\277\201\347\247\273\350\207\263 AtomGit \345\271\263\345\217\260/README.md" "b/.\346\234\254\351\241\271\347\233\256\345\267\262\347\273\217\346\255\243\345\274\217\350\277\201\347\247\273\350\207\263 AtomGit \345\271\263\345\217\260/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..da8214057b1012b4535d3c1f30c3690f962d9e1d --- /dev/null +++ "b/.\346\234\254\351\241\271\347\233\256\345\267\262\347\273\217\346\255\243\345\274\217\350\277\201\347\247\273\350\207\263 AtomGit \345\271\263\345\217\260/README.md" @@ -0,0 +1 @@ +# 通知: 本项目已经正式迁移至 [AtomGit](https://atomgit.com/src-openeuler/calamares) 平台 diff --git a/0001-branding-patch.patch b/0001-branding-patch.patch index 52f971918398b09213d77ef15a3668d76b8cf98c..f8d2e8cdd836a929e14889bad36a5acfee2a3cb0 100644 --- a/0001-branding-patch.patch +++ b/0001-branding-patch.patch @@ -122,7 +122,7 @@ index f4c50e629..f91d520cd 100644 - width: 200; height: 200 + id: background1 + source: "Slide1.png" -+ width: 980; height: 980 ++ width: 800; height: 800 fillMode: Image.PreserveAspectFit - anchors.centerIn: parent - } @@ -148,7 +148,7 @@ index f4c50e629..f91d520cd 100644 + Image { + id: background2 + source: "Slide2.png" -+ width: 980; height: 980 ++ width: 800; height: 800 + fillMode: Image.PreserveAspectFit + anchors.horizontalCenter:parent.horizontalCenter + y:parent.height / 2 - height / 2 -25 @@ -161,7 +161,7 @@ index f4c50e629..f91d520cd 100644 + Image { + id: background3 + source: "Slide3.png" -+ width: 980; height: 980 ++ width: 800; height: 800 + fillMode: Image.PreserveAspectFit + anchors.horizontalCenter:parent.horizontalCenter + y:parent.height / 2 - height / 2 -25 diff --git a/0006-modules-file.patch b/0006-modules-file.patch index d7473eaa46201d24be087139a7cadaada19487f9..a03be44e3f826ac106432fbb2adf9ef4cabd505a 100644 --- a/0006-modules-file.patch +++ b/0006-modules-file.patch @@ -36,7 +36,6 @@ Subject: [PATCH 4/4] modules Commit without .png, .svg, and .svgz files src/modules/unpackfs/main.py | 82 +- src/modules/unpackfs/unpackfs.conf | 12 +- src/modules/users/UsersPage.cpp | 2 +- - src/modules/users/page_usersetup.bak.ui | 710 ++++++++++++++++++ src/modules/users/page_usersetup.ui | 158 ++-- src/modules/users/users.conf | 2 +- src/modules/welcome/Config.cpp | 3 +- @@ -50,7 +49,6 @@ Subject: [PATCH 4/4] modules Commit without .png, .svg, and .svgz files mode change 100755 => 100644 src/modules/fstab/main.py mode change 100755 => 100644 src/modules/initramfscfg/encrypt_hook mode change 100755 => 100644 src/modules/initramfscfg/encrypt_hook_nokey - create mode 100644 src/modules/users/page_usersetup.bak.ui diff --git a/src/modules/bootloader/bootloader.conf b/src/modules/bootloader/bootloader.conf @@ -1324,722 +1322,6 @@ index 1ecc0eb..72fb3e0 100644 // Connect signals and slots ui->textBoxUserPassword->setText( config->userPassword() ); connect( ui->textBoxUserPassword, &QLineEdit::textChanged, config, &Config::setUserPassword ); -diff --git a/src/modules/users/page_usersetup.bak.ui b/src/modules/users/page_usersetup.bak.ui -new file mode 100644 -index 0000000..f808c89 ---- /dev/null -+++ b/src/modules/users/page_usersetup.bak.ui -@@ -0,0 +1,710 @@ -+ -+ -+ -+SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org> -+SPDX-License-Identifier: GPL-3.0-or-later -+ -+ Page_UserSetup -+ -+ -+ -+ 0 -+ 0 -+ 862 -+ 683 -+ -+ -+ -+ Form -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 6 -+ -+ -+ -+ -+ -+ -+ -+ What is your name? -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ Your Full Name -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ 1 -+ 0 -+ -+ -+ -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ What name do you want to use to log in? -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ login -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ 1 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ -+ -+ -+ Qt::AlignmentFlag::AlignVCenter -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ What is the name of this computer? -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ <small>This name will be used if you make the computer visible to others on a network.</small> -+ -+ -+ Computer Name -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ 1 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ -+ -+ -+ Qt::AlignmentFlag::AlignVCenter -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ Choose a password to keep your account safe. -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ <small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small> -+ -+ -+ QLineEdit::EchoMode::Password -+ -+ -+ Password -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ <small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small> -+ -+ -+ QLineEdit::EchoMode::Password -+ -+ -+ Repeat Password -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ 1 -+ 0 -+ -+ -+ -+ -+ 100 -+ 0 -+ -+ -+ -+ -+ -+ -+ Qt::AlignmentFlag::AlignVCenter -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ When this box is checked, password-strength checking is done and you will not be able to use a weak password. -+ -+ -+ Require strong passwords. -+ -+ -+ -+ -+ -+ -+ Log in automatically without asking for the password. -+ -+ -+ -+ -+ -+ -+ Use the same password for the administrator account. -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ Choose a password for the administrator account. -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ <small>Enter the same password twice, so that it can be checked for typing errors.</small> -+ -+ -+ QLineEdit::EchoMode::Password -+ -+ -+ Password -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 200 -+ 0 -+ -+ -+ -+ <small>Enter the same password twice, so that it can be checked for typing errors.</small> -+ -+ -+ QLineEdit::EchoMode::Password -+ -+ -+ Repeat Password -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ -+ 24 -+ 24 -+ -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ 1 -+ 0 -+ -+ -+ -+ -+ 100 -+ 0 -+ -+ -+ -+ -+ -+ -+ Qt::AlignmentFlag::AlignVCenter -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ QSizePolicy::Policy::Fixed -+ -+ -+ -+ 20 -+ 6 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Use Active Directory -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Domain: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Domain Administrator: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Password: -+ -+ -+ -+ -+ -+ -+ QLineEdit::EchoMode::Password -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ IP Address (optional): -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Orientation::Vertical -+ -+ -+ -+ 20 -+ 1 -+ -+ -+ -+ -+ -+ -+ -+ -+ diff --git a/src/modules/users/page_usersetup.ui b/src/modules/users/page_usersetup.ui index 6e6e542..2a5ccd2 100644 --- a/src/modules/users/page_usersetup.ui diff --git a/0010-cDebugDelect.patch b/0010-cDebugDelect.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5f63fef1df2e10c5603b4eaa39226486defbee3 --- /dev/null +++ b/0010-cDebugDelect.patch @@ -0,0 +1,400 @@ +From 662c8f4cdf8838d44f4a5b8be5455f840c0e314c Mon Sep 17 00:00:00 2001 +From: cui-gaoleng <562344211@qq.com> +Date: Tue, 19 Nov 2024 13:43:48 +0800 +Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF=E5=92=8C?= + =?UTF-8?q?=E5=B7=B2=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81=E5=88=A0=E9=99=A4?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/calamares/CalamaresWindow.cpp | 3 - + .../progresstree/ProgressTreeDelegate.cpp | 9 - + .../progresstree/ProgressTreeView.cpp | 2 - + src/libcalamares/CalamaresAbout.cpp | 1 - + .../modulesystem/CppJobModule.cpp | 4 - + src/modules/keyboard/KeyboardPage.cpp | 19 - + src/modules/keyboard/KeyboardPage.ui | 3 - + src/modules/locale/LocalePage.cpp | 20 +- + .../packagechooser/packagechooser.conf | 16 +- + src/modules/welcome/WelcomePage.cpp | 74 +- + 11 files changed, 7 insertions(+), 862 deletions(-) + +diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp +index 4721cb9..4917f75 100644 +--- a/src/calamares/CalamaresWindow.cpp ++++ b/src/calamares/CalamaresWindow.cpp +@@ -440,7 +440,6 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) + int h = qBound( minimumSize.height(), windowDimensionToPixels( brandingSizes.second ), availableSize.height() ); + + cDebug() << Logger::SubEntry << "Proposed window size:" << w << h; +- //resize( availableSize.width(), availableSize.height() );//通用桌面大小作为窗口大小 + resize( w, h );//通用桌面大小作为窗口大小 + QWidget* baseWidget = this; + if ( !( branding->imagePath( ImageEntry::ProductWallpaper ).isEmpty() ) ) +@@ -519,8 +518,6 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) + Calamares::unmarginLayout( contentsLayout ); + baseWidget->setLayout( mainLayout ); + setStyleSheet( Calamares::Branding::instance()->stylesheet() ); +- cDebug()<<"<---------------------------WindowWindowSize-------------------------------------->"<size(); +- cDebug()<< "<--------------------sideBox->size()-------------------->"<< sideBox->size(); + this->setFixedSize(this->size()); + } + +diff --git a/src/calamares/progresstree/ProgressTreeDelegate.cpp b/src/calamares/progresstree/ProgressTreeDelegate.cpp +index 6d5f865..7541356 100644 +--- a/src/calamares/progresstree/ProgressTreeDelegate.cpp ++++ b/src/calamares/progresstree/ProgressTreeDelegate.cpp +@@ -53,9 +53,6 @@ static QString getTypeOfStep(const QString& stepString){ + + // 将地区枚举值转换为字符串 + QString countryString = QLocale::countryToString(country); +- // 输出当前语言 +- cDebug() << "-------------------------------------------当前系统语言:" << languageString; +- cDebug() << "-------------------------------------------当前系统地区:" << countryString; + if(contains(baseSetting1,stepString)){ + return "BaseSetting"; + } +@@ -145,7 +142,6 @@ paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QMod + shrinkSteps++; + + QRectF boundingBox; +- cDebug() << "index.data().toString()" << index.data().toString(); + QString text; + if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"||!isVisable(index.data().toString())){ + text = ""; +@@ -179,7 +175,6 @@ ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModel + } + + QFont font = qApp->font(); +- cDebug() << "ProgressTreeDelegate::sizeHint"; + + font.setPointSize( item_fontsize() ); + QFontMetrics fm( font ); +@@ -190,14 +185,12 @@ ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModel + }else{ + return QSize( (Calamares::windowMinimumWidth*0.9)/3, height*2 ); + } +-// return QSize( option.rect.width(), height ); + + } + + void + ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const + { +- cDebug() << "ProgressTreeDelegate::paint----------"; + QStyleOptionViewItem opt = option; + + painter->save(); +@@ -209,11 +202,9 @@ ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& opti + QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) ); + painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) ); + if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"){ +- cDebug() << "ProgressTreeDelegate::欢迎Welcome--------Nopaint----------"; + }else{ + paintViewStep( painter, opt, index ); + } +- //paintViewStep( painter, opt, index ); + + painter->restore(); + } +diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp +index 29ee7ee..a9a15b8 100644 +--- a/src/calamares/progresstree/ProgressTreeView.cpp ++++ b/src/calamares/progresstree/ProgressTreeView.cpp +@@ -68,14 +68,12 @@ ProgressTreeView::setModel( QAbstractItemModel* model ) + void + ProgressTreeView::update() + { +- cDebug() << "update ---------------------"; + viewport()->update(); + } + + void + ProgressTreeView::updateVisibility(int currentStep) + { +- cDebug() << "int currentStep ------------------ " << currentStep; + // 在第一个步骤隐藏,其他步骤显示 + this->setVisible(currentStep > 0); + } + +diff --git a/src/libcalamares/CalamaresAbout.cpp b/src/libcalamares/CalamaresAbout.cpp +index 65a1b9d..595efc7 100644 +--- a/src/libcalamares/CalamaresAbout.cpp ++++ b/src/libcalamares/CalamaresAbout.cpp +@@ -65,7 +65,6 @@ Calamares::aboutString() + { + return substituteVersions( QCoreApplication::translate( "AboutData", s_header ) ) + aboutMaintainers() + + QCoreApplication::translate( "AboutData", s_footer ); +- // return aboutMaintainers()+ QCoreApplication::translate( "AboutData", s_footer ); + } + + const QString +diff --git a/src/libcalamaresui/modulesystem/CppJobModule.cpp b/src/libcalamaresui/modulesystem/CppJobModule.cpp +index c211006..b35a457 100644 +--- a/src/libcalamaresui/modulesystem/CppJobModule.cpp ++++ b/src/libcalamaresui/modulesystem/CppJobModule.cpp +@@ -53,10 +53,6 @@ CppJobModule::loadSelf() + cDebug() << "Could not load module:" << m_loader->errorString(); + return; + } +- // cDebug() << "CppJobModule loading self for instance" << instanceKey() +- // << "\nCppJobModule at address" << this +- // << "\nCalamares::PluginFactory at address" << pf +- // << "\nCppJob at address" << cppJob; + + cppJob->setModuleInstanceKey( instanceKey() ); + cppJob->setConfigurationMap( m_configurationMap ); +diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp +index 3f06158..be60521 100644 +--- a/src/modules/keyboard/KeyboardPage.cpp ++++ b/src/modules/keyboard/KeyboardPage.cpp +@@ -48,9 +48,6 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent ) + { + ui->setupUi( this ); + this->setContentsMargins(50,0,50,0); +- // Keyboard Preview +- // ui->KBPreviewLayout->addWidget( m_keyboardPreview ); +- + + { + auto* model = config->keyboardModels(); +@@ -93,27 +90,11 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent ) + &QItemSelectionModel::currentChanged, + [ this ]( const QModelIndex& current ) + { m_config->keyboardLayouts()->setCurrentIndex( current.row() ); } ); +- // connect( config->keyboardLayouts(), +- // &KeyboardLayoutModel::currentIndexChanged, +- // [ this ]( int index ) +- // { +- // ui->layoutSelector->setCurrentIndex( m_config->keyboardLayouts()->index( index ) ); +- // m_keyboardPreview->setLayout( m_config->keyboardLayouts()->key( index ) ); +- // m_keyboardPreview->setVariant( +- // m_config->keyboardVariants()->key( m_config->keyboardVariants()->currentIndex() ) ); +- // } ); + + connect( ui->variantSelector->selectionModel(), + &QItemSelectionModel::currentChanged, + [ this ]( const QModelIndex& current ) + { m_config->keyboardVariants()->setCurrentIndex( current.row() ); } ); +- // connect( config->keyboardVariants(), +- // &KeyboardVariantsModel::currentIndexChanged, +- // [ this ]( int index ) +- // { +- // ui->variantSelector->setCurrentIndex( m_config->keyboardVariants()->index( index ) ); +- // m_keyboardPreview->setVariant( m_config->keyboardVariants()->key( index ) ); +- // } ); + + connect( ui->groupSelector, + QOverload< int >::of( &QComboBox::currentIndexChanged ), +diff --git a/src/modules/keyboard/KeyboardPage.ui b/src/modules/keyboard/KeyboardPage.ui +index 1d6afbf..70cfca3 100644 +--- a/src/modules/keyboard/KeyboardPage.ui ++++ b/src/modules/keyboard/KeyboardPage.ui +@@ -45,9 +45,6 @@ SPDX-License-Identifier: GPL-3.0-or-later + + + +- + + + +diff --git a/src/modules/locale/LocalePage.cpp b/src/modules/locale/LocalePage.cpp +index 0568067..ed50574 100644 +--- a/src/modules/locale/LocalePage.cpp ++++ b/src/modules/locale/LocalePage.cpp +@@ -32,13 +32,6 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + { + QBoxLayout* mainLayout = new QVBoxLayout; + mainLayout->setContentsMargins(50,0,50,0); +- //QBoxLayout* tzwLayout = new QHBoxLayout; +- //m_tzWidget = new TimeZoneWidget( m_config->zonesModel(), this ); +- //tzwLayout->addStretch(); +- //tzwLayout->addWidget( m_tzWidget ); +- //tzwLayout->addStretch(); +- // Adjust for margins and spacing in this page +- //m_tzWidget->setMinimumHeight( m_tzWidget->minimumHeight() + 12 ); // 2 * spacing + + QBoxLayout* zoneAndRegionLayout = new QVBoxLayout; + m_regionLabel = new QLabel( this ); +@@ -90,7 +83,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + m_formatsChangeButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + formatsLayout->addWidget( m_formatsChangeButton ); + formatsLayout->addSpacing(20); +- //mainLayout->addLayout( tzwLayout ); ++ + mainLayout->addStretch(); + mainLayout->addLayout( zoneAndRegionLayout ); + mainLayout->addStretch(); +@@ -100,7 +93,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + mainLayout->addSpacing(20); + mainLayout->addLayout( timezoneLayout ); + mainLayout->addStretch(); +- //setMinimumWidth( m_tzWidget->width() ); ++ + setLayout( mainLayout ); + + m_localeChangeButton->hide(); +@@ -114,20 +107,15 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + zones->setRegion( location->region() ); + m_regionCombo->setModel( regions ); + m_zoneCombo->setModel( zones ); +- //m_tzWidget->setCurrentLocation( location ); ++ + locationChanged( location ); // doesn't inform TZ widget + } + + connect( config, &Config::currentLCStatusChanged, m_formatsLabel, &QLabel::setText ); + connect( config, &Config::currentLanguageStatusChanged, m_localeLabel, &QLabel::setText ); + connect( config, &Config::currentZoneChanged, m_timezoneLabel , &QLabel::setText); +- //connect( config, &Config::currentLocationChanged, m_tzWidget, &TimeZoneWidget::setCurrentLocation ); ++ + connect( config, &Config::currentLocationChanged, this, &LocalePage::locationChanged ); +- // connect( m_tzWidget, +- // &TimeZoneWidget::locationChanged, +- // config, +- // QOverload< const Calamares::Locale::TimeZoneData* >::of( &Config::setCurrentLocation ) ); +- + connect( m_regionCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::regionChanged ); + connect( m_zoneCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::zoneChanged ); + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index e7b9b00..aa048e2 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -157,11 +157,7 @@ items: + description[nl]: "Kies eventueel een desktop-omgeving uit deze lijst. Als u geen desktop-omgeving wenst te gebruiken, kies er dan geen. In dat geval start het systeem straks op in tekst-modus en kunt u later alsnog een desktop-omgeving installeren." + description[zh]: "请选择一个桌面环境。如果您不想安装桌面环境也没关系,您可以稍后再为系统安装桌面环境。" + screenshot: ":/images/Minimal-Install.png" +- # - id: kde +- # packages: [ kde-frameworks, kde-plasma, kde-gear ] +- # name: Plasma Desktop +- # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." +- # screenshot: ":/images/Plasma.png" ++ + - id: gnome + packages: [ checkpolicy, code, xorg-*, dejavu-fonts, liberation-fonts, gnu-*-fonts, google-*-fonts, adwaita-icon-theme, atk, atkmm, at-spi2-atk, at-spi2-core, baobab, abattis-cantarell-fonts, cheese, clutter, clutter-gst3, clutter-gtk, cogl, dconf, dconf-editor, devhelp, eog, epiphany, evince, evolution-data-server, file-roller, folks, gcab, gcr, gdk-pixbuf2, gdm, gedit, geocode-glib, gfbgraph, gjs, glib2, glibmm24, glib-networking, gmime30, gnome-autoar, gnome-backgrounds, gnome-bluetooth, gnome-builder, gnome-calculator, gnome-calendar, gnome-characters, gnome-clocks, gnome-color-manager, gnome-contacts, gnome-control-center, gnome-desktop3, gnome-disk-utility, gnome-font-viewer, gnome-getting-started-docs, gnome-initial-setup, gnome-keyring, gnome-logs, gnome-menus, gnome-music, gnome-online-accounts, gnome-online-miners, gnome-photos, gnome-remote-desktop, gnome-screenshot, gnome-session, gnome-settings-daemon, gnome-shell, gnome-shell-extensions, gnome-software, gnome-system-monitor, gnome-terminal, gnome-tour, gnome-user-docs, gnome-user-share, gnome-video-effects, gnome-weather, gobject-introspection, gom, grilo, grilo-plugins, gsettings-desktop-schemas, gsound, gspell, gssdp, gtk3, gtk4, gtk-doc, gtkmm30, gtksourceview4, gtk-vnc2, gupnp, gupnp-av, gupnp-dlna, gvfs, json-glib, libchamplain, libdazzle, libgdata, libgee, libgnomekbd, libgsf, libgtop2, libgweather, libgxps, libhandy, libmediaart, libnma, libnotify, libpeas, librsvg2, libsecret, libsigc++20, libsoup, mm-common, mutter, nautilus, orca, pango, pangomm, libphodav, python3-pyatspi, python3-gobject, rest, rygel, simple-scan, sushi, sysprof, tepl, totem, totem-pl-parser, tracker3, tracker3-miners, vala, vte291, yelp, yelp-tools, yelp-xsl, zenity, devstation-config, ibus-libpinyin ] + name: DevStation +@@ -169,13 +165,3 @@ items: + description: GNU Networked Object Modeling Environment Desktop + description[zh]: Devstation系统桌面 + screenshot: ":/images/gnome.png" +- #- id: ukui +- # packages: [ ukui ] +- # name: UKUI +- # description: Linux Desktop +- # screenshot: ":/images/UKUI.png" +- # - id: calamares +- # appdata: ../io.calamares.calamares.appdata.xml +- # screenshot: ":/images/calamares.png" +- # - id: kate +- # appstream: org.kde.kwrite.desktop +diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp +index 88f38c2..471187b 100644 +--- a/src/modules/welcome/WelcomePage.cpp ++++ b/src/modules/welcome/WelcomePage.cpp +@@ -91,21 +91,7 @@ WelcomePage::WelcomePage( Config* config, QWidget* parent ) + } + + void +-WelcomePage::init() +-{ +- //setup the url buttons +- // setupButton( WelcomePage::Button::Support, m_conf->supportUrl() ); +- // setupButton( WelcomePage::Button::KnownIssues, m_conf->knownIssuesUrl() ); +- // setupButton( WelcomePage::Button::ReleaseNotes, m_conf->releaseNotesUrl() ); +- // setupButton( WelcomePage::Button::Donate, m_conf->donateUrl() ); +- +- //language icon +- // auto icon = Calamares::Branding::instance()->image( m_conf->languageIcon(), QSize( 48, 48 ) ); +- // if ( !icon.isNull() ) +- // { +- // setLanguageIcon( icon ); +- // } +-} ++WelcomePage::init(){} + + void + WelcomePage::initLanguages() +@@ -125,57 +111,6 @@ WelcomePage::initLanguages() + &Config::setLocaleIndex ); + } + +-// void +-// WelcomePage::setupButton( Button role, const QString& url ) +-// { +-// QPushButton* button = nullptr; +-// Calamares::ImageType icon = Calamares::Information; +- +-// switch ( role ) +-// { +-// case Button::Donate: +-// button = ui->donateButton; +-// icon = Calamares::Donate; +-// break; +-// case Button::KnownIssues: +-// button = ui->knownIssuesButton; +-// icon = Calamares::Bugs; +-// break; +-// case Button::ReleaseNotes: +-// button = ui->releaseNotesButton; +-// icon = Calamares::Release; +-// break; +-// case Button::Support: +-// button = ui->supportButton; +-// icon = Calamares::Help; +-// break; +-// } +-// if ( !button ) +-// { +-// cWarning() << "Unknown button role" << smash( role ); +-// return; +-// } +- +-// if ( url.isEmpty() ) +-// { +-// button->hide(); +-// return; +-// } +- +-// QUrl u( url ); +-// if ( u.isValid() ) +-// { +-// auto size = 2 * QSize( Calamares::defaultFontHeight(), Calamares::defaultFontHeight() ); +-// button->setIcon( Calamares::defaultPixmap( icon, Calamares::Original, size ) ); +-// connect( button, &QPushButton::clicked, [ u ]() { QDesktopServices::openUrl( u ); } ); +-// } +-// else +-// { +-// cWarning() << "Welcome button" << smash( role ) << "URL" << url << "is invalid."; +-// button->hide(); +-// } +-// } +- + void + WelcomePage::focusInEvent( QFocusEvent* e ) + { +@@ -201,11 +136,6 @@ WelcomePage::externallySelectedLanguage( int row ) + } + } + +-// void +-// WelcomePage::setLanguageIcon( QPixmap i ) +-// { +-// ui->languageIcon->setPixmap( i ); +-// } + + void + WelcomePage::retranslate() +@@ -214,8 +144,6 @@ WelcomePage::retranslate() + + ui->mainText->setText( message.arg( Calamares::Branding::instance()->versionedName() ) ); + ui->retranslateUi( this ); +- // ui->supportButton->setText( +- // tr( "%1 Support", "@action" ).arg( Calamares::Branding::instance()->shortProductName() ) ); + } + + void + diff --git a/0011-fix-87-position-and-translate.patch b/0011-fix-87-position-and-translate.patch new file mode 100644 index 0000000000000000000000000000000000000000..0419506a4fc05c50217b96fc995c04c238e989b5 --- /dev/null +++ b/0011-fix-87-position-and-translate.patch @@ -0,0 +1,230 @@ +From 057721ec933fc439d9e9b9887dc69704cd49472e Mon Sep 17 00:00:00 2001 +From: cui-gaoleng <562344211@qq.com> +Date: Fri, 22 Nov 2024 12:14:08 +0800 +Subject: [PATCH] =?UTF-8?q?fix=20progress=20bar=20has=20been=20at=20the=20?= + =?UTF-8?q?87%=20position=20for=20a=20long=20time+=E4=B8=A4=E5=A4=84?= + =?UTF-8?q?=E7=B9=81=E4=BD=93=E7=BF=BB=E8=AF=91=E8=A1=A5=E9=BD=90?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + calamares.desktop | 2 +- + lang/calamares_zh_TW.ts | 6 +-- + src/modules/packages/main.py | 70 +++++++++++++++++++------------- + src/modules/packages/module.desc | 1 + + src/modules/unpackfs/main.py | 24 ++++++++--- + 5 files changed, 65 insertions(+), 38 deletions(-) + +diff --git a/calamares.desktop b/calamares.desktop +index 9a1416e..9d33495 100644 +--- a/calamares.desktop ++++ b/calamares.desktop +@@ -5,7 +5,7 @@ Name=Install System + GenericName=System Installer + Keywords=calamares;system;installer; + TryExec=calamares +-Exec=sh -c "pkexec calamares" ++Exec=sh -c "pkexec calamares -style Adwaita" + Comment=Calamares — System Installer + Icon=calamares + Terminal=false +diff --git a/lang/calamares_zh_TW.ts b/lang/calamares_zh_TW.ts +index 8689629..3cc473c 100644 +--- a/lang/calamares_zh_TW.ts ++++ b/lang/calamares_zh_TW.ts +@@ -613,9 +613,9 @@ The system will reboot or you can enter the debug mode for further investigation + + + +- &Debug ++ &Try Now + @button +- 調試(&D) ++ 立即試用(&D) + + + Do you really want to cancel the current install process? +@@ -4526,7 +4526,7 @@ Output: + + + language +- ++ 語言 + + + Open donations website +diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py +index 8c165e8..1fbe276 100644 +--- a/src/modules/packages/main.py ++++ b/src/modules/packages/main.py +@@ -138,10 +138,11 @@ class PackageManager(metaclass=abc.ABCMeta): + self.install([packagedata], from_local=from_local, options=options) + else: + self.run(packagedata["pre-script"]) +- if isinstance(packagedata["package"], list): +- self.install(packagedata["package"], from_local=from_local, options=options) +- else: +- self.install([packagedata["package"]], from_local=from_local, options=options) ++ if "package" in packagedata: ++ if isinstance(packagedata["package"], list): ++ self.install(packagedata["package"], from_local=from_local, options=options) ++ else: ++ self.install([packagedata["package"]], from_local=from_local, options=options) + if isinstance(packagedata["post-script"], list): + for script in packagedata["post-script"]: + self.run(script) +@@ -787,41 +788,54 @@ def run_operations(pkgman, entry, options): + names (strings) or package information dictionaries with pre- + and post-scripts. + """ +- global group_packages, completed_packages, mode_packages +- +- if "source" in entry and entry["source"] == "packagechooser@packagechooser": +- handle_packagechooser(entry) ++ global group_packages, completed_packages, mode_packages, custom_status_message + + for key in entry.keys(): + package_list = subst_locale(entry[key]) ++ libcalamares.utils.warning(str(package_list)) + group_packages = len(package_list) + +- if key == "install": +- _change_mode(INSTALL) +- pkgman.operation_install(package_list, options=options) +- elif key == "try_install": ++ if key in ["install", "try_install", "localInstall"]: + _change_mode(INSTALL) +- pkgman.operation_try_install(package_list, options=options) +- elif key == "remove": +- _change_mode(REMOVE) +- pkgman.operation_remove(package_list, options=options) +- elif key == "try_remove": ++ for package in package_list: ++ custom_status_message = f"Installing package: {package}" ++ try: ++ if key == "localInstall": ++ pkgman.operation_install([package], from_local=True, options=options) ++ elif key == "try_install": ++ pkgman.operation_try_install([package], options=options) ++ else: ++ pkgman.operation_install([package], options=options) ++ except Exception as e: ++ libcalamares.utils.warning("Failed to install package {}: {}".format(package, str(e))) ++ ++ completed_packages += 1 ++ progress = completed_packages / total_packages ++ libcalamares.job.setprogress(progress) ++ libcalamares.utils.debug("Progress: {:.2f}, Package: {}".format(progress, package)) ++ elif key in ["remove", "try_remove"]: + _change_mode(REMOVE) +- pkgman.operation_try_remove(package_list, options=options) +- elif key == "localInstall": +- _change_mode(INSTALL) +- pkgman.operation_install(package_list, from_local=True, options=options) +- elif key == "source": +- libcalamares.utils.debug("Package-list from {!s}".format(entry[key])) ++ for package in package_list: ++ try: ++ if key == "remove": ++ pkgman.operation_remove([package], options=options) ++ elif key == "try_remove": ++ pkgman.operation_try_remove([package], options=options) ++ except Exception as e: ++ libcalamares.utils.warning("Failed to remove package {}: {}".format(package, str(e))) ++ ++ completed_packages += 1 ++ progress = completed_packages / total_packages ++ libcalamares.job.setprogress(progress) ++ libcalamares.utils.debug("Progress: {:.2f}, Package: {}".format(progress, package)) + else: + libcalamares.utils.warning("Unknown package-operation key {!s}".format(key)) +- completed_packages += len(package_list) +- libcalamares.job.setprogress(completed_packages * 1.0 / total_packages) +- libcalamares.utils.debug("Pretty name: {!s}, setting progress..".format(pretty_name())) + ++ if "source" in entry and entry["source"] == "packagechooser@packagechooser": ++ packagemeta = handle_packagechooser() ++ pkgman.operation_install([packagemeta], from_local=True, options=options) + group_packages = 0 +- _change_mode(None) +- ++ _change_mode(None) + + def run(): + """ +diff --git a/src/modules/packages/module.desc b/src/modules/packages/module.desc +index 3e3053b..9529af6 100644 +--- a/src/modules/packages/module.desc ++++ b/src/modules/packages/module.desc +@@ -5,3 +5,4 @@ type: "job" + name: "packages" + interface: "python" + script: "main.py" ++weight: 50 +diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py +index 4148720..4c5518e 100644 +--- a/src/modules/unpackfs/main.py ++++ b/src/modules/unpackfs/main.py +@@ -26,6 +26,8 @@ import libcalamares + import platform + + import gettext ++ ++import libcalamares.utils + _ = gettext.translation("calamares-python", + localedir=libcalamares.utils.gettext_path(), + languages=libcalamares.utils.gettext_languages(), +@@ -263,6 +265,7 @@ def file_copy(source, entry, progress_cb): + progress_cb(num_files_copied, num_files_total_local) + try: + returncode = 0 ++ + arch = platform.machine() + + libcalamares.utils.host_env_process_output(["mkdir", "-p", entry.destination + "/etc/yum.repos.d/"], output_cb) +@@ -272,6 +275,7 @@ def file_copy(source, entry, progress_cb): + libcalamares.utils.host_env_process_output(["cp", "-af", "/etc/add_selinux_policy.sh", entry.destination + "/etc/add_selinux_policy.sh"], output_cb) + libcalamares.utils.host_env_process_output(["chmod", "+x", entry.destination + "/etc/add_selinux_policy.sh"], output_cb) + ++ completed_packages = 0 + if os.path.exists("/etc/yum.repos.d/local.repo"): + libcalamares.utils.host_env_process_output( + ["cp", "-af", "/etc/yum.repos.d/local.repo", entry.destination + "/etc/yum.repos.d/"], output_cb) +@@ -281,9 +285,13 @@ def file_copy(source, entry, progress_cb): + else: + packages = ["yum", "grub2", "grub2-efi-x64", "grub2-pc", "passwd", "sudo"] + +- libcalamares.utils.host_env_process_output( +- ["yum", "--installroot=" + entry.destination, "--disablerepo=*", "--enablerepo=local-repo", +- "--releasever=/", "--nogpgcheck", "--setopt=sslverify=0", "install", "-y"] + packages, output_cb) ++ for package in packages: ++ libcalamares.job.setprogress(completed_packages / len(packages)) ++ libcalamares.utils.host_env_process_output( ++ ["yum", "--installroot=" + entry.destination, "--disablerepo=*", "--enablerepo=local-repo", ++ "--releasever=/", "--nogpgcheck", "--setopt=sslverify=0", "install", "-y", package], output_cb) ++ completed_packages += 1 ++ libcalamares.job.setprogress(completed_packages / len(packages)) + else: + libcalamares.utils.host_env_process_output( + ["cp", "-af", "/etc/yum.repos.d/openEuler.repo", entry.destination + "/etc/yum.repos.d/"], output_cb) +@@ -292,9 +300,13 @@ def file_copy(source, entry, progress_cb): + else: + packages = ["yum", "grub2", "grub2-efi-x64", "grub2-pc", "passwd", "sudo"] + +- libcalamares.utils.host_env_process_output( +- ["yum", "--installroot=" + entry.destination, "--releasever=/", "--nogpgcheck", "--setopt=sslverify=0", +- "install", "-y"] + packages, output_cb) ++ for package in packages: ++ libcalamares.job.setprogress(completed_packages / len(packages)) ++ libcalamares.utils.host_env_process_output( ++ ["yum", "--installroot=" + entry.destination, "--releasever=/", "--nogpgcheck", "--setopt=sslverify=0", ++ "install", "-y", package], output_cb) ++ completed_packages += 1 ++ libcalamares.job.setprogress(completed_packages / len(packages)) + + libcalamares.utils.host_env_process_output(["rm", "-f", entry.destination + "/etc/shadow"], output_cb) + libcalamares.utils.host_env_process_output(["cp", "-af", "/etc/shadow", entry.destination + "/etc/shadow"], output_cb) +-- +2.43.0 + diff --git a/0012-replace-icon.patch b/0012-replace-icon.patch new file mode 100644 index 0000000000000000000000000000000000000000..9a36c87799fdf9d9f22ebca94ba12c0e72f6cd1b --- /dev/null +++ b/0012-replace-icon.patch @@ -0,0 +1,29 @@ +From ec4ad9b45ba894afb73ae30ae6e8631fb701f1dd Mon Sep 17 00:00:00 2001 +From: cui-gaoleng <562344211@qq.com> +Date: Fri, 22 Nov 2024 12:44:38 +0800 +Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=BE=E6=A0=87=E9=85=8D?= + =?UTF-8?q?=E7=BD=AE?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + calamares.desktop | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/calamares.desktop b/calamares.desktop +index 9d33495..00c2368 100644 +--- a/calamares.desktop ++++ b/calamares.desktop +@@ -7,7 +7,7 @@ Keywords=calamares;system;installer; + TryExec=calamares + Exec=sh -c "pkexec calamares -style Adwaita" + Comment=Calamares — System Installer +-Icon=calamares ++Icon=/usr/share/calamares/branding/default/openEuler-icon.png + Terminal=false + StartupNotify=true + Categories=Qt;System; +-- +2.43.0 + diff --git a/0013-1230.patch b/0013-1230.patch new file mode 100644 index 0000000000000000000000000000000000000000..75ee73436323a6bf478946d9606fa90ec120389b --- /dev/null +++ b/0013-1230.patch @@ -0,0 +1,10764 @@ +From 9dd33a244e37407d18a5a8e3903ec9d4fd59cde9 Mon Sep 17 00:00:00 2001 +From: lizixin <2271170409@qq.com> +Date: Fri, 27 Dec 2024 19:27:11 +0800 +Subject: [PATCH] 1230 + +--- + CMakeLists.txt | 1 + + calamares.desktop | 10 +- + lang/calamares_zh_CN.ts | 2 +- + lang/tz_zh_CN.ts | 2626 +++++++++++++++++ + lang/tz_zh_TW.ts | 2626 +++++++++++++++++ + src/branding/default/show.qml | 6 +- + src/calamares/CMakeLists.txt | 134 +- + src/calamares/CalamaresApplication.cpp | 4 +- + src/calamares/DebugWindow.cpp | 530 ++-- + src/calamares/DebugWindow.h | 192 +- + src/calamares/VariantModel.cpp | 570 ++-- + src/calamares/VariantModel.h | 208 +- + src/calamares/calamares-navigation.qml | 166 +- + src/calamares/calamares-sidebar.qml | 250 +- + src/calamares/calamares.qrc | 20 +- + src/calamares/main.cpp | 308 +- + .../progresstree/ProgressTreeDelegate.cpp | 422 +-- + .../progresstree/ProgressTreeDelegate.h | 62 +- + .../progresstree/ProgressTreeView.cpp | 154 +- + src/calamares/progresstree/ProgressTreeView.h | 82 +- + src/calamares/test_conf.cpp | 218 +- + src/calamares/testmain.cpp | 1144 +++---- + src/libcalamares/CalamaresAbout.cpp | 1 + + .../modulesystem/CppJobModule.cpp | 4 + + src/modules/displaymanager/main.py | 10 + + src/modules/keyboard/KeyboardPage.cpp | 19 + + src/modules/keyboard/KeyboardPage.ui | 3 + + src/modules/locale/Config.cpp | 43 + + src/modules/locale/LocalePage.cpp | 20 +- + .../packagechooser/packagechooser.conf | 20 +- + src/modules/packagechooser/packagechooser.qrc | 5 - + src/modules/packages/main.py | 14 +- + src/modules/packages/packages.conf | 4 +- + src/modules/partition/core/DeviceList.cpp | 23 +- + src/modules/partition/jobs/ClearMountsJob.cpp | 51 +- + src/modules/unpackfs/main.py | 6 +- + src/modules/users/CreateUserJob.cpp | 18 + + src/modules/users/UsersPage.cpp | 102 + + src/modules/users/UsersPage.h | 15 + + src/modules/welcome/WelcomePage.cpp | 74 +- + src/modules/welcome/welcome.qrc | 1 - + 41 files changed, 7895 insertions(+), 2273 deletions(-) + create mode 100644 lang/tz_zh_CN.ts + create mode 100644 lang/tz_zh_TW.ts + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 19395d4..40ae7e0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -744,3 +744,4 @@ set(CPACK_PACKAGE_DESCRIPTION + set(CPACK_PACKAGE_ICON "data/images/squid.png") + + include(CPack) ++ +diff --git a/calamares.desktop b/calamares.desktop +index 00c2368..b0d6c27 100644 +--- a/calamares.desktop ++++ b/calamares.desktop +@@ -7,7 +7,7 @@ Keywords=calamares;system;installer; + TryExec=calamares + Exec=sh -c "pkexec calamares -style Adwaita" + Comment=Calamares — System Installer +-Icon=/usr/share/calamares/branding/default/openEuler-icon.png ++Icon=/usr/share/applications/openEuler.png + Terminal=false + StartupNotify=true + Categories=Qt;System; +@@ -66,7 +66,7 @@ Icon[el]=calamares + GenericName[el]=Εγκατάσταση συστήματος + Comment[el]=Calamares — Εγκατάσταση συστήματος + Name[en_GB]=Install System +-Icon[en_GB]=calamares ++Icon[en_GB]=/usr/share/applications/openEuler.png + GenericName[en_GB]=System Installer + Comment[en_GB]=Calamares — System Installer + Name[eo]=Instali Sistemo +@@ -226,7 +226,7 @@ Icon[tr_TR]=calamares + GenericName[tr_TR]=Sistem Yükleyici + Comment[tr_TR]=Calamares — Sistem Yükleyici + Name[uk]=Встановити Систему +-Icon[uk]=calamares ++Icon[uk]=/usr/share/applications/openEuler.png + GenericName[uk]=Встановлювач системи + Comment[uk]=Calamares - Встановлювач системи + Name[vi]=Cài đặt hệ thống +@@ -234,10 +234,10 @@ Icon[vi]=calamares + GenericName[vi]=Bộ cài đặt hệ thống + Comment[vi]=Calamares — Bộ cài đặt hệ thống + Name[zh_CN]=安装系统 +-Icon[zh_CN]=calamares ++Icon[zh_CN]=/usr/share/applications/openEuler.png + GenericName[zh_CN]=系统安装程序 + Comment[zh_CN]=Calamares — 系统安装程序 + Name[zh_TW]=安裝系統 +-Icon[zh_TW]=calamares ++Icon[zh_TW]=/usr/share/applications/openEuler.png + GenericName[zh_TW]=系統安裝程式 + Comment[zh_TW]=Calamares ── 系統安裝程式 +diff --git a/lang/calamares_zh_CN.ts b/lang/calamares_zh_CN.ts +index 75ffe95..3479fd1 100644 +--- a/lang/calamares_zh_CN.ts ++++ b/lang/calamares_zh_CN.ts +@@ -1032,7 +1032,7 @@ The installer will quit and all changes will be lost. + + The timezone will be set to %1. + @info +- 设置时区为 %1. ++ 设置时区为 %1。 + + + The timezone whill be set to %1. +diff --git a/lang/tz_zh_CN.ts b/lang/tz_zh_CN.ts +new file mode 100644 +index 0000000..b154b93 +--- /dev/null ++++ b/lang/tz_zh_CN.ts +@@ -0,0 +1,2626 @@ ++ ++ ++ ++ ++ ++ QObject ++ ++ ++ Africa ++ tz_regions ++ 非洲 ++ ++ ++ ++ America ++ tz_regions ++ 美洲 ++ ++ ++ ++ Antarctica ++ tz_regions ++ 南极洲 ++ ++ ++ ++ Arctic ++ tz_regions ++ 北极 ++ ++ ++ ++ Asia ++ tz_regions ++ 亚洲 ++ ++ ++ ++ Atlantic ++ tz_regions ++ 大西洋 ++ ++ ++ ++ Australia ++ tz_regions ++ 澳大利亚 ++ ++ ++ ++ Europe ++ tz_regions ++ 欧洲 ++ ++ ++ ++ Indian ++ tz_regions ++ 印度 ++ ++ ++ ++ Pacific ++ tz_regions ++ 太平洋 ++ ++ ++ ++ Abidjan ++ tz_names ++ 阿比让 ++ ++ ++ ++ Accra ++ tz_names ++ 阿克拉 ++ ++ ++ ++ Adak ++ tz_names ++ 阿达克 ++ ++ ++ ++ Addis Ababa ++ tz_names ++ 亚的斯亚贝巴 ++ ++ ++ ++ Adelaide ++ tz_names ++ 阿德莱德 ++ ++ ++ ++ Aden ++ tz_names ++ 亚丁 ++ ++ ++ ++ Algiers ++ tz_names ++ 阿尔及尔 ++ ++ ++ ++ Almaty ++ tz_names ++ 阿拉木图 ++ ++ ++ ++ Amman ++ tz_names ++ 安曼 ++ ++ ++ ++ Amsterdam ++ tz_names ++ 阿姆斯特丹 ++ ++ ++ ++ Anadyr ++ tz_names ++ 阿纳迪尔 ++ ++ ++ ++ Anchorage ++ tz_names ++ 安克雷奇 ++ ++ ++ ++ Andorra ++ tz_names ++ 安道尔 ++ ++ ++ ++ Anguilla ++ tz_names ++ 安圭拉 ++ ++ ++ ++ Antananarivo ++ tz_names ++ 塔那那利佛 ++ ++ ++ ++ Antigua ++ tz_names ++ 安提瓜 ++ ++ ++ ++ Apia ++ tz_names ++ 阿皮亚 ++ ++ ++ ++ Aqtau ++ tz_names ++ 阿克托 ++ ++ ++ ++ Aqtobe ++ tz_names ++ 阿克托贝 ++ ++ ++ ++ Araguaina ++ tz_names ++ 阿拉瓜伊纳 ++ ++ ++ ++ Argentina/Buenos Aires ++ tz_names ++ 阿根廷/布宜诺斯艾利斯 ++ ++ ++ ++ Argentina/Catamarca ++ tz_names ++ 阿根廷/卡塔马卡 ++ ++ ++ ++ Argentina/Cordoba ++ tz_names ++ 阿根廷/科尔多瓦 ++ ++ ++ ++ Argentina/Jujuy ++ tz_names ++ 阿根廷/胡胡伊 ++ ++ ++ ++ Argentina/La Rioja ++ tz_names ++ 阿根廷/拉里奥哈 ++ ++ ++ ++ Argentina/Mendoza ++ tz_names ++ 阿根廷/门多萨 ++ ++ ++ ++ Argentina/Rio Gallegos ++ tz_names ++ 阿根廷/里奥加列戈斯 ++ ++ ++ ++ Argentina/Salta ++ tz_names ++ 阿根廷/萨尔塔 ++ ++ ++ ++ Argentina/San Juan ++ tz_names ++ 阿根廷/圣胡安 ++ ++ ++ ++ Argentina/San Luis ++ tz_names ++ 阿根廷/圣路易斯 ++ ++ ++ ++ Argentina/Tucuman ++ tz_names ++ 阿根廷/图库曼 ++ ++ ++ ++ Argentina/Ushuaia ++ tz_names ++ 阿根廷/乌斯怀亚 ++ ++ ++ ++ Aruba ++ tz_names ++ 阿鲁巴 ++ ++ ++ ++ Ashgabat ++ tz_names ++ 阿什哈巴德 ++ ++ ++ ++ Asmara ++ tz_names ++ 阿斯马拉 ++ ++ ++ ++ Astrakhan ++ tz_names ++ 阿斯特拉罕 ++ ++ ++ ++ Asuncion ++ tz_names ++ 亚松森 ++ ++ ++ ++ Athens ++ tz_names ++ 雅典 ++ ++ ++ ++ Atikokan ++ tz_names ++ 阿提科坎 ++ ++ ++ ++ Atyrau ++ tz_names ++ 阿特劳 ++ ++ ++ ++ Auckland ++ tz_names ++ 奥克兰 ++ ++ ++ ++ Azores ++ tz_names ++ 亚速尔群岛 ++ ++ ++ ++ Baghdad ++ tz_names ++ 巴格达 ++ ++ ++ ++ Bahia ++ tz_names ++ 巴伊亚 ++ ++ ++ ++ Bahia Banderas ++ tz_names ++ 巴伊亚·班德拉斯 ++ ++ ++ ++ Bahrain ++ tz_names ++ 巴林 ++ ++ ++ ++ Baku ++ tz_names ++ 巴库 ++ ++ ++ ++ Bamako ++ tz_names ++ 巴马科 ++ ++ ++ ++ Bangkok ++ tz_names ++ 曼谷 ++ ++ ++ ++ Bangui ++ tz_names ++ 班吉 ++ ++ ++ ++ Banjul ++ tz_names ++ 班珠尔 ++ ++ ++ ++ Barbados ++ tz_names ++ 巴巴多斯 ++ ++ ++ ++ Barnaul ++ tz_names ++ 巴尔瑙尔 ++ ++ ++ ++ Beirut ++ tz_names ++ 贝鲁特 ++ ++ ++ ++ Belem ++ tz_names ++ 贝伦 ++ ++ ++ ++ Belgrade ++ tz_names ++ 贝尔格莱德 ++ ++ ++ ++ Belize ++ tz_names ++ 伯利兹 ++ ++ ++ ++ Berlin ++ tz_names ++ 柏林 ++ ++ ++ ++ Bermuda ++ tz_names ++ 百慕大 ++ ++ ++ ++ Bishkek ++ tz_names ++ 比什凯克 ++ ++ ++ ++ Bissau ++ tz_names ++ 比绍 ++ ++ ++ ++ Blanc-Sablon ++ tz_names ++ 布兰克·萨布隆 ++ ++ ++ ++ Blantyre ++ tz_names ++ 布兰太尔 ++ ++ ++ ++ Boa Vista ++ tz_names ++ 博阿维斯塔 ++ ++ ++ ++ Bogota ++ tz_names ++ 波哥大 ++ ++ ++ ++ Boise ++ tz_names ++ 博伊西 ++ ++ ++ ++ Bougainville ++ tz_names ++ 布干维尔 ++ ++ ++ ++ Bratislava ++ tz_names ++ 布拉迪斯拉发 ++ ++ ++ ++ Brazzaville ++ tz_names ++ 布拉柴维尔 ++ ++ ++ ++ Brisbane ++ tz_names ++ 布里斯班 ++ ++ ++ ++ Broken Hill ++ tz_names ++ 布罗肯希尔 ++ ++ ++ ++ Brunei ++ tz_names ++ 文莱 ++ ++ ++ ++ Brussels ++ tz_names ++ 布鲁塞尔 ++ ++ ++ ++ Beijing ++ tz_names ++ 北京 ++ ++ ++ ++ Bucharest ++ tz_names ++ 布加勒斯特 ++ ++ ++ ++ Budapest ++ tz_names ++ 布达佩斯 ++ ++ ++ ++ Bujumbura ++ tz_names ++ 布琼布拉 ++ ++ ++ ++ Busingen ++ tz_names ++ 比辛根 ++ ++ ++ ++ Cairo ++ tz_names ++ 开罗 ++ ++ ++ ++ Cambridge Bay ++ tz_names ++ 剑桥湾 ++ ++ ++ ++ Campo Grande ++ tz_names ++ 坎波格兰德 ++ ++ ++ ++ Canary ++ tz_names ++ 加那利群岛 ++ ++ ++ ++ Cancun ++ tz_names ++ 坎昆 ++ ++ ++ ++ Cape Verde ++ tz_names ++ 佛得角 ++ ++ ++ ++ Caracas ++ tz_names ++ 加拉加斯 ++ ++ ++ ++ Casablanca ++ tz_names ++ 卡萨布兰卡 ++ ++ ++ ++ Casey ++ tz_names ++ 凯西 ++ ++ ++ ++ Cayenne ++ tz_names ++ 卡宴 ++ ++ ++ ++ Cayman ++ tz_names ++ 开曼群岛 ++ ++ ++ ++ Ceuta ++ tz_names ++ 休达 ++ ++ ++ ++ Chagos ++ tz_names ++ 查戈斯 ++ ++ ++ ++ Chatham ++ tz_names ++ 查塔姆 ++ ++ ++ ++ Chicago ++ tz_names ++ 芝加哥 ++ ++ ++ ++ Chihuahua ++ tz_names ++ 吉娃娃 ++ ++ ++ ++ Chisinau ++ tz_names ++ 基希讷乌 ++ ++ ++ ++ Chita ++ tz_names ++ 赤塔 ++ ++ ++ ++ Choibalsan ++ tz_names ++ 乔巴桑 ++ ++ ++ ++ Christmas ++ tz_names ++ 伯利恒 ++ ++ ++ ++ Chuuk ++ tz_names ++ 楚克 ++ ++ ++ ++ Cocos ++ tz_names ++ 科科斯 ++ ++ ++ ++ Colombo ++ tz_names ++ 科伦坡 ++ ++ ++ ++ Comoro ++ tz_names ++ 科摩罗 ++ ++ ++ ++ Conakry ++ tz_names ++ 科纳克里 ++ ++ ++ ++ Copenhagen ++ tz_names ++ 哥本哈根 ++ ++ ++ ++ Costa Rica ++ tz_names ++ 哥斯达黎加 ++ ++ ++ ++ Creston ++ tz_names ++ 克雷斯顿 ++ ++ ++ ++ Cuiaba ++ tz_names ++ 库亚巴 ++ ++ ++ ++ Curacao ++ tz_names ++ 库拉索 ++ ++ ++ ++ Currie ++ tz_names ++ 柯里 ++ ++ ++ ++ Dakar ++ tz_names ++ 达喀尔 ++ ++ ++ ++ Damascus ++ tz_names ++ 大马士革 ++ ++ ++ ++ Danmarkshavn ++ tz_names ++ 丹麦 ++ ++ ++ ++ Dar es Salaam ++ tz_names ++ 达累斯萨拉姆 ++ ++ ++ ++ Darwin ++ tz_names ++ 达尔文 ++ ++ ++ ++ Davis ++ tz_names ++ 戴维斯 ++ ++ ++ ++ Dawson ++ tz_names ++ 道森 ++ ++ ++ ++ Dawson Creek ++ tz_names ++ 道森溪 ++ ++ ++ ++ Denver ++ tz_names ++ 丹佛 ++ ++ ++ ++ Detroit ++ tz_names ++ 底特律 ++ ++ ++ ++ Dhaka ++ tz_names ++ 达卡 ++ ++ ++ ++ Dili ++ tz_names ++ 帝力 ++ ++ ++ ++ Djibouti ++ tz_names ++ 吉布提 ++ ++ ++ ++ Dominica ++ tz_names ++ 多米尼克 ++ ++ ++ ++ Douala ++ tz_names ++ 杜阿拉 ++ ++ ++ ++ Dubai ++ tz_names ++ 迪拜 ++ ++ ++ ++ Dublin ++ tz_names ++ 都柏林 ++ ++ ++ ++ DumontDUrville ++ tz_names ++ 杜蒙·杜维尔 ++ ++ ++ ++ Dushanbe ++ tz_names ++ 杜尚别 ++ ++ ++ ++ Easter ++ tz_names ++ 伊斯特迪 ++ ++ ++ ++ Edmonton ++ tz_names ++ 埃德蒙顿 ++ ++ ++ ++ Efate ++ tz_names ++ 埃法特岛 ++ ++ ++ ++ Eirunepe ++ tz_names ++ 埃鲁内佩 ++ ++ ++ ++ El Aaiun ++ tz_names ++ 阿尤恩 ++ ++ ++ ++ El Salvador ++ tz_names ++ 萨尔瓦多 ++ ++ ++ ++ Enderbury ++ tz_names ++ 恩德伯里 ++ ++ ++ ++ Eucla ++ tz_names ++ 尤克拉 ++ ++ ++ ++ Fakaofo ++ tz_names ++ 法考福 ++ ++ ++ ++ Famagusta ++ tz_names ++ 法马古斯塔 ++ ++ ++ ++ Faroe ++ tz_names ++ 法罗 ++ ++ ++ ++ Fiji ++ tz_names ++ 斐济 ++ ++ ++ ++ Fort Nelson ++ tz_names ++ 纳尔逊堡 ++ ++ ++ ++ Fortaleza ++ tz_names ++ 福塔莱萨 ++ ++ ++ ++ Freetown ++ tz_names ++ 弗里敦 ++ ++ ++ ++ Funafuti ++ tz_names ++ 富纳富提 ++ ++ ++ ++ Gaborone ++ tz_names ++ 哈博罗内 ++ ++ ++ ++ Galapagos ++ tz_names ++ 加拉帕戈斯群岛 ++ ++ ++ ++ Gambier ++ tz_names ++ 甘比尔 ++ ++ ++ ++ Gaza ++ tz_names ++ 加沙 ++ ++ ++ ++ Gibraltar ++ tz_names ++ 直布罗陀 ++ ++ ++ ++ Glace Bay ++ tz_names ++ 格莱斯湾 ++ ++ ++ ++ Godthab ++ tz_names ++ 戈德萨布 ++ ++ ++ ++ Goose Bay ++ tz_names ++ 鹅湾 ++ ++ ++ ++ Grand Turk ++ tz_names ++ 大特克 ++ ++ ++ ++ Grenada ++ tz_names ++ 格林纳达 ++ ++ ++ ++ Guadalcanal ++ tz_names ++ 瓜达尔卡纳尔岛 ++ ++ ++ ++ Guadeloupe ++ tz_names ++ 瓜德罗普岛 ++ ++ ++ ++ Guam ++ tz_names ++ 关岛 ++ ++ ++ ++ Guatemala ++ tz_names ++ 危地马拉 ++ ++ ++ ++ Guayaquil ++ tz_names ++ 瓜亚基尔 ++ ++ ++ ++ Guernsey ++ tz_names ++ 根西岛 ++ ++ ++ ++ Guyana ++ tz_names ++ 圭亚那 ++ ++ ++ ++ Halifax ++ tz_names ++ 哈利法克斯 ++ ++ ++ ++ Harare ++ tz_names ++ 哈拉雷 ++ ++ ++ ++ Havana ++ tz_names ++ 哈瓦那 ++ ++ ++ ++ Hebron ++ tz_names ++ 希伯伦 ++ ++ ++ ++ Helsinki ++ tz_names ++ 赫尔辛基 ++ ++ ++ ++ Hermosillo ++ tz_names ++ 埃莫西洛 ++ ++ ++ ++ Ho Chi Minh ++ tz_names ++ 胡志明 ++ ++ ++ ++ Hobart ++ tz_names ++ 霍巴特 ++ ++ ++ ++ Hong Kong(China) ++ tz_names ++ 香港(中国) ++ ++ ++ ++ Honolulu ++ tz_names ++ 檀香山 ++ ++ ++ ++ Hovd ++ tz_names ++ 科布多 ++ ++ ++ ++ Indiana/Indianapolis ++ tz_names ++ 印第安纳州/印第安纳波利斯 ++ ++ ++ ++ Indiana/Knox ++ tz_names ++ 印第安纳州/诺克斯 ++ ++ ++ ++ Indiana/Marengo ++ tz_names ++ 印度/马伦戈 ++ ++ ++ ++ Indiana/Petersburg ++ tz_names ++ 印第安纳州/彼得堡 ++ ++ ++ ++ Indiana/Tell City ++ tz_names ++ 印第安纳州/泰尔城 ++ ++ ++ ++ Indiana/Vevay ++ tz_names ++ 印度/沃韦 ++ ++ ++ ++ Indiana/Vincennes ++ tz_names ++ 印第安纳州/文森斯 ++ ++ ++ ++ Indiana/Winamac ++ tz_names ++ 印第安纳州/威纳马克 ++ ++ ++ ++ Inuvik ++ tz_names ++ 伊努维克 ++ ++ ++ ++ Iqaluit ++ tz_names ++ 伊魁特 ++ ++ ++ ++ Irkutsk ++ tz_names ++ 伊尔库茨克 ++ ++ ++ ++ Isle of Man ++ tz_names ++ 马恩岛 ++ ++ ++ ++ Istanbul ++ tz_names ++ 伊斯坦布尔 ++ ++ ++ ++ Jakarta ++ tz_names ++ 雅加达 ++ ++ ++ ++ Jamaica ++ tz_names ++ 牙买加 ++ ++ ++ ++ Jayapura ++ tz_names ++ 查亚普拉 ++ ++ ++ ++ Jersey ++ tz_names ++ 泽西岛 ++ ++ ++ ++ Jerusalem ++ tz_names ++ 耶路撒冷 ++ ++ ++ ++ Johannesburg ++ tz_names ++ 约翰内斯堡 ++ ++ ++ ++ Juba ++ tz_names ++ 朱巴 ++ ++ ++ ++ Juneau ++ tz_names ++ 朱诺 ++ ++ ++ ++ Kabul ++ tz_names ++ 喀布尔 ++ ++ ++ ++ Kaliningrad ++ tz_names ++ 加里宁格勒 ++ ++ ++ ++ Kamchatka ++ tz_names ++ 堪察加半岛 ++ ++ ++ ++ Kampala ++ tz_names ++ 坎帕拉 ++ ++ ++ ++ Karachi ++ tz_names ++ 卡拉奇 ++ ++ ++ ++ Kathmandu ++ tz_names ++ 加德满都 ++ ++ ++ ++ Kentucky/Louisville ++ tz_names ++ 肯塔基州/路易斯维尔 ++ ++ ++ ++ Kentucky/Monticello ++ tz_names ++ 肯塔基州/蒙蒂塞洛 ++ ++ ++ ++ Kerguelen ++ tz_names ++ 凯尔盖朗 ++ ++ ++ ++ Khandyga ++ tz_names ++ 坎代加 ++ ++ ++ ++ Khartoum ++ tz_names ++ 喀土穆 ++ ++ ++ ++ Kiev ++ tz_names ++ 基辅 ++ ++ ++ ++ Kigali ++ tz_names ++ 基加利 ++ ++ ++ ++ Kinshasa ++ tz_names ++ 金沙萨 ++ ++ ++ ++ Kiritimati ++ tz_names ++ 基里蒂马提斯 ++ ++ ++ ++ Kirov ++ tz_names ++ 基洛夫 ++ ++ ++ ++ Kolkata ++ tz_names ++ 加尔格达 ++ ++ ++ ++ Kosrae ++ tz_names ++ 科斯雷 ++ ++ ++ ++ Kralendijk ++ tz_names ++ 克罗地亚 ++ ++ ++ ++ Krasnoyarsk ++ tz_names ++ 克拉斯诺亚尔斯克 ++ ++ ++ ++ Kuala Lumpur ++ tz_names ++ 吉隆坡 ++ ++ ++ ++ Kuching ++ tz_names ++ 古晋 ++ ++ ++ ++ Kuwait ++ tz_names ++ 科威特 ++ ++ ++ ++ Kwajalein ++ tz_names ++ 夸贾林 ++ ++ ++ ++ La Paz ++ tz_names ++ 拉巴斯 ++ ++ ++ ++ Lagos ++ tz_names ++ 拉各斯 ++ ++ ++ ++ Libreville ++ tz_names ++ 利伯维尔 ++ ++ ++ ++ Lima ++ tz_names ++ 利马 ++ ++ ++ ++ Lindeman ++ tz_names ++ 林德曼 ++ ++ ++ ++ Lisbon ++ tz_names ++ 里斯本 ++ ++ ++ ++ Ljubljana ++ tz_names ++ 卢布尔雅那 ++ ++ ++ ++ Lome ++ tz_names ++ 多哥 ++ ++ ++ ++ London ++ tz_names ++ 伦敦 ++ ++ ++ ++ Longyearbyen ++ tz_names ++ 朗伊尔城 ++ ++ ++ ++ Lord Howe ++ tz_names ++ 豪勋爵 ++ ++ ++ ++ Los Angeles ++ tz_names ++ 洛杉矶 ++ ++ ++ ++ Lower Princes ++ tz_names ++ 圣马丁 ++ ++ ++ ++ Luanda ++ tz_names ++ 罗安达 ++ ++ ++ ++ Lubumbashi ++ tz_names ++ 卢本巴希 ++ ++ ++ ++ Lusaka ++ tz_names ++ 卢萨卡 ++ ++ ++ ++ Luxembourg ++ tz_names ++ 卢森堡 ++ ++ ++ ++ Macau(China) ++ tz_names ++ 澳门(中国) ++ ++ ++ ++ Maceio ++ tz_names ++ 马塞奥 ++ ++ ++ ++ Macquarie ++ tz_names ++ 麦格理 ++ ++ ++ ++ Madeira ++ tz_names ++ 马德拉 ++ ++ ++ ++ Madrid ++ tz_names ++ 马德里 ++ ++ ++ ++ Magadan ++ tz_names ++ 马加丹 ++ ++ ++ ++ Mahe ++ tz_names ++ 马埃 ++ ++ ++ ++ Majuro ++ tz_names ++ 马朱罗 ++ ++ ++ ++ Makassar ++ tz_names ++ 望加锡 ++ ++ ++ ++ Malabo ++ tz_names ++ 马拉博 ++ ++ ++ ++ Maldives ++ tz_names ++ 马尔代夫 ++ ++ ++ ++ Malta ++ tz_names ++ 马耳他 ++ ++ ++ ++ Managua ++ tz_names ++ 马那瓜 ++ ++ ++ ++ Manaus ++ tz_names ++ 马瑙斯 ++ ++ ++ ++ Manila ++ tz_names ++ 马尼拉 ++ ++ ++ ++ Maputo ++ tz_names ++ 马普托 ++ ++ ++ ++ Mariehamn ++ tz_names ++ 玛丽港 ++ ++ ++ ++ Marigot ++ tz_names ++ 马里戈 ++ ++ ++ ++ Marquesas ++ tz_names ++ 马克萨斯 ++ ++ ++ ++ Martinique ++ tz_names ++ 马提尼克岛 ++ ++ ++ ++ Maseru ++ tz_names ++ 马塞卢 ++ ++ ++ ++ Matamoros ++ tz_names ++ 马塔莫罗斯 ++ ++ ++ ++ Mauritius ++ tz_names ++ 毛里求斯 ++ ++ ++ ++ Mawson ++ tz_names ++ 莫森 ++ ++ ++ ++ Mayotte ++ tz_names ++ 马约特岛 ++ ++ ++ ++ Mazatlan ++ tz_names ++ 马萨特兰 ++ ++ ++ ++ Mbabane ++ tz_names ++ 姆巴巴内 ++ ++ ++ ++ McMurdo ++ tz_names ++ 麦克默多 ++ ++ ++ ++ Melbourne ++ tz_names ++ 墨尔本 ++ ++ ++ ++ Menominee ++ tz_names ++ 梅诺米尼 ++ ++ ++ ++ Merida ++ tz_names ++ 梅里达 ++ ++ ++ ++ Metlakatla ++ tz_names ++ 梅特拉卡特拉 ++ ++ ++ ++ Mexico City ++ tz_names ++ 墨西哥城 ++ ++ ++ ++ Midway ++ tz_names ++ 中途岛 ++ ++ ++ ++ Minsk ++ tz_names ++ 明斯克 ++ ++ ++ ++ Miquelon ++ tz_names ++ 密克隆 ++ ++ ++ ++ Mogadishu ++ tz_names ++ 摩加迪沙 ++ ++ ++ ++ Monaco ++ tz_names ++ 摩纳哥 ++ ++ ++ ++ Moncton ++ tz_names ++ 蒙克顿 ++ ++ ++ ++ Monrovia ++ tz_names ++ 蒙罗维亚 ++ ++ ++ ++ Monterrey ++ tz_names ++ 蒙特雷 ++ ++ ++ ++ Montevideo ++ tz_names ++ 蒙得维的亚 ++ ++ ++ ++ Montserrat ++ tz_names ++ 蒙特塞拉特 ++ ++ ++ ++ Moscow ++ tz_names ++ 莫斯科 ++ ++ ++ ++ Muscat ++ tz_names ++ 马斯喀特 ++ ++ ++ ++ Nairobi ++ tz_names ++ 内罗毕 ++ ++ ++ ++ Nassau ++ tz_names ++ 拿骚 ++ ++ ++ ++ Nauru ++ tz_names ++ 瑙鲁 ++ ++ ++ ++ Ndjamena ++ tz_names ++ 恩贾梅纳 ++ ++ ++ ++ New York ++ tz_names ++ 纽约 ++ ++ ++ ++ Niamey ++ tz_names ++ 尼亚美 ++ ++ ++ ++ Nicosia ++ tz_names ++ 尼科西亚 ++ ++ ++ ++ Nipigon ++ tz_names ++ 尼皮贡 ++ ++ ++ ++ Niue ++ tz_names ++ 纽埃 ++ ++ ++ ++ Nome ++ tz_names ++ 诺姆 ++ ++ ++ ++ Norfolk ++ tz_names ++ 诺福克 ++ ++ ++ ++ Noronha ++ tz_names ++ 诺罗尼亚 ++ ++ ++ ++ North Dakota/Beulah ++ tz_names ++ 北达科他州/比拉 ++ ++ ++ ++ North Dakota/Center ++ tz_names ++ 北达科他州/中心 ++ ++ ++ ++ North Dakota/New Salem ++ tz_names ++ 北达科他州/新塞勒姆 ++ ++ ++ ++ Nouakchott ++ tz_names ++ 努瓦克肖特 ++ ++ ++ ++ Noumea ++ tz_names ++ 努美阿 ++ ++ ++ ++ Novokuznetsk ++ tz_names ++ 新库兹涅茨克 ++ ++ ++ ++ Novosibirsk ++ tz_names ++ 新西伯利亚 ++ ++ ++ ++ Ojinaga ++ tz_names ++ 魁北克 ++ ++ ++ ++ Omsk ++ tz_names ++ 鄂木斯克 ++ ++ ++ ++ Oral ++ tz_names ++ 多拉 ++ ++ ++ ++ Oslo ++ tz_names ++ 奥斯陆 ++ ++ ++ ++ Ouagadougou ++ tz_names ++ 瓦加杜古 ++ ++ ++ ++ Pago Pago ++ tz_names ++ 帕果帕果 ++ ++ ++ ++ Palau ++ tz_names ++ 帕劳 ++ ++ ++ ++ Palmer ++ tz_names ++ 帕尔默 ++ ++ ++ ++ Panama ++ tz_names ++ 巴拿马 ++ ++ ++ ++ Pangnirtung ++ tz_names ++ 巴芬岛的旁涅唐 ++ ++ ++ ++ Paramaribo ++ tz_names ++ 帕拉马里博 ++ ++ ++ ++ Paris ++ tz_names ++ 巴黎 ++ ++ ++ ++ Perth ++ tz_names ++ 珀斯 ++ ++ ++ ++ Phnom Penh ++ tz_names ++ 金边 ++ ++ ++ ++ Phoenix ++ tz_names ++ 凤凰城 ++ ++ ++ ++ Pitcairn ++ tz_names ++ 皮特凯恩 ++ ++ ++ ++ Podgorica ++ tz_names ++ 波德戈里察 ++ ++ ++ ++ Pohnpei ++ tz_names ++ 波纳佩岛 ++ ++ ++ ++ Pontianak ++ tz_names ++ 坤甸 ++ ++ ++ ++ Port Moresby ++ tz_names ++ 莫尔兹比港 ++ ++ ++ ++ Port of Spain ++ tz_names ++ 西班牙港 ++ ++ ++ ++ Port-au-Prince ++ tz_names ++ 太子港 ++ ++ ++ ++ Porto Velho ++ tz_names ++ 维略港 ++ ++ ++ ++ Porto-Novo ++ tz_names ++ 波多诺伏 ++ ++ ++ ++ Prague ++ tz_names ++ 布拉格 ++ ++ ++ ++ Puerto Rico ++ tz_names ++ 波多黎各 ++ ++ ++ ++ Punta Arenas ++ tz_names ++ 蓬塔阿雷纳斯 ++ ++ ++ ++ Pyongyang ++ tz_names ++ 平壤 ++ ++ ++ ++ Qatar ++ tz_names ++ 卡塔尔 ++ ++ ++ ++ Qostanay ++ tz_names ++ 库斯塔 ++ ++ ++ ++ Qyzylorda ++ tz_names ++ 克孜勒奥尔达 ++ ++ ++ ++ Rainy River ++ tz_names ++ 雷尼河 ++ ++ ++ ++ Rankin Inlet ++ tz_names ++ 兰京海口 ++ ++ ++ ++ Rarotonga ++ tz_names ++ 拉罗汤加 ++ ++ ++ ++ Recife ++ tz_names ++ 累西腓 ++ ++ ++ ++ Regina ++ tz_names ++ 里贾纳 ++ ++ ++ ++ Resolute ++ tz_names ++ 雷索卢特 ++ ++ ++ ++ Reunion ++ tz_names ++ 留尼旺岛 ++ ++ ++ ++ Reykjavik ++ tz_names ++ 雷克雅未克 ++ ++ ++ ++ Riga ++ tz_names ++ 里加 ++ ++ ++ ++ Rio Branco ++ tz_names ++ 里奥·布兰科 ++ ++ ++ ++ Riyadh ++ tz_names ++ 利雅得 ++ ++ ++ ++ Rome ++ tz_names ++ 罗马 ++ ++ ++ ++ Rothera ++ tz_names ++ 罗瑟拉 ++ ++ ++ ++ Saipan ++ tz_names ++ 塞班岛 ++ ++ ++ ++ Sakhalin ++ tz_names ++ 萨哈林 ++ ++ ++ ++ Samara ++ tz_names ++ 萨马拉 ++ ++ ++ ++ Samarkand ++ tz_names ++ 撒马尔罕 ++ ++ ++ ++ San Marino ++ tz_names ++ 圣马力诺 ++ ++ ++ ++ Santarem ++ tz_names ++ 圣塔伦 ++ ++ ++ ++ Santiago ++ tz_names ++ 圣地亚哥 ++ ++ ++ ++ Santo Domingo ++ tz_names ++ 圣多明各 ++ ++ ++ ++ Sao Paulo ++ tz_names ++ 圣保罗 ++ ++ ++ ++ Sao Tome ++ tz_names ++ 圣多美 ++ ++ ++ ++ Sarajevo ++ tz_names ++ 萨拉热窝 ++ ++ ++ ++ Saratov ++ tz_names ++ 萨拉托夫 ++ ++ ++ ++ Scoresbysund ++ tz_names ++ 斯科斯比基金 ++ ++ ++ ++ Seoul ++ tz_names ++ 首尔 ++ ++ ++ ++ Shanghai ++ tz_names ++ 上海 ++ ++ ++ ++ Simferopol ++ tz_names ++ 辛菲罗波尔 ++ ++ ++ ++ Singapore ++ tz_names ++ 新加坡 ++ ++ ++ ++ Sitka ++ tz_names ++ 锡特卡 ++ ++ ++ ++ Skopje ++ tz_names ++ 斯科普里 ++ ++ ++ ++ Sofia ++ tz_names ++ 索菲亚 ++ ++ ++ ++ South Georgia ++ tz_names ++ 南乔治亚州 ++ ++ ++ ++ Srednekolymsk ++ tz_names ++ 雅库特 ++ ++ ++ ++ St Barthelemy ++ tz_names ++ 圣巴泰勒米 ++ ++ ++ ++ St Helena ++ tz_names ++ 圣赫勒拿 ++ ++ ++ ++ St Johns ++ tz_names ++ 圣约翰 ++ ++ ++ ++ St Kitts ++ tz_names ++ 圣基茨 ++ ++ ++ ++ St Lucia ++ tz_names ++ 圣卢西亚 ++ ++ ++ ++ St Thomas ++ tz_names ++ 圣托马斯 ++ ++ ++ ++ St Vincent ++ tz_names ++ 圣文森特 ++ ++ ++ ++ Stanley ++ tz_names ++ 斯坦利 ++ ++ ++ ++ Stockholm ++ tz_names ++ 斯德哥尔摩 ++ ++ ++ ++ Swift Current ++ tz_names ++ 斯威夫特卡伦特 ++ ++ ++ ++ Sydney ++ tz_names ++ 悉尼 ++ ++ ++ ++ Syowa ++ tz_names ++ 圣何塞 ++ ++ ++ ++ Tahiti ++ tz_names ++ 大溪地 ++ ++ ++ ++ Taipei(China) ++ tz_names ++ 台北(中国) ++ ++ ++ ++ Tallinn ++ tz_names ++ 塔林 ++ ++ ++ ++ Tarawa ++ tz_names ++ 塔拉瓦 ++ ++ ++ ++ Tashkent ++ tz_names ++ 塔什干 ++ ++ ++ ++ Tbilisi ++ tz_names ++ 第比利斯 ++ ++ ++ ++ Tegucigalpa ++ tz_names ++ 特古西加尔巴 ++ ++ ++ ++ Tehran ++ tz_names ++ 德黑兰 ++ ++ ++ ++ Thimphu ++ tz_names ++ 廷布 ++ ++ ++ ++ Thule ++ tz_names ++ 图勒 ++ ++ ++ ++ Thunder Bay ++ tz_names ++ 雷湾 ++ ++ ++ ++ Tijuana ++ tz_names ++ 蒂华纳 ++ ++ ++ ++ Tirane ++ tz_names ++ 地拉那 ++ ++ ++ ++ Tokyo ++ tz_names ++ 东京 ++ ++ ++ ++ Tomsk ++ tz_names ++ 托木斯克 ++ ++ ++ ++ Tongatapu ++ tz_names ++ 汤加塔布 ++ ++ ++ ++ Toronto ++ tz_names ++ 多伦多 ++ ++ ++ ++ Tortola ++ tz_names ++ 托托拉岛 ++ ++ ++ ++ Tripoli ++ tz_names ++ 的黎波里 ++ ++ ++ ++ Troll ++ tz_names ++ 特罗尔海坦 ++ ++ ++ ++ Tunis ++ tz_names ++ 突尼斯 ++ ++ ++ ++ Ulaanbaatar ++ tz_names ++ 乌兰巴托 ++ ++ ++ ++ Ulyanovsk ++ tz_names ++ 乌里扬诺夫斯克 ++ ++ ++ ++ Urumqi ++ tz_names ++ 乌鲁木齐 ++ ++ ++ ++ Ust-Nera ++ tz_names ++ 乌斯季挪拉 ++ ++ ++ ++ Uzhgorod ++ tz_names ++ 乌日哥罗德 ++ ++ ++ ++ Vaduz ++ tz_names ++ 瓦杜兹 ++ ++ ++ ++ Vancouver ++ tz_names ++ 温哥华 ++ ++ ++ ++ Vatican ++ tz_names ++ 梵蒂冈 ++ ++ ++ ++ Vienna ++ tz_names ++ 维也纳 ++ ++ ++ ++ Vientiane ++ tz_names ++ 万象 ++ ++ ++ ++ Vilnius ++ tz_names ++ 维尔纽斯 ++ ++ ++ ++ Vladivostok ++ tz_names ++ 符拉迪沃斯托克 ++ ++ ++ ++ Volgograd ++ tz_names ++ 伏尔加格勒 ++ ++ ++ ++ Vostok ++ tz_names ++ 沃斯托克 ++ ++ ++ ++ Wake ++ tz_names ++ 韦克 ++ ++ ++ ++ Wallis ++ tz_names ++ 沃利斯 ++ ++ ++ ++ Warsaw ++ tz_names ++ 华沙 ++ ++ ++ ++ Whitehorse ++ tz_names ++ 怀特霍斯 ++ ++ ++ ++ Windhoek ++ tz_names ++ 温得和克 ++ ++ ++ ++ Winnipeg ++ tz_names ++ 温尼伯 ++ ++ ++ ++ Yakutat ++ tz_names ++ 雅库特 ++ ++ ++ ++ Yakutsk ++ tz_names ++ 雅库茨克 ++ ++ ++ ++ Yangon ++ tz_names ++ 仰光 ++ ++ ++ ++ Yekaterinburg ++ tz_names ++ 叶卡捷琳堡 ++ ++ ++ ++ Yellowknife ++ tz_names ++ 耶洛奈夫 ++ ++ ++ ++ Yerevan ++ tz_names ++ 埃里温 ++ ++ ++ ++ Zagreb ++ tz_names ++ 萨格勒布 ++ ++ ++ ++ Zaporozhye ++ tz_names ++ 扎波罗热 ++ ++ ++ ++ Zurich ++ tz_names ++ 苏黎世 ++ ++ ++ +diff --git a/lang/tz_zh_TW.ts b/lang/tz_zh_TW.ts +new file mode 100644 +index 0000000..2713d37 +--- /dev/null ++++ b/lang/tz_zh_TW.ts +@@ -0,0 +1,2626 @@ ++ ++ ++ ++ ++ ++ QObject ++ ++ ++ Africa ++ tz_regions ++ 非洲 ++ ++ ++ ++ America ++ tz_regions ++ 美洲 ++ ++ ++ ++ Antarctica ++ tz_regions ++ 南極洲 ++ ++ ++ ++ Arctic ++ tz_regions ++ 北極 ++ ++ ++ ++ Asia ++ tz_regions ++ 亞洲 ++ ++ ++ ++ Atlantic ++ tz_regions ++ 大西洋 ++ ++ ++ ++ Australia ++ tz_regions ++ 澳大利亞 ++ ++ ++ ++ Europe ++ tz_regions ++ 歐洲 ++ ++ ++ ++ Indian ++ tz_regions ++ 印度 ++ ++ ++ ++ Pacific ++ tz_regions ++ 太平洋 ++ ++ ++ ++ Abidjan ++ tz_names ++ 阿必尚 ++ ++ ++ ++ Accra ++ tz_names ++ 阿克拉 ++ ++ ++ ++ Adak ++ tz_names ++ 阿達克 ++ ++ ++ ++ Addis Ababa ++ tz_names ++ 阿迪斯阿貝巴 ++ ++ ++ ++ Adelaide ++ tz_names ++ 阿德萊德 ++ ++ ++ ++ Aden ++ tz_names ++ 亞丁 ++ ++ ++ ++ Algiers ++ tz_names ++ 阿爾及爾 ++ ++ ++ ++ Almaty ++ tz_names ++ 阿拉木圖 ++ ++ ++ ++ Amman ++ tz_names ++ 安曼 ++ ++ ++ ++ Amsterdam ++ tz_names ++ 阿姆斯特丹 ++ ++ ++ ++ Anadyr ++ tz_names ++ 阿納迪爾 ++ ++ ++ ++ Anchorage ++ tz_names ++ 安克雷奇 ++ ++ ++ ++ Andorra ++ tz_names ++ 安道爾 ++ ++ ++ ++ Anguilla ++ tz_names ++ 安圭拉 ++ ++ ++ ++ Antananarivo ++ tz_names ++ 安塔那那利佛 ++ ++ ++ ++ Antigua ++ tz_names ++ 安提瓜 ++ ++ ++ ++ Apia ++ tz_names ++ 亞庇 ++ ++ ++ ++ Aqtau ++ tz_names ++ 阿克托 ++ ++ ++ ++ Aqtobe ++ tz_names ++ 阿克托貝 ++ ++ ++ ++ Araguaina ++ tz_names ++ 阿拉瓜伊納 ++ ++ ++ ++ Argentina/Buenos Aires ++ tz_names ++ 阿根廷/布宜諾賽勒斯 ++ ++ ++ ++ Argentina/Catamarca ++ tz_names ++ 阿根廷/卡塔馬卡 ++ ++ ++ ++ Argentina/Cordoba ++ tz_names ++ 阿根廷/科爾多瓦 ++ ++ ++ ++ Argentina/Jujuy ++ tz_names ++ 阿根廷/胡胡伊 ++ ++ ++ ++ Argentina/La Rioja ++ tz_names ++ 阿根廷/拉里奧哈 ++ ++ ++ ++ Argentina/Mendoza ++ tz_names ++ 阿根廷/門多薩 ++ ++ ++ ++ Argentina/Rio Gallegos ++ tz_names ++ 阿根廷/裏奧加列戈斯 ++ ++ ++ ++ Argentina/Salta ++ tz_names ++ 阿根廷/薩爾塔 ++ ++ ++ ++ Argentina/San Juan ++ tz_names ++ 阿根廷/聖胡安 ++ ++ ++ ++ Argentina/San Luis ++ tz_names ++ 阿根廷/聖路易斯 ++ ++ ++ ++ Argentina/Tucuman ++ tz_names ++ 阿根廷/圖庫曼 ++ ++ ++ ++ Argentina/Ushuaia ++ tz_names ++ 阿根廷/烏斯懷亞 ++ ++ ++ ++ Aruba ++ tz_names ++ 阿魯巴 ++ ++ ++ ++ Ashgabat ++ tz_names ++ 阿什哈巴德 ++ ++ ++ ++ Asmara ++ tz_names ++ 阿斯馬拉 ++ ++ ++ ++ Astrakhan ++ tz_names ++ 阿斯特拉罕 ++ ++ ++ ++ Asuncion ++ tz_names ++ 亞松森 ++ ++ ++ ++ Athens ++ tz_names ++ 雅典 ++ ++ ++ ++ Atikokan ++ tz_names ++ 阿提科坎 ++ ++ ++ ++ Atyrau ++ tz_names ++ 阿特勞 ++ ++ ++ ++ Auckland ++ tz_names ++ 奧克蘭 ++ ++ ++ ++ Azores ++ tz_names ++ 亞速爾群島 ++ ++ ++ ++ Baghdad ++ tz_names ++ 巴格達 ++ ++ ++ ++ Bahia ++ tz_names ++ 巴伊亞 ++ ++ ++ ++ Bahia Banderas ++ tz_names ++ 巴伊亞·班德拉斯 ++ ++ ++ ++ Bahrain ++ tz_names ++ 巴林 ++ ++ ++ ++ Baku ++ tz_names ++ 巴庫 ++ ++ ++ ++ Bamako ++ tz_names ++ 巴馬科 ++ ++ ++ ++ Bangkok ++ tz_names ++ 曼谷 ++ ++ ++ ++ Bangui ++ tz_names ++ 班基 ++ ++ ++ ++ Banjul ++ tz_names ++ 班竹 ++ ++ ++ ++ Barbados ++ tz_names ++ 巴巴多斯 ++ ++ ++ ++ Barnaul ++ tz_names ++ 巴爾瑙爾 ++ ++ ++ ++ Beirut ++ tz_names ++ 貝魯特 ++ ++ ++ ++ Belem ++ tz_names ++ 貝倫 ++ ++ ++ ++ Belgrade ++ tz_names ++ 貝爾格勒 ++ ++ ++ ++ Belize ++ tz_names ++ 貝裡斯 ++ ++ ++ ++ Berlin ++ tz_names ++ 柏林 ++ ++ ++ ++ Bermuda ++ tz_names ++ 百慕大 ++ ++ ++ ++ Bishkek ++ tz_names ++ 比什凱克 ++ ++ ++ ++ Bissau ++ tz_names ++ 比索 ++ ++ ++ ++ Beijing ++ tz_names ++ 北京 ++ ++ ++ ++ Blanc-Sablon ++ tz_names ++ 布蘭克·薩布隆 ++ ++ ++ ++ Blantyre ++ tz_names ++ 布蘭太爾 ++ ++ ++ ++ Boa Vista ++ tz_names ++ 博阿維斯塔 ++ ++ ++ ++ Bogota ++ tz_names ++ 波哥大 ++ ++ ++ ++ Boise ++ tz_names ++ 博伊西 ++ ++ ++ ++ Bougainville ++ tz_names ++ 布幹維爾 ++ ++ ++ ++ Bratislava ++ tz_names ++ 布拉提斯拉瓦 ++ ++ ++ ++ Brazzaville ++ tz_names ++ 布拉柴維爾 ++ ++ ++ ++ Brisbane ++ tz_names ++ 布里斯班 ++ ++ ++ ++ Broken Hill ++ tz_names ++ 布羅肯希爾 ++ ++ ++ ++ Brunei ++ tz_names ++ 汶萊 ++ ++ ++ ++ Brussels ++ tz_names ++ 布魯塞爾 ++ ++ ++ ++ Bucharest ++ tz_names ++ 布加勒斯特 ++ ++ ++ ++ Budapest ++ tz_names ++ 布達佩斯 ++ ++ ++ ++ Bujumbura ++ tz_names ++ 布松布拉 ++ ++ ++ ++ Busingen ++ tz_names ++ 匯流排 ++ ++ ++ ++ Cairo ++ tz_names ++ 開羅 ++ ++ ++ ++ Cambridge Bay ++ tz_names ++ 劍橋灣 ++ ++ ++ ++ Campo Grande ++ tz_names ++ 坎波格蘭德 ++ ++ ++ ++ Canary ++ tz_names ++ 加那利群島 ++ ++ ++ ++ Cancun ++ tz_names ++ 坎昆 ++ ++ ++ ++ Cape Verde ++ tz_names ++ 佛得角 ++ ++ ++ ++ Caracas ++ tz_names ++ 卡拉卡斯 ++ ++ ++ ++ Casablanca ++ tz_names ++ 卡薩布蘭卡 ++ ++ ++ ++ Casey ++ tz_names ++ 凱西 ++ ++ ++ ++ Cayenne ++ tz_names ++ 卡宴 ++ ++ ++ ++ Cayman ++ tz_names ++ 開曼群島 ++ ++ ++ ++ Ceuta ++ tz_names ++ 休達 ++ ++ ++ ++ Chagos ++ tz_names ++ 查戈斯 ++ ++ ++ ++ Chatham ++ tz_names ++ 查塔姆 ++ ++ ++ ++ Chicago ++ tz_names ++ 芝加哥 ++ ++ ++ ++ Chihuahua ++ tz_names ++ 吉娃娃 ++ ++ ++ ++ Chisinau ++ tz_names ++ 基希訥烏 ++ ++ ++ ++ Chita ++ tz_names ++ 赤塔 ++ ++ ++ ++ Choibalsan ++ tz_names ++ 喬巴桑 ++ ++ ++ ++ Christmas ++ tz_names ++ 耶誕節 ++ ++ ++ ++ Chuuk ++ tz_names ++ 楚克 ++ ++ ++ ++ Cocos ++ tz_names ++ 科科斯 ++ ++ ++ ++ Colombo ++ tz_names ++ 可倫坡 ++ ++ ++ ++ Comoro ++ tz_names ++ 科摩羅 ++ ++ ++ ++ Conakry ++ tz_names ++ 柯那克里 ++ ++ ++ ++ Copenhagen ++ tz_names ++ 哥本哈根 ++ ++ ++ ++ Costa Rica ++ tz_names ++ 哥斯大黎加 ++ ++ ++ ++ Creston ++ tz_names ++ 克雷斯頓 ++ ++ ++ ++ Cuiaba ++ tz_names ++ 庫亞巴 ++ ++ ++ ++ Curacao ++ tz_names ++ 庫拉索 ++ ++ ++ ++ Currie ++ tz_names ++ 柯裡 ++ ++ ++ ++ Dakar ++ tz_names ++ 達喀爾 ++ ++ ++ ++ Damascus ++ tz_names ++ 大馬士革 ++ ++ ++ ++ Danmarkshavn ++ tz_names ++ 丹麥 ++ ++ ++ ++ Dar es Salaam ++ tz_names ++ 沙蘭港 ++ ++ ++ ++ Darwin ++ tz_names ++ 達爾文 ++ ++ ++ ++ Davis ++ tz_names ++ 大衛斯 ++ ++ ++ ++ Dawson ++ tz_names ++ 道森 ++ ++ ++ ++ Dawson Creek ++ tz_names ++ 道森溪 ++ ++ ++ ++ Denver ++ tz_names ++ 丹佛 ++ ++ ++ ++ Detroit ++ tz_names ++ 底特律 ++ ++ ++ ++ Dhaka ++ tz_names ++ 達卡 ++ ++ ++ ++ Dili ++ tz_names ++ 帝利 ++ ++ ++ ++ Djibouti ++ tz_names ++ 吉佈提 ++ ++ ++ ++ Dominica ++ tz_names ++ 多明尼克 ++ ++ ++ ++ Douala ++ tz_names ++ 杜阿拉 ++ ++ ++ ++ Dubai ++ tz_names ++ 迪拜 ++ ++ ++ ++ Dublin ++ tz_names ++ 都柏林 ++ ++ ++ ++ DumontDUrville ++ tz_names ++ 杜蒙·杜維爾 ++ ++ ++ ++ Dushanbe ++ tz_names ++ 杜桑貝 ++ ++ ++ ++ Easter ++ tz_names ++ 復活節 ++ ++ ++ ++ Edmonton ++ tz_names ++ 埃德蒙頓 ++ ++ ++ ++ Efate ++ tz_names ++ 埃法特島 ++ ++ ++ ++ Eirunepe ++ tz_names ++ 埃魯內佩 ++ ++ ++ ++ El Aaiun ++ tz_names ++ 阿尤恩 ++ ++ ++ ++ El Salvador ++ tz_names ++ 薩爾瓦多 ++ ++ ++ ++ Enderbury ++ tz_names ++ 恩德伯裡 ++ ++ ++ ++ Eucla ++ tz_names ++ 尤克拉 ++ ++ ++ ++ Fakaofo ++ tz_names ++ 法攷福 ++ ++ ++ ++ Famagusta ++ tz_names ++ 法馬古斯塔 ++ ++ ++ ++ Faroe ++ tz_names ++ 法羅 ++ ++ ++ ++ Fiji ++ tz_names ++ 斐濟 ++ ++ ++ ++ Fort Nelson ++ tz_names ++ 納爾遜堡 ++ ++ ++ ++ Fortaleza ++ tz_names ++ 福塔雷薩 ++ ++ ++ ++ Freetown ++ tz_names ++ 弗裏敦 ++ ++ ++ ++ Funafuti ++ tz_names ++ 福納佛提 ++ ++ ++ ++ Gaborone ++ tz_names ++ 嘉柏隆里 ++ ++ ++ ++ Galapagos ++ tz_names ++ 加拉帕戈斯群島 ++ ++ ++ ++ Gambier ++ tz_names ++ 甘比爾 ++ ++ ++ ++ Gaza ++ tz_names ++ 加沙 ++ ++ ++ ++ Gibraltar ++ tz_names ++ 直布羅陀 ++ ++ ++ ++ Glace Bay ++ tz_names ++ 格萊斯灣 ++ ++ ++ ++ Godthab ++ tz_names ++ 戈德薩布 ++ ++ ++ ++ Goose Bay ++ tz_names ++ 鹅灣 ++ ++ ++ ++ Grand Turk ++ tz_names ++ 大特克 ++ ++ ++ ++ Grenada ++ tz_names ++ 格林伍德 ++ ++ ++ ++ Guadalcanal ++ tz_names ++ 瓜達爾卡納爾島 ++ ++ ++ ++ Guadeloupe ++ tz_names ++ 瓜德羅普島 ++ ++ ++ ++ Guam ++ tz_names ++ 關島 ++ ++ ++ ++ Guatemala ++ tz_names ++ 瓜地馬拉 ++ ++ ++ ++ Guayaquil ++ tz_names ++ 瓜亞基爾 ++ ++ ++ ++ Guernsey ++ tz_names ++ 根西島 ++ ++ ++ ++ Guyana ++ tz_names ++ 蓋亞那 ++ ++ ++ ++ Halifax ++ tz_names ++ 哈利法克斯 ++ ++ ++ ++ Harare ++ tz_names ++ 哈拉雷 ++ ++ ++ ++ Havana ++ tz_names ++ 哈瓦那 ++ ++ ++ ++ Hebron ++ tz_names ++ 希伯倫 ++ ++ ++ ++ Helsinki ++ tz_names ++ 赫爾辛基 ++ ++ ++ ++ Hermosillo ++ tz_names ++ 埃莫西洛 ++ ++ ++ ++ Ho Chi Minh ++ tz_names ++ 胡志明 ++ ++ ++ ++ Hobart ++ tz_names ++ 霍巴特 ++ ++ ++ ++ Hong Kong(China) ++ tz_names ++ 香港(中国) ++ ++ ++ ++ Honolulu ++ tz_names ++ 檀香山 ++ ++ ++ ++ Hovd ++ tz_names ++ 科布多 ++ ++ ++ ++ Indiana/Indianapolis ++ tz_names ++ 印第安那州/印弟安納波里斯 ++ ++ ++ ++ Indiana/Knox ++ tz_names ++ 印第安那州/諾克斯 ++ ++ ++ ++ Indiana/Marengo ++ tz_names ++ 印度/馬倫戈 ++ ++ ++ ++ Indiana/Petersburg ++ tz_names ++ 印第安那州/彼得堡 ++ ++ ++ ++ Indiana/Tell City ++ tz_names ++ 印第安那州/泰爾城 ++ ++ ++ ++ Indiana/Vevay ++ tz_names ++ 印度/沃韋 ++ ++ ++ ++ Indiana/Vincennes ++ tz_names ++ 印第安那州/文森斯 ++ ++ ++ ++ Indiana/Winamac ++ tz_names ++ 印第安那州/威納馬克 ++ ++ ++ ++ Inuvik ++ tz_names ++ 伊努維克 ++ ++ ++ ++ Iqaluit ++ tz_names ++ 伊魁特 ++ ++ ++ ++ Irkutsk ++ tz_names ++ 伊爾庫茨克 ++ ++ ++ ++ Isle of Man ++ tz_names ++ 曼島 ++ ++ ++ ++ Istanbul ++ tz_names ++ 蓋章 ++ ++ ++ ++ Jakarta ++ tz_names ++ 雅加達 ++ ++ ++ ++ Jamaica ++ tz_names ++ 牙買加 ++ ++ ++ ++ Jayapura ++ tz_names ++ 查亞普拉 ++ ++ ++ ++ Jersey ++ tz_names ++ 澤西島 ++ ++ ++ ++ Jerusalem ++ tz_names ++ 耶路撒冷 ++ ++ ++ ++ Johannesburg ++ tz_names ++ 約翰尼斯堡 ++ ++ ++ ++ Juba ++ tz_names ++ 朱巴 ++ ++ ++ ++ Juneau ++ tz_names ++ 朱諾 ++ ++ ++ ++ Kabul ++ tz_names ++ 喀布爾 ++ ++ ++ ++ Kaliningrad ++ tz_names ++ 加里寧格勒 ++ ++ ++ ++ Kamchatka ++ tz_names ++ 堪察加半島 ++ ++ ++ ++ Kampala ++ tz_names ++ 坎帕拉 ++ ++ ++ ++ Karachi ++ tz_names ++ 卡拉奇 ++ ++ ++ ++ Kathmandu ++ tz_names ++ 加德滿都 ++ ++ ++ ++ Kentucky/Louisville ++ tz_names ++ 肯塔基州/路易斯維爾 ++ ++ ++ ++ Kentucky/Monticello ++ tz_names ++ 肯塔基州/蒙蒂塞洛 ++ ++ ++ ++ Kerguelen ++ tz_names ++ 凱爾蓋朗 ++ ++ ++ ++ Khandyga ++ tz_names ++ 坎代加 ++ ++ ++ ++ Khartoum ++ tz_names ++ 喀土穆 ++ ++ ++ ++ Kiev ++ tz_names ++ 基輔 ++ ++ ++ ++ Kigali ++ tz_names ++ 吉佳利 ++ ++ ++ ++ Kinshasa ++ tz_names ++ 金夏沙 ++ ++ ++ ++ Kiritimati ++ tz_names ++ 基裏蒂馬提斯 ++ ++ ++ ++ Kirov ++ tz_names ++ 基洛夫 ++ ++ ++ ++ Kolkata ++ tz_names ++ 加爾格達 ++ ++ ++ ++ Kosrae ++ tz_names ++ 科斯雷 ++ ++ ++ ++ Kralendijk ++ tz_names ++ 克羅地亞 ++ ++ ++ ++ Krasnoyarsk ++ tz_names ++ 克拉斯諾亞爾斯克 ++ ++ ++ ++ Kuala Lumpur ++ tz_names ++ 吉隆玻 ++ ++ ++ ++ Kuching ++ tz_names ++ 古晋 ++ ++ ++ ++ Kuwait ++ tz_names ++ 科威特 ++ ++ ++ ++ Kwajalein ++ tz_names ++ 誇賈林 ++ ++ ++ ++ La Paz ++ tz_names ++ 拉巴斯 ++ ++ ++ ++ Lagos ++ tz_names ++ 拉各斯 ++ ++ ++ ++ Libreville ++ tz_names ++ 利伯維爾 ++ ++ ++ ++ Lima ++ tz_names ++ 利馬 ++ ++ ++ ++ Lindeman ++ tz_names ++ 林德曼 ++ ++ ++ ++ Lisbon ++ tz_names ++ 里斯本 ++ ++ ++ ++ Ljubljana ++ tz_names ++ 盧布亞納 ++ ++ ++ ++ Lome ++ tz_names ++ 多哥 ++ ++ ++ ++ London ++ tz_names ++ 倫敦 ++ ++ ++ ++ Longyearbyen ++ tz_names ++ 龍宜爾比恩 ++ ++ ++ ++ Lord Howe ++ tz_names ++ 豪勳爵 ++ ++ ++ ++ Los Angeles ++ tz_names ++ 洛杉磯 ++ ++ ++ ++ Lower Princes ++ tz_names ++ 聖馬丁 ++ ++ ++ ++ Luanda ++ tz_names ++ 魯安達 ++ ++ ++ ++ Lubumbashi ++ tz_names ++ 盧本巴希 ++ ++ ++ ++ Lusaka ++ tz_names ++ 路沙卡 ++ ++ ++ ++ Luxembourg ++ tz_names ++ 盧森堡 ++ ++ ++ ++ Macau ++ tz_names ++ 澳門(中国) ++ ++ ++ ++ Maceio ++ tz_names ++ 馬塞奧 ++ ++ ++ ++ Macquarie ++ tz_names ++ 麥格理 ++ ++ ++ ++ Madeira ++ tz_names ++ 馬德拉 ++ ++ ++ ++ Madrid ++ tz_names ++ 馬德里 ++ ++ ++ ++ Magadan ++ tz_names ++ 馬加丹 ++ ++ ++ ++ Mahe ++ tz_names ++ 馬埃 ++ ++ ++ ++ Majuro ++ tz_names ++ 麥哲魯 ++ ++ ++ ++ Makassar ++ tz_names ++ 望加錫 ++ ++ ++ ++ Malabo ++ tz_names ++ 馬拉博 ++ ++ ++ ++ Maldives ++ tz_names ++ 瑪律地夫 ++ ++ ++ ++ Malta ++ tz_names ++ 馬爾他 ++ ++ ++ ++ Managua ++ tz_names ++ 馬納瓜 ++ ++ ++ ++ Manaus ++ tz_names ++ 馬瑙斯 ++ ++ ++ ++ Manila ++ tz_names ++ 馬尼拉 ++ ++ ++ ++ Maputo ++ tz_names ++ 馬布多 ++ ++ ++ ++ Mariehamn ++ tz_names ++ 瑪麗港 ++ ++ ++ ++ Marigot ++ tz_names ++ 馬裏戈 ++ ++ ++ ++ Marquesas ++ tz_names ++ 馬克薩斯 ++ ++ ++ ++ Martinique ++ tz_names ++ 馬提尼克島 ++ ++ ++ ++ Maseru ++ tz_names ++ 馬塞魯 ++ ++ ++ ++ Matamoros ++ tz_names ++ 馬塔莫羅斯 ++ ++ ++ ++ Mauritius ++ tz_names ++ 模裡西斯 ++ ++ ++ ++ Mawson ++ tz_names ++ 莫森 ++ ++ ++ ++ Mayotte ++ tz_names ++ 馬約特島 ++ ++ ++ ++ Mazatlan ++ tz_names ++ 馬薩特蘭 ++ ++ ++ ++ Mbabane ++ tz_names ++ 姆巴班 ++ ++ ++ ++ McMurdo ++ tz_names ++ 麥克默多 ++ ++ ++ ++ Melbourne ++ tz_names ++ 墨爾本 ++ ++ ++ ++ Menominee ++ tz_names ++ 梅諾米尼 ++ ++ ++ ++ Merida ++ tz_names ++ 梅里達 ++ ++ ++ ++ Metlakatla ++ tz_names ++ 梅特拉卡特拉 ++ ++ ++ ++ Mexico City ++ tz_names ++ 墨西哥城 ++ ++ ++ ++ Midway ++ tz_names ++ 中途島 ++ ++ ++ ++ Minsk ++ tz_names ++ 明斯克 ++ ++ ++ ++ Miquelon ++ tz_names ++ 密克隆 ++ ++ ++ ++ Mogadishu ++ tz_names ++ 摩加迪休 ++ ++ ++ ++ Monaco ++ tz_names ++ 摩納哥 ++ ++ ++ ++ Moncton ++ tz_names ++ 蒙克頓 ++ ++ ++ ++ Monrovia ++ tz_names ++ 蒙羅維亞 ++ ++ ++ ++ Monterrey ++ tz_names ++ 蒙特雷 ++ ++ ++ ++ Montevideo ++ tz_names ++ 蒙特維多 ++ ++ ++ ++ Montserrat ++ tz_names ++ 蒙特塞拉特 ++ ++ ++ ++ Moscow ++ tz_names ++ 莫斯科 ++ ++ ++ ++ Muscat ++ tz_names ++ 馬斯喀特 ++ ++ ++ ++ Nairobi ++ tz_names ++ 奈洛比 ++ ++ ++ ++ Nassau ++ tz_names ++ 拿索 ++ ++ ++ ++ Nauru ++ tz_names ++ 瑙魯 ++ ++ ++ ++ Ndjamena ++ tz_names ++ 恩賈梅納 ++ ++ ++ ++ New York ++ tz_names ++ 紐約 ++ ++ ++ ++ Niamey ++ tz_names ++ 尼阿美 ++ ++ ++ ++ Nicosia ++ tz_names ++ 尼古西亞 ++ ++ ++ ++ Nipigon ++ tz_names ++ 尼皮貢 ++ ++ ++ ++ Niue ++ tz_names ++ 紐埃 ++ ++ ++ ++ Nome ++ tz_names ++ 諾姆 ++ ++ ++ ++ Norfolk ++ tz_names ++ 諾福克 ++ ++ ++ ++ Noronha ++ tz_names ++ 諾羅尼亞 ++ ++ ++ ++ North Dakota/Beulah ++ tz_names ++ 北達科他州/比拉 ++ ++ ++ ++ North Dakota/Center ++ tz_names ++ 北達科他州/中心 ++ ++ ++ ++ North Dakota/New Salem ++ tz_names ++ 北達科他州/新賽勒姆 ++ ++ ++ ++ Nouakchott ++ tz_names ++ 諾克少 ++ ++ ++ ++ Noumea ++ tz_names ++ 諾美亞 ++ ++ ++ ++ Novokuznetsk ++ tz_names ++ 新庫茲涅茨克 ++ ++ ++ ++ Novosibirsk ++ tz_names ++ 新西伯利亞 ++ ++ ++ ++ Ojinaga ++ tz_names ++ 魁北克 ++ ++ ++ ++ Omsk ++ tz_names ++ 鄂木斯克 ++ ++ ++ ++ Oral ++ tz_names ++ 朵拉 ++ ++ ++ ++ Oslo ++ tz_names ++ 奧斯陸 ++ ++ ++ ++ Ouagadougou ++ tz_names ++ 瓦加杜古 ++ ++ ++ ++ Pago Pago ++ tz_names ++ 帕果帕果 ++ ++ ++ ++ Palau ++ tz_names ++ 帕勞 ++ ++ ++ ++ Palmer ++ tz_names ++ 帕爾默 ++ ++ ++ ++ Panama ++ tz_names ++ 巴拿馬 ++ ++ ++ ++ Pangnirtung ++ tz_names ++ 巴芬島的旁涅唐 ++ ++ ++ ++ Paramaribo ++ tz_names ++ 巴拉馬利波 ++ ++ ++ ++ Paris ++ tz_names ++ 巴黎 ++ ++ ++ ++ Perth ++ tz_names ++ 珀斯 ++ ++ ++ ++ Phnom Penh ++ tz_names ++ 金邊 ++ ++ ++ ++ Phoenix ++ tz_names ++ 鳳凰城 ++ ++ ++ ++ Pitcairn ++ tz_names ++ 皮特凱恩 ++ ++ ++ ++ Podgorica ++ tz_names ++ 波德戈裡察 ++ ++ ++ ++ Pohnpei ++ tz_names ++ 波納佩島 ++ ++ ++ ++ Pontianak ++ tz_names ++ 坤甸 ++ ++ ++ ++ Port Moresby ++ tz_names ++ 莫爾斯貝港 ++ ++ ++ ++ Port of Spain ++ tz_names ++ 西班牙港 ++ ++ ++ ++ Port-au-Prince ++ tz_names ++ 太子港 ++ ++ ++ ++ Porto Velho ++ tz_names ++ 維略港 ++ ++ ++ ++ Porto-Novo ++ tz_names ++ 波多洛 ++ ++ ++ ++ Prague ++ tz_names ++ 布拉格 ++ ++ ++ ++ Puerto Rico ++ tz_names ++ 波多黎各 ++ ++ ++ ++ Punta Arenas ++ tz_names ++ 蓬塔阿雷納斯 ++ ++ ++ ++ Pyongyang ++ tz_names ++ 平壤 ++ ++ ++ ++ Qatar ++ tz_names ++ 卡塔爾 ++ ++ ++ ++ Qostanay ++ tz_names ++ 庫斯塔 ++ ++ ++ ++ Qyzylorda ++ tz_names ++ 克孜勒奧爾達 ++ ++ ++ ++ Rainy River ++ tz_names ++ 雷尼河 ++ ++ ++ ++ Rankin Inlet ++ tz_names ++ 蘭京海口 ++ ++ ++ ++ Rarotonga ++ tz_names ++ 拉羅湯加 ++ ++ ++ ++ Recife ++ tz_names ++ 累西腓 ++ ++ ++ ++ Regina ++ tz_names ++ 里賈納 ++ ++ ++ ++ Resolute ++ tz_names ++ 雷索盧特 ++ ++ ++ ++ Reunion ++ tz_names ++ 留尼旺島 ++ ++ ++ ++ Reykjavik ++ tz_names ++ 雷克雅維克 ++ ++ ++ ++ Riga ++ tz_names ++ 裏加 ++ ++ ++ ++ Rio Branco ++ tz_names ++ 裏奧·布蘭科 ++ ++ ++ ++ Riyadh ++ tz_names ++ 利雅德 ++ ++ ++ ++ Rome ++ tz_names ++ 羅馬 ++ ++ ++ ++ Rothera ++ tz_names ++ 羅瑟拉 ++ ++ ++ ++ Saipan ++ tz_names ++ 塞班島 ++ ++ ++ ++ Sakhalin ++ tz_names ++ 薩哈林 ++ ++ ++ ++ Samara ++ tz_names ++ 薩馬拉 ++ ++ ++ ++ Samarkand ++ tz_names ++ 撒馬爾罕 ++ ++ ++ ++ San Marino ++ tz_names ++ 聖馬利諾 ++ ++ ++ ++ Santarem ++ tz_names ++ 聖塔倫 ++ ++ ++ ++ Santiago ++ tz_names ++ 聖地牙哥 ++ ++ ++ ++ Santo Domingo ++ tz_names ++ 聖多明哥 ++ ++ ++ ++ Sao Paulo ++ tz_names ++ 聖保羅 ++ ++ ++ ++ Sao Tome ++ tz_names ++ 聖多美 ++ ++ ++ ++ Sarajevo ++ tz_names ++ 塞拉耶佛 ++ ++ ++ ++ Saratov ++ tz_names ++ 薩拉托夫 ++ ++ ++ ++ Scoresbysund ++ tz_names ++ 斯科斯比基金 ++ ++ ++ ++ Seoul ++ tz_names ++ 首爾 ++ ++ ++ ++ Shanghai ++ tz_names ++ 上海 ++ ++ ++ ++ Simferopol ++ tz_names ++ 辛菲羅波爾 ++ ++ ++ ++ Singapore ++ tz_names ++ 新加坡 ++ ++ ++ ++ Sitka ++ tz_names ++ 錫特卡 ++ ++ ++ ++ Skopje ++ tz_names ++ 斯高彼亞 ++ ++ ++ ++ Sofia ++ tz_names ++ 索菲亞 ++ ++ ++ ++ South Georgia ++ tz_names ++ 南喬治亞州 ++ ++ ++ ++ Srednekolymsk ++ tz_names ++ 雅庫特 ++ ++ ++ ++ St Barthelemy ++ tz_names ++ 聖巴泰勒米 ++ ++ ++ ++ St Helena ++ tz_names ++ 聖赫倫那 ++ ++ ++ ++ St Johns ++ tz_names ++ 聖約翰 ++ ++ ++ ++ St Kitts ++ tz_names ++ 聖基茨 ++ ++ ++ ++ St Lucia ++ tz_names ++ 聖盧西亞 ++ ++ ++ ++ St Thomas ++ tz_names ++ 聖托馬斯 ++ ++ ++ ++ St Vincent ++ tz_names ++ 聖文森特 ++ ++ ++ ++ Stanley ++ tz_names ++ 斯坦利 ++ ++ ++ ++ Stockholm ++ tz_names ++ 斯德哥爾摩 ++ ++ ++ ++ Swift Current ++ tz_names ++ 斯威夫特卡倫特 ++ ++ ++ ++ Sydney ++ tz_names ++ 雪梨 ++ ++ ++ ++ Syowa ++ tz_names ++ 聖約瑟 ++ ++ ++ ++ Tahiti ++ tz_names ++ 大溪地 ++ ++ ++ ++ Taipei(China) ++ tz_names ++ 臺北(中国) ++ ++ ++ ++ Tallinn ++ tz_names ++ 數位行 ++ ++ ++ ++ Tarawa ++ tz_names ++ 塔拉瓦 ++ ++ ++ ++ Tashkent ++ tz_names ++ 塔什干 ++ ++ ++ ++ Tbilisi ++ tz_names ++ 第比利斯 ++ ++ ++ ++ Tegucigalpa ++ tz_names ++ 德古西加巴 ++ ++ ++ ++ Tehran ++ tz_names ++ 德黑蘭 ++ ++ ++ ++ Thimphu ++ tz_names ++ 辛布 ++ ++ ++ ++ Thule ++ tz_names ++ 圖勒 ++ ++ ++ ++ Thunder Bay ++ tz_names ++ 雷灣 ++ ++ ++ ++ Tijuana ++ tz_names ++ 蒂華納 ++ ++ ++ ++ Tirane ++ tz_names ++ 地拉那 ++ ++ ++ ++ Tokyo ++ tz_names ++ 東京 ++ ++ ++ ++ Tomsk ++ tz_names ++ 托木斯克 ++ ++ ++ ++ Tongatapu ++ tz_names ++ 湯加塔布 ++ ++ ++ ++ Toronto ++ tz_names ++ 多倫多 ++ ++ ++ ++ Tortola ++ tz_names ++ 托托拉島 ++ ++ ++ ++ Tripoli ++ tz_names ++ 的黎波里 ++ ++ ++ ++ Troll ++ tz_names ++ 特羅爾海坦 ++ ++ ++ ++ Tunis ++ tz_names ++ 突尼斯 ++ ++ ++ ++ Ulaanbaatar ++ tz_names ++ 烏蘭巴托 ++ ++ ++ ++ Ulyanovsk ++ tz_names ++ 烏裡揚諾夫斯克 ++ ++ ++ ++ Urumqi ++ tz_names ++ 烏魯木齊 ++ ++ ++ ++ Ust-Nera ++ tz_names ++ 烏斯季挪拉 ++ ++ ++ ++ Uzhgorod ++ tz_names ++ 烏日哥羅德 ++ ++ ++ ++ Vaduz ++ tz_names ++ 瓦都茲 ++ ++ ++ ++ Vancouver ++ tz_names ++ 溫哥華 ++ ++ ++ ++ Vatican ++ tz_names ++ 梵蒂岡 ++ ++ ++ ++ Vienna ++ tz_names ++ 維也納 ++ ++ ++ ++ Vientiane ++ tz_names ++ 萬象 ++ ++ ++ ++ Vilnius ++ tz_names ++ 維爾紐斯 ++ ++ ++ ++ Vladivostok ++ tz_names ++ 符拉迪沃斯托克 ++ ++ ++ ++ Volgograd ++ tz_names ++ 伏爾加格勒 ++ ++ ++ ++ Vostok ++ tz_names ++ 沃斯托克 ++ ++ ++ ++ Wake ++ tz_names ++ 韋克 ++ ++ ++ ++ Wallis ++ tz_names ++ 沃利斯 ++ ++ ++ ++ Warsaw ++ tz_names ++ 華沙 ++ ++ ++ ++ Whitehorse ++ tz_names ++ 懷特霍斯 ++ ++ ++ ++ Windhoek ++ tz_names ++ 溫吐克 ++ ++ ++ ++ Winnipeg ++ tz_names ++ 溫尼伯 ++ ++ ++ ++ Yakutat ++ tz_names ++ 雅庫特 ++ ++ ++ ++ Yakutsk ++ tz_names ++ 亞庫次克 ++ ++ ++ ++ Yangon ++ tz_names ++ 仰光 ++ ++ ++ ++ Yekaterinburg ++ tz_names ++ 葉卡捷琳堡 ++ ++ ++ ++ Yellowknife ++ tz_names ++ 黃刀 ++ ++ ++ ++ Yerevan ++ tz_names ++ 葉里溫 ++ ++ ++ ++ Zagreb ++ tz_names ++ 札格雷布 ++ ++ ++ ++ Zaporozhye ++ tz_names ++ 紮波羅熱 ++ ++ ++ ++ Zurich ++ tz_names ++ 蘇黎世 ++ ++ ++ +diff --git a/src/branding/default/show.qml b/src/branding/default/show.qml +index f6223c0..f91d520 100644 +--- a/src/branding/default/show.qml ++++ b/src/branding/default/show.qml +@@ -33,7 +33,7 @@ Presentation + Image { + id: background1 + source: "Slide1.png" +- width: 800; height: 800 ++ width: 980; height: 980 + fillMode: Image.PreserveAspectFit + anchors.horizontalCenter:parent.horizontalCenter + y:parent.height / 2 - height / 2 -25 +@@ -44,7 +44,7 @@ Presentation + Image { + id: background2 + source: "Slide2.png" +- width: 800; height: 800 ++ width: 980; height: 980 + fillMode: Image.PreserveAspectFit + anchors.horizontalCenter:parent.horizontalCenter + y:parent.height / 2 - height / 2 -25 +@@ -55,7 +55,7 @@ Presentation + Image { + id: background3 + source: "Slide3.png" +- width: 800; height: 800 ++ width: 980; height: 980 + fillMode: Image.PreserveAspectFit + anchors.horizontalCenter:parent.horizontalCenter + y:parent.height / 2 - height / 2 -25 +diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt +index 3be6b92..9f806c7 100644 +--- a/src/calamares/CMakeLists.txt ++++ b/src/calamares/CMakeLists.txt +@@ -1,67 +1,67 @@ +-# === This file is part of Calamares - === +-# +-# SPDX-FileCopyrightText: 2020 Adriaan de Groot +-# SPDX-License-Identifier: BSD-2-Clause +-# +- +-set(calamaresSources +- main.cpp +- CalamaresApplication.cpp +- CalamaresWindow.cpp +- DebugWindow.cpp +- VariantModel.cpp +- progresstree/ProgressTreeDelegate.cpp +- progresstree/ProgressTreeView.cpp +-) +- +-include_directories( +- ${CMAKE_SOURCE_DIR}/src/libcalamares +- ${CMAKE_SOURCE_DIR}/src/libcalamaresui +- ${CMAKE_BINARY_DIR}/src/libcalamares +- ${CMAKE_CURRENT_SOURCE_DIR} +-) +- +-### EXECUTABLE +-# +-# "calamares_bin" is the main application, not to be confused with +-# the target "calamares" which is the non-GUI library part. +-# +-# The calamares-i18n.cxx file -- full path in CALAMARES_TRANSLATIONS_SOURCE -- +-# is created as a target in the lang/ directory. This is compiled to a +-# library (it's just the result of a QRC compile). +-add_executable(calamares_bin ${calamaresSources} calamares.qrc) +-target_include_directories(calamares_bin PRIVATE ${CMAKE_SOURCE_DIR}) +-set_target_properties(calamares_bin PROPERTIES ENABLE_EXPORTS TRUE RUNTIME_OUTPUT_NAME calamares) +-calamares_automoc( calamares_bin ) +-calamares_autouic( calamares_bin ) +-calamares_autorcc( calamares_bin ) +- +-target_link_libraries( +- calamares_bin +- PRIVATE calamares calamaresui calamares-i18n kdsingleapplication ${qtname}::Core ${qtname}::Widgets +-) +-target_link_libraries(calamares_bin PRIVATE ${kfname}::CoreAddons) +-if(BUILD_CRASH_REPORTING) +- target_link_libraries(calamares_bin PRIVATE ${kfname}::Crash) +- target_compile_definitions(calamares_bin PRIVATE BUILD_CRASH_REPORTING) +-endif() +- +-install(TARGETS calamares_bin BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +- +-install( +- FILES ${CMAKE_SOURCE_DIR}/data/images/squid.svg +- RENAME calamares.svg +- DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps +-) +- +-### TESTS +-# +-# +-if(BUILD_TESTING) +- # Don't install, these are just for enable_testing +- add_executable(loadmodule testmain.cpp) +- target_link_libraries(loadmodule PRIVATE ${qtname}::Core ${qtname}::Widgets calamares calamaresui) +- +- add_executable(test_conf test_conf.cpp) +- target_link_libraries(test_conf PUBLIC yamlcpp::yamlcpp ${qtname}::Core) +-endif() ++# === This file is part of Calamares - === ++# ++# SPDX-FileCopyrightText: 2020 Adriaan de Groot ++# SPDX-License-Identifier: BSD-2-Clause ++# ++ ++set(calamaresSources ++ main.cpp ++ CalamaresApplication.cpp ++ CalamaresWindow.cpp ++ DebugWindow.cpp ++ VariantModel.cpp ++ progresstree/ProgressTreeDelegate.cpp ++ progresstree/ProgressTreeView.cpp ++) ++ ++include_directories( ++ ${CMAKE_SOURCE_DIR}/src/libcalamares ++ ${CMAKE_SOURCE_DIR}/src/libcalamaresui ++ ${CMAKE_BINARY_DIR}/src/libcalamares ++ ${CMAKE_CURRENT_SOURCE_DIR} ++) ++ ++### EXECUTABLE ++# ++# "calamares_bin" is the main application, not to be confused with ++# the target "calamares" which is the non-GUI library part. ++# ++# The calamares-i18n.cxx file -- full path in CALAMARES_TRANSLATIONS_SOURCE -- ++# is created as a target in the lang/ directory. This is compiled to a ++# library (it's just the result of a QRC compile). ++add_executable(calamares_bin ${calamaresSources} calamares.qrc) ++target_include_directories(calamares_bin PRIVATE ${CMAKE_SOURCE_DIR}) ++set_target_properties(calamares_bin PROPERTIES ENABLE_EXPORTS TRUE RUNTIME_OUTPUT_NAME calamares) ++calamares_automoc( calamares_bin ) ++calamares_autouic( calamares_bin ) ++calamares_autorcc( calamares_bin ) ++ ++target_link_libraries( ++ calamares_bin ++ PRIVATE calamares calamaresui calamares-i18n kdsingleapplication ${qtname}::Core ${qtname}::Widgets ++) ++target_link_libraries(calamares_bin PRIVATE ${kfname}::CoreAddons) ++if(BUILD_CRASH_REPORTING) ++ target_link_libraries(calamares_bin PRIVATE ${kfname}::Crash) ++ target_compile_definitions(calamares_bin PRIVATE BUILD_CRASH_REPORTING) ++endif() ++ ++install(TARGETS calamares_bin BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) ++ ++install( ++ FILES ${CMAKE_SOURCE_DIR}/data/images/squid.svg ++ RENAME calamares.svg ++ DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps ++) ++ ++### TESTS ++# ++# ++if(BUILD_TESTING) ++ # Don't install, these are just for enable_testing ++ add_executable(loadmodule testmain.cpp) ++ target_link_libraries(loadmodule PRIVATE ${qtname}::Core ${qtname}::Widgets calamares calamaresui) ++ ++ add_executable(test_conf test_conf.cpp) ++ target_link_libraries(test_conf PUBLIC yamlcpp::yamlcpp ${qtname}::Core) ++endif() +diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp +index a07edad..6b62fd6 100644 +--- a/src/calamares/CalamaresApplication.cpp ++++ b/src/calamares/CalamaresApplication.cpp +@@ -51,8 +51,8 @@ CalamaresApplication::CalamaresApplication( int& argc, char* argv[] ) + // directory -- where Calamares stores logs, for instance -- + // //, so we end up with ~/.cache/Calamares/calamares/ + // which is excessively squidly. +- // +- // setOrganizationName( QStringLiteral( CALAMARES_ORGANIZATION_NAME ) ); ++ ++ + setOrganizationDomain( QStringLiteral( CALAMARES_ORGANIZATION_DOMAIN ) ); + setApplicationName( QStringLiteral( CALAMARES_APPLICATION_NAME ) ); + setApplicationVersion( QStringLiteral( CALAMARES_VERSION ) ); +diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp +index b28661e..69584b8 100644 +--- a/src/calamares/DebugWindow.cpp ++++ b/src/calamares/DebugWindow.cpp +@@ -1,265 +1,265 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2019 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#include "DebugWindow.h" +-#include "ui_DebugWindow.h" +- +-#include "Branding.h" +-#include "CalamaresAbout.h" +-#include "CalamaresVersion.h" +-#include "GlobalStorage.h" +-#include "Job.h" +-#include "JobQueue.h" +-#include "Settings.h" +-#include "VariantModel.h" +-#include "modulesystem/Module.h" +-#include "modulesystem/ModuleManager.h" +-#include "utils/Gui.h" +-#include "utils/Logger.h" +-#include "utils/Paste.h" +-#include "utils/Retranslator.h" +-#include "widgets/TranslationFix.h" +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-/** +- * @brief crash makes Calamares crash immediately. +- */ +-static void +-crash() +-{ +- kill( getpid(), SIGTRAP ); +-} +- +-/// @brief Print out the widget tree (names) in indented form. +-static void +-dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) +-{ +- if ( !widget ) +- { +- return; +- } +- +- deb << Logger::Continuation; +- for ( int i = 0; i < depth; ++i ) +- { +- deb << ' '; +- } +- deb << widget->metaObject()->className() << widget->objectName(); +- +- for ( const auto* w : widget->findChildren< QWidget* >( QString(), Qt::FindDirectChildrenOnly ) ) +- { +- dumpWidgetTree( deb, w, depth + 1 ); +- } +-} +- +-namespace Calamares +-{ +- +-DebugWindow::DebugWindow() +- : QWidget( nullptr ) +- , m_ui( new Ui::DebugWindow ) +- , m_globals( JobQueue::instance()->globalStorage()->data() ) +- , m_globals_model( std::make_unique< VariantModel >( &m_globals ) ) +- , m_module_model( std::make_unique< VariantModel >( &m_module ) ) +-{ +- GlobalStorage* gs = JobQueue::instance()->globalStorage(); +- +- m_ui->setupUi( this ); +- +- m_ui->globalStorageView->setModel( m_globals_model.get() ); +- m_ui->globalStorageView->expandAll(); +- +- // Do above when the GS changes, too +- connect( gs, +- &GlobalStorage::changed, +- this, +- [ = ] +- { +- m_globals = JobQueue::instance()->globalStorage()->data(); +- m_globals_model->reload(); +- m_ui->globalStorageView->expandAll(); +- } ); +- +- // JobQueue page +- m_ui->jobQueueText->setReadOnly( true ); +- connect( JobQueue::instance(), +- &JobQueue::queueChanged, +- this, +- [ this ]( const QStringList& jobs ) { m_ui->jobQueueText->setText( jobs.join( '\n' ) ); } ); +- +- // Modules page +- QStringList modulesKeys; +- for ( const auto& m : ModuleManager::instance()->loadedInstanceKeys() ) +- { +- modulesKeys << m.toString(); +- } +- +- QStringListModel* modulesModel = new QStringListModel( modulesKeys ); +- m_ui->modulesListView->setModel( modulesModel ); +- m_ui->modulesListView->setSelectionMode( QAbstractItemView::SingleSelection ); +- +- m_ui->moduleConfigView->setModel( m_module_model.get() ); +- +- connect( m_ui->modulesListView->selectionModel(), +- &QItemSelectionModel::selectionChanged, +- this, +- [ this ] +- { +- QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); +- Module* module +- = ModuleManager::instance()->moduleInstance( ModuleSystem::InstanceKey::fromString( moduleName ) ); +- if ( module ) +- { +- m_module = module->configurationMap(); +- m_module_model->reload(); +- m_ui->moduleConfigView->expandAll(); +- m_ui->moduleTypeLabel->setText( module->typeString() ); +- m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); +- } +- } ); +- +- // Tools page +- connect( m_ui->crashButton, &QPushButton::clicked, this, [] { ::crash(); } ); +- connect( m_ui->reloadStylesheetButton, +- &QPushButton::clicked, +- []() +- { +- for ( auto* w : qApp->topLevelWidgets() ) +- { +- // Needs to match what's set in CalamaresWindow +- if ( w->objectName() == QStringLiteral( "mainApp" ) ) +- { +- w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); +- } +- } +- } ); +- connect( m_ui->widgetTreeButton, +- &QPushButton::clicked, +- []() +- { +- for ( auto* w : qApp->topLevelWidgets() ) +- { +- Logger::CDebug deb; +- dumpWidgetTree( deb, w, 0 ); +- } +- } ); +- +- // Send Log button only if it would be useful +- m_ui->sendLogButton->setVisible( Calamares::Paste::isEnabled() ); +- connect( m_ui->sendLogButton, &QPushButton::clicked, [ this ]() { Calamares::Paste::doLogUploadUI( this ); } ); +- +- CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); setWindowTitle( tr( "Debug Information", "@title" ) ); ); +-} +- +-void +-DebugWindow::closeEvent( QCloseEvent* e ) +-{ +- Q_UNUSED( e ) +- emit closed(); +-} +- +-DebugWindowManager::DebugWindowManager( QObject* parent ) +- : QObject( parent ) +-{ +-} +- +-bool +-DebugWindowManager::enabled() const +-{ +- const auto* s = Settings::instance(); +- return ( Logger::logLevel() >= Logger::LOGVERBOSE ) || ( s ? s->debugMode() : false ); +-} +- +-void +-DebugWindowManager::show( bool visible ) +-{ +- if ( !enabled() ) +- { +- visible = false; +- } +- if ( m_visible == visible ) +- { +- return; +- } +- +- if ( visible ) +- { +- m_debugWindow = new Calamares::DebugWindow(); +- m_debugWindow->show(); +- connect( m_debugWindow.data(), +- &Calamares::DebugWindow::closed, +- this, +- [ = ]() +- { +- m_debugWindow->deleteLater(); +- m_visible = false; +- emit visibleChanged( false ); +- } ); +- m_visible = true; +- emit visibleChanged( true ); +- } +- else +- { +- if ( m_debugWindow ) +- { +- m_debugWindow->deleteLater(); +- } +- m_visible = false; +- emit visibleChanged( false ); +- } +-} +- +-void +-DebugWindowManager::toggle() +-{ +- show( !m_visible ); +-} +- +-void +-DebugWindowManager::about() +-{ +- QString title = Calamares::Settings::instance()->isSetupMode() +- ? QCoreApplication::translate( "WelcomePage", "About %1 Setup", "@title" ) +- : QCoreApplication::translate( "WelcomePage", "About %1 Installer", "@title" ); +- QMessageBox mb( QMessageBox::Information, +- title.arg( CALAMARES_APPLICATION_NAME ), +- Calamares::aboutString().arg( Calamares::Branding::instance()->versionedName() ), +- QMessageBox::Ok, +- nullptr ); +- Calamares::fixButtonLabels( &mb ); +- mb.setStyleSheet( +- "QMessageBox {" +- "border: 1px solid hsl(240,2%,79%);" +- "border-radius: 5px;" +- "background-color: #FFFFFF;" // 设置对话框背景颜色 +- "}" +- ); +- mb.setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); +- mb.setIconPixmap( +- Calamares::defaultPixmap( Calamares::BigLogo,//Biglogo.svg +- Calamares::Original, +- QSize( 321/1.9, 297/2 ) ) ); +- QGridLayout* layout = reinterpret_cast< QGridLayout* >( mb.layout() ); +- if ( layout ) +- { +- layout->setColumnMinimumWidth( 2, Calamares::defaultFontHeight() * 24 ); +- } +- mb.exec(); +-} +- +-} // namespace Calamares ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2019 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#include "DebugWindow.h" ++#include "ui_DebugWindow.h" ++ ++#include "Branding.h" ++#include "CalamaresAbout.h" ++#include "CalamaresVersion.h" ++#include "GlobalStorage.h" ++#include "Job.h" ++#include "JobQueue.h" ++#include "Settings.h" ++#include "VariantModel.h" ++#include "modulesystem/Module.h" ++#include "modulesystem/ModuleManager.h" ++#include "utils/Gui.h" ++#include "utils/Logger.h" ++#include "utils/Paste.h" ++#include "utils/Retranslator.h" ++#include "widgets/TranslationFix.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/** ++ * @brief crash makes Calamares crash immediately. ++ */ ++static void ++crash() ++{ ++ kill( getpid(), SIGTRAP ); ++} ++ ++/// @brief Print out the widget tree (names) in indented form. ++static void ++dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) ++{ ++ if ( !widget ) ++ { ++ return; ++ } ++ ++ deb << Logger::Continuation; ++ for ( int i = 0; i < depth; ++i ) ++ { ++ deb << ' '; ++ } ++ deb << widget->metaObject()->className() << widget->objectName(); ++ ++ for ( const auto* w : widget->findChildren< QWidget* >( QString(), Qt::FindDirectChildrenOnly ) ) ++ { ++ dumpWidgetTree( deb, w, depth + 1 ); ++ } ++} ++ ++namespace Calamares ++{ ++ ++DebugWindow::DebugWindow() ++ : QWidget( nullptr ) ++ , m_ui( new Ui::DebugWindow ) ++ , m_globals( JobQueue::instance()->globalStorage()->data() ) ++ , m_globals_model( std::make_unique< VariantModel >( &m_globals ) ) ++ , m_module_model( std::make_unique< VariantModel >( &m_module ) ) ++{ ++ GlobalStorage* gs = JobQueue::instance()->globalStorage(); ++ ++ m_ui->setupUi( this ); ++ ++ m_ui->globalStorageView->setModel( m_globals_model.get() ); ++ m_ui->globalStorageView->expandAll(); ++ ++ // Do above when the GS changes, too ++ connect( gs, ++ &GlobalStorage::changed, ++ this, ++ [ = ] ++ { ++ m_globals = JobQueue::instance()->globalStorage()->data(); ++ m_globals_model->reload(); ++ m_ui->globalStorageView->expandAll(); ++ } ); ++ ++ // JobQueue page ++ m_ui->jobQueueText->setReadOnly( true ); ++ connect( JobQueue::instance(), ++ &JobQueue::queueChanged, ++ this, ++ [ this ]( const QStringList& jobs ) { m_ui->jobQueueText->setText( jobs.join( '\n' ) ); } ); ++ ++ // Modules page ++ QStringList modulesKeys; ++ for ( const auto& m : ModuleManager::instance()->loadedInstanceKeys() ) ++ { ++ modulesKeys << m.toString(); ++ } ++ ++ QStringListModel* modulesModel = new QStringListModel( modulesKeys ); ++ m_ui->modulesListView->setModel( modulesModel ); ++ m_ui->modulesListView->setSelectionMode( QAbstractItemView::SingleSelection ); ++ ++ m_ui->moduleConfigView->setModel( m_module_model.get() ); ++ ++ connect( m_ui->modulesListView->selectionModel(), ++ &QItemSelectionModel::selectionChanged, ++ this, ++ [ this ] ++ { ++ QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); ++ Module* module ++ = ModuleManager::instance()->moduleInstance( ModuleSystem::InstanceKey::fromString( moduleName ) ); ++ if ( module ) ++ { ++ m_module = module->configurationMap(); ++ m_module_model->reload(); ++ m_ui->moduleConfigView->expandAll(); ++ m_ui->moduleTypeLabel->setText( module->typeString() ); ++ m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); ++ } ++ } ); ++ ++ // Tools page ++ connect( m_ui->crashButton, &QPushButton::clicked, this, [] { ::crash(); } ); ++ connect( m_ui->reloadStylesheetButton, ++ &QPushButton::clicked, ++ []() ++ { ++ for ( auto* w : qApp->topLevelWidgets() ) ++ { ++ // Needs to match what's set in CalamaresWindow ++ if ( w->objectName() == QStringLiteral( "mainApp" ) ) ++ { ++ w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); ++ } ++ } ++ } ); ++ connect( m_ui->widgetTreeButton, ++ &QPushButton::clicked, ++ []() ++ { ++ for ( auto* w : qApp->topLevelWidgets() ) ++ { ++ Logger::CDebug deb; ++ dumpWidgetTree( deb, w, 0 ); ++ } ++ } ); ++ ++ // Send Log button only if it would be useful ++ m_ui->sendLogButton->setVisible( Calamares::Paste::isEnabled() ); ++ connect( m_ui->sendLogButton, &QPushButton::clicked, [ this ]() { Calamares::Paste::doLogUploadUI( this ); } ); ++ ++ CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); setWindowTitle( tr( "Debug Information", "@title" ) ); ); ++} ++ ++void ++DebugWindow::closeEvent( QCloseEvent* e ) ++{ ++ Q_UNUSED( e ) ++ emit closed(); ++} ++ ++DebugWindowManager::DebugWindowManager( QObject* parent ) ++ : QObject( parent ) ++{ ++} ++ ++bool ++DebugWindowManager::enabled() const ++{ ++ const auto* s = Settings::instance(); ++ return ( Logger::logLevel() >= Logger::LOGVERBOSE ) || ( s ? s->debugMode() : false ); ++} ++ ++void ++DebugWindowManager::show( bool visible ) ++{ ++ if ( !enabled() ) ++ { ++ visible = false; ++ } ++ if ( m_visible == visible ) ++ { ++ return; ++ } ++ ++ if ( visible ) ++ { ++ m_debugWindow = new Calamares::DebugWindow(); ++ m_debugWindow->show(); ++ connect( m_debugWindow.data(), ++ &Calamares::DebugWindow::closed, ++ this, ++ [ = ]() ++ { ++ m_debugWindow->deleteLater(); ++ m_visible = false; ++ emit visibleChanged( false ); ++ } ); ++ m_visible = true; ++ emit visibleChanged( true ); ++ } ++ else ++ { ++ if ( m_debugWindow ) ++ { ++ m_debugWindow->deleteLater(); ++ } ++ m_visible = false; ++ emit visibleChanged( false ); ++ } ++} ++ ++void ++DebugWindowManager::toggle() ++{ ++ show( !m_visible ); ++} ++ ++void ++DebugWindowManager::about() ++{ ++ QString title = Calamares::Settings::instance()->isSetupMode() ++ ? QCoreApplication::translate( "WelcomePage", "About %1 Setup", "@title" ) ++ : QCoreApplication::translate( "WelcomePage", "About %1 Installer", "@title" ); ++ QMessageBox mb( QMessageBox::Information, ++ title.arg( CALAMARES_APPLICATION_NAME ), ++ Calamares::aboutString().arg( Calamares::Branding::instance()->versionedName() ), ++ QMessageBox::Ok, ++ nullptr ); ++ Calamares::fixButtonLabels( &mb ); ++ mb.setStyleSheet( ++ "QMessageBox {" ++ "border: 1px solid hsl(240,2%,79%);" ++ "border-radius: 5px;" ++ "background-color: #FFFFFF;" // 设置对话框背景颜色 ++ "}" ++ ); ++ mb.setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); ++ mb.setIconPixmap( ++ Calamares::defaultPixmap( Calamares::BigLogo,//Biglogo.svg ++ Calamares::Original, ++ QSize( 321/1.9, 297/2 ) ) ); ++ QGridLayout* layout = reinterpret_cast< QGridLayout* >( mb.layout() ); ++ if ( layout ) ++ { ++ layout->setColumnMinimumWidth( 2, Calamares::defaultFontHeight() * 24 ); ++ } ++ mb.exec(); ++} ++ ++} // namespace Calamares +diff --git a/src/calamares/DebugWindow.h b/src/calamares/DebugWindow.h +index 83bfb08..9ed77e5 100644 +--- a/src/calamares/DebugWindow.h ++++ b/src/calamares/DebugWindow.h +@@ -1,96 +1,96 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2015 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2019 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#ifndef CALAMARES_DEBUGWINDOW_H +-#define CALAMARES_DEBUGWINDOW_H +- +-#include "VariantModel.h" +- +-#include +-#include +-#include +- +-#include +- +-namespace Calamares +-{ +- +-// From the .ui file +-namespace Ui +-{ +-class DebugWindow; +-} // namespace Ui +- +-class DebugWindow : public QWidget +-{ +- Q_OBJECT +- +-public: +- explicit DebugWindow(); +- +-signals: +- void closed(); +- +-protected: +- void closeEvent( QCloseEvent* e ) override; +- +-private: +- Ui::DebugWindow* m_ui; +- QVariant m_globals; +- QVariant m_module; +- std::unique_ptr< VariantModel > m_globals_model; +- std::unique_ptr< VariantModel > m_module_model; +-}; +- +-/** @brief Manager for meta-windows (Debug and About windows) +- * +- * Only one DebugWindow is expected to be around. This class manages +- * (exactly one) DebugWindow and can create and destroy it as needed. +- * It is available to the Calamares panels as object `DebugWindow`. +- * +- * The about() method shows a modal pop-up about Calamares. +- */ +-class DebugWindowManager : public QObject +-{ +- Q_OBJECT +- +- /// @brief Proxy to Settings::debugMode() default @c false +- Q_PROPERTY( bool enabled READ enabled CONSTANT FINAL ) +- +- /** @brief Is the debug window visible? +- * +- * Writing @c true to this **may** make the debug window visible to +- * the user; only if debugMode() is on. +- */ +- Q_PROPERTY( bool visible READ visible WRITE show NOTIFY visibleChanged ) +- +-public: +- DebugWindowManager( QObject* parent = nullptr ); +- virtual ~DebugWindowManager() override = default; +- +-public Q_SLOTS: +- bool enabled() const; +- bool visible() const { return m_visible; } +- void show( bool visible ); +- void toggle(); +- +- void about(); +- +-signals: +- void visibleChanged( bool visible ); +- +-private: +- QPointer< DebugWindow > m_debugWindow; +- bool m_visible = false; +-}; +- +- +-} // namespace Calamares +-#endif ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2015 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2019 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#ifndef CALAMARES_DEBUGWINDOW_H ++#define CALAMARES_DEBUGWINDOW_H ++ ++#include "VariantModel.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace Calamares ++{ ++ ++// From the .ui file ++namespace Ui ++{ ++class DebugWindow; ++} // namespace Ui ++ ++class DebugWindow : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit DebugWindow(); ++ ++signals: ++ void closed(); ++ ++protected: ++ void closeEvent( QCloseEvent* e ) override; ++ ++private: ++ Ui::DebugWindow* m_ui; ++ QVariant m_globals; ++ QVariant m_module; ++ std::unique_ptr< VariantModel > m_globals_model; ++ std::unique_ptr< VariantModel > m_module_model; ++}; ++ ++/** @brief Manager for meta-windows (Debug and About windows) ++ * ++ * Only one DebugWindow is expected to be around. This class manages ++ * (exactly one) DebugWindow and can create and destroy it as needed. ++ * It is available to the Calamares panels as object `DebugWindow`. ++ * ++ * The about() method shows a modal pop-up about Calamares. ++ */ ++class DebugWindowManager : public QObject ++{ ++ Q_OBJECT ++ ++ /// @brief Proxy to Settings::debugMode() default @c false ++ Q_PROPERTY( bool enabled READ enabled CONSTANT FINAL ) ++ ++ /** @brief Is the debug window visible? ++ * ++ * Writing @c true to this **may** make the debug window visible to ++ * the user; only if debugMode() is on. ++ */ ++ Q_PROPERTY( bool visible READ visible WRITE show NOTIFY visibleChanged ) ++ ++public: ++ DebugWindowManager( QObject* parent = nullptr ); ++ virtual ~DebugWindowManager() override = default; ++ ++public Q_SLOTS: ++ bool enabled() const; ++ bool visible() const { return m_visible; } ++ void show( bool visible ); ++ void toggle(); ++ ++ void about(); ++ ++signals: ++ void visibleChanged( bool visible ); ++ ++private: ++ QPointer< DebugWindow > m_debugWindow; ++ bool m_visible = false; ++}; ++ ++ ++} // namespace Calamares ++#endif +diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp +index da4f556..6d175d5 100644 +--- a/src/calamares/VariantModel.cpp ++++ b/src/calamares/VariantModel.cpp +@@ -1,285 +1,285 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2019 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#include "VariantModel.h" +- +-#include "compat/Variant.h" +- +-static bool +-isMapLike( const QVariant& item ) +-{ +- return item.canConvert< QVariantMap >(); +-} +- +-static bool +-isListLike( const QVariant& item ) +-{ +- return item.canConvert< QVariantList >() && !( Calamares::typeOf( item ) == Calamares::StringVariantType ); +-} +- +-static void +-overallLength( const QVariant& item, quintptr& c, quintptr parent, VariantModel::IndexVector* skiplist ) +-{ +- if ( skiplist ) +- { +- skiplist->append( parent ); +- } +- +- parent = c++; +- if ( isMapLike( item ) ) +- { +- for ( const auto& subitem : item.toMap() ) +- { +- overallLength( subitem, c, parent, skiplist ); +- } +- } +- else if ( isListLike( item ) ) +- { +- for ( const auto& subitem : item.toList() ) +- { +- overallLength( subitem, c, parent, skiplist ); +- } +- } +-} +- +-static quintptr +-findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) +-{ +- constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); +- +- if ( n < 0 ) +- { +- return invalid_index; +- } +- +- int index = static_cast< int >( value ); +- while ( ( n >= 0 ) && ( index < skiplist.count() ) ) +- { +- if ( skiplist[ index ] == value ) +- { +- if ( --n < 0 ) +- { +- // It's bigger than 0 +- return static_cast< quintptr >( index ); +- } +- } +- index++; +- } +- return invalid_index; +-} +- +- +-VariantModel::VariantModel( const QVariant* p ) +- : m_p( p ) +-{ +- reload(); +-} +- +-VariantModel::~VariantModel() {} +- +-void +-VariantModel::reload() +-{ +- constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); +- +- quintptr x = 0; +- m_rows.clear(); // Start over +- if ( m_rows.capacity() < 64 ) +- { +- m_rows.reserve( 64 ); // Start reasonably-sized +- } +- overallLength( *m_p, x, invalid_index, &m_rows ); +-} +- +-int +-VariantModel::columnCount( const QModelIndex& ) const +-{ +- return 2; +-} +- +-int +-VariantModel::rowCount( const QModelIndex& index ) const +-{ +- quintptr p = index.isValid() ? index.internalId() : 0; +- return m_rows.count( p ); +-} +- +-QModelIndex +-VariantModel::index( int row, int column, const QModelIndex& parent ) const +-{ +- quintptr p = 0; +- +- if ( parent.isValid() ) +- { +- if ( inRange( parent ) ) +- { +- p = parent.internalId(); +- } +- } +- +- return createIndex( row, column, findNth( m_rows, p, row ) ); +-} +- +-static inline quintptr +-deref( const VariantModel::IndexVector& v, quintptr i ) +-{ +- return v[ static_cast< int >( i ) ]; +-} +- +-QModelIndex +-VariantModel::parent( const QModelIndex& index ) const +-{ +- if ( !index.isValid() || !inRange( index ) ) +- { +- return QModelIndex(); +- } +- +- quintptr p = deref( m_rows, index.internalId() ); +- if ( p == 0 ) +- { +- return QModelIndex(); +- } +- +- if ( !inRange( p ) ) +- { +- return QModelIndex(); +- } +- quintptr p_pid = deref( m_rows, p ); +- int row = 0; +- for ( int i = static_cast< int >( p_pid ); i < static_cast< int >( p ); ++i ) +- { +- if ( m_rows[ i ] == p_pid ) +- { +- row++; +- } +- } +- +- return createIndex( row, index.column(), p ); +-} +- +-QVariant +-VariantModel::data( const QModelIndex& index, int role ) const +-{ +- if ( role != Qt::DisplayRole ) +- { +- return QVariant(); +- } +- +- if ( !index.isValid() ) +- { +- return QVariant(); +- } +- +- if ( ( index.column() < 0 ) || ( index.column() > 1 ) ) +- { +- return QVariant(); +- } +- +- if ( !inRange( index ) ) +- { +- return QVariant(); +- } +- +- const QVariant thing = underlying( parent( index ) ); +- +- if ( !thing.isValid() ) +- { +- return QVariant(); +- } +- +- if ( isMapLike( thing ) ) +- { +- QVariantMap the_map = thing.toMap(); +- const auto key = the_map.keys().at( index.row() ); +- if ( index.column() == 0 ) +- { +- return key; +- } +- else +- { +- return the_map[ key ]; +- } +- } +- else if ( isListLike( thing ) ) +- { +- if ( index.column() == 0 ) +- { +- return index.row(); +- } +- else +- { +- QVariantList the_list = thing.toList(); +- return the_list.at( index.row() ); +- } +- } +- else +- { +- if ( index.column() == 0 ) +- { +- return QVariant(); +- } +- else +- { +- return thing; +- } +- } +-} +- +-QVariant +-VariantModel::headerData( int section, Qt::Orientation orientation, int role ) const +-{ +- if ( role != Qt::DisplayRole ) +- { +- return QVariant(); +- } +- +- if ( orientation == Qt::Horizontal ) +- { +- if ( section == 0 ) +- { +- return tr( "Key", "Column header for key/value" ); +- } +- else if ( section == 1 ) +- { +- return tr( "Value", "Column header for key/value" ); +- } +- else +- { +- return QVariant(); +- } +- } +- else +- { +- return QVariant(); +- } +-} +- +-const QVariant +-VariantModel::underlying( const QModelIndex& index ) const +-{ +- if ( !index.isValid() ) +- { +- return *m_p; +- } +- +- const auto& thing = underlying( parent( index ) ); +- if ( isMapLike( thing ) ) +- { +- const auto& the_map = thing.toMap(); +- return the_map[ the_map.keys()[ index.row() ] ]; +- } +- else if ( isListLike( thing ) ) +- { +- return thing.toList()[ index.row() ]; +- } +- else +- { +- return thing; +- } +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2019 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#include "VariantModel.h" ++ ++#include "compat/Variant.h" ++ ++static bool ++isMapLike( const QVariant& item ) ++{ ++ return item.canConvert< QVariantMap >(); ++} ++ ++static bool ++isListLike( const QVariant& item ) ++{ ++ return item.canConvert< QVariantList >() && !( Calamares::typeOf( item ) == Calamares::StringVariantType ); ++} ++ ++static void ++overallLength( const QVariant& item, quintptr& c, quintptr parent, VariantModel::IndexVector* skiplist ) ++{ ++ if ( skiplist ) ++ { ++ skiplist->append( parent ); ++ } ++ ++ parent = c++; ++ if ( isMapLike( item ) ) ++ { ++ for ( const auto& subitem : item.toMap() ) ++ { ++ overallLength( subitem, c, parent, skiplist ); ++ } ++ } ++ else if ( isListLike( item ) ) ++ { ++ for ( const auto& subitem : item.toList() ) ++ { ++ overallLength( subitem, c, parent, skiplist ); ++ } ++ } ++} ++ ++static quintptr ++findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) ++{ ++ constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); ++ ++ if ( n < 0 ) ++ { ++ return invalid_index; ++ } ++ ++ int index = static_cast< int >( value ); ++ while ( ( n >= 0 ) && ( index < skiplist.count() ) ) ++ { ++ if ( skiplist[ index ] == value ) ++ { ++ if ( --n < 0 ) ++ { ++ // It's bigger than 0 ++ return static_cast< quintptr >( index ); ++ } ++ } ++ index++; ++ } ++ return invalid_index; ++} ++ ++ ++VariantModel::VariantModel( const QVariant* p ) ++ : m_p( p ) ++{ ++ reload(); ++} ++ ++VariantModel::~VariantModel() {} ++ ++void ++VariantModel::reload() ++{ ++ constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); ++ ++ quintptr x = 0; ++ m_rows.clear(); // Start over ++ if ( m_rows.capacity() < 64 ) ++ { ++ m_rows.reserve( 64 ); // Start reasonably-sized ++ } ++ overallLength( *m_p, x, invalid_index, &m_rows ); ++} ++ ++int ++VariantModel::columnCount( const QModelIndex& ) const ++{ ++ return 2; ++} ++ ++int ++VariantModel::rowCount( const QModelIndex& index ) const ++{ ++ quintptr p = index.isValid() ? index.internalId() : 0; ++ return m_rows.count( p ); ++} ++ ++QModelIndex ++VariantModel::index( int row, int column, const QModelIndex& parent ) const ++{ ++ quintptr p = 0; ++ ++ if ( parent.isValid() ) ++ { ++ if ( inRange( parent ) ) ++ { ++ p = parent.internalId(); ++ } ++ } ++ ++ return createIndex( row, column, findNth( m_rows, p, row ) ); ++} ++ ++static inline quintptr ++deref( const VariantModel::IndexVector& v, quintptr i ) ++{ ++ return v[ static_cast< int >( i ) ]; ++} ++ ++QModelIndex ++VariantModel::parent( const QModelIndex& index ) const ++{ ++ if ( !index.isValid() || !inRange( index ) ) ++ { ++ return QModelIndex(); ++ } ++ ++ quintptr p = deref( m_rows, index.internalId() ); ++ if ( p == 0 ) ++ { ++ return QModelIndex(); ++ } ++ ++ if ( !inRange( p ) ) ++ { ++ return QModelIndex(); ++ } ++ quintptr p_pid = deref( m_rows, p ); ++ int row = 0; ++ for ( int i = static_cast< int >( p_pid ); i < static_cast< int >( p ); ++i ) ++ { ++ if ( m_rows[ i ] == p_pid ) ++ { ++ row++; ++ } ++ } ++ ++ return createIndex( row, index.column(), p ); ++} ++ ++QVariant ++VariantModel::data( const QModelIndex& index, int role ) const ++{ ++ if ( role != Qt::DisplayRole ) ++ { ++ return QVariant(); ++ } ++ ++ if ( !index.isValid() ) ++ { ++ return QVariant(); ++ } ++ ++ if ( ( index.column() < 0 ) || ( index.column() > 1 ) ) ++ { ++ return QVariant(); ++ } ++ ++ if ( !inRange( index ) ) ++ { ++ return QVariant(); ++ } ++ ++ const QVariant thing = underlying( parent( index ) ); ++ ++ if ( !thing.isValid() ) ++ { ++ return QVariant(); ++ } ++ ++ if ( isMapLike( thing ) ) ++ { ++ QVariantMap the_map = thing.toMap(); ++ const auto key = the_map.keys().at( index.row() ); ++ if ( index.column() == 0 ) ++ { ++ return key; ++ } ++ else ++ { ++ return the_map[ key ]; ++ } ++ } ++ else if ( isListLike( thing ) ) ++ { ++ if ( index.column() == 0 ) ++ { ++ return index.row(); ++ } ++ else ++ { ++ QVariantList the_list = thing.toList(); ++ return the_list.at( index.row() ); ++ } ++ } ++ else ++ { ++ if ( index.column() == 0 ) ++ { ++ return QVariant(); ++ } ++ else ++ { ++ return thing; ++ } ++ } ++} ++ ++QVariant ++VariantModel::headerData( int section, Qt::Orientation orientation, int role ) const ++{ ++ if ( role != Qt::DisplayRole ) ++ { ++ return QVariant(); ++ } ++ ++ if ( orientation == Qt::Horizontal ) ++ { ++ if ( section == 0 ) ++ { ++ return tr( "Key", "Column header for key/value" ); ++ } ++ else if ( section == 1 ) ++ { ++ return tr( "Value", "Column header for key/value" ); ++ } ++ else ++ { ++ return QVariant(); ++ } ++ } ++ else ++ { ++ return QVariant(); ++ } ++} ++ ++const QVariant ++VariantModel::underlying( const QModelIndex& index ) const ++{ ++ if ( !index.isValid() ) ++ { ++ return *m_p; ++ } ++ ++ const auto& thing = underlying( parent( index ) ); ++ if ( isMapLike( thing ) ) ++ { ++ const auto& the_map = thing.toMap(); ++ return the_map[ the_map.keys()[ index.row() ] ]; ++ } ++ else if ( isListLike( thing ) ) ++ { ++ return thing.toList()[ index.row() ]; ++ } ++ else ++ { ++ return thing; ++ } ++} +diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h +index 9d33231..4e47a93 100644 +--- a/src/calamares/VariantModel.h ++++ b/src/calamares/VariantModel.h +@@ -1,104 +1,104 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2019 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#ifndef VARIANTMODEL_H +-#define VARIANTMODEL_H +- +-#include +-#include +-#include +- +-/** @brief A model that operates directly on a QVariant +- * +- * A VariantModel operates directly on an underlying +- * QVariant, treating QVariantMap and QVariantList as +- * nodes with multiple children. In general, putting +- * a QVariantMap into a QVariant and passing that into +- * the model will get you a tree-like model of the +- * VariantMap's data structure. +- * +- * Take care of object lifetimes and that the underlying +- * QVariant does not change during use. If the QVariant +- * **does** change, call reload() to re-build the internal +- * representation of the tree. +- */ +-class VariantModel : public QAbstractItemModel +-{ +- Q_OBJECT +-public: +- /** @brief Auxiliary data +- * +- * The nodes of the tree are enumerated into a vector +- * (of length equal to the number of nodes in the tree + 1) +- * which are used to do index and parent calculations. +- */ +- using IndexVector = QVector< quintptr >; +- +- /** @brief Constructor +- * +- * The QVariant's lifetime is **not** affected by the model, +- * so take care that the QVariant lives at least as long as +- * the model). Also, don't change the QVariant underneath the model. +- */ +- VariantModel( const QVariant* p ); +- +- ~VariantModel() override; +- +- /** @brief Re-build the internal tree +- * +- * Call this when the underlying variant is changed, which +- * might impact how the tree is laid out. +- */ +- void reload(); +- +- int columnCount( const QModelIndex& index ) const override; +- int rowCount( const QModelIndex& index ) const override; +- +- QModelIndex index( int row, int column, const QModelIndex& parent ) const override; +- QModelIndex parent( const QModelIndex& index ) const override; +- QVariant data( const QModelIndex& index, int role ) const override; +- QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; +- +-private: +- const QVariant* const m_p; +- +- /** @brief Tree representation of the variant. +- * +- * At index 0 in the vector , we store -1 to indicate the root. +- * +- * Then we enumerate all the elements in the tree (by traversing +- * the variant and using QVariantMap and QVariantList as having +- * children, and everything else being a leaf node) and at the index +- * for a child, store the index of its parent. This means that direct +- * children of the root store a 0 in their indexes, children of the first +- * child of the root store a 1, and we can "pointer chase" from an index +- * through parents back to index 0. +- * +- * Because of this structure, the value stored at index i must be +- * less than i (except for index 0, which is special). This makes it +- * slightly easier to search for a given value *p*, because we can start +- * at index *p* (or even *p+1*). +- * +- * Given an index *i* into the vector corresponding to a child, we know the +- * parent, but can also count which row this child should have, by counting +- * *other* indexes before *i* with the same parent (and by the ordering +- * of values, we can start counting at index *parent-index*). +- * +- */ +- IndexVector m_rows; +- +- /// @brief Implementation of walking an index through the variant-tree +- const QVariant underlying( const QModelIndex& index ) const; +- +- /// @brief Helpers for range-checking +- inline bool inRange( quintptr p ) const { return p < static_cast< quintptr >( m_rows.count() ); } +- inline bool inRange( const QModelIndex& index ) const { return inRange( index.internalId() ); } +-}; +- +-#endif ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2019 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#ifndef VARIANTMODEL_H ++#define VARIANTMODEL_H ++ ++#include ++#include ++#include ++ ++/** @brief A model that operates directly on a QVariant ++ * ++ * A VariantModel operates directly on an underlying ++ * QVariant, treating QVariantMap and QVariantList as ++ * nodes with multiple children. In general, putting ++ * a QVariantMap into a QVariant and passing that into ++ * the model will get you a tree-like model of the ++ * VariantMap's data structure. ++ * ++ * Take care of object lifetimes and that the underlying ++ * QVariant does not change during use. If the QVariant ++ * **does** change, call reload() to re-build the internal ++ * representation of the tree. ++ */ ++class VariantModel : public QAbstractItemModel ++{ ++ Q_OBJECT ++public: ++ /** @brief Auxiliary data ++ * ++ * The nodes of the tree are enumerated into a vector ++ * (of length equal to the number of nodes in the tree + 1) ++ * which are used to do index and parent calculations. ++ */ ++ using IndexVector = QVector< quintptr >; ++ ++ /** @brief Constructor ++ * ++ * The QVariant's lifetime is **not** affected by the model, ++ * so take care that the QVariant lives at least as long as ++ * the model). Also, don't change the QVariant underneath the model. ++ */ ++ VariantModel( const QVariant* p ); ++ ++ ~VariantModel() override; ++ ++ /** @brief Re-build the internal tree ++ * ++ * Call this when the underlying variant is changed, which ++ * might impact how the tree is laid out. ++ */ ++ void reload(); ++ ++ int columnCount( const QModelIndex& index ) const override; ++ int rowCount( const QModelIndex& index ) const override; ++ ++ QModelIndex index( int row, int column, const QModelIndex& parent ) const override; ++ QModelIndex parent( const QModelIndex& index ) const override; ++ QVariant data( const QModelIndex& index, int role ) const override; ++ QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; ++ ++private: ++ const QVariant* const m_p; ++ ++ /** @brief Tree representation of the variant. ++ * ++ * At index 0 in the vector , we store -1 to indicate the root. ++ * ++ * Then we enumerate all the elements in the tree (by traversing ++ * the variant and using QVariantMap and QVariantList as having ++ * children, and everything else being a leaf node) and at the index ++ * for a child, store the index of its parent. This means that direct ++ * children of the root store a 0 in their indexes, children of the first ++ * child of the root store a 1, and we can "pointer chase" from an index ++ * through parents back to index 0. ++ * ++ * Because of this structure, the value stored at index i must be ++ * less than i (except for index 0, which is special). This makes it ++ * slightly easier to search for a given value *p*, because we can start ++ * at index *p* (or even *p+1*). ++ * ++ * Given an index *i* into the vector corresponding to a child, we know the ++ * parent, but can also count which row this child should have, by counting ++ * *other* indexes before *i* with the same parent (and by the ordering ++ * of values, we can start counting at index *parent-index*). ++ * ++ */ ++ IndexVector m_rows; ++ ++ /// @brief Implementation of walking an index through the variant-tree ++ const QVariant underlying( const QModelIndex& index ) const; ++ ++ /// @brief Helpers for range-checking ++ inline bool inRange( quintptr p ) const { return p < static_cast< quintptr >( m_rows.count() ); } ++ inline bool inRange( const QModelIndex& index ) const { return inRange( index.internalId() ); } ++}; ++ ++#endif +diff --git a/src/calamares/calamares-navigation.qml b/src/calamares/calamares-navigation.qml +index becc1b4..58c233d 100644 +--- a/src/calamares/calamares-navigation.qml ++++ b/src/calamares/calamares-navigation.qml +@@ -1,83 +1,83 @@ +-/* Sample of QML navigation. +- +- SPDX-FileCopyrightText: 2020 Adriaan de Groot +- SPDX-License-Identifier: GPL-3.0-or-later +- +- +- The navigation panel is generally "horizontal" in layout, with +- buttons for next and previous; this particular one copies +- the layout and size of the widgets panel. +-*/ +-import io.calamares.ui 1.0 +-import io.calamares.core 1.0 +- +-import QtQuick 2.3 +-import QtQuick.Controls 2.10 +-import QtQuick.Layouts 1.3 +- +-Rectangle { +- id: navigationBar; +- color: Branding.styleString( Branding.SidebarBackground ); +- height: 48; +- +- RowLayout { +- id: buttonBar +- anchors.fill: parent; +- +- Item +- { +- Layout.fillWidth: true; +- } +- +- Button +- { +- text: ViewManager.backLabel; +- icon.name: ViewManager.backIcon; +- +- enabled: ViewManager.backEnabled; +- visible: ViewManager.backAndNextVisible; +- onClicked: { ViewManager.back(); } +- } +- Button +- { +- text: ViewManager.nextLabel; +- icon.name: ViewManager.nextIcon; +- +- enabled: ViewManager.nextEnabled; +- visible: ViewManager.backAndNextVisible; +- onClicked: { ViewManager.next(); } +- // This margin goes in the "next" button, because the "quit" +- // button can vanish and we want to keep the margin to +- // the next-thing-in-the-navigation-panel around. +- Layout.rightMargin: 3 * buttonBar.spacing; +- } +- Button +- { +- Layout.rightMargin: 2 * buttonBar.spacing +- text: ViewManager.quitLabel; +- icon.name: ViewManager.quitIcon; +- +- ToolTip.visible: hovered +- ToolTip.timeout: 5000 +- ToolTip.delay: 1000 +- ToolTip.text: ViewManager.quitTooltip; +- +- /* +- * The ViewManager has settings -- user-controlled via the +- * branding component, and party based on program state -- +- * whether the quit button should be enabled and visible. +- * +- * QML navigation *should* follow this pattern, but can also +- * add other qualifications. For instance, you may have a +- * "finished" module that handles quit in its own way, and +- * want to hide the quit button then. The ViewManager has a +- * current step and a total count, so compare them: +- * +- * visible: ViewManager.quitVisible && ( ViewManager.currentStepIndex < ViewManager.rowCount()-1); +- */ +- enabled: ViewManager.quitEnabled; +- visible: ViewManager.quitVisible; +- onClicked: { ViewManager.quit(); } +- } +- } +-} ++/* Sample of QML navigation. ++ ++ SPDX-FileCopyrightText: 2020 Adriaan de Groot ++ SPDX-License-Identifier: GPL-3.0-or-later ++ ++ ++ The navigation panel is generally "horizontal" in layout, with ++ buttons for next and previous; this particular one copies ++ the layout and size of the widgets panel. ++*/ ++import io.calamares.ui 1.0 ++import io.calamares.core 1.0 ++ ++import QtQuick 2.3 ++import QtQuick.Controls 2.10 ++import QtQuick.Layouts 1.3 ++ ++Rectangle { ++ id: navigationBar; ++ color: Branding.styleString( Branding.SidebarBackground ); ++ height: 48; ++ ++ RowLayout { ++ id: buttonBar ++ anchors.fill: parent; ++ ++ Item ++ { ++ Layout.fillWidth: true; ++ } ++ ++ Button ++ { ++ text: ViewManager.backLabel; ++ icon.name: ViewManager.backIcon; ++ ++ enabled: ViewManager.backEnabled; ++ visible: ViewManager.backAndNextVisible; ++ onClicked: { ViewManager.back(); } ++ } ++ Button ++ { ++ text: ViewManager.nextLabel; ++ icon.name: ViewManager.nextIcon; ++ ++ enabled: ViewManager.nextEnabled; ++ visible: ViewManager.backAndNextVisible; ++ onClicked: { ViewManager.next(); } ++ // This margin goes in the "next" button, because the "quit" ++ // button can vanish and we want to keep the margin to ++ // the next-thing-in-the-navigation-panel around. ++ Layout.rightMargin: 3 * buttonBar.spacing; ++ } ++ Button ++ { ++ Layout.rightMargin: 2 * buttonBar.spacing ++ text: ViewManager.quitLabel; ++ icon.name: ViewManager.quitIcon; ++ ++ ToolTip.visible: hovered ++ ToolTip.timeout: 5000 ++ ToolTip.delay: 1000 ++ ToolTip.text: ViewManager.quitTooltip; ++ ++ /* ++ * The ViewManager has settings -- user-controlled via the ++ * branding component, and party based on program state -- ++ * whether the quit button should be enabled and visible. ++ * ++ * QML navigation *should* follow this pattern, but can also ++ * add other qualifications. For instance, you may have a ++ * "finished" module that handles quit in its own way, and ++ * want to hide the quit button then. The ViewManager has a ++ * current step and a total count, so compare them: ++ * ++ * visible: ViewManager.quitVisible && ( ViewManager.currentStepIndex < ViewManager.rowCount()-1); ++ */ ++ enabled: ViewManager.quitEnabled; ++ visible: ViewManager.quitVisible; ++ onClicked: { ViewManager.quit(); } ++ } ++ } ++} +diff --git a/src/calamares/calamares-sidebar.qml b/src/calamares/calamares-sidebar.qml +index 4780823..3a75d95 100644 +--- a/src/calamares/calamares-sidebar.qml ++++ b/src/calamares/calamares-sidebar.qml +@@ -1,125 +1,125 @@ +-/* Sample of QML progress tree. +- +- SPDX-FileCopyrightText: 2020 Adriaan de Groot +- SPDX-FileCopyrightText: 2021 Anke Boersma +- SPDX-License-Identifier: GPL-3.0-or-later +- +- +- The progress tree (actually a list) is generally "vertical" in layout, +- with the steps going "down", but it could also be a more compact +- horizontal layout with suitable branding settings. +- +- This example emulates the layout and size of the widgets progress tree. +-*/ +-import io.calamares.ui 1.0 +-import io.calamares.core 1.0 +- +-import QtQuick 2.3 +-import QtQuick.Layouts 1.3 +- +-Rectangle { +- id: sideBar; +- color: Branding.styleString( Branding.SidebarBackground ); +- anchors.fill: parent; +- +- ColumnLayout { +- anchors.fill: parent; +- spacing: 0; +- +- Image { +- Layout.topMargin: 12; +- Layout.bottomMargin: 12; +- Layout.alignment: Qt.AlignHCenter | Qt.AlignTop +- id: logo; +- width: 80; +- height: width; // square +- source: "file:/" + Branding.imagePath(Branding.ProductLogo); +- sourceSize.width: width; +- sourceSize.height: height; +- } +- +- Repeater { +- model: ViewManager +- Rectangle { +- Layout.leftMargin: 6; +- Layout.rightMargin: 6; +- Layout.fillWidth: true; +- height: 35; +- radius: 6; +- color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground ); +- +- Text { +- anchors.verticalCenter: parent.verticalCenter; +- anchors.horizontalCenter: parent.horizontalCenter; +- color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextCurrent : Branding.SidebarText ); +- text: display; +- } +- } +- } +- +- Item { +- Layout.fillHeight: true; +- } +- +- Rectangle { +- id: metaArea +- Layout.fillWidth: true; +- height: 35 +- Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom +- color: Branding.styleString( Branding.SidebarBackground ); +- visible: true; +- +- Rectangle { +- id: aboutArea +- height: 35 +- width: parent.width / 2; +- anchors.left: parent.left +- color: Branding.styleString( Branding.SidebarBackgroundCurrent ); +- visible: true; +- +- MouseArea { +- id: mouseAreaAbout +- anchors.fill: parent; +- cursorShape: Qt.PointingHandCursor +- hoverEnabled: true +- Text { +- anchors.verticalCenter: parent.verticalCenter; +- anchors.horizontalCenter: parent.horizontalCenter; +- x: parent.x + 4; +- text: qsTr("About") +- color: Branding.styleString( Branding.SidebarTextCurrent ); +- font.pointSize : 9 +- } +- +- onClicked: debug.about() +- } +- } +- +- Rectangle { +- id: debugArea +- height: 35 +- width: parent.width / 2; +- anchors.right: parent.right +- color: Branding.styleString( Branding.SidebarBackgroundCurrent ); +- visible: debug.enabled +- +- MouseArea { +- id: mouseAreaDebug +- anchors.fill: parent; +- cursorShape: Qt.PointingHandCursor +- hoverEnabled: true +- Text { +- anchors.verticalCenter: parent.verticalCenter; +- anchors.horizontalCenter: parent.horizontalCenter; +- x: parent.x + 4; +- text: qsTr("Debug") +- color: Branding.styleString( Branding.SidebarTextCurrent ); +- font.pointSize : 9 +- } +- +- onClicked: debug.toggle() +- } +- } +- } +- } +-} ++/* Sample of QML progress tree. ++ ++ SPDX-FileCopyrightText: 2020 Adriaan de Groot ++ SPDX-FileCopyrightText: 2021 Anke Boersma ++ SPDX-License-Identifier: GPL-3.0-or-later ++ ++ ++ The progress tree (actually a list) is generally "vertical" in layout, ++ with the steps going "down", but it could also be a more compact ++ horizontal layout with suitable branding settings. ++ ++ This example emulates the layout and size of the widgets progress tree. ++*/ ++import io.calamares.ui 1.0 ++import io.calamares.core 1.0 ++ ++import QtQuick 2.3 ++import QtQuick.Layouts 1.3 ++ ++Rectangle { ++ id: sideBar; ++ color: Branding.styleString( Branding.SidebarBackground ); ++ anchors.fill: parent; ++ ++ ColumnLayout { ++ anchors.fill: parent; ++ spacing: 0; ++ ++ Image { ++ Layout.topMargin: 12; ++ Layout.bottomMargin: 12; ++ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop ++ id: logo; ++ width: 80; ++ height: width; // square ++ source: "file:/" + Branding.imagePath(Branding.ProductLogo); ++ sourceSize.width: width; ++ sourceSize.height: height; ++ } ++ ++ Repeater { ++ model: ViewManager ++ Rectangle { ++ Layout.leftMargin: 6; ++ Layout.rightMargin: 6; ++ Layout.fillWidth: true; ++ height: 35; ++ radius: 6; ++ color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground ); ++ ++ Text { ++ anchors.verticalCenter: parent.verticalCenter; ++ anchors.horizontalCenter: parent.horizontalCenter; ++ color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextCurrent : Branding.SidebarText ); ++ text: display; ++ } ++ } ++ } ++ ++ Item { ++ Layout.fillHeight: true; ++ } ++ ++ Rectangle { ++ id: metaArea ++ Layout.fillWidth: true; ++ height: 35 ++ Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom ++ color: Branding.styleString( Branding.SidebarBackground ); ++ visible: true; ++ ++ Rectangle { ++ id: aboutArea ++ height: 35 ++ width: parent.width / 2; ++ anchors.left: parent.left ++ color: Branding.styleString( Branding.SidebarBackgroundCurrent ); ++ visible: true; ++ ++ MouseArea { ++ id: mouseAreaAbout ++ anchors.fill: parent; ++ cursorShape: Qt.PointingHandCursor ++ hoverEnabled: true ++ Text { ++ anchors.verticalCenter: parent.verticalCenter; ++ anchors.horizontalCenter: parent.horizontalCenter; ++ x: parent.x + 4; ++ text: qsTr("About") ++ color: Branding.styleString( Branding.SidebarTextCurrent ); ++ font.pointSize : 9 ++ } ++ ++ onClicked: debug.about() ++ } ++ } ++ ++ Rectangle { ++ id: debugArea ++ height: 35 ++ width: parent.width / 2; ++ anchors.right: parent.right ++ color: Branding.styleString( Branding.SidebarBackgroundCurrent ); ++ visible: debug.enabled ++ ++ MouseArea { ++ id: mouseAreaDebug ++ anchors.fill: parent; ++ cursorShape: Qt.PointingHandCursor ++ hoverEnabled: true ++ Text { ++ anchors.verticalCenter: parent.verticalCenter; ++ anchors.horizontalCenter: parent.horizontalCenter; ++ x: parent.x + 4; ++ text: qsTr("Debug") ++ color: Branding.styleString( Branding.SidebarTextCurrent ); ++ font.pointSize : 9 ++ } ++ ++ onClicked: debug.toggle() ++ } ++ } ++ } ++ } ++} +diff --git a/src/calamares/calamares.qrc b/src/calamares/calamares.qrc +index 5733ea0..8517bad 100644 +--- a/src/calamares/calamares.qrc ++++ b/src/calamares/calamares.qrc +@@ -1,10 +1,10 @@ +- +- +- +- +- calamares-sidebar.qml +- calamares-navigation.qml +- +- ++ ++ ++ ++ ++ calamares-sidebar.qml ++ calamares-navigation.qml ++ ++ +diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp +index e0491e5..af1b13a 100644 +--- a/src/calamares/main.cpp ++++ b/src/calamares/main.cpp +@@ -1,154 +1,154 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2014 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#include "CalamaresApplication.h" +- +-#include "Settings.h" +-#include "utils/Dirs.h" +-#include "utils/Logger.h" +-#include "utils/Retranslator.h" +- +-// From 3rdparty/ +-#include "kdsingleapplication.h" +- +-#include +-#ifdef BUILD_CRASH_REPORTING +-#include +-#endif +- +-#include +-#include +-#include +- +-#include +- +-/** @brief Gets debug-level from -D command-line-option +- * +- * If unset, use LOGERROR (corresponding to -D1), although +- * effectively -D2 is the lowest level you can set for +- * logging-to-the-console, and everything always gets +- * logged to the session file). +- */ +-static unsigned int +-debug_level( QCommandLineParser& parser, QCommandLineOption& levelOption ) +-{ +- if ( !parser.isSet( levelOption ) ) +- { +- return Logger::LOGERROR; +- } +- +- bool ok = true; +- int l = parser.value( levelOption ).toInt( &ok ); +- if ( !ok || ( l < 0 ) ) +- { +- return Logger::LOGVERBOSE; +- } +- else +- { +- return static_cast< unsigned int >( l ); // l >= 0 +- } +-} +- +-/** @brief Handles the command-line arguments +- * +- * Sets up internals for Calamares based on command-line arguments like `-D`, +- * `-d`, etc. Returns @c true if this is a *debug* run, i.e. if the `-d` +- * command-line flag is given, @c false otherwise. +- */ +-static bool +-handle_args( CalamaresApplication& a ) +-{ +- QCommandLineOption debugOption( QStringList { "d", "debug" }, +- "Also look in current directory for configuration. Implies -D8." ); +- QCommandLineOption debugLevelOption( +- QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" ); +- QCommandLineOption debugTxOption( QStringList { "T", "debug-translation" }, +- "Also look in the current directory for translation." ); +- +- QCommandLineOption configOption( +- QStringList { "c", "config" }, "Configuration directory to use, for testing purposes.", "config" ); +- QCommandLineOption xdgOption( QStringList { "X", "xdg-config" }, "Use XDG_{CONFIG,DATA}_DIRS as well." ); +- +- QCommandLineParser parser; +- parser.setApplicationDescription( "Distribution-independent installer framework" ); +- parser.addHelpOption(); +- parser.addVersionOption(); +- +- parser.addOption( debugOption ); +- parser.addOption( debugLevelOption ); +- parser.addOption( configOption ); +- parser.addOption( xdgOption ); +- parser.addOption( debugTxOption ); +- +- parser.process( a ); +- +- Logger::setupLogLevel( parser.isSet( debugOption ) ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) ); +- if ( parser.isSet( configOption ) ) +- { +- Calamares::setAppDataDir( QDir( parser.value( configOption ) ) ); +- } +- if ( parser.isSet( xdgOption ) ) +- { +- Calamares::setXdgDirs(); +- } +- Calamares::setAllowLocalTranslation( parser.isSet( debugOption ) || parser.isSet( debugTxOption ) ); +- +- return parser.isSet( debugOption ); +-} +- +-int +-main( int argc, char* argv[] ) +-{ +-#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) +- // Not needed in Qt6 +- QApplication::setAttribute( Qt::AA_EnableHighDpiScaling ); +-#endif +- CalamaresApplication a( argc, argv ); +- +- KAboutData aboutData( "calamares", +- "Calamares", +- a.applicationVersion(), +- "The universal system installer", +- KAboutLicense::GPL_V3, +- QString(), +- QString(), +- "https://calamares.io", +- "https://github.com/calamares/calamares/issues" ); +- KAboutData::setApplicationData( aboutData ); +- a.setApplicationDisplayName( QString() ); // To avoid putting an extra "Calamares/" into the log-file +- +-#ifdef BUILD_CRASH_REPORTING +- KCrash::initialize(); +- // KCrash::setCrashHandler(); +- KCrash::setDrKonqiEnabled( true ); +- KCrash::setFlags( KCrash::SaferDialog | KCrash::AlwaysDirectly ); +-#endif +- +- std::unique_ptr< KDSingleApplication > possiblyUnique; +- const bool is_debug = handle_args( a ); +- if ( !is_debug ) +- { +- possiblyUnique = std::make_unique< KDSingleApplication >(); +- if ( !possiblyUnique->isPrimaryInstance() ) +- { +- qCritical() << "Calamares is already running."; +- return 87; // EUSERS on Linux +- } +- } +- +- Calamares::Settings::init( is_debug ); +- if ( !Calamares::Settings::instance() || !Calamares::Settings::instance()->isValid() ) +- { +- qCritical() << "Calamares has invalid settings, shutting down."; +- return 78; // EX_CONFIG on FreeBSD +- } +- a.init(); +- return a.exec(); +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2014 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#include "CalamaresApplication.h" ++ ++#include "Settings.h" ++#include "utils/Dirs.h" ++#include "utils/Logger.h" ++#include "utils/Retranslator.h" ++ ++// From 3rdparty/ ++#include "kdsingleapplication.h" ++ ++#include ++#ifdef BUILD_CRASH_REPORTING ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include ++ ++/** @brief Gets debug-level from -D command-line-option ++ * ++ * If unset, use LOGERROR (corresponding to -D1), although ++ * effectively -D2 is the lowest level you can set for ++ * logging-to-the-console, and everything always gets ++ * logged to the session file). ++ */ ++static unsigned int ++debug_level( QCommandLineParser& parser, QCommandLineOption& levelOption ) ++{ ++ if ( !parser.isSet( levelOption ) ) ++ { ++ return Logger::LOGERROR; ++ } ++ ++ bool ok = true; ++ int l = parser.value( levelOption ).toInt( &ok ); ++ if ( !ok || ( l < 0 ) ) ++ { ++ return Logger::LOGVERBOSE; ++ } ++ else ++ { ++ return static_cast< unsigned int >( l ); // l >= 0 ++ } ++} ++ ++/** @brief Handles the command-line arguments ++ * ++ * Sets up internals for Calamares based on command-line arguments like `-D`, ++ * `-d`, etc. Returns @c true if this is a *debug* run, i.e. if the `-d` ++ * command-line flag is given, @c false otherwise. ++ */ ++static bool ++handle_args( CalamaresApplication& a ) ++{ ++ QCommandLineOption debugOption( QStringList { "d", "debug" }, ++ "Also look in current directory for configuration. Implies -D8." ); ++ QCommandLineOption debugLevelOption( ++ QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" ); ++ QCommandLineOption debugTxOption( QStringList { "T", "debug-translation" }, ++ "Also look in the current directory for translation." ); ++ ++ QCommandLineOption configOption( ++ QStringList { "c", "config" }, "Configuration directory to use, for testing purposes.", "config" ); ++ QCommandLineOption xdgOption( QStringList { "X", "xdg-config" }, "Use XDG_{CONFIG,DATA}_DIRS as well." ); ++ ++ QCommandLineParser parser; ++ parser.setApplicationDescription( "Distribution-independent installer framework" ); ++ parser.addHelpOption(); ++ parser.addVersionOption(); ++ ++ parser.addOption( debugOption ); ++ parser.addOption( debugLevelOption ); ++ parser.addOption( configOption ); ++ parser.addOption( xdgOption ); ++ parser.addOption( debugTxOption ); ++ ++ parser.process( a ); ++ ++ Logger::setupLogLevel( parser.isSet( debugOption ) ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) ); ++ if ( parser.isSet( configOption ) ) ++ { ++ Calamares::setAppDataDir( QDir( parser.value( configOption ) ) ); ++ } ++ if ( parser.isSet( xdgOption ) ) ++ { ++ Calamares::setXdgDirs(); ++ } ++ Calamares::setAllowLocalTranslation( parser.isSet( debugOption ) || parser.isSet( debugTxOption ) ); ++ ++ return parser.isSet( debugOption ); ++} ++ ++int ++main( int argc, char* argv[] ) ++{ ++#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) ++ // Not needed in Qt6 ++ QApplication::setAttribute( Qt::AA_EnableHighDpiScaling ); ++#endif ++ CalamaresApplication a( argc, argv ); ++ ++ KAboutData aboutData( "calamares", ++ "Calamares", ++ a.applicationVersion(), ++ "The universal system installer", ++ KAboutLicense::GPL_V3, ++ QString(), ++ QString(), ++ "https://calamares.io", ++ "https://github.com/calamares/calamares/issues" ); ++ KAboutData::setApplicationData( aboutData ); ++ a.setApplicationDisplayName( QString() ); // To avoid putting an extra "Calamares/" into the log-file ++ ++#ifdef BUILD_CRASH_REPORTING ++ KCrash::initialize(); ++ // KCrash::setCrashHandler(); ++ KCrash::setDrKonqiEnabled( true ); ++ KCrash::setFlags( KCrash::SaferDialog | KCrash::AlwaysDirectly ); ++#endif ++ ++ std::unique_ptr< KDSingleApplication > possiblyUnique; ++ const bool is_debug = handle_args( a ); ++ if ( !is_debug ) ++ { ++ possiblyUnique = std::make_unique< KDSingleApplication >(); ++ if ( !possiblyUnique->isPrimaryInstance() ) ++ { ++ qCritical() << "Calamares is already running."; ++ return 87; // EUSERS on Linux ++ } ++ } ++ ++ Calamares::Settings::init( is_debug ); ++ if ( !Calamares::Settings::instance() || !Calamares::Settings::instance()->isValid() ) ++ { ++ qCritical() << "Calamares has invalid settings, shutting down."; ++ return 78; // EX_CONFIG on FreeBSD ++ } ++ a.init(); ++ return a.exec(); ++} +diff --git a/src/calamares/progresstree/ProgressTreeDelegate.cpp b/src/calamares/progresstree/ProgressTreeDelegate.cpp +index f0a2470..5b988d6 100644 +--- a/src/calamares/progresstree/ProgressTreeDelegate.cpp ++++ b/src/calamares/progresstree/ProgressTreeDelegate.cpp +@@ -1,210 +1,212 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2017 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#include "ProgressTreeDelegate.h" +- +-#include "Branding.h" +-#include "CalamaresApplication.h" +-#include "CalamaresWindow.h" +-#include "ViewManager.h" +-#include "utils/Gui.h" +-#include "utils/Logger.h" +- +-#include +-#include +-static constexpr int const item_margin = 8; +-static inline int +-item_fontsize() +-{ +- return Calamares::defaultFontSize(); +-} +-static bool contains(const std::vector& vec,const QString& value){ +- for(const QString& v : vec){ +- if(v==value){ +- return true; +- } +- } +- return false; +-} +-static QString getTypeOfStep(const QString& stepString){ +- std::vector baseSetting1 = {"Location","Keyboard"}; +- std::vector userSetting1 = {"Users","Packages"}; +- std::vector installSteps1 = {"Partitions","Summary","Install","Finish"}; +- std::vector baseSetting2 = {"位置","键盘"}; +- std::vector userSetting2 = {"用户","桌面"}; +- std::vector installSteps2 = {"分区","摘要","安装","结束"}; +- std::vector baseSetting3 = {"位置", "鍵盤"}; +- std::vector userSetting3 = {"使用者", "軟體包"}; +- std::vector installSteps3 = {"分割區", "總覽", "安裝", "完成"}; +- // 获取当前系统的语言设置 +- QLocale locale; +- QLocale::Language lang = locale.language(); +- +- // 将语言枚举值转换为字符串 +- QString languageString = QLocale::languageToString(lang); +- QLocale::Country country = locale.country(); +- +- // 将地区枚举值转换为字符串 +- QString countryString = QLocale::countryToString(country); +- if(contains(baseSetting1,stepString)){ +- return "BaseSetting"; +- } +- if(contains(userSetting1,stepString)){ +- return "UserSetting"; +- } +- if(contains(installSteps1,stepString)){ +- return "InstallSetting"; +- } +- if(contains(baseSetting2,stepString) && countryString=="China"){ +- return "基础设置"; +- } +- if(contains(userSetting2,stepString) && countryString=="China"){ +- return "用户设置"; +- } +- if(contains(installSteps2,stepString) && countryString=="China"){ +- return "安装设置"; +- } +- if (contains(baseSetting3, stepString) && countryString=="Taiwan") { +- return "基礎設定"; +- } +- if (contains(userSetting3, stepString) && countryString=="Taiwan"){ +- return "使用者設定"; +- } +- if (contains(installSteps3, stepString) && countryString=="Taiwan") { +- return "安裝設定"; +- } +- return 0; +-} +-static int getTypeOfStep(int val){ +- if(val<=1){ +- return 1; +- } +- else if(val<=3){ +- return 2; +- } +- else if(val<=8){ +- return 3; +- } +- else{ +- return 0; +- } +-} +-static bool isVisable(const QString& stepString){ +- std::vector installSteps = {"鍵盤", "軟體包", "總覽", "安裝", "完成", +- "Keyboard","Packages","Summary","Install","Finish", +- "键盘","桌面","摘要","安装","结束"}; +- return !contains(installSteps, stepString); +-} +-static void +-paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) +-{ +- QRect textRect = option.rect.adjusted( item_margin, item_margin, -item_margin, -item_margin ); +- QFont font = qApp->font(); +- font.setPointSize( item_fontsize() ); +- font.setBold( false ); +- painter->setFont( font ); +- +- int CurrentTypeOfStep = getTypeOfStep(index.data( Calamares::ViewManager::ProgressTreeItemCurrentIndex ).toInt()); +- int TypeOfStep = getTypeOfStep(index.row()); +- if ( CurrentTypeOfStep == TypeOfStep ) +- { +- painter->setPen( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextCurrent ) ); +- QString textHighlight +- = Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackgroundCurrent ); +- if ( textHighlight.isEmpty() ) +- { +- painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().window() ); +- } +- else +- { +- painter->setBrush( QColor( textHighlight ) ); +- } +- } +- +- // Draw the text at least once. If it doesn't fit, then shrink the font +- // being used by 1 pt on each iteration, up to a maximum of maximumShrink +- // times. On each loop, we'll have to blank out the rectangle again, so this +- // is an expensive (in terms of drawing operations) thing to do. +- // +- // (The loop uses <= because the counter is incremented at the start). +- static constexpr int const maximumShrink = 4; +- int shrinkSteps = 0; +- do +- { +- +- shrinkSteps++; +- +- QRectF boundingBox; +- QString text; +- if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"||!isVisable(index.data().toString())){ +- text = ""; +- }else{ +- text = getTypeOfStep(index.data().toString()); +- painter->fillRect( option.rect, painter->brush().color() ); +- } +- painter->drawText( +- textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, text, &boundingBox ); +- +- // The extra check here is to avoid the changing-font-size if we're not going to use +- // it in the next iteration of the loop anyway. +- if ( ( shrinkSteps <= maximumShrink ) && ( boundingBox.width() > textRect.width() ) ) +- { +- font.setPointSize( item_fontsize() ); +- painter->setFont( font ); +- } +- else +- { +- break; // It fits +- } +- } while ( shrinkSteps <= maximumShrink ); +-} +- +-QSize +-ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const +-{ +- if ( !index.isValid() ) +- { +- return option.rect.size(); +- } +- +- QFont font = qApp->font(); +- +- font.setPointSize( item_fontsize() ); +- QFontMetrics fm( font ); +- int height = fm.height(); +- height += 2 * item_margin; +- if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"||!isVisable(index.data().toString())){ +- return QSize( 0, 0 ); +- }else{ +- return QSize( (Calamares::windowMinimumWidth*0.9)/3, height*2 ); +- } +- +-} +- +-void +-ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const +-{ +- QStyleOptionViewItem opt = option; +- +- painter->save(); +- +- initStyleOption( &opt, index ); +- opt.text.clear(); +- +- painter->setBrush( +- QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) ); +- painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) ); +- if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"){ +- }else{ +- paintViewStep( painter, opt, index ); +- } +- +- painter->restore(); +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2017 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#include "ProgressTreeDelegate.h" ++ ++#include "Branding.h" ++#include "CalamaresApplication.h" ++#include "CalamaresWindow.h" ++#include "ViewManager.h" ++#include "utils/Gui.h" ++#include "utils/Logger.h" ++ ++#include ++#include ++static constexpr int const item_margin = 8; ++static inline int ++item_fontsize() ++{ ++ return Calamares::defaultFontSize(); ++} ++static bool contains(const std::vector& vec,const QString& value){ ++ for(const QString& v : vec){ ++ if(v==value){ ++ return true; ++ } ++ } ++ return false; ++} ++static QString getTypeOfStep(const QString& stepString){ ++ std::vector baseSetting1 = {"Location","Keyboard"}; ++ std::vector userSetting1 = {"Users","Packages"}; ++ std::vector installSteps1 = {"Partitions","Summary","Install","Finish"}; ++ std::vector baseSetting2 = {"位置","键盘"}; ++ std::vector userSetting2 = {"用户","桌面"}; ++ std::vector installSteps2 = {"分区","摘要","安装","结束"}; ++ std::vector baseSetting3 = {"位置", "鍵盤"}; ++ std::vector userSetting3 = {"使用者", "軟體包"}; ++ std::vector installSteps3 = {"分割區", "總覽", "安裝", "完成"}; ++ // 获取当前系统的语言设置 ++ QLocale locale; ++ QLocale::Language lang = locale.language(); ++ ++ // 将语言枚举值转换为字符串 ++ QString languageString = QLocale::languageToString(lang); ++ QLocale::Country country = locale.country(); ++ ++ // 将地区枚举值转换为字符串 ++ QString countryString = QLocale::countryToString(country); ++ // 输出当前语言 ++ if(contains(baseSetting1,stepString)){ ++ return "BaseSetting"; ++ } ++ if(contains(userSetting1,stepString)){ ++ return "UserSetting"; ++ } ++ if(contains(installSteps1,stepString)){ ++ return "InstallSetting"; ++ } ++ if(contains(baseSetting2,stepString) && countryString=="China"){ ++ return "基础设置"; ++ } ++ if(contains(userSetting2,stepString) && countryString=="China"){ ++ return "用户设置"; ++ } ++ if(contains(installSteps2,stepString) && countryString=="China"){ ++ return "安装设置"; ++ } ++ if (contains(baseSetting3, stepString) && countryString=="Taiwan") { ++ return "基礎設定"; ++ } ++ if (contains(userSetting3, stepString) && countryString=="Taiwan"){ ++ return "使用者設定"; ++ } ++ if (contains(installSteps3, stepString) && countryString=="Taiwan") { ++ return "安裝設定"; ++ } ++ return 0; ++} ++static int getTypeOfStep(int val){ ++ if(val<=1){ ++ return 1; ++ } ++ else if(val<=3){ ++ return 2; ++ } ++ else if(val<=8){ ++ return 3; ++ } ++ else{ ++ return 0; ++ } ++} ++static bool isVisable(const QString& stepString){ ++ std::vector installSteps = {"鍵盤", "軟體包", "總覽", "安裝", "完成", ++ "Keyboard","Packages","Summary","Install","Finish", ++ "键盘","桌面","摘要","安装","结束"}; ++ return !contains(installSteps, stepString); ++} ++static void ++paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) ++{ ++ QRect textRect = option.rect.adjusted( item_margin, item_margin, -item_margin, -item_margin ); ++ QFont font = qApp->font(); ++ font.setPointSize( item_fontsize() ); ++ font.setBold( false ); ++ painter->setFont( font ); ++ ++ int CurrentTypeOfStep = getTypeOfStep(index.data( Calamares::ViewManager::ProgressTreeItemCurrentIndex ).toInt()); ++ int TypeOfStep = getTypeOfStep(index.row()); ++ if ( CurrentTypeOfStep == TypeOfStep ) ++ { ++ painter->setPen( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextCurrent ) ); ++ QString textHighlight ++ = Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackgroundCurrent ); ++ if ( textHighlight.isEmpty() ) ++ { ++ painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().window() ); ++ } ++ else ++ { ++ painter->setBrush( QColor( textHighlight ) ); ++ } ++ } ++ ++ // Draw the text at least once. If it doesn't fit, then shrink the font ++ // being used by 1 pt on each iteration, up to a maximum of maximumShrink ++ // times. On each loop, we'll have to blank out the rectangle again, so this ++ // is an expensive (in terms of drawing operations) thing to do. ++ // ++ // (The loop uses <= because the counter is incremented at the start). ++ static constexpr int const maximumShrink = 4; ++ int shrinkSteps = 0; ++ do ++ { ++ ++ shrinkSteps++; ++ ++ QRectF boundingBox; ++ QString text; ++ if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"||!isVisable(index.data().toString())){ ++ text = ""; ++ }else{ ++ text = getTypeOfStep(index.data().toString()); ++ painter->fillRect( option.rect, painter->brush().color() ); ++ } ++ painter->drawText( ++ textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, text, &boundingBox ); ++ ++ // The extra check here is to avoid the changing-font-size if we're not going to use ++ // it in the next iteration of the loop anyway. ++ if ( ( shrinkSteps <= maximumShrink ) && ( boundingBox.width() > textRect.width() ) ) ++ { ++ font.setPointSize( item_fontsize() ); ++ painter->setFont( font ); ++ } ++ else ++ { ++ break; // It fits ++ } ++ } while ( shrinkSteps <= maximumShrink ); ++} ++ ++QSize ++ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const ++{ ++ if ( !index.isValid() ) ++ { ++ return option.rect.size(); ++ } ++ ++ QFont font = qApp->font(); ++ ++ font.setPointSize( item_fontsize() ); ++ QFontMetrics fm( font ); ++ int height = fm.height(); ++ height += 2 * item_margin; ++ if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"||!isVisable(index.data().toString())){ ++ return QSize( 0, 0 ); ++ }else{ ++ return QSize( (Calamares::windowMinimumWidth*0.9)/3, height*2 ); ++ } ++ ++} ++ ++void ++ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const ++{ ++ QStyleOptionViewItem opt = option; ++ ++ painter->save(); ++ ++ initStyleOption( &opt, index ); ++ opt.text.clear(); ++ ++ painter->setBrush( ++ QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) ); ++ painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) ); ++ if(index.data().toString()=="欢迎" || index.data().toString()=="Welcome"){ ++ ++ }else{ ++ paintViewStep( painter, opt, index ); ++ } ++ ++ painter->restore(); ++} +diff --git a/src/calamares/progresstree/ProgressTreeDelegate.h b/src/calamares/progresstree/ProgressTreeDelegate.h +index d5a5abc..af4fef9 100644 +--- a/src/calamares/progresstree/ProgressTreeDelegate.h ++++ b/src/calamares/progresstree/ProgressTreeDelegate.h +@@ -1,31 +1,31 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2019 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#ifndef PROGRESSTREEDELEGATE_H +-#define PROGRESSTREEDELEGATE_H +- +-#include +- +-/** +- * @brief The ProgressTreeDelegate class customizes the look and feel of the +- * ProgressTreeView elements. +- * @see ProgressTreeView +- */ +-class ProgressTreeDelegate : public QStyledItemDelegate +-{ +-public: +- using QStyledItemDelegate::QStyledItemDelegate; +- +-protected: +- QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override; +- void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; +-}; +- +-#endif // PROGRESSTREEDELEGATE_H ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2019 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#ifndef PROGRESSTREEDELEGATE_H ++#define PROGRESSTREEDELEGATE_H ++ ++#include ++ ++/** ++ * @brief The ProgressTreeDelegate class customizes the look and feel of the ++ * ProgressTreeView elements. ++ * @see ProgressTreeView ++ */ ++class ProgressTreeDelegate : public QStyledItemDelegate ++{ ++public: ++ using QStyledItemDelegate::QStyledItemDelegate; ++ ++protected: ++ QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override; ++ void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; ++}; ++ ++#endif // PROGRESSTREEDELEGATE_H +diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp +index cdbafeb..5ea761c 100644 +--- a/src/calamares/progresstree/ProgressTreeView.cpp ++++ b/src/calamares/progresstree/ProgressTreeView.cpp +@@ -1,79 +1,75 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2014 Teo Mrnjavac +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#include "ProgressTreeView.h" +- +-#include "ProgressTreeDelegate.h" +- +-#include "Branding.h" +-#include "ViewManager.h" +-#include "utils/Logger.h" +- +-ProgressTreeView::ProgressTreeView( QWidget* parent ) +- : QListView( parent ) +-{ +- this->setObjectName( "sidebarMenuApp" ); +- setFrameShape( QFrame::NoFrame ); +- setContentsMargins( 0, 0, 0, 0 ); +- +- setFlow(QListView::LeftToRight);// +- setSelectionMode( QAbstractItemView::NoSelection ); +- setDragDropMode( QAbstractItemView::NoDragDrop ); +- setAcceptDrops( false ); +-// setVisible( false); +- +- setItemDelegate( new ProgressTreeDelegate( this ) ); +- +- QPalette plt = palette(); +- plt.setColor( QPalette::Base, +- Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ); +- setPalette( plt ); +-// connect(parent, SIGNAL(currentStepChanged(int)), this, SLOT(updateVisibility(int))); +- connect( Calamares::ViewManager::instance(), +- &Calamares::ViewManager::currentStepChanged, +- this, +- &ProgressTreeView::updateVisibility, +- Qt::UniqueConnection ); +-// connect(viewManager, &ViewManager::currentStepChanged, this, &ProgressTreeView::updateVisibility); +-} +- +- +-ProgressTreeView::~ProgressTreeView() {} +- +- +- +-void +-ProgressTreeView::setModel( QAbstractItemModel* model ) +-{ +- if ( ProgressTreeView::model() ) +- { +- return; +- } +- +- QListView::setModel( model ); +- +- connect( Calamares::ViewManager::instance(), +- &Calamares::ViewManager::currentStepChanged, +- this, +- &ProgressTreeView::update, +- Qt::UniqueConnection ); +-} +- +-void +-ProgressTreeView::update() +-{ +- viewport()->update(); +-} +- +-void +-ProgressTreeView::updateVisibility(int currentStep) +-{ +- // 在第一个步骤隐藏,其他步骤显示 +- this->setVisible(currentStep > 0); +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2014 Teo Mrnjavac ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#include "ProgressTreeView.h" ++ ++#include "ProgressTreeDelegate.h" ++ ++#include "Branding.h" ++#include "ViewManager.h" ++#include "utils/Logger.h" ++ ++ProgressTreeView::ProgressTreeView( QWidget* parent ) ++ : QListView( parent ) ++{ ++ this->setObjectName( "sidebarMenuApp" ); ++ setFrameShape( QFrame::NoFrame ); ++ setContentsMargins( 0, 0, 0, 0 ); ++ ++ setFlow(QListView::LeftToRight); ++ setSelectionMode( QAbstractItemView::NoSelection ); ++ setDragDropMode( QAbstractItemView::NoDragDrop ); ++ setAcceptDrops( false ); ++ ++ setItemDelegate( new ProgressTreeDelegate( this ) ); ++ ++ QPalette plt = palette(); ++ plt.setColor( QPalette::Base, ++ Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ); ++ setPalette( plt ); ++ connect( Calamares::ViewManager::instance(), ++ &Calamares::ViewManager::currentStepChanged, ++ this, ++ &ProgressTreeView::updateVisibility, ++ Qt::UniqueConnection ); ++} ++ ++ ++ProgressTreeView::~ProgressTreeView() {} ++ ++ ++ ++void ++ProgressTreeView::setModel( QAbstractItemModel* model ) ++{ ++ if ( ProgressTreeView::model() ) ++ { ++ return; ++ } ++ ++ QListView::setModel( model ); ++ ++ connect( Calamares::ViewManager::instance(), ++ &Calamares::ViewManager::currentStepChanged, ++ this, ++ &ProgressTreeView::update, ++ Qt::UniqueConnection ); ++} ++ ++void ++ProgressTreeView::update() ++{ ++ viewport()->update(); ++} ++ ++void ++ProgressTreeView::updateVisibility(int currentStep) ++{ ++ this->setVisible(currentStep > 0); ++} +diff --git a/src/calamares/progresstree/ProgressTreeView.h b/src/calamares/progresstree/ProgressTreeView.h +index 11491e4..b02b9ce 100644 +--- a/src/calamares/progresstree/ProgressTreeView.h ++++ b/src/calamares/progresstree/ProgressTreeView.h +@@ -1,41 +1,41 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2014 Teo Mrnjavac +- * SPDX-FileCopyrightText: 2017 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-#ifndef PROGRESSTREEVIEW_H +-#define PROGRESSTREEVIEW_H +- +-#include +-#include "utils/Logger.h" +- +-/** +- * @brief Displays progress through the list of (visible) steps +- * +- * The ProgressTreeView class is a modified QListView which displays the +- * available view steps and the user's progress through them. +- * Since Calamares doesn't support "sub steps", it isn't really a tree. +- */ +-class ProgressTreeView : public QListView +-{ +- Q_OBJECT +-public: +- explicit ProgressTreeView( QWidget* parent = nullptr ); +- ~ProgressTreeView() override; +- +- /** +- * @brief setModel assigns a model to this view. +- */ +- void setModel( QAbstractItemModel* model ) override; +- +-public Q_SLOTS: +- void update(); +- void updateVisibility(int currentStep); +-}; +- +-#endif // PROGRESSTREEVIEW_H ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2014 Teo Mrnjavac ++ * SPDX-FileCopyrightText: 2017 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++#ifndef PROGRESSTREEVIEW_H ++#define PROGRESSTREEVIEW_H ++ ++#include ++#include "utils/Logger.h" ++ ++/** ++ * @brief Displays progress through the list of (visible) steps ++ * ++ * The ProgressTreeView class is a modified QListView which displays the ++ * available view steps and the user's progress through them. ++ * Since Calamares doesn't support "sub steps", it isn't really a tree. ++ */ ++class ProgressTreeView : public QListView ++{ ++ Q_OBJECT ++public: ++ explicit ProgressTreeView( QWidget* parent = nullptr ); ++ ~ProgressTreeView() override; ++ ++ /** ++ * @brief setModel assigns a model to this view. ++ */ ++ void setModel( QAbstractItemModel* model ) override; ++ ++public Q_SLOTS: ++ void update(); ++ void updateVisibility(int currentStep); ++}; ++ ++#endif // PROGRESSTREEVIEW_H +diff --git a/src/calamares/test_conf.cpp b/src/calamares/test_conf.cpp +index 73b19aa..81f4e36 100644 +--- a/src/calamares/test_conf.cpp ++++ b/src/calamares/test_conf.cpp +@@ -1,109 +1,109 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-/** +- * This is a test-application that just checks the YAML config-file +- * shipped with each module for correctness -- well, for parseability. +- */ +- +-#include "utils/Yaml.h" +- +-#include +-#include +- +-#include +- +-#include +-#include +- +-using std::cerr; +- +-static const char usage[] = "Usage: test_conf [-v] [-b] ...\n"; +- +-int +-main( int argc, char** argv ) +-{ +- bool verbose = false; +- bool bytes = false; +- +- int opt; +- while ( ( opt = getopt( argc, argv, "vb" ) ) != -1 ) +- { +- switch ( opt ) +- { +- case 'v': +- verbose = true; +- break; +- case 'b': +- bytes = true; +- break; +- default: /* '?' */ +- cerr << usage; +- return 1; +- } +- } +- +- if ( optind >= argc ) +- { +- cerr << usage; +- return 1; +- } +- +- const char* filename = argv[ optind ]; +- try +- { +- YAML::Node doc; +- if ( bytes ) +- { +- QFile f( filename ); +- if ( f.open( QFile::ReadOnly | QFile::Text ) ) +- { +- doc = YAML::Load( f.readAll().constData() ); +- } +- } +- else +- { +- doc = YAML::LoadFile( filename ); +- } +- +- if ( doc.IsNull() ) +- { +- // Special case: empty config files are valid, +- // but aren't a map. For the example configs, +- // this is still an error. +- cerr << "WARNING:" << filename << '\n'; +- cerr << "WARNING: empty YAML\n"; +- return 1; +- } +- +- if ( !doc.IsMap() ) +- { +- cerr << "WARNING:" << filename << '\n'; +- cerr << "WARNING: not-a-YAML-map (type=" << doc.Type() << ")\n"; +- return 1; +- } +- +- if ( verbose ) +- { +- cerr << "Keys:\n"; +- for ( auto i = doc.begin(); i != doc.end(); ++i ) +- { +- cerr << i->first.as< std::string >() << '\n'; +- } +- } +- } +- catch ( YAML::Exception& e ) +- { +- cerr << "WARNING:" << filename << '\n'; +- cerr << "WARNING: YAML parser error " << e.what() << '\n'; +- return 1; +- } +- +- return 0; +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++/** ++ * This is a test-application that just checks the YAML config-file ++ * shipped with each module for correctness -- well, for parseability. ++ */ ++ ++#include "utils/Yaml.h" ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++using std::cerr; ++ ++static const char usage[] = "Usage: test_conf [-v] [-b] ...\n"; ++ ++int ++main( int argc, char** argv ) ++{ ++ bool verbose = false; ++ bool bytes = false; ++ ++ int opt; ++ while ( ( opt = getopt( argc, argv, "vb" ) ) != -1 ) ++ { ++ switch ( opt ) ++ { ++ case 'v': ++ verbose = true; ++ break; ++ case 'b': ++ bytes = true; ++ break; ++ default: /* '?' */ ++ cerr << usage; ++ return 1; ++ } ++ } ++ ++ if ( optind >= argc ) ++ { ++ cerr << usage; ++ return 1; ++ } ++ ++ const char* filename = argv[ optind ]; ++ try ++ { ++ YAML::Node doc; ++ if ( bytes ) ++ { ++ QFile f( filename ); ++ if ( f.open( QFile::ReadOnly | QFile::Text ) ) ++ { ++ doc = YAML::Load( f.readAll().constData() ); ++ } ++ } ++ else ++ { ++ doc = YAML::LoadFile( filename ); ++ } ++ ++ if ( doc.IsNull() ) ++ { ++ // Special case: empty config files are valid, ++ // but aren't a map. For the example configs, ++ // this is still an error. ++ cerr << "WARNING:" << filename << '\n'; ++ cerr << "WARNING: empty YAML\n"; ++ return 1; ++ } ++ ++ if ( !doc.IsMap() ) ++ { ++ cerr << "WARNING:" << filename << '\n'; ++ cerr << "WARNING: not-a-YAML-map (type=" << doc.Type() << ")\n"; ++ return 1; ++ } ++ ++ if ( verbose ) ++ { ++ cerr << "Keys:\n"; ++ for ( auto i = doc.begin(); i != doc.end(); ++i ) ++ { ++ cerr << i->first.as< std::string >() << '\n'; ++ } ++ } ++ } ++ catch ( YAML::Exception& e ) ++ { ++ cerr << "WARNING:" << filename << '\n'; ++ cerr << "WARNING: YAML parser error " << e.what() << '\n'; ++ return 1; ++ } ++ ++ return 0; ++} +diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp +index c25bc51..7ab15c9 100644 +--- a/src/calamares/testmain.cpp ++++ b/src/calamares/testmain.cpp +@@ -1,572 +1,572 @@ +-/* === This file is part of Calamares - === +- * +- * SPDX-FileCopyrightText: 2018 Adriaan de Groot +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- * Calamares is Free Software: see the License-Identifier above. +- * +- */ +- +-/* +- * This executable loads and runs a Calamares Python module +- * within a C++ application, in order to test the different +- * bindings. +- */ +- +-#include "Branding.h" +-#include "CppJob.h" +-#include "GlobalStorage.h" +-#include "Job.h" +-#include "JobQueue.h" +-#include "Settings.h" +-#include "ViewManager.h" +-#include "modulesystem/Module.h" +-#include "modulesystem/ModuleManager.h" +-#include "modulesystem/ViewModule.h" +-#include "utils/Logger.h" +-#include "utils/Retranslator.h" +-#include "utils/System.h" +-#include "utils/Yaml.h" +-#include "viewpages/ExecutionViewStep.h" +- +-// Optional features of Calamares +-// - Python support with pybind11 +-// - Python support with older Boost implementation +-// - QML support +-#ifdef WITH_PYTHON +-#ifdef WITH_PYBIND11 +-#include "python/PythonJob.h" +-#else +-#include "PythonJob.h" +-#endif +-#endif +-#ifdef WITH_QML +-#include "utils/Qml.h" +-#endif +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-struct ModuleConfig +-{ +- QString moduleName() const { return m_module; } +- QString configFile() const { return m_jobConfig; } +- QString language() const { return m_language; } +- QString globalConfigFile() const { return m_globalConfig; } +- +- QString m_module; +- QString m_jobConfig; +- QString m_globalConfig; +- QString m_settingsConfig; +- QString m_language; +- QString m_branding; +- bool m_ui; +- bool m_pythonInjection; +-}; +- +-static ModuleConfig +-handle_args( QCoreApplication& a ) +-{ +- QCommandLineOption debugLevelOption( +- QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8), ignored.", "level" ); +- QCommandLineOption settingsOption( { QStringLiteral( "S" ), QStringLiteral( "settings" ) }, +- QStringLiteral( "Settings.conf document" ), +- QString( "settings.conf" ) ); +- QCommandLineOption globalOption( { QStringLiteral( "g" ), QStringLiteral( "global" ) }, +- QStringLiteral( "Global storage settings document" ), +- "global.yaml" ); +- QCommandLineOption jobOption( +- { QStringLiteral( "j" ), QStringLiteral( "job" ) }, QStringLiteral( "Job settings document" ), "job.yaml" ); +- QCommandLineOption langOption( { QStringLiteral( "l" ), QStringLiteral( "language" ) }, +- QStringLiteral( "Language (global)" ), +- "languagecode" ); +- QCommandLineOption brandOption( { QStringLiteral( "b" ), QStringLiteral( "branding" ) }, +- QStringLiteral( "Branding directory" ), +- "path/to/branding.desc", +- "src/branding/default/branding.desc" ); +- QCommandLineOption uiOption( { QStringLiteral( "U" ), QStringLiteral( "ui" ) }, QStringLiteral( "Enable UI" ) ); +- QCommandLineOption slideshowOption( { QStringLiteral( "s" ), QStringLiteral( "slideshow" ) }, +- QStringLiteral( "Run slideshow module" ) ); +- QCommandLineParser parser; +- parser.setApplicationDescription( "Calamares module tester" ); +- parser.addHelpOption(); +- parser.addVersionOption(); +- +- parser.addOption( debugLevelOption ); +- parser.addOption( settingsOption ); +- parser.addOption( globalOption ); +- parser.addOption( jobOption ); +- parser.addOption( langOption ); +- parser.addOption( brandOption ); +- parser.addOption( uiOption ); +- parser.addOption( slideshowOption ); +-#ifdef WITH_PYTHON +- QCommandLineOption pythonOption( { QStringLiteral( "P" ), QStringLiteral( "no-injected-python" ) }, +- QStringLiteral( "Do not disable potentially-harmful Python commands" ) ); +- parser.addOption( pythonOption ); +-#endif +- +- parser.addPositionalArgument( "module", "Path or name of module to run." ); +- parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" ); +- +- parser.process( a ); +- +- const QStringList args = parser.positionalArguments(); +- if ( args.isEmpty() && !parser.isSet( slideshowOption ) ) +- { +- cError() << "Missing path.\n"; +- parser.showHelp(); +- } +- else if ( args.size() > 2 ) +- { +- cError() << "More than one path.\n"; +- parser.showHelp(); +- } +- else +- { +- QString jobSettings( parser.value( jobOption ) ); +- if ( jobSettings.isEmpty() && ( args.size() == 2 ) ) +- { +- jobSettings = args.at( 1 ); +- } +- +- bool pythonInjection = true; +-#ifdef WITH_PYTHON +- if ( parser.isSet( pythonOption ) ) +- { +- pythonInjection = false; +- } +-#endif +- return ModuleConfig { parser.isSet( slideshowOption ) ? QStringLiteral( "-" ) : args.first(), +- jobSettings, +- parser.value( globalOption ), +- parser.value( settingsOption ), +- parser.value( langOption ), +- parser.value( brandOption ), +- parser.isSet( slideshowOption ) || parser.isSet( uiOption ), +- pythonInjection }; +- } +-} +- +-/** @brief Bogus Job for --slideshow option +- * +- * Generally one would use DummyCppJob for this kind of dummy +- * job, but that class lives in a module so isn't available +- * in this test application. +- * +- * This bogus job just sleeps for 3. +- */ +-class ExecViewJob : public Calamares::CppJob +-{ +-public: +- explicit ExecViewJob( const QString& name, unsigned long t = 3 ) +- : m_name( name ) +- , m_delay( t ) +- { +- } +- ~ExecViewJob() override; +- +- QString prettyName() const override { return m_name; } +- +- Calamares::JobResult exec() override +- { +- QThread::sleep( m_delay ); +- return Calamares::JobResult::ok(); +- } +- +- void setConfigurationMap( const QVariantMap& ) override {} +- +-private: +- QString m_name; +- unsigned long m_delay; +-}; +- +-ExecViewJob::~ExecViewJob() {} +- +-/** @brief Bogus module for --slideshow option +- * +- * Normally the slideshow -- displayed by ExecutionViewStep -- is not +- * associated with any particular module in the Calamares configuration. +- * It is added internally by the module manager. For the module-loader +- * testing application, we need something that pretends to be the +- * module for the ExecutionViewStep. +- */ +-class ExecViewModule : public Calamares::Module +-{ +-public: +- ExecViewModule(); +- ~ExecViewModule() override; +- +- void loadSelf() override; +- +- virtual Calamares::ModuleSystem::Type type() const override; +- virtual Calamares::ModuleSystem::Interface interface() const override; +- +- virtual Calamares::JobList jobs() const override; +- +-protected: +- void initFrom( const Calamares::ModuleSystem::Descriptor& ) override; +-}; +- +-ExecViewModule::ExecViewModule() +- : Calamares::Module() +-{ +- // Normally the module-loader gives the module an instance key +- // (out of the settings file, or the descriptor of the module). +- // We don't have one, so build one -- this gives us "execView@execView". +- QVariantMap m; +- const QString execView = QStringLiteral( "execView" ); +- m.insert( "name", execView ); +- Calamares::Module::initFrom( Calamares::ModuleSystem::Descriptor::fromDescriptorData( m, execView ), execView ); +-} +- +-ExecViewModule::~ExecViewModule() {} +- +-void +-ExecViewModule::initFrom( const Calamares::ModuleSystem::Descriptor& ) +-{ +-} +- +-void +-ExecViewModule::loadSelf() +-{ +- auto* viewStep = new Calamares::ExecutionViewStep(); +- viewStep->setModuleInstanceKey( instanceKey() ); +- viewStep->setConfigurationMap( m_configurationMap ); +- viewStep->appendJobModuleInstanceKey( instanceKey() ); +- Calamares::ViewManager::instance()->addViewStep( viewStep ); +- m_loaded = true; +-} +- +-Calamares::Module::Type +-ExecViewModule::type() const +-{ +- return Module::Type::View; +-} +- +-Calamares::Module::Interface +-ExecViewModule::interface() const +-{ +- return Module::Interface::QtPlugin; +-} +- +-Calamares::JobList +-ExecViewModule::jobs() const +-{ +- Calamares::JobList l; +- const auto* gs = Calamares::JobQueue::instance()->globalStorage(); +- if ( gs && gs->contains( "jobs" ) ) +- { +- QVariantList joblist = gs->value( "jobs" ).toList(); +- for ( const auto& jd : joblist ) +- { +- QVariantMap jobdescription = jd.toMap(); +- if ( jobdescription.contains( "name" ) && jobdescription.contains( "delay" ) ) +- { +- l.append( Calamares::job_ptr( new ExecViewJob( jobdescription.value( "name" ).toString(), +- jobdescription.value( "delay" ).toULongLong() ) ) ); +- } +- } +- } +- if ( l.count() > 0 ) +- { +- return l; +- } +- +- l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "step 1" ) ) ) ); +- l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "step two" ) ) ) ); +- l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "locking mutexes" ), 20 ) ) ); +- l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "unlocking mutexes" ), 1 ) ) ); +- for ( const QString& s : QStringList { "Harder", "Better", "Faster", "Stronger" } ) +- { +- l.append( Calamares::job_ptr( new ExecViewJob( s, 0 ) ) ); +- } +- l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "cleaning up" ), 20 ) ) ); +- return l; +-} +- +-static Calamares::Module* +-load_module( const ModuleConfig& moduleConfig ) +-{ +- QString moduleName = moduleConfig.moduleName(); +- if ( moduleName == "-" ) +- { +- return new ExecViewModule; +- } +- +- QFileInfo fi; // This is kept around to hold the path of the module descriptor +- +- bool ok = false; +- QVariantMap descriptor; +- +- QStringList moduleDirectories { "./", "src/modules/", "modules/", CMAKE_INSTALL_FULL_LIBDIR "/calamares/modules/" }; +- for ( const QString& prefix : qAsConst( moduleDirectories ) ) +- { +- // Could be a complete path, eg. src/modules/dummycpp/module.desc +- fi = QFileInfo( prefix + moduleName ); +- if ( fi.exists() && fi.isFile() ) +- { +- descriptor = Calamares::YAML::load( fi, &ok ); +- } +- if ( ok ) +- { +- break; +- } +- +- // Could be a path without module.desc +- fi = QFileInfo( prefix + moduleName ); +- if ( fi.exists() && fi.isDir() ) +- { +- fi = QFileInfo( prefix + moduleName + "/module.desc" ); +- if ( fi.exists() && fi.isFile() ) +- { +- descriptor = Calamares::YAML::load( fi, &ok ); +- } +- if ( ok ) +- { +- break; +- } +- else +- { +- if ( !fi.exists() ) +- { +- cDebug() << "Expected a descriptor file" << fi.path(); +- } +- else +- { +- cDebug() << "Read descriptor" << fi.path() << "and it was empty."; +- } +- } +- } +- } +- +- if ( !ok ) +- { +- cWarning() << "No suitable module descriptor found in" << Logger::DebugList( moduleDirectories ); +- return nullptr; +- } +- +- QString name = descriptor.value( "name" ).toString(); +- if ( name.isEmpty() ) +- { +- cWarning() << "No name found in module descriptor" << fi.absoluteFilePath(); +- return nullptr; +- } +- +- QString moduleDirectory = fi.absolutePath(); +- QString configFile( moduleConfig.configFile().isEmpty() ? moduleDirectory + '/' + name + ".conf" +- : moduleConfig.configFile() ); +- +- cDebug() << Logger::SubEntry << "Module" << moduleName << "job-configuration:" << configFile; +- +- Calamares::Module* module = Calamares::moduleFromDescriptor( +- Calamares::ModuleSystem::Descriptor::fromDescriptorData( descriptor, fi.absoluteFilePath() ), +- name, +- configFile, +- moduleDirectory ); +- +- return module; +-} +- +-static bool +-is_ui_option( const char* s ) +-{ +- return !qstrcmp( s, "--ui" ) || !qstrcmp( s, "-U" ); +-} +- +-static bool +-is_slideshow_option( const char* s ) +-{ +- return !qstrcmp( s, "--slideshow" ) || !qstrcmp( s, "-s" ); +-} +- +-/** @brief Create the right kind of QApplication +- * +- * Does primitive parsing of argv[] to find the --ui option and returns +- * a UI-enabled application if it does. +- * +- * @p argc must be a reference (to main's argc) because the QCoreApplication +- * constructors take a reference as well, and that would otherwise be a +- * reference to a temporary. +- */ +-QCoreApplication* +-createApplication( int& argc, char* argv[] ) +-{ +- for ( int i = 1; i < argc; ++i ) +- { +- if ( is_slideshow_option( argv[ i ] ) || is_ui_option( argv[ i ] ) ) +- { +- auto* aw = new QApplication( argc, argv ); +- aw->setQuitOnLastWindowClosed( true ); +- return aw; +- } +- } +- return new QCoreApplication( argc, argv ); +-} +- +-#ifdef WITH_PYTHON +-static const char pythonPreScript[] = R"%( +-# This is Python code executed by Python modules *before* the +-# script file (e.g. main.py) is executed. +-# +-# Calls to suprocess methods that execute something are +-# suppressed and logged -- scripts should really be using libcalamares +-# methods instead. +-_calamares_subprocess = __import__("subprocess", globals(), locals(), [], 0) +-import sys +-import libcalamares +-class fake_subprocess(object): +- PIPE = object() +- STDOUT = object() +- STDERR = object() +- class CompletedProcess(object): +- returncode = 0 +- stdout = "" +- stderr = "" +- @staticmethod +- def call(*args, **kwargs): +- libcalamares.utils.debug("subprocess.call(%r,%r) X ignored" % (args, kwargs)) +- return 0 +- @staticmethod +- def check_call(*args, **kwargs): +- libcalamares.utils.debug("subprocess.check_call(%r,%r) X ignored" % (args, kwargs)) +- return 0 +- # This is a 3.5-and-later method, is supposed to return a CompletedProcess +- @staticmethod +- def run(*args, **kwargs): +- libcalamares.utils.debug("subprocess.run(%r,%r) X ignored" % (args, kwargs)) +- return fake_subprocess.CompletedProcess() +-for attr in ("CalledProcessError",): +- setattr(fake_subprocess,attr,getattr(_calamares_subprocess,attr)) +-sys.modules["subprocess"] = fake_subprocess +-libcalamares.utils.debug('pre-script for testing purposes injected') +- +-)%"; +-#endif +- +-int +-main( int argc, char* argv[] ) +-{ +- QCoreApplication* application = createApplication( argc, argv ); +- +- Logger::setupLogLevel( Logger::LOGVERBOSE ); +- +- ModuleConfig module = handle_args( *application ); +- if ( module.moduleName().isEmpty() ) +- { +- return 1; +- } +- +- std::unique_ptr< Calamares::Settings > settings_p( Calamares::Settings::init( module.m_settingsConfig ) ); +- std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); +- std::unique_ptr< Calamares::System > system_p( new Calamares::System( settings_p->doChroot() ) ); +- +- QMainWindow* mainWindow = nullptr; +- +- auto* gs = jobqueue_p->globalStorage(); +- if ( !module.globalConfigFile().isEmpty() ) +- { +- gs->loadYaml( module.globalConfigFile() ); +- } +- if ( !module.language().isEmpty() ) +- { +- QVariantMap vm; +- vm.insert( "LANG", module.language() ); +- gs->insert( "localeConf", vm ); +- } +- +-#ifdef WITH_PYTHON +- if ( module.m_pythonInjection ) +- { +-#ifdef WITH_PYBIND11 +- Calamares::Python::Job::setInjectedPreScript( pythonPreScript ); +-#else +- // Old Boost approach +- Calamares::PythonJob::setInjectedPreScript( pythonPreScript ); +-#endif +- } +-#endif +-#ifdef WITH_QML +- Calamares::initQmlModulesDir(); // don't care if failed +-#endif +- +- cDebug() << "Calamares module-loader testing" << module.moduleName(); +- Calamares::Module* m = load_module( module ); +- if ( !m ) +- { +- cError() << "Could not load module" << module.moduleName(); +- return 1; +- } +- +- cDebug() << Logger::SubEntry << "got" << m->name() << m->typeString() << m->interfaceString(); +- if ( m->type() == Calamares::Module::Type::View ) +- { +- // If we forgot the --ui, any ViewModule will core dump as it +- // tries to create the widget **which won't be used anyway**. +- // +- // To avoid that crash, re-create the QApplication, now with GUI +- if ( !qobject_cast< QApplication* >( application ) ) +- { +- auto* replace_app = new QApplication( argc, argv ); +- replace_app->setQuitOnLastWindowClosed( true ); +- application = replace_app; +- } +- mainWindow = module.m_ui ? new QMainWindow() : nullptr; +- if ( mainWindow ) +- { +- mainWindow->installEventFilter( Calamares::Retranslator::instance() ); +- } +- +- (void)new Calamares::Branding( module.m_branding ); +- auto* modulemanager = new Calamares::ModuleManager( QStringList(), nullptr ); +- (void)Calamares::ViewManager::instance( mainWindow ); +- modulemanager->addModule( m ); +- } +- +- if ( !m->isLoaded() ) +- { +- m->loadSelf(); +- } +- +- if ( !m->isLoaded() ) +- { +- cError() << "Module" << module.moduleName() << "could not be loaded."; +- return 1; +- } +- +- if ( mainWindow ) +- { +- auto* vm = Calamares::ViewManager::instance(); +- vm->onInitComplete(); +- QWidget* w = vm->currentStep()->widget(); +- w->setParent( mainWindow ); +- mainWindow->setCentralWidget( w ); +- w->show(); +- mainWindow->show(); +- return application->exec(); +- } +- +- using TR = Logger::DebugRow< const char*, const QString >; +- +- cDebug() << Logger::SubEntry << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() ) +- << TR( "interface", m->interfaceString() ); +- +- Calamares::JobQueue::instance()->enqueue( 100, m->jobs() ); +- +- QObject::connect( Calamares::JobQueue::instance(), +- &Calamares::JobQueue::finished, +- [ application ]() +- { QTimer::singleShot( std::chrono::seconds( 3 ), application, &QApplication::quit ); } ); +- QTimer::singleShot( 0, []() { Calamares::JobQueue::instance()->start(); } ); +- +- return application->exec(); +-} ++/* === This file is part of Calamares - === ++ * ++ * SPDX-FileCopyrightText: 2018 Adriaan de Groot ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ * ++ * Calamares is Free Software: see the License-Identifier above. ++ * ++ */ ++ ++/* ++ * This executable loads and runs a Calamares Python module ++ * within a C++ application, in order to test the different ++ * bindings. ++ */ ++ ++#include "Branding.h" ++#include "CppJob.h" ++#include "GlobalStorage.h" ++#include "Job.h" ++#include "JobQueue.h" ++#include "Settings.h" ++#include "ViewManager.h" ++#include "modulesystem/Module.h" ++#include "modulesystem/ModuleManager.h" ++#include "modulesystem/ViewModule.h" ++#include "utils/Logger.h" ++#include "utils/Retranslator.h" ++#include "utils/System.h" ++#include "utils/Yaml.h" ++#include "viewpages/ExecutionViewStep.h" ++ ++// Optional features of Calamares ++// - Python support with pybind11 ++// - Python support with older Boost implementation ++// - QML support ++#ifdef WITH_PYTHON ++#ifdef WITH_PYBIND11 ++#include "python/PythonJob.h" ++#else ++#include "PythonJob.h" ++#endif ++#endif ++#ifdef WITH_QML ++#include "utils/Qml.h" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++struct ModuleConfig ++{ ++ QString moduleName() const { return m_module; } ++ QString configFile() const { return m_jobConfig; } ++ QString language() const { return m_language; } ++ QString globalConfigFile() const { return m_globalConfig; } ++ ++ QString m_module; ++ QString m_jobConfig; ++ QString m_globalConfig; ++ QString m_settingsConfig; ++ QString m_language; ++ QString m_branding; ++ bool m_ui; ++ bool m_pythonInjection; ++}; ++ ++static ModuleConfig ++handle_args( QCoreApplication& a ) ++{ ++ QCommandLineOption debugLevelOption( ++ QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8), ignored.", "level" ); ++ QCommandLineOption settingsOption( { QStringLiteral( "S" ), QStringLiteral( "settings" ) }, ++ QStringLiteral( "Settings.conf document" ), ++ QString( "settings.conf" ) ); ++ QCommandLineOption globalOption( { QStringLiteral( "g" ), QStringLiteral( "global" ) }, ++ QStringLiteral( "Global storage settings document" ), ++ "global.yaml" ); ++ QCommandLineOption jobOption( ++ { QStringLiteral( "j" ), QStringLiteral( "job" ) }, QStringLiteral( "Job settings document" ), "job.yaml" ); ++ QCommandLineOption langOption( { QStringLiteral( "l" ), QStringLiteral( "language" ) }, ++ QStringLiteral( "Language (global)" ), ++ "languagecode" ); ++ QCommandLineOption brandOption( { QStringLiteral( "b" ), QStringLiteral( "branding" ) }, ++ QStringLiteral( "Branding directory" ), ++ "path/to/branding.desc", ++ "src/branding/default/branding.desc" ); ++ QCommandLineOption uiOption( { QStringLiteral( "U" ), QStringLiteral( "ui" ) }, QStringLiteral( "Enable UI" ) ); ++ QCommandLineOption slideshowOption( { QStringLiteral( "s" ), QStringLiteral( "slideshow" ) }, ++ QStringLiteral( "Run slideshow module" ) ); ++ QCommandLineParser parser; ++ parser.setApplicationDescription( "Calamares module tester" ); ++ parser.addHelpOption(); ++ parser.addVersionOption(); ++ ++ parser.addOption( debugLevelOption ); ++ parser.addOption( settingsOption ); ++ parser.addOption( globalOption ); ++ parser.addOption( jobOption ); ++ parser.addOption( langOption ); ++ parser.addOption( brandOption ); ++ parser.addOption( uiOption ); ++ parser.addOption( slideshowOption ); ++#ifdef WITH_PYTHON ++ QCommandLineOption pythonOption( { QStringLiteral( "P" ), QStringLiteral( "no-injected-python" ) }, ++ QStringLiteral( "Do not disable potentially-harmful Python commands" ) ); ++ parser.addOption( pythonOption ); ++#endif ++ ++ parser.addPositionalArgument( "module", "Path or name of module to run." ); ++ parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" ); ++ ++ parser.process( a ); ++ ++ const QStringList args = parser.positionalArguments(); ++ if ( args.isEmpty() && !parser.isSet( slideshowOption ) ) ++ { ++ cError() << "Missing path.\n"; ++ parser.showHelp(); ++ } ++ else if ( args.size() > 2 ) ++ { ++ cError() << "More than one path.\n"; ++ parser.showHelp(); ++ } ++ else ++ { ++ QString jobSettings( parser.value( jobOption ) ); ++ if ( jobSettings.isEmpty() && ( args.size() == 2 ) ) ++ { ++ jobSettings = args.at( 1 ); ++ } ++ ++ bool pythonInjection = true; ++#ifdef WITH_PYTHON ++ if ( parser.isSet( pythonOption ) ) ++ { ++ pythonInjection = false; ++ } ++#endif ++ return ModuleConfig { parser.isSet( slideshowOption ) ? QStringLiteral( "-" ) : args.first(), ++ jobSettings, ++ parser.value( globalOption ), ++ parser.value( settingsOption ), ++ parser.value( langOption ), ++ parser.value( brandOption ), ++ parser.isSet( slideshowOption ) || parser.isSet( uiOption ), ++ pythonInjection }; ++ } ++} ++ ++/** @brief Bogus Job for --slideshow option ++ * ++ * Generally one would use DummyCppJob for this kind of dummy ++ * job, but that class lives in a module so isn't available ++ * in this test application. ++ * ++ * This bogus job just sleeps for 3. ++ */ ++class ExecViewJob : public Calamares::CppJob ++{ ++public: ++ explicit ExecViewJob( const QString& name, unsigned long t = 3 ) ++ : m_name( name ) ++ , m_delay( t ) ++ { ++ } ++ ~ExecViewJob() override; ++ ++ QString prettyName() const override { return m_name; } ++ ++ Calamares::JobResult exec() override ++ { ++ QThread::sleep( m_delay ); ++ return Calamares::JobResult::ok(); ++ } ++ ++ void setConfigurationMap( const QVariantMap& ) override {} ++ ++private: ++ QString m_name; ++ unsigned long m_delay; ++}; ++ ++ExecViewJob::~ExecViewJob() {} ++ ++/** @brief Bogus module for --slideshow option ++ * ++ * Normally the slideshow -- displayed by ExecutionViewStep -- is not ++ * associated with any particular module in the Calamares configuration. ++ * It is added internally by the module manager. For the module-loader ++ * testing application, we need something that pretends to be the ++ * module for the ExecutionViewStep. ++ */ ++class ExecViewModule : public Calamares::Module ++{ ++public: ++ ExecViewModule(); ++ ~ExecViewModule() override; ++ ++ void loadSelf() override; ++ ++ virtual Calamares::ModuleSystem::Type type() const override; ++ virtual Calamares::ModuleSystem::Interface interface() const override; ++ ++ virtual Calamares::JobList jobs() const override; ++ ++protected: ++ void initFrom( const Calamares::ModuleSystem::Descriptor& ) override; ++}; ++ ++ExecViewModule::ExecViewModule() ++ : Calamares::Module() ++{ ++ // Normally the module-loader gives the module an instance key ++ // (out of the settings file, or the descriptor of the module). ++ // We don't have one, so build one -- this gives us "execView@execView". ++ QVariantMap m; ++ const QString execView = QStringLiteral( "execView" ); ++ m.insert( "name", execView ); ++ Calamares::Module::initFrom( Calamares::ModuleSystem::Descriptor::fromDescriptorData( m, execView ), execView ); ++} ++ ++ExecViewModule::~ExecViewModule() {} ++ ++void ++ExecViewModule::initFrom( const Calamares::ModuleSystem::Descriptor& ) ++{ ++} ++ ++void ++ExecViewModule::loadSelf() ++{ ++ auto* viewStep = new Calamares::ExecutionViewStep(); ++ viewStep->setModuleInstanceKey( instanceKey() ); ++ viewStep->setConfigurationMap( m_configurationMap ); ++ viewStep->appendJobModuleInstanceKey( instanceKey() ); ++ Calamares::ViewManager::instance()->addViewStep( viewStep ); ++ m_loaded = true; ++} ++ ++Calamares::Module::Type ++ExecViewModule::type() const ++{ ++ return Module::Type::View; ++} ++ ++Calamares::Module::Interface ++ExecViewModule::interface() const ++{ ++ return Module::Interface::QtPlugin; ++} ++ ++Calamares::JobList ++ExecViewModule::jobs() const ++{ ++ Calamares::JobList l; ++ const auto* gs = Calamares::JobQueue::instance()->globalStorage(); ++ if ( gs && gs->contains( "jobs" ) ) ++ { ++ QVariantList joblist = gs->value( "jobs" ).toList(); ++ for ( const auto& jd : joblist ) ++ { ++ QVariantMap jobdescription = jd.toMap(); ++ if ( jobdescription.contains( "name" ) && jobdescription.contains( "delay" ) ) ++ { ++ l.append( Calamares::job_ptr( new ExecViewJob( jobdescription.value( "name" ).toString(), ++ jobdescription.value( "delay" ).toULongLong() ) ) ); ++ } ++ } ++ } ++ if ( l.count() > 0 ) ++ { ++ return l; ++ } ++ ++ l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "step 1" ) ) ) ); ++ l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "step two" ) ) ) ); ++ l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "locking mutexes" ), 20 ) ) ); ++ l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "unlocking mutexes" ), 1 ) ) ); ++ for ( const QString& s : QStringList { "Harder", "Better", "Faster", "Stronger" } ) ++ { ++ l.append( Calamares::job_ptr( new ExecViewJob( s, 0 ) ) ); ++ } ++ l.append( Calamares::job_ptr( new ExecViewJob( QStringLiteral( "cleaning up" ), 20 ) ) ); ++ return l; ++} ++ ++static Calamares::Module* ++load_module( const ModuleConfig& moduleConfig ) ++{ ++ QString moduleName = moduleConfig.moduleName(); ++ if ( moduleName == "-" ) ++ { ++ return new ExecViewModule; ++ } ++ ++ QFileInfo fi; // This is kept around to hold the path of the module descriptor ++ ++ bool ok = false; ++ QVariantMap descriptor; ++ ++ QStringList moduleDirectories { "./", "src/modules/", "modules/", CMAKE_INSTALL_FULL_LIBDIR "/calamares/modules/" }; ++ for ( const QString& prefix : qAsConst( moduleDirectories ) ) ++ { ++ // Could be a complete path, eg. src/modules/dummycpp/module.desc ++ fi = QFileInfo( prefix + moduleName ); ++ if ( fi.exists() && fi.isFile() ) ++ { ++ descriptor = Calamares::YAML::load( fi, &ok ); ++ } ++ if ( ok ) ++ { ++ break; ++ } ++ ++ // Could be a path without module.desc ++ fi = QFileInfo( prefix + moduleName ); ++ if ( fi.exists() && fi.isDir() ) ++ { ++ fi = QFileInfo( prefix + moduleName + "/module.desc" ); ++ if ( fi.exists() && fi.isFile() ) ++ { ++ descriptor = Calamares::YAML::load( fi, &ok ); ++ } ++ if ( ok ) ++ { ++ break; ++ } ++ else ++ { ++ if ( !fi.exists() ) ++ { ++ cDebug() << "Expected a descriptor file" << fi.path(); ++ } ++ else ++ { ++ cDebug() << "Read descriptor" << fi.path() << "and it was empty."; ++ } ++ } ++ } ++ } ++ ++ if ( !ok ) ++ { ++ cWarning() << "No suitable module descriptor found in" << Logger::DebugList( moduleDirectories ); ++ return nullptr; ++ } ++ ++ QString name = descriptor.value( "name" ).toString(); ++ if ( name.isEmpty() ) ++ { ++ cWarning() << "No name found in module descriptor" << fi.absoluteFilePath(); ++ return nullptr; ++ } ++ ++ QString moduleDirectory = fi.absolutePath(); ++ QString configFile( moduleConfig.configFile().isEmpty() ? moduleDirectory + '/' + name + ".conf" ++ : moduleConfig.configFile() ); ++ ++ cDebug() << Logger::SubEntry << "Module" << moduleName << "job-configuration:" << configFile; ++ ++ Calamares::Module* module = Calamares::moduleFromDescriptor( ++ Calamares::ModuleSystem::Descriptor::fromDescriptorData( descriptor, fi.absoluteFilePath() ), ++ name, ++ configFile, ++ moduleDirectory ); ++ ++ return module; ++} ++ ++static bool ++is_ui_option( const char* s ) ++{ ++ return !qstrcmp( s, "--ui" ) || !qstrcmp( s, "-U" ); ++} ++ ++static bool ++is_slideshow_option( const char* s ) ++{ ++ return !qstrcmp( s, "--slideshow" ) || !qstrcmp( s, "-s" ); ++} ++ ++/** @brief Create the right kind of QApplication ++ * ++ * Does primitive parsing of argv[] to find the --ui option and returns ++ * a UI-enabled application if it does. ++ * ++ * @p argc must be a reference (to main's argc) because the QCoreApplication ++ * constructors take a reference as well, and that would otherwise be a ++ * reference to a temporary. ++ */ ++QCoreApplication* ++createApplication( int& argc, char* argv[] ) ++{ ++ for ( int i = 1; i < argc; ++i ) ++ { ++ if ( is_slideshow_option( argv[ i ] ) || is_ui_option( argv[ i ] ) ) ++ { ++ auto* aw = new QApplication( argc, argv ); ++ aw->setQuitOnLastWindowClosed( true ); ++ return aw; ++ } ++ } ++ return new QCoreApplication( argc, argv ); ++} ++ ++#ifdef WITH_PYTHON ++static const char pythonPreScript[] = R"%( ++# This is Python code executed by Python modules *before* the ++# script file (e.g. main.py) is executed. ++# ++# Calls to suprocess methods that execute something are ++# suppressed and logged -- scripts should really be using libcalamares ++# methods instead. ++_calamares_subprocess = __import__("subprocess", globals(), locals(), [], 0) ++import sys ++import libcalamares ++class fake_subprocess(object): ++ PIPE = object() ++ STDOUT = object() ++ STDERR = object() ++ class CompletedProcess(object): ++ returncode = 0 ++ stdout = "" ++ stderr = "" ++ @staticmethod ++ def call(*args, **kwargs): ++ libcalamares.utils.debug("subprocess.call(%r,%r) X ignored" % (args, kwargs)) ++ return 0 ++ @staticmethod ++ def check_call(*args, **kwargs): ++ libcalamares.utils.debug("subprocess.check_call(%r,%r) X ignored" % (args, kwargs)) ++ return 0 ++ # This is a 3.5-and-later method, is supposed to return a CompletedProcess ++ @staticmethod ++ def run(*args, **kwargs): ++ libcalamares.utils.debug("subprocess.run(%r,%r) X ignored" % (args, kwargs)) ++ return fake_subprocess.CompletedProcess() ++for attr in ("CalledProcessError",): ++ setattr(fake_subprocess,attr,getattr(_calamares_subprocess,attr)) ++sys.modules["subprocess"] = fake_subprocess ++libcalamares.utils.debug('pre-script for testing purposes injected') ++ ++)%"; ++#endif ++ ++int ++main( int argc, char* argv[] ) ++{ ++ QCoreApplication* application = createApplication( argc, argv ); ++ ++ Logger::setupLogLevel( Logger::LOGVERBOSE ); ++ ++ ModuleConfig module = handle_args( *application ); ++ if ( module.moduleName().isEmpty() ) ++ { ++ return 1; ++ } ++ ++ std::unique_ptr< Calamares::Settings > settings_p( Calamares::Settings::init( module.m_settingsConfig ) ); ++ std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); ++ std::unique_ptr< Calamares::System > system_p( new Calamares::System( settings_p->doChroot() ) ); ++ ++ QMainWindow* mainWindow = nullptr; ++ ++ auto* gs = jobqueue_p->globalStorage(); ++ if ( !module.globalConfigFile().isEmpty() ) ++ { ++ gs->loadYaml( module.globalConfigFile() ); ++ } ++ if ( !module.language().isEmpty() ) ++ { ++ QVariantMap vm; ++ vm.insert( "LANG", module.language() ); ++ gs->insert( "localeConf", vm ); ++ } ++ ++#ifdef WITH_PYTHON ++ if ( module.m_pythonInjection ) ++ { ++#ifdef WITH_PYBIND11 ++ Calamares::Python::Job::setInjectedPreScript( pythonPreScript ); ++#else ++ // Old Boost approach ++ Calamares::PythonJob::setInjectedPreScript( pythonPreScript ); ++#endif ++ } ++#endif ++#ifdef WITH_QML ++ Calamares::initQmlModulesDir(); // don't care if failed ++#endif ++ ++ cDebug() << "Calamares module-loader testing" << module.moduleName(); ++ Calamares::Module* m = load_module( module ); ++ if ( !m ) ++ { ++ cError() << "Could not load module" << module.moduleName(); ++ return 1; ++ } ++ ++ cDebug() << Logger::SubEntry << "got" << m->name() << m->typeString() << m->interfaceString(); ++ if ( m->type() == Calamares::Module::Type::View ) ++ { ++ // If we forgot the --ui, any ViewModule will core dump as it ++ // tries to create the widget **which won't be used anyway**. ++ // ++ // To avoid that crash, re-create the QApplication, now with GUI ++ if ( !qobject_cast< QApplication* >( application ) ) ++ { ++ auto* replace_app = new QApplication( argc, argv ); ++ replace_app->setQuitOnLastWindowClosed( true ); ++ application = replace_app; ++ } ++ mainWindow = module.m_ui ? new QMainWindow() : nullptr; ++ if ( mainWindow ) ++ { ++ mainWindow->installEventFilter( Calamares::Retranslator::instance() ); ++ } ++ ++ (void)new Calamares::Branding( module.m_branding ); ++ auto* modulemanager = new Calamares::ModuleManager( QStringList(), nullptr ); ++ (void)Calamares::ViewManager::instance( mainWindow ); ++ modulemanager->addModule( m ); ++ } ++ ++ if ( !m->isLoaded() ) ++ { ++ m->loadSelf(); ++ } ++ ++ if ( !m->isLoaded() ) ++ { ++ cError() << "Module" << module.moduleName() << "could not be loaded."; ++ return 1; ++ } ++ ++ if ( mainWindow ) ++ { ++ auto* vm = Calamares::ViewManager::instance(); ++ vm->onInitComplete(); ++ QWidget* w = vm->currentStep()->widget(); ++ w->setParent( mainWindow ); ++ mainWindow->setCentralWidget( w ); ++ w->show(); ++ mainWindow->show(); ++ return application->exec(); ++ } ++ ++ using TR = Logger::DebugRow< const char*, const QString >; ++ ++ cDebug() << Logger::SubEntry << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() ) ++ << TR( "interface", m->interfaceString() ); ++ ++ Calamares::JobQueue::instance()->enqueue( 100, m->jobs() ); ++ ++ QObject::connect( Calamares::JobQueue::instance(), ++ &Calamares::JobQueue::finished, ++ [ application ]() ++ { QTimer::singleShot( std::chrono::seconds( 3 ), application, &QApplication::quit ); } ); ++ QTimer::singleShot( 0, []() { Calamares::JobQueue::instance()->start(); } ); ++ ++ return application->exec(); ++} +diff --git a/src/libcalamares/CalamaresAbout.cpp b/src/libcalamares/CalamaresAbout.cpp +index 595efc7..65a1b9d 100644 +--- a/src/libcalamares/CalamaresAbout.cpp ++++ b/src/libcalamares/CalamaresAbout.cpp +@@ -65,6 +65,7 @@ Calamares::aboutString() + { + return substituteVersions( QCoreApplication::translate( "AboutData", s_header ) ) + aboutMaintainers() + + QCoreApplication::translate( "AboutData", s_footer ); ++ // return aboutMaintainers()+ QCoreApplication::translate( "AboutData", s_footer ); + } + + const QString +diff --git a/src/libcalamaresui/modulesystem/CppJobModule.cpp b/src/libcalamaresui/modulesystem/CppJobModule.cpp +index b35a457..c211006 100644 +--- a/src/libcalamaresui/modulesystem/CppJobModule.cpp ++++ b/src/libcalamaresui/modulesystem/CppJobModule.cpp +@@ -53,6 +53,10 @@ CppJobModule::loadSelf() + cDebug() << "Could not load module:" << m_loader->errorString(); + return; + } ++ // cDebug() << "CppJobModule loading self for instance" << instanceKey() ++ // << "\nCppJobModule at address" << this ++ // << "\nCalamares::PluginFactory at address" << pf ++ // << "\nCppJob at address" << cppJob; + + cppJob->setModuleInstanceKey( instanceKey() ); + cppJob->setConfigurationMap( m_configurationMap ); +diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py +index 6ca279e..02fec0f 100644 +--- a/src/modules/displaymanager/main.py ++++ b/src/modules/displaymanager/main.py +@@ -410,6 +410,11 @@ class DMgdm(DisplayManager): + if self.config is None: + raise ValueError( "No config file for GDM has been set." ) + ++ ++ libcalamares.utils.target_env_call( ++ ['hostnamectl', 'set-hostname', username] ++ ) ++ + # Systems with GDM as Desktop Manager + gdm_conf_path = os.path.join(self.root_mount_point, self.config) + +@@ -571,6 +576,11 @@ class DMlightdm(DisplayManager): + # Ideally, we should use configparser for the ini conf file, + # but we just do a simple text replacement for now, as it + # worksforme(tm) ++ ++ libcalamares.utils.target_env_call( ++ ['hostnamectl', 'set-hostname', username] ++ ) ++ + lightdm_conf_path = os.path.join( + self.root_mount_point, "etc/lightdm/lightdm.conf" + ) +diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp +index be60521..3f06158 100644 +--- a/src/modules/keyboard/KeyboardPage.cpp ++++ b/src/modules/keyboard/KeyboardPage.cpp +@@ -48,6 +48,9 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent ) + { + ui->setupUi( this ); + this->setContentsMargins(50,0,50,0); ++ // Keyboard Preview ++ // ui->KBPreviewLayout->addWidget( m_keyboardPreview ); ++ + + { + auto* model = config->keyboardModels(); +@@ -90,11 +93,27 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent ) + &QItemSelectionModel::currentChanged, + [ this ]( const QModelIndex& current ) + { m_config->keyboardLayouts()->setCurrentIndex( current.row() ); } ); ++ // connect( config->keyboardLayouts(), ++ // &KeyboardLayoutModel::currentIndexChanged, ++ // [ this ]( int index ) ++ // { ++ // ui->layoutSelector->setCurrentIndex( m_config->keyboardLayouts()->index( index ) ); ++ // m_keyboardPreview->setLayout( m_config->keyboardLayouts()->key( index ) ); ++ // m_keyboardPreview->setVariant( ++ // m_config->keyboardVariants()->key( m_config->keyboardVariants()->currentIndex() ) ); ++ // } ); + + connect( ui->variantSelector->selectionModel(), + &QItemSelectionModel::currentChanged, + [ this ]( const QModelIndex& current ) + { m_config->keyboardVariants()->setCurrentIndex( current.row() ); } ); ++ // connect( config->keyboardVariants(), ++ // &KeyboardVariantsModel::currentIndexChanged, ++ // [ this ]( int index ) ++ // { ++ // ui->variantSelector->setCurrentIndex( m_config->keyboardVariants()->index( index ) ); ++ // m_keyboardPreview->setVariant( m_config->keyboardVariants()->key( index ) ); ++ // } ); + + connect( ui->groupSelector, + QOverload< int >::of( &QComboBox::currentIndexChanged ), +diff --git a/src/modules/keyboard/KeyboardPage.ui b/src/modules/keyboard/KeyboardPage.ui +index 70cfca3..1d6afbf 100644 +--- a/src/modules/keyboard/KeyboardPage.ui ++++ b/src/modules/keyboard/KeyboardPage.ui +@@ -45,6 +45,9 @@ SPDX-License-Identifier: GPL-3.0-or-later + + + ++ + + + +diff --git a/src/modules/locale/Config.cpp b/src/modules/locale/Config.cpp +index 0d70ff3..fbcbf48 100644 +--- a/src/modules/locale/Config.cpp ++++ b/src/modules/locale/Config.cpp +@@ -426,6 +426,33 @@ Config::currentLCStatus() const + .arg( localeLabel( m_selectedLocaleConfiguration.lc_numeric ) ); + } + ++ ++static QString ++getTranRes(QString& filePath,QString& keyWord) { ++ QFile file(filePath); ++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { ++ qDebug() << "无法打开文件"; ++ return QString(); ++ } ++ ++ QTextStream in(&file); ++ QString currentLine; ++ QString resLine; ++ ++ while (!in.atEnd()) { ++ currentLine = in.readLine(); ++ if (currentLine.contains(keyWord, Qt::CaseInsensitive)) { ++ in.readLine(); ++ resLine = in.readLine(); ++ file.close(); ++ return resLine.trimmed().replace("","").replace("",""); ++ } ++ } ++ ++ return keyWord; ++} ++ ++ + QString + Config::currentTimeZoneStatus() const + { +@@ -434,6 +461,22 @@ Config::currentTimeZoneStatus() const + { + zone = "Hong Kong(China)"; + } ++ ++ ++ zone.replace("_"," "); ++ QString translationFile = ""; ++ if( m_selectedLocaleConfiguration.language() == "zh_CN.utf8"){ ++ translationFile = "tz_zh_CN.ts"; ++ } else if( m_selectedLocaleConfiguration.language() == "zh_TW.utf8"){ ++ translationFile="tz_zh_TW.ts"; ++ } ++ ++ QString transFilePath = QStringLiteral("/usr/share/calamares/") + translationFile; ++ cDebug() << "transFilePath" << transFilePath; ++ if(translationFile != ""){ ++ zone = getTranRes(transFilePath, zone); ++ } ++ + return tr("The timezone will be set to %1.","@info") + .arg( zone ); + } +diff --git a/src/modules/locale/LocalePage.cpp b/src/modules/locale/LocalePage.cpp +index ed50574..0568067 100644 +--- a/src/modules/locale/LocalePage.cpp ++++ b/src/modules/locale/LocalePage.cpp +@@ -32,6 +32,13 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + { + QBoxLayout* mainLayout = new QVBoxLayout; + mainLayout->setContentsMargins(50,0,50,0); ++ //QBoxLayout* tzwLayout = new QHBoxLayout; ++ //m_tzWidget = new TimeZoneWidget( m_config->zonesModel(), this ); ++ //tzwLayout->addStretch(); ++ //tzwLayout->addWidget( m_tzWidget ); ++ //tzwLayout->addStretch(); ++ // Adjust for margins and spacing in this page ++ //m_tzWidget->setMinimumHeight( m_tzWidget->minimumHeight() + 12 ); // 2 * spacing + + QBoxLayout* zoneAndRegionLayout = new QVBoxLayout; + m_regionLabel = new QLabel( this ); +@@ -83,7 +90,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + m_formatsChangeButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + formatsLayout->addWidget( m_formatsChangeButton ); + formatsLayout->addSpacing(20); +- ++ //mainLayout->addLayout( tzwLayout ); + mainLayout->addStretch(); + mainLayout->addLayout( zoneAndRegionLayout ); + mainLayout->addStretch(); +@@ -93,7 +100,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + mainLayout->addSpacing(20); + mainLayout->addLayout( timezoneLayout ); + mainLayout->addStretch(); +- ++ //setMinimumWidth( m_tzWidget->width() ); + setLayout( mainLayout ); + + m_localeChangeButton->hide(); +@@ -107,15 +114,20 @@ LocalePage::LocalePage( Config* config, QWidget* parent ) + zones->setRegion( location->region() ); + m_regionCombo->setModel( regions ); + m_zoneCombo->setModel( zones ); +- ++ //m_tzWidget->setCurrentLocation( location ); + locationChanged( location ); // doesn't inform TZ widget + } + + connect( config, &Config::currentLCStatusChanged, m_formatsLabel, &QLabel::setText ); + connect( config, &Config::currentLanguageStatusChanged, m_localeLabel, &QLabel::setText ); + connect( config, &Config::currentZoneChanged, m_timezoneLabel , &QLabel::setText); +- ++ //connect( config, &Config::currentLocationChanged, m_tzWidget, &TimeZoneWidget::setCurrentLocation ); + connect( config, &Config::currentLocationChanged, this, &LocalePage::locationChanged ); ++ // connect( m_tzWidget, ++ // &TimeZoneWidget::locationChanged, ++ // config, ++ // QOverload< const Calamares::Locale::TimeZoneData* >::of( &Config::setCurrentLocation ) ); ++ + connect( m_regionCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::regionChanged ); + connect( m_zoneCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::zoneChanged ); + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index aa048e2..3f35638 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -147,6 +147,8 @@ labels: + # + # An item for AppStream may also contain an *id* and a *screenshot* + # key which will override the data from AppStream. ++# liberation-fonts, gnu-*-fonts, google-*-fonts, adwaita-icon-theme, atk, atkmm, at-spi2-atk, at-spi2-core, baobab, abattis-cantarell-fonts, cheese, clutter, clutter-gst3, clutter-gtk, cogl, dconf, dconf-editor, devhelp, eog, epiphany, evince, evolution-data-server, file-roller, folks, gcab, gcr, gdk-pixbuf2, gdm, gedit, geocode-glib, gfbgraph, gjs, glib2, glibmm24, glib-networking, gmime30, gnome-autoar, gnome-backgrounds, gnome-bluetooth, gnome-builder, gnome-calculator, gnome-calendar, gnome-characters, gnome-clocks, gnome-color-manager, gnome-contacts, gnome-control-center, gnome-desktop3, gnome-disk-utility, gnome-font-viewer, gnome-getting-started-docs, gnome-initial-setup, gnome-keyring, gnome-logs, gnome-menus, gnome-music, gnome-online-accounts, gnome-online-miners, gnome-photos, gnome-remote-desktop, gnome-screenshot, gnome-session, gnome-settings-daemon, gnome-shell, gnome-shell-extensions, gnome-software, gnome-system-monitor, gnome-terminal, gnome-tour, gnome-user-docs, gnome-user-share, gnome-video-effects, gnome-weather, gobject-introspection, gom, grilo, grilo-plugins, gsettings-desktop-schemas, gsound, gspell, gssdp, gtk3, gtk4, gtk-doc, gtkmm30, gtksourceview4, gtk-vnc2, gupnp, gupnp-av, gupnp-dlna, gvfs, json-glib, libchamplain, libdazzle, libgdata, libgee, libgnomekbd, libgsf, libgtop2, libgweather, libgxps, libhandy, libmediaart, libnma, libnotify, libpeas, librsvg2, libsecret, libsigc++20, libsoup, mm-common, mutter, nautilus, orca, pango, pangomm, libphodav, python3-pyatspi, python3-gobject, rest, rygel, simple-scan, sushi, sysprof, tepl, totem, totem-pl-parser, tracker3, tracker3-miners, vala, vte291, yelp, yelp-tools, yelp-xsl, zenity, devstation-config, ibus-libpinyin ] ++ + items: + - id: "" + # packages: [] # This item installs no packages +@@ -157,11 +159,25 @@ items: + description[nl]: "Kies eventueel een desktop-omgeving uit deze lijst. Als u geen desktop-omgeving wenst te gebruiken, kies er dan geen. In dat geval start het systeem straks op in tekst-modus en kunt u later alsnog een desktop-omgeving installeren." + description[zh]: "请选择一个桌面环境。如果您不想安装桌面环境也没关系,您可以稍后再为系统安装桌面环境。" + screenshot: ":/images/Minimal-Install.png" +- ++ # - id: kde ++ # packages: [ kde-frameworks, kde-plasma, kde-gear ] ++ # name: Plasma Desktop ++ # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." ++ # screenshot: ":/images/Plasma.png" + - id: gnome +- packages: [ checkpolicy, code, xorg-*, dejavu-fonts, liberation-fonts, gnu-*-fonts, google-*-fonts, adwaita-icon-theme, atk, atkmm, at-spi2-atk, at-spi2-core, baobab, abattis-cantarell-fonts, cheese, clutter, clutter-gst3, clutter-gtk, cogl, dconf, dconf-editor, devhelp, eog, epiphany, evince, evolution-data-server, file-roller, folks, gcab, gcr, gdk-pixbuf2, gdm, gedit, geocode-glib, gfbgraph, gjs, glib2, glibmm24, glib-networking, gmime30, gnome-autoar, gnome-backgrounds, gnome-bluetooth, gnome-builder, gnome-calculator, gnome-calendar, gnome-characters, gnome-clocks, gnome-color-manager, gnome-contacts, gnome-control-center, gnome-desktop3, gnome-disk-utility, gnome-font-viewer, gnome-getting-started-docs, gnome-initial-setup, gnome-keyring, gnome-logs, gnome-menus, gnome-music, gnome-online-accounts, gnome-online-miners, gnome-photos, gnome-remote-desktop, gnome-screenshot, gnome-session, gnome-settings-daemon, gnome-shell, gnome-shell-extensions, gnome-software, gnome-system-monitor, gnome-terminal, gnome-tour, gnome-user-docs, gnome-user-share, gnome-video-effects, gnome-weather, gobject-introspection, gom, grilo, grilo-plugins, gsettings-desktop-schemas, gsound, gspell, gssdp, gtk3, gtk4, gtk-doc, gtkmm30, gtksourceview4, gtk-vnc2, gupnp, gupnp-av, gupnp-dlna, gvfs, json-glib, libchamplain, libdazzle, libgdata, libgee, libgnomekbd, libgsf, libgtop2, libgweather, libgxps, libhandy, libmediaart, libnma, libnotify, libpeas, librsvg2, libsecret, libsigc++20, libsoup, mm-common, mutter, nautilus, orca, pango, pangomm, libphodav, python3-pyatspi, python3-gobject, rest, rygel, simple-scan, sushi, sysprof, tepl, totem, totem-pl-parser, tracker3, tracker3-miners, vala, vte291, yelp, yelp-tools, yelp-xsl, zenity, devstation-config, ibus-libpinyin ] ++ packages: [ checkpolicy, code, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts ] + name: DevStation + name[zh]: DevStation + description: GNU Networked Object Modeling Environment Desktop + description[zh]: Devstation系统桌面 + screenshot: ":/images/gnome.png" ++ #- id: ukui ++ # packages: [ ukui ] ++ # name: UKUI ++ # description: Linux Desktop ++ # screenshot: ":/images/UKUI.png" ++ # - id: calamares ++ # appdata: ../io.calamares.calamares.appdata.xml ++ # screenshot: ":/images/calamares.png" ++ # - id: kate ++ # appstream: org.kde.kwrite.desktop +diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc +index 2f76726..b5c4a9c 100644 +--- a/src/modules/packagechooser/packagechooser.qrc ++++ b/src/modules/packagechooser/packagechooser.qrc +@@ -1,12 +1,7 @@ + + + images/no-selection.png +- images/calamares.png +- + images/gnome.png +- +- +- + images/Minimal-Install.png + + +diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py +index 1fbe276..2c6e6ad 100644 +--- a/src/modules/packages/main.py ++++ b/src/modules/packages/main.py +@@ -756,7 +756,7 @@ def subst_locale_orig(plist): + return ret + + +-def handle_packagechooser(entry): ++def handle_packagechooser(): + """ + Handle special logic for entries with source "packagechooser@packagechooser". + Modifies the entry to include specific pre- and post-scripts. +@@ -764,13 +764,11 @@ def handle_packagechooser(entry): + :param entry: dict + The operation entry to process. + """ +- if "install" in entry: +- item = { +- "package": entry["install"], +- "pre-script": "", +- "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target"] +- } +- entry["install"] = [item] ++ item = { ++ "pre-script": "", ++ "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target"] ++ } ++ return item + + + def run_operations(pkgman, entry, options): +diff --git a/src/modules/packages/packages.conf b/src/modules/packages/packages.conf +index 490c289..31e51c2 100644 +--- a/src/modules/packages/packages.conf ++++ b/src/modules/packages/packages.conf +@@ -215,7 +215,7 @@ operations: + - coreutils + - efibootmgr + - shim +- - java-11-openjdk-devel ++ - java-21-openjdk-devel + - vim + - gdb + - perf +@@ -229,5 +229,3 @@ operations: + options: + - --nogpgcheck + - --setopt=sslverify=0 +- - --disablerepo=* +- - --enablerepo=local-repo +diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp +index 16723c7..1885949 100644 +--- a/src/modules/partition/core/DeviceList.cpp ++++ b/src/modules/partition/core/DeviceList.cpp +@@ -43,6 +43,17 @@ hasRootPartition( Device* device ) + return false; + } + ++/** ++ * Does the given @p device path should point to a device ++ */ ++static bool ++isValidDevice(const QString& devicePath) ++{ ++ auto result = Calamares::System::runCommand({ "blkid", devicePath }, std::chrono::seconds(30)); ++ ++ return result.getExitCode() == 0 && !result.getOutput().isEmpty(); ++} ++ + /** @brief Check if @p path holds an iso9660 filesystem + * + * The @p path should point to a device; blkid is used to check the FS type. +@@ -187,7 +198,17 @@ getDevices( DeviceType which ) + } + else + { +- ++it; ++ const QString devicePath = (*it)->deviceNode(); ++ ++ if (!isValidDevice(devicePath)) ++ { ++ cDebug() << Logger::SubEntry << "Skipping device due to blkid failure: " << devicePath; ++ it = removeInAllModes(devices, it); ++ } ++ else ++ { ++ ++it; ++ } + } + } + cDebug() << Logger::SubEntry << "there are" << devices.count() << "devices left."; +diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp +index ce1355b..d36c4e5 100644 +--- a/src/modules/partition/jobs/ClearMountsJob.cpp ++++ b/src/modules/partition/jobs/ClearMountsJob.cpp +@@ -260,7 +260,7 @@ STATICTEST MessageAndPath + tryUmount( const QString& partPath ) + { + QProcess process; +- process.start( "umount", { partPath } ); ++ process.start( "umount", { "-l", partPath } ); + process.waitForFinished(); + if ( process.exitCode() == 0 ) + { +@@ -317,6 +317,51 @@ tryCryptoClose( const QString& mapperPath ) + return {}; + } + ++STATICTEST MessageAndPath ++tryClearLVM(const QString& LVMPath) ++{ ++ tryUmount( LVMPath ); ++ ++ QProcess process; ++ process.start( "dmsetup", {"remove", LVMPath } ); ++ process.waitForFinished(); ++ if ( process.exitCode() == 0 ) ++ { ++ return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully removed LVM %1." ), LVMPath }; ++ } ++ return {}; ++} ++ ++STATICTEST MessageAndPath ++mpathClear(const QString& deviceName) ++{ ++ QString devicePath = "/dev/" + deviceName; ++ QProcess process; ++ process.start("multipath", { "-ll", devicePath } ); ++ process.waitForFinished(); ++ if( process.exitCode() == 0 ) ++ { ++ QStringList multiPathLines = QString::fromLocal8Bit( process.readAllStandardOutput() ).split( '\n' ); ++ QStringList firstLines = multiPathLines.first().split(' '); ++ QString mpath = firstLines.first(); ++ return tryClearLVM("/dev/mapper/" + mpath); ++ } ++ return {}; ++} ++ ++STATICTEST MessageAndPath ++diskClear(const QString& diskPath) ++{ ++ QString devicePath = "/dev/" + diskPath; ++ QProcess process; ++ process.start( "wipefs", { "-af", devicePath } ); ++ process.waitForFinished(); ++ if( process.exitCode() == 0 ) ++ { ++ return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully cleared %1." ), diskPath }; ++ } ++ return {}; ++} + STATICTEST MessageAndPath + tryVGDisable( const QString& vgName ) + { +@@ -380,12 +425,14 @@ ClearMountsJob::exec() + QList< MessageAndPath > goodNews; + + apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); +- apply( getLVMVolumes(), tryUmount, goodNews ); ++ apply( getLVMVolumes(), tryClearLVM, goodNews ); + apply( getPVGroups( deviceName ), tryVGDisable, goodNews ); + + apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); + apply( getPartitionsForDevice( deviceName ), tryUmount, goodNews ); + apply( getSwapsForDevice( m_deviceNode ), tryClearSwap, goodNews ); ++ diskClear(deviceName); ++ mpathClear(deviceName); + + Calamares::JobResult ok = Calamares::JobResult::ok(); + ok.setMessage( tr( "Cleared all mounts for %1" ).arg( m_deviceNode ) ); +diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py +index 4c5518e..7db5f2e 100644 +--- a/src/modules/unpackfs/main.py ++++ b/src/modules/unpackfs/main.py +@@ -207,7 +207,7 @@ def file_copy(source, entry, progress_cb): + # `source` *must* end with '/' otherwise a directory named after the source + # will be created in `dest`: ie if `source` is "/foo/bar" and `dest` is + # "/dest", then files will be copied in "/dest/bar". +- if not source.endswith("/") and not os.path.isfile(source): ++ if source and not source.endswith("/") and not os.path.isfile(source): + source += "/" + + num_files_total_local = 0 +@@ -395,8 +395,6 @@ class UnpackOperation: + for entry in self.entries: + status = _("Starting to unpack {}").format(entry.source) + libcalamares.job.setprogress( ( 1.0 * complete ) / len(self.entries) ) +- entry.do_mount(source_mount_path) +- entry.do_count() # Fill in the entry.total + + self.report_progress() + error_msg = self.unpack_image(entry, entry.mountPoint) +@@ -437,7 +435,7 @@ class UnpackOperation: + + return file_copy(source, entry, progress_cb) + finally: +- if not entry.is_file(): ++ if imgmountdir and not entry.is_file() and os.path.isdir(imgmountdir): + subprocess.check_call(["umount", "-l", imgmountdir]) + + +diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp +index 4e36c50..9699141 100644 +--- a/src/modules/users/CreateUserJob.cpp ++++ b/src/modules/users/CreateUserJob.cpp +@@ -79,6 +79,23 @@ createUser( const QString& loginName, const QString& fullName, const QString& sh + return Calamares::JobResult::ok(); + } + ++static Calamares::JobResult ++config_root_bash(const QString& loginName) ++{ ++ QStringList copyBashFilesCommand; ++ copyBashFilesCommand << "cp" ++ << QString("/home/%1/.bashrc").arg(loginName) ++ << QString("/home/%1/.bash_profile").arg(loginName) ++ << "/root/"; ++ auto commandResult = Calamares::System::instance()->targetEnvCommand( copyBashFilesCommand ); ++ if ( commandResult.getExitCode() ) ++ { ++ cError() << "copy bash config file failed" << commandResult.getExitCode(); ++ return commandResult.explainProcess( copyBashFilesCommand, std::chrono::seconds( 10 ) /* bogus timeout */ ); ++ } ++ return Calamares::JobResult::ok(); ++} ++ + static Calamares::JobResult + setUserGroups( const QString& loginName, const QStringList& groups ) + { +@@ -155,6 +172,7 @@ CreateUserJob::exec() + QString userGroup = QString( "%1:%2" ).arg( m_config->loginName() ).arg( m_config->loginName() ); + QString homeDir = QString( "/home/%1" ).arg( m_config->loginName() ); + auto commandResult = Calamares::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } ); ++ config_root_bash(m_config->loginName()); + if ( commandResult.getExitCode() ) + { + cError() << "chown failed" << commandResult.getExitCode(); +diff --git a/src/modules/users/UsersPage.cpp b/src/modules/users/UsersPage.cpp +index 72fb3e0..a4edddf 100644 +--- a/src/modules/users/UsersPage.cpp ++++ b/src/modules/users/UsersPage.cpp +@@ -31,6 +31,9 @@ + #include + #include + #include ++#include ++#include ++#include + + /** @brief Add an error message and pixmap to a label. */ + static inline void +@@ -83,6 +86,105 @@ UsersPage::UsersPage( Config* config, QWidget* parent ) + { + ui->setupUi( this ); + this->setContentsMargins(50,15,50,0); ++ ++ ++ //初始化参数 ++ userPassword=false; ++ userVertifyPassword=false; ++ rootPassword=false; ++ rootVertifyPassword=false; ++ ++ userButton=new QPushButton(); ++ userVertifyButton=new QPushButton(); ++ rootButton=new QPushButton(); ++ rootVertifyButton=new QPushButton(); ++ ++ hIcon = QIcon(imagePath + "password-hide.png"); ++ sIcon = QIcon(imagePath + "password-show.png"); ++ userButton->setIcon(hIcon); ++ userVertifyButton->setIcon(hIcon); ++ rootButton->setIcon(hIcon); ++ rootVertifyButton->setIcon(hIcon); ++ ++ userButton->setCursor(Qt::PointingHandCursor); ++ userButton->setStyleSheet("QPushButton:hover {background-color:transparent;border-style:outset;}"); ++ userButton->setWindowFlags(Qt::FramelessWindowHint); ++ userButton->setFlat(true); ++ ++ userVertifyButton->setCursor(Qt::PointingHandCursor); ++ userVertifyButton->setStyleSheet("QPushButton:hover {background-color:transparent;border-style:outset;}"); ++ userVertifyButton->setWindowFlags(Qt::FramelessWindowHint); ++ userVertifyButton->setFlat(true); ++ ++ rootButton->setCursor(Qt::PointingHandCursor); ++ rootButton->setStyleSheet("QPushButton:hover {background-color:transparent;border-style:outset;}"); ++ rootButton->setWindowFlags(Qt::FramelessWindowHint); ++ rootButton->setFlat(true); ++ ++ rootVertifyButton->setCursor(Qt::PointingHandCursor); ++ rootVertifyButton->setStyleSheet("QPushButton:hover {background-color:transparent;border-style:outset;}"); ++ rootVertifyButton->setWindowFlags(Qt::FramelessWindowHint); ++ rootVertifyButton->setFlat(true); ++ ++ QWidgetAction* userPasswordAction = new QWidgetAction(ui->textBoxUserPassword); ++ QWidgetAction* userVerifiedPasswordAction = new QWidgetAction(ui->textBoxUserVerifiedPassword); ++ QWidgetAction* rootPasswordAction = new QWidgetAction(ui->textBoxRootPassword); ++ QWidgetAction* rootVerifiedPasswordAction = new QWidgetAction(ui->textBoxVerifiedRootPassword); ++ ++ userPasswordAction->setDefaultWidget(userButton); ++ ui->textBoxUserPassword->addAction(userPasswordAction,QLineEdit::TrailingPosition); ++ userVerifiedPasswordAction->setDefaultWidget(userVertifyButton); ++ ui->textBoxUserVerifiedPassword->addAction(userVerifiedPasswordAction,QLineEdit::TrailingPosition); ++ rootPasswordAction->setDefaultWidget(rootButton); ++ ui->textBoxRootPassword->addAction(rootPasswordAction,QLineEdit::TrailingPosition); ++ rootVerifiedPasswordAction->setDefaultWidget(rootVertifyButton); ++ ui->textBoxVerifiedRootPassword->addAction(rootVerifiedPasswordAction,QLineEdit::TrailingPosition); ++ ++ connect( ++ userButton, ++ &QPushButton::clicked, ++ [this] ( ) { ++ userPassword =! userPassword; ++ if(userPassword){ ++ userButton->setIcon(sIcon); ++ ui->textBoxUserPassword->setEchoMode(QLineEdit::Normal); ++ } else { ++ userButton->setIcon(hIcon); ++ ui->textBoxUserPassword->setEchoMode(QLineEdit::Password); ++ } ++ }); ++ connect(userVertifyButton,&QPushButton::clicked, [this](){ ++ userVertifyPassword =! userVertifyPassword; ++ if(userVertifyPassword){ ++ userVertifyButton->setIcon(sIcon); ++ ui->textBoxUserVerifiedPassword->setEchoMode(QLineEdit::Normal); ++ } else { ++ userVertifyButton->setIcon(hIcon); ++ ui->textBoxUserVerifiedPassword->setEchoMode(QLineEdit::Password); ++ } ++ }); ++ connect(rootButton,&QPushButton::clicked, [this](){ ++ rootPassword =! rootPassword; ++ if(rootPassword){ ++ rootButton->setIcon(sIcon); ++ ui->textBoxRootPassword->setEchoMode(QLineEdit::Normal); ++ } else { ++ rootButton->setIcon(hIcon); ++ ui->textBoxRootPassword->setEchoMode(QLineEdit::Password); ++ } ++ }); ++ connect(rootVertifyButton,&QPushButton::clicked, [this](){ ++ rootVertifyPassword =! rootVertifyPassword; ++ if(rootVertifyPassword){ ++ rootVertifyButton->setIcon(sIcon); ++ ui->textBoxVerifiedRootPassword->setEchoMode(QLineEdit::Normal); ++ } else { ++ rootVertifyButton->setIcon(hIcon); ++ ui->textBoxVerifiedRootPassword->setEchoMode(QLineEdit::Password); ++ } ++ }); ++ ++ + // Connect signals and slots + ui->textBoxUserPassword->setText( config->userPassword() ); + connect( ui->textBoxUserPassword, &QLineEdit::textChanged, config, &Config::setUserPassword ); +diff --git a/src/modules/users/UsersPage.h b/src/modules/users/UsersPage.h +index 379176a..fcee0f0 100644 +--- a/src/modules/users/UsersPage.h ++++ b/src/modules/users/UsersPage.h +@@ -17,6 +17,10 @@ + #define USERSPAGE_H + + #include ++#include ++#include ++#include ++ + + class Config; + +@@ -51,6 +55,17 @@ private: + + Ui::Page_UserSetup* ui; + Config* m_config; ++ bool userPassword; ++ bool userVertifyPassword; ++ bool rootPassword; ++ bool rootVertifyPassword; ++ QIcon hIcon; ++ QIcon sIcon; ++ QPushButton* userButton; ++ QPushButton* userVertifyButton; ++ QPushButton* rootButton; ++ QPushButton* rootVertifyButton; ++ QString imagePath="/usr/share/calamares/branding/default/"; + }; + + #endif // USERSPAGE_H +diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp +index 471187b..88f38c2 100644 +--- a/src/modules/welcome/WelcomePage.cpp ++++ b/src/modules/welcome/WelcomePage.cpp +@@ -91,7 +91,21 @@ WelcomePage::WelcomePage( Config* config, QWidget* parent ) + } + + void +-WelcomePage::init(){} ++WelcomePage::init() ++{ ++ //setup the url buttons ++ // setupButton( WelcomePage::Button::Support, m_conf->supportUrl() ); ++ // setupButton( WelcomePage::Button::KnownIssues, m_conf->knownIssuesUrl() ); ++ // setupButton( WelcomePage::Button::ReleaseNotes, m_conf->releaseNotesUrl() ); ++ // setupButton( WelcomePage::Button::Donate, m_conf->donateUrl() ); ++ ++ //language icon ++ // auto icon = Calamares::Branding::instance()->image( m_conf->languageIcon(), QSize( 48, 48 ) ); ++ // if ( !icon.isNull() ) ++ // { ++ // setLanguageIcon( icon ); ++ // } ++} + + void + WelcomePage::initLanguages() +@@ -111,6 +125,57 @@ WelcomePage::initLanguages() + &Config::setLocaleIndex ); + } + ++// void ++// WelcomePage::setupButton( Button role, const QString& url ) ++// { ++// QPushButton* button = nullptr; ++// Calamares::ImageType icon = Calamares::Information; ++ ++// switch ( role ) ++// { ++// case Button::Donate: ++// button = ui->donateButton; ++// icon = Calamares::Donate; ++// break; ++// case Button::KnownIssues: ++// button = ui->knownIssuesButton; ++// icon = Calamares::Bugs; ++// break; ++// case Button::ReleaseNotes: ++// button = ui->releaseNotesButton; ++// icon = Calamares::Release; ++// break; ++// case Button::Support: ++// button = ui->supportButton; ++// icon = Calamares::Help; ++// break; ++// } ++// if ( !button ) ++// { ++// cWarning() << "Unknown button role" << smash( role ); ++// return; ++// } ++ ++// if ( url.isEmpty() ) ++// { ++// button->hide(); ++// return; ++// } ++ ++// QUrl u( url ); ++// if ( u.isValid() ) ++// { ++// auto size = 2 * QSize( Calamares::defaultFontHeight(), Calamares::defaultFontHeight() ); ++// button->setIcon( Calamares::defaultPixmap( icon, Calamares::Original, size ) ); ++// connect( button, &QPushButton::clicked, [ u ]() { QDesktopServices::openUrl( u ); } ); ++// } ++// else ++// { ++// cWarning() << "Welcome button" << smash( role ) << "URL" << url << "is invalid."; ++// button->hide(); ++// } ++// } ++ + void + WelcomePage::focusInEvent( QFocusEvent* e ) + { +@@ -136,6 +201,11 @@ WelcomePage::externallySelectedLanguage( int row ) + } + } + ++// void ++// WelcomePage::setLanguageIcon( QPixmap i ) ++// { ++// ui->languageIcon->setPixmap( i ); ++// } + + void + WelcomePage::retranslate() +@@ -144,6 +214,8 @@ WelcomePage::retranslate() + + ui->mainText->setText( message.arg( Calamares::Branding::instance()->versionedName() ) ); + ui->retranslateUi( this ); ++ // ui->supportButton->setText( ++ // tr( "%1 Support", "@action" ).arg( Calamares::Branding::instance()->shortProductName() ) ); + } + + void +diff --git a/src/modules/welcome/welcome.qrc b/src/modules/welcome/welcome.qrc +index d338d73..7182a4d 100644 +--- a/src/modules/welcome/welcome.qrc ++++ b/src/modules/welcome/welcome.qrc +@@ -1,6 +1,5 @@ + + +- + WelcomePage.cpp + language-icon-128px.png + language-icon-48px.png +-- +2.46.0 + diff --git a/0014-setRepoSource.patch b/0014-setRepoSource.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6c5409edbf6147cd666bcebca392698390b037c --- /dev/null +++ b/0014-setRepoSource.patch @@ -0,0 +1,180 @@ +From 74d4000b332446b18145737929b8c517e6cb908a Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Wed, 8 Jan 2025 23:38:02 +0800 +Subject: [PATCH] =?UTF-8?q?netinstall/ISO=E9=95=9C=E5=83=8F=E5=88=87?= + =?UTF-8?q?=E6=8D=A2repo=E6=BA=90?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +磁盘自动分区清理 + +磁盘自动分区清理 + +更改主机名称 + +删除多余补丁 +--- + src/modules/packages/main.py | 5 +++++ + src/modules/partition/core/PartitionCoreModule.cpp | 2 +- + src/modules/partition/jobs/ClearMountsJob.cpp | 14 ++++++++++---- + src/modules/partition/jobs/ClearMountsJob.h | 4 +++- + src/modules/unpackfs/main.py | 14 +++++++++++++- + src/modules/users/users.conf | 2 +- + 6 files changed, 33 insertions(+), 8 deletions(-) + +diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py +index 2c6e6adb4..030455cd0 100644 +--- a/src/modules/packages/main.py ++++ b/src/modules/packages/main.py +@@ -17,6 +17,7 @@ + import abc + from string import Template + import subprocess ++import os + + import libcalamares + from libcalamares.utils import check_target_env_call, target_env_call +@@ -905,6 +906,10 @@ def run(): + else: + options.append(option) + ++ if os.path.exists("/etc/yum.repos.d/local.repo"): ++ options.append("--disablerepo=*") ++ options.append("--enablerepo=local-repo") ++ + for entry in operations: + group_packages = 0 + libcalamares.utils.debug(pretty_name()) +diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp +index 51e99f2d2..59973b798 100644 +--- a/src/modules/partition/core/PartitionCoreModule.cpp ++++ b/src/modules/partition/core/PartitionCoreModule.cpp +@@ -676,7 +676,7 @@ PartitionCoreModule::jobs( const Config* config ) const + { + if ( info->isDirty() ) + { +- auto* job = new ClearMountsJob( info->device.data() ); ++ auto* job = new ClearMountsJob( info->device.data(), config ); + job->setMapperExceptions( doNotClose ); + lst << Calamares::job_ptr( job ); + } +diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp +index d36c4e512..113bff826 100644 +--- a/src/modules/partition/jobs/ClearMountsJob.cpp ++++ b/src/modules/partition/jobs/ClearMountsJob.cpp +@@ -17,6 +17,7 @@ + #include "partition/Sync.h" + #include "utils/Logger.h" + #include "utils/String.h" ++#include "Config.h" + + // KPMcore + #include +@@ -399,9 +400,10 @@ stringify( const QList< MessageAndPath >& news ) + return l; + } + +-ClearMountsJob::ClearMountsJob( Device* device ) ++ClearMountsJob::ClearMountsJob( Device* device, const Config* config ) + : Calamares::Job() + , m_deviceNode( device->deviceNode() ) ++ , m_config( config ) + { + } + +@@ -425,14 +427,18 @@ ClearMountsJob::exec() + QList< MessageAndPath > goodNews; + + apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); +- apply( getLVMVolumes(), tryClearLVM, goodNews ); ++ apply( getLVMVolumes(), tryUmount, goodNews ); + apply( getPVGroups( deviceName ), tryVGDisable, goodNews ); + + apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); + apply( getPartitionsForDevice( deviceName ), tryUmount, goodNews ); + apply( getSwapsForDevice( m_deviceNode ), tryClearSwap, goodNews ); +- diskClear(deviceName); +- mpathClear(deviceName); ++ auto choice = m_config -> installChoice(); ++ if(choice == Config::InstallChoice::Erase){ ++ apply( getLVMVolumes(), tryClearLVM, goodNews ); ++ diskClear(deviceName); ++ mpathClear(deviceName); ++ } + + Calamares::JobResult ok = Calamares::JobResult::ok(); + ok.setMessage( tr( "Cleared all mounts for %1" ).arg( m_deviceNode ) ); +diff --git a/src/modules/partition/jobs/ClearMountsJob.h b/src/modules/partition/jobs/ClearMountsJob.h +index fb3aca1e4..992779d73 100644 +--- a/src/modules/partition/jobs/ClearMountsJob.h ++++ b/src/modules/partition/jobs/ClearMountsJob.h +@@ -11,6 +11,7 @@ + #define CLEARMOUNTSJOB_H + + #include "Job.h" ++#include "Config.h" + + class Device; + +@@ -42,7 +43,7 @@ public: + * No ownership is transferred; the @p device is used only to access + * the device node (name). + */ +- explicit ClearMountsJob( Device* device ); ++ explicit ClearMountsJob( Device* device, const Config* config ); + + QString prettyName() const override; + QString prettyStatusMessage() const override; +@@ -54,6 +55,7 @@ public: + private: + const QString m_deviceNode; + QStringList m_mapperExceptions; ++ const Config* m_config; + }; + + #endif // CLEARMOUNTSJOB_H +diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py +index 7db5f2ea6..9237eb58e 100644 +--- a/src/modules/unpackfs/main.py ++++ b/src/modules/unpackfs/main.py +@@ -275,10 +275,22 @@ def file_copy(source, entry, progress_cb): + libcalamares.utils.host_env_process_output(["cp", "-af", "/etc/add_selinux_policy.sh", entry.destination + "/etc/add_selinux_policy.sh"], output_cb) + libcalamares.utils.host_env_process_output(["chmod", "+x", entry.destination + "/etc/add_selinux_policy.sh"], output_cb) + ++ ++ rpm_package_path = "/run/initramfs/live/Packages" ++ if os.path.exists(rpm_package_path): ++ repo_source_file = "/etc/yum.repos.d/local.repo" ++ repo_file_content = "[local-repo]\nname=local\nbaseurl=file:///run/initramfs/live\nenabled=1\ngpgcheck=0" ++ libcalamares.utils.host_env_process_output(["mkdir", "-p", "/etc/yum.repos.d/"], output_cb) ++ libcalamares.utils.host_env_process_output(["touch", repo_source_file], output_cb) ++ with open(repo_source_file,'w') as file: ++ subprocess.run(['echo', '-e', repo_file_content], stdout = file) ++ ++ ++ + completed_packages = 0 + if os.path.exists("/etc/yum.repos.d/local.repo"): + libcalamares.utils.host_env_process_output( +- ["cp", "-af", "/etc/yum.repos.d/local.repo", entry.destination + "/etc/yum.repos.d/"], output_cb) ++ ["cp", "-af", "/etc/yum.repos.d/local.repo", entry.destination + "/etc/yum.repos.d/local.repo"], output_cb) + + if arch == "aarch64": + packages = ["yum", "grub2-efi", "passwd", "sudo"] +diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf +index 57a82ddc9..6cb0f79bb 100644 +--- a/src/modules/users/users.conf ++++ b/src/modules/users/users.conf +@@ -262,7 +262,7 @@ user: + hostname: + location: EtcFile + writeHostsFile: true +- template: "derp-${cpu}" ++ template: "DevStation" + forbidden_names: [ localhost ] + + # Enable Active Directory enrollment support (opt-in) +-- +2.46.0 + diff --git a/0015-requireDiskScan.patch b/0015-requireDiskScan.patch new file mode 100644 index 0000000000000000000000000000000000000000..59405430cad2e3556a06737cbe91281b58e726ef --- /dev/null +++ b/0015-requireDiskScan.patch @@ -0,0 +1,55 @@ +From c8c11d780cccabc463d2005ea28453df115f37bf Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Thu, 13 Feb 2025 00:03:51 +0800 +Subject: [PATCH] =?UTF-8?q?=E6=AC=A2=E8=BF=8E=E9=A1=B5=E7=B3=BB=E7=BB=9F?= + =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= + =?UTF-8?q?=E4=BF=AE=E8=AE=A2?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/modules/partition/core/DeviceList.cpp | 2 +- + src/modules/welcome/WelcomePage.cpp | 5 ++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp +index 188594963..666bb1833 100644 +--- a/src/modules/partition/core/DeviceList.cpp ++++ b/src/modules/partition/core/DeviceList.cpp +@@ -49,7 +49,7 @@ hasRootPartition( Device* device ) + static bool + isValidDevice(const QString& devicePath) + { +- auto result = Calamares::System::runCommand({ "blkid", devicePath }, std::chrono::seconds(30)); ++ auto result = Calamares::System::runCommand({ "lsblk" }, std::chrono::seconds(30)); + + return result.getExitCode() == 0 && !result.getOutput().isEmpty(); + } +diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp +index 88f38c256..bbbda8f68 100644 +--- a/src/modules/welcome/WelcomePage.cpp ++++ b/src/modules/welcome/WelcomePage.cpp +@@ -27,6 +27,7 @@ + #include "utils/Logger.h" + #include "utils/NamedEnum.h" + #include "utils/Retranslator.h" ++#include "utils/System.h" + + #include + #include +@@ -211,8 +212,10 @@ void + WelcomePage::retranslate() + { + const QString message = m_conf->genericWelcomeMessage(); ++ auto rse = Calamares::System::runCommand({"cat", "/etc/os-release"}, std::chrono::seconds(30)); ++ QString osVersion = rse.getOutput().split("PRETTY_NAME=\"")[1].split("\"\n")[0].replace(" ", "-"); + +- ui->mainText->setText( message.arg( Calamares::Branding::instance()->versionedName() ) ); ++ ui->mainText->setText( message.arg(osVersion) ); + ui->retranslateUi( this ); + // ui->supportButton->setText( + // tr( "%1 Support", "@action" ).arg( Calamares::Branding::instance()->shortProductName() ) ); +-- +2.46.0 + diff --git a/0016-DevStation-25.03-add-dependency.patch b/0016-DevStation-25.03-add-dependency.patch new file mode 100644 index 0000000000000000000000000000000000000000..7818615834c2d67d8965124e51c459415b5ac2c5 --- /dev/null +++ b/0016-DevStation-25.03-add-dependency.patch @@ -0,0 +1,36 @@ +From 42f778f81250c8871b4b3605e2146bcd6bbe8372 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Tue, 25 Feb 2025 22:11:20 +0800 +Subject: [PATCH] =?UTF-8?q?DevStation=E6=96=B0=E5=A2=9E25.03=E7=89=88?= + =?UTF-8?q?=E6=9C=AC=E4=BE=9D=E8=B5=96?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +增加gnome-keyring + +新增WIFI驱动包 + +增加gnome-shell-extension-dash-to-dock依赖 + +增加git +--- + src/modules/packagechooser/packagechooser.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index 3f356382e..cc88c71ef 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -165,7 +165,7 @@ items: + # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + # screenshot: ":/images/Plasma.png" + - id: gnome +- packages: [ checkpolicy, code, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts ] ++ packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, kmail-account-wizard, akonadi-import-wizard, akonadi-import-wizard-devel, pim-data-exporter, pim-data-exporter-libs, grantlee-editor-libs, grantlee-editor, polkit-qt5-1, polkit-qt5-1-devel, python3-kolabformat, java-kolabformat, libkolabxml, php-kolabformat, libkolabxml-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, kmail, kmail-libs, pim-sieve-editor, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, kdepim-runtime-libs, kdepim-runtime, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git] + name: DevStation + name[zh]: DevStation + description: GNU Networked Object Modeling Environment Desktop +-- +2.46.0 + diff --git a/0017-Devstation-25.03-fix-timezoneErrors.patch b/0017-Devstation-25.03-fix-timezoneErrors.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a7270e3166109ae9f37e9c9fb4aeb5e0ca63f80 --- /dev/null +++ b/0017-Devstation-25.03-fix-timezoneErrors.patch @@ -0,0 +1,139 @@ +From 42591e54c5fd8b4491fb81dcdb5ade3a0caa46aa Mon Sep 17 00:00:00 2001 +From: lizixin <2271170409@qq.com> +Date: Mon, 10 Mar 2025 11:31:39 +0800 +Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=89=E8=A3=85=E7=A8=8B?= + =?UTF-8?q?=E5=BA=8F=E7=89=88=E6=9C=AC=E5=8F=B7=E6=98=BE=E7=A4=BA=E9=97=AE?= + =?UTF-8?q?=E9=A2=98?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + CMakeLists.txt | 4 ++++ + src/branding/default/branding.desc | 4 ++-- + src/modules/partition/gui/ChoicePage.cpp | 20 +++++++++++--------- + 3 files changed, 17 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 40ae7e052..9e54345ee 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -686,6 +686,10 @@ install(FILES calamares.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/application + + install(FILES man/calamares.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/) + ++install(FILES lang/tz_zh_CN.ts DESTINATION /usr/share/calamares) ++ ++install(FILES lang/tz_zh_TW.ts DESTINATION /usr/share/calamares) ++ + if(INSTALL_CONFIG) + install(FILES settings.conf DESTINATION share/calamares) + endif() +diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc +index 9f0843385..412252678 100644 +--- a/src/branding/default/branding.desc ++++ b/src/branding/default/branding.desc +@@ -125,8 +125,8 @@ strings: + shortProductName: Generic + version: 24.09 + shortVersion: 24.09 +- versionedName: openEuler-24.09 +- shortVersionedName: openEuler 24.09 ++ versionedName: openEuler-25.03 ++ shortVersionedName: openEuler 25.03 + bootloaderEntryName: openEuler + productUrl: https://openeuler.org/ + supportUrl: null +diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp +index 6185d3ff5..e5fc25870 100644 +--- a/src/modules/partition/gui/ChoicePage.cpp ++++ b/src/modules/partition/gui/ChoicePage.cpp +@@ -41,6 +41,7 @@ + #include "utils/Retranslator.h" + #include "utils/Units.h" + #include "widgets/PrettyRadioButton.h" ++#include "utils/System.h" + + #include + #include +@@ -1272,7 +1273,8 @@ void + ChoicePage::setupActions() + { + Logger::Once o; +- ++ auto rse = Calamares::System::runCommand({"cat", "/etc/os-release"}, std::chrono::seconds(30)); ++ QString osVersion = rse.getOutput().split("PRETTY_NAME=\"")[1].split("\"\n")[0].replace(" ", "-"); + Device* currentDevice = selectedDevice(); + OsproberEntryList osproberEntriesForCurrentDevice = getOsproberEntriesForDevice( currentDevice ); + +@@ -1350,11 +1352,11 @@ ChoicePage::setupActions() + + m_alongsideButton->setText( tr( "Install alongside
" + "The installer will shrink a partition to make room for %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ++ .arg( osVersion ) ); + + m_replaceButton->setText( tr( "Replace a partition
" + "Replaces a partition with %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); ++ .arg( osVersion ) ); ); + + m_replaceButton->hide(); + m_alongsideButton->hide(); +@@ -1379,7 +1381,7 @@ ChoicePage::setupActions() + + m_alongsideButton->setText( tr( "Install alongside
" + "The installer will shrink a partition to make room for %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ++ .arg( osVersion ) ); + + m_eraseButton->setText( tr( "Automatic partitioning
" + "This will delete all data " +@@ -1387,7 +1389,7 @@ ChoicePage::setupActions() + + m_replaceButton->setText( tr( "Replace a partition
" + "Replaces a partition with %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); ++ .arg( osVersion ) ); ); + } + else + { +@@ -1400,7 +1402,7 @@ ChoicePage::setupActions() + + m_alongsideButton->setText( tr( "Install alongside
" + "The installer will shrink a partition to make room for %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ++ .arg( osVersion ) ); + + m_eraseButton->setText( tr( "Automatic partitioning
" + "This will delete all data " +@@ -1408,7 +1410,7 @@ ChoicePage::setupActions() + + m_replaceButton->setText( tr( "Replace a partition
" + "Replaces a partition with %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); ++ .arg( osVersion ) ); ); + } + } + else +@@ -1425,7 +1427,7 @@ ChoicePage::setupActions() + + m_alongsideButton->setText( tr( "Install alongside
" + "The installer will shrink a partition to make room for %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ++ .arg( osVersion ) ); + + m_eraseButton->setText( tr( "Automatic partitioning
" + "This will delete all data " +@@ -1433,7 +1435,7 @@ ChoicePage::setupActions() + + m_replaceButton->setText( tr( "Replace a partition
" + "Replaces a partition with %1." ) +- .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); ++ .arg( osVersion ) ); ); + } + + #ifdef DEBUG_PARTITION_UNSAFE +-- +2.46.0 + diff --git a/0018-fix-desktop-icon-show.patch b/0018-fix-desktop-icon-show.patch new file mode 100644 index 0000000000000000000000000000000000000000..34abc9ee25ab4f2418e7a49c760a5d754f169d62 --- /dev/null +++ b/0018-fix-desktop-icon-show.patch @@ -0,0 +1,56 @@ +From 2cf8070d333fbadecd5b94da06ad7432ebaeba94 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Thu, 6 Mar 2025 08:28:38 +0800 +Subject: [PATCH] fix desktop-icon-show + +--- + calamares.desktop | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/calamares.desktop b/calamares.desktop +index b0d6c2753..072a4e2c9 100644 +--- a/calamares.desktop ++++ b/calamares.desktop +@@ -7,7 +7,7 @@ Keywords=calamares;system;installer; + TryExec=calamares + Exec=sh -c "pkexec calamares -style Adwaita" + Comment=Calamares — System Installer +-Icon=/usr/share/applications/openEuler.png ++Icon=/usr/share/calamares/branding/default/openEuler-icon.png + Terminal=false + StartupNotify=true + Categories=Qt;System; +@@ -66,7 +66,7 @@ Icon[el]=calamares + GenericName[el]=Εγκατάσταση συστήματος + Comment[el]=Calamares — Εγκατάσταση συστήματος + Name[en_GB]=Install System +-Icon[en_GB]=/usr/share/applications/openEuler.png ++Icon[en_GB]=/usr/share/calamares/branding/default/openEuler-icon.png + GenericName[en_GB]=System Installer + Comment[en_GB]=Calamares — System Installer + Name[eo]=Instali Sistemo +@@ -226,7 +226,7 @@ Icon[tr_TR]=calamares + GenericName[tr_TR]=Sistem Yükleyici + Comment[tr_TR]=Calamares — Sistem Yükleyici + Name[uk]=Встановити Систему +-Icon[uk]=/usr/share/applications/openEuler.png ++Icon[uk]=/usr/share/calamares/branding/default/openEuler-icon.png + GenericName[uk]=Встановлювач системи + Comment[uk]=Calamares - Встановлювач системи + Name[vi]=Cài đặt hệ thống +@@ -234,10 +234,10 @@ Icon[vi]=calamares + GenericName[vi]=Bộ cài đặt hệ thống + Comment[vi]=Calamares — Bộ cài đặt hệ thống + Name[zh_CN]=安装系统 +-Icon[zh_CN]=/usr/share/applications/openEuler.png ++Icon[zh_CN]=/usr/share/calamares/branding/default/openEuler-icon.png + GenericName[zh_CN]=系统安装程序 + Comment[zh_CN]=Calamares — 系统安装程序 + Name[zh_TW]=安裝系統 +-Icon[zh_TW]=/usr/share/applications/openEuler.png ++Icon[zh_TW]=/usr/share/calamares/branding/default/openEuler-icon.png + GenericName[zh_TW]=系統安裝程式 + Comment[zh_TW]=Calamares ── 系統安裝程式 +-- +2.46.0 + diff --git a/0019-add-email-tool.patch b/0019-add-email-tool.patch new file mode 100644 index 0000000000000000000000000000000000000000..dfa02e44c5e570c74c07a09d3adc7f2074ae8c75 --- /dev/null +++ b/0019-add-email-tool.patch @@ -0,0 +1,30 @@ +From 3520f763ec73798e9f9f42ebfa144564007eaaed Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Thu, 6 Mar 2025 17:11:16 +0800 +Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BE=E7=BD=AE=E6=97=B6?= + =?UTF-8?q?=E5=8C=BA=E4=BE=9D=E8=B5=96?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +集成thunderbird邮箱工具 +--- + src/modules/packagechooser/packagechooser.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index cc88c71ef..30525e3f9 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -165,7 +165,7 @@ items: + # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + # screenshot: ":/images/Plasma.png" + - id: gnome +- packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, kmail-account-wizard, akonadi-import-wizard, akonadi-import-wizard-devel, pim-data-exporter, pim-data-exporter-libs, grantlee-editor-libs, grantlee-editor, polkit-qt5-1, polkit-qt5-1-devel, python3-kolabformat, java-kolabformat, libkolabxml, php-kolabformat, libkolabxml-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, kmail, kmail-libs, pim-sieve-editor, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, kdepim-runtime-libs, kdepim-runtime, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git] ++ packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, polkit-qt5-1, polkit-qt5-1-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git, thunderbird, autogen, ntp, timedatex, chrony] + name: DevStation + name[zh]: DevStation + description: GNU Networked Object Modeling Environment Desktop +-- +2.46.0 + diff --git a/0020-aboutPage-release-version-problem.patch b/0020-aboutPage-release-version-problem.patch new file mode 100644 index 0000000000000000000000000000000000000000..384f45c41607f30d0d53d2c93743f2574af54cf1 --- /dev/null +++ b/0020-aboutPage-release-version-problem.patch @@ -0,0 +1,142 @@ +From 104600c18bcc37e509c9059925963b1ff2da83be Mon Sep 17 00:00:00 2001 +From: lizixin <2271170409@qq.com> +Date: Thu, 13 Mar 2025 15:02:00 +0800 +Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=87=AA=E6=B5=8B=E9=97=AE?= + =?UTF-8?q?=E9=A2=98?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/libcalamares/CalamaresAbout.cpp | 117 ++++++++++++---------------- + 1 file changed, 51 insertions(+), 66 deletions(-) + +diff --git a/src/libcalamares/CalamaresAbout.cpp b/src/libcalamares/CalamaresAbout.cpp +index 65a1b9d33..11a628463 100644 +--- a/src/libcalamares/CalamaresAbout.cpp ++++ b/src/libcalamares/CalamaresAbout.cpp +@@ -7,69 +7,54 @@ + * + */ + +-#include "CalamaresAbout.h" +- +-#include "CalamaresVersionX.h" +- +-#include +- +-static const char s_header[] +- = QT_TRANSLATE_NOOP( "AboutData", "

Release:%1


" ); +- +-static const char s_footer[] +- = QT_TRANSLATE_NOOP( "AboutData", +- "Thanks to the openEuler team."); +- +-struct Maintainer +-{ +- unsigned int start; +- unsigned int end; +- const char* name; +- const char* email; +- QString text() const +- { +- //: Copyright year-year Name +- return QCoreApplication::translate( "AboutData", "Copyright %1-%2 %3 <%4>
" ) +- .arg( start ) +- .arg( end ) +- .arg( name ) +- .arg( email ); +- } +-}; +- +-static constexpr const Maintainer maintainers[] = { +- // { 2014, 2017, "Teo Mrnjavac", "teo@kde.org" }, +- // { 2017, 2022, "Adriaan de Groot", "groot@kde.org" }, +- // { 2022, 2024, "Adriaan de Groot (community)", "groot@kde.org" }, +-}; +- +-static QString +-aboutMaintainers() +-{ +- QStringList s; +- for ( const auto& m : maintainers ) +- { +- s.append( m.text() ); +- } +- return s.join( QString() ); +-} +- +-static QString +-substituteVersions( const QString& s ) +-{ +- return s.arg( "openEuler-24.09" ).arg(""); +-} +- +-const QString +-Calamares::aboutString() +-{ +- return substituteVersions( QCoreApplication::translate( "AboutData", s_header ) ) + aboutMaintainers() +- + QCoreApplication::translate( "AboutData", s_footer ); +- // return aboutMaintainers()+ QCoreApplication::translate( "AboutData", s_footer ); +-} +- +-const QString +-Calamares::aboutStringUntranslated() +-{ +- return substituteVersions( QString( s_header ) ) + aboutMaintainers() + QString( s_footer ); +-} ++ #include "CalamaresAbout.h" ++ ++ #include "CalamaresVersionX.h" ++ ++ #include "utils/System.h" ++ ++ #include ++ ++ static const char s_header[] ++ = QT_TRANSLATE_NOOP( "AboutData", "

Release:%1


" ); ++ ++ static const char s_footer[] ++ = QT_TRANSLATE_NOOP( "AboutData", ++ "Thanks to the openEuler team."); ++ ++ struct Maintainer ++ { ++ unsigned int start; ++ unsigned int end; ++ const char* name; ++ const char* email; ++ QString text() const ++ { ++ return QCoreApplication::translate( "AboutData", "Copyright %1-%2 %3 <%4>
" ) ++ .arg( start ) ++ .arg( end ) ++ .arg( name ) ++ .arg( email ); ++ } ++ }; ++ ++ static QString ++ substituteVersions( const QString& s ) ++ { ++ auto rse = Calamares::System::runCommand({"cat", "/etc/os-release"}, std::chrono::seconds(30)); ++ QString osVersion = rse.getOutput().split("PRETTY_NAME=\"")[1].split("\"\n")[0].replace(" ", "-"); ++ return s.arg( osVersion ).arg(""); ++ } ++ ++ const QString ++ Calamares::aboutString() ++ { ++ return substituteVersions( QCoreApplication::translate( "AboutData", s_header ) ) + QCoreApplication::translate( "AboutData", s_footer ); ++ } ++ ++ const QString ++ Calamares::aboutStringUntranslated() ++ { ++ return substituteVersions( QString( s_header ) ) + QString( s_footer ); ++ } ++ +\ No newline at end of file +-- +2.46.0 + diff --git a/0021-aarch64-start-desktop-failed.patch b/0021-aarch64-start-desktop-failed.patch new file mode 100644 index 0000000000000000000000000000000000000000..a2ae96f6d2d47fc9b45da16b8f4490aa9a44d026 --- /dev/null +++ b/0021-aarch64-start-desktop-failed.patch @@ -0,0 +1,52 @@ +From 22ee37f127f197d60ed461be5493bc1e5f139325 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Fri, 7 Mar 2025 08:26:01 +0800 +Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9aarch64=E5=90=AF=E5=8A=A8?= + =?UTF-8?q?=E8=BF=9B=E5=85=A5=E6=A1=8C=E9=9D=A2=E5=A4=B1=E8=B4=A5=E9=97=AE?= + =?UTF-8?q?=E9=A2=98?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/modules/packages/main.py | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py +index 030455cd0..91c627a9d 100644 +--- a/src/modules/packages/main.py ++++ b/src/modules/packages/main.py +@@ -18,6 +18,7 @@ import abc + from string import Template + import subprocess + import os ++import platform + + import libcalamares + from libcalamares.utils import check_target_env_call, target_env_call +@@ -765,10 +766,18 @@ def handle_packagechooser(): + :param entry: dict + The operation entry to process. + """ +- item = { +- "pre-script": "", +- "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target"] +- } ++ cpu_type = platform.machine() ++ if cpu_type == "aarch64": ++ item = { ++ "pre-script": "", ++ "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target", "/usr/bin/chcon -t bin_t /etc/gdm/PreSession/Default"] ++ } ++ else: ++ item = { ++ "pre-script": "", ++ "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target"] ++ } ++ + return item + + +-- +2.46.0 + diff --git a/0022-add-gnome-user-docs-dependency.patch b/0022-add-gnome-user-docs-dependency.patch new file mode 100644 index 0000000000000000000000000000000000000000..bce580501a83d12feea59f56325da6909d48b0fe --- /dev/null +++ b/0022-add-gnome-user-docs-dependency.patch @@ -0,0 +1,29 @@ +From 5ab9b7179dbc05ef0ab526a40b1049706b262f35 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Wed, 12 Mar 2025 00:35:15 +0800 +Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Egnome-user-docs=E3=80=81gnome?= + =?UTF-8?q?-doc-utils=E3=80=81yelp-tools=E4=BE=9D=E8=B5=96?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/modules/packagechooser/packagechooser.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index 30525e3f9..40b1ac6d7 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -165,7 +165,7 @@ items: + # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + # screenshot: ":/images/Plasma.png" + - id: gnome +- packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, polkit-qt5-1, polkit-qt5-1-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git, thunderbird, autogen, ntp, timedatex, chrony] ++ packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, polkit-qt5-1, polkit-qt5-1-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git, thunderbird, autogen, ntp, timedatex, chrony, gnome-user-docs, gnome-doc-utils, yelp-tools] + name: DevStation + name[zh]: DevStation + description: GNU Networked Object Modeling Environment Desktop +-- +2.46.0 + diff --git a/0023-add-module-dependency.patch b/0023-add-module-dependency.patch new file mode 100644 index 0000000000000000000000000000000000000000..f86633f3794dc36b0974d983c4a9fae7e5d3c753 --- /dev/null +++ b/0023-add-module-dependency.patch @@ -0,0 +1,35 @@ +From 0f054a57ecf2f04fe72f3d481b7d8b955e00934f Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Thu, 13 Mar 2025 00:14:28 +0800 +Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9B=B4=E6=96=B0module=20de?= + =?UTF-8?q?pendency=20=E7=9A=84=E8=84=9A=E6=9C=AC?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/modules/packages/main.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py +index 91c627a9d..b2aff1e4d 100644 +--- a/src/modules/packages/main.py ++++ b/src/modules/packages/main.py +@@ -770,12 +770,12 @@ def handle_packagechooser(): + if cpu_type == "aarch64": + item = { + "pre-script": "", +- "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target", "/usr/bin/chcon -t bin_t /etc/gdm/PreSession/Default"] ++ "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target", "/usr/bin/chcon -t bin_t /etc/gdm/PreSession/Default", "depmod"] + } + else: + item = { + "pre-script": "", +- "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target"] ++ "post-script": ["/bin/bash /etc/add_selinux_policy.sh", "systemctl enable gdm", "systemctl set-default graphical.target", "depmod"] + } + + return item +-- +2.46.0 + diff --git a/0024-add-mcp-server-dependency.patch b/0024-add-mcp-server-dependency.patch new file mode 100644 index 0000000000000000000000000000000000000000..75d3d05d01b6ee0dda5e8171034905c013da52c6 --- /dev/null +++ b/0024-add-mcp-server-dependency.patch @@ -0,0 +1,29 @@ +From 7ff5081c5d11377954cadca12f997d632bb5ebed Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Tue, 18 Mar 2025 08:42:58 +0800 +Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0roo-code,=20uv,=20python3-mcp?= + =?UTF-8?q?=E5=8C=85?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/modules/packagechooser/packagechooser.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf +index 40b1ac6d7..52a96336a 100644 +--- a/src/modules/packagechooser/packagechooser.conf ++++ b/src/modules/packagechooser/packagechooser.conf +@@ -165,7 +165,7 @@ items: + # description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + # screenshot: ":/images/Plasma.png" + - id: gnome +- packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, polkit-qt5-1, polkit-qt5-1-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git, thunderbird, autogen, ntp, timedatex, chrony, gnome-user-docs, gnome-doc-utils, yelp-tools] ++ packages: [ checkpolicy, dejavu-fonts, liberation-fonts, gnome-shell, gnome-session, gnome-terminal, gnome-software, gnome-menus, nautilus, xdg-utils, google-droid-sans-fonts, google-noto-fonts-common, google-noto-sans-arabic-vf-fonts, google-noto-sans-armenian-vf-fonts, google-noto-sans-bengali-vf-fonts, google-noto-sans-canadian-aboriginal-vf-fonts, google-noto-sans-cherokee-vf-fonts, google-noto-sans-devanagari-vf-fonts, google-noto-sans-ethiopic-vf-fonts, google-noto-sans-georgian-vf-fonts, google-noto-sans-hebrew-vf-fonts, google-noto-sans-kannada-vf-fonts, google-noto-sans-khmer-vf-fonts, google-noto-sans-lao-vf-fonts, google-noto-sans-math-fonts, google-noto-sans-mono-vf-fonts, google-noto-sans-sinhala-vf-fonts, google-noto-sans-symbols2-fonts, google-noto-sans-symbols-vf-fonts, google-noto-sans-tamil-vf-fonts, google-noto-sans-thaana-vf-fonts, google-noto-sans-thai-vf-fonts, google-noto-sans-vf-fonts, google-noto-serif-armenian-vf-fonts, google-noto-serif-ethiopic-vf-fonts, google-noto-serif-georgian-vf-fonts, google-noto-serif-gujarati-vf-fonts, google-noto-serif-gurmukhi-vf-fonts, google-noto-serif-hebrew-vf-fonts, google-noto-serif-kannada-vf-fonts, google-noto-serif-khmer-vf-fonts, google-noto-serif-lao-vf-fonts, google-noto-serif-sinhala-vf-fonts, google-noto-serif-tamil-vf-fonts, google-noto-serif-thai-vf-fonts, google-noto-serif-vf-fonts, gdm, ibus-libpinyin, webp-pixbuf-loader, firefox, devstation-config, wqy-zenhei-fonts, oeDevPlugin, rust-cbindgen, polkit-qt5-1, polkit-qt5-1-devel, oedp, kernel-extra-modules, epkg, euler-copilot-shell, vscodium, oegitext, kf5-kcalendarcore-devel, kf5-kcalendarcore, rust-ripgrep, xorg-x11-drv-*, linux-firmware-iwlwifi, linux-firmware-mediatek, gnome-keyring, gnome-keyring-pam, linux-firmware-ath, linux-firmware-cypress, linux-firmware-libertas, linux-firmware-mrvl, linux-firmware-netronome, linux-firmware-ti-connectivity, gnome-shell-extension-dash-to-dock, git, thunderbird, autogen, ntp, timedatex, chrony, gnome-user-docs, gnome-doc-utils, yelp-tools, roo-code, uv, python3-mcp, euler-copilot-desktop, dev-store, python3-django-rest-framework, tigervnc-server] + name: DevStation + name[zh]: DevStation + description: GNU Networked Object Modeling Environment Desktop +-- +2.46.0 + diff --git a/0025-get-os-release-version.patch b/0025-get-os-release-version.patch new file mode 100644 index 0000000000000000000000000000000000000000..5cc3dafbb3e8441d542429f036ae5fb1b05c2bc1 --- /dev/null +++ b/0025-get-os-release-version.patch @@ -0,0 +1,72 @@ +From f69963d210e516b707a8974a4d628147787926b9 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Fri, 2 May 2025 16:46:56 +0800 +Subject: [PATCH] get os release version + +--- + src/branding/default/branding.desc | 2 +- + src/calamares/CalamaresApplication.cpp | 28 ++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc +index 9f0843385..f4e6e2a7c 100644 +--- a/src/branding/default/branding.desc ++++ b/src/branding/default/branding.desc +@@ -121,7 +121,7 @@ navigation: widget + # are visible as buttons there if the corresponding *show* keys + # are set to "true" (they can also be overridden). + strings: +- productName: "${NAME}" ++ productName: @OS_VERSION@ + shortProductName: Generic + version: 24.09 + shortVersion: 24.09 +diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp +index 6b62fd67d..60cc815fc 100644 +--- a/src/calamares/CalamaresApplication.cpp ++++ b/src/calamares/CalamaresApplication.cpp +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + + /// @brief Convenience for "are the settings in debug mode" + static bool +@@ -158,6 +160,32 @@ CalamaresApplication::initQmlPath() + void + CalamaresApplication::initBranding() + { ++ ++ auto rse = Calamares::System::runCommand({"cat", "/etc/os-release"}, std::chrono::seconds(30)); ++ QString osVersion = rse.getOutput().split("PRETTY_NAME=\"")[1].split("\"\n")[0].replace(" ", "-"); ++ cDebug() << "osVersion is " << osVersion; ++ QFile descFile("/usr/share/calamares/branding/default/branding.desc"); ++ if (descFile.open(QIODevice::ReadOnly | QIODevice::Text)) { // 改为只读模式 ++ // 读取内容 ++ QTextStream inStream(&descFile); ++ QString content = inStream.readAll(); ++ descFile.close(); // 关闭文件 ++ ++ // 执行替换 ++ content.replace("@OS_VERSION@", osVersion); ++ ++ // 重新打开文件写入 ++ if (descFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { ++ QTextStream outStream(&descFile); ++ outStream << content; ++ descFile.close(); ++ } else { ++ qDebug() << "写入失败:" << descFile.errorString(); ++ } ++ } else { ++ qDebug() << "打开失败:" << descFile.errorString(); ++ } ++ + QString brandingComponentName = Calamares::Settings::instance()->brandingComponentName(); + if ( brandingComponentName.simplified().isEmpty() ) + { +-- +2.46.0 + diff --git a/0026-fix-ppt-picture-show-issue-and-set-release-version.patch b/0026-fix-ppt-picture-show-issue-and-set-release-version.patch new file mode 100644 index 0000000000000000000000000000000000000000..9b3e807e1d67fd9fe7bacfb983d7a036248463e8 --- /dev/null +++ b/0026-fix-ppt-picture-show-issue-and-set-release-version.patch @@ -0,0 +1,91 @@ +From bc26e3276a6e82b6e523d1af5837cb725dfba2c3 Mon Sep 17 00:00:00 2001 +From: lw520203 <1823363429@qq.com> +Date: Sat, 3 May 2025 10:02:09 +0800 +Subject: [PATCH] resolve PPT pictures show issue + +--- + src/branding/default/branding.desc | 8 ++++---- + src/branding/default/show.qml | 24 +++++++++++------------- + 2 files changed, 15 insertions(+), 17 deletions(-) + +diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc +index 2a9f640dd..91542662f 100644 +--- a/src/branding/default/branding.desc ++++ b/src/branding/default/branding.desc +@@ -123,10 +123,10 @@ navigation: widget + strings: + productName: @OS_VERSION@ + shortProductName: Generic +- version: 24.09 +- shortVersion: 24.09 +- versionedName: openEuler-25.03 +- shortVersionedName: openEuler 25.03 ++ version: @OS_VERSION@ ++ shortVersion: @OS_VERSION@ ++ versionedName: @OS_VERSION@ ++ shortVersionedName: @OS_VERSION@ + bootloaderEntryName: openEuler + productUrl: https://openeuler.org/ + supportUrl: null +diff --git a/src/branding/default/show.qml b/src/branding/default/show.qml +index f91d520cd..4551a8838 100644 +--- a/src/branding/default/show.qml ++++ b/src/branding/default/show.qml +@@ -14,6 +14,7 @@ import calamares.slideshow 1.0; + Presentation + { + id: presentation ++ anchors.fill: parent + + function nextSlide() { + console.log("QML Component (default slideshow) Next slide"); +@@ -29,36 +30,33 @@ Presentation + } + + Slide { +- id: slide1 ++ id: slide1 ++ anchors.fill: parent + Image { + id: background1 + source: "Slide1.png" +- width: 980; height: 980 +- fillMode: Image.PreserveAspectFit +- anchors.horizontalCenter:parent.horizontalCenter +- y:parent.height / 2 - height / 2 -25 ++ fillMode: Image.Stretch ++ anchors.fill: parent + } + } + Slide { + id: slide2 ++ anchors.fill: parent + Image { + id: background2 + source: "Slide2.png" +- width: 980; height: 980 +- fillMode: Image.PreserveAspectFit +- anchors.horizontalCenter:parent.horizontalCenter +- y:parent.height / 2 - height / 2 -25 ++ fillMode: Image.Stretch ++ anchors.fill: parent + } + } + Slide { + id: slide3 ++ anchors.fill: parent + Image { + id: background3 + source: "Slide3.png" +- width: 980; height: 980 +- fillMode: Image.PreserveAspectFit +- anchors.horizontalCenter:parent.horizontalCenter +- y:parent.height / 2 - height / 2 -25 ++ fillMode: Image.Stretch ++ anchors.fill: parent + } + } + // When this slideshow is loaded as a V1 slideshow, only +-- +2.46.0 + diff --git a/README.md b/README.md index 707e8ea4fd336eb26136a1ccbe9bbc515ca723ab..764379fde5a5e4c0850cddcf3c60cbaa5c7a55f9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +# 通知: 本项目已经正式迁移至 [AtomGit](https://atomgit.com/src-openeuler/calamares) 平台 # calamares #### 介绍 diff --git a/calamares.service b/calamares.service index 774f3f1bbadcc00b22c7cbb2d42fb1cd8a6747fe..c7f5ce1ed49baf8d2a2b0bb29be028aeddabbeb5 100644 --- a/calamares.service +++ b/calamares.service @@ -6,7 +6,8 @@ After=basic.target [Service] Type=simple ExecStartPre=/sbin/multipath -F -ExecStart=/usr/bin/calamares -style Adwaita +ExecStartPre=/usr/sbin/partprobe +ExecStart=/usr/bin/echo "DevStation System Installer" Restart=on-abort [Install] diff --git a/calamares.spec b/calamares.spec index 6c3665908cacebcd7e3fb62acc7ea3beba080243..22b1705c946aef6d0a649cbe0acb5e1ccdadf4c5 100644 --- a/calamares.spec +++ b/calamares.spec @@ -2,7 +2,7 @@ Name: calamares Version: 3.3.7 -Release: 1 +Release: 23 Summary: Installer from a live CD/DVD/USB to disk License: GPL-3.0-or-later @@ -38,7 +38,9 @@ Source16: information.svgz Source17: openEuler.png Source18: openEulerWord-blus.png Source19: openEulerWord.png - +Source20: openEuler-icon.png +Source21: password-hide.png +Source22: password-show.png # patch Patch0: 0001-branding-patch.patch Patch1: 0002-lang.patch @@ -49,9 +51,27 @@ Patch5: 0006-modules-file.patch Patch6: 0007-root.patch Patch7: 0008-progromTree.patch Patch8: 0009-qss.patch +Patch9: 0010-cDebugDelect.patch +Patch10: 0011-fix-87-position-and-translate.patch +Patch11: 0012-replace-icon.patch +Patch12: 0013-1230.patch +Patch13: 0014-setRepoSource.patch +Patch14: 0015-requireDiskScan.patch +Patch15: 0016-DevStation-25.03-add-dependency.patch +Patch16: 0017-Devstation-25.03-fix-timezoneErrors.patch +Patch17: 0018-fix-desktop-icon-show.patch +Patch18: 0019-add-email-tool.patch +Patch19: 0020-aboutPage-release-version-problem.patch +Patch20: 0021-aarch64-start-desktop-failed.patch +Patch21: 0022-add-gnome-user-docs-dependency.patch +Patch22: 0023-add-module-dependency.patch +Patch23: 0024-add-mcp-server-dependency.patch +Patch24: 0025-get-os-release-version.patch +Patch25: 0026-fix-ppt-picture-show-issue-and-set-release-version.patch + # Calamares is only supported where live images (and GRUB) are. (#1171380) # This list matches the arches where grub2-efi is used to boot the system -ExclusiveArch: %{ix86} x86_64 aarch64 riscv64 +ExclusiveArch: %{ix86} x86_64 aarch64 riscv64 loongarch64 # Macros BuildRequires: git-core @@ -213,6 +233,7 @@ mkdir -p %{_builddir}/calamares-3.3.7/data/images install -Dm 0644 %{SOURCE8} %{_builddir}/calamares-3.3.7/data/images/Biglogo.svgz install -Dm 0644 %{SOURCE9} %{_builddir}/calamares-3.3.7/data/images/Biglogo.svg install -Dm 0644 %{SOURCE16} %{_builddir}/calamares-3.3.7/data/images/information.svgz + mkdir -p %{_builddir}/calamares-3.3.7/src/modules/packagechooser/images install -Dm 0644 %{SOURCE10} %{_builddir}/calamares-3.3.7/src/branding/default/Biglogo.png install -Dm 0644 %{SOURCE11} %{_builddir}/calamares-3.3.7/src/modules/packagechooser/images/Minimal-Install.png @@ -226,6 +247,9 @@ install -Dm 0644 %{SOURCE15} %{_builddir}/calamares-3.3.7/src/branding/default/S install -Dm 0644 %{SOURCE17} %{_builddir}/calamares-3.3.7/src/branding/default/openEuler.png install -Dm 0644 %{SOURCE18} %{_builddir}/calamares-3.3.7/src/branding/default/openEulerWord-blus.png install -Dm 0644 %{SOURCE19} %{_builddir}/calamares-3.3.7/src/branding/default/openEulerWord.png +install -Dm 0644 %{SOURCE20} %{_builddir}/calamares-3.3.7/src/branding/default/openEuler-icon.png +install -Dm 0644 %{SOURCE21} %{_builddir}/calamares-3.3.7/src/branding/default/password-hide.png +install -Dm 0644 %{SOURCE22} %{_builddir}/calamares-3.3.7/src/branding/default/password-show.png %build mkdir build cd build @@ -261,7 +285,6 @@ mkdir -p %{buildroot}/data/images install -Dm 0644 %{SOURCE8} %{buildroot}/data/images/Biglogo.svgz install -Dm 0644 %{SOURCE9} %{buildroot}/data/images/Biglogo.svg install -Dm 0644 %{SOURCE16} %{buildroot}/data/images/information.svgz - # calamares模块图片目录 mkdir -p %{buildroot}%{_datadir}/calamares/modules/packagechooser/images install -Dm 0644 %{SOURCE10} %{buildroot}%{_datadir}/calamares/branding/default/Biglogo.png @@ -276,7 +299,9 @@ install -Dm 0644 %{SOURCE15} %{buildroot}%{_datadir}/calamares/branding/default/ install -Dm 0644 %{SOURCE17} %{buildroot}%{_datadir}/calamares/branding/default/openEuler.png install -Dm 0644 %{SOURCE18} %{buildroot}%{_datadir}/calamares/branding/default/openEulerWord-blus.png install -Dm 0644 %{SOURCE19} %{buildroot}%{_datadir}/calamares/branding/default/openEulerWord.png - +install -Dm 0644 %{SOURCE20} %{buildroot}%{_datadir}/calamares/branding/default/openEuler-icon.png +install -Dm 0644 %{SOURCE21} %{_builddir}/calamares-3.3.7/src/branding/default/password-hide.png +install -Dm 0644 %{SOURCE22} %{_builddir}/calamares-3.3.7/src/branding/default/password-show.png %files %doc AUTHORS %license LICENSES/* @@ -313,7 +338,7 @@ install -Dm 0644 %{SOURCE19} %{buildroot}%{_datadir}/calamares/branding/default/ %{_datadir}/calamares/branding/default/openEulerWord-blus.png %{_datadir}/calamares/branding/default/openEulerWord.png %{_datadir}/calamares/branding/default/openEuler.png - +%{_datadir}/calamares/branding/default/openEuler-icon.png %files libs %{_libdir}/libcalamares.so.* %{_libdir}/libcalamaresui.so.* @@ -335,5 +360,73 @@ cd %{_builddir} || exit 0 rm -rf %{buildroot} %changelog +* Mon Nov 10 2025 Wenlong Zhang - 3.3.7-23 +- enable loongarch64 for calamares + +* Wed Sep 17 2025 Liu Wang <1823363429@qq.com> - 3.3.7-22 +- ID:NA +- SUG:NA +- DESC: add tigervnc-server + +* Mon Sep 01 2025 Liu Wang <1823363429@qq.com> - 3.3.7-21 +- add 25.09 docs + +* Tue Jun 17 2025 wu-donger - 3.3.7-20 +- Revise docs formatting guidelines + +* Tue Jun 10 2025 Liu Wang <1823363429@qq.com> - 3.3.7-19 +- Add euler-copilot-desktop server + +* Thu Jun 05 2025 Liu Wang <1823363429@qq.com> - 3.3.7-18 +- Delete euler-copilot server and get all release version + +* Wed Jun 04 2025 Liu Wang <1823363429@qq.com> - 3.3.7-17 +- Get os release version + +* Tue Jun 03 2025 Liu Wang <1823363429@qq.com> - 3.3.7-16 +- Add euler-copilot-web server + +* Thu May 29 2025 Liu Wang <1823363429@qq.com> - 3.3.7-15 +- Add DevStation install guide docs + +* Fri Apr 18 2025 Liu Wang <1823363429@qq.com> - 3.3.7-14 +- Add roo-code, uv, python3-mcp dependency for mcp server + +* Mon Mar 24 2025 Liu Wang <1823363429@qq.com> - 3.3.7-13 +- Add module dependency depmod command + +* Thu Mar 20 2025 Liu Wang <1823363429@qq.com> - 3.3.7-12 +- Fix gnome desktop user help center show fail issue + +* Fri Mar 14 2025 Liu Wang <1823363429@qq.com> - 3.3.7-11 +- Fix aarch64 desktop start up failed issue + +* Thu Mar 13 2025 Li Zixin <2271170409@qq.com> - 3.3.7-10 +- fix aboutPage release version problem + +* Thu Mar 13 2025 Liu Wang <1823363429@qq.com> - 3.3.7-9 +- Add thunderbird emial tool + +* Wed Mar 12 2025 Liu Wang <1823363429@qq.com> - 3.3.7-8 +- Fix desktop icon show + +* Mon Mar 10 2025 Li Zixin <2271170409@qq.com> - 3.3.7-7 +- Devstation fix timezone and release problem + +* Mon Mar 10 2025 Liu Wang <1823363429@qq.com> - 3.3.7-6 +- DevStation add 25.03 release dependency + +* Thu Feb 27 2025 Li Zixin <2271170409@qq.com> - 3.3.7-5 +- Update calamares.service + +* Mon Feb 17 2025 Liu Wang <1823363429@qq.com> - 3.3.7-4 +- Require disk scan and welcome page version show + +* Wed Jan 15 2025 Liu Wang <1823363429@qq.com> - 3.3.7-3 +- Select repo source by image type + +* Fri Dec 27 2024 Li Zixin - 3.3.7-2 +- Update to 1230 version + * Wed Oct 9 2024 Li Ping - 3.3.7-1 - Initial package diff --git a/docs/zh/_toc.yaml b/docs/zh/_toc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0f18a075c834f0f36efd9e2147cdc8948481217c --- /dev/null +++ b/docs/zh/_toc.yaml @@ -0,0 +1,22 @@ +label: Devstation安装指南 +isManual: true +description: calamares 为 DevStation 客户端安装工具,帮助用户顺利完成 openEuler DevStation 安装 +sections: + - label: 概述 + href: ./install/devstation_installation_guide.md + - label: calamares简介 + href: ./calamares_introduction.md + - label: 在VirtualBox上安装 + href: ./install/devstation_installation_on_virtualbox.md + - label: 安装准备 + href: ./install/installation_preparations.md + - label: 安装指导 + href: ./install/installation_guide.md + - label: 在个人PC上双系统安装 + href: ./install/devstation_installation_on_pc_for_dual_booting.md + - label: 安装准备 + href: ./install/installation_preparations_1.md + - label: 安装指导 + href: ./install/installation_guide_1.md + - label: 在Hyper-v虚拟机上安装DevStation指南 + href: ./install/installation_guide_2.md diff --git a/docs/zh/calamares_introduction.md b/docs/zh/calamares_introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..dc8720cdcd8b666127374fda578e0a767dcc642a --- /dev/null +++ b/docs/zh/calamares_introduction.md @@ -0,0 +1,3 @@ +# calamares 安装工具简介 + +calamares 为安装 DevStation 客户端工具, 帮助用户顺利完成 openEuler DevStation 安装。 diff --git a/docs/zh/install/devstation_installation_guide.md b/docs/zh/install/devstation_installation_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..c36e82ce87bcf221ef3ad178dbda4d4bde1245c6 --- /dev/null +++ b/docs/zh/install/devstation_installation_guide.md @@ -0,0 +1,5 @@ +# 安装指南 + +本文档主要介绍 openEuler DevStation 安装方法,以指导用户顺利完成 openEuler DevStation 安装。 + +本文档适用于所有使用 openEuler DevStation 的用户,特别是初次使用或想了解 openEuler DevStation 的用户,包括社区开发者、高校师生、系统工程师、管理员及维护人员等。 diff --git a/docs/zh/install/devstation_installation_on_pc_for_dual_booting.md b/docs/zh/install/devstation_installation_on_pc_for_dual_booting.md new file mode 100644 index 0000000000000000000000000000000000000000..c0949db9a5a36d36661c8cef0c43fe37499e6096 --- /dev/null +++ b/docs/zh/install/devstation_installation_on_pc_for_dual_booting.md @@ -0,0 +1,5 @@ +# 在个人PC上双系统安装 DevStation + +前提:请先安装 windows 系统,再进行 openEuler DevStation 系统安装,不要将两者顺序颠倒,否则安装完成后无法引导 openEuler DevStation 系统。 + +本文是介绍在个人PC上安装 openEuler Devstation 的步骤方法,使用本手册需要具备基本的 Linux 系统管理知识。 diff --git a/docs/zh/install/devstation_installation_on_virtualbox.md b/docs/zh/install/devstation_installation_on_virtualbox.md new file mode 100644 index 0000000000000000000000000000000000000000..32652b722e49980923a2f91aa3f82e6187198865 --- /dev/null +++ b/docs/zh/install/devstation_installation_on_virtualbox.md @@ -0,0 +1,3 @@ +# 在 VirtualBox 上安装 DevStation + +本文是介绍在 VirtualBox 上安装 openEuler Devstation 的步骤方法。 diff --git a/docs/zh/install/figures/1-createvm.png b/docs/zh/install/figures/1-createvm.png new file mode 100644 index 0000000000000000000000000000000000000000..77a914f27d02915b3c738a00e4affac5983733d8 Binary files /dev/null and b/docs/zh/install/figures/1-createvm.png differ diff --git a/docs/zh/install/figures/1-welcome.png b/docs/zh/install/figures/1-welcome.png new file mode 100644 index 0000000000000000000000000000000000000000..6add3c39c3a6767eeca3f1e0ab4099ac21507e2c Binary files /dev/null and b/docs/zh/install/figures/1-welcome.png differ diff --git a/docs/zh/install/figures/10-startinstall.png b/docs/zh/install/figures/10-startinstall.png new file mode 100644 index 0000000000000000000000000000000000000000..38e6fd27a848a5e67e98d84b4e1184f9a395956d Binary files /dev/null and b/docs/zh/install/figures/10-startinstall.png differ diff --git a/docs/zh/install/figures/10-username.png b/docs/zh/install/figures/10-username.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb2009a7a9ca506580a3bf808b9ec272aeeda2d Binary files /dev/null and b/docs/zh/install/figures/10-username.png differ diff --git a/docs/zh/install/figures/11-packages.png b/docs/zh/install/figures/11-packages.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ea30f980fb4b97fce136b78c5586887901668e Binary files /dev/null and b/docs/zh/install/figures/11-packages.png differ diff --git a/docs/zh/install/figures/11-summary.png b/docs/zh/install/figures/11-summary.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9822f8c009ac923838fc609a118f7a41f27f43 Binary files /dev/null and b/docs/zh/install/figures/11-summary.png differ diff --git a/docs/zh/install/figures/12-disk.png b/docs/zh/install/figures/12-disk.png new file mode 100644 index 0000000000000000000000000000000000000000..23abafb4bbdb9906b29a796b99220bf8ed45e558 Binary files /dev/null and b/docs/zh/install/figures/12-disk.png differ diff --git a/docs/zh/install/figures/12-installing.png b/docs/zh/install/figures/12-installing.png new file mode 100644 index 0000000000000000000000000000000000000000..0199a9d3e909d3aa88f9c403b8ec3e9fd59ccaa5 Binary files /dev/null and b/docs/zh/install/figures/12-installing.png differ diff --git a/docs/zh/install/figures/13-grub.png b/docs/zh/install/figures/13-grub.png new file mode 100644 index 0000000000000000000000000000000000000000..b99751c017cc22a0c5469d2aa239c34eaf38308a Binary files /dev/null and b/docs/zh/install/figures/13-grub.png differ diff --git a/docs/zh/install/figures/13-install.png b/docs/zh/install/figures/13-install.png new file mode 100644 index 0000000000000000000000000000000000000000..0199a9d3e909d3aa88f9c403b8ec3e9fd59ccaa5 Binary files /dev/null and b/docs/zh/install/figures/13-install.png differ diff --git a/docs/zh/install/figures/14-install-sure.png b/docs/zh/install/figures/14-install-sure.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9822f8c009ac923838fc609a118f7a41f27f43 Binary files /dev/null and b/docs/zh/install/figures/14-install-sure.png differ diff --git a/docs/zh/install/figures/2-create_dialog_box.png b/docs/zh/install/figures/2-create_dialog_box.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7a0351a354d6015dbfec14502bef027cae58cf Binary files /dev/null and b/docs/zh/install/figures/2-create_dialog_box.png differ diff --git a/docs/zh/install/figures/2-timezone.png b/docs/zh/install/figures/2-timezone.png new file mode 100644 index 0000000000000000000000000000000000000000..0c178aa9c33786fe22dcdfb8a431c010254f23bc Binary files /dev/null and b/docs/zh/install/figures/2-timezone.png differ diff --git a/docs/zh/install/figures/3-installation.png b/docs/zh/install/figures/3-installation.png new file mode 100644 index 0000000000000000000000000000000000000000..b99751c017cc22a0c5469d2aa239c34eaf38308a Binary files /dev/null and b/docs/zh/install/figures/3-installation.png differ diff --git a/docs/zh/install/figures/3-username.png b/docs/zh/install/figures/3-username.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb2009a7a9ca506580a3bf808b9ec272aeeda2d Binary files /dev/null and b/docs/zh/install/figures/3-username.png differ diff --git a/docs/zh/install/figures/4-packages.png b/docs/zh/install/figures/4-packages.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ea30f980fb4b97fce136b78c5586887901668e Binary files /dev/null and b/docs/zh/install/figures/4-packages.png differ diff --git a/docs/zh/install/figures/5-manifast.png b/docs/zh/install/figures/5-manifast.png new file mode 100644 index 0000000000000000000000000000000000000000..b3eef9651b47fa2ec47197d30b18bb7c0ee772cf Binary files /dev/null and b/docs/zh/install/figures/5-manifast.png differ diff --git a/docs/zh/install/figures/6-fat32.png b/docs/zh/install/figures/6-fat32.png new file mode 100644 index 0000000000000000000000000000000000000000..38e6fd27a848a5e67e98d84b4e1184f9a395956d Binary files /dev/null and b/docs/zh/install/figures/6-fat32.png differ diff --git a/docs/zh/install/figures/7-apps.png b/docs/zh/install/figures/7-apps.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbe689b72b2159f9297c5494b538d7151c790f7 Binary files /dev/null and b/docs/zh/install/figures/7-apps.png differ diff --git a/docs/zh/install/figures/7-bootefi.png b/docs/zh/install/figures/7-bootefi.png new file mode 100644 index 0000000000000000000000000000000000000000..285bd4e306e157435b6044298ff9bbc2a3630ba6 Binary files /dev/null and b/docs/zh/install/figures/7-bootefi.png differ diff --git a/docs/zh/install/figures/8-devstation.png b/docs/zh/install/figures/8-devstation.png new file mode 100644 index 0000000000000000000000000000000000000000..f88aab98378cb9c0ae7e41b0ae2345d68b90930c Binary files /dev/null and b/docs/zh/install/figures/8-devstation.png differ diff --git a/docs/zh/install/figures/8-selectlanguage.png b/docs/zh/install/figures/8-selectlanguage.png new file mode 100644 index 0000000000000000000000000000000000000000..6add3c39c3a6767eeca3f1e0ab4099ac21507e2c Binary files /dev/null and b/docs/zh/install/figures/8-selectlanguage.png differ diff --git a/docs/zh/install/figures/9-boot.png b/docs/zh/install/figures/9-boot.png new file mode 100644 index 0000000000000000000000000000000000000000..bc6c04ae18d3b4308bb0105b3ff233383342aa51 Binary files /dev/null and b/docs/zh/install/figures/9-boot.png differ diff --git a/docs/zh/install/figures/9-timezone.png b/docs/zh/install/figures/9-timezone.png new file mode 100644 index 0000000000000000000000000000000000000000..0c178aa9c33786fe22dcdfb8a431c010254f23bc Binary files /dev/null and b/docs/zh/install/figures/9-timezone.png differ diff --git a/docs/zh/install/figures/blkid-share.png b/docs/zh/install/figures/blkid-share.png new file mode 100644 index 0000000000000000000000000000000000000000..dd541429f167a51cdbdde9f12a37655ab3b78ef9 Binary files /dev/null and b/docs/zh/install/figures/blkid-share.png differ diff --git a/docs/zh/install/figures/compress.png b/docs/zh/install/figures/compress.png new file mode 100644 index 0000000000000000000000000000000000000000..869553e97cd8d63bba6efb3d096a91af26e97c53 Binary files /dev/null and b/docs/zh/install/figures/compress.png differ diff --git a/docs/zh/install/figures/desktop-icon.png b/docs/zh/install/figures/desktop-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a9c56ea9b959ec4ff15724ec9377d10f6f963f Binary files /dev/null and b/docs/zh/install/figures/desktop-icon.png differ diff --git a/docs/zh/install/figures/disk-location.png b/docs/zh/install/figures/disk-location.png new file mode 100644 index 0000000000000000000000000000000000000000..6920e5040cb484d96f0a48aec659a7860421ca2b Binary files /dev/null and b/docs/zh/install/figures/disk-location.png differ diff --git a/docs/zh/install/figures/download.png b/docs/zh/install/figures/download.png new file mode 100644 index 0000000000000000000000000000000000000000..f4030ac5eab4c4c42882c27189e79780236039a1 Binary files /dev/null and b/docs/zh/install/figures/download.png differ diff --git a/docs/zh/install/figures/first.png b/docs/zh/install/figures/first.png new file mode 100644 index 0000000000000000000000000000000000000000..f2d191da1b2b696683c1440badf1242a03646cb0 Binary files /dev/null and b/docs/zh/install/figures/first.png differ diff --git a/docs/zh/install/figures/hyper-cache.png b/docs/zh/install/figures/hyper-cache.png new file mode 100644 index 0000000000000000000000000000000000000000..9651b02060936608cf3bf78a8ed89c321f98884b Binary files /dev/null and b/docs/zh/install/figures/hyper-cache.png differ diff --git a/docs/zh/install/figures/hyper-disk-create.png b/docs/zh/install/figures/hyper-disk-create.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d2bc631f9fa4621494b913f051bca38e184f6d Binary files /dev/null and b/docs/zh/install/figures/hyper-disk-create.png differ diff --git a/docs/zh/install/figures/hyper-iso.png b/docs/zh/install/figures/hyper-iso.png new file mode 100644 index 0000000000000000000000000000000000000000..79acc13ed53fcc81a8ae7324e5d680c42a8d432c Binary files /dev/null and b/docs/zh/install/figures/hyper-iso.png differ diff --git a/docs/zh/install/figures/hyper-net.png b/docs/zh/install/figures/hyper-net.png new file mode 100644 index 0000000000000000000000000000000000000000..7402d76dd1a969a734d600d0603523d138aaa045 Binary files /dev/null and b/docs/zh/install/figures/hyper-net.png differ diff --git a/docs/zh/install/figures/hyper-set.png b/docs/zh/install/figures/hyper-set.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2548fff5ab9e4c08762e40087b52de0b698163 Binary files /dev/null and b/docs/zh/install/figures/hyper-set.png differ diff --git a/docs/zh/install/figures/install-exe.png b/docs/zh/install/figures/install-exe.png new file mode 100644 index 0000000000000000000000000000000000000000..28fb63862ef46a3cb4eca24510cc906e4bb3552e Binary files /dev/null and b/docs/zh/install/figures/install-exe.png differ diff --git a/docs/zh/install/figures/install-location.png b/docs/zh/install/figures/install-location.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad0cd64baef9946c48eb0618d7d72a71cf742c0 Binary files /dev/null and b/docs/zh/install/figures/install-location.png differ diff --git a/docs/zh/install/figures/install-strong.jpg b/docs/zh/install/figures/install-strong.jpg new file mode 100644 index 0000000000000000000000000000000000000000..637c030424670743014cce12e23be5f3c641215d Binary files /dev/null and b/docs/zh/install/figures/install-strong.jpg differ diff --git a/docs/zh/install/figures/new-machain.png b/docs/zh/install/figures/new-machain.png new file mode 100644 index 0000000000000000000000000000000000000000..9c09a481baa42ce6dd1b5df860c66147f860ef01 Binary files /dev/null and b/docs/zh/install/figures/new-machain.png differ diff --git a/docs/zh/install/figures/remove-iso.png b/docs/zh/install/figures/remove-iso.png new file mode 100644 index 0000000000000000000000000000000000000000..30efe94fa55c500d67061b9cf5f73c98cc40aa7f Binary files /dev/null and b/docs/zh/install/figures/remove-iso.png differ diff --git a/docs/zh/install/figures/run-bash.png b/docs/zh/install/figures/run-bash.png new file mode 100644 index 0000000000000000000000000000000000000000..8893a28f6e330672d78d6775ea4ed181a2ca1c9f Binary files /dev/null and b/docs/zh/install/figures/run-bash.png differ diff --git a/docs/zh/install/figures/run-mount.png b/docs/zh/install/figures/run-mount.png new file mode 100644 index 0000000000000000000000000000000000000000..ce736f40ae9eb4c1dbbe7631b80f1f21646ea9aa Binary files /dev/null and b/docs/zh/install/figures/run-mount.png differ diff --git a/docs/zh/install/figures/set-hyper-v.png b/docs/zh/install/figures/set-hyper-v.png new file mode 100644 index 0000000000000000000000000000000000000000..64234851aa89b0930765a271fd25326305182932 Binary files /dev/null and b/docs/zh/install/figures/set-hyper-v.png differ diff --git a/docs/zh/install/figures/share-dir.png b/docs/zh/install/figures/share-dir.png new file mode 100644 index 0000000000000000000000000000000000000000..3a904e0ae2db554f671ca4b57bfaf9a184e7a48e Binary files /dev/null and b/docs/zh/install/figures/share-dir.png differ diff --git a/docs/zh/install/figures/vir-config.png b/docs/zh/install/figures/vir-config.png new file mode 100644 index 0000000000000000000000000000000000000000..80c67cf12949d5a3bd5dc598704af4c7aaff60bd Binary files /dev/null and b/docs/zh/install/figures/vir-config.png differ diff --git a/docs/zh/install/figures/vir-show.png b/docs/zh/install/figures/vir-show.png new file mode 100644 index 0000000000000000000000000000000000000000..c476a5ae694ae55a07cb014b4bcd818f3606526b Binary files /dev/null and b/docs/zh/install/figures/vir-show.png differ diff --git a/docs/zh/install/figures/vnc-connect.png b/docs/zh/install/figures/vnc-connect.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e558f3f51728f910d6ed6575cf10fc182bd335 Binary files /dev/null and b/docs/zh/install/figures/vnc-connect.png differ diff --git a/docs/zh/install/figures/vnc-download.png b/docs/zh/install/figures/vnc-download.png new file mode 100644 index 0000000000000000000000000000000000000000..c88e9eb07827f3586101e590690983750db2798e Binary files /dev/null and b/docs/zh/install/figures/vnc-download.png differ diff --git a/docs/zh/install/figures/xstartup-conf-back.png b/docs/zh/install/figures/xstartup-conf-back.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed1ac272b11846043758a72aa9ec5d7a2e6bedf Binary files /dev/null and b/docs/zh/install/figures/xstartup-conf-back.png differ diff --git a/docs/zh/install/figures/xstartup-conf.png b/docs/zh/install/figures/xstartup-conf.png new file mode 100644 index 0000000000000000000000000000000000000000..29cf9eae11e9200bbd445614f543fb9eac10ff75 Binary files /dev/null and b/docs/zh/install/figures/xstartup-conf.png differ diff --git a/docs/zh/install/installation_guide.md b/docs/zh/install/installation_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..82a810e653cb19e1cf7af9f3067290747307820c --- /dev/null +++ b/docs/zh/install/installation_guide.md @@ -0,0 +1,327 @@ +# 安装指南 + +本章将以光盘安装为例,详细介绍如何安装 openEuler DevStation。对于其他安装方式,除了在启动安装时的引导方式可能有所不同外,其余的安装流程均相同,因此本章不再赘述。 + +## VirtualBox 下载安装 + +进入[virtualbox官网](https://www.virtualbox.org/),在Download栏目下选择Windows hosts下载 + +![](./figures/download.png) + +完成后双击.exe打开安装程序,选择自定义安装路径,点击下一步,在自定安装页面按需选择是否创建**桌面创建快捷方式** ,最后点击安装等待安装完成即可 + +![](./figures/install-exe.png) + +![](./figures/install-location.png) + +![](./figures/desktop-icon.png) + +## 启动安装 + +### 使用光盘引导安装 + +使用光盘引导安装 openEuler DevStation,具体步骤如下。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> 在安装开始前,需要保证启动选项为光驱优先。安装步骤以 VirtualBox 挂载虚拟光驱进行光盘安装的操作举例。 + +1. 在 VM VirtualBox 工具栏中,单击新建如下图所示。 + + **图 1** 光驱图标 + + ![](./figures/1-createvm.png) + + 弹出新建虚拟电脑对话框,如下图所示。 + + **图 2** 新建虚拟电脑对话框 + + ![](./figures/2-create_dialog_box.png) +2. 在新建虚拟电脑对话框中,选择“虚拟光盘”, 并单击下拉框。选择 DevStation 镜像。 +3. 选择下一步,在virtual hardware虚机配置页面按个人电脑配置情况将虚机内存、CPU、磁盘大小配置好,建议Base Memory内存配置不小于4G,DiskSize磁盘大小不小于40G,同时勾选“**Use EFI**”,现代计算机都基本都是UEFI方式启动,接着一路点击下一步即可完成虚拟机创建 + +![](./figures/vir-config.png) + +已创建的虚拟机会显示在Virtualbox页面左边,如图所示 + +![](./figures/vir-show.png) + +### 安装引导界面 + +系统使用引导介质完成引导后会显示引导菜单。该引导菜单除启动安装程序外还提供一些选项。安装系统时,默认采用“Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09”方式进行安装。如果要选择默认选项之外的选项,请使用键盘中的“↑”和“↓”方向键进行选择,并在选项为高亮状态时按“Enter”。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - 如果60秒内未按任何键,系统将从默认选项“Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09”自动进入安装界面。 + +**图 3** 安装引导界面 + +![img](./figures/3-installation.png) + +安装引导选项说明如下: + +- Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09 —— 默认选项。 +- Troubleshooting —— 问题定位模式,系统无法正常安装时使用。-功能待完善 + +在安装引导界面,按“e”进入已选选项的参数编辑界面,按“c”进入命令行模式。 + +DevStation 正常启动之后,会以Livecd方式进入主界面,同时以devstation用户权限自动拉起系统安装服务进行落盘安装。 + +## 设置系统语言 + +在“欢迎”页面中选择“语言”,设置系统的语言。如[图5](#zh-cn_topic_0186390098_zh-cn_topic_0122145772_fig187301927172619)所示,用户也可根据实际情况进行调整,选择“简体中文”。 + +**图 5** 语言支持 + +![](./figures/8-selectlanguage.png) + +## 设置时间和日期 + +在“基础设置”页面中选择“地区和区域”,设置系统的时区、日期、时间等。 + +设置时区时,用户可通过页面顶部的“地区”和“城市”下拉菜单中进行选择,如[图6](#zh-cn_topic_0186390096_zh-cn_topic_0122145900_fig1260162652312)所示。 + +如果您所在城市没有出现在下拉菜单中,请选择同一时区中离您最近的城市。 + +**图 6** 日期和时间 + +![](./figures/9-timezone.png) + +## 设置帐户密码 + +在“用户设置”页面中设置账号密码,如[图7](#zh-cn_topic_0186390266_zh-cn_topic_0122145909_fig1323165793018)所示,根据[密码复杂度](https://www.openeuler.openatom.cn/whitepaper/openEuler%2024.03%20LTS%20SP2%20%E6%8A%80%E6%9C%AF%E7%99%BD%E7%9A%AE%E4%B9%A6.pdf)输入密码并再次输入密码进行确认。 + +>[!NOTE]说明 +> +> - root帐户是用来执行关键系统管理任务,不建议您在日常工作及系统访问时使用root帐户。 + +**图 7** root帐户 + +![](./figures/10-username.png) + +如上图所示,界面选中“为管理员账号使用同样的密码”选项后,管理员账户(即root)的密码与界面设置的用户密码相同,该选项避免多次输入密码(习惯上人们都会趋向于不同账号设置同一个密码,方便记忆)。相反,当取消选择该选项后,在该页面可以为管理员账号及密码进行单独设置。 + +## 选择安装软件 + +在“用户设置”页面中选择“DevStation”,指定需要安装的软件包。 + +用户需要根据实际的业务需求,在左侧也可以选择一个“最小安装”,如[图8](#zh-cn_topic_0186390261_zh-cn_topic_0122145865_fig03031519101414)所示。 + +**图 8** 软件选择 + +![img](./figures/11-packages.png) + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - 在最小安装的环境下,并非安装源中所有的包都会安装。如果用户需要使用的包未安装,可将安装源挂载到本地制作repo源,通过DNF工具单独安装。 + +## 设置安装目的地 + +在“安装设置”页面中选择“存储器”,设置操作系统的安装磁盘及分区。 + +在[图9](#fig1195417125015)所示的页面中您可以看到计算机中的本地可用存储设备。 + +**图 9** 安装目标位置 + +![](./figures/12-disk.png) + +### 存储配置 -待完善 + +**自动**分区 + +如果是在未使用过的存储设备中执行全新安装,或者不需要保留该存储设备中任何数据,建议选择“自动”进行自动分区。 + +**自定义**分区 -待完善 + +## 开始安装 + +在安装界面上完成所有必填选项的配置后。此时,用户可以单击“安装”进行系统安装,如[图10](#fig-install-sure)。 + +**图 10** 安装配置确认 + +![](./figures/14-install-sure.png) + +## 安装过程 + +开始安装后会出现进度页面,显示安装进度及所选软件包写入系统的进度,如[图11](#zh-cn_topic_0186390266_zh-cn_topic_0122145909_fig1590863119306)所示。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> 若系统安装过程中,单击“退出”,或复位、下电服务器,则安装过程被中断,系统将不可用,需要重新进行安装。 + +**图 11** 安装过程 + +![](./figures/13-install.png) + +## 安装完成 + +在安装过程执行完成后,openEuler Devstation即完成了安装。请点击“重启系统”按钮,系统将会重新启动。 + +## VirtualBox 共享文件夹配置指南 + +### 第一步:安装增强功能 + +在安装增强功能之前,确保虚机有网络。 + +**移除iso镜像文件**:操作如下:**设置->存储->控制器:IDE->Remove Disk From Virtual Drive** + +![](./figures/remove-iso.png) + +**加载虚拟光盘**:启动虚拟机并登录到操作系统,在VirtualBox顶部菜单栏,点击 **“设备” → “安装增强功能”**,如下图,这会自动加载一个虚拟光盘。 + +![](./figures/install-strong.jpg) + +之后在终端运行命令"**blkid**"查看结果:在输出结果中,寻找一个标识为 `cdrom` 或类型为 `iso9660` 的设备。如果看到类似 `/dev/sr0` 且文件系统是 `iso9660` 的行,就说明虚拟光盘已加载成功,如图所示。 + +```bash +blkid +``` + +![](./figures/blkid-share.png) + +**安装kernel-devel**:需要在虚机内部安装kernel-devel软件包: + +```bash +sudo dnf install kernel-devel -y +``` + +**安装增强功能**:进入“/dev/sr0”挂载的目录(查看/dev/sr0挂载目录:**lsblk** ),并在该目录下执行“VBoxLinuxAdditions.run脚本”,完成后**务必重启**虚拟机生效 + +```bash +lsblk +``` + +![](./figures/run-mount.png) + +```bash +./VBoxLinuxAdditions.run +``` + +![](./figures/run-bash.png) + +### 第二步:在VirtualBox中设置共享文件夹 + +打开VirtualBox,在虚拟机列表中选择需要配置的虚拟机,点击 “设置” 按钮,在设置窗口中,选择左侧的 “共享文件夹” 选项卡,点击右侧的 “添加共享文件夹” 图标(带加号的文件夹图标)。在弹出的对话框中,按以下要求配置: + +**文件夹路径**:点击右侧文件夹图标,选择宿主机上要共享的目录 + +**文件夹名称**:为这个共享起一个名字(例如 Share)。建议使用英文且不带空格 + +**只读分配**:如果只需要从虚拟机读取文件,可以勾选此项 + +**自动挂载**:**必须勾选**,这样VirtualBox增强功能通常会自动将共享文件夹挂载到 `/media/sf_<共享名称>` 目录下(例如 `/media/sf_share`),该目录即为共享目录 + +最后点击 “确定” 保存设置。这样,我们就成功设置/media/sf_share为共享目录 + +![](./figures/share-dir.png) + +### 第三步:设置普通用户操作权限 + +要确保用户对该目录有操作权限,需要将当前用户加入vboxsf用户组。执行此命令后**需要重启虚机**生效。 + +```bash +sudo usermod -aG vboxsf $USER +``` + +## VNC远程连接DevStation操作指南 + +### 一、VNC客户端安装(Windows系统为例) + +#### 1. 下载客户端 + +访问[VNC官网下载页面](https://sourceforge.net/projects/tigervnc/files/stable/1.15.0/) + +- 选择Windows版本下载安装文件 + + ![](./figures/vnc-download.png) + +- 下载完成后双击“.exe”文件进行安装 + +- 安装过程按照默认设置,一直点击“下一步”即可完成 + +#### 2. 安装验证 + +- 安装完成后可在开始菜单找到“TigerVNC Viewer”程序 + +### 二、DevStation环境准备 + +#### 1. 关闭防火墙 + +```bash +sudo systemctl stop firewalld +``` + +#### 2. 关闭SELinux + +```bash +sudo setenforce 0 +``` + +#### 3. 确保服务以普通用户启动 + +- 使用普通用户账户进行操作,不要使用root用户 + +### 三、VNC服务配置 + +#### 1. 设置VNC连接密码 + +```bash +sudo vncpasswd +``` + +- 按照提示设置并确认密码 + +#### 2. 启动VNC服务 + +```bash +sudo vncserver :2 +``` + +**端口说明:** + +- `:2` 对应端口 **5902** +- `:3` 对应端口 **5903** +- 以此类推,端口号 = 5900 + 启动编号 + +#### 3. 修改VNC启动配置文件 + +#### 配置文件位置 + +```bash +/home/[用户名]/.vnc/xstartup +``` + +例如:用户名为aaa,则路径为 `/home/aaa/.vnc/xstartup` + +#### 修改步骤 + +```bash +sudo sed -i '/if \[ -e \/usr\/bin\/gnome-session \]; then/,/fi/s/^/# /' /home/aaa/.vnc/xstartup +``` + +#### 配置文件对比 + +- **修改前**: + + ![](./figures/xstartup-conf.png) + +- **修改后**:这两行已被注释(以#开头) + + ![](./figures/xstartup-conf-back.png) + +### 四、客户端连接 + +#### 1. 启动TigerVNC Viewer + +- 打开安装好的TigerVNC Viewer客户端 + +#### 2. 输入连接信息 + +- 在连接地址栏输入:`IP:端口号`,例如:`192.168.1.100:5902`,或简写:`192.168.1.100:2` + + ![](./figures/vnc-connect.png) + +#### 3. 身份验证 + +- 点击“连接”按钮 +- 在弹出的窗口中输入之前设置的VNC密码 +- 点击“确定”即可建立远程连接 diff --git a/docs/zh/install/installation_guide_1.md b/docs/zh/install/installation_guide_1.md new file mode 100644 index 0000000000000000000000000000000000000000..5168ffee7851e224c4b235e18636aa91681a2aa2 --- /dev/null +++ b/docs/zh/install/installation_guide_1.md @@ -0,0 +1,248 @@ +# **安装指导** + +## 1. 安装前准备 + +### 1.1 BIOS设置 + +> ![](./public_sys-resources/icon-warning.gif) **重要提示:** +> +> - 不同品牌设备进入BIOS方式不同(常见品牌:F1/F2/DEL/ESC) +> - 必须关闭"安全启动"(Secure Boot)选项 +> - 错误修改BIOS设置可能导致系统无法启动 + +1. 插入U盘启动盘 +2. 开机时立即按下设备对应的BIOS键(持续快速点击) +3. 在Security选项中禁用Secure Boot +4. 保存设置(F10)并重启 + +### 1.2 启动菜单选择 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - 启动菜单键通常为F12/ESC +> - 需在BIOS POST完成后快速按下 + +1. 重启后立即按下启动菜单键 +2. 选择带有"UEFI:"前缀的U盘设备 +3. 按Enter确认启动 + +## 2. 安装引导界面 + +### 2.1 引导菜单 + +系统将显示引导菜单,默认选项为: + +- `Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09`(推荐) +- `Troubleshooting`(仅用于问题诊断) + +> ![](./public_sys-resources/icon-note.gif) **操作说明:** +> +> - 使用↑/↓方向键选择 +> - 按Enter确认选择 +> - 60秒无操作将自动进入默认选项 + +**图1** 安装引导界面 + +![引导界面](./figures/3-installation.png) + +### 2.2 高级选项 + +- 按 `e`:编辑启动参数(高级用户) +- 按 `c`:进入命令行模式(故障诊断) + +## 3. 初始设置 + +### 3.1 语言选择 + +在欢迎界面选择"简体中文"(或其他支持语言) + +> ![](./public_sys-resources/icon-warning.gif) **注意:** +> +> - 此处选择的语言将作为系统默认语言 +> - 安装完成后仍可修改 + +**图2** 语言设置界面 + +![语言设置](./figures/1-welcome.png) + +### 3.2 时区设置 + +1. 选择"亚洲/北京"时区(UTC+8) +2. 如城市未列出,选择同区域最近城市 + +**图3** 时区设置界面 + +![时区设置](./figures/2-timezone.png) + +## 4. 账户与安全设置 + +### 4.1 用户账户设置 + +**图4** 账户设置界面 + +![账户设置](./figures/3-username.png) + +1. 设置用户名(建议使用英文) +2. 设置符合复杂度要求的密码: + - 至少8位字符 + - 包含大小写字母和数字 + - 建议使用特殊符号 + +> ![](./public_sys-resources/icon-warning.gif) **安全建议:** +> +> - 避免使用简单密码如"123456" +> - 不要使用与个人信息相关的密码 +> - 定期更换密码 + +### 4.2 Root账户设置 + +- 勾选"为管理员账号使用同样的密码"可统一密码 +- 取消勾选可单独设置Root密码 + +> ![](./public_sys-resources/icon-note.gif) **最佳实践:** +> +> - 日常操作建议使用普通账户 +> - 仅在进行系统管理时使用Root账户 + +## 5. 软件包选择 + +### 5.1 基础环境选择 + +**图5** 软件包选择界面 + +![软件选择](./figures/4-packages.png) + +可选方案: + +1. **DevStation全功能环境**(推荐): + 1. 包含开发工具链和常用应用 + 2. 适合大多数开发者 +2. **最小安装**: + 1. 仅基础系统组件 + 2. 适合自定义构建环境 + +> ![](./public_sys-resources/icon-note.gif) **扩展建议:** +> +> - 安装完成后可通过以下命令添加软件: +> +> ```bash +> sudo dnf install +> ``` +> +> - 可使用 `dnf search`命令查找可用软件包 + +## 6. 磁盘分区(关键步骤❗️❗️❗️) + +### 6.1 存储设备选择 + +> - 操作:选择"手动分区" ![](./public_sys-resources/icon-warning.gif) **重要警告:不要选择自动分区,请选择手动分区,请谨慎操作❗️❗️❗️** +> - 选择"自动分区"将会删除目前选定的存储器上所有数据,将会导致windows系统也被删除 +> - 请选择预留有空闲空间的磁盘 + +**图6** 存储设备列表 + +![存储设备](./figures/5-manifast.png) + +> ![](./public_sys-resources/icon-warning.gif) **重要警告:** +> +> - 错误的分区操作将导致数据永久丢失 +> - 建议提前备份重要数据 +> - 双系统用户请特别注意以下步骤 + +### 6.2 EFI系统分区设置 + +1. 选择现有的FAT32格式分区(通常为300-500MB) +2. 点击"编辑"按钮: + - 操作:选择"保留" ![](./public_sys-resources/icon-warning.gif) **重要警告:不保留的话,将导致windows系统永久丢失,请谨慎操作❗️❗️❗️** + - 挂载点:`/boot/efi` + +**图7** EFI分区设置 + +![EFI设置](./figures/7-bootefi.png) + +### 6.3 根分区设置 + +1. 选择安装前预留的空闲分区(如nvme0n1p7) +2. 点击"编辑"按钮: + - 文件系统:ext4 + - 挂载点:`/` + - 卷标:可自定义(如devstation) + +**图8** 根分区设置 + +![根分区](./figures/9-boot.png) + +### 6.4 分区确认 + +**图9** 分区总览 + +![分区总览](./figures/10-startinstall.png) + +> ![](./public_sys-resources/icon-warning.gif) **再次确认:** +> +> - 仔细检查每个分区的挂载点和大小 +> - 确认不会误操作其他系统的分区 + +## 7. 安装与初始化 + +### 7.1 安装确认 + +**图10** 安装确认界面 + +> ![](./public_sys-resources/icon-warning.gif) **最后确认:** +> +> - 再次检查所有设置,请确认分区当前和之后,是否选定**正确的空闲分区**上(如nvme0n1p7)安装 openEuler-25.09 +> - 确保电源稳定(笔记本请接通电源) + +点击"安装"开始系统部署 + +![安装确认](./figures/11-summary.png) + +### 7.2 安装进度 + +**图11** 安装过程界面 + +![安装进度](./figures/12-installing.png) + +预计时间:5-10分钟(取决于硬件配置) + +### 7.3 安装完成 + +1. 系统将提示安装成功 +2. 点击"重启"按钮 +3. **重要**:及时移除安装介质(U盘) + +**图12** 启动菜单 + +![启动菜单](./figures/13-grub.png) + +- 选择"openEuler"启动项 +- 首次启动可能需较长时间初始化 + +## 8. 首次启动配置 + +### 8.1 登录系统 + +- 使用安装时设置的账户登录 +- root账号可在终端中切换 + +### 8.2 网络配置 + +1. 点击系统托盘网络图标 +2. 选择Wi-Fi网络并输入密码 +3. 或有线网络将自动连接 + +### 8.3 应用管理 + +- 通过"应用中心"查找安装软件 +- 或使用终端命令: + +```bash +sudo dnf list installed +``` + +> ![](./public_sys-resources/icon-note.gif) **提示:** +> +> 遇到问题可查阅及反馈: +> +> - 社区论坛:[https://forum.openeuler.org](https://forum.openeuler.org) diff --git a/docs/zh/install/installation_guide_2.md b/docs/zh/install/installation_guide_2.md new file mode 100644 index 0000000000000000000000000000000000000000..2d76fc67fcc47ef1d4dd4931011463404c46c9e4 --- /dev/null +++ b/docs/zh/install/installation_guide_2.md @@ -0,0 +1,330 @@ +# 安装指南 + +本章将以光盘安装为例,详细介绍如何安装 openEuler DevStation。对于其他安装方式,除了在启动安装时的引导方式可能有所不同外,其余的安装流程均相同,因此本章不再赘述。 + +## Hyper-V 虚拟机创建完整指南 + +### 一、启用和安装 Hyper-V 功能 + +#### Windows 10/11 专业版/企业版/教育版 + +1. 打开 **控制面板** → **程序** → **启用或关闭 Windows 功能** + +2. 勾选以下选项: + + - Hyper-V + + - Hyper-V 管理工具 + + - Hyper-V 平台 + + - Hyper-V Hypervisor + + - Hyper-V 服务 + +3. 点击 **确定**,系统会自动安装 + +4. 安装完成后重启计算机 + +![](./figures/set-hyper-v.png) + +### 二、配置 Hyper-V 设置 + +#### 1. 打开 Hyper-V 管理器 + +- 开始菜单搜索 "Hyper-V 管理器" + +- 或运行 `virtmgmt.msc` + +#### 2. 配置虚拟硬盘和虚拟机存储路径 + +1. 在右侧操作面板点击 **Hyper-V 设置** + +2. 配置以下路径(建议选择空间充足的磁盘): + +- 虚拟硬盘(指定存储虚拟机磁盘文件的位置):`D:\Hyper-v-disk` + +- 虚拟机(指定存储虚拟机配置文件的位置):`D:\Hyper-v-machain` + +![](./figures/hyper-set.png) + +### 三、创建虚拟机 + +在 Hyper-V 管理器点击 快速创建 + +步骤1:启动向导 + +在右侧操作面板点击 新建 → 虚拟机 + +![](./figures/new-machain.png) + +点击 下一步 + +步骤2:指定名称和位置 + +名称:新建虚拟机 + +位置:D:\Hyper-v-disk + +![](./figures/disk-location.png) + +步骤3:指定代数 + +第1代:支持32位/64位,兼容旧系统 + +**PS:此处需选择第一代,第二代启动虚机会失败** + +![](./figures/first.png) + +步骤4:分配内存 + +启动内存:4096 MB(4GB) + +为 Hyper-V 使用动态内存:推荐勾选,勾选后内存变换范围:1024 MB至8192 MB。内存缓冲:20% + +![](./figures/hyper-cache.png) + +步骤5:配置网络 + +连接:Default Switch + +![](./figures/hyper-net.png) + +步骤6:连接虚拟硬盘 + +创建虚拟硬盘 + +名称:`新建虚拟机.vhdx` + +位置:D:\Hyper-v-disk\新建虚拟机\Virtual Hard Disks\ + +大小:64 GB(动态扩展) + +![](./figures/hyper-disk-create.png) + +步骤7:安装选项 + +选择 从可启动的CD/DVD-ROM安装操作系统 + +选择安装介质: + +映像文件 (.iso):浏览选择 Windows ISO 文件 + +![](./figures/hyper-iso.png) + +点击下一步,浏览虚拟机配置,然后点击完成即完成虚拟机的创建 + +### 安装引导界面 + +系统使用引导介质完成引导后会显示引导菜单。该引导菜单除启动安装程序外还提供一些选项。安装系统时,默认采用“Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09”方式进行安装。如果要选择默认选项之外的选项,请使用键盘中的“↑”和“↓”方向键进行选择,并在选项为高亮状态时按“Enter”。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - 如果60秒内未按任何键,系统将从默认选项“Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09”自动进入安装界面。 + +**图 3** 安装引导界面 + +![img](./figures/3-installation.png) + +安装引导选项说明如下: + +- Start openEuler-25.09-DevStation-x86_64-dvd.iso 25.09 —— 默认选项。 +- Troubleshooting —— 问题定位模式,系统无法正常安装时使用。-功能待完善 + +在安装引导界面,按“e”进入已选选项的参数编辑界面,按“c”进入命令行模式。 + +DevStation 正常启动之后,会以Livecd方式进入主界面,同时以devstation用户权限自动拉起系统安装服务进行落盘安装。 + +## 设置系统语言 + +在“欢迎”页面中选择“语言”,设置系统的语言。如[图5](#zh-cn_topic_0186390098_zh-cn_topic_0122145772_fig187301927172619)所示,用户也可根据实际情况进行调整,选择“简体中文”。 + +**图 5** 语言支持 + +![](./figures/8-selectlanguage.png) + +## 设置时间和日期 + +在“基础设置”页面中选择“地区和区域”,设置系统的时区、日期、时间等。 + +设置时区时,用户可通过页面顶部的“地区”和“城市”下拉菜单中进行选择,如[图6](#zh-cn_topic_0186390096_zh-cn_topic_0122145900_fig1260162652312)所示。 + +如果您所在城市没有出现在下拉菜单中,请选择同一时区中离您最近的城市。 + +**图 6** 日期和时间 + +![](./figures/9-timezone.png) + +## 设置帐户密码 + +在“用户设置”页面中设置账号密码,如[图7](#zh-cn_topic_0186390266_zh-cn_topic_0122145909_fig1323165793018)所示,根据[密码复杂度](https://www.openeuler.openatom.cn/whitepaper/openEuler%2024.03%20LTS%20SP2%20%E6%8A%80%E6%9C%AF%E7%99%BD%E7%9A%AE%E4%B9%A6.pdf)输入密码并再次输入密码进行确认。 + +>[!NOTE]说明 +> +> - root帐户是用来执行关键系统管理任务,不建议您在日常工作及系统访问时使用root帐户。 + +**图 7** root帐户 + +![](./figures/10-username.png) + +如上图所示,界面选中“为管理员账号使用同样的密码”选项后,管理员账户(即root)的密码与界面设置的用户密码相同,该选项避免多次输入密码(习惯上人们都会趋向于不同账号设置同一个密码,方便记忆)。相反,当取消选择该选项后,在该页面可以为管理员账号及密码进行单独设置。 + +## 选择安装软件 + +在“用户设置”页面中选择“DevStation”,指定需要安装的软件包。 + +用户需要根据实际的业务需求,在左侧也可以选择一个“最小安装”,如[图8](#zh-cn_topic_0186390261_zh-cn_topic_0122145865_fig03031519101414)所示。 + +**图 8** 软件选择 + +![img](./figures/11-packages.png) + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - 在最小安装的环境下,并非安装源中所有的包都会安装。如果用户需要使用的包未安装,可将安装源挂载到本地制作repo源,通过DNF工具单独安装。 + +## 设置安装目的地 + +在“安装设置”页面中选择“存储器”,设置操作系统的安装磁盘及分区。 + +在[图9](#fig1195417125015)所示的页面中您可以看到计算机中的本地可用存储设备。 + +**图 9** 安装目标位置 + +![](./figures/12-disk.png) + +### 存储配置 -待完善 + +**自动**分区 + +如果是在未使用过的存储设备中执行全新安装,或者不需要保留该存储设备中任何数据,建议选择“自动”进行自动分区。 + +**自定义**分区 -待完善 + +## 开始安装 + +在安装界面上完成所有必填选项的配置后。此时,用户可以单击“安装”进行系统安装,如[图10](#fig-install-sure)。 + +**图 10** 安装配置确认 + +![](./figures/14-install-sure.png) + +## 安装过程 + +开始安装后会出现进度页面,显示安装进度及所选软件包写入系统的进度,如[图11](#zh-cn_topic_0186390266_zh-cn_topic_0122145909_fig1590863119306)所示。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> 若系统安装过程中,单击“退出”,或复位、下电服务器,则安装过程被中断,系统将不可用,需要重新进行安装。 + +**图 11** 安装过程 + +![](./figures/13-install.png) + +## 安装完成 + +在安装过程执行完成后,openEuler Devstation即完成了安装。请点击“重启系统”按钮,系统将会重新启动。 + +## VNC远程连接DevStation操作指南 + +### 一、VNC客户端安装(Windows系统为例) + +#### 1. 下载客户端 + +访问[VNC官网下载页面](https://sourceforge.net/projects/tigervnc/files/stable/1.15.0/) + +- 选择Windows版本下载安装文件 + + ![](./figures/vnc-download.png) + +- 下载完成后双击“.exe”文件进行安装 + +- 安装过程按照默认设置,一直点击“下一步”即可完成 + +#### 2. 安装验证 + +- 安装完成后可在开始菜单找到“TigerVNC Viewer”程序 + +### 二、DevStation环境准备 + +#### 1. 关闭防火墙 + +```bash +sudo systemctl stop firewalld +``` + +#### 2. 关闭SELinux + +```bash +sudo setenforce 0 +``` + +#### 3. 确保服务以普通用户启动 + +- 使用普通用户账户进行操作,不要使用root用户 + +### 三、VNC服务配置 + +#### 1. 设置VNC连接密码 + +```bash +sudo vncpasswd +``` + +- 按照提示设置并确认密码 + +#### 2. 启动VNC服务 + +```bash +sudo vncserver :2 +``` + +**端口说明:** + +- `:2` 对应端口 **5902** +- `:3` 对应端口 **5903** +- 以此类推,端口号 = 5900 + 启动编号 + +#### 3. 修改VNC启动配置文件 + +#### 配置文件位置 + +```bash +/home/[用户名]/.vnc/xstartup +``` + +例如:用户名为aaa,则路径为 `/home/aaa/.vnc/xstartup` + +#### 修改步骤 + +```bash +sudo sed -i '/if \[ -e \/usr\/bin\/gnome-session \]; then/,/fi/s/^/# /' /home/aaa/.vnc/xstartup +``` + +#### 配置文件对比 + +- **修改前**: + + ![](./figures/xstartup-conf.png) + +- **修改后**:这两行已被注释(以#开头) + + ![](./figures/xstartup-conf-back.png) + +### 四、客户端连接 + +#### 1. 启动TigerVNC Viewer + +- 打开安装好的TigerVNC Viewer客户端 + +#### 2. 输入连接信息 + +- 在连接地址栏输入:`IP:端口号`,例如:`192.168.1.100:5902`,或简写:`192.168.1.100:2` + + ![](./figures/vnc-connect.png) + +#### 3. 身份验证 + +- 点击“连接”按钮 +- 在弹出的窗口中输入之前设置的VNC密码 +- 点击“确定”即可建立远程连接 diff --git a/docs/zh/install/installation_preparations.md b/docs/zh/install/installation_preparations.md new file mode 100644 index 0000000000000000000000000000000000000000..480f38f66a769794a9bba549f7de29bb02fba331 --- /dev/null +++ b/docs/zh/install/installation_preparations.md @@ -0,0 +1,102 @@ +# 安装准备 + +在安装前,需要考虑软硬件的兼容性问题,并评估相关配置和准备工作,确保安装过程顺利进行。 + +## 获取安装源 + +在安装开始前,您需要获取 openEuler DevStation 的镜像和校验文件。 + +请按以下步骤获取 openEuler Devstation 的镜像和校验文件: + +1. 登录[openEuler DevStation 社区镜像源](https://repo.openeuler.org/)网站。 +2. 选择 openEuler-25.09 版本。 +3. 根据实际待安装环境的架构和场景选择需要下载的 openEuler DevStation 的镜像和校验文件。 + 1. 若为 aarch64 架构。 + 1. 选择 aarch64 目录。 + 2. 将镜像 “openEuler-25.09-DevStation-aarch64-dvd.iso” 下载到本地。 + 2. 若为 x86_64 架构。 + 1. 选择 x86_64 目录。 + 2. 将镜像 “openEuler-25.09-DevStation-x86_64-dvd.iso” 下载到本地。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - aarch64 架构的镜像支持 UEFI 模式,x86\_64 架构的镜像支持 UEFI 模式和 Legacy 模式。 + +## 镜像完整性校验 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> 本章节以 aarch64 架构的镜像完整性校验为例,x86\_64 架构的镜像完整性校验的操作方法相同。 + +### 简介 + +为了确认软件包在传输过程中由于网络原因或者存储设备原因是否出现下载不完整的问题,在获取到软件包后,需要对软件包的完整性进行校验,通过了校验的软件包才能部署。 + +这里通过对比校验文件中记录的校验值和手动方式计算的 iso 文件校验值,判断软件包是否完整。若两个值相同,说明iso文件完整,否则,iso 完整性被破坏,请重新获取 iso 镜像。 + +### 前提条件 + +在校验镜像完整性之前,需要准备如下文件: + +- iso 文件:openEuler-25.09-DevStation-aarch64-dvd.iso。 +- 校验文件:openEuler-25.09-DevStation-aarch64-dvd.iso.sha256sum,文件保存ISO完整性校验值信息,校验信息与ISO值一一对应。 + +### 操作指导 + +文件完整性校验操作步骤如下: + +1. 计算文件的 sha256 校验值。执行命令如下: + + ```bash + sha256sum openEuler-25.09-DevStation-aarch64-dvd.iso + ``` + + 命令执行完成后,输出校验值。 +2. 对比步骤1计算的校验值与校验文件中复制的 SHA256 值是否一致。 + + 如果校验值一致说明 iso 文件完整,如果校验值不一致则可以确认文件完整性已被破坏,需要重新获取。 + +## 物理机的安装要求 + +若需要在物理机环境上安装 openEuler DevStation ,则物理机需要满足如下的硬件兼容性和最小硬件要求。 + +### 硬件兼容支持 - 待补充 + +openEuler DevStation 安装时,应注意硬件兼容性方面的问题,当前已支持的服务器类型请参考[兼容性列表](https://www.openeuler.org/zh/compatibility/)。 - 待补充 + +### 最小硬件要求 + +openEuler DevStation 所需的最小硬件要求如[表2](#tff48b99c9bf24b84bb602c53229e2541)所示。 + +**表 2** 最小硬件要求 + +| 部件名称 | 最小硬件要求 | +| :------- | :------------------------------------------------------ | +| 架构 | aarch64 或 x86_64 | +| CPU | 现代1Ghz 双核处理器 | +| 内存 | 不小于 4GB(为了获得更好的应用体验,建议不小于 8GB) | +| 硬盘 | 不小于 32GB(为了获得更好的应用体验,建议不小于 120GB) | + +## 虚拟机的安装要求 + +若需要在虚拟机环境上安装 openEuler DevStation ,则虚拟机需要满足如下的虚拟化平台兼容性和最小虚拟化要求。 + +### 虚拟化平台兼容性 + +openEuler DevStation 安装时,应注意虚拟化平台兼容性的问题,当前已支持的虚拟化平台为: + +- Hyper-v +- VMware Workstation +- VM VirtualBox + +### 最小虚拟化空间要求 + +openEuler所需的最小虚拟化空间要求如[表3](#tff48b99c9bf24b84bb602c53229e2542)所示。 + +**表 3** 最小虚拟化空间要求 + +| 部件名称 | 最小虚拟化空间要求 | +| :------- | :------------------------------------------------------ | +| 架构 | aarch64 或 x86_64 | +| CPU | 双核 CPU | +| 内存 | 不小于 4GB(为了获得更好的应用体验,建议不小于 8GB) | +| 硬盘 | 不小于 32GB(为了获得更好的应用体验,建议不小于 120GB) | diff --git a/docs/zh/install/installation_preparations_1.md b/docs/zh/install/installation_preparations_1.md new file mode 100644 index 0000000000000000000000000000000000000000..ab2b48a7a642621111dbebebe640b0f4898ff42c --- /dev/null +++ b/docs/zh/install/installation_preparations_1.md @@ -0,0 +1,156 @@ +# 安装准备 + +在安装前,需要考虑软硬件的兼容性问题,并评估相关配置和准备工作,确保安装过程顺利进行。 + +## 系统要求 + +### 1️⃣ **存储空间** + +| 项目 | 说明 | +| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| **最低要求(Windows保留)** | Windows系统盘至少保留100GB可用空间(仅Windows系统+基本软件占用的空间) | +| **双系统推荐配置(DevStation)** | 需单独分出一个**空闲分区**(未使用的磁盘空间),大小至少40GB(建议80GB),这个空间将专门用于安装openEuler DevStation系统 | + +**举个🌰**: + +如果你的硬盘是500GB,典型分区建议: + +- Windows系统盘:150GB(实际Windows 11安装需约40GB,预留常用软件空间) +- 数据盘(D盘):300GB (存放个人文件) +- **空闲分区**:50GB(专门留给openEuler DevStation) + +> ⚠️ 注意:这里的"空闲分区"必须处于**未格式化状态**,安装系统时会自动格式化! + +### 2️⃣ **内存** + +| 项目 | 说明 | 对双系统的影响 | +| ------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------- | +| **最低要求(4GB)** | 只要满足任一系统单独运行的最基本内存需求 | 当运行Windows或DevStation时,电脑能勉强启动使用(但无法同时运行双系统) | +| **推荐配置(8GB DDR4+)** | 现代操作系统的流畅运行基础 | 可让双系统中的任一系统运行时流畅开启开发工具(如VSCode、Docker等) | + +> 🤔 **常见误区**:双系统不是同时运行的!**同一时间只能使用一个系统**,内存需求是针对每个系统独立计算的。 + +### 3️⃣ **UEFI支持** + +**什么是UEFI?**:现代电脑的**新型启动模式**(相比传统的Legacy BIOS),提供更安全的启动环境和支持大容量硬盘。 + +| 关键项 | 要求说明 | 失败案例 | +| ----------------- | -------------------------------------------------------------------------------- | ------------------------------------ | +| **必需** | 你的电脑主板需支持UEFI启动模式(2012年后生产的电脑基本都支持) | 旧电脑使用Legacy模式可能导致分区失败 | +| **开启CSM** | 针对**老旧设备**:在主板设置中开启"兼容性支持模块"(让UEFI兼容Legacy设备) | 不开启可能导致安装界面卡死 | + +**▶ 如何检查UEFI模式?** +在Windows中按 `Win+R` 输入 `msinfo32` → 查看**BIOS模式**是否为"UEFI" + +**▶ 为什么要用UEFI?** + +- 支持超过2TB的硬盘 +- 更快的启动速度 +- 双系统引导更稳定(GRUB与Windows Boot Manager兼容性好) + +### ❓ **如果不符合要求会怎样?** + +| 硬件项 | 不符合后果 | 解决方案 | +| ---------- | -------------------------------- | -------------------------------------------------------- | +| 存储不足 | 安装过程中出现"磁盘空间不足"错误 | 压缩Windows分区 | +| 内存不足 | 系统运行极度卡顿,频繁崩溃 | 关闭后台程序或添加内存条(笔记本用户需确认是否支持扩展) | +| 无UEFI支持 | 无法完成安装程序初始化 | 旧电脑需开启CSM或单独制作Legacy模式启动盘 | + +**实际场景下的建议方案**: + +如果你是学生或开发者的典型配置: + +```markdown +硬盘:512GB SSD +- Windows分配200GB(系统+基础开发环境) +- DevStation分配80GB (Linux开发环境+容器) +- 剩余232GB作为公共数据盘(NTFS格式,Windows/Linux均可读写) + +内存:16GB DDR4 → 可同时应对IDE/虚拟机等重度场景 +固件:UEFI模式+关闭Secure Boot → 确保硬件驱动兼容性 +``` + +## 获取安装源 + +在安装开始前,您需要获取 openEuler DevStation 的镜像和校验文件。 + +请按以下步骤获取 openEuler Devstation 的镜像和校验文件: + +1. 登录[openEuler DevStation 社区镜像源](https://repo.openeuler.org/)网站。 +2. 选择 openEuler-25.09 版本。 +3. 根据实际待安装环境的架构和场景选择需要下载的 openEuler DevStation 的镜像和校验文件。 + 1. 若为 aarch64 架构。 + 1. 选择 aarch64 目录。 + 2. 将镜像 “openEuler-25.09-DevStation-aarch64-dvd.iso” 下载到本地。 + 2. 若为 x86_64 架构。 + 1. 选择 x86_64 目录。 + 2. 将镜像 “openEuler-25.09-DevStation-x86_64-dvd.iso” 下载到本地。 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> +> - aarch64 架构的镜像支持 UEFI 模式,x86\_64 架构的镜像支持 UEFI 模式和 Legacy 模式。 + +## 镜像完整性校验 + +> ![](./public_sys-resources/icon-note.gif) **说明:** +> 本章节以 aarch64 架构的镜像完整性校验为例,x86\_64 架构的镜像完整性校验的操作方法相同。 + +### 简介 + +为了确认软件包在传输过程中由于网络原因或者存储设备原因是否出现下载不完整的问题,在获取到软件包后,需要对软件包的完整性进行校验,通过了校验的软件包才能部署。 + +这里通过对比校验文件中记录的校验值和手动方式计算的 iso 文件校验值,判断软件包是否完整。若两个值相同,说明iso文件完整,否则,iso 完整性被破坏,请重新获取 iso 镜像。 + +### 前提条件 + +在校验镜像完整性之前,需要准备如下文件: + +- iso 文件:openEuler-25.09-DevStation-aarch64-dvd.iso。 +- 校验文件:openEuler-25.09-DevStation-aarch64-dvd.iso.sha256sum,文件保存ISO完整性校验值信息,校验信息与ISO值一一对应。 + +### 操作指导 + +文件完整性校验操作步骤如下: + +1. 计算文件的 sha256 校验值。执行命令如下: + + ```bash + sha256sum openEuler-25.09-DevStation-aarch64-dvd.iso + ``` + + 命令执行完成后,输出校验值。 +2. 对比步骤1计算的校验值与校验文件中复制的 SHA256 值是否一致。 + + 如果校验值一致说明 iso 文件完整,如果校验值不一致则可以确认文件完整性已被破坏,需要重新获取。 + +## 制作启动盘 + +1. 下载 [Rufus](https://rufus.ie/)(或使用Etcher、Ventoy等工具) +2. 插入U盘(容量≥8GB) +3. 打开Rufus,选择下载的ISO镜像: + 1. 分区类型:MBR + 2. 目标系统类型:BIOS 或 UEFI + 3. 文件系统:FAT32 +4. 制作完成后,记录U盘卷标(例如:"openEuler-25.09-DevStation-netin") + +## Windows 磁盘空间释放 + +### 分区压缩步骤 + +1. **打开磁盘管理** + + ![Win+X → 磁盘管理](./figures/compress.png) +2. **右键目标分区→压缩卷** +3. **输入压缩量(单位MB)**: + + ```bash + 推荐公式: (总空间 - 系统已用)*0.3 # 例如100GB系统盘建议保留30GB供Windows + ``` + +### 空间验证 + +```powershell +# 以管理员身份执行: +Get-Partition | ft -AutoSize +# 确认显示"未分配"空间 +``` diff --git a/docs/zh/install/public_sys-resources/icon-caution.gif b/docs/zh/install/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-caution.gif differ diff --git a/docs/zh/install/public_sys-resources/icon-danger.gif b/docs/zh/install/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-danger.gif differ diff --git a/docs/zh/install/public_sys-resources/icon-note.gif b/docs/zh/install/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-note.gif differ diff --git a/docs/zh/install/public_sys-resources/icon-notice.gif b/docs/zh/install/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-notice.gif differ diff --git a/docs/zh/install/public_sys-resources/icon-tip.gif b/docs/zh/install/public_sys-resources/icon-tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7 Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-tip.gif differ diff --git a/docs/zh/install/public_sys-resources/icon-warning.gif b/docs/zh/install/public_sys-resources/icon-warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/docs/zh/install/public_sys-resources/icon-warning.gif differ diff --git a/openEuler-icon.png b/openEuler-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db2afafdd36eabdd5c5fd083d9bc00aff9911e6c Binary files /dev/null and b/openEuler-icon.png differ diff --git a/password-hide.png b/password-hide.png new file mode 100644 index 0000000000000000000000000000000000000000..424b4feb99d3f66926d22b36f32949da45ed0819 Binary files /dev/null and b/password-hide.png differ diff --git a/password-show.png b/password-show.png new file mode 100644 index 0000000000000000000000000000000000000000..2ff2c6717fa8e188177d52d924d7dd5068bfb372 Binary files /dev/null and b/password-show.png differ