1/*
2 * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#ifndef REDPANDA_QT_UTILS_H
18#define REDPANDA_QT_UTILS_H
19#include <type_traits>
20#include <utility>
21#include <functional>
22#include <QString>
23#include <QRect>
24#include <QStringList>
25#include <memory>
26#include <QThread>
27#include <QProcessEnvironment>
28
29class QByteArray;
30class QTextStream;
31class QTextCodec;
32
33#define ENCODING_AUTO_DETECT "AUTO"
34#define ENCODING_UTF8 "UTF-8"
35#define ENCODING_UTF8_BOM "UTF-8 BOM"
36#define ENCODING_SYSTEM_DEFAULT "SYSTEM"
37#define ENCODING_ASCII "ASCII"
38
39enum class FileEndingType {
40 Windows,
41 Linux,
42 Mac
43};// Windows: CRLF, UNIX: LF, Mac: CR
44
45class BaseError{
46public:
47 explicit BaseError(const QString& reason);
48 QString reason() const;
49
50protected:
51 QString mReason;
52};
53
54class IndexOutOfRange:public BaseError {
55public:
56 explicit IndexOutOfRange(int Index);
57};
58
59class FileError: public BaseError {
60public:
61 explicit FileError(const QString& reason);
62};
63
64/* text processing utils */
65const QByteArray guessTextEncoding(const QByteArray& text);
66
67bool isTextAllAscii(const QByteArray& text);
68bool isTextAllAscii(const QString& text);
69
70bool isNonPrintableAsciiChar(char ch);
71
72using LineProcessFunc = std::function<void(const QString&)>;
73
74QStringList textToLines(const QString& text);
75void textToLines(const QString& text, LineProcessFunc lineFunc);
76QString linesToText(const QStringList& lines, const QString& lineBreak="\n");
77
78QList<QByteArray> splitByteArrayToLines(const QByteArray& content);
79
80QString trimRight(const QString& s);
81QString trimLeft(const QString& s);
82
83int countLeadingWhitespaceChars(const QString& line);
84
85bool stringIsBlank(const QString& s);
86
87QByteArray toByteArray(const QString& s);
88QString fromByteArray(const QByteArray& s);
89
90/* text I/O utils */
91
92QStringList readStreamToLines(QTextStream* stream);
93void readStreamToLines(QTextStream* stream, LineProcessFunc lineFunc);
94
95/**
96 * @brief readFileToLines
97 * @param fileName
98 * @param codec
99 * @return
100 */
101QStringList readFileToLines(const QString& fileName, QTextCodec* codec);
102QStringList readFileToLines(const QString& fileName);
103void readFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
104
105QByteArray readFileToByteArray(const QString& fileName);
106
107void stringsToFile(const QStringList& list, const QString& fileName);
108void stringToFile(const QString& str, const QString& fileName);
109
110/* File I/O utils */
111bool fileExists(const QString& file);
112bool fileExists(const QString& dir, const QString& fileName);
113bool directoryExists(const QString& file);
114bool removeFile(const QString& filename);
115void copyFolder(const QString &fromDir, const QString& toDir);
116bool copyFile(const QString &fromFile, const QString& toFile, bool overwrite);
117
118QString includeTrailingPathDelimiter(const QString& path);
119QString excludeTrailingPathDelimiter(const QString& path);
120QString changeFileExt(const QString& filename, QString ext);
121
122QString localizePath(const QString& path);
123
124QString extractRelativePath(const QString& base, const QString& dest);
125QString extractFileName(const QString& fileName);
126QString extractFileDir(const QString& fileName);
127QString extractFilePath(const QString& filePath);
128QString extractAbsoluteFilePath(const QString& filePath);
129
130bool isReadOnly(const QString& filename);
131
132int compareFileModifiedTime(const QString& filename1, const QString& filename2);
133
134/* UI utils */
135void inflateRect(QRect& rect, int delta);
136void inflateRect(QRect& rect, int dx, int dy);
137
138int screenDPI();
139void setScreenDPI(int dpi);
140float pointToPixel(float point);
141float pointToPixel(float point, float dpi);
142float pixelToPoint(float pixel);
143
144void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);
145
146
147/**
148 * from https://github.com/Microsoft/GSL
149 **/
150
151template <class F>
152class final_action
153{
154public:
155 static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
156 !std::is_volatile<F>::value,
157 "Final_action should store its callable by value");
158
159 explicit final_action(F f) noexcept : f_(std::move(f)) {}
160
161 final_action(final_action&& other) noexcept
162 : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
163 {}
164
165 final_action(const final_action&) = delete;
166 final_action& operator=(const final_action&) = delete;
167 final_action& operator=(final_action&&) = delete;
168
169 ~final_action() noexcept
170 {
171 if (invoke_) f_();
172 }
173
174private:
175 F f_;
176 bool invoke_{true};
177};
178
179template <class F> final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>
180finally(F&& f) noexcept
181{
182 return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
183 std::forward<F>(f));
184}
185#endif // UTILS_H
186