rkward-0.7.2/0000775000175000017510000000000013740275541012375 5ustar thomasthomasrkward-0.7.2/rkward/0000775000175000017510000000000013740275541013667 5ustar thomasthomasrkward-0.7.2/rkward/org.kde.rkward.appdata.xml0000664000175000017510000005103613736365060020652 0ustar thomasthomas org.kde.rkward FSFAP GPL-2.0+ RKward RKward RKward RKward RKward RKward RKward RKward RKward RKward RKWard RKward RKWard RKward RKward RKward RKward RKward RKward RKward RKward RKward RKward xxRKwardxx KDE frontend to the R statistics language Frontal del KDE per al llenguatge estadístic R Frontal del KDE per al llenguatge estadístic R KDE-Oberfläche für die Statistiksprache R KDE frontend to the R statistics language Interfaz de KDE para el lenguaje de estadísticas R KDE R statistikakeele kasutajaliides R-tilastolaskentakielen KDE-käyttöliittymä Interface utilisateur pour le langage de statistiques « R » Interface de KDE para a linguaxe de estatística R Frontend KDE untuk bahasa statistik R Interfaccia di KDE per il linguaggio statistico R R 통계 언어의 KDE 프론트엔드 KDE frontend naar de statistische taal R Nakładka KDE na język statystyczny R Interface para o KDE da linguagem de estatísticas R KDE frontend pre štatistický jazyk R KDE začelje za statistični paket R KDE-gränssnitt till statistikspråket R Оболонка KDE до мови для статичних обчислень R xxKDE frontend to the R statistics languagexx

RKWard aims to become an easy to use, transparent frontend to R, a powerful system for statistical computation and graphics. Besides a convenient GUI for the most important statistical functions, future versions will also provide seamless integration with an office-suite.

El RKWard pretén esdevenir un frontal fàcil d'utilitzar i transparent per a l'R, un potent sistema de càlcul estadístic i de gràfics. A més d'una IGU còmoda per a les característiques estadístiques més importants, les futures versions també proporcionaran una perfecta integració amb una suite d'oficina.

El RKWard pretén esdevenir un frontal fàcil d'utilitzar i transparent per a l'R, un potent sistema de càlcul estadístic i de gràfics. A més d'una IGU còmoda per a les característiques estadístiques més importants, les futures versions també proporcionaran una perfecta integració amb una suite d'oficina.

RKWard aims to become an easy to use, transparent frontend to R, a powerful system for statistical computation and graphics. Besides a convenient GUI for the most important statistical functions, future versions will also provide seamless integration with an office-suite.

RKWard pretende convertirse en una interfaz transparente a R fácil de usar, un potente sistema para cálculos estadísticos y gráficos. Además de una interfaz gráfica de usuario conveniente para la mayoría de las funciones estadísticas importantes, las versiones futuras también proporcionarán una integración sin fisuras con una suite de ofimática.

RKwardi siht on olla hõlpsasti kasutatav ja läbipaistev R - võimas statistiliste arvutuste ja nende graafilise esitamise tööriist - kasutajaliides. Lisaks kõige olulisemate statistikafunktsioonide käepärasele graafilisele kasutajaliidesele on tulevastes versioonides kavas pakkuda ka sujuvat lõimimist kontoritöö rakendustega.

RKward pyrkii olemaan helppokäyttöinen ja läpinäkyvä käyttöliittymä tehokkaalle tilastolaskenta- ja kaaviojärjestelmälle R:lle. Paitsi kätevän graafisen käyttöliittymän tärkeimpiin tilastofunktioihin tulevat versiot tarjoavat myös saumattoman integroinnin toimisto-ohjelmiin.

Le logiciel RKWard se veut devenir une interface utilisateur simple à utiliser pour le langage « R », un environnement puissant pour le calcul et l'affichage graphique de statistique. En plus d'une interface graphique utilisateur adapté pour les fonctions de statistiques les plus importantes, les futures versions offriront une intégration transparente avec les suites de bureautique.

RKWard pretende converterse nunha interface para R fácil de usar e transparente, un potente sistema de computación estatística e gráficas. Ademais de fornecer unha interface gráfica cómoda para as funcións estatísticas máis importantes, versión futuras fornecerán integración transparente cunha suite de ofimática.

RKWard ditujukan untuk menjadi yang mudah digunakan, frontend transparan untuk R, sebuah sistem yang unggul untuk grafik dan komputasi statistik. Selain GUI yang nyaman untuk beberapa fungsi statistik yang penting, versi masa depan juga akan menyediakan integrasi yang sama dengan office suite.

RKWard mira a diventare un'interfaccia trasparente per R, facile da usare, un potente sistema per il calcolo statistico e la grafica. Oltre a una comoda interfaccia per le funzioni statistiche più importanti, le versioni future forniranno anche una perfetta integrazione con una suite per ufficio.

RKWard는 강력한 통계 계산 및 그래픽 시스템인 R의 사용하기 쉽고 투명한 프론트엔드입니다. 가장 중요한 편리한 통계 기능 GUI 외에도 이후 버전은 사무용 도구와 완벽하게 통합됩니다.

Het doel van RKWard is een gemakkelijk te gebruiken, transparante frontend naar R, een krachtig systeem voor statistische berekeningen en grafieken te worden. En ernaast een gemakkelijke GUI voor de meest belangrijke statistische functies, toekomstige versies zullen ook naadloze integratie bieden met een kantoor-suite.

RKWard dąży do tego, aby stać się łatwą w użyciu i przejrzystą nakładką na R, zaawansowany system do obliczeń statystycznych i obrazowania. Poza wygodnym interfejsem użytkownika dla większości z ważnych funkcji, przyszłe wydania dostarczą także integrację z pakietem biurowym.

O RKWard pretende tornar-se uma interface simples de usar e transparente para o R, um sistema poderoso para cálculos estatísticos e gráficos. Para além de uma interface adequada para as funções estatísticas mais importantes, as futuras versões também irão oferecer uma integração transparente com os pacotes de aplicações de escritório.

Cilj RKWard-a je postati preprosto za uporabo in pregledno začelje za R, zmogljivsistem za izračunavanje statistike in grafiko. Poleg priročnega grafičnega vmesnika za najpomembnejše statistične funkcije bodo tudi prihodnje različice zagotavljale brezhibno integracijo s pisarniškim paketom.

RKward har som mål att bli ett lättanvänt, transparent gränssnitt till R, ett kraftfullt system för statistiska beräkningar och grafik. Förutom ett praktiskt grafiskt användargränssnitt för de viktigaste statistikfunktionerna, kommer framtida versioner också att tillhandahålla sömlös integrering med en kontorssvit.

RKWard — проста у користуванні, прозора оболонка до R — потужної системи для статистичних обчислень та побудови графіків. Окрім зручного графічного інтерфейсу до більшості статистичних функцій, у майбутніх версіях буде реалізовано безшовну інтеграцію із комплексами офісних програм.

xxRKWard aims to become an easy to use, transparent frontend to R, a powerful system for statistical computation and graphics. Besides a convenient GUI for the most important statistical functions, future versions will also provide seamless integration with an office-suite.xx

https://rkward.kde.org https://bugs.kde.org/enter_bug.cgi?format=guided&product=rkward https://www.kde.org/community/donations/?app=rkward https://docs.kde.org/?application=rkward org.kde.rkward.desktop Application main window, with object browser, data editor, file browser, and interactive R console visible. Window placement can be re-arranged and all windows can also detached from the main window. Finestra principal de l'aplicació, amb navegador d'objectes, editor de dades, navegador de fitxers, i una consola visible d'R interactiva. La col·locació de les finestres es pot reconfigurar i també totes les finestres es poden separar de la finestra principal. Finestra principal de l'aplicació, amb navegador d'objectes, editor de dades, navegador de fitxers, i una consola visible d'R interactiva. La col·locació de les finestres es pot reconfigurar i també totes les finestres es poden separar de la finestra principal. Application main window, with object browser, data editor, file browser, and interactive R console visible. Window placement can be re-arranged and all windows can also detached from the main window. Ventana principal de la aplicación, con explorador de objetos, editor de datos, navegador de archivos y consola interactiva de R visible. La posición de la ventana se puede reorganizar y también es posible desprender todas las ventanas de la ventana principal. Rakenduse peaaken objektisirvija, andmeredaktori, failisirvija ja interaktiivse R konsooliga. Akende asukohta saab muuta, samuti saab kõiki aknaid peaaknast lahti haakida. La fenêtre principale de l'application, avec un navigateur d'objets, un éditeur de données, un explorateur de fichiers et une console interactive « R ». L'emplacement de la fenêtre peut être modifié et toutes les fenêtres peuvent aussi être détachées de la fenêtre principale. Xanela principal da aplicación, co navegador de obxectos, o editor de datos, o navegador de ficheiros e a consola interactiva de R visíbeis. A colocación das xanelas pode reorganizarse e todas as xanelas poden despregarse da xanela principal. Window utama aplikasi, dengan penelusur objek, pengedit data, penelusur file, dan interaktif konsol R yang terlihat. penempatan window bisa diatur ulang dan semua window juga bisa dilepas dari window utama. Finestra principale dell'applicazione con navigatore degli oggetti, editor di dati, navigatore dei file e console interattiva di R visibile. Il posizionamento delle finestre può essere modificato, inoltre tutte le finestre possono essere staccate dalla principale. 프로그램 주 창. 객체 탐색기, 데이터 편집기, 파일 탐색기 및 대화식 R 콘솔이 표시되어 있습니다. 창 배치는 사용자 정의 가능하며 모든 창을 주 창에서 분리할 수도 있습니다. Hoofdvenster, met hierin objectbrowser, gegevenseditor, bestandsbrowser, en interactieve console van R. Plaatsing van venster kan worden gewijzigd, en all vensters kunnen ook worden losgemaakt van het hoofdvenster. Główne okno aplikacji z przeglądarką obiektów, edytorem danych, przeglądarką plików i interaktywną konsolą R. Umieszczenie okien można zmienić i każde okno można odczepić od głównego okna. Janela principal da aplicação, com um navegador de objectos, um editor de dados, um navegador de ficheiros e uma consola de R interactiva visíveis. A colocação das janelas pode ser reorganizada e todas as janelas poder-se-ão destacar da janela principal. Glavno okno aplikacije z brskalnikom predmetov, urejevalnikom podatkov, brskalnikom datotek invidno interaktivno konzolo R. Namestitev oken lahko preuredite in vsa okna se lahko odlepijo tudi od glavnega okna. Huvudfönster i programmet, med objektbläddrare, dataeditor, filbläddrare och interaktiv R-terminal synliga. Fönsterplaceringen kan arrangeras om och alla fönster kan också kopplas loss från huvudfönstret. Головне вікно програми із панеллю навігації об'єктами, редактором даних, панеллю навігації файловою системою та інтерактивною консоллю R. Розташування панелей можна змінювати, усі панелі також можна від'єднувати від головного вікна. xxApplication main window, with object browser, data editor, file browser, and interactive R console visible. Window placement can be re-arranged and all windows can also detached from the main window.xx https://cdn.kde.org/screenshots/rkward/main_window.png Script editor with active preview. Un editor de scripts amb vista prèvia activa. Un editor de scripts amb vista prèvia activa. Editor skriptů s aktivním náhledem. Script editor with active preview. Editor de scripts con vista previa activa. Skriptiredaktor aktiivse eelvaatlusega. Éditeur de scripts avec aperçu actif. Editor de scripts con vista previa activa. Pengedit skrip dengan pratinjau yang aktif. Editor di script con anteprima attiva. 스크립트를 미리 보여 주는 편집기. Scripteditor met actieve preview. Edytor skryptów z podglądem na żywo. Editor de programas com uma antevisão activa. Urejevalnik skriptov z aktivnim predogledom. Skripteditor med aktiv förhandsgranskning. Редактор скриптів із активним попереднім переглядом. xxScript editor with active preview.xx https://cdn.kde.org/screenshots/rkward/script_preview.png Working with data in RKward Treballant amb dades al RKward Treballant amb dades al RKward Arbeiten mit Daten in RKward Working with data in RKward Trabajando con datos en RKward Andmete töötlemine RKwardis Datatyöskentelyä RKWardissa Travailler avec des données dans RKward Traballando con datos en RKWard Bekerja dengan data di RKward Lavorare coi dati in RKward RKward에서 데이터 작업 Met gegevens werken in RKward Praca z danymi w RKward Lidar com dados no RKward Práca s dátami v RKward Delo s podatki v RKward Arbeta med data i RKward Робота з даними у RKward xxWorking with data in RKwardxx https://rkward.kde.org/assets/img/EditorDataFrame.png Searching objects by name, searching for help pages, and in-app help viewer. Cerca objectes per nom, cerca a les pàgines d'ajuda, i visor d'ajuda integrat a l'aplicació. Cerca objectes per nom, cerca a les pàgines d'ajuda, i visor d'ajuda integrat a l'aplicació. Searching objects by name, searching for help pages, and in-app help viewer. Búsqueda de objetos por nombre, búsqueda de páginas de ayuda y visor de ayuda integrado en la aplicación. Objektide otsimine nime järgi, abilehekülgede otsimine ja rakenduse enda abinäitaja. Rechercher des objets par nom, des pages d'aide ou dans l'afficheur d'aide intégré. Buscar obxectos por nome, buscar páxinas de axuda, e visor de axuda dentro do aplicativo. Pencarian objek berdasarkan nama, pencarian halaman bantuan, dan penampil bantuan dalam-apl. Ricerca di oggetti in base al nome, ricerca di pagine di aiuto e visualizzatore di aiuto all'interno dell'applicazione. 이름으로 객체 검색, 도움말 페이지 검색 및 프로그램 내장 도움말 뷰어. Objecten zoeken op naam, zoeken naar helppagina's, en in-app helpviewer. Wyszukiwanie obiektów po nazwie, wyszukiwanie na stronach pomocy i wbudowana przeglądarka pomocy w aplikacji. Pesquisa de objectos por nome, pesquisa nas páginas de ajuda e visualizador de ajuda na aplicação. Iskanje predmetov po imenu, iskanje strani s pomočjo in pregledovalnik pomoči v aplikaciji. Sökning efter objekt enligt namn, sökning efter hjälpsidor, och hjälpvisning i programmet. Пошук об'єктів за назвою, пошук сторінок довідки та вбудована панель перегляду довідки. xxSearching objects by name, searching for help pages, and in-app help viewer.xx https://cdn.kde.org/screenshots/rkward/object_and_help_search.png rkward KDE
rkward-0.7.2/rkward/rkward.cpp0000664000175000017510000012674513740267466015713 0ustar thomasthomas/*************************************************************************** rkward.cpp - description ------------------- begin : Tue Oct 29 20:06:08 CET 2002 copyright : (C) 2002-2020 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "rkward.h" // include files for QT #include #include #include #include #include #include #include #include #include #include #include #include // include files for KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // application specific includes #include "core/rkmodificationtracker.h" #include "plugin/rkcomponentmap.h" #include "settings/rksettings.h" #include "settings/rksettingsmoduleplugins.h" #include "settings/rksettingsmodulegeneral.h" #include "settings/rksettingsmoduleoutput.h" #include "settings/rksettingsmodulecommandeditor.h" #include "settings/rksettingsmodulekateplugins.h" #include "rbackend/rkrinterface.h" #include "core/robjectlist.h" #include "core/renvironmentobject.h" #include "misc/rkstandardicons.h" #include "misc/rkcommonfunctions.h" #include "misc/rkxmlguisyncer.h" #include "misc/rkdbusapi.h" #include "misc/rkdialogbuttonbox.h" #include "rkglobals.h" #include "dialogs/startupdialog.h" #include "dialogs/rkloadlibsdialog.h" #include "dialogs/rkimportdialog.h" #include "dialogs/rkrecoverdialog.h" #include "dialogs/rksetupwizard.h" #include "agents/rksaveagent.h" #include "agents/rkloadagent.h" #include "agents/rkquitagent.h" #include "windows/robjectbrowser.h" #include "windows/rcontrolwindow.h" #include "windows/rkhtmlwindow.h" #include "windows/rkworkplaceview.h" #include "windows/rkworkplace.h" #include "windows/rkcommandlog.h" #include "windows/rkhelpsearchwindow.h" #include "windows/rktoplevelwindowgui.h" #include "windows/rkfilebrowser.h" #include "windows/rktoolwindowlist.h" #include "windows/rkdebugconsole.h" #include "windows/rkcallstackviewer.h" #include "windows/rkdebugmessagewindow.h" #include "windows/katepluginintegration.h" #include "rkconsole.h" #include "debug.h" #include "agents/showedittextfileagent.h" // TODO: see below: needed purely for linking! #include "dialogs/rkreadlinedialog.h" // TODO: see below: needed purely for linking! #include "dialogs/rkselectlistdialog.h" // TODO: see below: needed purely for linking! #include "windows/detachedwindowcontainer.h" // TODO: see below: needed purely for linking! #include "dataeditor/rkeditordataframe.h" // TODO: see below: needed purely for linking! #include "agents/rkeditobjectagent.h" // TODO: see below: needed purely for linking! #include "agents/rkprintagent.h" // TODO: see below: needed purely for linking! // This nevers gets called. It's needed to trick ld into linking correctly. Nothing else. void bogusCalls () { ShowEditTextFileAgent::showEditFiles (0); // TODO: AAAAAAAARGGGH!!!! It won't link without this bogus line!!! RKReadLineDialog::readLine (0, QString(), QString(), 0, 0); // TODO: see above RKSelectListDialog::doSelect (0, QString(), QStringList(), QStringList(), false); // TODO: see above new RKEditorDataFrame (0, 0); DetachedWindowContainer (0, false); new RKWorkplaceView (0); new RKEditObjectAgent (QStringList (), 0); RKPrintAgent::printPostscript (QString (), false); } /** Main window **/ //static RKWardMainWindow *RKWardMainWindow::rkward_mainwin = 0; RKWardMainWindow::RKWardMainWindow () : KParts::MainWindow ((QWidget *)0, (Qt::WindowFlags) KDE_DEFAULT_WINDOWFLAGS) { RK_TRACE (APP); RK_ASSERT (rkward_mainwin == 0); gui_rebuild_locked = true; no_ask_save = true; workspace_modified = false; merge_loads = false; rkward_mainwin = this; katepluginintegration = 0; RKGlobals::rinter = 0; RKCommonFunctions::getRKWardDataDir(); // call this before any forking, in order to avoid potential race conditions during initialization of data dir RKSettings::settings_tracker = new RKSettingsTracker (this); /////////////////////////////////////////////////////////////////// // call inits to invoke all other construction parts RKStandardIcons::initIcons (); initActions(); initStatusBar(); new RKWorkplace (this); RKWorkplace::mainWorkplace ()->initActions (actionCollection ()); setCentralWidget (RKWorkplace::mainWorkplace ()); connect (RKWorkplace::mainWorkplace ()->view (), &RKWorkplaceView::captionChanged, this, static_cast(&RKWardMainWindow::setCaption)); connect (RKWorkplace::mainWorkplace (), &RKWorkplace::workspaceUrlChanged, this, &RKWardMainWindow::addWorkspaceUrl); part_manager = new KParts::PartManager (this); // When the manager says the active part changes, // the builder updates (recreates) the GUI connect (partManager (), &KParts::PartManager::activePartChanged, this, &RKWardMainWindow::partChanged); readOptions(); RKGlobals::mtracker = new RKModificationTracker (this); initToolViewsAndR (); /////////////////////////////////////////////////////////////////// // build the interface setHelpMenuEnabled (false); setXMLFile ("rkwardui.rc"); insertChildClient (toplevel_actions = new RKTopLevelWindowGUI (this)); insertChildClient (katePluginIntegration ()->mainWindow ()); createShellGUI (true); // This is pretty convoluted, but while loading plugins the katePluginIntegration-client may gain new actions and thus needs // to be reloaded. We cannot - currently, KF5.65 - delay loading the UI defintion(s), because plugins rely on it having a GUI factory. katePluginIntegration ()->loadPlugins (RKSettingsModuleKatePlugins::pluginsToLoad ()); // TODO: initToolWindowActions() should be called after all plugins are loaded (and have registered their tool views). However // that may be a problem, if there is no KXMLGUIFactory around, yet. So, annoyingly, we need to create the GUI, before we // have everything to populate it. Therefore, after init, the client is removed and re-added in order to trigger a UI // refresh. toplevel_actions->initToolWindowActions (); factory()->removeClient (toplevel_actions); factory()->addClient (toplevel_actions); RKXMLGUISyncer::self ()->watchXMLGUIClientUIrc (this); // replicate File->import and export menus into the Open/Save toolbar button menus QMenu *menu = dynamic_cast(guiFactory ()->container ("import", this)); if (menu) open_any_action->addAction (menu->menuAction ()); menu = dynamic_cast(guiFactory ()->container ("export", this)); if (menu) save_any_action->addAction (menu->menuAction ()); RKComponentMap::initialize (); // stuff which should wait until the event loop is running QTimer::singleShot (0, this, SLOT (doPostInit())); } RKWardMainWindow::~RKWardMainWindow() { RK_TRACE (APP); // these would not be strictly necessary, as we're exiting the app, anyway. delete RObjectList::getObjectList (); delete RObjectBrowser::mainBrowser (); delete RKCommandLog::getLog (); delete RKConsole::mainConsole (); delete RKHelpSearchWindow::mainHelpSearch (); delete RKGlobals::tracker (); delete RKGlobals::rInterface (); delete RControlWindow::getControl (); factory ()->removeClient (RKComponentMap::getMap ()); delete RKComponentMap::getMap (); } KatePluginIntegrationApp* RKWardMainWindow::katePluginIntegration () { RK_TRACE (APP); if (!katepluginintegration) { katepluginintegration = new KatePluginIntegrationApp (this); } return katepluginintegration; } void RKWardMainWindow::closeEvent (QCloseEvent *e) { RK_TRACE (APP); if (RKQuitAgent::quittingInProgress ()) { KParts::MainWindow::closeEvent (e); return; } e->ignore (); if (doQueryQuit ()) { emit (aboutToQuitRKWard()); new RKQuitAgent (this); } } void RKWardMainWindow::doPostInit () { RK_TRACE (APP); QStringList open_urls = RKGlobals::startup_options.take ("initial_urls").toStringList (); bool warn_external = RKGlobals::startup_options.take ("warn_external").toBool (); QString evaluate_code = RKGlobals::startup_options.take ("evaluate").toString (); initPlugins (); gui_rebuild_locked = false; show (); RKSetupWizard::doAutoCheck(); KMessageBox::enableMessage ("external_link_warning"); // can only be disabled per session QUrl recover_url = RKRecoverDialog::checkRecoverCrashedWorkspace (); if (!recover_url.isEmpty ()) { open_urls.clear (); // Well, not a perfect solution. But we certainly don't want to overwrite the just recovered workspace. open_urls.append (recover_url.url ()); } for (int i = 0; i < open_urls.size (); ++i) { // make sure local urls are absolute, as we may be changing wd before loading QUrl url = QUrl::fromUserInput (open_urls[i], QDir::currentPath(), QUrl::AssumeLocalFile); RK_ASSERT (!url.isRelative ()); open_urls[i] = url.url (); } QString cd_to = RKSettingsModuleGeneral::initialWorkingDirectory (); if (!cd_to.isEmpty ()) { RKGlobals::rInterface ()->issueCommand ("setwd (" + RObject::rQuote (cd_to) + ")\n", RCommand::App); QDir::setCurrent (cd_to); } if (!open_urls.isEmpty()) { // this is also done when there are no urls specified on the command line. But in that case _after_ loading any workspace, so // the help window will be on top if (RKSettingsModuleGeneral::showHelpOnStartup ()) toplevel_actions->showRKWardHelp (); openUrlsFromCommandLineOrDBus (warn_external, open_urls); } else { StartupDialog::StartupDialogResult result = StartupDialog::getStartupAction (this, fileOpenRecentWorkspace); if (!result.open_url.isEmpty ()) { openWorkspace (result.open_url); } else { if (result.result == StartupDialog::ChoseFile) { askOpenWorkspace (QUrl()); } else if (result.result == StartupDialog::EmptyTable) { RKWorkplace::mainWorkplace ()->editNewDataFrame (i18n ("my.data")); } } if (RKSettingsModuleGeneral::workplaceSaveMode () == RKSettingsModuleGeneral::SaveWorkplaceWithSession) { RKWorkplace::mainWorkplace ()->restoreWorkplace (RKSettingsModuleGeneral::getSavedWorkplace (KSharedConfig::openConfig ().data ()).split ('\n')); } if (RKSettingsModuleGeneral::showHelpOnStartup ()) toplevel_actions->showRKWardHelp (); } setNoAskSave (false); // up to this point, no "real" save-worthy stuff can be pending in the backend. So mark this point as "clean". RCommand *command = new RCommand (QString (), RCommand::EmptyCommand | RCommand::Sync | RCommand::App); connect (command->notifier (), &RCommandNotifier::commandFinished, this, &RKWardMainWindow::setWorkspaceUnmodified); RKGlobals::rInterface ()->issueCommand (command); if (!evaluate_code.isEmpty ()) RKConsole::pipeUserCommand (evaluate_code); RKDBusAPI *dbus = new RKDBusAPI (this); connect (this, &RKWardMainWindow::aboutToQuitRKWard, dbus, &RKDBusAPI::deleteLater); // around on the bus in this case. updateCWD (); connect (RKGlobals::rInterface (), &RInterface::backendWorkdirChanged, this, &RKWardMainWindow::updateCWD); setCaption (QString ()); // our version of setCaption takes care of creating a correct caption, so we do not need to provide it here } void RKWardMainWindow::openUrlsFromCommandLineOrDBus (bool warn_external, QStringList _urls) { RK_TRACE (APP); bool any_dangerous_urls = false; QList urls; for (int i = 0; i < _urls.size (); ++i) { QUrl url = QUrl::fromUserInput (_urls[i], QString (), QUrl::AssumeLocalFile); if (url.scheme () == "rkward" && url.host () == "runplugin") { any_dangerous_urls = true; } urls.append (url); } if (warn_external && any_dangerous_urls) { RK_ASSERT (urls.size () == 1); QString message = i18n ("

You are about to start an RKWard dialog from outside of RKWard, probably by clicking on an 'rkward://'-link, somewhere. In case you have found this link on an external website, please bear in mind that R can be used to run arbitrary commands on your computer, potentially including downloading and installing malicious software. If you do not trust the source of the link you were following, you should press 'Cancel', below.

In case you click 'Continue', no R code will be run, unless and until you click 'Submit' in the dialog window, and you are encouraged to review the generated R code, before doing so.

Note: Checking 'Do not ask again' will suppress this message for the remainder of this session, only."); if (KMessageBox::warningContinueCancel (this, message, i18n ("A note on external links"), KStandardGuiItem::cont (), KStandardGuiItem::cancel (), "external_link_warning") != KMessageBox::Continue) return; } RKWardMainWindow::getMain ()->setMergeLoads (true); for (int i = 0; i < urls.size (); ++i) { RKWorkplace::mainWorkplace ()->openAnyUrl (urls[i], QString (), false); } RKWardMainWindow::getMain ()->setMergeLoads (false); } void RKWardMainWindow::initPlugins (const QStringList &automatically_added) { RK_TRACE (APP); slotSetStatusBarText(i18n("Setting up plugins...")); QStringList all_maps = RKSettingsModulePlugins::pluginMaps (); factory ()->removeClient (RKComponentMap::getMap ()); RKComponentMap::getMap ()->clearAll (); QStringList completely_broken_maps; QStringList completely_broken_maps_details; QStringList somewhat_broken_maps; QStringList somewhat_broken_maps_details; for (int i = 0; i < all_maps.size (); ++i) { const QString &map = all_maps[i]; RKPluginMapParseResult result = RKComponentMap::getMap ()->addPluginMap (map); if (!result.valid_plugins) { RKSettingsModulePlugins::markPluginMapAsBroken (map); completely_broken_maps.append (map); completely_broken_maps_details.append (result.detailed_problems); } else if (!result.detailed_problems.isEmpty ()) { if (RKSettingsModulePlugins::markPluginMapAsQuirky (map)) { somewhat_broken_maps.append (map); somewhat_broken_maps_details.append (result.detailed_problems); } } else { RKSettingsModulePlugins::markPluginMapAsWorking (map); } } RKComponentMap::getMap ()->finalizeAll (); factory ()->addClient (RKComponentMap::getMap ()); if (!automatically_added.isEmpty ()) { // NOTE: When plugins are added from R, these must be fully initialized *before* showing any dialog, which is modal, i.e. has an event loop. Otherwise, subsequent calls e.g. to rk.call.plugin() could sneak in front of this. // This is the reason for handling notification about automatically_added plugins, here. KMessageBox::informationList (RKWardMainWindow::getMain (), i18n ("New RKWard plugin packs (listed below) have been found, and have been activated, automatically. To de-activate selected plugin packs, use Settings->Configure RKWard->Plugins."), automatically_added, i18n ("New plugins found"), "new_plugins_found"); } if (!completely_broken_maps.isEmpty ()) { QString maplist = "

  • " + completely_broken_maps.join ("
  • \n
  • ") + "
"; KMessageBox::detailedError (0, QString ("

%1

%2

").arg (i18n ("The following RKWard pluginmap files could not be loaded, and have been disabled. This could be because they are broken, not compatible with this version of RKWard, or not meant for direct loading (see the 'Details' for more information). They have been disabled.")).arg (maplist), completely_broken_maps_details.join ("\n"), i18n ("Failed to load some plugin maps")); } if (!somewhat_broken_maps.isEmpty ()) { QString maplist = "
  • " + somewhat_broken_maps.join ("
  • \n
  • ") + "
"; KMessageBox::detailedError (0, QString ("

%1

%2

%3

").arg (i18n ("Some errors were encountered while loading the following RKWard pluginmap files. This could be because individual plugins are broken or not compatible with this version of RKWard (see the 'Details' for more information). Other plugins were loaded, successfully, however.")).arg (maplist).arg (i18n ("Note: You will not be warned about these pluginmap files again, until you upgrade RKWard, or remove and re-add them in Settings->Configure RKWard->Plugins.")), somewhat_broken_maps_details.join ("\n"), i18n ("Failed to load some plugin maps")); } slotSetStatusReady (); } void RKWardMainWindow::startR () { RK_TRACE (APP); RK_ASSERT (!RKGlobals::rInterface ()); // make sure our general purpose files directory exists QString packages_path = RKSettingsModuleGeneral::filesPath() + "/.rkward_packages"; bool ok = QDir ().mkpath (packages_path); RK_ASSERT (ok); // Copy RKWard R source packages to general purpose files directory (if still needed). // This may look redundant at first (since the package still needs to be installed from the // backend. However, if frontend and backend are on different machines (eventually), only the // filesPath is shared between both. QStringList packages; packages << "rkward.tgz" << "rkwardtests.tgz"; for (int i = 0; i < packages.size (); ++i) { QString package = QDir (packages_path).absoluteFilePath (packages[i]); if (RKSettingsModuleGeneral::rkwardVersionChanged ()) { RK_DEBUG(APP, DL_INFO, "RKWard version changed. Discarding cached package at %s", qPrintable (package)); QFile::remove (package); } if (!QFileInfo (package).exists()) { RK_DEBUG(APP, DL_INFO, "Copying rkward R source package to %s", qPrintable (package)); RK_ASSERT(QFile::copy (RKCommonFunctions::getRKWardDataDir () + "/rpackages/" + packages[i], package)); } } RKGlobals::rinter = new RInterface (); connect(RKGlobals::rInterface(), &RInterface::backendStatusChanged, this, &RKWardMainWindow::setRStatus); new RObjectList (); RObjectBrowser::mainBrowser ()->unlock (); } void RKWardMainWindow::slotConfigure () { RK_TRACE (APP); RKSettings::configureSettings (RKSettings::NoPage, this); } void RKWardMainWindow::slotCancelAllCommands () { RK_TRACE (APP); RK_ASSERT (RKGlobals::rInterface ()); RKGlobals::rInterface ()->cancelAll (); } void RKWardMainWindow::configureCarbonCopy () { RK_TRACE (APP); QDialog *dialog = new QDialog (); dialog->setWindowTitle (i18n ("Carbon Copy Settings")); QVBoxLayout *layout = new QVBoxLayout (dialog); RKCarbonCopySettings *settings = new RKCarbonCopySettings (dialog); layout->addWidget (settings); RKDialogButtonBox *box = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel, dialog); dialog->setAttribute (Qt::WA_DeleteOnClose); connect (dialog, &QDialog::accepted, settings, &RKCarbonCopySettings::applyChanges); connect (box->button (QDialogButtonBox::Apply), &QPushButton::clicked, settings, &RKCarbonCopySettings::applyChanges); layout->addWidget (box); dialog->show (); } void RKWardMainWindow::initToolViewsAndR () { RK_TRACE (APP); RObjectBrowser::object_browser = new RObjectBrowser (0, true); RObjectBrowser::mainBrowser ()->setCaption (i18n ("Workspace")); RKToolWindowList::registerToolWindow (RObjectBrowser::mainBrowser (), "workspace", RKToolWindowList::Left, Qt::AltModifier + Qt::Key_1); RKCommandLog::rkcommand_log = new RKCommandLog (0, true); RKToolWindowList::registerToolWindow (RKCommandLog::rkcommand_log, "commandlog", RKToolWindowList::Bottom, Qt::AltModifier + Qt::Key_3); startR (); RKFileBrowser::main_browser = new RKFileBrowser (0, true); RKFileBrowser::main_browser->setCaption (i18n ("Files")); RKToolWindowList::registerToolWindow (RKFileBrowser::main_browser, "filebrowser", RKToolWindowList::Left, Qt::AltModifier + Qt::Key_2); RControlWindow::control_window = new RControlWindow (0, true); RControlWindow::getControl ()->setCaption (i18n ("Pending Jobs")); RKToolWindowList::registerToolWindow (RControlWindow::getControl (), "pendingjobs", RKToolWindowList::Nowhere, Qt::AltModifier + Qt::Key_4); RKConsole *console = new RKConsole (0, true); RKConsole::setMainConsole (console); RKToolWindowList::registerToolWindow (console, "console", RKToolWindowList::Bottom, Qt::AltModifier + Qt::Key_5); RKHelpSearchWindow *help_search = new RKHelpSearchWindow (0, true); RKHelpSearchWindow::main_help_search = help_search; RKToolWindowList::registerToolWindow (help_search, "helpsearch", RKToolWindowList::Bottom, Qt::AltModifier + Qt::Key_6); RKCallstackViewer::_instance = new RKCallstackViewer (0, true); RKCallstackViewer::instance ()->setCaption (i18n ("Debugger Frames")); RKToolWindowList::registerToolWindow (RKCallstackViewer::instance (), "debugframes", RKToolWindowList::Right, Qt::AltModifier + Qt::Key_8); // HACK: Creating this _after_ the callstackviewer is important, so the debug console will end up the active window when entering a debug context RKDebugConsole::_instance = new RKDebugConsole (0, true); RKDebugConsole::instance ()->setCaption (i18n ("Debugger Console")); RKToolWindowList::registerToolWindow (RKDebugConsole::instance (), "debugconsole", RKToolWindowList::Nowhere, Qt::AltModifier + Qt::Key_7); RKDebugMessageWindow::_instance = new RKDebugMessageWindow (0, true); RKDebugMessageWindow::instance ()->setCaption (i18n ("RKWard Debug Messages")); RKToolWindowList::registerToolWindow (RKDebugMessageWindow::instance (), "rkdebugmessages", RKToolWindowList::Nowhere, 0); RKWorkplace::mainWorkplace ()->placeToolWindows (); } void RKWardMainWindow::initActions() { RK_TRACE (APP); QAction *action; // TODO: is there a way to insert actions between standard actions without having to give all standard actions custom ids? new_data_frame = actionCollection ()->addAction ("new_data_frame", this, SLOT (slotNewDataFrame())); new_data_frame->setText (i18n ("Dataset")); new_data_frame->setIcon (RKStandardIcons::getIcon (RKStandardIcons::WindowDataFrameEditor)); new_data_frame->setStatusTip (i18n ("Creates new empty dataset and opens it for editing")); new_command_editor = actionCollection ()->addAction (KStandardAction::New, "new_command_editor", this, SLOT(slotNewCommandEditor())); new_command_editor->setText (i18n ("Script File")); new_command_editor->setIcon (RKStandardIcons::getIcon (RKStandardIcons::WindowCommandEditor)); fileOpen = actionCollection ()->addAction (KStandardAction::Open, "file_openy", this, SLOT(slotOpenCommandEditor())); fileOpen->setText (i18n ("Open R Script File...")); QAction *file_open_any = actionCollection ()->addAction (KStandardAction::Open, "file_open_any"); connect (file_open_any, &QAction::triggered, this, &RKWardMainWindow::openAnyFile); file_open_any->setText (i18n ("Open any File...")); actionCollection ()->setDefaultShortcut (file_open_any, Qt::ControlModifier + Qt::AltModifier + Qt::Key_O); fileOpenRecent = static_cast (actionCollection ()->addAction (KStandardAction::OpenRecent, "file_open_recenty", this, SLOT(slotOpenCommandEditor(QUrl)))); fileOpenRecent->setText (i18n ("Open Recent R Script File")); #if 0 // TODO: Fix import dialog and re-enable it: https://mail.kde.org/pipermail/rkward-devel/2015-June/004156.html #ifdef Q_OS_WIN // TODO: find the cause and fix it! http://sourceforge.net/p/rkward/bugs/54/ # ifdef __GNUC__ # warning TODO: import data dialog is disabled on windows due to bug in kdelibs # endif #else action = actionCollection ()->addAction ("import_data", this, SLOT (importData())); action->setText (i18n ("Import Data")); action->setStatusTip (i18n ("Import data from a variety of file formats")); #endif #endif fileOpenWorkspace = actionCollection ()->addAction (KStandardAction::Open, "file_openx", this, SLOT(slotFileOpenWorkspace())); fileOpenWorkspace->setText (i18n ("Open Workspace...")); actionCollection ()->setDefaultShortcut (fileOpenWorkspace, Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_O); fileOpenWorkspace->setStatusTip (i18n ("Opens an existing document")); fileOpenRecentWorkspace = static_cast (actionCollection ()->addAction (KStandardAction::OpenRecent, "file_open_recentx", this, SLOT(askOpenWorkspace(QUrl)))); fileOpenRecentWorkspace->setText (i18n ("Open Recent Workspace")); fileOpenRecentWorkspace->setStatusTip (i18n ("Opens a recently used file")); fileSaveWorkspace = actionCollection ()->addAction (KStandardAction::Save, "file_savex", this, SLOT(slotFileSaveWorkspace())); fileSaveWorkspace->setText (i18n ("Save Workspace")); actionCollection ()->setDefaultShortcut (fileSaveWorkspace, Qt::ControlModifier + Qt::AltModifier + Qt::Key_S); fileSaveWorkspace->setStatusTip (i18n ("Saves the actual document")); fileSaveWorkspaceAs = actionCollection ()->addAction (KStandardAction::SaveAs, "file_save_asx", this, SLOT(slotFileSaveWorkspaceAs())); actionCollection ()->setDefaultShortcut (fileSaveWorkspaceAs, Qt::ControlModifier + Qt::AltModifier + Qt::ShiftModifier + Qt::Key_S); fileSaveWorkspaceAs->setText (i18n ("Save Workspace As")); fileSaveWorkspaceAs->setStatusTip (i18n ("Saves the actual document as...")); fileQuit = actionCollection ()->addAction (KStandardAction::Quit, "file_quitx", this, SLOT(close())); fileQuit->setStatusTip (i18n ("Quits the application")); interrupt_all_commands = actionCollection ()->addAction ("cancel_all_commands", this, SLOT (slotCancelAllCommands())); interrupt_all_commands->setText (i18n ("Interrupt all commands")); actionCollection ()->setDefaultShortcut (interrupt_all_commands, Qt::ShiftModifier + Qt::Key_Escape); interrupt_all_commands->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionInterrupt)); interrupt_all_commands->setEnabled (false); // enabled from within setRStatus() action = actionCollection ()->addAction ("carbon_copy", this, SLOT (configureCarbonCopy())); action->setText (i18n ("CC commands to output...")); // These two currently do the same thing action = actionCollection ()->addAction ("load_unload_libs", this, SLOT (slotFileLoadLibs())); action->setText (i18n ("Manage R packages and plugins...")); action->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionConfigurePackages)); action = actionCollection ()->addAction ("configure_packages", this, SLOT (slotFileLoadLibs())); action->setText (i18n ("Manage R packages and plugins...")); action->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionConfigurePackages)); setStandardToolBarMenuEnabled (true); createStandardStatusBarAction (); close_all_editors = actionCollection ()->addAction ("close_all_editors", this, SLOT (slotCloseAllEditors())); close_all_editors->setText (i18n ("Close All Data")); close_all_editors->setStatusTip (i18n ("Closes all open data editors")); action = actionCollection ()->addAction (KStandardAction::Close, "window_close", this, SLOT (slotCloseWindow())); window_close_all = actionCollection ()->addAction ("window_close_all", this, SLOT (slotCloseAllWindows())); window_close_all->setText (i18n ("Close All")); window_detach = actionCollection ()->addAction ("window_detach", this, SLOT (slotDetachWindow())); window_detach->setIcon (RKStandardIcons::getIcon (RKStandardIcons::ActionDetachWindow)); window_detach->setText (i18n ("Detach")); configure = actionCollection ()->addAction (KStandardAction::Preferences, "options_configure", this, SLOT (slotConfigure())); action = actionCollection()->addAction("setup_wizard"); action->setText(i18n("Check installation")); connect(action, &QAction::triggered, &RKSetupWizard::manualCheck); edit_menu_dummy = actionCollection ()->addAction ("edit_menu_dummy", this); edit_menu_dummy->setText (i18n ("[No actions available for current view]")); edit_menu_dummy->setEnabled (false); view_menu_dummy = actionCollection ()->addAction ("view_menu_dummy", this); view_menu_dummy->setText (edit_menu_dummy->text ()); view_menu_dummy->setEnabled (false); // collections for the toolbar: open_any_action = new KActionMenu (QIcon::fromTheme("document-open-folder"), i18n ("Open..."), this); open_any_action->setDelayed (false); actionCollection ()->addAction ("open_any", open_any_action); open_any_action->addAction (fileOpenWorkspace); open_any_action->addAction (fileOpenRecentWorkspace); open_any_action->addSeparator (); open_any_action->addAction (fileOpen); open_any_action->addAction (fileOpenRecent); open_any_action->addAction (file_open_any); open_any_action->addSeparator (); //open_any_action->addAction (proxy_import); -> later KActionMenu* new_any_action = new KActionMenu (QIcon::fromTheme("document-new"), i18n ("Create..."), this); new_any_action->setDelayed (false); actionCollection ()->addAction ("new_any", new_any_action); new_any_action->addAction (new_data_frame); new_any_action->addAction (new_command_editor); save_any_action = new KActionMenu (QIcon::fromTheme("document-save"), i18n ("Save..."), this); save_any_action->setDelayed (false); actionCollection ()->addAction ("save_any", save_any_action); save_any_action->addAction (fileSaveWorkspace); save_any_action->addAction (fileSaveWorkspaceAs); save_any_action->addSeparator (); // TODO: A way to add R-script-save actions, dynamically, would be nice save_actions_plug_point = save_any_action->addSeparator (); //save_any_action->addAction (proxy_export); -> later } /* // debug code: prints out all current actions void printActionsRecursive (QAction* action, const QString &prefix) { if (action->menu ()) { foreach (QAction *a, action->menu ()->actions ()) printActionsRecursive (a, prefix + action->text () + "->"); } else { qDebug ("%s", qPrintable (prefix + action->text ())); } } */ void updateEmptyMenuIndicator (QAction* indicator, const QMenu *menu) { if (!menu) { indicator->setVisible (false); return; } // NOTE: QMenu::isEmpty () does not work, here QList actions = menu->actions (); for (int i = 0; i < actions.size (); ++i) { if (actions[i] == indicator) continue; if (actions[i]->isSeparator ()) continue; if (actions[i]->isVisible ()) { indicator->setVisible (false); return; } } indicator->setVisible (true); } void RKWardMainWindow::partChanged (KParts::Part *part) { RK_TRACE (APP); if (gui_rebuild_locked) return; if (!part) return; createGUI (part); if (!guiFactory ()) { RK_ASSERT (false); return; } updateEmptyMenuIndicator (edit_menu_dummy, dynamic_cast(guiFactory ()->container ("edit", this))); updateEmptyMenuIndicator (view_menu_dummy, dynamic_cast(guiFactory ()->container ("view", this))); // plug save file actions into the toolbar collections RK_ASSERT (save_any_action); for (int i = 0; i < plugged_save_actions.size (); ++i) { QAction* a = plugged_save_actions[i].data (); if (a) save_any_action->removeAction (a); } plugged_save_actions.clear (); RKMDIWindow *w = RKWorkplace::mainWorkplace ()->activeWindow (RKMDIWindow::Attached); if (w && (w->isType (RKMDIWindow::CommandEditorWindow))) { QAction *a = static_cast(w)->fileSaveAction (); if (a) plugged_save_actions.append (a); a = static_cast(w)->fileSaveAsAction (); if (a) plugged_save_actions.append (a); } for (int i = 0; i < plugged_save_actions.size (); ++i) { save_any_action->insertAction (save_actions_plug_point, plugged_save_actions[i]); } /* // debug code: prints out all current actions foreach (QAction *action, menuBar ()->actions ()) printActionsRecursive (action, QString ()); */ } void RKWardMainWindow::lockGUIRebuild (bool lock) { RK_TRACE (APP); if (lock) { RK_ASSERT (!gui_rebuild_locked); gui_rebuild_locked = true; } else { gui_rebuild_locked = false; partChanged (part_manager->activePart ()); } } void RKWardMainWindow::initStatusBar () { RK_TRACE (APP); statusbar_ready = new QLabel (i18n ("Ready."), statusBar ()); statusBar ()->addWidget (statusbar_ready); statusbar_cwd = new KSqueezedTextLabel (statusBar ()); statusbar_cwd->setAlignment (Qt::AlignRight); statusbar_cwd->setToolTip (i18n ("Current working directory")); statusBar ()->addWidget (statusbar_cwd, 10); updateCWD (); QWidget *box = new QWidget (statusBar ()); QHBoxLayout *boxl = new QHBoxLayout (box); boxl->setSpacing (0); statusbar_r_status = new QLabel (" R ", box); statusbar_r_status->setFixedHeight (statusBar ()->fontMetrics ().height () + 2); boxl->addWidget (statusbar_r_status); QToolButton* dummy = new QToolButton (box); dummy->setDefaultAction (interrupt_all_commands); dummy->setFixedHeight (statusbar_r_status->height ()); dummy->setAutoRaise (true); boxl->addWidget (dummy); statusBar ()->addPermanentWidget (box, 0); setRStatus (RInterface::Starting); } void RKWardMainWindow::openWorkspace (const QUrl &url) { RK_TRACE (APP); if (url.isEmpty ()) return; new RKLoadAgent (url, merge_loads); } void RKWardMainWindow::saveOptions () { RK_TRACE (APP); KSharedConfig::Ptr config = KSharedConfig::openConfig (); KConfigGroup cg = config->group ("main window options"); saveMainWindowSettings (cg); cg = config->group ("General Options"); // TODO: WORKAROUND. See corresponding line in readOptions () cg.writeEntry("Geometry", size ()); fileOpenRecentWorkspace->saveEntries (config->group ("Recent Files")); fileOpenRecent->saveEntries (config->group ("Recent Command Files")); RKSettings::saveSettings (config.data ()); config->sync (); } void RKWardMainWindow::readOptions () { RK_TRACE (APP); KSharedConfig::Ptr config = KSharedConfig::openConfig (); applyMainWindowSettings (config->group ("main window options")); // TODO: WORKAROUND: Actually applyMainWindowSettings could/should do this, but apparently this just does not work for maximized windows. Therefore we use our own version instead. // KDE4: still needed? // KF5 TODO: still needed? KConfigGroup cg = config->group ("General Options"); QSize size = cg.readEntry ("Geometry", QSize ()); if (size.isEmpty ()) { size = QApplication::desktop ()->availableGeometry ().size (); } resize (size); RKSettings::loadSettings (config.data ()); // initialize the recent file list fileOpenRecentWorkspace->loadEntries (config->group ("Recent Files")); fileOpenRecent->setMaxItems (RKSettingsModuleCommandEditor::maxNumRecentFiles ()); fileOpenRecent->loadEntries (config->group ("Recent Command Files")); } bool RKWardMainWindow::doQueryQuit () { RK_TRACE (APP); slotSetStatusBarText (i18n ("Exiting...")); saveOptions (); if (RKSettingsModuleGeneral::workplaceSaveMode () == RKSettingsModuleGeneral::SaveWorkplaceWithSession) { RKSettingsModuleGeneral::setSavedWorkplace (RKWorkplace::mainWorkplace ()->makeWorkplaceDescription ().join ("\n"), KSharedConfig::openConfig ().data ()); } // if (!RObjectList::getGlobalEnv ()->isEmpty ()) { int res; res = KMessageBox::questionYesNoCancel (this, i18n ("Quitting RKWard: Do you want to save the workspace?"), i18n ("Save Workspace?"), KStandardGuiItem::save (), KStandardGuiItem::discard (), KGuiItem (i18n ("Do Not Quit"))); if (res == KMessageBox::Yes) { new RKSaveAgent (RKWorkplace::mainWorkplace ()->workspaceURL (), false, RKSaveAgent::DoNothing); } else if (res == KMessageBox::Cancel) { slotSetStatusReady (); return false; } // } RKWorkplace::RKWorkplaceObjectList map = RKWorkplace::mainWorkplace ()->getObjectList (); for (RKWorkplace::RKWorkplaceObjectList::const_iterator it = map.constBegin (); it != map.constEnd (); ++it) { lockGUIRebuild (true); if (!(*it)->close (true)) { if (!(*it)->isType (RKMDIWindow::X11Window)) { // X11 windows have a delayed close // If a child refuses to close, we return false. slotSetStatusReady (); lockGUIRebuild (false); return false; } } gui_rebuild_locked = false; // like lockGUIRebuild (false), but does not trigger an immediate rebuild, as we are about to leave, anyway. } return true; } void RKWardMainWindow::slotNewDataFrame () { RK_TRACE (APP); bool ok; QString name = QInputDialog::getText (this, i18n ("New dataset"), i18n ("Enter name for the new dataset"), QLineEdit::Normal, "my.data", &ok); if (ok) RKWorkplace::mainWorkplace ()->editNewDataFrame (name); } void RKWardMainWindow::askOpenWorkspace (const QUrl &url) { RK_TRACE (APP); if (!no_ask_save && ((!RObjectList::getGlobalEnv ()->isEmpty () && workspace_modified) || !RKGlobals::rInterface ()->backendIsIdle ())) { int res; res = KMessageBox::questionYesNoCancel (this, i18n ("Do you want to save the current workspace?"), i18n ("Save Workspace?")); if (res == KMessageBox::Yes) { new RKSaveAgent (RKWorkplace::mainWorkplace ()->workspaceURL (), false, RKSaveAgent::Load, url); } else if (res != KMessageBox::No) { // Cancel return; } } slotCloseAllEditors (); slotSetStatusBarText(i18n("Opening workspace...")); QUrl lurl = url; if (lurl.isEmpty ()) { lurl = QFileDialog::getOpenFileUrl (this, i18n("Select workspace to open..."), RKSettingsModuleGeneral::lastUsedUrlFor ("workspaces"), i18n ("R Workspace Files [%1](%1);;All files [*](*)", RKSettingsModuleGeneral::workspaceFilenameFilter ())); } if (!lurl.isEmpty ()) { RKSettingsModuleGeneral::updateLastUsedUrl ("workspaces", lurl.adjusted (QUrl::RemoveFilename)); openWorkspace (lurl); } slotSetStatusReady (); } void RKWardMainWindow::slotFileOpenWorkspace () { RK_TRACE (APP); askOpenWorkspace (QUrl ()); } void RKWardMainWindow::slotFileLoadLibs () { RK_TRACE (APP); RKLoadLibsDialog *dial = new RKLoadLibsDialog (this, 0); dial->show (); } void RKWardMainWindow::slotFileSaveWorkspace () { RK_TRACE (APP); new RKSaveAgent (RKWorkplace::mainWorkplace ()->workspaceURL ()); } void RKWardMainWindow::slotFileSaveWorkspaceAs () { RK_TRACE (APP); new RKSaveAgent (RKWorkplace::mainWorkplace ()->workspaceURL (), true); } void RKWardMainWindow::addWorkspaceUrl (const QUrl &url) { RK_TRACE (APP); if (!url.isEmpty ()) fileOpenRecentWorkspace->addUrl (url); setCaption (QString ()); // trigger update of caption } void RKWardMainWindow::updateCWD () { RK_TRACE (APP); statusbar_cwd->setText (QDir::currentPath ()); } void RKWardMainWindow::slotSetStatusBarText (const QString &text) { RK_TRACE (APP); //KDE4: still needed? QString ntext = text.trimmed (); ntext.replace ("", QString ()); // WORKAROUND: what the ?!? is going on? The KTHMLPart seems to post such messages. if (ntext.isEmpty ()) { statusBar ()->clearMessage (); } else { statusBar ()->showMessage (ntext); } } void RKWardMainWindow::slotCloseWindow () { RK_TRACE (APP); RKWorkplace::mainWorkplace ()->closeActiveWindow (); } void RKWardMainWindow::slotCloseAllWindows () { RK_TRACE (APP); RKWorkplace::mainWorkplace ()->closeAll (); } void RKWardMainWindow::slotCloseAllEditors () { RK_TRACE (APP); RKWorkplace::mainWorkplace ()->closeAll (RKMDIWindow::DataEditorWindow); } void RKWardMainWindow::slotDetachWindow () { RK_TRACE (APP); RKWorkplace::mainWorkplace ()->detachWindow (RKWorkplace::mainWorkplace ()->activeWindow (RKMDIWindow::Attached)); } void RKWardMainWindow::setRStatus (int status) { RK_TRACE (APP); QColor status_color; if (status == RInterface::Busy) { status_color = QColor (255, 0, 0); statusbar_r_status->setToolTip (i18n ("The R engine is busy.")); interrupt_all_commands->setEnabled (true); } else if (status == RInterface::Idle) { status_color = QColor (0, 255, 0); statusbar_r_status->setToolTip (i18n ("The R engine is idle.")); interrupt_all_commands->setEnabled (false); } else if (status == RInterface::Starting) { status_color = QColor (255, 255, 0); statusbar_r_status->setToolTip (i18n ("The R engine is being initialized.")); } else { status_color = QColor (255, 0, 0); statusbar_r_status->setToolTip (i18n ("The R engine is unavailable.")); interrupt_all_commands->setEnabled (false); } QPalette palette = statusbar_r_status->palette (); palette.setBrush (statusbar_r_status->backgroundRole(), QBrush (status_color)); statusbar_r_status->setAutoFillBackground (true); statusbar_r_status->setPalette (palette); } void RKWardMainWindow::importData () { RK_TRACE (APP); new RKImportDialog ("import", this); } void RKWardMainWindow::slotNewCommandEditor () { RK_TRACE (APP); slotOpenCommandEditor (QUrl ()); } void RKWardMainWindow::addScriptUrl (const QUrl &url) { RK_TRACE (APP); if (!url.isEmpty ()) fileOpenRecent->addUrl (url); } void RKWardMainWindow::openAnyFile () { RK_TRACE (APP); QFileDialog* dialog = new QFileDialog (0, QString (), RKSettingsModuleGeneral::lastUsedUrlFor ("rscripts").toLocalFile (), QString ("*|All Files (*)\n%1|R Script Files (%1)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ())); dialog->setFileMode (QFileDialog::ExistingFiles); // Create a type selection widget, and hack it into the dialog: QFrame* dummy = new QFrame (this); dummy->setWindowTitle (i18n ("Open")); QVBoxLayout* layout = new QVBoxLayout (dummy); QHBoxLayout* hbox = new QHBoxLayout; layout->addLayout (hbox); hbox->addWidget (new QLabel (i18n ("Opening mode:"))); QComboBox* open_mode = new QComboBox; open_mode->addItems (QStringList () << i18n ("Guess file type, automatically") << i18n ("Open as text / script file") << i18n ("Open as text file and force R highlighting") << ("Open as R workspace")); hbox->addWidget (open_mode); hbox->setStretchFactor (open_mode, 100); dummy->setWindowFlags (dialog->windowFlags ()); dialog->setOption (QFileDialog::DontUseNativeDialog); dialog->setWindowFlags (Qt::Widget); layout->addWidget (dialog); dummy->show (); auto res = dialog->exec (); QUrl url = QUrl::fromLocalFile (dialog->selectedFiles ().value (0)); int mode = open_mode->currentIndex (); delete dummy; if (res != QDialog::Accepted) return; if (mode == 0) { RKWorkplace::mainWorkplace ()->openAnyUrl (url); } else if (mode == 1) { RKWorkplace::mainWorkplace ()->openScriptEditor (url); RKSettingsModuleGeneral::updateLastUsedUrl ("rscripts", url.adjusted (QUrl::RemoveFilename)); } else if (mode == 2) { RKWorkplace::mainWorkplace ()->openScriptEditor (url, QString (), RKCommandEditorFlags::DefaultFlags | RKCommandEditorFlags::ForceRHighlighting); RKSettingsModuleGeneral::updateLastUsedUrl ("rscripts", url.adjusted (QUrl::RemoveFilename)); } else if (mode == 3) { openWorkspace (url); RKSettingsModuleGeneral::updateLastUsedUrl ("workspaces", url.adjusted (QUrl::RemoveFilename)); } } void RKWardMainWindow::slotOpenCommandEditor (const QUrl &url, const QString &encoding) { RK_TRACE (APP); RKWorkplace::mainWorkplace ()->openScriptEditor (url, encoding); } void RKWardMainWindow::slotOpenCommandEditor () { RK_TRACE (APP); KEncodingFileDialog::Result res; res = KEncodingFileDialog::getOpenUrlsAndEncoding (QString (), RKSettingsModuleGeneral::lastUsedUrlFor ("rscripts"), QString ("%1|R Script Files (%1)\n*|All Files (*)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ()), this, i18n ("Open script file(s)")); for (int i = 0; i < res.URLs.size (); ++i) { if (i == 0) RKSettingsModuleGeneral::updateLastUsedUrl ("rscripts", res.URLs[i].adjusted (QUrl::RemoveFilename)); slotOpenCommandEditor (res.URLs[i], res.encoding); } }; void RKWardMainWindow::setCaption (const QString &) { RK_TRACE (APP); QString wcaption = RKWorkplace::mainWorkplace ()->workspaceURL ().fileName (); if (wcaption.isEmpty ()) wcaption = RKWorkplace::mainWorkplace ()->workspaceURL ().toDisplayString (); if (wcaption.isEmpty ()) wcaption = i18n ("[Unnamed Workspace]"); RKMDIWindow *window = RKWorkplace::mainWorkplace ()->view ()->activePage (); if (window) wcaption.append (" - " + window->fullCaption ()); KParts::MainWindow::setCaption (wcaption); } rkward-0.7.2/rkward/Info.plist0000644000175000017510000000272413640140626015634 0ustar thomasthomas CFBundleDevelopmentRegion English CFBundleExecutable ${MACOSX_BUNDLE_EXECUTABLE_NAME} CFBundleGetInfoString ${MACOSX_BUNDLE_INFO_STRING} CFBundleIconFile ${MACOSX_BUNDLE_ICON_FILE} CFBundleIdentifier ${MACOSX_BUNDLE_GUI_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString ${MACOSX_BUNDLE_LONG_VERSION_STRING} CFBundleName ${MACOSX_BUNDLE_BUNDLE_NAME} CFBundleDisplayName ${MACOSX_BUNDLE_DISPLAY_NAME} CFBundlePackageType APPL CFBundleShortVersionString ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleVersion ${MACOSX_BUNDLE_BUNDLE_VERSION} CSResourcesFileMapped LSRequiresCarbon NSAppSleepDisabled NSSupportsAutomaticTermination NSPrincipalClass NSApplication NSHighResolutionCapable True NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} rkward-0.7.2/rkward/dialogs/0000744000175000017510000000000013740267466015314 5ustar thomasthomasrkward-0.7.2/rkward/dialogs/rkreadlinedialog.h0000644000175000017510000000457213572465432020773 0ustar thomasthomas/*************************************************************************** rkreadlinedialog - description ------------------- begin : Fri Sep 15 2006 copyright : (C) 2006, 2007, 2009 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKREADLINEDIALOG_H #define RKREADLINEDIALOG_H #include class QLineEdit; class QWidget; class RCommand; /** This class represent a dialog asking for a line of input. It is used, when the backend calls readline(). This dialog displays the question asked, the output context (as often times the question is not meaningful without that context), and a QLineEdit to get the user response. @author Thomas Friedrichsmeier */ class RKReadLineDialog : public QDialog { public: /** Construct and run modal RKReadLineDialog. @param parent QWidget to center the modal dialog on (0 for application) @param prompt The question @param command The command the readline() has arisen from. This is used to get the relevant output context @param result The answer to the question (the line read) will be stored in this string @returns true if ok was pressed (or the dialog was closed), false if cancel was pressed (i.e. the command should be cancelled) */ static bool readLine (QWidget *parent, const QString &caption, const QString &prompt, RCommand *command, QString *result); protected: /** ctor. Use the static readLine() instead. */ RKReadLineDialog (QWidget *parent, const QString &caption, const QString &prompt, RCommand *command); /** destructor */ ~RKReadLineDialog (); private: QLineEdit *input; static QByteArray stored_geom; }; #endif rkward-0.7.2/rkward/dialogs/rkrecoverdialog.cpp0000664000175000017510000001277713736365060021216 0ustar thomasthomas/*************************************************************************** rkrecoverdialog - description ------------------- begin : Fri Feb 04 2011 copyright : (C) 2011, 2012, 2014 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "rkrecoverdialog.h" #include #include #include #include #include #include #include #include #include #include "../settings/rksettingsmodulegeneral.h" #include "../misc/rkcommonfunctions.h" #include "../misc/rkdialogbuttonbox.h" #include "../debug.h" RKRecoverDialog::RKRecoverDialog (const QStringList &recovery_files) : QDialog () { RK_TRACE (DIALOGS); RK_ASSERT (!recovery_files.isEmpty ()); files = recovery_files; QVBoxLayout *layout = new QVBoxLayout (this); const QString caption = i18n ("Crash recovery file detected"); setWindowTitle (caption); QString text = QString ("

%1

").arg (caption); text.append (i18n ("

It looks like RKWard has crashed, recently. We are sorry about that! However, not everything is lost, and with a bit of luck, your data has been saved in time.

")); text.append (i18np ("

A workspace recovery file exists, dating from %2.

", "

%1 workspace recovery files exist, the most recent one of which dates from %2.

", recovery_files.count (), QFileInfo (recovery_files.first ()).lastModified ().toString (Qt::SystemLocaleShortDate))); text.append (i18n ("

Do you want to open this file, now, save it for later (as %1), or discard it?

", saveFileFor (recovery_files.first ()))); layout->addWidget (RKCommonFunctions::wordWrappedLabel (text)); RKDialogButtonBox *buttons = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Discard, this); buttons->button (QDialogButtonBox::Ok)->setText (i18n ("Recover")); RKCommonFunctions::setTips (i18n ("Saves the recovery file(s), and opens it (or the most recent one)"), buttons->button (QDialogButtonBox::Ok)); buttons->button (QDialogButtonBox::Cancel)->setText (i18n ("Save for later")); RKCommonFunctions::setTips (i18n ("Saves the recovery file(s) for later use, but does not open it"), buttons->button (QDialogButtonBox::Cancel)); buttons->button (QDialogButtonBox::Discard)->setText (i18n ("Delete")); RKCommonFunctions::setTips (i18n ("Deletes the recovery file(s)"), buttons->button (QDialogButtonBox::Discard)); connect (buttons->button (QDialogButtonBox::Discard), &QPushButton::clicked, this, &RKRecoverDialog::deleteButtonClicked); layout->addWidget (buttons); } RKRecoverDialog::~RKRecoverDialog () { RK_TRACE (DIALOGS); } void RKRecoverDialog::deleteButtonClicked () { RK_TRACE (DIALOGS); if (KMessageBox::warningContinueCancel (this, i18np ("You are about to delete the recovery file %2. There will be no way to bring it back. Really delete it?", "You are about to delete %1 recovery files (the most recent one is %2). There will be no way to bring them back. Really delete them?", files.count (), files.first ()), i18n ("Really delete recovery file(s)?"), KStandardGuiItem::del()) != KMessageBox::Continue) return; for (int i = 0; i < files.count (); ++i) { QFile (files[i]).remove (); // TODO: error handling? } files.clear (); reject (); } //static QString RKRecoverDialog::saveFileFor (const QString& recovery_file) { RK_TRACE (DIALOGS); QFileInfo fi (recovery_file); QDateTime mtime = fi.lastModified (); QDir dir = fi.absoluteDir (); QString new_name; for (int i = 0; i < 100; ++i) { // If we just had more than 100 crashes per minutes, you'll excuse another small bug, at this point QString num; if (i > 0) num = '_' + QString::number (i+1); new_name = dir.absoluteFilePath ("recovered_workspace_" + mtime.toString ("yyyy-MM-dd_hh:mm") + num + ".RData"); if (!QFileInfo (new_name).exists ()) break; } return new_name; } //static QUrl RKRecoverDialog::checkRecoverCrashedWorkspace () { RK_TRACE (DIALOGS); QDir dir (RKSettingsModuleGeneral::filesPath ()); dir.setNameFilters (QStringList ("rkward_recover*.RData")); QStringList matches = dir.entryList (QDir::Files, QDir::Time); for (int i = 0; i < matches.count (); ++i) { matches[i] = dir.absoluteFilePath (matches[i]); } if (!matches.isEmpty ()) { RKRecoverDialog dialog (matches); dialog.exec (); // "Save" recovery files, so they want be matched, again matches = dialog.files; // May have been modified, notably deleted for (int i = matches.count () - 1; i >= 0; --i) { QString new_name = saveFileFor (matches[i]); QFile::rename (matches[i], new_name); matches[i] = new_name; } if (dialog.result () == QDialog::Accepted) return (QUrl::fromLocalFile (dir.absoluteFilePath (matches.first ()))); } return QUrl (); } rkward-0.7.2/rkward/dialogs/rkimportdialog.h0000664000175000017510000000375613736365060020525 0ustar thomasthomas/*************************************************************************** rkimportdialog - description ------------------- begin : Tue Jan 30 2007 copyright : (C) 2007 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKIMPORTDIALOG_H #define RKIMPORTDIALOG_H #include #include class QComboBox; class RKComponentGUIXML; /** This dialog is designed to allow the user to select a file, and file format. After that a suitable plugin is opened automatically to deal with this type of file . */ class RKImportDialog : public QFileDialog { Q_OBJECT public: /** constructor @param context_id The id of the context containing the relevant plugins @param parent Parent widget (dialog will be centered on this widget, if non-zero */ RKImportDialog (const QString &context_id, QWidget *parent); /** dtor */ ~RKImportDialog (); protected: /** reimplemented to a) invoke the relevant plugin, b) trigger self-destruction of the dialog */ void accept () override; /** reimplemented to trigger self-destruction of the dialog */ void reject () override; private: int format_count; QStringList filters; QStringList component_ids; RKComponentGUIXML *context; }; #endif rkward-0.7.2/rkward/dialogs/rkreadlinedialog.cpp0000664000175000017510000000723313736365060021323 0ustar thomasthomas/*************************************************************************** rkreadlinedialog - description ------------------- begin : Fri Sep 15 2006 copyright : (C) 2006, 2007, 2008, 2009 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "rkreadlinedialog.h" #include #include #include #include #include #include #include #include #include #include #include "../rbackend/rcommand.h" #include "../misc/rkdialogbuttonbox.h" #include "../misc/rkcommonfunctions.h" #include "../debug.h" QByteArray RKReadLineDialog::stored_geom; RKReadLineDialog::RKReadLineDialog (QWidget *parent, const QString &caption, const QString &prompt, RCommand *command) : QDialog (parent) { RK_TRACE (DIALOGS); RK_ASSERT (command); setModal (true); setWindowTitle (caption); QVBoxLayout *layout = new QVBoxLayout (this); layout->addWidget (new QLabel (caption, this)); int screen_width = qApp->desktop ()->availableGeometry (this).width (); QString context = command->fullOutput (); if (!context.isEmpty ()) { layout->addWidget (new QLabel (i18n ("Context:"), this)); QTextEdit *output = new QTextEdit (this); output->setUndoRedoEnabled (false); output->setPlainText (QString ()); output->setCurrentFont (QFontDatabase::systemFont (QFontDatabase::FixedFont)); output->setLineWrapMode (QTextEdit::NoWrap); output->insertPlainText (context); output->setReadOnly (true); // there seems to be no easier way to get at the contents width... int cwidth = output->horizontalScrollBar ()->maximum () + output->width (); output->setMinimumWidth (screen_width < cwidth ? screen_width : cwidth); output->moveCursor (QTextCursor::End); output->setFocusPolicy (Qt::NoFocus); layout->addWidget (output); layout->setStretchFactor (output, 10); } QLabel *promptl = RKCommonFunctions::wordWrappedLabel (prompt); layout->addWidget (promptl); input = new QLineEdit (QString (), this); input->setMinimumWidth (fontMetrics ().maxWidth ()*20); input->setFocus (); layout->addWidget (input); RKDialogButtonBox *box = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); layout->addWidget (box); } RKReadLineDialog::~RKReadLineDialog () { RK_TRACE (DIALOGS); } //static bool RKReadLineDialog::readLine (QWidget *parent, const QString &caption, const QString &prompt, RCommand *command, QString *result) { RK_TRACE (DIALOGS); RK_ASSERT (result); RKReadLineDialog *dialog = new RKReadLineDialog (parent, caption, prompt, command); if (!stored_geom.isNull ()) dialog->restoreGeometry (stored_geom); QTimer::singleShot (0, dialog->input, SLOT(setFocus())); int res = dialog->exec (); *result = dialog->input->text (); stored_geom = dialog->saveGeometry (); delete dialog; return (res != QDialog::Rejected); } rkward-0.7.2/rkward/dialogs/startupdialog.cpp0000664000175000017510000001573613736365060020714 0ustar thomasthomas/*************************************************************************** startupdialog - description ------------------- begin : Thu Aug 26 2004 copyright : (C) 2004-2018 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "startupdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../settings/rksettingsmodulegeneral.h" #include "../misc/rkcommonfunctions.h" #include "../misc/rkdialogbuttonbox.h" #include "../debug.h" StartupDialog::StartupDialog (QWidget *parent, StartupDialogResult *result, KRecentFilesAction *recent_files) : QDialog (parent) { RK_TRACE (DIALOGS); setModal (true); StartupDialog::result = result; setWindowTitle (i18n ("What would you like to do?")); QVBoxLayout *vbox = new QVBoxLayout (); setLayout (vbox); QLabel *pic = new QLabel (this); vbox->addWidget (pic); pic->setPixmap (QPixmap (RKCommonFunctions::getRKWardDataDir () + "icons/rkward_logo.png")); choser = new QButtonGroup (this); QGroupBox* choser_box = new QGroupBox (this); vbox->addWidget (choser_box); QVBoxLayout* choser_layout = new QVBoxLayout(choser_box); choser_layout->addWidget (empty_workspace_button = new QRadioButton (i18n ("Start with an empty workspace"), choser_box)); choser->addButton (empty_workspace_button); choser_layout->addWidget (empty_table_button = new QRadioButton (i18n ("Start with an empty table"), choser_box)); choser->addButton (empty_table_button); QUrl rdata_file = getRestoreFile (); choser_layout->addWidget (restore_workspace_button = new QRadioButton (choser_box)); choser->addButton (restore_workspace_button); if (rdata_file.isEmpty ()) { restore_workspace_button->setEnabled (false); restore_workspace_button->setText (i18n ("Load workspace from current directory")); } else restore_workspace_button->setText (i18n ("Load workspace from current directory:\n%1", rdata_file.toLocalFile ())); choser_layout->addWidget (open_button = new QRadioButton (i18n ("Load an existing workspace:"), choser_box)); choser->addButton (open_button); connect (open_button, &QRadioButton::toggled, this, &StartupDialog::openButtonSelected); empty_table_button->setChecked (true); file_list = new QListWidget (choser_box); file_list->setSelectionMode (QAbstractItemView::SingleSelection); file_list->setSortingEnabled (false); chose_file_item = new QListWidgetItem (i18n ("<>"), file_list); if (recent_files) { QList urls = recent_files->urls (); for (int i = 0; i < urls.length (); ++i) { file_list->addItem (urls[i].url (QUrl::PreferLocalFile)); } } connect (file_list, &QListWidget::itemClicked, this, &StartupDialog::listClicked); connect (file_list, &QListWidget::itemDoubleClicked, this, &StartupDialog::listDoubleClicked); choser_layout->addWidget (file_list); choser_layout->addWidget (remember_box = new QCheckBox (i18n ("Always do this on startup"), choser_box)); RKDialogButtonBox *buttonBox = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); buttonBox->button (QDialogButtonBox::Ok)->setDefault (true); vbox->addWidget (buttonBox); } StartupDialog::~StartupDialog() { RK_TRACE (DIALOGS); } void StartupDialog::accept () { RK_TRACE (DIALOGS); if (empty_workspace_button->isChecked ()) { result->result = EmptyWorkspace; } else if (empty_table_button->isChecked ()) { result->result = EmptyTable; } else if (restore_workspace_button->isChecked ()) { result->result = RestoreFromWD; result->open_url = getRestoreFile (); } else if (open_button->isChecked ()) { QListWidgetItem *item = file_list->currentItem (); if (item == chose_file_item) { result->result = ChoseFile; } else { result->result = OpenFile; result->open_url = QUrl::fromLocalFile (item->text ()); } } else { RK_ASSERT (false); } if (remember_box->isChecked ()) RKSettingsModuleGeneral::setStartupAction (result->result); QDialog::accept (); } void StartupDialog::reject () { RK_TRACE (DIALOGS); result->result = EmptyWorkspace; QDialog::reject (); } void StartupDialog::listDoubleClicked (QListWidgetItem *item) { RK_TRACE (DIALOGS); if (item) { open_button->setChecked (true); file_list->setCurrentItem (item); item->setSelected (true); accept (); } } void StartupDialog::listClicked (QListWidgetItem *item) { RK_TRACE (DIALOGS); if (item) { open_button->setChecked (true); openButtonSelected (true); // always do processing } } void StartupDialog::openButtonSelected (bool checked) { RK_TRACE (DIALOGS); if (checked) { if (!file_list->currentItem ()) { file_list->setCurrentRow (0); } if (file_list->currentItem () != chose_file_item) { remember_box->setChecked (false); remember_box->setEnabled (false); } else { remember_box->setEnabled (true); } } else { remember_box->setEnabled (true); } } void StartupDialog::showEvent (QShowEvent *event) { RK_TRACE (DIALOGS); // somehow, trying to achieve this in the ctor leads to the dialog never actually being shown (KDE4.0 beta) setFixedWidth (width ()); QDialog::showEvent (event); } // static QUrl StartupDialog::getRestoreFile () { RK_TRACE (DIALOGS); QFileInfo rdata_file (".RData"); if (rdata_file.exists ()) return QUrl::fromLocalFile (rdata_file.absoluteFilePath ()); return QUrl (); } //static StartupDialog::StartupDialogResult StartupDialog::getStartupAction (QWidget *parent, KRecentFilesAction *recent_files) { RK_TRACE (DIALOGS); StartupDialogResult result; result.result = RKSettingsModuleGeneral::startupAction (); if (result.result == RestoreFromWD) { result.open_url = getRestoreFile (); if (result.open_url.isEmpty ()) result.result = NoSavedSetting; } if (result.result != NoSavedSetting) { return result; } StartupDialog *dialog = new StartupDialog (parent, &result, recent_files); dialog->exec (); delete dialog; RK_DEBUG (DIALOGS, DL_DEBUG, "startup-dialog result: %d, url: %s", result.result, qPrintable (result.open_url.url ())); return result; } rkward-0.7.2/rkward/dialogs/rkloadlibsdialog.h0000664000175000017510000002375013736365060021000 0ustar thomasthomas/*************************************************************************** rkloadlibsdialog - description ------------------- begin : Mon Sep 6 2004 copyright : (C) 2004 - 2020 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKLOADLIBSDIALOG_H #define RKLOADLIBSDIALOG_H #include #include #include #include #include "../settings/rksettingsmoduler.h" #include "../rbackend/rcommandreceiver.h" class QLineEdit; class QTreeView; class QTreeWidget; class QSortFilterProxyModel; class QComboBox; class QPushButton; class RKProgressControl; class QWidget; class QCloseEvent; class RCommandChain; class QCheckBox; class PackageInstallParamsWidget; class InstallPackagesWidget; class RKDynamicSearchLine; /** Dialog which excapsulates widgets to load/unload, update and install R packages @author Thomas Friedrichsmeier */ // TODO: add a static member to create (single) instance of the dialog class RKLoadLibsDialog : public KPageDialog, public RCommandReceiver { Q_OBJECT public: RKLoadLibsDialog (QWidget *parent, RCommandChain *chain, bool modal=false); ~RKLoadLibsDialog (); bool installPackages (const QStringList &packages, QString to_libloc, bool install_suggested_packages, const QStringList& repos); bool removePackages (QStringList packages, QStringList from_liblocs); /** opens a modal RKLoadLibsDialog with the "Install new Packages" tab on front (To be used when a require () fails in the R backend @param parent parent QWidget. The dialog will be centered there @param chain RCommandChain to run the necessary commands in @param package_name name of the required package */ static void showInstallPackagesModal (QWidget *parent, RCommandChain *chain, const QStringList &package_names); static void showPluginmapConfig (QWidget *parent=0, RCommandChain *chain=0); QStringList currentLibraryLocations () const { return library_locations; }; void accept () override; void reject () override; signals: void downloadComplete (); void installationComplete (); void libraryLocationsChanged (const QStringList &liblocs); void installationOutput (const QString &output); void installationError (const QString &error); void installedPackagesChanged (); protected: void rCommandDone (RCommand *command) override; void closeEvent (QCloseEvent *e) override; protected slots: void childDeleted (); void processExited (int exitCode, QProcess::ExitStatus exitStatus); void installationProcessOutput (); void installationProcessError (); void automatedInstall (const QStringList &packages); void slotPageChanged (); private: void addLibraryLocation (const QString &new_loc); void tryDestruct (); void runInstallationCommand (const QString& command, bool as_root, const QString& message, const QString& title); KPageWidgetItem* addChild (QWidget *child_page, const QString &caption); friend class LoadUnloadWidget; friend class InstallPackagesWidget; RCommandChain *chain; InstallPackagesWidget *install_packages_widget; // needed for automated installation KPageWidgetItem *install_packages_pageitem; KPageWidgetItem *configure_pluginmaps_pageitem; QStringList library_locations; int num_child_widgets; bool was_accepted; QProcess* installation_process; }; /** Shows which packages are available (installed) / loaded, and lets the user load or detach packages. To be used in RKLoadLibsDialog @author Thomas Friedrichsmeier */ class LoadUnloadWidget : public QWidget, public RCommandReceiver { Q_OBJECT public: explicit LoadUnloadWidget (RKLoadLibsDialog *dialog); ~LoadUnloadWidget (); signals: void loadUnloadDone (); public slots: void loadButtonClicked (); void detachButtonClicked (); void ok (); void apply (); void cancel (); void updateInstalledPackages (); void updateButtons (); void activated (); protected: void rCommandDone (RCommand *command) override; private: void updateCurrentList (); void doLoadUnload (); QTreeWidget *loaded_view; QTreeWidget *installed_view; QPushButton *load_button; QPushButton *detach_button; QStringList prev_packages; RKLoadLibsDialog *parent; }; /** Item model and encapsulation for package status (used in InstallPackagesWidget) */ class RKRPackageInstallationStatus : public QAbstractItemModel { Q_OBJECT public: explicit RKRPackageInstallationStatus (QObject* parent); ~RKRPackageInstallationStatus (); void initialize (RCommandChain *chain); enum Columns { EnhancesRKWard, InstallationStatus, PackageName, PackageTitle, Version, Location, COLUMN_COUNT }; enum ToplevelItems { UpdateablePackages, NewPackages, InstalledPackages, TOPLEVELITEM_COUNT }; enum PackageStatusChange { Install, Remove, NoAction }; /* Item model implementation */ int rowCount (const QModelIndex &parent = QModelIndex()) const override; int columnCount (const QModelIndex &) const override { return COLUMN_COUNT; }; QVariant data (const QModelIndex &index, int role=Qt::DisplayRole) const override; QVariant headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override; Qt::ItemFlags flags (const QModelIndex &index) const override; QModelIndex index (int row, int column, const QModelIndex &parent=QModelIndex()) const override; QModelIndex parent (const QModelIndex &index) const override; bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; /** returns a list of packages selected for installation / update */ QStringList packagesToInstall () const; /** fills a list of packages selected for removal, and a parallel list of the locations, from which to remove. * @return true, if any packages are marked for removal, false otherwise. */ bool packagesToRemove (QStringList *packages, QStringList *liblocs); /** mark a package for installation. * @returns the index of the package, if the package is available, an invalid index, if it is not available */ QModelIndex markPackageForInstallation (const QString& package_name); /** mark all available updates for installation. * @returns the index of the "Updateable Packages" item */ QModelIndex markAllUpdatesForInstallation (); /** reset all installation states to NoAction */ void clearStatus (); QStringList currentRepositories () const { return current_repos; }; bool initialized () const { return _initialized; }; private slots: void statusCommandFinished (RCommand *command); private: QStringList available_packages, available_titles, available_versions, available_repos; QStringList installed_packages, installed_titles, installed_versions, installed_libpaths; RData::IntStorage enhance_rk_in_available; RData::IntStorage enhance_rk_in_installed; RData::IntStorage new_packages_in_available; RData::IntStorage updateable_packages_in_available; RData::IntStorage updateable_packages_in_installed; QVector installed_status; QVector available_status; QVector installed_has_update; bool _initialized; QStringList current_repos; }; class RKRPackageInstallationStatusSortFilterModel : public QSortFilterProxyModel { public: explicit RKRPackageInstallationStatusSortFilterModel (QObject* parent = 0); ~RKRPackageInstallationStatusSortFilterModel (); void setRKWardOnly (bool only); protected: bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override; bool rkward_only; }; /** Allows the user to update / install R packages. To be used in RKLoadLibsDialog. @author Thomas Friedrichsmeier */ class InstallPackagesWidget : public QWidget { Q_OBJECT public: explicit InstallPackagesWidget (RKLoadLibsDialog *dialog); ~InstallPackagesWidget (); void trySelectPackages (const QStringList &package_names); void initialize (); public slots: void ok (); void apply (); void cancel (); void filterChanged (); void activated (); void markAllUpdates (); void configureRepositories (); void rowClicked (const QModelIndex& row); private: void doInstall (bool refresh); QTreeView *packages_view; RKRPackageInstallationStatus *packages_status; RKRPackageInstallationStatusSortFilterModel *model; QPushButton *mark_all_updates_button; RKDynamicSearchLine *filter_edit; QCheckBox *rkward_packages_only; PackageInstallParamsWidget *install_params; RKLoadLibsDialog *parent; }; /** Simple helper class for RKLoadLibsDialog to allow selection of installation parameters @author Thomas Friedrichsmeier */ class PackageInstallParamsWidget : public QWidget { Q_OBJECT public: explicit PackageInstallParamsWidget (QWidget *parent); ~PackageInstallParamsWidget (); bool installSuggestedPackages (); QString installLocation (); public slots: void liblocsChanged (const QStringList &newlist); private: QComboBox *libloc_selector; QCheckBox *suggested_packages; }; #include "../settings/rksettingsmoduleplugins.h" class RKPluginMapSelectionWidget : public QWidget { Q_OBJECT public: explicit RKPluginMapSelectionWidget (RKLoadLibsDialog *dialog); virtual ~RKPluginMapSelectionWidget (); public slots: void ok (); void apply (); void cancel (); void activated (); void changed () { changes_pending = true; }; private: RKMultiStringSelectorV2* selector; RKSettingsModulePluginsModel* model; bool changes_pending; }; #endif rkward-0.7.2/rkward/dialogs/rkimportdialog.cpp0000664000175000017510000000572513736365060021056 0ustar thomasthomas/*************************************************************************** rkimportdialog - description ------------------- begin : Tue Jan 30 2007 copyright : (C) 2007-2018 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "rkimportdialog.h" #include #include #include #include #include "../plugin/rkcomponentmap.h" #include "../plugin/rkcomponentcontext.h" #include "../debug.h" RKImportDialog::RKImportDialog (const QString &context_id, QWidget *parent) : QFileDialog (parent) { RK_TRACE (DIALOGS); setModal (false); context = RKComponentMap::getContext (context_id); if (!context) { KMessageBox::sorry (this, i18n ("No plugins defined for context '%1'", context_id)); return; } component_ids = context->components (); for (QStringList::const_iterator it = component_ids.constBegin (); it != component_ids.constEnd (); ++it) { RKComponentHandle *handle = RKComponentMap::getComponentHandle (*it); if (!handle) { RK_ASSERT (false); continue; } QString filter = handle->getAttributeValue ("format"); QString label = handle->getAttributeLabel ("format"); QString elabel = label; elabel.replace ('(', "["); elabel.replace (')', "]"); filters.append (elabel + " [" + filter + "] (" + filter + ')'); } // initialize setFileMode (QFileDialog::ExistingFile); setNameFilters (filters); show (); } RKImportDialog::~RKImportDialog () { RK_TRACE (DIALOGS); } void RKImportDialog::accept () { RK_TRACE (DIALOGS); int index = filters.indexOf (selectedNameFilter ()); QString cid = component_ids.value (index); RKComponentHandle *handle = RKComponentMap::getComponentHandle (cid); RKContextHandler *chandler = context->makeContextHandler (this, false); if (!(handle && chandler)) { RK_ASSERT (false); } else { RKComponentPropertyBase *filename = new RKComponentPropertyBase (chandler, false); filename->setValue (selectedFiles ().value (0)); chandler->addChild ("filename", filename); chandler->invokeComponent (handle); } QFileDialog::accept (); deleteLater (); } void RKImportDialog::reject () { RK_TRACE (DIALOGS); QFileDialog::reject (); deleteLater (); } rkward-0.7.2/rkward/dialogs/rkerrordialog.h0000644000175000017510000000274413572465432020340 0ustar thomasthomas/*************************************************************************** rkerrordialog - description ------------------- begin : Thu Apr 25 2013 copyright : (C) 2013 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKERRORDIALOG_H #define RKERRORDIALOG_H #include class QWidget; namespace RKErrorDialog { /** Displays an error message with a button "Report bug" */ void reportableErrorMessage (QWidget *parent_widget, const QString &user_message, const QString &details, const QString &caption, const QString &message_code); /** Open "Report bug" dialog */ void reportBug (QWidget *parent_widget = 0, const QString &message_info=QString ()); }; #endif rkward-0.7.2/rkward/dialogs/startupdialog.h0000664000175000017510000000644013736365060020351 0ustar thomasthomas/*************************************************************************** startupdialog - description ------------------- begin : Thu Aug 26 2004 copyright : (C) 2004, 2011 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef STARTUPDIALOG_H #define STARTUPDIALOG_H #include #include class QCheckBox; class QButtonGroup; class QRadioButton; class QListWidget; class QListWidgetItem; class KRecentFilesAction; /** This class represents the startup dialog asking you whether to open a recent file, start with an empty workspace, etc. It's probably only ever used in one place, namely RKWard startup. The normal way to invoke it is via the static member-function getStartupAction. The selected action is returned in a StartupDialogResult. Remember to delete that struct after you read it. @author Thomas Friedrichsmeier */ /// the startup dialog class StartupDialog : public QDialog { Q_OBJECT public: /** enum to hold result of StartupDialog. WARNING: do not change the numeric values! They are saved as user settings in the config (@see RKSettingsModuleGeneral). */ enum Result { EmptyWorkspace=0, /**< start with an empty workspace */ EmptyTable=1, /**< start with an empty table */ ChoseFile=2, /**< chose file to open */ NoSavedSetting=3, /**< not actually returned as a result. Used in RKSettingsModuleGeneral. This is saved, if user wants to be asked on every startup */ OpenFile=4, /**< open a recent file (already specified) */ RestoreFromWD=5 /**< load workspace from current directory, if available (R option --restore). */ }; struct StartupDialogResult { Result result; QUrl open_url; }; StartupDialog (QWidget *parent, StartupDialogResult *result, KRecentFilesAction *recent_files); ~StartupDialog(); static StartupDialogResult getStartupAction (QWidget *parent, KRecentFilesAction *recent_files); static QUrl getRestoreFile (); public slots: void accept () override; void reject () override; void listDoubleClicked (QListWidgetItem* item); void listClicked (QListWidgetItem* item); void openButtonSelected (bool checked); protected: /** reimplemented from QWidget to achieve fixed width */ void showEvent (QShowEvent *event) override; private: QRadioButton *empty_workspace_button; QRadioButton *empty_table_button; QRadioButton *restore_workspace_button; QRadioButton *open_button; QCheckBox *remember_box; QButtonGroup *choser; QListWidget *file_list; QListWidgetItem *chose_file_item; StartupDialogResult *result; }; #endif rkward-0.7.2/rkward/dialogs/rkselectlistdialog.h0000664000175000017510000000437613736365060021365 0ustar thomasthomas/*************************************************************************** rkselectlistdialog - description ------------------- begin : Thu Mar 18 2010 copyright : (C) 2010 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKSELECTLISTDIALOG_H #define RKSELECTLISTDIALOG_H #include class QListWidget; class QDialogButtonBox; /** This class represent a dialog asking for a choice among several options. It is used, when the backend calls select.list() / menu(). @author Thomas Friedrichsmeier */ class RKSelectListDialog : public QDialog { Q_OBJECT public: /** Construct and run modal RKSelectListDialog. @param parent QWidget to center the modal dialog on (0 for application) @param caption Dialog title @param choices The list of available choices @param preselected The preselected choices (QStringList ()) for no preselects @param multiple Whether multiple items may be selected @returns The selected option(s). An empty list, if cancel was pressed. */ static QStringList doSelect (QWidget *parent, const QString &caption, const QStringList& choices, const QStringList& preselected, bool multiple); protected: /** ctor. Use the doSelect() instead. */ RKSelectListDialog (QWidget *parent, const QString &caption, const QStringList& choices, const QStringList& preselected, bool multiple); /** destructor */ ~RKSelectListDialog (); private slots: void updateState (); private: QListWidget *input; QDialogButtonBox *buttons; }; #endif rkward-0.7.2/rkward/dialogs/rkerrordialog.cpp0000664000175000017510000002264113736365060020671 0ustar thomasthomas/*************************************************************************** rkerrordialog - description ------------------- begin : Thu Apr 25 2013 copyright : (C) 2013-2020 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "rkerrordialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../rbackend/rkrinterface.h" #include "../rbackend/rksessionvars.h" #include "../misc/rkprogresscontrol.h" #include "../misc/rkdialogbuttonbox.h" #include "../misc/rkcommonfunctions.h" #include "../rkglobals.h" #include "../rkward.h" #include "../version.h" #include "../debug.h" #define SUBMIT_ADDRESS "https://bugs.kde.org/enter_bug.cgi" class RKBugzillaReportDialog : public QDialog { public: RKBugzillaReportDialog (QWidget* parent, const QString& report_template) : QDialog (parent) { RK_TRACE (DIALOGS); RKBugzillaReportDialog::report_template = report_template; setWindowTitle (i18n ("Reporting bugs in RKWard")); QVBoxLayout *layout = new QVBoxLayout (this); QLabel *label = RKCommonFunctions::wordWrappedLabel (i18n ("

Where should I report bugs or wishes?

Thank you for taking the time to help improve RKWard. To help us " "handle your request, efficiently, please submit your bug reports or wishes in the " "KDE bugtracking system. Note that you need a user account for this, so that we will be able to contact you, " "for follow-up questions. If you do not have an account, please create one, first.

" "

In case this is not possible for some reason, refer to %3 for alternative ways of reporting issues.

", QString ("https://bugs.kde.org"), QString ("https://bugs.kde.org/createaccount.cgi"), QString ("https://rkward.kde.org/Bugs.html")) + i18n ("

What information should I provide, and how?

Clicking \"Report issue\" will take you to the " "KDE bugtracking system. After logging in, some information will already be pre-filled into the report form. Please make sure " "to fill in the missing bits - in English - where indicated, especially in the \"Comment\" field.

")); label->setOpenExternalLinks (true); layout->addWidget (label); RKDialogButtonBox *buttons = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); buttons->button (QDialogButtonBox::Ok)->setText (i18n ("Report issue")); buttons->button (QDialogButtonBox::Ok)->setIcon (QIcon::fromTheme("tools-report-bug")); layout->addWidget (buttons); connect (this, &QDialog::finished, this, &RKBugzillaReportDialog::deleteLater); } void accept () override { // The report template is just too large to pass it via GET, so we use a local proxy page to pass it in a POST request QTemporaryFile proxy; proxy.setFileTemplate (QDir::tempPath () + "/rkwardbugXXXXXX.html"); // Force .html-suffix, as it appears to be required on Windows proxy.setAutoRemove (false); proxy.open (); QTextStream out (&proxy); out << "Relaying to " SUBMIT_ADDRESS "\n"; out << "

" + i18n ("Forwarding you to the KDE bugtracking system") + "

\n"; out << "

" + i18n ("You are now being forwarded to the KDE bugtracking system. Should you continue to see this page for more than a few seconds (e.g. if JavaScript is disabled), please click \"Proceed\", below.") + "

\n"; out << "
\n"; out << "\n"; out << "\n"; out << "\n"; out << "\n"; out << "\n"; out << "
"; proxy.close (); QDesktopServices::openUrl (QUrl::fromLocalFile (proxy.fileName ())); QDialog::accept (); } private: QString report_template; }; void RKErrorDialog::reportableErrorMessage (QWidget* parent_widget, const QString& user_message, const QString &details, const QString& caption, const QString& message_code) { RK_TRACE (APP); if (!parent_widget) parent_widget = RKWardMainWindow::getMain (); // adjusted from KMessageBox::detailedError QDialog *dialog = new QDialog (parent_widget, Qt::Dialog); dialog->setWindowTitle (caption); QDialogButtonBox *buttonbox = new QDialogButtonBox (dialog); if (details.isEmpty ()) buttonbox->setStandardButtons (QDialogButtonBox::Ok | QDialogButtonBox::No); else { buttonbox->setStandardButtons (QDialogButtonBox::Ok | QDialogButtonBox::No | QDialogButtonBox::Help); buttonbox->button (QDialogButtonBox::Help)->setText (i18n ("Show Details")); } buttonbox->button (QDialogButtonBox::No)->setText (i18n ("Report As Bug")); dialog->setObjectName ("error"); buttonbox->button (QDialogButtonBox::Ok)->setDefault (true); buttonbox->button (QDialogButtonBox::Ok)->setShortcut (Qt::Key_Escape); KMessageBox::Options options = KMessageBox::Notify | KMessageBox::AllowLink; dialog->setModal (true); int ret = KMessageBox::createKMessageBox (dialog, buttonbox, QMessageBox::Critical, user_message, QStringList(), QString(), 0, options, details); if (ret == QDialogButtonBox::No) { reportBug (parent_widget, (message_code.isEmpty () ? QString () : i18n ("Message code: %1\n", message_code)) + user_message); } } void RKErrorDialog::reportBug (QWidget* parent_widget, const QString& message_info) { RK_TRACE (APP); if (!parent_widget) parent_widget = RKWardMainWindow::getMain (); QString report_template = i18n ("---Problem description---\nPlease fill in the missing bits *in English*.\n\n"); if (message_info.isEmpty ()) { report_template.append (i18n ("Please give a brief summary on the problem:\n###Please fill in###\n\n")); } else { report_template.append (i18n ("I encountered the error message quoted below. Additionally, I saw the following symptoms:\n###Please fill in (if applicable)###\n\n")); } report_template.append (i18n ("What - in detail - did you do directly before you encountered this problem?\n###Please fill in###\n\n")); report_template.append (i18n ("When you try to repeat the above, does the problem occur again (no, sometimes, always)?\n###Please fill in###\n\n")); report_template.append (i18n ("If applicable: When doing the same thing in an R session outside of RKWard, do you see the same problem?\n###Please fill in###\n\n")); report_template.append (i18n ("Do you have any further information that might help us to track this problem down? In particular, if applicable, can you provide sample data and sample R code to reproduce this problem?\n###Please fill in###\n\n")); report_template.append (i18n ("RKWard is available in many different packagings, and sometimes problems are specific to one method of installation. How did you install RKWard (which file(s) did you download)?\n###Please fill in###\n\n")); if (!message_info.isEmpty ()) { report_template.append ("\n---Error Message---\n"); report_template.append (message_info); report_template.append ("\n"); } report_template.append ("\n---Session Info---\n"); bool ok = false; if (!RKGlobals::rInterface ()->backendIsDead ()) { RCommand *command = new RCommand ("rk.sessionInfo()", RCommand::App); RKProgressControl *control = new RKProgressControl (parent_widget, i18n ("Please stand by while gathering some information on your setup.\nIn case the backend has died or hung up, you may want to press 'Cancel' to skip this step."), i18n ("Gathering setup information"), RKProgressControl::CancellableNoProgress); control->addRCommand (command, true); RKGlobals::rInterface ()->issueCommand (command); ok = control->doModal (false); // NOTE: command is already deleted at this point report_template.append (control->fullCommandOutput ()); delete control; } if (!ok) { report_template.append (RKSessionVars::frontendSessionInfo ().join ("\n")); report_template.append ("\n- backend not available or rk.sessionInfo() canceled -\n"); } RKBugzillaReportDialog *dialog = new RKBugzillaReportDialog (parent_widget, report_template); dialog->show (); } rkward-0.7.2/rkward/dialogs/rksetupwizard.h0000664000175000017510000000714513736365060020410 0ustar thomasthomas/*************************************************************************** rksetupwizard - description ------------------- begin : Fri May 25 20200 copyright : (C) 2020 by Thomas Friedrichsmeier email : thomas.friedrichsmeier@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef RKSETUPWIZARD_H #define RKSETUPWIZARD_H #include #include class QGridLayout; class QLabel; class RKSetupWizardItem; class RKSetupWizard : public KAssistantDialog { protected: enum InvokationReason { ProblemsDetected, NewVersionRKWard, NewVersionR, ManualCheck }; RKSetupWizard(QWidget* parent, InvokationReason reason, const QList &settings_items); ~RKSetupWizard(); static bool has_been_run; public: static void doAutoCheck(); static void fullInteractiveCheck(InvokationReason reason, const QList &settings_items = QList()); static void manualCheck(); void markSoftwareForInstallation(const QString &name, const QString &download_url, bool install); void markRPackageForInstallation(const QString &name, bool install); private: QStringList software_to_install; QStringList software_to_install_urls; QStringList packages_to_install; void createStandardPage(); QWidget *current_page; int current_row; QGridLayout* current_layout; void appendItem(RKSetupWizardItem* item); QList items; bool reinstallation_required; void next() override; KPageWidgetItem *second_to_last_page_ref; QLabel* last_page_label; }; class QComboBox; class RKSetupWizardItem { public: enum Status { Error, Warning, Good }; RKSetupWizardItem(const QString &shortlabel, const QString &longlabel=QString(), Status status=Good, const QString &shortstatuslabel=QString()) : status(status), shortlabel(shortlabel), longlabel(longlabel), shortstatuslabel(shortstatuslabel), box(nullptr) {}; ~RKSetupWizardItem() {}; void addOption(const QString &shortlabel, const QString &longlabel, std::function callback) { options.append(Option(shortlabel, longlabel, callback)); } void setStatus(Status _status, const QString &_shortstatuslabel) { status = _status; shortstatuslabel = _shortstatuslabel; }; void setShortLabel(const QString &label) { shortlabel = label; }; void setLongLabel(const QString &label) { longlabel = label; }; private: friend class RKSetupWizard; void createWidget(QGridLayout *layout, int row); void apply(RKSetupWizard *wizard); struct Option { Option(const QString &shortlabel, const QString &longlabel, std::function callback) : shortlabel(shortlabel), longlabel(longlabel), callback(callback) {}; QString shortlabel; QString longlabel; std::function callback; }; QList