Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F103832
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/Info.plist.in b/Info.plist.in
index eb01716..dc5e269 100644
--- a/Info.plist.in
+++ b/Info.plist.in
@@ -1,20 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSHighResolutionCapable</key>
+ <string>True</string>
<key>CFBundleIconFile</key>
<string>Guitar.icns</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleGetInfoString</key>
<string>@CMAKE_PROJECT_VERSION@</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
<string>Guitar</string>
<key>CFBundleIdentifier</key>
<string>jp.soramimi.Guitar</string>
</dict>
</plist>
diff --git a/prepare.rb b/prepare.rb
index 15f2b8c..0295aca 100755
--- a/prepare.rb
+++ b/prepare.rb
@@ -1,89 +1,91 @@
#!/usr/bin/ruby
# create the following files
# * version.c
# * win.rc
# * Info.plist
load 'version.rb'
def get_revision()
rev = ""
if Dir.exist?(".git")
hash = `git rev-parse HEAD`
if hash =~ /^[0-9A-Za-z]+/
rev = hash[0, 7]
end
end
return rev
end
File.open("src/version.h", "w") {|f|
f.puts <<_____
int copyright_year = #{$copyright_year};
char const product_version[] = "#{$version_a}.#{$version_b}.#{$version_c}";
char const source_revision[] = "#{get_revision()}";
_____
}
File.open("win.rc", "w") {|f|
f.puts <<_____
#include <windows.h>
100 ICON DISCARDABLE "src/resources/#{$product_name}.ico"
VS_VERSION_INFO VERSIONINFO
FILEVERSION #{$version_a},#{$version_b},#{$version_c},#{$version_d}
PRODUCTVERSION #{$version_a},#{$version_b},#{$version_c},#{$version_d}
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041103a4"
BEGIN
VALUE "CompanyName", "S.Fuchita"
VALUE "FileDescription", "The Git GUI Client"
VALUE "FileVersion", "#{$version_a}, #{$version_b}, #{$version_c}, #{$version_d}"
VALUE "InternalName", "#{$product_name}.exe"
VALUE "LegalCopyright", "Copyright (C) #{$copyright_year} S.Fuchita (@soramimi_jp)"
VALUE "OriginalFilename","#{$product_name}.exe"
VALUE "ProductName", "#{$product_name}"
VALUE "ProductVersion", "#{$version_a}, #{$version_b}, #{$version_c}, #{$version_d}"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0411, 932
END
END
_____
}
File.open("Info.plist", "w") {|f|
f.puts <<_____
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSHighResolutionCapable</key>
+ <string>True</string>
<key>CFBundleIconFile</key>
<string>#{$product_name}.icns</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleGetInfoString</key>
<string>#{$version_a}.#{$version_b}.#{$version_c}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
<string>#{$product_name}</string>
<key>CFBundleIdentifier</key>
<string>jp.soramimi.#{$product_name}</string>
</dict>
</plist>
_____
}
diff --git a/src/AvatarLoader.cpp b/src/AvatarLoader.cpp
index 9c7a0ed..5e6a6ac 100644
--- a/src/AvatarLoader.cpp
+++ b/src/AvatarLoader.cpp
@@ -1,161 +1,161 @@
#include "AvatarLoader.h"
#include "BasicMainWindow.h"
#include "MemoryReader.h"
#include "webclient.h"
#include <QCryptographicHash>
#include <QDebug>
#include <QWaitCondition>
namespace {
const int MAX_CACHE_COUNT = 1000;
-const int ICON_SIZE = 64;
+const int ICON_SIZE = 128;
}
using WebClientPtr = std::shared_ptr<WebClient>;
struct AvatarLoader::Private {
QMutex mutex;
QWaitCondition condition;
std::deque<RequestItem> requested;
std::deque<RequestItem> completed;
BasicMainWindow *mainwindow = nullptr;
WebClientPtr web;
};
AvatarLoader::AvatarLoader()
: m(new Private)
{
}
AvatarLoader::~AvatarLoader()
{
delete m;
}
void AvatarLoader::start(BasicMainWindow *mainwindow)
{
m->mainwindow = mainwindow;
QThread::start();
}
void AvatarLoader::run()
{
m->web = std::make_shared<WebClient>(m->mainwindow->webContext());
while (1) {
if (isInterruptionRequested()) return;
std::deque<RequestItem> requests;
{
QMutexLocker lock(&m->mutex);
if (m->requested.empty()) {
m->condition.wait(&m->mutex);
}
if (!m->requested.empty()) {
std::swap(requests, m->requested);
}
}
for (RequestItem &item : requests) {
if (isInterruptionRequested()) return;
if (strchr(item.email.c_str(), '@')) {
QString id;
{
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(item.email.c_str(), item.email.size());
QByteArray ba = hash.result();
char tmp[100];
for (int i = 0; i < ba.size(); i++) {
sprintf(tmp + i * 2, "%02x", ba.data()[i] & 0xff);
}
id = tmp;
}
QString url = "https://www.gravatar.com/avatar/%1?s=%2";
url = url.arg(id).arg(ICON_SIZE);
if (m->web->get(WebClient::Request(url.toStdString())) == 200) {
if (!m->web->response().content.empty()) {
MemoryReader reader(m->web->response().content.data(), m->web->response().content.size());
reader.open(MemoryReader::ReadOnly);
QImage image;
image.load(&reader, nullptr);
int w = image.width();
int h = image.height();
if (w > 0 && h > 0) {
item.image = image;
{
QMutexLocker lock(&m->mutex);
size_t i = m->requested.size();
while (i > 0) {
i--;
if (m->requested[i].email == item.email) {
m->requested.erase(m->requested.begin() + i);
}
}
while (m->completed.size() >= MAX_CACHE_COUNT) {
m->completed.pop_back();
}
m->completed.push_front(item);
}
emit updated();
continue;
}
}
} else {
m->mainwindow->emitWriteLog(QString("Failed to fetch the avatar.\n").toUtf8());
QString msg = QString::fromStdString(m->web->error().message() + '\n');
m->mainwindow->emitWriteLog(msg.toUtf8());
}
}
}
}
}
QIcon AvatarLoader::fetch(std::string const &email, bool request) const
{
QMutexLocker lock(&m->mutex);
RequestItem item;
item.email = email;
for (size_t i = 0; i < m->completed.size(); i++) {
if (item.email == m->completed[i].email) {
item = m->completed[i];
m->completed.erase(m->completed.begin() + i);
m->completed.insert(m->completed.begin(), item);
return QIcon(QPixmap::fromImage(item.image));
}
}
if (request) {
bool waiting = false;
for (RequestItem const &r : m->requested) {
if (item.email == r.email) {
waiting = true;
break;
}
}
if (!waiting) {
m->requested.push_back(item);
m->condition.wakeOne();
}
}
return QIcon();
}
void AvatarLoader::stop()
{
{
QMutexLocker lock(&m->mutex);
requestInterruption();
m->requested.clear();
m->condition.wakeAll();
}
if (!wait(3000)) {
terminate();
}
if (m->web) {
m->web->close();
m->web.reset();
}
m->completed.clear();
}
diff --git a/src/main.cpp b/src/main.cpp
index 43b3464..71c2e03 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,182 +1,184 @@
#include "main.h"
#include "ApplicationGlobal.h"
#include "MainWindow.h"
#include "MySettings.h"
#include "SettingGeneralForm.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include "darktheme/DarkStyle.h"
#include "platform.h"
#include "webclient.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QProxyStyle>
#include <QStandardPaths>
#include <QTranslator>
#include <signal.h>
#include <string>
#ifdef Q_OS_WIN
#include "win32/win32.h"
#include "SettingGeneralForm.h"
#endif
#ifndef APP_GUITAR
#error APP_GUITAR is not defined.
#endif
ApplicationGlobal *global = nullptr;
ApplicationSettings ApplicationSettings::defaultSettings()
{
ApplicationSettings s;
s.proxy_server = "http://squid:3128/";
return s;
}
static bool isHighDpiScalingEnabled()
{
MySettings s;
s.beginGroup("UI");
QVariant v = s.value("EnableHighDpiScaling");
return v.isNull() || v.toBool();
}
void setEnvironmentVariable(QString const &name, QString const &value);
void onSigTerm(int)
{
qDebug() << "SIGTERM caught";
if (global->mainwindow) {
global->mainwindow->close();
}
}
int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
setEnvironmentVariable("UNICODEMAP_JP", "cp932");
#else
setenv("UNICODEMAP_JP", "cp932", 1);
#endif
ApplicationGlobal g;
global = &g;
signal(SIGTERM, onSigTerm);
global->organization_name = ORGANIZATION_NAME;
global->application_name = APPLICATION_NAME;
global->generic_config_dir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
global->app_config_dir = global->generic_config_dir / global->organization_name / global->application_name;
global->config_file_path = joinpath(global->app_config_dir, global->application_name + ".ini");
if (!QFileInfo(global->app_config_dir).isDir()) {
QDir().mkpath(global->app_config_dir);
}
if (isHighDpiScalingEnabled()){
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
qDebug() << "High DPI scaling is not supported";
#else
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
}
QApplication a(argc, argv);
+ a.setAttribute(Qt::AA_UseHighDpiPixmaps);
+
QApplication::setOrganizationName(global->organization_name);
QApplication::setApplicationName(global->application_name);
qRegisterMetaType<RepositoryItem>("RepositoryItem");
{
MySettings s;
s.beginGroup("UI");
global->language_id = s.value("Language").toString();
global->theme_id = s.value("Theme").toString();
if (global->theme_id.compare("dark", Qt::CaseInsensitive) == 0) {
global->theme = createDarkTheme();
} else {
global->theme = createStandardTheme();
}
s.endGroup();
}
QApplication::setStyle(global->theme->newStyle());
if (QApplication::queryKeyboardModifiers() & Qt::ShiftModifier) {
global->start_with_shift_key = true;
}
WebClient::initialize();
bool f_open_here = false;
QStringList args;
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg[0] == '-') {
if (arg == "--open-here") {
f_open_here = true;
}
} else {
args.push_back(QString::fromStdString(arg));
}
}
if (global->app_config_dir.isEmpty()) {
QMessageBox::warning(nullptr, qApp->applicationName(), "Preparation of data storage folder failed.");
return 1;
}
// 設定ファイルがないときは、言語の選択をする。
if (!QFileInfo::exists(global->config_file_path)) {
auto langs = SettingGeneralForm::languages();
SettingGeneralForm::execSelectLanguageDialog(nullptr, langs, [](){});
}
QTranslator translator;
{
if (global->language_id.isEmpty() || global->language_id == "en") {
// thru
} else {
QString path = ":/translations/Guitar_" + global->language_id;
bool f = translator.load(path, QApplication::applicationDirPath());
if (!f) {
qDebug() << QString("Failed to load the translation file: %1").arg(path);
}
QApplication::installTranslator(&translator);
}
}
MainWindow w;
global->mainwindow = &w;
global->panel_bg_color = w.palette().color(QPalette::Background);
w.setWindowIcon(QIcon(":/image/guitar.png"));
w.show();
w.shown();
if (f_open_here) {
QString dir = QDir::current().absolutePath();
w.autoOpenRepository(dir);
} else if (args.size() == 1) {
QString dir = args[0] / QString();
if (dir.startsWith("./") || dir.startsWith(".\\")) {
dir = QDir::current().absolutePath() / dir.mid(2);
}
QFileInfo fi(dir);
if (fi.isDir()) {
dir = fi.absolutePath();
w.autoOpenRepository(dir);
}
}
int r = QApplication::exec();
global->mainwindow = nullptr;
return r;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Feb 7, 12:08 PM (12 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55981
Default Alt Text
(12 KB)
Attached To
Mode
R77 Guitar
Attached
Detach File
Event Timeline
Log In to Comment