feat: 回归完善预览文本功能;

This commit is contained in:
寂静的羽夏 2025-03-22 20:46:15 +08:00
parent b0560c37f7
commit b4a03ae827
26 changed files with 1671 additions and 210 deletions

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "QConsoleWidget.h"
#include "QConsoleIODevice.h"
#include "wingsyntaxhighlighter.h"

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef _QCONSOLEWIDGET_H_
#define _QCONSOLEWIDGET_H_

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "commandhistorymanager.h"
#include "utilities.h"

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef COMMANDHISTORYMANAGER_H
#define COMMANDHISTORYMANAGER_H

View File

@ -24,7 +24,10 @@
QHexBuffer::QHexBuffer(QObject *parent) : QObject(parent) {}
uchar QHexBuffer::at(qsizetype idx) { return uchar(this->read(idx, 1)[0]); }
uchar QHexBuffer::at(qsizetype idx) {
auto data = this->read(idx, 1);
return uchar(data[0]);
}
bool QHexBuffer::isEmpty() const { return this->length() <= 0; }

View File

@ -175,7 +175,11 @@ set(DIALOG_SRC
src/dialog/crashreport.cpp
src/dialog/crashreport.ui
src/dialog/showtextdialog.cpp
src/dialog/showtextdialog.h)
src/dialog/showtextdialog.h
src/dialog/definitiondownload.cpp
src/dialog/definitiondownload.h
src/dialog/searchdialog.cpp
src/dialog/searchdialog.h)
set(CONTROL_SRC
src/control/codeedit.h

BIN
images/defines.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
images/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -232,7 +232,7 @@
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:700;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../src/dialog/crashreport.cpp" line="36"/>
<location filename="../../src/dialog/crashreport.cpp" line="53"/>
<source>CopyToClipBoard</source>
<translation></translation>
</message>
@ -268,6 +268,44 @@
<translation></translation>
</message>
</context>
<context>
<name>DefinitionDownloadDialog</name>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="43"/>
<source>Update Syntax Definitions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="72"/>
<source>Updating syntax definitions from online repository...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="85"/>
<source>%1:%2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="90"/>
<source>%1:%2 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="97"/>
<source>%1.%2 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="99"/>
<source>%1 ms</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="102"/>
<source>Update operation completed (%1)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DockWidgetTab</name>
<message>
@ -1235,7 +1273,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1066"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1135"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3785"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3788"/>
<source>NothingToSave</source>
<translation></translation>
</message>
@ -1399,7 +1437,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1641"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1654"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3017"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3020"/>
<source>LayoutRestoring...</source>
<translation>...</translation>
</message>
@ -1410,7 +1448,7 @@
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1667"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3001"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3004"/>
<source>SaveLayout</source>
<translation></translation>
</message>
@ -1521,13 +1559,13 @@
<location filename="../../src/dialog/mainwindow.cpp" line="2137"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2167"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2194"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3171"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3234"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3252"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3260"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3506"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3823"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3832"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3174"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3237"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3255"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3263"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3509"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3826"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3835"/>
<source>Error</source>
<translation></translation>
</message>
@ -1544,8 +1582,8 @@
<location filename="../../src/dialog/mainwindow.cpp" line="1952"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1986"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2046"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3823"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3832"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3826"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3835"/>
<source>FilePermission</source>
<translation></translation>
</message>
@ -1571,7 +1609,7 @@
<location filename="../../src/dialog/mainwindow.cpp" line="2114"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2181"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2761"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3791"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3794"/>
<source>ChooseSaveFile</source>
<translation></translation>
</message>
@ -1591,42 +1629,42 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3024"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3027"/>
<source>SaveLayoutSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3027"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3030"/>
<source>SaveLayoutError</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3212"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3215"/>
<source>HasClonedView</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3778"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3781"/>
<source>SaveWorkSpace</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3779"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3782"/>
<source>WingHexWorkSpace (*.wingpro)</source>
<translation> (*.wingpro)</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3894"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3897"/>
<source>ConfirmSave</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3913"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3916"/>
<source>Column %1</source>
<translation> %1</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3974"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3977"/>
<source>ConfirmAPPSave</source>
<translation></translation>
</message>
@ -1636,7 +1674,7 @@
<location filename="../../src/dialog/mainwindow.cpp" line="1244"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2061"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2125"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3863"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3866"/>
<source>SaveSuccessfully</source>
<translation></translation>
</message>
@ -1647,7 +1685,7 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3212"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3215"/>
<source>Warn</source>
<translation></translation>
</message>
@ -1820,7 +1858,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="2603"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2644"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3365"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3368"/>
<source>NoSelection</source>
<translation></translation>
</message>
@ -1876,83 +1914,83 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="2995"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2998"/>
<source>LayoutSaving...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3001"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3004"/>
<source>PleaseInput</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3033"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3036"/>
<source>LogExporting...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3038"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3041"/>
<source>ExportLogError</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3041"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3044"/>
<source>ExportLogSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3049"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3052"/>
<source>ClearLogSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3110"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3113"/>
<source>BadNetwork</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3115"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3118"/>
<source>NewestVersion</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="386"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3112"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3115"/>
<source>OlderVersion</source>
<translation>使 Github Gitee </translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3097"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3100"/>
<source>CheckingUpdate</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3172"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3175"/>
<source>Too much opened files</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3234"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3237"/>
<source>FilePermissionSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3252"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3255"/>
<source>UnknownErrorSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3260"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3263"/>
<source>WorkSpaceUnSavedSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3423"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3426"/>
<source>CopyLimit</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3507"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3510"/>
<source>ErrOpenFileBelow</source>
<translation></translation>
</message>
@ -2477,32 +2515,32 @@
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="289"/>
<location filename="../../src/settings/qeditconfig.cpp" line="291"/>
<source>Default</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="301"/>
<location filename="../../src/settings/qeditconfig.cpp" line="303"/>
<source>IndentMixed</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="298"/>
<location filename="../../src/settings/qeditconfig.cpp" line="300"/>
<source>IndentSpaces</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="161"/>
<location filename="../../src/settings/qeditconfig.cpp" line="163"/>
<source>Console</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="299"/>
<location filename="../../src/settings/qeditconfig.cpp" line="301"/>
<source>IndentTabs</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="165"/>
<location filename="../../src/settings/qeditconfig.cpp" line="167"/>
<source>Edit</source>
<translation></translation>
</message>
@ -4386,22 +4424,22 @@
<context>
<name>ScriptingConsole</name>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="84"/>
<location filename="../../src/control/scriptingconsole.cpp" line="89"/>
<source>[Info]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="92"/>
<location filename="../../src/control/scriptingconsole.cpp" line="97"/>
<source>[Warn]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="100"/>
<location filename="../../src/control/scriptingconsole.cpp" line="105"/>
<source>[Error]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="176"/>
<location filename="../../src/control/scriptingconsole.cpp" line="198"/>
<source>[Console]</source>
<translation></translation>
</message>
@ -4835,6 +4873,143 @@
<translation> QT</translation>
</message>
</context>
<context>
<name>SearchDialog</name>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="207"/>
<source>Find and Replace...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="213"/>
<source>Match ca&amp;se</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="215"/>
<source>Match &amp;whole words</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="217"/>
<source>Regular e&amp;xpressions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="219"/>
<source>&amp;Escape sequences</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="221"/>
<source>Wrap Aro&amp;und</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="232"/>
<source>Find &amp;Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="234"/>
<source>Find &amp;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="236"/>
<source>&amp;Replace</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="238"/>
<source>Replace &amp;All</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="240"/>
<source>&amp;In Selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="244"/>
<source>&amp;Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="264"/>
<source>&amp;Find:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="269"/>
<source>Replace wit&amp;h:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="520"/>
<location filename="../../src/dialog/searchdialog.cpp" line="581"/>
<source>The specified text was not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="588"/>
<source>The specified text was not found in the selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="617"/>
<source>Successfully replaced %1 matches</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SearchWidget</name>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="51"/>
<source>Search Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="56"/>
<source>Match ca&amp;se</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="58"/>
<source>Match &amp;whole words</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="60"/>
<source>Regular e&amp;xpressions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="62"/>
<source>&amp;Escape sequences</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="64"/>
<source>Wrap Aro&amp;und</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="86"/>
<source>Find Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="91"/>
<source>Find Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="151"/>
<source>The specified text was not found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingDialog</name>
<message>
@ -4877,57 +5052,63 @@
<context>
<name>ShowTextDialog</name>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="131"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="147"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="133"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="149"/>
<source>Copy</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="83"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="92"/>
<source>TextBroswer</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="107"/>
<source>Plain Text</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="116"/>
<source>TooHugeFile</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="124"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="121"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="188"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="141"/>
<source>Edit</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="125"/>
<source>View</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="137"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="153"/>
<source>Find</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="141"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="157"/>
<source>Goto</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="146"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="162"/>
<source>Encoding</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="157"/>
<source>Display</source>
<translation></translation>
<location filename="../../src/dialog/showtextdialog.cpp" line="165"/>
<source>UpdateDefs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="165"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="175"/>
<source>CopyToClipBoard</source>
<translation></translation>
</message>
@ -4948,7 +5129,7 @@
<context>
<name>SyntaxPopup</name>
<message>
<location filename="../../src/control/settingspopup.cpp" line="196"/>
<location filename="../../src/control/settingspopup.cpp" line="185"/>
<source>Plain Text</source>
<translation></translation>
</message>

View File

@ -232,7 +232,7 @@
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:700;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../src/dialog/crashreport.cpp" line="36"/>
<location filename="../../src/dialog/crashreport.cpp" line="53"/>
<source>CopyToClipBoard</source>
<translation></translation>
</message>
@ -268,6 +268,44 @@
<translation></translation>
</message>
</context>
<context>
<name>DefinitionDownloadDialog</name>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="43"/>
<source>Update Syntax Definitions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="72"/>
<source>Updating syntax definitions from online repository...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="85"/>
<source>%1:%2 hours</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="90"/>
<source>%1:%2 minutes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="97"/>
<source>%1.%2 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="99"/>
<source>%1 ms</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/definitiondownload.cpp" line="102"/>
<source>Update operation completed (%1)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DockWidgetTab</name>
<message>
@ -1235,7 +1273,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1066"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1135"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3785"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3788"/>
<source>NothingToSave</source>
<translation></translation>
</message>
@ -1399,7 +1437,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1641"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1654"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3017"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3020"/>
<source>LayoutRestoring...</source>
<translation>...</translation>
</message>
@ -1410,7 +1448,7 @@
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="1667"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3001"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3004"/>
<source>SaveLayout</source>
<translation></translation>
</message>
@ -1521,13 +1559,13 @@
<location filename="../../src/dialog/mainwindow.cpp" line="2137"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2167"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2194"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3171"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3234"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3252"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3260"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3506"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3823"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3832"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3174"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3237"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3255"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3263"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3509"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3826"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3835"/>
<source>Error</source>
<translation></translation>
</message>
@ -1544,8 +1582,8 @@
<location filename="../../src/dialog/mainwindow.cpp" line="1952"/>
<location filename="../../src/dialog/mainwindow.cpp" line="1986"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2046"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3823"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3832"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3826"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3835"/>
<source>FilePermission</source>
<translation></translation>
</message>
@ -1571,7 +1609,7 @@
<location filename="../../src/dialog/mainwindow.cpp" line="2114"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2181"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2761"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3791"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3794"/>
<source>ChooseSaveFile</source>
<translation></translation>
</message>
@ -1591,42 +1629,42 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3024"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3027"/>
<source>SaveLayoutSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3027"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3030"/>
<source>SaveLayoutError</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3212"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3215"/>
<source>HasClonedView</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3778"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3781"/>
<source>SaveWorkSpace</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3779"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3782"/>
<source>WingHexWorkSpace (*.wingpro)</source>
<translation> (*.wingpro)</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3894"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3897"/>
<source>ConfirmSave</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3913"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3916"/>
<source>Column %1</source>
<translation> %1</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3974"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3977"/>
<source>ConfirmAPPSave</source>
<translation></translation>
</message>
@ -1636,7 +1674,7 @@
<location filename="../../src/dialog/mainwindow.cpp" line="1244"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2061"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2125"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3863"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3866"/>
<source>SaveSuccessfully</source>
<translation></translation>
</message>
@ -1647,7 +1685,7 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3212"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3215"/>
<source>Warn</source>
<translation></translation>
</message>
@ -1820,7 +1858,7 @@
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="2603"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2644"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3365"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3368"/>
<source>NoSelection</source>
<translation></translation>
</message>
@ -1876,83 +1914,83 @@
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="2995"/>
<location filename="../../src/dialog/mainwindow.cpp" line="2998"/>
<source>LayoutSaving...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3001"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3004"/>
<source>PleaseInput</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3033"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3036"/>
<source>LogExporting...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3038"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3041"/>
<source>ExportLogError</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3041"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3044"/>
<source>ExportLogSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3049"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3052"/>
<source>ClearLogSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3110"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3113"/>
<source>BadNetwork</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3115"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3118"/>
<source>NewestVersion</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="386"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3112"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3115"/>
<source>OlderVersion</source>
<translation>使 Github Gitee </translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3097"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3100"/>
<source>CheckingUpdate</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3172"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3175"/>
<source>Too much opened files</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3234"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3237"/>
<source>FilePermissionSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3252"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3255"/>
<source>UnknownErrorSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3260"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3263"/>
<source>WorkSpaceUnSavedSure2Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3423"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3426"/>
<source>CopyLimit</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/mainwindow.cpp" line="3507"/>
<location filename="../../src/dialog/mainwindow.cpp" line="3510"/>
<source>ErrOpenFileBelow</source>
<translation></translation>
</message>
@ -2477,32 +2515,32 @@
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="289"/>
<location filename="../../src/settings/qeditconfig.cpp" line="291"/>
<source>Default</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="301"/>
<location filename="../../src/settings/qeditconfig.cpp" line="303"/>
<source>IndentMixed</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="298"/>
<location filename="../../src/settings/qeditconfig.cpp" line="300"/>
<source>IndentSpaces</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="161"/>
<location filename="../../src/settings/qeditconfig.cpp" line="163"/>
<source>Console</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="299"/>
<location filename="../../src/settings/qeditconfig.cpp" line="301"/>
<source>IndentTabs</source>
<translation></translation>
</message>
<message>
<location filename="../../src/settings/qeditconfig.cpp" line="165"/>
<location filename="../../src/settings/qeditconfig.cpp" line="167"/>
<source>Edit</source>
<translation></translation>
</message>
@ -4386,22 +4424,22 @@
<context>
<name>ScriptingConsole</name>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="84"/>
<location filename="../../src/control/scriptingconsole.cpp" line="89"/>
<source>[Info]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="92"/>
<location filename="../../src/control/scriptingconsole.cpp" line="97"/>
<source>[Warn]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="100"/>
<location filename="../../src/control/scriptingconsole.cpp" line="105"/>
<source>[Error]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/control/scriptingconsole.cpp" line="176"/>
<location filename="../../src/control/scriptingconsole.cpp" line="198"/>
<source>[Console]</source>
<translation></translation>
</message>
@ -4835,6 +4873,143 @@
<translation> QT</translation>
</message>
</context>
<context>
<name>SearchDialog</name>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="207"/>
<source>Find and Replace...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="213"/>
<source>Match ca&amp;se</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="215"/>
<source>Match &amp;whole words</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="217"/>
<source>Regular e&amp;xpressions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="219"/>
<source>&amp;Escape sequences</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="221"/>
<source>Wrap Aro&amp;und</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="232"/>
<source>Find &amp;Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="234"/>
<source>Find &amp;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="236"/>
<source>&amp;Replace</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="238"/>
<source>Replace &amp;All</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="240"/>
<source>&amp;In Selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="244"/>
<source>&amp;Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="264"/>
<source>&amp;Find:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="269"/>
<source>Replace wit&amp;h:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="520"/>
<location filename="../../src/dialog/searchdialog.cpp" line="581"/>
<source>The specified text was not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="588"/>
<source>The specified text was not found in the selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="617"/>
<source>Successfully replaced %1 matches</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SearchWidget</name>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="51"/>
<source>Search Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="56"/>
<source>Match ca&amp;se</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="58"/>
<source>Match &amp;whole words</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="60"/>
<source>Regular e&amp;xpressions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="62"/>
<source>&amp;Escape sequences</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="64"/>
<source>Wrap Aro&amp;und</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="86"/>
<source>Find Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="91"/>
<source>Find Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/searchdialog.cpp" line="151"/>
<source>The specified text was not found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingDialog</name>
<message>
@ -4877,57 +5052,63 @@
<context>
<name>ShowTextDialog</name>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="131"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="147"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="133"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="149"/>
<source>Copy</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="83"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="92"/>
<source>TextBroswer</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="107"/>
<source>Plain Text</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="116"/>
<source>TooHugeFile</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="124"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="121"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="188"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="141"/>
<source>Edit</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="125"/>
<source>View</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="137"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="153"/>
<source>Find</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="141"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="157"/>
<source>Goto</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="146"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="162"/>
<source>Encoding</source>
<translation></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="157"/>
<source>Display</source>
<translation></translation>
<location filename="../../src/dialog/showtextdialog.cpp" line="165"/>
<source>UpdateDefs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/dialog/showtextdialog.cpp" line="165"/>
<location filename="../../src/dialog/showtextdialog.cpp" line="175"/>
<source>CopyToClipBoard</source>
<translation></translation>
</message>
@ -4948,7 +5129,7 @@
<context>
<name>SyntaxPopup</name>
<message>
<location filename="../../src/control/settingspopup.cpp" line="196"/>
<location filename="../../src/control/settingspopup.cpp" line="185"/>
<source>Plain Text</source>
<translation></translation>
</message>

View File

@ -27,6 +27,7 @@
<file>images/dbgstepout.png</file>
<file>images/dbgstepover.png</file>
<file>images/dbgstop.png</file>
<file>images/defines.png</file>
<file>images/del.png</file>
<file>images/devext.png</file>
<file>images/edit.png</file>
@ -126,6 +127,7 @@
<file alias="paste.png">images/paste.png</file>
<file alias="redo.png">images/redo.png</file>
<file alias="replace.png">images/replace.png</file>
<file>images/search.png</file>
<file alias="undo.png">images/undo.png</file>
</qresource>
<qresource prefix="/completion">

View File

@ -109,7 +109,6 @@
<context attribute="String" lineEndContext="#pop" name="StringEscapedChar">
<HlCStringChar attribute="String Char" context="#pop"/>
<RegExpr attribute="String Char" context="#pop" String="\\u+[0-9a-fA-F]{4}"/>
<RegExpr attribute="Error" context="#pop" String="\\(u+[0-9a-fA-F]*|.)?"/>
</context>
<context attribute="Text Block" lineEndContext="#stay" name="TextBlock">
<DetectChar context="StringEscapedChar" char="\" lookAhead="1"/>
@ -132,8 +131,8 @@
</context>
<context attribute="Decimal" lineEndContext="#pop" name="Decimal"/>
<context attribute="Macro" lineEndContext="#pop" name="Macro">
<Detect2Chars attribute="Comment" context="LineComment" char="/" char1="/"/>
<Detect2Chars attribute="Comment" context="BlockComment" char="/" char1="*" beginRegion="Comment"/>
<Detect2Chars attribute="Comment" context="#pop" char="/" char1="/"/>
<Detect2Chars attribute="Comment" context="#pop" char="/" char1="*" beginRegion="Comment"/>
</context>
</contexts>
<itemDatas>

View File

@ -17,11 +17,17 @@
#include "codeedit.h"
#include "class/scriptsettings.h"
#include "class/skinmanager.h"
#include "model/codecompletionmodel.h"
#include <QApplication>
#include <QModelIndex>
#include <QShortcut>
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Repository>
#include <KSyntaxHighlighting/Theme>
CodeEdit::CodeEdit(QWidget *parent) : WingCodeEdit(parent) {
connect(this->document(), &QTextDocument::modificationChanged, this,
&CodeEdit::contentModified);
@ -30,6 +36,28 @@ CodeEdit::CodeEdit(QWidget *parent) : WingCodeEdit(parent) {
connect(&ScriptSettings::instance(), &ScriptSettings::editorSettingsUpdate,
this, &CodeEdit::applyEditorSetStyle);
applyEditorSetStyle();
m_searchWidget = new SearchWidget(this, parent);
showSearchBar(false);
connect(this, &CodeEdit::textChanged, this, [this] {
if (m_searchWidget->isVisible())
showSearchBar(false);
});
}
void CodeEdit::showSearchBar(bool show) {
m_searchWidget->setVisible(show);
m_searchWidget->setEnabled(show);
if (show) {
const QTextCursor cursor = textCursor();
if (cursor.hasSelection())
m_searchWidget->setSearchText(cursor.selectedText());
m_searchWidget->activate();
} else {
clearLiveSearch();
setFocus(Qt::OtherFocusReason);
}
}
void CodeEdit::onCompletion(const QModelIndex &index) {
@ -65,6 +93,23 @@ void CodeEdit::applyEditorSetStyle() {
auto &set = ScriptSettings::instance();
auto dfont = QFont(set.editorFontFamily());
dfont.setPointSize(set.editorFontSize());
auto thname = set.editorTheme();
if (thname.isEmpty()) {
switch (SkinManager::instance().currentTheme()) {
case SkinManager::Theme::Dark:
this->setTheme(syntaxRepo().defaultTheme(
KSyntaxHighlighting::Repository::DarkTheme));
break;
case SkinManager::Theme::Light:
this->setTheme(syntaxRepo().defaultTheme(
KSyntaxHighlighting::Repository::LightTheme));
break;
}
} else {
this->setTheme(syntaxRepo().theme(thname));
}
this->setFont(dfont);
this->setTabWidth(set.editorTabWidth());
this->setIndentationMode(WingCodeEdit::IndentationMode(set.editorInden()));
@ -77,3 +122,16 @@ void CodeEdit::applyEditorSetStyle() {
this->setShowWhitespace(set.editorShowWhiteSpace());
this->setAutoCloseChar(set.editorAutoCloseChar());
}
void CodeEdit::resizeEvent(QResizeEvent *event) {
if (event)
WingCodeEdit::resizeEvent(event);
// Move the search widget to the upper-right corner
const QPoint editorPos = this->pos();
QSize searchSize = m_searchWidget->sizeHint();
m_searchWidget->resize(searchSize);
m_searchWidget->move(editorPos.x() + this->viewport()->width() -
searchSize.width() - 16,
editorPos.y());
}

View File

@ -19,6 +19,7 @@
#define CODEEDIT_H
#include "WingCodeEdit/wingcodeedit.h"
#include "dialog/searchdialog.h"
class CodeEdit : public WingCodeEdit {
Q_OBJECT
@ -26,6 +27,9 @@ class CodeEdit : public WingCodeEdit {
public:
explicit CodeEdit(QWidget *parent = nullptr);
public:
void showSearchBar(bool show);
signals:
void contentModified(bool b);
@ -35,8 +39,15 @@ protected slots:
private:
void addMoveLineShortCut();
// QWidget interface
protected:
virtual void resizeEvent(QResizeEvent *event) override;
private slots:
void applyEditorSetStyle();
private:
SearchWidget *m_searchWidget;
};
#endif // CODEEDIT_H

View File

@ -20,6 +20,7 @@
#include "class/logger.h"
#include "class/scriptconsolemachine.h"
#include "class/scriptsettings.h"
#include "class/skinmanager.h"
#include "model/codecompletionmodel.h"
#include <QApplication>
@ -28,6 +29,10 @@
#include <QRegularExpression>
#include <QTextBlock>
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Repository>
#include <KSyntaxHighlighting/Theme>
ScriptingConsole::ScriptingConsole(QWidget *parent)
: ScriptingConsoleBase(parent) {
connect(&ScriptSettings::instance(), &ScriptSettings::consoleSettingUpdate,
@ -135,6 +140,23 @@ void ScriptingConsole::applyScriptSettings() {
auto &set = ScriptSettings::instance();
auto dfont = QFont(set.consoleFontFamily());
dfont.setPointSize(set.consoleFontSize());
auto thname = set.editorTheme();
if (thname.isEmpty()) {
switch (SkinManager::instance().currentTheme()) {
case SkinManager::Theme::Dark:
setTheme(syntaxRepo().defaultTheme(
KSyntaxHighlighting::Repository::DarkTheme));
break;
case SkinManager::Theme::Light:
setTheme(syntaxRepo().defaultTheme(
KSyntaxHighlighting::Repository::LightTheme));
break;
}
} else {
setTheme(syntaxRepo().theme(thname));
}
this->setFont(dfont);
this->setTabWidth(set.consoleTabWidth());
this->setIndentationMode(WingCodeEdit::IndentationMode(set.consoleInden()));

View File

@ -37,18 +37,7 @@
#include "utilities.h"
TreeFilterEdit::TreeFilterEdit(QWidget *parent) : QLineEdit(parent) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
const bool darkTheme =
(QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark);
#else
const bool darkTheme =
(palette().color(QPalette::Window).lightness() < 128);
#endif
// TODO
// m_searchIcon =
//(QStringLiteral("search-filter"),
// darkTheme);
m_searchIcon = QIcon(QStringLiteral(":/qeditor/images/search.png"));
setClearButtonEnabled(true);
recomputeIconPos();

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "crashreport.h"
#include "ui_crashreport.h"

View File

@ -0,0 +1,110 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "definitiondownload.h"
#include <QDialogButtonBox>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <KSyntaxHighlighting/DefinitionDownloader>
class ResizedPlainTextEdit : public QPlainTextEdit {
public:
ResizedPlainTextEdit(QWidget *parent) : QPlainTextEdit(parent) {}
protected:
QSize sizeHint() const override {
const auto &metrics = fontMetrics();
return QSize(
metrics.boundingRect(QString(60, QLatin1Char('x'))).width(),
metrics.height() * 10);
}
};
DefinitionDownloadDialog::DefinitionDownloadDialog(
KSyntaxHighlighting::Repository *repository, QWidget *parent)
: FramelessDialogBase(parent) {
setWindowTitle(tr("Update Syntax Definitions"));
setModal(true);
auto w = new QWidget(this);
m_status = new ResizedPlainTextEdit(w);
m_status->setReadOnly(true);
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
m_buttonBox->button(QDialogButtonBox::Close)->setEnabled(false);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto layout = new QVBoxLayout(w);
layout->setSpacing(10);
layout->addWidget(m_status);
layout->addWidget(m_buttonBox);
buildUpContent(w);
m_downloader =
new KSyntaxHighlighting::DefinitionDownloader(repository, this);
QObject::connect(
m_downloader,
&KSyntaxHighlighting::DefinitionDownloader::informationMessage,
m_status, &QPlainTextEdit::appendPlainText);
QObject::connect(m_downloader,
&KSyntaxHighlighting::DefinitionDownloader::done, this,
&DefinitionDownloadDialog::downloadFinished);
m_status->appendPlainText(
tr("Updating syntax definitions from online repository..."));
m_downloader->start();
m_timer.start();
}
void DefinitionDownloadDialog::downloadFinished() {
qint64 elapsed = m_timer.elapsed();
QString timeStr;
if (elapsed >= 60 * 60 * 1000) {
qint64 hours = elapsed / (60 * 60 * 1000);
elapsed %= (60 * 60 * 1000);
qint64 minutes = elapsed / (60 * 1000);
timeStr =
tr("%1:%2 hours").arg(hours).arg(minutes, 2, 10, QLatin1Char('0'));
} else if (elapsed >= 60 * 1000) {
qint64 minutes = elapsed / (60 * 1000);
elapsed %= (60 * 1000);
qint64 seconds = elapsed / 1000;
timeStr = tr("%1:%2 minutes")
.arg(minutes)
.arg(seconds, 2, 10, QLatin1Char('0'));
} else if (elapsed >= 1000) {
qint64 seconds = elapsed / 1000;
elapsed %= 1000;
timeStr =
tr("%1.%2 seconds").arg(seconds).arg((int)qRound(elapsed / 100.0));
} else {
timeStr = tr("%1 ms").arg(elapsed);
}
m_status->appendPlainText(
tr("Update operation completed (%1)").arg(timeStr));
m_buttonBox->button(QDialogButtonBox::Close)->setEnabled(true);
m_downloader->deleteLater();
}
void DefinitionDownloadDialog::closeEvent(QCloseEvent *e) {
if (!m_buttonBox->button(QDialogButtonBox::Close)->isEnabled())
e->ignore();
}

View File

@ -0,0 +1,53 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef QTEXTPAD_DEFINITIONDOWNLOAD_H
#define QTEXTPAD_DEFINITIONDOWNLOAD_H
#include "dialog/framelessdialogbase.h"
#include <QElapsedTimer>
class QPlainTextEdit;
class QDialogButtonBox;
namespace KSyntaxHighlighting {
class Repository;
class DefinitionDownloader;
} // namespace KSyntaxHighlighting
class DefinitionDownloadDialog : public FramelessDialogBase {
Q_OBJECT
public:
explicit DefinitionDownloadDialog(
KSyntaxHighlighting::Repository *repository, QWidget *parent);
public Q_SLOTS:
void downloadFinished();
protected:
void closeEvent(QCloseEvent *) override;
private:
KSyntaxHighlighting::DefinitionDownloader *m_downloader;
QPlainTextEdit *m_status;
QDialogButtonBox *m_buttonBox;
QElapsedTimer m_timer;
};
#endif // QTEXTPAD_DEFINITIONDOWNLOAD_H

View File

@ -2976,11 +2976,14 @@ void MainWindow::on_selectionChanged() {
}
void MainWindow::on_viewtxt() {
auto hexeditor = currentHexView();
if (hexeditor == nullptr) {
auto editor = currentEditor();
if (editor == nullptr) {
return;
}
_showtxt->load(hexeditor->document()->buffer());
auto hexeditor = editor->hexEditor();
QMimeDatabase db;
_showtxt->load(hexeditor->document()->buffer(),
db.mimeTypeForFile(editor->fileName()).name());
}
void MainWindow::on_fullScreen() {

618
src/dialog/searchdialog.cpp Normal file
View File

@ -0,0 +1,618 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "searchdialog.h"
#include "utilities.h"
#include "class/wingmessagebox.h"
#include <QCheckBox>
#include <QComboBox>
#include <QCompleter>
#include <QGridLayout>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QPainter>
#include <QPushButton>
#include <QStringView>
#include <QToolButton>
#include <QVBoxLayout>
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
#include <QGuiApplication>
#include <QStyleHints>
#endif
static SearchDialog *s_instance = Q_NULLPTR;
SearchWidget::SearchWidget(WingCodeEdit *editor, QWidget *parent)
: QWidget(parent), m_editor(editor) {
auto tbMenu = new QToolButton(this);
tbMenu->setAutoRaise(true);
tbMenu->setIcon(QIcon::fromTheme(QStringLiteral("theme")));
tbMenu->setToolTip(tr("Search Settings"));
tbMenu->setStyleSheet(
QStringLiteral("QToolButton::menu-indicator { image: none; }"));
auto settingsMenu = new QMenu(this);
m_caseSensitive = settingsMenu->addAction(tr("Match ca&se"));
m_caseSensitive->setCheckable(true);
m_wholeWord = settingsMenu->addAction(tr("Match &whole words"));
m_wholeWord->setCheckable(true);
m_regex = settingsMenu->addAction(tr("Regular e&xpressions"));
m_regex->setCheckable(true);
m_escapes = settingsMenu->addAction(tr("&Escape sequences"));
m_escapes->setCheckable(true);
m_wrapSearch = settingsMenu->addAction(tr("Wrap Aro&und"));
m_wrapSearch->setCheckable(true);
tbMenu->setMenu(settingsMenu);
tbMenu->setPopupMode(QToolButton::InstantPopup);
connect(m_caseSensitive, &QAction::triggered, this,
&SearchWidget::updateSettings);
connect(m_wholeWord, &QAction::triggered, this,
&SearchWidget::updateSettings);
connect(m_regex, &QAction::triggered, this, &SearchWidget::updateSettings);
connect(m_escapes, &QAction::triggered, this,
&SearchWidget::updateSettings);
connect(m_wrapSearch, &QAction::triggered, this,
&SearchWidget::updateSettings);
m_searchText = new QLineEdit(this);
m_searchText->setClearButtonEnabled(true);
setFocusProxy(m_searchText);
auto tbNext = new QToolButton(this);
tbNext->setAutoRaise(true);
tbNext->setIcon(ICONRES(""));
tbNext->setToolTip(tr("Find Next"));
auto tbPrev = new QToolButton(this);
tbPrev->setAutoRaise(true);
tbPrev->setIcon(ICONRES(""));
tbPrev->setToolTip(tr("Find Previous"));
auto layout = new QHBoxLayout(this);
layout->setContentsMargins(5, 5, 5, 5);
layout->setSpacing(5);
layout->addWidget(tbMenu);
layout->addWidget(m_searchText);
layout->addWidget(tbNext);
layout->addWidget(tbPrev);
setLayout(layout);
connect(m_searchText, &QLineEdit::textChanged, this,
[this](const QString &text) {
m_searchParams.searchText =
m_escapes->isChecked()
? SearchDialog::translateEscapes(text)
: text;
m_editor->setLiveSearch(m_searchParams);
});
connect(m_searchText, &QLineEdit::returnPressed, this,
[this] { searchNext(false); });
connect(tbNext, &QToolButton::clicked, this, [this] { searchNext(false); });
connect(tbPrev, &QToolButton::clicked, this, [this] { searchNext(true); });
}
void SearchWidget::setSearchText(const QString &text) {
m_searchText->setText(text);
}
void SearchWidget::activate() {
m_searchParams.caseSensitive = m_caseSensitive->isChecked();
m_searchParams.wholeWord = m_wholeWord->isChecked();
m_searchParams.regex = m_regex->isChecked();
setFocus(Qt::OtherFocusReason);
m_searchText->selectAll();
m_editor->setLiveSearch(m_searchParams);
}
void SearchWidget::searchNext(bool reverse) {
if (!isVisible()) {
setVisible(true);
setEnabled(true);
activate();
}
if (m_searchParams.searchText.isEmpty())
return;
auto searchCursor = m_editor->textSearch(m_editor->textCursor(),
m_searchParams, false, reverse);
if (searchCursor.isNull() && m_wrapSearch->isChecked()) {
QTextCursor wrapCursor = m_editor->textCursor();
wrapCursor.movePosition(reverse ? QTextCursor::End
: QTextCursor::Start);
searchCursor =
m_editor->textSearch(wrapCursor, m_searchParams, true, reverse);
}
if (searchCursor.isNull())
QMessageBox::information(this, QString(),
tr("The specified text was not found"));
else
m_editor->setTextCursor(searchCursor);
}
void SearchWidget::paintEvent(QPaintEvent *) {
QPainter painter(this);
// Round the corners of this widget. Not strictly necessary, but
// it looks nicer...
const int arc = 4;
const int circ = 8;
const int h = height() - 1;
const int w = width() - 1;
painter.setPen(palette().color(QPalette::Mid));
const QColor windowColor = palette().color(QPalette::Window);
painter.setBrush(windowColor);
painter.drawEllipse(0, h - circ, circ, circ);
painter.drawEllipse(w - circ, h - circ, circ, circ);
painter.fillRect(0, 0, arc, h - arc, windowColor);
painter.fillRect(w - arc, 0, arc, h - arc, windowColor);
painter.fillRect(arc, h - arc, w - circ, arc, windowColor);
painter.fillRect(arc, 0, w - circ, h - arc, windowColor);
painter.drawLine(0, 0, 0, h - arc);
painter.drawLine(arc, h, w - arc, h);
painter.drawLine(w, 0, w, h - arc);
}
void SearchWidget::updateSettings() {
m_searchParams.caseSensitive = m_caseSensitive->isChecked();
m_searchParams.wholeWord = m_wholeWord->isChecked();
m_searchParams.regex = m_regex->isChecked();
m_editor->setLiveSearch(m_searchParams);
}
/* Just sets some more sane defaults for QComboBox:
* - Don't auto-insert items (we handle that manually)
* - Disable the completer, since it insists on changing the typed
* item to match another item in the list that differs only in case.
*/
class SearchComboBox : public QComboBox {
public:
explicit SearchComboBox(QWidget *parent) : QComboBox(parent) {
setEditable(true);
setInsertPolicy(QComboBox::NoInsert);
setDuplicatesEnabled(true);
setCompleter(Q_NULLPTR);
}
};
SearchDialog::SearchDialog(QWidget *parent)
: FramelessDialogBase(parent), m_editor() {
s_instance = this;
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(tr("Find and Replace..."));
setWindowIcon(ICONRES("edit-find-replace"));
m_searchText = new SearchComboBox(this);
m_replaceText = new SearchComboBox(this);
m_caseSensitive = new QCheckBox(tr("Match ca&se"), this);
m_caseSensitive->setChecked(false);
m_wholeWord = new QCheckBox(tr("Match &whole words"), this);
m_wholeWord->setChecked(false);
m_regex = new QCheckBox(tr("Regular e&xpressions"), this);
m_regex->setChecked(false);
m_escapes = new QCheckBox(tr("&Escape sequences"), this);
m_escapes->setChecked(false);
m_wrapSearch = new QCheckBox(tr("Wrap Aro&und"), this);
m_wrapSearch->setChecked(false);
// QDialogButtonBox insists on rearranging buttons depending on your
// platform, which would be fine if we only had standard actions, but most
// of our action buttons here are custom.
auto buttonBox = new QWidget(this);
buttonBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
auto buttonLayout = new QVBoxLayout(buttonBox);
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->setSpacing(5);
auto findNext = new QPushButton(tr("Find &Next"), this);
buttonLayout->addWidget(findNext);
auto findPrev = new QPushButton(tr("Find &Previous"), this);
buttonLayout->addWidget(findPrev);
auto replaceNext = new QPushButton(tr("&Replace"), this);
buttonLayout->addWidget(replaceNext);
auto replaceAll = new QPushButton(tr("Replace &All"), this);
buttonLayout->addWidget(replaceAll);
m_replaceSelectionButton = new QPushButton(tr("&In Selection"), this);
buttonLayout->addWidget(m_replaceSelectionButton);
buttonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum,
QSizePolicy::MinimumExpanding));
auto closeButton = new QPushButton(tr("&Close"), this);
buttonLayout->addWidget(closeButton);
connect(findNext, &QPushButton::clicked, this,
&SearchDialog::searchForward);
connect(findPrev, &QPushButton::clicked, this,
&SearchDialog::searchBackward);
connect(replaceNext, &QPushButton::clicked, this,
&SearchDialog::replaceCurrent);
connect(replaceAll, &QPushButton::clicked, this,
[this] { performReplaceAll(WholeDocument); });
connect(m_replaceSelectionButton, &QPushButton::clicked, this,
[this] { performReplaceAll(InSelection); });
connect(closeButton, &QPushButton::clicked, this, &QDialog::close);
auto w = new QWidget(this);
auto layout = new QGridLayout(w);
layout->setContentsMargins(10, 10, 10, 10);
layout->setVerticalSpacing(5);
layout->setHorizontalSpacing(10);
auto searchLabel = new QLabel(tr("&Find:"), this);
searchLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
searchLabel->setBuddy(m_searchText);
layout->addWidget(searchLabel, 0, 0);
layout->addWidget(m_searchText, 0, 1, 1, 2);
auto replaceLabel = new QLabel(tr("Replace wit&h:"), this);
replaceLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
replaceLabel->setBuddy(m_replaceText);
layout->addWidget(replaceLabel, 1, 0);
layout->addWidget(m_replaceText, 1, 1, 1, 2);
layout->addItem(new QSpacerItem(0, 10, QSizePolicy::MinimumExpanding,
QSizePolicy::Fixed),
2, 0, 1, 3);
layout->addWidget(m_caseSensitive, 3, 1);
layout->addWidget(m_wholeWord, 4, 1);
layout->addWidget(m_regex, 5, 1);
layout->addWidget(m_escapes, 6, 1);
layout->addWidget(m_wrapSearch, 3, 2);
layout->addItem(
new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding),
layout->rowCount(), 0, 1, 3);
layout->addWidget(buttonBox, 0, layout->columnCount(), layout->rowCount(),
1);
buildUpContent(w);
}
SearchDialog::~SearchDialog() {
syncSearchSettings(false);
s_instance = Q_NULLPTR;
}
SearchDialog *SearchDialog::create(WingCodeEdit *editor, QWidget *parent) {
if (s_instance) {
s_instance->raise();
} else {
Q_ASSERT(parent);
s_instance = new SearchDialog(parent);
s_instance->show();
s_instance->raise();
s_instance->activateWindow();
s_instance->m_editor = editor;
connect(s_instance->m_editor, &WingCodeEdit::selectionChanged,
s_instance, [] {
bool hasSelection =
s_instance->m_editor->textCursor().hasSelection();
s_instance->m_replaceSelectionButton->setEnabled(
hasSelection);
});
}
const QTextCursor cursor = s_instance->m_editor->textCursor();
if (cursor.hasSelection()) {
s_instance->m_searchText->setCurrentText(cursor.selectedText());
s_instance->m_searchText->lineEdit()->selectAll();
}
s_instance->m_replaceSelectionButton->setEnabled(cursor.hasSelection());
return s_instance;
}
static QString translateCharEscape(QStringView digits, int *advance) {
Q_ASSERT(digits.size() > 0);
Q_ASSERT(advance);
*advance = 0;
if (digits.at(0) == QLatin1Char('x')) {
// We only support exactly 2 hex bytes with \x format
if (digits.size() < 3)
return QString();
QByteArray number = digits.mid(1, 2).toLatin1();
char *end;
ulong ch = strtoul(number.constData(), &end, 16);
if (*end != '\0')
return QString();
*advance = 2;
return QString(QChar::fromLatin1(static_cast<char>(ch)));
} else if (digits.at(0) == QLatin1Char('u')) {
if (digits.size() < 5)
return QString();
QByteArray number = digits.mid(1, 4).toLatin1();
char *end;
ulong ch = strtoul(number.constData(), &end, 16);
if (*end != '\0')
return QString();
*advance = 4;
return QString(QChar(static_cast<ushort>(ch)));
} else if (digits.at(0) == QLatin1Char('U')) {
if (digits.size() < 9)
return QString();
QByteArray number = digits.mid(1, 8).toLatin1();
char *end;
ulong ch = strtoul(number.constData(), &end, 16);
if (*end != '\0')
return QString();
*advance = 8;
if (ch > 0xFFFFU) {
const QChar utf16[2] = {
QChar::highSurrogate(ch),
QChar::lowSurrogate(ch),
};
return QString(utf16, 2);
} else {
return QString(QChar(static_cast<ushort>(ch)));
}
} else {
// Octal no longer supported
qFatal("Unsupported character escape prefix");
return QString();
}
}
QString SearchDialog::translateEscapes(const QString &text) {
QString result;
result.reserve(text.size());
int start = 0;
for (;;) {
int pos = text.indexOf(QLatin1Char('\\'), start);
if (pos < 0 || pos + 1 >= text.size())
break;
result.append(text.sliced(start, pos - start));
QChar next = text.at(pos + 1);
start = pos + 2;
switch (next.unicode()) {
case 'a':
result.append(QLatin1Char('\a'));
break;
case 'b':
result.append(QLatin1Char('\b'));
break;
case 'e':
result.append(QLatin1Char('\x1b'));
break;
case 'f':
result.append(QLatin1Char('\f'));
break;
case 'n':
result.append(QLatin1Char('\n'));
break;
case 'r':
result.append(QLatin1Char('\r'));
break;
case 't':
result.append(QLatin1Char('\t'));
break;
case 'v':
result.append(QLatin1Char('\v'));
break;
case '\\':
case '?':
case '\'':
case '"':
result.append(next);
break;
case 'x': // Hex byte
case 'u': // Unicode character (16-bit)
case 'U': // Unicode character (32-bit)
{
int advance;
const QString chars =
translateCharEscape(QStringView(text).mid(pos + 1), &advance);
if (chars.isEmpty()) {
// Translation failed
result.append(QLatin1Char('\\'));
result.append(next);
} else {
result.append(chars);
start += advance;
}
} break;
default:
// Just keep unrecognized sequences untranslated
result.append(QLatin1Char('\\'));
result.append(next);
break;
}
}
result.append(text.sliced(start));
return result;
}
QString SearchDialog::regexReplace(const QString &text,
const QRegularExpressionMatch &regexMatch) {
QString result;
result.reserve(text.size());
int start = 0;
for (;;) {
int pos = text.indexOf(QLatin1Char('\\'), start);
if (pos < 0 || pos + 1 >= text.size())
break;
result.append(text.sliced(start, pos - start));
QChar next = text.at(pos + 1);
if (next.unicode() >= '0' && next.unicode() <= '9') {
// We support up to 99 replacements...
QByteArray number = QStringView(text).mid(pos + 1, 2).toLatin1();
char *end;
ulong ref = strtoul(number.constData(), &end, 10);
result.append(regexMatch.captured(ref));
start = pos + 1 + (end - number.constData());
} else {
result.append(QLatin1Char('\\'));
result.append(next);
start = pos + 2;
}
}
result.append(text.sliced(start));
return result;
}
void SearchDialog::syncSearchSettings(bool saveRecent) {
const QString searchText = m_searchText->currentText();
if (!searchText.isEmpty() && saveRecent) {
if (m_searchText->count() == 0 ||
m_searchText->itemText(0) != searchText) {
m_searchText->insertItem(0, searchText);
}
}
m_searchParams.searchText =
m_escapes->isChecked() ? translateEscapes(searchText) : searchText;
const QString replaceText = m_replaceText->currentText();
if (!replaceText.isEmpty() && saveRecent) {
if (m_replaceText->count() == 0 ||
m_replaceText->itemText(0) != replaceText) {
m_replaceText->insertItem(0, replaceText);
}
}
m_searchParams.caseSensitive = m_caseSensitive->isChecked();
m_searchParams.wholeWord = m_wholeWord->isChecked();
m_searchParams.regex = m_regex->isChecked();
}
QTextCursor SearchDialog::searchNext(bool reverse) {
Q_ASSERT(m_editor);
if (m_searchParams.searchText.isEmpty())
return QTextCursor();
auto searchCursor = m_editor->textSearch(
m_editor->textCursor(), m_searchParams, false, reverse, &m_regexMatch);
if (searchCursor.isNull() && m_wrapSearch->isChecked()) {
QTextCursor wrapCursor = m_editor->textCursor();
wrapCursor.movePosition(reverse ? QTextCursor::End
: QTextCursor::Start);
searchCursor = m_editor->textSearch(wrapCursor, m_searchParams, true,
reverse, &m_regexMatch);
}
if (searchCursor.isNull())
WingMessageBox::information(this, QString(),
tr("The specified text was not found"));
else
m_editor->setTextCursor(searchCursor);
return searchCursor;
}
void SearchDialog::searchForward() {
syncSearchSettings(true);
m_replaceCursor = searchNext(false);
}
void SearchDialog::searchBackward() {
syncSearchSettings(true);
m_replaceCursor = searchNext(true);
}
void SearchDialog::replaceCurrent() {
syncSearchSettings(true);
Q_ASSERT(m_editor);
const QString searchText = m_searchText->currentText();
if (searchText.isEmpty())
return;
if (m_replaceCursor.isNull() || m_replaceCursor != m_editor->textCursor()) {
m_replaceCursor = searchNext(false);
return;
}
QString replaceText = m_replaceText->currentText();
if (m_escapes->isChecked())
replaceText = translateEscapes(replaceText);
m_replaceCursor.beginEditBlock();
m_replaceCursor.removeSelectedText();
if (m_regex->isChecked())
m_replaceCursor.insertText(regexReplace(replaceText, m_regexMatch));
else
m_replaceCursor.insertText(replaceText);
m_replaceCursor.endEditBlock();
m_replaceCursor = searchNext(false);
}
void SearchDialog::performReplaceAll(ReplaceAllMode mode) {
syncSearchSettings(true);
Q_ASSERT(m_editor);
const QString searchText = m_searchText->currentText();
if (searchText.isEmpty())
return;
auto searchCursor = m_editor->textCursor();
if (mode == InSelection)
searchCursor.setPosition(m_editor->textCursor().selectionStart());
else
searchCursor.movePosition(QTextCursor::Start);
searchCursor = m_editor->textSearch(searchCursor, m_searchParams, true,
false, &m_regexMatch);
if (searchCursor.isNull()) {
QMessageBox::information(this, QString(),
tr("The specified text was not found"));
return;
} else if (mode == InSelection &&
searchCursor.selectionEnd() >
m_editor->textCursor().selectionEnd()) {
WingMessageBox::information(
this, QString(),
tr("The specified text was not found in the selection"));
return;
}
QString replaceText = m_replaceText->currentText();
if (m_escapes->isChecked())
replaceText = translateEscapes(replaceText);
searchCursor.beginEditBlock();
auto replaceCursor = searchCursor;
int replacements = 0;
while (!replaceCursor.isNull()) {
if (mode == InSelection && replaceCursor.selectionEnd() >
m_editor->textCursor().selectionEnd())
break;
replaceCursor.removeSelectedText();
if (m_regex->isChecked())
replaceCursor.insertText(regexReplace(replaceText, m_regexMatch));
else
replaceCursor.insertText(replaceText);
replaceCursor = m_editor->textSearch(replaceCursor, m_searchParams,
false, false, &m_regexMatch);
++replacements;
}
searchCursor.endEditBlock();
WingMessageBox::information(
this, QString(),
tr("Successfully replaced %1 matches").arg(replacements));
}

113
src/dialog/searchdialog.h Normal file
View File

@ -0,0 +1,113 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef QTEXTPAD_SEARCHDIALOG_H
#define QTEXTPAD_SEARCHDIALOG_H
#include <QList>
#include <QRegularExpressionMatch>
#include <QTextCursor>
#include "dialog/framelessdialogbase.h"
#include "wingcodeedit.h"
class QLineEdit;
class QComboBox;
class QCheckBox;
class QPushButton;
class QTextCursor;
class SearchWidget : public QWidget {
Q_OBJECT
public:
explicit SearchWidget(WingCodeEdit *editor, QWidget *parent);
QSize sizeHint() const override {
// Make the default just a bit wider
const QSize parentHint = QWidget::sizeHint();
return {(parentHint.width() * 5) / 4, parentHint.height()};
}
void setSearchText(const QString &text);
void activate();
public Q_SLOTS:
void searchNext(bool reverse);
protected:
void paintEvent(QPaintEvent *event) override;
private Q_SLOTS:
void updateSettings();
private:
QLineEdit *m_searchText;
QAction *m_caseSensitive;
QAction *m_wholeWord;
QAction *m_regex;
QAction *m_escapes;
QAction *m_wrapSearch;
WingCodeEdit *m_editor;
WingCodeEdit::SearchParams m_searchParams;
};
class SearchDialog : public FramelessDialogBase {
Q_OBJECT
public:
static SearchDialog *create(WingCodeEdit *editor, QWidget *parent);
virtual ~SearchDialog();
static QString translateEscapes(const QString &text);
static QString regexReplace(const QString &text,
const QRegularExpressionMatch &regexMatch);
public Q_SLOTS:
QTextCursor searchNext(bool reverse);
private Q_SLOTS:
void searchForward();
void searchBackward();
void replaceCurrent();
private:
explicit SearchDialog(QWidget *parent);
void syncSearchSettings(bool saveRecent);
enum ReplaceAllMode { WholeDocument, InSelection };
void performReplaceAll(ReplaceAllMode mode);
QComboBox *m_searchText;
QComboBox *m_replaceText;
QCheckBox *m_caseSensitive;
QCheckBox *m_wholeWord;
QCheckBox *m_regex;
QCheckBox *m_escapes;
QCheckBox *m_wrapSearch;
QPushButton *m_replaceSelectionButton;
QTextCursor m_replaceCursor;
WingCodeEdit *m_editor;
WingCodeEdit::SearchParams m_searchParams;
QRegularExpressionMatch m_regexMatch;
};
#endif // QTEXTPAD_SEARCHDIALOG_H

View File

@ -23,11 +23,14 @@
#include "control/popupactionwidget.h"
#include "control/settingspopup.h"
#include "control/toast.h"
#include "dialog/definitiondownload.h"
#include "dialog/encodingdialog.h"
#include <QThread>
#include <QVBoxLayout>
#include <KSyntaxHighlighting/Repository>
constexpr auto EMPTY_FUNC = [] {};
class SyntaxPopupAction : public PopupActionWidget {
@ -67,7 +70,6 @@ ShowTextDialog::ShowTextDialog(QWidget *parent) : FramelessDialogBase(parent) {
layout->addWidget(q_check_ptr(m_ribbon));
m_edit = new CodeEdit(this);
m_edit->setShowLongLineEdge(false);
m_edit->setReadOnly(true);
m_edit->setAcceptDrops(false);
@ -79,6 +81,13 @@ ShowTextDialog::ShowTextDialog(QWidget *parent) : FramelessDialogBase(parent) {
layout->addWidget(m_status);
buildUpContent(cw);
m_syntaxButton = new QToolButton(this);
m_syntaxButton->setAutoRaise(true);
m_syntaxButton->setPopupMode(QToolButton::InstantPopup);
m_syntaxButton->addAction(new SyntaxPopupAction(this));
m_status->addPermanentWidget(m_syntaxButton);
// ok, preparing for starting...
this->setWindowTitle(tr("TextBroswer"));
this->setWindowIcon(ICONRES(QStringLiteral("viewtxt")));
@ -91,38 +100,45 @@ ShowTextDialog::~ShowTextDialog() {}
void ShowTextDialog::setSyntax(const KSyntaxHighlighting::Definition &syntax) {
m_edit->setSyntax(syntax);
if (syntax.isValid()) {
m_syntaxButton->setText(syntax.translatedName() + QChar(' ') +
QChar(char16_t(0x25BC)));
} else {
m_syntaxButton->setText(tr("Plain Text") + QChar(' ') +
QChar(char16_t(0x25BC)));
}
}
void ShowTextDialog::load(QHexBuffer *buffer, const QString encoding) {
// auto editor = m_edit->editor();
// editor->blockSignals(true);
// editor->setCodec(encoding);
// load(buffer, offset, size);
// editor->blockSignals(false);
}
void ShowTextDialog::load(QHexBuffer *buffer) {
void ShowTextDialog::load(QHexBuffer *buffer, const QString &mime,
const QString &encoding) {
constexpr auto MAXLEN = 1024 * 1024 * 1024;
if (buffer->length() > MAXLEN) {
WingMessageBox::critical(this, this->windowTitle(), tr("TooHugeFile"));
return;
}
m_edit->setUpdatesEnabled(false);
// auto doc = editor->document();
// auto orign = offset;
m_edit->setUpdatesEnabled(true);
// m_status->showMessage(editor->codecName());
show();
m_status->showMessage(tr("Loading..."));
QString enc;
auto ecs = Utilities::getEncodings();
if (encoding.isEmpty() || !ecs.contains(encoding)) {
enc = QStringLiteral("ASCII");
} else {
enc = encoding;
}
this->buffer = buffer->read(qsizetype(0), buffer->length());
m_edit->setPlainText(Utilities::decodingString(this->buffer, enc));
m_status->showMessage(enc);
setSyntax(WingCodeEdit::syntaxRepo().definitionForMimeType(mime));
}
void ShowTextDialog::buildUpRibbonBar() {
m_ribbon = new Ribbon(this);
m_ribbon->setAcceptDrops(false);
buildEditPage(m_ribbon->addTab(tr("Edit")));
buildViewPage(m_ribbon->addTab(tr("View")));
}
RibbonTabContent *ShowTextDialog::buildEditPage(RibbonTabContent *tab) {
@ -146,28 +162,20 @@ RibbonTabContent *ShowTextDialog::buildEditPage(RibbonTabContent *tab) {
addPannelAction(pannel, QStringLiteral("encoding"), tr("Encoding"),
&ShowTextDialog::on_encoding,
shortcuts.keySequence(QKeySequences::Key::ENCODING));
addPannelAction(pannel, QStringLiteral("defines"), tr("UpdateDefs"),
&ShowTextDialog::on_updateDefs);
}
return tab;
}
RibbonTabContent *ShowTextDialog::buildViewPage(RibbonTabContent *tab) {
auto shortcuts = QKeySequences::instance();
auto pannel = tab->addGroup(tr("Display"));
return tab;
}
void ShowTextDialog::on_copyfile() {
m_edit->copy();
Toast::toast(this, NAMEICONRES(QStringLiteral("copy")),
tr("CopyToClipBoard"));
}
void ShowTextDialog::on_findfile() {
// m_edit->editor()->find();
}
void ShowTextDialog::on_findfile() { m_edit->showSearchBar(true); }
void ShowTextDialog::on_gotoline() {
// m_edit->editor()->gotoLine();
@ -177,8 +185,17 @@ void ShowTextDialog::on_encoding() {
EncodingDialog d;
if (d.exec()) {
auto res = d.getResult();
// m_edit->editor()->setCodec(res);
m_status->showMessage(tr("Loading..."));
m_edit->setPlainText(Utilities::decodingString(this->buffer, res));
m_status->showMessage(res);
}
}
void ShowTextDialog::on_cancel() { m_canceled = true; }
void ShowTextDialog::on_updateDefs() {
auto downloadDialog =
new DefinitionDownloadDialog(&WingCodeEdit::syntaxRepo(), this);
downloadDialog->setAttribute(Qt::WA_DeleteOnClose);
downloadDialog->show();
downloadDialog->raise();
downloadDialog->activateWindow();
}

View File

@ -43,14 +43,13 @@ public:
void setSyntax(const KSyntaxHighlighting::Definition &syntax);
public:
void load(QHexBuffer *buffer, const QString encoding);
void load(QHexBuffer *buffer);
void load(QHexBuffer *buffer, const QString &mime,
const QString &encoding = {});
private:
void buildUpRibbonBar();
RibbonTabContent *buildEditPage(RibbonTabContent *tab);
RibbonTabContent *buildViewPage(RibbonTabContent *tab);
private:
template <typename Func>
@ -119,21 +118,15 @@ private slots:
void on_findfile();
void on_gotoline();
void on_encoding();
void on_cancel();
void on_updateDefs();
private:
Ribbon *m_ribbon = nullptr;
CodeEdit *m_edit = nullptr;
bool m_canceled = false;
QStatusBar *m_status = nullptr;
QToolButton *m_syntaxButton = nullptr;
struct {
QHexBuffer *buffer = nullptr;
qsizetype offset = 0;
qsizetype size = -1;
} m_last;
QByteArray buffer;
};
#endif // SHOWTEXTDIALOG_H

View File

@ -1,17 +1,19 @@
/****************************************************************************
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This file is part of the Edyuk project <http://edyuk.org>
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** This file may be used under the terms of the GNU General Public License
** version 3 as published by the Free Software Foundation and appearing in the
** file GPL.txt included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "qeditconfig.h"

View File

@ -1,3 +1,20 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef QEDITCONFIG_H
#define QEDITCONFIG_H