123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- #include "sheets/codesheet.h"
- #include "widgets/codeeditor.h"
- #include "widgets/codesearchbar.h"
- #include "windows/rememberdialog.h"
- #include "windows/progressdialog.h"
- #include "base/application.h"
- #include <KSyntaxHighlighting/Definition>
- #include <KSyntaxHighlighting/DefinitionDownloader>
- #include <QAbstractButton>
- #include <QAction>
- #include <QBoxLayout>
- #include <QFileInfo>
- #include <QPushButton>
- #include <QRegularExpression>
- #include <QScrollBar>
- #include <QTextCodec>
- CodeSheet::CodeSheet(const ResourceModelIndex &index, QWidget *parent)
- : BaseFileSheet(index, parent)
- {
- filePath = index.path();
- QString sheetTitle = filePath.section('/', -2);
- QRegularExpression guid("^{\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}}");
- if (guid.match(sheetTitle).hasMatch()) {
- sheetTitle = sheetTitle.split('/').last();
- }
- setSheetTitle(sheetTitle);
- btnDownloadDefinitions = new QPushButton(this);
- btnDownloadDefinitions->hide();
- connect(btnDownloadDefinitions, &QPushButton::clicked, this, &CodeSheet::downloadDefinitions);
- editor = new CodeEditor(this);
- editor->setCenterOnScroll(true);
- const auto definition = app->highlightingRepository.definitionForFileName(filePath);
- if (definition.isValid()) {
- editor->setDefinition(definition);
- } else {
- checkFormatSupport();
- }
- searchBar = new CodeSearchBar(editor);
- connect(editor, &CodeEditor::searchFinished, searchBar, &CodeSearchBar::setResults);
- auto statusBar = new QHBoxLayout;
- statusBar->addWidget(btnDownloadDefinitions);
- auto layout = new QVBoxLayout(this);
- layout->addWidget(editor);
- layout->addWidget(searchBar);
- layout->addLayout(statusBar);
- layout->setMargin(0);
- layout->setSpacing(0);
- load();
- connect(editor, &QPlainTextEdit::modificationChanged, this, &CodeSheet::setModified);
- // Initialize actions:
- addActionSeparator();
- auto actionWordWrap = app->actions.getWordWrap(this);
- actionWordWrap->setChecked(editor->getWordWrap());
- addAction(actionWordWrap);
- connect(actionWordWrap, &QAction::triggered, editor, &CodeEditor::setWordWrap);
- addActionSeparator();
- auto actionFind = app->actions.getFind(this);
- addAction(actionFind);
- connect(actionFind, &QAction::triggered, this, &CodeSheet::findSelectedText);
- auto actionFindNext = app->actions.getFindNext(this);
- addAction(actionFindNext);
- connect(actionFindNext, &QAction::triggered, this, [=]() {
- searchBar->show();
- editor->nextSearchQuery();
- });
- auto actionFindPrevious = app->actions.getFindPrevious(this);
- addAction(actionFindPrevious);
- connect(actionFindPrevious, &QAction::triggered, this, [=]() {
- searchBar->show();
- editor->prevSearchQuery();
- });
- auto actionReplace = app->actions.getReplace(this);
- addAction(actionReplace);
- connect(actionReplace, &QAction::triggered, this, &CodeSheet::replaceSelectedText);
- retranslate();
- }
- bool CodeSheet::load()
- {
- QFile file(index.path());
- if (file.open(QFile::ReadOnly)) {
- QTextStream stream(&file);
- stream.setCodec("UTF-8"); // Fallback if no codec is detected on further read
- auto cursor = editor->textCursor();
- const int selectionStart = cursor.selectionStart();
- const int selectionEnd = cursor.selectionEnd();
- const int scrollPosition = editor->verticalScrollBar()->value();
- editor->setPlainText(stream.readAll());
- codec = stream.codec(); // Qt automatically deletes the codec on exit
- cursor.setPosition(selectionStart);
- cursor.setPosition(selectionEnd, QTextCursor::KeepAnchor);
- editor->setTextCursor(cursor);
- editor->verticalScrollBar()->setValue(scrollPosition);
- setModified(false);
- return true;
- }
- qWarning() << "Error: Could not open code resource file";
- return false;
- }
- bool CodeSheet::save(const QString &as)
- {
- QFile file(as.isEmpty() ? index.path() : as);
- if (file.open(QFile::WriteOnly)) {
- file.resize(0);
- QTextStream stream(&file);
- stream.setCodec(codec);
- stream.setGenerateByteOrderMark(codec->name() != "UTF-8");
- stream << editor->toPlainText();
- if (as.isEmpty()) {
- setModified(false);
- emit saved();
- }
- return true;
- }
- qWarning() << "Error: Could not save code resource file";
- return false;
- }
- void CodeSheet::setTextCursor(int lineNumber, int columnNumber, int selectionLength)
- {
- auto cursor = editor->textCursor();
- cursor.movePosition(QTextCursor::Start);
- cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, lineNumber - 1);
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, columnNumber);
- if (selectionLength > 0) {
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, selectionLength);
- }
- editor->setTextCursor(cursor);
- }
- void CodeSheet::changeEvent(QEvent *event)
- {
- if (event->type() == QEvent::LanguageChange) {
- retranslate();
- }
- BaseSheet::changeEvent(event);
- }
- void CodeSheet::keyPressEvent(QKeyEvent *event)
- {
- if (event->key() == Qt::Key_Escape) {
- searchBar->hide();
- }
- BaseFileSheet::keyPressEvent(event);
- }
- void CodeSheet::findSelectedText()
- {
- auto cursor = editor->textCursor();
- if (!cursor.hasSelection()) {
- cursor.select(QTextCursor::WordUnderCursor);
- }
- const auto selection(cursor.selectedText());
- cursor.setPosition(cursor.selectionStart()); // Move to the beginning of the selection and clear it
- editor->setTextCursor(cursor);
- searchBar->setFindText(selection);
- searchBar->show();
- searchBar->focusFindBar();
- }
- void CodeSheet::replaceSelectedText()
- {
- const auto selection = editor->textCursor().selectedText();
- searchBar->show();
- searchBar->showReplaceBar();
- if (selection.isEmpty()) {
- searchBar->focusFindBar();
- } else {
- searchBar->setFindText(selection);
- searchBar->focusReplaceBar();
- }
- }
- void CodeSheet::checkFormatSupport()
- {
- const auto fileName = QFileInfo(filePath).fileName();
- for (const auto &extension : supportedExtensions()) {
- auto regex = QRegularExpression::wildcardToRegularExpression(extension);
- if (QRegularExpression(regex).match(fileName).hasMatch()) {
- const QString question(tr("Would you like to download syntax definitions for this and other formats?"));
- if (RememberDialog::ask("download-syntax-definitions", question, this)) {
- downloadDefinitions();
- } else {
- btnDownloadDefinitions->show();
- }
- break;
- }
- }
- }
- void CodeSheet::downloadDefinitions()
- {
- auto progressDialog = new ProgressDialog(this);
- progressDialog->setPrimaryText(tr("Downloading syntax definitions..."));
- progressDialog->setCancelEnabled(false);
- progressDialog->show();
- auto downloader = new KSyntaxHighlighting::DefinitionDownloader(&app->highlightingRepository);
- connect(downloader, &KSyntaxHighlighting::DefinitionDownloader::informationMessage, [progressDialog](const QString &message) {
- qDebug() << message;
- });
- connect(downloader, &KSyntaxHighlighting::DefinitionDownloader::done, this, [=]() {
- editor->setDefinition(app->highlightingRepository.definitionForFileName(filePath));
- btnDownloadDefinitions->hide();
- downloader->deleteLater();
- progressDialog->deleteLater();
- });
- downloader->start();
- }
- void CodeSheet::retranslate()
- {
- btnDownloadDefinitions->setText(tr("Download Syntax Definitions"));
- }
- QStringList CodeSheet::supportedExtensions() const
- {
- return {
- "*.mustache", "*.handlebars", "*.hbs", "*.ractive", "*.hogan", "*.hulk", "*.html.mst", "*.html.mu", "*.html.rac",
- "*.kbasic",
- "*.per", "*.PER", "*.per.err",
- "*.csv",
- "*.xul", "*.xbl",
- "*.bat",
- "*.c++", "*.cxx", "*.cpp", "*.cc", "*.C", "*.h", "*.hh", "*.H", "*.h++", "*.hxx", "*.hpp", "*.hcc",
- "*.clist", "*.CLIST",
- "*.mll",
- "*.mtt",
- "*.k",
- "*.dtd",
- "*.reg",
- "*.pb", "*.pbi",
- "*.sql", "*.SQL", "*.ddl", "*.DDL",
- "*.supp",
- "*.asm",
- "*.ll",
- "*.prg", "*.PRG", "*.ch",
- "*.abc", "*.ABC",
- "*.scss",
- "*.graphql",
- "*.dat",
- "*.jira",
- "*.html",
- "*.sa",
- "*.oors",
- "*.stl",
- "*.cfg",
- "*.kt", "*.kts",
- "*.vhdl", "*.vhd",
- "*.dart",
- "*.jsp", "*.JSP",
- "*.eml", "*.email", "*.emlx", "*.mbox", "*.mbx",
- "*.c", "*.C", "*.h",
- "*.mod", "*.def",
- "*.idr",
- "*.clj", "*.cljs", "*.cljc",
- "*.php", "*.php3", "*.wml", "*.phtml", "*.phtm", "*.inc", "*.ctp",
- "*.cfg",
- "*.mab", "*.MAB", "*.Mab",
- "*.pro", "*.pri", "*.prf",
- "*.vtc",
- "*.e",
- "*.sv", "*.svh",
- "*.asm",
- "*.tsx",
- "*.nsi",
- "Jam*", "*.jam",
- "*.lgt", ".logtalk",
- "*.d", "*.D", "*.di", "*.DI",
- "*.lua", "*.rockspec",
- "changelog",
- "*.curry",
- "*.raku", "*.rakumod", "*.rakudoc", "*.rakutest", "*.pl6", "*.PL6", "*.p6", "*.pm6", "*.pod6",
- "*.java",
- "*.desktop", "*.kdelnk", "*.desktop.cmake",
- "Kconfig*", "Config.*",
- "*.t2t",
- "fstab", "mtab",
- "*.ad", "*.adoc", "*.asciidoc",
- "*.tex", "*.ltx", "*.dtx", "*.sty", "*.cls", "*.bbx", "*.cbx", "*.lbx", "*.tikz", "*.pgf",
- "*.sql", "*.SQL", "*.ddl", "*.DDL",
- "*.go",
- "*.csv",
- "*.css",
- "*.aff",
- "*.lcurry",
- "*.js", "*.mjs", "*.cjs", "*.kwinscript", "*.julius",
- "*.btm",
- "*.vala",
- "*.4th", "*.4TH", "*.f", "*.F", "*.frt", "*.FRT", "*.fs", "*.FS", "*.fth", "*.FTH", "*.seq", "*.SEQ",
- "*.adb", "*.ads", "*.ada", "*.a",
- "*.rng", "*.RNG",
- "*.erl",
- "*.asm", "*.inc", "*.ASM", "*.INC",
- "*.mml",
- "*.yang",
- "*.replicode",
- "*.w", "*.nw",
- "*.as",
- "*.mm", "*.M", "*.h",
- "*.f", "*.F", "*.for", "*.FOR", "*.fpp", "*.FPP",
- "*.m3", "*.i3", "*.ig", "*.mg",
- "*.s", "*.i", "*.S", "*.I",
- "*.sql", "*.SQL", "*.ddl", "*.DDL", "*.trg", "*.TRG", "*.spc", "*.SPC", "*.bdy", "*.DBY",
- "*.purs",
- "*.do", "*.ado", "*.doh", "*.DO", "*.ADO", "*.DOH",
- "*.mod", "*.def",
- "*.m3u",
- "*.sh", "*.zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".profile",
- "*.mod", "*.def",
- "*.inf", "*.h",
- "*.dic",
- "*.tig",
- "*.obj",
- ".kdesrc-buildrc", "kdesrc-buildrc",
- "*.rtf",
- "*.gdf",
- "*.pug", "*.jade",
- "*.properties",
- "*.sed",
- "*.p", "*.w", "*.i", "*.cls",
- "*.c++", "*.cxx", "*.cpp", "*.cc", "*.C", "*.h", "*.hh", "*.H", "*.h++", "*.hxx", "*.hpp", "*.hcc", "*.moc",
- "*.mup", "*.not",
- "*.v", "*.V", "*.vl",
- "*.logcat",
- "*.s",
- "*.vcl",
- "*.sci", "*.sce",
- "QRPG*.*", "qrpg*.*",
- "*.tf",
- "*.mod", "*.def",
- "*.prolog", "*.dcg", "*.pro",
- "*.pp",
- "*.n",
- "*.znn",
- "*.dot",
- "*.p", "*.pas", "*.pp",
- "*.1", "*.2", "*.3", "*.4", "*.5", "*.6", "*.7", "*.8", "*.1m", "*.3x", "*.tmac",
- "*.kcrash", "*.crash", "*.bt",
- "*.proto",
- "*.s", "*.S",
- "*.elm",
- "*.bib",
- "*.feature",
- "*.gdb",
- "*.texi",
- "*.cg", "*.cgfx",
- "*.hs", "*.chs", "*.hs-boot",
- "*.rib",
- "*.rs",
- "*.crk",
- "*.sp", "*.hsp",
- "*.nb",
- "*.tt*",
- "*.org",
- "*.ample", "*.menu", "*.startup",
- "*.less",
- "*.bb", "*.bbappend", "*.bbclass", "*.inc",
- "*.boo",
- "*.idl",
- "*.fe", "*.feh",
- "*.te", "*.if", "*.spt", "policy.conf", "access_vectors", "mls", "mcs", "mls_macros", "te_macros", "policy_capabilities", "seapp_contexts", "port_contexts",
- "*.haml",
- "*.pike",
- "*.qml", "*.qmltypes",
- "GNUmakefile", "Makefile", "makefile", "GNUmakefile.*", "Makefile.*", "makefile.*", "*.mk",
- "*.mako", "*.mak",
- "*.awk",
- "Dockerfile",
- "*.cfg", "*.pbl", "*.CFG", "*.PBL",
- "*.ninja",
- "*.htm", "*.html",
- "*.m4",
- "*.rkt", "*.scrbl",
- "*.cis",
- "*.mediawiki",
- "*.textile",
- "*.jl",
- "*.ldif",
- "*.hex", "*.ihx",
- "*.csv",
- "*.diff", "*patch", "*.rej",
- "*.g",
- "*.Rd",
- "Cakefile", "*.coffee", "*.coco", "*.cson",
- "gitolite.conf",
- "*.iss",
- "*.mch", "*.imp", "*.ref",
- "Doxyfile", "Doxyfile.*",
- "*.py", "*.pyw", "*.pyi", "SConstruct", "SConscript", "*.FCMacro",
- "*.iCal", "*.iCalendar", ".ics", "*.ifb", "*.iFBf", "*.vcal", "*.vcalendar", "*.vcard", "*.vcf",
- "*.asn", "*.asn1",
- "*.ftl",
- "*.pgn", "*.PGN",
- "*.md", "*.mmd", "*.markdown",
- "*.hamlet",
- "*.vb",
- "*.sst", "*.ssm", "*.ssi", "*._sst", "*.-sst",
- "*.ys",
- "*.rqb",
- "*.glsl", "*.vert", "*.vs", "*.frag", "*.fs", "*.geom", "*.gs", "*.tcs", "*.tes",
- "*.swift",
- "*.sgml",
- "*.nc",
- "*.fbs",
- "*.toml",
- "*.cp", "*.bro",
- "*.inc", "*.pov",
- "*.pl", "*.PL", "*.pm",
- "meson.build", "meson_options.txt",
- "*.vr", "*.vri", "*.vrh",
- "*.agda",
- "*.rnc",
- "*.c++", "*.cxx", "*.cpp", "*.cc", "*.C", "*.cu", "*.h", "*.hh", "*.H", "*.h++", "*.hxx", "*.hpp", "*.hcc", "*.cuh", "*.inl", "*.ino", "*.pde", "*.moc",
- "*.gnuplot", "*.gp", "*.gplt", "*.plt",
- "*.ml", "*.mli",
- "*.cfg",
- "*.nim", "*.nims", "*.nimble",
- "*.jsx",
- "*.c++", "*.cxx", "*.cpp", "*.cc", "*.C", "*.h", "*.hh", "*.H", "*.h++", "*.hxx", "*.hpp", "*.hcc", "*.moc",
- "ChangeLog",
- "*.sass",
- "git-rebase-todo",
- "*.ctx", "*.mkiv", "*.mkvi", "*.mkxl", "*.mklx",
- "*.nix",
- "*.idx",
- "*.cs", "*.ashx",
- "*.vm",
- "*.m", "*.h",
- "*.fastq", "*.fq", "*.fastq.gz", "*.fq.gz",
- "*.abap", "*.ABAP",
- "*.vcc",
- "*.fish", "fishd.*",
- "*.l", "*.lex", "*.flex",
- "*.srt",
- "*.stan", "*.stanfunctions",
- "*.ini", "*.pls", "*.kcfgc", ".gitattributes*", ".gitconfig*", ".gitmodules*", ".editorconfig*",
- "*.octave", "*.m", "*.M",
- "*.bas", "*.bi", "*.BAS", "*.BI",
- "*.cl",
- "*.rules", "*.snort", "*.suricata",
- "*.prg", "*.PRG", "*.ch",
- "*.csh", "*.tcsh", "csh.cshrc", "csh.login", ".tcshrc", ".cshrc", ".login",
- "*.asm", "*.ASM", "*.asm-avr",
- "*.cfg",
- "*.fc", "file_contexts", "file_contexts_*", "file_contexts.local", "file_contexts.homedirs", "file_contexts.template", "homedir_template", "property_contexts", "service_contexts", "hwservice_contexts", "initial_sid_contexts", "genfs_contexts", "fs_use",
- "*.sh", "*.bash", "*.ebuild", "*.eclass", "*.exlib", "*.exheres-0", ".bashrc", ".bash_profile", ".bash_login", ".profile", "PKGBUILD", "APKBUILD",
- "*.dox", "*.doxygen",
- "*.cue",
- "*.yar", "*.yara",
- "usr.bin.*", "usr.sbin.*", "bin.*", "sbin.*", "usr.lib.*", "usr.lib64.*", "usr.lib32.*", "usr.libx32.*", "usr.libexec.*", "usr.local.bin.*", "usr.local.sbin.*", "usr.local.lib*", "opt.*", "etc.cron.*", "snap.*", "snap-update-ns.*", "snap-confine.*",
- "*.brs",
- "*.ahk", "*.iahk",
- "todo.txt",
- "*.automount", "*.device", "*.mount", "*.path", "*.service", "*.slice", "*.socket", "*.swap", "*.target", "*.timer",
- "xorg.conf",
- "*.asm", "*.inc", "*.fasm",
- "*.mapcss",
- "*.lsl",
- "*.lhs",
- "*.Praat", "*.praat", "*.psc", "*.praat-script", "*.praatscript", "*.proc",
- "*.tcl", "*.tk",
- "*.gd", "*.gi", "*.g",
- "*.retro",
- "*.ps1", "*.psm1", "*.psd1",
- "*.rmd", "*.Rmd", "*.RMD",
- "*.ahdl", "*.tdf",
- "*.sml", "*.ml",
- "*.ijs", "*.ijt", "*.IJS", "*.IJT",
- "*.overpassql",
- "*.rpy",
- "*.sol",
- "*.gd",
- "*.4gl", "*.4GL", "*.err",
- "*.mm",
- "*.mp", "*.mps", "*.mpost", "*.mf",
- "*.fs", "*.fsi", "*.fsx",
- "*.groovy", "*.gradle", "*.gvy", "Jenkinsfile",
- "*.po", "*.pot",
- "*.hx", "*.Hx", "*.hX", "*.HX",
- "*.ngc", "*.gcode",
- "*.mib",
- "*.pro",
- "*.scm", "*.ss", "*.scheme", "*.guile", "*.chicken", "*.meta",
- "*.wrl",
- "*.json", ".kateproject", ".arcconfig", "*.geojson", "*.gltf", "*.theme",
- "*.tjp", "*.tji",
- "*.pony",
- "*.gdl", "*.vcg", "*.GDL", "*.VCG",
- "*.qdocconf",
- "*.cil",
- "*.pig",
- "*.src", "*.SRC", "*.asm", "*.ASM", "*.pic", "*.PIC",
- "*.ps", "*.ai", "*.eps",
- "*.f90", "*.F90", "*.f95", "*.F95", "*.f03", "*.F03", "*.f08", "*.F08",
- "*.dats", "*.sats", "*.hats",
- "*.uc",
- "*.spec",
- "*.t", "*.h",
- "*.ftl",
- "*.mel",
- "*.mss",
- "*.sql", "*.SQL", "*.ddl", "*.DDL",
- "*.cr",
- "*.q",
- "*.ex", "*.exs", "*.eex", "*.xml.eex", "*.js.eex",
- "*.tsv", "*.tab",
- "*.mo",
- "*.ccss",
- "*.ppd",
- "*.mac", "*.MAC", "*.dem", "*.DEM",
- "*.cfm", "*.cfc", "*.cfml", "*.dbm",
- "*.ts", "*.mts", "*.cts",
- "*.csv",
- ".gitignore*",
- "*.R", "*.r", "*.S", "*.s", "*.q",
- "*.ly", "*.LY", "*.ily", "*.ILY", "*.lyi", "*.LYI",
- "*.mly",
- "*.gdbinit",
- "control",
- "*.ld",
- "*.xsl", "*.xslt",
- "*.rhtml", "*.RHTML", "*.html.erb",
- "*.pure",
- "*.pli", "*.pl1",
- "httpd.conf", "httpd2.conf", "apache.conf", "apache2.conf", ".htaccess*", ".htpasswd*",
- "*.rst",
- "*.e", "*.ex", "*.exw", "*.exu",
- "*.rex", "*.rx", "*.rexx",
- "*.rb", "*.rjs", "*.rxml", "*.xml.erb", "*.js.erb", "*.rake", "Rakefile", "Gemfile", "*.gemspec", "Vagrantfile",
- "*.e",
- "*.JCL", "*.jcl",
- "*.ply",
- "*.ans",
- "*.c", "*.h", "*.inc", "*.o",
- "*.m", "*.M",
- "*.asp",
- "*.m", "*.mag",
- "*.y", "*.yy", "*.ypp", "*.y++",
- "*.lisp", "*.cl", "*.lsp", "*.el",
- "*.il",
- "CMakeLists.txt", "*.cmake", "*.cmake.in",
- "*.cgis",
- "*.c", "*.C", "*.h",
- "*.siv", "*.sieve",
- "*.scad",
- "*.scala", "*.sbt",
- "*.impl", "*.sign",
- };
- }
|