1 /************************************************************************
2 **
3 **  Copyright (C) 2015-2019 Kevin B. Hendricks, Stratford Ontario Canada
4 **  Copyright (C) 2016-2020 Doug Massay
5 **  Copyright (C) 2009-2011 Strahinja Markovic  <strahinja.markovic@gmail.com>
6 **
7 **  This file is part of Sigil.
8 **
9 **  Sigil is free software: you can redistribute it and/or modify
10 **  it under the terms of the GNU General Public License as published by
11 **  the Free Software Foundation, either version 3 of the License, or
12 **  (at your option) any later version.
13 **
14 **  Sigil is distributed in the hope that it will be useful,
15 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 **  GNU General Public License for more details.
18 **
19 **  You should have received a copy of the GNU General Public License
20 **  along with Sigil.  If not, see <http://www.gnu.org/licenses/>.
21 **
22 *************************************************************************/
23 
24 #pragma once
25 #ifndef UTILITY_H
26 #define UTILITY_H
27 
28 
29 #include <QCoreApplication>
30 #include <QtCore/QString>
31 #include <QColor>
32 #include <QSet>
33 
34 class QStringList;
35 class QStringRef;
36 class QWidget;
37 class QMenu;
38 
39 struct ExceptionBase;
40 
41 class Utility
42 {
43     Q_DECLARE_TR_FUNCTIONS(Utility)
44 
45 public:
46 
47     enum Casing {
48         Casing_Uppercase,     /**< Change characters to uppercase */
49         Casing_Lowercase,     /**< Change characters to lowercase */
50         Casing_Titlecase,    /**< Change first character of each word to uppercase, reset to lowercase. */
51         Casing_Capitalize,    /**< Change first character of sentence to uppercase, rest to lowercase. */
52     };
53 
54     enum Val_Msg_Type {
55         INFO_BRUSH,
56         WARNING_BRUSH,
57         ERROR_BRUSH,
58     };
59 
60     static QString ChangeCase(const QString &text, const Casing &casing);
61 
62     // Define the user preferences location to be used
63     static QString DefinePrefsDir();
64 
65     // Indicates if application palette in dark mode
66     static bool IsDarkMode();
67 
68     // Indicates Windows system dark mode is enabled
69     static bool IsWindowsSysDarkMode();
70 
71     // Should Windows Sigil be using dark mode?
72     static bool WindowsShouldUseDarkMode();
73 
74 #if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
75     // Return correct path(s) for Linux hunspell dictionaries
76     static QStringList LinuxHunspellDictionaryDirs();
77 #endif
78 
79     // Uses QUuid to generate a random UUID but also removes
80     // the curly braces that QUuid::createUuid() adds
81     static QString CreateUUID();
82 
83     // Returns true if the string is mixed case, false otherwise.
84     // For instance, "test" and "TEST" return false, "teSt" returns true.
85     static bool IsMixedCase(const QString &string);
86 
87     // Returns a substring of a QStringRef as a real string
88     // the characters included are in the interval:
89     // [ start_index, end_index >
90     static QString Substring(int start_index, int end_index, const QStringRef &string);
91 
92     // Returns a substring of a specified string;
93     // the characters included are in the interval:
94     // [ start_index, end_index >
95     static QString Substring(int start_index, int end_index, const QString &string);
96 
97     // Returns a substring of a specified string;
98     // the characters included are in the interval:
99     // [ start_index, end_index >
100     static QStringRef SubstringRef(int start_index, int end_index, const QString &string);
101 
102     // Replace the first occurrence of string "before"
103     // with string "after" in string "string"
104     static QString ReplaceFirst(const QString &before, const QString &after, const QString &string);
105 
106     // Copies every file and folder in the source folder
107     // to the destination folder; the paths to the folders are submitted;
108     // the destination folder needs to be created in advance
109     static void CopyFiles(const QString &fullfolderpath_source, const QString &fullfolderpath_destination);
110 
111     // Johns own recursive directory removal code
112     static bool removeDir(const QString &dirName);
113 
114     // Deletes the specified file if it exists
115     static bool SDeleteFile(const QString &fullfilepath);
116 
117     static bool ForceCopyFile(const QString &fullinpath, const QString &fulloutpath);
118 
119     static bool SMoveFile(const QString &oldfilepath, const QString &newfilepath);
120 
121     static bool RenameFile(const QString &oldfilepath, const QString &newfilepath);
122 
123     // Returns path to a random filename with the specified extension in
124     // the systems TEMP directory. The caller has responsibility for
125     // creating a file at this location and removing it afterwards.
126     static QString GetTemporaryFileNameWithExtension(const QString &extension);
127 
128     // Returns true if the file can be read;
129     // shows an error dialog if it can't
130     // with a message elaborating what's wrong
131     static bool IsFileReadable(const QString &fullfilepath);
132 
133     // Reads the text file specified with the full file path;
134     // text needs to be in UTF-8 or UTF-16; if the file cannot
135     // be read, an error dialog is shown and an empty string returned
136     static QString ReadUnicodeTextFile(const QString &fullfilepath);
137 
138     // Writes the provided text variable to the specified
139     // file; if the file exists, it is truncated
140     static void WriteUnicodeTextFile(const QString &text, const QString &fullfilepath);
141 
142     // Converts Mac and Windows style line endings to Unix style
143     // line endings that are expected throughout the Qt framework
144     static QString ConvertLineEndings(const QString &text);
145 
146     // Decodes XML escaped string to normal text
147     // &amp; -> &    &apos; -> '  &quot; -> "   &lt; -> <  &gt; -> >
148     static QString DecodeXML(const QString &text);
149 
150     // Encodes (Escapes) XML string
151     // & -> &amp;    ' -> &apos;    " -> &quot;   < -> &lt;     > ->  &gt;
152     static QString EncodeXML(const QString &text);
153 
154 
155     /**
156      * URL encodes the provided path string.
157      * The path separator ('/') and the ID hash ('#') are left alone.
158      *
159      * @param path The path to encode.
160      * @return The encoded path string.
161      */
162     static bool NeedToPercentEncode(uint cp);
163     static QString URLEncodePath(const QString &path);
164 
165     /**
166      * URL decodes the provided path string.
167      *
168      * @param path The path to decode.
169      * @return The decoded path string.
170      */
171     static QString URLDecodePath(const QString &path);
172 
173     static void DisplayStdErrorDialog(const QString &error_message, const QString &detailed_text = QString());
174 
175     static void DisplayStdWarningDialog(const QString &warning_message, const QString &detailed_text = QString());
176 
177     static void DisplayExceptionErrorDialog(const QString &error_info);
178 
179     // Returns a value for the environment variable name passed;
180     // if the env var isn't set, it returns an empty string
181     static QString GetEnvironmentVar(const QString &variable_name);
182 
183     // Returns the same number, but rounded to one decimal place
184     static float RoundToOneDecimal(float number);
185 
186     static QWidget *GetMainWindow();
187 
188     static QString getSpellingSafeText(const QString &raw_text);
189 
190     static bool has_non_ascii_chars(const QString &str);
191     static bool use_filename_warning(const QString &filename);
192 
193 #if defined(Q_OS_WIN32)
194     static std::wstring QStringToStdWString(const QString &str);
195     static QString stdWStringToQString(const std::wstring &str);
196 #endif
197 
198     static bool UnZip(const QString &zippath, const QString &destdir);
199     static QStringList ZipInspect(const QString &zippath);
200 
201     // Generate relative path to destination from starting directory path
202     // Both paths should be absolute and preferably cannonical
203     static QString relativePath(const QString & destination, const QString & starting_dir);
204 
205     // works with absolute or book paths
206     static QString longestCommonPath(const QStringList& filepaths, const QString& sep);
207 
208     // works with absolute or book paths
209     static QString resolveRelativeSegmentsInFilePath(const QString& file_path, const QString &sep);
210 
211     // start_folder is the book path (internal to epub) to the starting folder
212     static QString buildBookPath(const QString& dest_relpath, const QString& start_folder);
213 
214     // both the "from" and "to" book paths are to FILES
215     static QString buildRelativePath(const QString &from_file_bkpath, const QString &to_file_bkpath);
216 
217     static std::pair<QString, QString> parseRelativeHREF(const QString &relative_href);
218 
219     static QString buildRelativeHREF(const QString &apath, const QString &afrag);
220 
221     static QString startingDir(const QString &file_bookpath);
222 
223     // sort list of strings by list of counts in a decreasing fashion, highest count first
224     static bool sort_pair_in_reverse(const std::pair<int,QString> &a, const std::pair<int,QString> &b);
225     static QStringList sortByCounts(const QStringList &folderlst, const QList<int> &countlst);
226 
227     // perform a locale aware string sort
228     static QStringList LocaleAwareSort(const QStringList &names);
229 
230     // inject dark mode css into html for Preview, AVTab, ImageTab, ViewImage, and SelectFiles
231     static QString AddDarkCSS(const QString &html);
232 
233     // return the proper background color for QWebEngineView
234     static QColor WebViewBackgroundColor(bool followpref = false);
235 
236     // return the qbrushes for ValidationResultsView
237     static QBrush ValidationResultBrush(const Val_Msg_Type &valres);
238 
239     // parse a line of data from a csv file into a list of string values
240     static QStringList parseCSVLine(const QString &data);
241 
242     // create a line of data in csv format
243     static QString createCSVLine(const QStringList &data);
244 
245     // Generate a Unique Id given a root id and Used Set
246     static QString GenerateUniqueId(const QString &id, const QSet<QString>& Used);
247 
248 };
249 #endif // UTILITY_H
250 
251 
252