Add URL drag and drop and desktop-aware theming
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(prozgui VERSION 2.2.2 LANGUAGES C CXX)
|
||||
project(prozgui VERSION 2.3.0 LANGUAGES C CXX)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@@ -11,6 +11,10 @@ file downloading speeds.
|
||||
Features:
|
||||
Supports FTP
|
||||
Supports HTTP including redirection.
|
||||
Supports dragging URLs, newline-separated URL lists, and local URL-list files
|
||||
onto the main window.
|
||||
Selects a suitable FLTK appearance for GNOME/MATE and KDE automatically;
|
||||
set FLTK_SCHEME to override the automatic choice.
|
||||
Proxy servers supported.
|
||||
Resume Supported.
|
||||
Improved error checking and correction.
|
||||
@@ -93,4 +97,3 @@ We sincerely hope that you will like the download accelerator..
|
||||
Enjoy!
|
||||
|
||||
Kalum Somaratana (Grendel) <kalum@genesys.ro>
|
||||
|
||||
|
||||
@@ -532,3 +532,9 @@ msgstr "Version de l'interface %s"
|
||||
|
||||
msgid "libprozilla version %s"
|
||||
msgstr "Version de libprozilla %s"
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr "Déposez ici des URL ou des fichiers de listes d’URL"
|
||||
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr "%d téléchargement(s) démarré(s) ; %d élément(s) invalide(s), en double ou illisible(s) ignoré(s)."
|
||||
|
||||
@@ -515,3 +515,9 @@ msgstr "Versione GUI %s"
|
||||
|
||||
msgid "libprozilla version %s"
|
||||
msgstr "Versione libprozilla %s"
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr "Trascina qui URL o file con elenchi di URL"
|
||||
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr "Avviati %d download; ignorati %d elementi non validi, duplicati o illeggibili."
|
||||
|
||||
@@ -431,3 +431,9 @@ msgstr "GUI-versie %s"
|
||||
|
||||
msgid "libprozilla version %s"
|
||||
msgstr "libprozilla-versie %s"
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr "Sleep URL's of bestanden met URL-lijsten hierheen"
|
||||
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr "%d download(s) gestart; %d ongeldig(e), dubbel(e) of onleesbaar(e) item(s) overgeslagen."
|
||||
|
||||
@@ -555,6 +555,15 @@ msgstr ""
|
||||
msgid "Prozilla - Download Accelerator"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/options.cpp:130
|
||||
#, c-format
|
||||
msgid "%s does not seem to be a valid directory"
|
||||
|
||||
@@ -534,3 +534,9 @@ msgstr "Versão da interface %s"
|
||||
|
||||
msgid "libprozilla version %s"
|
||||
msgstr "Versão da libprozilla %s"
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr "Solte URLs ou arquivos de listas de URLs aqui"
|
||||
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr "%d download(s) iniciado(s); %d item(ns) inválido(s), duplicado(s) ou ilegível(is) ignorado(s)."
|
||||
|
||||
@@ -454,3 +454,9 @@ msgstr "Versiune interfață %s"
|
||||
|
||||
msgid "libprozilla version %s"
|
||||
msgstr "Versiune libprozilla %s"
|
||||
msgid "Drop URLs or URL list files here"
|
||||
msgstr "Plasați aici URL-uri sau fișiere cu liste de URL-uri"
|
||||
|
||||
#, c-format
|
||||
msgid "Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."
|
||||
msgstr "S-au pornit %d descărcări; s-au omis %d elemente nevalide, duplicate sau ilizibile."
|
||||
|
||||
+201
-3
@@ -23,6 +23,12 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
@@ -70,6 +76,36 @@ void open_new_dl_win(urlinfo * url_data, boolean ftpsearch);
|
||||
void menu_download_start();
|
||||
void menu_download_stop();
|
||||
void menu_download_remove();
|
||||
void import_dropped_text(const char *text);
|
||||
|
||||
void apply_desktop_scheme()
|
||||
{
|
||||
const char *requested_scheme = getenv("FLTK_SCHEME");
|
||||
if (requested_scheme && *requested_scheme)
|
||||
{
|
||||
Fl::scheme(requested_scheme);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *desktop = getenv("XDG_CURRENT_DESKTOP");
|
||||
if (!desktop)
|
||||
desktop = getenv("XDG_SESSION_DESKTOP");
|
||||
if (!desktop)
|
||||
return;
|
||||
|
||||
std::string name(desktop);
|
||||
for (std::string::size_type i = 0; i < name.size(); ++i)
|
||||
name[i] = static_cast<char>(std::tolower(static_cast<unsigned char>(name[i])));
|
||||
|
||||
if (name.find("gnome") != std::string::npos ||
|
||||
name.find("mate") != std::string::npos ||
|
||||
name.find("cinnamon") != std::string::npos ||
|
||||
name.find("xfce") != std::string::npos)
|
||||
Fl::scheme("gtk+");
|
||||
else if (name.find("kde") != std::string::npos ||
|
||||
name.find("plasma") != std::string::npos)
|
||||
Fl::scheme("gleam");
|
||||
}
|
||||
|
||||
class Main_Window:public Fl_Window {
|
||||
public:
|
||||
@@ -85,11 +121,17 @@ Main_Window::Main_Window(int w, int h, const char *l):Fl_Window(w, h, l)
|
||||
|
||||
int Main_Window::handle(int e)
|
||||
{
|
||||
|
||||
if (e == FL_PASTE)
|
||||
switch (e)
|
||||
{
|
||||
// printf("%s\n", Fl::event_text());
|
||||
case FL_DND_ENTER:
|
||||
case FL_DND_DRAG:
|
||||
case FL_DND_RELEASE:
|
||||
return 1;
|
||||
case FL_PASTE:
|
||||
import_dropped_text(Fl::event_text());
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Fl_Window::handle(e))
|
||||
@@ -209,6 +251,154 @@ void open_new_dl_win(urlinfo * url_data, boolean ftpsearch)
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::string trim(const std::string &value)
|
||||
{
|
||||
const std::string::size_type first = value.find_first_not_of(" \t\r\n");
|
||||
if (first == std::string::npos)
|
||||
return std::string();
|
||||
const std::string::size_type last = value.find_last_not_of(" \t\r\n");
|
||||
return value.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
int hex_value(char value)
|
||||
{
|
||||
if (value >= '0' && value <= '9')
|
||||
return value - '0';
|
||||
value = static_cast<char>(std::tolower(static_cast<unsigned char>(value)));
|
||||
return value >= 'a' && value <= 'f' ? value - 'a' + 10 : -1;
|
||||
}
|
||||
|
||||
bool file_uri_to_path(const std::string &uri, std::string *path)
|
||||
{
|
||||
if (uri.compare(0, 7, "file://") != 0)
|
||||
return false;
|
||||
|
||||
std::string encoded = uri.substr(7);
|
||||
if (encoded.compare(0, 10, "localhost/") == 0)
|
||||
encoded.erase(0, 9);
|
||||
else if (encoded.empty() || encoded[0] != '/')
|
||||
return false;
|
||||
|
||||
path->clear();
|
||||
for (std::string::size_type i = 0; i < encoded.size(); ++i)
|
||||
{
|
||||
if (encoded[i] == '%' && i + 2 < encoded.size())
|
||||
{
|
||||
const int high = hex_value(encoded[i + 1]);
|
||||
const int low = hex_value(encoded[i + 2]);
|
||||
if (high < 0 || low < 0)
|
||||
return false;
|
||||
path->push_back(static_cast<char>((high << 4) | low));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
path->push_back(encoded[i]);
|
||||
}
|
||||
return path->find('\0') == std::string::npos;
|
||||
}
|
||||
|
||||
bool read_url_list(const std::string &path, std::string *contents)
|
||||
{
|
||||
std::error_code error;
|
||||
const std::filesystem::path file(path);
|
||||
if (!std::filesystem::is_regular_file(file, error) || error)
|
||||
return false;
|
||||
const std::uintmax_t size = std::filesystem::file_size(file, error);
|
||||
if (error || size > 1024 * 1024)
|
||||
return false;
|
||||
|
||||
std::ifstream stream(file, std::ios::binary);
|
||||
if (!stream)
|
||||
return false;
|
||||
std::ostringstream buffer;
|
||||
buffer << stream.rdbuf();
|
||||
*contents = buffer.str();
|
||||
return static_cast<bool>(stream) || stream.eof();
|
||||
}
|
||||
|
||||
bool start_dropped_url(const std::string &url)
|
||||
{
|
||||
urlinfo *url_data = static_cast<urlinfo *>(calloc(1, sizeof(urlinfo)));
|
||||
if (!url_data)
|
||||
return false;
|
||||
|
||||
if (proz_parse_url(url.c_str(), url_data, 0) != URLOK ||
|
||||
strlen(url_data->file) == 0)
|
||||
{
|
||||
proz_free_url(url_data, 0);
|
||||
free(url_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < browser->size(); ++i)
|
||||
{
|
||||
if (strcmp(url_data->url, browser->text(i + 1)) == 0)
|
||||
{
|
||||
proz_free_url(url_data, 0);
|
||||
free(url_data);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
open_new_dl_win(url_data, rt.use_ftpsearch);
|
||||
return true;
|
||||
}
|
||||
|
||||
void import_url_lines(const std::string &text, int *started, int *skipped)
|
||||
{
|
||||
std::istringstream lines(text);
|
||||
std::string line;
|
||||
while (std::getline(lines, line))
|
||||
{
|
||||
line = trim(line);
|
||||
if (line.empty() || line[0] == '#')
|
||||
continue;
|
||||
if (start_dropped_url(line))
|
||||
++*started;
|
||||
else
|
||||
++*skipped;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void import_dropped_text(const char *text)
|
||||
{
|
||||
if (!text || !*text)
|
||||
return;
|
||||
|
||||
int started = 0;
|
||||
int skipped = 0;
|
||||
std::istringstream dropped(text);
|
||||
std::string item;
|
||||
while (std::getline(dropped, item))
|
||||
{
|
||||
item = trim(item);
|
||||
if (item.empty() || item[0] == '#')
|
||||
continue;
|
||||
|
||||
std::string path;
|
||||
std::string contents;
|
||||
if (file_uri_to_path(item, &path))
|
||||
{
|
||||
if (read_url_list(path, &contents))
|
||||
import_url_lines(contents, &started, &skipped);
|
||||
else
|
||||
++skipped;
|
||||
}
|
||||
else if (start_dropped_url(item))
|
||||
++started;
|
||||
else
|
||||
++skipped;
|
||||
}
|
||||
|
||||
if (skipped > 0)
|
||||
fl_message(_("Started %d download(s); skipped %d invalid, duplicate, or unreadable item(s)."),
|
||||
started, skipped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void show_prefs()
|
||||
@@ -431,6 +621,8 @@ int main(int argc, char **argv)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
apply_desktop_scheme();
|
||||
|
||||
set_defaults(&argc, &argv);
|
||||
load_prefs();
|
||||
set_runtime_values();
|
||||
@@ -473,6 +665,12 @@ int main(int argc, char **argv)
|
||||
menubar->menu(menuitems);
|
||||
}
|
||||
|
||||
Fl_Box *drop_hint = new Fl_Box(20, 55, 460, 165,
|
||||
_("Drop URLs or URL list files here"));
|
||||
drop_hint->box(FL_DOWN_BOX);
|
||||
drop_hint->labelsize(16);
|
||||
drop_hint->labelcolor(FL_DARK3);
|
||||
|
||||
/*The browser window */
|
||||
browser = new Fl_Hold_Browser(2, 250, 495, 80);
|
||||
browser->callback(browser_cb);
|
||||
|
||||
Reference in New Issue
Block a user