⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 configurationpanel.java

📁 Java写的ERP系统
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
 * The contents of this file are subject to the   Compiere License  Version 1.1
 * ("License"); You may not use this file except in compliance with the License
 * You may obtain a copy of the License at http://www.compiere.org/license.html
 * Software distributed under the License is distributed on an  "AS IS"  basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * The Original Code is                  Compiere  ERP & CRM  Business Solution
 * The Initial Developer of the Original Code is Jorg Janke  and ComPiere, Inc.
 * Portions created by Jorg Janke are Copyright (C) 1999-2002 Jorg Janke, parts
 * created by ComPiere are Copyright (C) ComPiere, Inc.;   All Rights Reserved.
 * Contributor(s): ______________________________________.
 *****************************************************************************/
package org.compiere.install;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.sql.*;
import oracle.jdbc.*;

import javax.mail.*;
import javax.mail.internet.*;

import org.compiere.Compiere;
import org.compiere.apps.SwingWorker;
import org.compiere.db.*;
import org.compiere.util.*;


/**
 *	Configuration Panel
 *
 * 	@author 	Jorg Janke
 * 	@author 	Marek Mosiewicz<marek.mosiewicz@jotel.com.pl> support for RMI over HTTP
 * 	@version 	$Id: ConfigurationPanel.java,v 1.2 2003/05/04 18:34:48 marekmosiewicz Exp $
 */
public class ConfigurationPanel extends JPanel
	implements ActionListener
{
	/**
	 * 	Constructor
	 *  @param statusBar for info
	 * 	@throws Exception
	 */
	public ConfigurationPanel(JLabel statusBar) throws Exception
	{
		m_statusBar = statusBar;
		jbInit();
		dynInit();
	}	//	ConfigurationPanel

	public static final String	COMPIERE_ENV_FILE	= "CompiereEnv.properties";

	public static final String	COMPIERE_HOME 		= "COMPIERE_HOME";
	public static final String	JAVA_HOME 		= "JAVA_HOME";
	public static final String	COMPIERE_JAVA_OPTIONS 	= "COMPIERE_JAVA_OPTIONS";

	public static final String	COMPIERE_APPS_SERVER 	= "COMPIERE_APPS_SERVER";
        public static final String	COMPIERE_RMI_OVER_HTTP 	= "COMPIERE_RMI_OVER_HTTP";        
	public static final String	COMPIERE_JNP_PORT 	= "COMPIERE_JNP_PORT";
	public static final String	COMPIERE_WEB_PORT 	= "COMPIERE_WEB_PORT";
	public static final String	COMPIERE_SSL_PORT 	= "COMPIERE_SSL_PORT";

	public static final String	COMPIERE_DB_SERVER 	= "COMPIERE_DB_SERVER";
	public static final String	COMPIERE_DB_PORT 	= "COMPIERE_DB_PORT";
	public static final String	COMPIERE_DB_NAME 	= "COMPIERE_DB_NAME";

	public static final String	COMPIERE_DB_USER 	= "COMPIERE_DB_USER";
	public static final String	COMPIERE_DB_PASSWORD 	= "COMPIERE_DB_PASSWORD";
	public static final String	COMPIERE_DB_SYSTEM 	= "COMPIERE_DB_SYSTEM";

	public static final String	COMPIERE_DB_URL 	= "COMPIERE_DB_URL";
	public static final String	COMPIERE_DB_TNS 	= "COMPIERE_DB_TNS";

	public static final String	COMPIERE_MAIL_SERVER 	= "COMPIERE_MAIL_SERVER";
	public static final String	COMPIERE_MAIL_USER 	= "COMPIERE_MAIL_USER";
	public static final String	COMPIERE_MAIL_PASSWORD 	= "COMPIERE_MAIL_PASSWORD";
	public static final String	COMPIERE_ADMIN_EMAIL	= "COMPIERE_ADMIN_EMAIL";

	public static final String	COMPIERE_FTP_SERVER	= "COMPIERE_FTP_SERVER";
	public static final String	COMPIERE_FTP_USER	= "COMPIERE_FTP_USER";
	public static final String	COMPIERE_FTP_PASSWORD	= "COMPIERE_FTP_PASSWORD";
	public static final String	COMPIERE_FTP_PREFIX	= "COMPIERE_FTP_PREFIX";

	private String			m_errorString;
	private File			m_javaHome;
	private File			m_compiereHome;
	private InetAddress		m_appsServer;
        private boolean                 m_RMIoverHTTP;
	private int			m_WebPort;
	private int			m_JNPPort;
	private InetAddress		m_databaseServer;
	private int			m_databasePort;
	private String			m_databaseName;
	private String			m_connectionString;
	private String			m_systemPassword;
	private String			m_databaseUser;
	private String			m_databasePassword;
	private String			m_TNSName;

	private InetAddress		m_mailServer;
	private InternetAddress		m_adminEMail;
	private String			m_mailUser;
	private String			m_mailPassword;

	private volatile boolean		m_success = false;
	private volatile boolean	 	m_testing = false;

	/** Translation				*/
	static ResourceBundle 		res = ResourceBundle.getBundle("org.compiere.install.SetupRes");

	/**	Driver					*/
	private static Driver		s_driver = null;
	/** Environment Properties	*/
	private Properties			m_properties = new Properties();
	/** Status Bar				*/
	private JLabel 				m_statusBar;

	private static ImageIcon iOpen = new ImageIcon(ConfigurationPanel.class.getResource("openFile.gif"));
	private static ImageIcon iSave = new ImageIcon(Compiere.class.getResource("images/Save16.gif"));
	private static ImageIcon iHelp = new ImageIcon(Compiere.class.getResource("images/Help16.gif"));


	//	-------------	Static UI
	private GridBagLayout gridBagLayout = new GridBagLayout();
	private JLabel lCompiereHome = new JLabel();
	private JTextField fCompiereHome = new JTextField();
	private JLabel lWebPort = new JLabel();
	private JTextField fWebPort = new JTextField();
	private JLabel lAppsServer = new JLabel();
	private JTextField fAppsServer = new JTextField();
	private JLabel lDatabaseType = new JLabel();
	private JComboBox fDatabaseType = new JComboBox();
	private JLabel lDatabaseName = new JLabel();
	private JLabel lDatabasePort = new JLabel();
	private JLabel lDatabaseUser = new JLabel();
	private JLabel lDatabasePassword = new JLabel();
	private JTextField fDatabaseName = new JTextField();
	private JTextField fDatabasePort = new JTextField();
	private JTextField fDatabaseUser = new JTextField();
	private JPasswordField fDatabasePassword = new JPasswordField();
	private JLabel lTNSName = new JLabel();
	private JComboBox fTNSName = new JComboBox();
	private JLabel lSystemPassword = new JLabel();
	private JPasswordField fSystemPassword = new JPasswordField();
	private JLabel lMailServer = new JLabel();
	private JTextField fMailServer = new JTextField();
	private JLabel lAdminEMail = new JLabel();
	private JTextField fAdminEMail = new JTextField();
	private JLabel lDatabaseServer = new JLabel();
	private JTextField fDatabaseServer = new JTextField();
	private JLabel lJavaHome = new JLabel();
	private JTextField fJavaHome = new JTextField();
	private JButton bCompiereHome = new JButton(iOpen);
	private JButton bJavaHome = new JButton(iOpen);
	private JButton bHelp = new JButton(iHelp);
	private JButton bTest = new JButton();
	private JButton bSave = new JButton(iSave);
	private JLabel lJNPPort = new JLabel();
	private JTextField fJNPPort = new JTextField();
	private JLabel lMailUser = new JLabel();
	private JLabel lMailPassword = new JLabel();
	private JTextField fMailUser = new JTextField();
	private JPasswordField fMailPassword = new JPasswordField();
        JCheckBox cbRMIoverHTTP = new JCheckBox();


	/**
	 * 	Static Layout Init
	 *  @throws Exception
	 */
	private void jbInit() throws Exception
	{
		lCompiereHome.setToolTipText(res.getString("CompiereHomeInfo"));
		lCompiereHome.setText(res.getString("CompiereHome"));
		this.setLayout(gridBagLayout);
		fCompiereHome.setText("D:\\Compiere2");
		lWebPort.setToolTipText(res.getString("WebPortInfo"));
		lWebPort.setText(res.getString("WebPort"));
		fWebPort.setText("80");
		lAppsServer.setToolTipText(res.getString("AppsServerInfo"));
		lAppsServer.setText(res.getString("AppsServer"));
		fAppsServer.setText("server.company.com");
		lDatabaseType.setToolTipText(res.getString("DatabaseTypeInfo"));
		lDatabaseType.setText(res.getString("DatabaseType"));
		lDatabaseName.setToolTipText(res.getString("DatabaseNameInfo"));
		lDatabaseName.setText(res.getString("DatabaseName"));
		lDatabasePort.setToolTipText(res.getString("DatabasePortInfo"));
		lDatabasePort.setText(res.getString("DatabasePort"));
		lDatabaseUser.setToolTipText(res.getString("DatabaseUserInfo"));
		lDatabaseUser.setText(res.getString("DatabaseUser"));
		lDatabasePassword.setToolTipText(res.getString("DatabasePasswordInfo"));
		lDatabasePassword.setText(res.getString("DatabasePassword"));
		fDatabaseName.setText("compiere");
		fDatabasePort.setText("1521");
		fDatabaseUser.setText("compiere");
		fDatabasePassword.setText("compiere");
		lTNSName.setToolTipText(res.getString("TNSNameInfo"));
		lTNSName.setText(res.getString("TNSName"));
		fTNSName.setEditable(true);
		lSystemPassword.setToolTipText(res.getString("SystemPasswordInfo"));
		lSystemPassword.setText(res.getString("SystemPassword"));
		fSystemPassword.setText("manager");
		lMailServer.setToolTipText(res.getString("MailServerInfo"));
		lMailServer.setText(res.getString("MailServer"));
		fMailServer.setText("mail.company.com");
		lAdminEMail.setToolTipText(res.getString("AdminEMailInfo"));
		lAdminEMail.setText(res.getString("AdminEMail"));
		fAdminEMail.setText("admin@company.com");
		bTest.setToolTipText(res.getString("TestInfo"));
		bTest.setText(res.getString("Test"));
		bSave.setToolTipText(res.getString("SaveInfo"));
		bSave.setText(res.getString("Save"));
		lDatabaseServer.setToolTipText(res.getString("DatabaseServerInfo"));
		lDatabaseServer.setText(res.getString("DatabaseServer"));
		lJavaHome.setToolTipText(res.getString("JavaHomeInfo"));
		lJavaHome.setText(res.getString("JavaHome"));
		fJavaHome.setText("Java141");
		lJNPPort.setToolTipText(res.getString("JNPPortInfo"));
		lJNPPort.setText(res.getString("JNPPort"));
		fJNPPort.setText("1099");
		bHelp.setToolTipText(res.getString("HelpInfo"));
		lMailUser.setToolTipText(res.getString("MailUserInfo"));
		lMailUser.setText(res.getString("MailUser"));
		lMailPassword.setToolTipText(res.getString("MailPasswordInfo"));
		lMailPassword.setText(res.getString("MailPassword"));
		fMailUser.setText("compiere");
		fMailPassword.setText("compiere");
    cbRMIoverHTTP.setToolTipText("configure server to use HTTP protocol (necessery to use via firewall)");
    cbRMIoverHTTP.setActionCommand("jCheckBox1");
    cbRMIoverHTTP.setText(res.getString("RMIoverHTTP"));
    cbRMIoverHTTP.addActionListener(new ConfigurationPanel_cbRMIoverHTTP_actionAdapter(this));
    this.add(lCompiereHome,           new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fCompiereHome,             new GridBagConstraints(1, 1, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lWebPort,           new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fWebPort,            new GridBagConstraints(1, 3, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lAppsServer,          new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fAppsServer,           new GridBagConstraints(1, 2, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lDatabaseType,           new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fDatabaseType,          new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lDatabasePort,          new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lDatabaseUser,           new GridBagConstraints(0, 8, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fDatabaseName,             new GridBagConstraints(1, 6, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fDatabasePort,            new GridBagConstraints(1, 7, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fDatabaseUser,             new GridBagConstraints(1, 8, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lTNSName,           new GridBagConstraints(2, 5, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fTNSName,              new GridBagConstraints(3, 5, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lMailServer,          new GridBagConstraints(0, 9, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lSystemPassword,           new GridBagConstraints(2, 7, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fSystemPassword,          new GridBagConstraints(3, 7, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fDatabasePassword,           new GridBagConstraints(3, 8, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lDatabasePassword,          new GridBagConstraints(2, 8, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fMailServer,          new GridBagConstraints(1, 9, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(bTest,         new GridBagConstraints(0, 11, 1, 1, 0.0, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(bSave,          new GridBagConstraints(3, 11, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lDatabaseServer,          new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fDatabaseServer,         new GridBagConstraints(1, 5, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lDatabaseName,       new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lJavaHome,      new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fJavaHome,            new GridBagConstraints(1, 0, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(bCompiereHome,     new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(bHelp,        new GridBagConstraints(2, 11, 1, 1, 0.0, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(bJavaHome,     new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lJNPPort,     new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
		this.add(fJNPPort,      new GridBagConstraints(3, 3, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
		this.add(lMailPassword,      new GridBagConstraints(2, 10, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fMailPassword,       new GridBagConstraints(3, 10, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lAdminEMail,   new GridBagConstraints(2, 9, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fMailUser,   new GridBagConstraints(1, 10, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(fAdminEMail,    new GridBagConstraints(3, 9, 1, 1, 0.5, 0.0
			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 5, 5), 0, 0));
		this.add(lMailUser,  new GridBagConstraints(0, 10, 1, 1, 0.0, 0.0
			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 5, 5, 0), 0, 0));
    this.add(cbRMIoverHTTP,   new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));

		//
		bCompiereHome.addActionListener(this);
		bJavaHome.addActionListener(this);
		bHelp.addActionListener(this);
		bTest.addActionListener(this);
		bSave.addActionListener(this);
	}	//	jbInit


	/**
	 * 	Dynamic Init
	 *  @throws Exception
	 */
	private void dynInit() throws Exception
	{
		//	Layout - Column Length
		fWebPort.setColumns(30);
		fJNPPort.setColumns(30);

		//	DatabaseType
		fDatabaseType.addItem("Oracle 9i2");

		//	Compiere Home
		String ch = System.getProperty(COMPIERE_HOME);
		if (ch == null || ch.length() == 0)
			ch = System.getProperty("user.dir");
		fCompiereHome.setText(ch);
		boolean envLoaded = false;
		String fileName = ch + File.separator + COMPIERE_ENV_FILE;
		File env = new File (fileName);
		System.out.println(env + " - exists=" + env.exists());
		if (env.exists())
		{
			try
			{
				FileInputStream fis = new FileInputStream(env);
				m_properties.load(fis);
				fis.close();
			}
			catch (Exception e)
			{
				System.err.println(e.toString());
			}
			System.out.println("Loading ...");
			if (m_properties.size() > 5)
				envLoaded = true;
			//
			fCompiereHome.setText((String)m_properties.get(COMPIERE_HOME));
			fJavaHome.setText((String)m_properties.get(JAVA_HOME));
			fAppsServer.setText((String)m_properties.get(COMPIERE_APPS_SERVER));
			fWebPort.setText((String)m_properties.get(COMPIERE_WEB_PORT));
			fJNPPort.setText((String)m_properties.get(COMPIERE_JNP_PORT));

			fDatabaseServer.setText((String)m_properties.get(COMPIERE_DB_SERVER));
			fDatabasePort.setText((String)m_properties.get(COMPIERE_DB_PORT));
			fDatabaseName.setText((String)m_properties.get(COMPIERE_DB_NAME));

			fDatabaseUser.setText((String)m_properties.get(COMPIERE_DB_USER));
			fDatabasePassword.setText((String)m_properties.get(COMPIERE_DB_PASSWORD));
			fSystemPassword.setText((String)m_properties.get(COMPIERE_DB_SYSTEM));
			fillTNSName((String)m_properties.get(COMPIERE_DB_TNS));

			fMailServer.setText((String)m_properties.get(COMPIERE_MAIL_SERVER));
			fMailUser.setText((String)m_properties.get(COMPIERE_MAIL_USER));
			fMailPassword.setText((String)m_properties.get(COMPIERE_MAIL_PASSWORD));
			fAdminEMail.setText((String)m_properties.get(COMPIERE_ADMIN_EMAIL));
                        try{
                          m_RMIoverHTTP = new Boolean((String)m_properties.get(COMPIERE_RMI_OVER_HTTP)).booleanValue();
                        }catch(Exception e){ //can not exist till now
                            m_RMIoverHTTP=false;
                        }
                        cbRMIoverHTTP.setSelected(m_RMIoverHTTP);
                        lJNPPort.setEnabled(!m_RMIoverHTTP);
                        fJNPPort.setEnabled(!m_RMIoverHTTP);
                        
		}

		//	No environment file found - defaults
		if (!envLoaded)
		{
			System.out.println("Setting Defaults");
			//	Java Home, e.g. D:\j2sdk1.4.1\jre
			String javaHome = System.getProperty("java.home");
			if (javaHome.endsWith("jre"))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -