7 changed files with 286 additions and 5 deletions
@ -0,0 +1,30 @@ |
|||
cmake_minimum_required(VERSION 3.7) |
|||
enable_language(CXX) |
|||
|
|||
set(CMAKE_INCLUDE_CURRENT_DIR ON) |
|||
set(CMAKE_CXX_STANDARD 11) |
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON) |
|||
|
|||
find_package(PkgConfig REQUIRED) |
|||
pkg_check_modules(gtkmm REQUIRED gtkmm-3.0) |
|||
|
|||
project(ragephoto-gtkviewer LANGUAGES CXX) |
|||
|
|||
set(GTKVIEWER_HEADERS |
|||
src/PhotoViewer.h |
|||
) |
|||
|
|||
set(GTKVIEWER_SOURCES |
|||
src/main.cpp |
|||
src/PhotoViewer.cpp |
|||
) |
|||
|
|||
if(TARGET ragephoto) |
|||
set(RAGEPHOTO_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src) |
|||
add_executable(ragephoto-gtkviewer ${GTKVIEWER_HEADERS} ${GTKVIEWER_SOURCES}) |
|||
target_link_libraries(ragephoto-gtkviewer ${gtkmm_LIBRARIES} ragephoto) |
|||
target_link_directories(ragephoto-gtkviewer PRIVATE ${gtkmm_LIBRARY_DIRS}) |
|||
target_include_directories(ragephoto-gtkviewer PRIVATE ${gtkmm_INCLUDE_DIRS} ${RAGEPHOTO_INCLUDE_DIRS}) |
|||
else() |
|||
message("ragephoto-gtkviewer need to be build with libragephoto together") |
|||
endif() |
@ -0,0 +1,102 @@ |
|||
/*****************************************************************************
|
|||
* libragephoto RAGE Photo Parser |
|||
* Copyright (C) 2021 Syping |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without modification, |
|||
* are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* |
|||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* This software is provided as-is, no warranties are given to you, we are not |
|||
* responsible for anything with use of the software, you are self responsible. |
|||
*****************************************************************************/ |
|||
|
|||
#include "PhotoViewer.h" |
|||
#include <cairomm/context.h> |
|||
#include <gdkmm/general.h> |
|||
#include <RagePhoto.h> |
|||
#include <iostream> |
|||
|
|||
PhotoViewer::PhotoViewer(Gtk::Label *title_label, Gtk::Label *json_label) : p_title_label(title_label), p_json_label(json_label) |
|||
{ |
|||
} |
|||
|
|||
void PhotoViewer::open_file(const char *filename) |
|||
{ |
|||
RagePhoto ragePhoto; |
|||
// Read file
|
|||
FILE *file = fopen(filename, "rb"); |
|||
if (!file) { |
|||
return; |
|||
} |
|||
const int fseek_end_value = fseek(file, 0, SEEK_END); |
|||
if (fseek_end_value == -1) { |
|||
fclose(file); |
|||
return; |
|||
} |
|||
const size_t file_size = ftell(file); |
|||
if (file_size == -1) { |
|||
fclose(file); |
|||
return; |
|||
} |
|||
const int fseek_set_value = fseek(file, 0, SEEK_SET); |
|||
if (fseek_set_value == -1) { |
|||
fclose(file); |
|||
return; |
|||
} |
|||
char *data = static_cast<char*>(malloc(file_size)); |
|||
const size_t file_rsize = fread(data, 1, file_size, file); |
|||
if (file_size != file_rsize) { |
|||
fclose(file); |
|||
return; |
|||
} |
|||
fclose(file); |
|||
const bool loaded = ragePhoto.load(data, file_size); |
|||
free(data); |
|||
if (!loaded) { |
|||
const RagePhoto::Error error = ragePhoto.error(); |
|||
if (error <= RagePhoto::Error::PhotoReadError) |
|||
return; |
|||
} |
|||
|
|||
guchar *photoData = static_cast<guchar*>(malloc(ragePhoto.photoSize())); |
|||
if (!photoData) |
|||
return; |
|||
|
|||
memcpy(photoData, ragePhoto.photoData(), ragePhoto.photoSize()); |
|||
|
|||
GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); |
|||
gdk_pixbuf_loader_write(loader, photoData, static_cast<gsize>(ragePhoto.photoSize()), nullptr); |
|||
GdkPixbuf *c_pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); |
|||
p_image = Glib::wrap(c_pixbuf); |
|||
|
|||
p_title_label->set_text("Title: " + ragePhoto.title()); |
|||
// p_title_label->show();
|
|||
|
|||
get_parent_window()->set_title("RagePhoto GTK Photo Viewer - " + ragePhoto.title()); |
|||
|
|||
free(photoData); |
|||
|
|||
if (p_image) |
|||
set_size_request(p_image->get_width(), p_image->get_height()); |
|||
} |
|||
|
|||
bool PhotoViewer::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) |
|||
{ |
|||
if (!p_image) |
|||
return false; |
|||
|
|||
Gtk::Allocation allocation = get_allocation(); |
|||
const int width = allocation.get_width(); |
|||
const int height = allocation.get_height(); |
|||
|
|||
Gdk::Cairo::set_source_pixbuf(cr, p_image, (width - p_image->get_width()) / 2, (height - p_image->get_height()) / 2); |
|||
cr->paint(); |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,39 @@ |
|||
/*****************************************************************************
|
|||
* libragephoto RAGE Photo Parser |
|||
* Copyright (C) 2021 Syping |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without modification, |
|||
* are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* |
|||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* This software is provided as-is, no warranties are given to you, we are not |
|||
* responsible for anything with use of the software, you are self responsible. |
|||
*****************************************************************************/ |
|||
|
|||
#ifndef PHOTOVIEWER_H |
|||
#define PHOTOVIEWER_H |
|||
|
|||
#include <gtkmm/drawingarea.h> |
|||
#include <gtkmm/label.h> |
|||
#include <gdkmm/pixbuf.h> |
|||
|
|||
class PhotoViewer : public Gtk::DrawingArea |
|||
{ |
|||
public: |
|||
PhotoViewer(Gtk::Label *title_label, Gtk::Label *json_label); |
|||
void open_file(const char *filename); |
|||
|
|||
protected: |
|||
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override; |
|||
Glib::RefPtr<Gdk::Pixbuf> p_image; |
|||
Gtk::Label *p_title_label; |
|||
Gtk::Label *p_json_label; |
|||
}; |
|||
|
|||
#endif // PHOTOVIEWER_H
|
@ -0,0 +1,105 @@ |
|||
/*****************************************************************************
|
|||
* libragephoto RAGE Photo Parser |
|||
* Copyright (C) 2021 Syping |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without modification, |
|||
* are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* |
|||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* This software is provided as-is, no warranties are given to you, we are not |
|||
* responsible for anything with use of the software, you are self responsible. |
|||
*****************************************************************************/ |
|||
|
|||
#include "PhotoViewer.h" |
|||
#include <gtkmm/application.h> |
|||
#include <gtkmm/box.h> |
|||
#include <gtkmm/button.h> |
|||
#include <gtkmm/filechooserdialog.h> |
|||
#include <gtkmm/filefilter.h> |
|||
#include <gtkmm/label.h> |
|||
#include <gtkmm/window.h> |
|||
#include <iostream> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
auto app = Gtk::Application::create(argc, argv, "de.syping.ragephoto.gtkviewer", Gio::APPLICATION_HANDLES_OPEN); |
|||
|
|||
Gtk::Window win; |
|||
win.set_title("RagePhoto GTK Photo Viewer"); |
|||
win.set_default_size(400, 0); |
|||
win.set_resizable(false); |
|||
|
|||
Gtk::Box vertical_box(Gtk::ORIENTATION_VERTICAL); |
|||
|
|||
Gtk::Label title_label; |
|||
Gtk::Label json_label; |
|||
PhotoViewer photo_viewer(&title_label, &json_label); |
|||
vertical_box.add(photo_viewer); |
|||
vertical_box.add(title_label); |
|||
vertical_box.add(json_label); |
|||
photo_viewer.show(); |
|||
|
|||
Gtk::Box horizontal_box(Gtk::ORIENTATION_HORIZONTAL); |
|||
vertical_box.add(horizontal_box); |
|||
|
|||
Gtk::Button open_button; |
|||
open_button.set_label("Open"); |
|||
open_button.set_hexpand(true); |
|||
open_button.set_can_default(false); |
|||
open_button.signal_clicked().connect([&](){ |
|||
Gtk::FileChooserDialog dialog("Open Photo", Gtk::FILE_CHOOSER_ACTION_OPEN); |
|||
dialog.set_transient_for(win); |
|||
|
|||
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL); |
|||
dialog.add_button("_Open", Gtk::RESPONSE_OK); |
|||
|
|||
Glib::RefPtr<Gtk::FileFilter> filter_photo = Gtk::FileFilter::create(); |
|||
filter_photo->set_name("GTA V Photo"); |
|||
filter_photo->add_pattern("PGTA5*"); |
|||
|
|||
int result = dialog.run(); |
|||
|
|||
switch(result) { |
|||
case Gtk::RESPONSE_OK: { |
|||
std::string filename = dialog.get_filename(); |
|||
photo_viewer.open_file(filename.c_str()); |
|||
break; |
|||
} |
|||
default: |
|||
break; |
|||
} |
|||
}); |
|||
horizontal_box.add(open_button); |
|||
open_button.show(); |
|||
|
|||
Gtk::Button close_button; |
|||
close_button.set_label("Close"); |
|||
close_button.set_hexpand(true); |
|||
close_button.set_can_default(false); |
|||
close_button.signal_clicked().connect([&](){ |
|||
win.close(); |
|||
}); |
|||
horizontal_box.add(close_button); |
|||
close_button.show(); |
|||
|
|||
app->signal_open().connect([&](const Gio::Application::type_vec_files &files, const Glib::ustring &hint){ |
|||
for (const auto &file : files) { |
|||
photo_viewer.open_file(file->get_path().c_str()); |
|||
} |
|||
app->add_window(win); |
|||
win.show(); |
|||
}); |
|||
|
|||
horizontal_box.show(); |
|||
vertical_box.show(); |
|||
|
|||
win.add(vertical_box); |
|||
|
|||
return app->run(win); |
|||
} |
Loading…
Reference in new issue