mirror of https://github.com/procxx/kepka.git
Merge branch 'master' of https://github.com/telegramdesktop/tdesktop
This commit is contained in:
commit
7ce76a763e
12
.travis.yml
12
.travis.yml
|
@ -3,14 +3,24 @@ sudo: required
|
||||||
language: cpp
|
language: cpp
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
global:
|
||||||
|
# GitHub auth token (GH_AUTH_TOKEN)
|
||||||
|
- secure: "QBbD9VXAx3Mn0vFmHZtm6/sq+twMyR7ilQh7TQm8gBy2TrjhHKDKQ4wRQ5sa2MUFUbzrUOvPlPGq1WuY1mAUt8UE6jZDJNyyDWb6iIlcEmNRsd39XAhYHvJ+uI9JsD+U3OctZ+7Bo4fno0RLv1D5lzh5bpohmjgWxx9TiSZItbsRU+m0XM0Tahx335aXF8NFoVjheGXCOcLAXDt6OmaKPmlrXreuta5nOoRKeOg5vHlt/KNU1pYb8MFvWJc14DKxq3jNqrYlo9vHFv5tVhR1aqvVFWTD/4Z88OSxx3POzyVWdMso0lFov9uxs8qHoqLsGhDMElggyz/jnqZIHpwQMaYIGQ0LLYDv21jGgOuCOWKYlfjDY+tuESXmVPzerTlYBWLZDPrpE8BnXVYo8B/sF4WN6oCuBRjawlqYhqTH+tDDORc9Uc9pamhcuh6OsLMx3PHoyg8joN3t8yUnwhySXyfQ36hqlZ+Y4bBDRZBH/SB/EPmedyLGwdhzQFsUnOBotYeOym7LUdnGraGcj1iTPLdo5TMlBYlAiB12J5mHTNuzUKXh+PBV4REg4Mm2xYX+Pue5Qo1JcOWJteIX4BdPv526DXB3yaNWS1pZgGvYqtBwQlCeOfwOYupS0PksvmV7aX7c4qJSyW3dmEd03cxmebD0b2SbqyPxGFuUajJ7B60="
|
||||||
|
matrix:
|
||||||
- BUILD_VERSION=""
|
- BUILD_VERSION=""
|
||||||
- BUILD_VERSION="disable_autoupdate"
|
- BUILD_VERSION="disable_autoupdate"
|
||||||
- BUILD_VERSION="disable_register_custom_scheme"
|
- BUILD_VERSION="disable_register_custom_scheme"
|
||||||
- BUILD_VERSION="disable_crash_reports"
|
- BUILD_VERSION="disable_crash_reports"
|
||||||
- BUILD_VERSION="disable_network_proxy"
|
- BUILD_VERSION="disable_network_proxy"
|
||||||
- BUILD_VERSION="disable_desktop_file_generation"
|
- BUILD_VERSION="disable_desktop_file_generation"
|
||||||
|
- BUILD_VERSION="disable_unity_integration"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
arch:
|
arch:
|
||||||
|
repos:
|
||||||
|
- home_ItachiSan_archlinux_Arch_Extra=http://download.opensuse.org/repositories/home:/ItachiSan:/archlinux/Arch_Extra/$arch
|
||||||
packages:
|
packages:
|
||||||
- bzr
|
- bzr
|
||||||
- wget
|
- wget
|
||||||
|
@ -18,7 +28,7 @@ arch:
|
||||||
|
|
||||||
- git
|
- git
|
||||||
- patch
|
- patch
|
||||||
- dee-fixed
|
- home_ItachiSan_archlinux_Arch_Extra/dee # Use fixed dee version (See #2005)
|
||||||
- libunity
|
- libunity
|
||||||
- libappindicator-gtk2
|
- libappindicator-gtk2
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,10 @@ prepare() {
|
||||||
options+="\nDEFINES += TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION"
|
options+="\nDEFINES += TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ $BUILD_VERSION == *"disable_unity_integration"* ]]; then
|
||||||
|
options+="\nDEFINES += TDESKTOP_DISABLE_UNITY_INTEGRATION"
|
||||||
|
fi
|
||||||
|
|
||||||
options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"'
|
options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"'
|
||||||
options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"'
|
options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"'
|
||||||
options+='\nINCLUDEPATH += "/usr/include/opus"'
|
options+='\nINCLUDEPATH += "/usr/include/opus"'
|
||||||
|
@ -104,7 +108,7 @@ build() {
|
||||||
cd "$srcdir/Libraries/qt${_qtver}"
|
cd "$srcdir/Libraries/qt${_qtver}"
|
||||||
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
|
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
|
||||||
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
|
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
|
||||||
-qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests
|
-qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests
|
||||||
make --silent -j4
|
make --silent -j4
|
||||||
make --silent -j4 install
|
make --silent -j4 install
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ checkCommitMessage() {
|
||||||
if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then
|
if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then
|
||||||
error_msg "The commit message does not contain the signature!"
|
error_msg "The commit message does not contain the signature!"
|
||||||
error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work"
|
error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work"
|
||||||
|
addMissingSignatureInfos
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
success_msg "Commit message contains signature"
|
success_msg "Commit message contains signature"
|
||||||
|
@ -20,6 +21,37 @@ checkCommitMessage() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addMissingSignatureInfos() {
|
||||||
|
if [[ $BUILD_VERSION == "" ]]; then
|
||||||
|
local TEXT="Hi,\n\
|
||||||
|
thanks for the pull request!\n\
|
||||||
|
\n\
|
||||||
|
Please read our [contributing policy](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md). You'll need to make a pull request with the \\\"Signed-off-by:\\\" signature being the last line of your commit message, like it is described in [sign your work](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work) section. That will grant your work into the public domain.\n\
|
||||||
|
\n\
|
||||||
|
(See [travis build](https://travis-ci.org/telegramdesktop/tdesktop/jobs/${TRAVIS_JOB_ID}))"
|
||||||
|
addCommentToGitHub "${TEXT}"
|
||||||
|
addLabelToGitHub "missing signature"
|
||||||
|
info_msg "Added missing signature info on github"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
addCommentToGitHub() {
|
||||||
|
local BODY=$1
|
||||||
|
sendGitHubRequest "POST" "{\"body\": \"${BODY}\"}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}/comments"
|
||||||
|
}
|
||||||
|
|
||||||
|
addLabelToGitHub() {
|
||||||
|
local LABEL=$1
|
||||||
|
sendGitHubRequest "PATCH" "{\"labels\": [\"${LABEL}\"]}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sendGitHubRequest() {
|
||||||
|
local METHOD=$1
|
||||||
|
local BODY=$2
|
||||||
|
local URI=$3
|
||||||
|
curl -H "Authorization: token ${GH_AUTH_TOKEN}" --request "${METHOD}" --data "${BODY}" --silent "https://api.github.com/${URI}" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
source ./.travis/common.sh
|
source ./.travis/common.sh
|
||||||
|
|
||||||
run
|
run
|
||||||
|
|
|
@ -27,8 +27,6 @@ class MainWindow;
|
||||||
class MainWidget;
|
class MainWidget;
|
||||||
class SettingsWidget;
|
class SettingsWidget;
|
||||||
class ApiWrap;
|
class ApiWrap;
|
||||||
class Font;
|
|
||||||
class Color;
|
|
||||||
class FileUploader;
|
class FileUploader;
|
||||||
|
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
|
|
@ -215,3 +215,23 @@ style::sprite documentCorner(int32 colorIndex) {
|
||||||
RoundCorners documentCorners(int32 colorIndex) {
|
RoundCorners documentCorners(int32 colorIndex) {
|
||||||
return RoundCorners(DocBlueCorners + (colorIndex & 3));
|
return RoundCorners(DocBlueCorners + (colorIndex & 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool documentIsValidMediaFile(const QString &filepath) {
|
||||||
|
static StaticNeverFreedPointer<QList<QString>> validMediaTypes(([] {
|
||||||
|
std_::unique_ptr<QList<QString>> result = std_::make_unique<QList<QString>>();
|
||||||
|
*result = qsl("\
|
||||||
|
webm mkv flv vob ogv ogg drc gif gifv mng avi mov qt wmv yuv rm rmvb asf amv mp4 m4p \
|
||||||
|
m4v mpg mp2 mpeg mpe mpv m2v svi 3gp 3g2 mxf roq nsv f4v f4p f4a f4b wma divx evo mk3d \
|
||||||
|
mka mks mcf m2p ps ts m2ts ifo aaf avchd cam dat dsh dvr-ms m1v fla flr sol wrap smi swf \
|
||||||
|
wtv 8svx 16svx iff aiff aif aifc au bwf cdda raw wav flac la pac m4a ape ofr ofs off rka \
|
||||||
|
shn tak tta wv brstm dts dtshd dtsma ast amr mp3 spx gsm aac mpc vqf ra ots swa vox voc \
|
||||||
|
dwd smp aup cust mid mus sib sid ly gym vgm psf nsf mod ptb s3m xm it mt2 minipsf psflib \
|
||||||
|
2sf dsf gsf psf2 qsf ssf usf rmj spc niff mxl xml txm ym jam mp1 mscz \
|
||||||
|
").split(' ');
|
||||||
|
return result.release();
|
||||||
|
})());
|
||||||
|
|
||||||
|
QFileInfo info(filepath);
|
||||||
|
auto parts = info.fileName().split('.', QString::SkipEmptyParts);
|
||||||
|
return !parts.isEmpty() && (validMediaTypes->indexOf(parts.back().toLower()) >= 0);
|
||||||
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ style::color documentOverColor(int32 colorIndex);
|
||||||
style::color documentSelectedColor(int32 colorIndex);
|
style::color documentSelectedColor(int32 colorIndex);
|
||||||
style::sprite documentCorner(int32 colorIndex);
|
style::sprite documentCorner(int32 colorIndex);
|
||||||
RoundCorners documentCorners(int32 colorIndex);
|
RoundCorners documentCorners(int32 colorIndex);
|
||||||
|
bool documentIsValidMediaFile(const QString &filepath);
|
||||||
|
|
||||||
class PaintContextBase {
|
class PaintContextBase {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -44,21 +44,9 @@ int main(int argc, char *argv[]) {
|
||||||
Logs::start(); // must be started before Platform is started
|
Logs::start(); // must be started before Platform is started
|
||||||
Platform::start(); // must be started before QApplication is created
|
Platform::start(); // must be started before QApplication is created
|
||||||
|
|
||||||
// prepare fake args to disable QT_STYLE_OVERRIDE env variable
|
|
||||||
// currently this is required in some desktop environments, including Xubuntu 15.10
|
|
||||||
// when we don't default style to "none" Qt dynamically loads GTK somehow internally and
|
|
||||||
// our own GTK dynamic load and usage leads GTK errors and freeze of the current main thread
|
|
||||||
// we can't disable our own GTK loading because it is required by libappindicator, which
|
|
||||||
// provides the tray icon for this system, because Qt tray icon is broken there
|
|
||||||
// see https://github.com/telegramdesktop/tdesktop/issues/1774
|
|
||||||
QByteArray args[] = { "-style=0" };
|
|
||||||
static const int a_cnt = sizeof(args) / sizeof(args[0]);
|
|
||||||
int a_argc = a_cnt + 1;
|
|
||||||
char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
|
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
{
|
{
|
||||||
Application app(a_argc, a_argv);
|
Application app(argc, argv);
|
||||||
result = app.exec();
|
result = app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1541,7 +1541,11 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
||||||
DocumentData *audio = audioId.audio;
|
DocumentData *audio = audioId.audio;
|
||||||
QString filepath = audio->filepath(DocumentData::FilePathResolveSaveFromData);
|
QString filepath = audio->filepath(DocumentData::FilePathResolveSaveFromData);
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
|
if (documentIsValidMediaFile(filepath)) {
|
||||||
psOpenFile(filepath);
|
psOpenFile(filepath);
|
||||||
|
} else {
|
||||||
|
psShowInFolder(filepath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1568,7 +1572,11 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
||||||
DocumentData *document = songId.song;
|
DocumentData *document = songId.song;
|
||||||
QString filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
|
QString filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
|
if (documentIsValidMediaFile(filepath)) {
|
||||||
psOpenFile(filepath);
|
psOpenFile(filepath);
|
||||||
|
} else {
|
||||||
|
psShowInFolder(filepath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -505,9 +505,7 @@ void MainWindow::clearWidgets() {
|
||||||
intro = 0;
|
intro = 0;
|
||||||
}
|
}
|
||||||
if (_mediaView) {
|
if (_mediaView) {
|
||||||
if (!_mediaView->isHidden()) {
|
hideMediaview();
|
||||||
_mediaView->hide();
|
|
||||||
}
|
|
||||||
_mediaView->rpcClear();
|
_mediaView->rpcClear();
|
||||||
}
|
}
|
||||||
title->updateBackButton();
|
title->updateBackButton();
|
||||||
|
|
|
@ -0,0 +1,497 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "platform/linux/file_dialog_linux.h"
|
||||||
|
|
||||||
|
#include <private/qguiapplication_p.h>
|
||||||
|
#include "platform/linux/linux_libs.h"
|
||||||
|
#include "platform/linux/linux_gdk_helper.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "localstorage.h"
|
||||||
|
|
||||||
|
QStringList qt_make_filter_list(const QString &filter);
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace FileDialog {
|
||||||
|
|
||||||
|
using Type = ::FileDialog::internal::Type;
|
||||||
|
|
||||||
|
bool Supported() {
|
||||||
|
return Platform::internal::GdkHelperLoaded()
|
||||||
|
&& (Libs::gtk_widget_hide_on_delete != nullptr)
|
||||||
|
&& (Libs::gtk_clipboard_store != nullptr)
|
||||||
|
&& (Libs::gtk_clipboard_get != nullptr)
|
||||||
|
&& (Libs::gtk_widget_destroy != nullptr)
|
||||||
|
&& (Libs::gtk_dialog_get_type != nullptr)
|
||||||
|
&& (Libs::gtk_dialog_run != nullptr)
|
||||||
|
&& (Libs::gtk_widget_realize != nullptr)
|
||||||
|
&& (Libs::gdk_window_set_modal_hint != nullptr)
|
||||||
|
&& (Libs::gtk_widget_show != nullptr)
|
||||||
|
&& (Libs::gdk_window_focus != nullptr)
|
||||||
|
&& (Libs::gtk_widget_hide != nullptr)
|
||||||
|
&& (Libs::gtk_widget_hide_on_delete != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_dialog_new != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_get_type != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_current_folder != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_get_current_folder != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_current_name != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_select_filename != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_get_filenames != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_filter != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_get_filter != nullptr)
|
||||||
|
&& (Libs::gtk_window_get_type != nullptr)
|
||||||
|
&& (Libs::gtk_window_set_title != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_local_only != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_action != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_select_multiple != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_set_do_overwrite_confirmation != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_remove_filter != nullptr)
|
||||||
|
&& (Libs::gtk_file_filter_set_name != nullptr)
|
||||||
|
&& (Libs::gtk_file_filter_add_pattern != nullptr)
|
||||||
|
&& (Libs::gtk_file_chooser_add_filter != nullptr)
|
||||||
|
&& (Libs::gtk_file_filter_new != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) {
|
||||||
|
auto parent = App::wnd() ? App::wnd()->filedialogParent() : nullptr;
|
||||||
|
internal::GtkFileDialog dialog(parent, caption, QString(), filter);
|
||||||
|
|
||||||
|
dialog.setModal(true);
|
||||||
|
if (type == Type::ReadFile || type == Type::ReadFiles) {
|
||||||
|
dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
|
} else if (type == Type::ReadFolder) {
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
|
dialog.setFileMode(QFileDialog::Directory);
|
||||||
|
dialog.setOption(QFileDialog::ShowDirsOnly);
|
||||||
|
} else {
|
||||||
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
}
|
||||||
|
if (startFile.isEmpty() || startFile.at(0) != '/') {
|
||||||
|
startFile = cDialogLastPath() + '/' + startFile;
|
||||||
|
}
|
||||||
|
dialog.selectFile(startFile);
|
||||||
|
|
||||||
|
int res = dialog.exec();
|
||||||
|
|
||||||
|
QString path = dialog.directory().absolutePath();
|
||||||
|
if (path != cDialogLastPath()) {
|
||||||
|
cSetDialogLastPath(path);
|
||||||
|
Local::writeUserSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == QDialog::Accepted) {
|
||||||
|
if (type == Type::ReadFiles) {
|
||||||
|
files = dialog.selectedFiles();
|
||||||
|
} else {
|
||||||
|
files = dialog.selectedFiles().mid(0, 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
files = QStringList();
|
||||||
|
remoteContent = QByteArray();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) {
|
||||||
|
Libs::g_signal_connect_swapped_helper(Libs::g_object_cast(gtkWidget), "response", GCallback(onResponse), this);
|
||||||
|
Libs::g_signal_connect_helper(Libs::g_object_cast(gtkWidget), "delete-event", GCallback(Libs::gtk_widget_hide_on_delete), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
QGtkDialog::~QGtkDialog() {
|
||||||
|
Libs::gtk_clipboard_store(Libs::gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
|
||||||
|
Libs::gtk_widget_destroy(gtkWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkDialog *QGtkDialog::gtkDialog() const {
|
||||||
|
return Libs::gtk_dialog_cast(gtkWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGtkDialog::exec() {
|
||||||
|
if (auto w = App::wnd()) {
|
||||||
|
w->onReActivate();
|
||||||
|
QTimer::singleShot(200, w, SLOT(onReActivate()));
|
||||||
|
}
|
||||||
|
if (modality() == Qt::ApplicationModal) {
|
||||||
|
// block input to the whole app, including other GTK dialogs
|
||||||
|
Libs::gtk_dialog_run(gtkDialog());
|
||||||
|
} else {
|
||||||
|
// block input to the window, allow input to other GTK dialogs
|
||||||
|
QEventLoop loop;
|
||||||
|
connect(this, SIGNAL(accept()), &loop, SLOT(quit()));
|
||||||
|
connect(this, SIGNAL(reject()), &loop, SLOT(quit()));
|
||||||
|
loop.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGtkDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) {
|
||||||
|
connect(parent, &QWindow::destroyed, this, &QGtkDialog::onParentWindowDestroyed,
|
||||||
|
Qt::UniqueConnection);
|
||||||
|
setParent(parent);
|
||||||
|
setFlags(flags);
|
||||||
|
setModality(modality);
|
||||||
|
|
||||||
|
Libs::gtk_widget_realize(gtkWidget); // creates X window
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
Platform::internal::XSetTransientForHint(Libs::gtk_widget_get_window(gtkWidget), parent->winId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modality != Qt::NonModal) {
|
||||||
|
Libs::gdk_window_set_modal_hint(Libs::gtk_widget_get_window(gtkWidget), true);
|
||||||
|
QGuiApplicationPrivate::showModalWindow(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Libs::gtk_widget_show(gtkWidget);
|
||||||
|
Libs::gdk_window_focus(Libs::gtk_widget_get_window(gtkWidget), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGtkDialog::hide() {
|
||||||
|
QGuiApplicationPrivate::hideModalWindow(this);
|
||||||
|
Libs::gtk_widget_hide(gtkWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGtkDialog::onResponse(QGtkDialog *dialog, int response) {
|
||||||
|
if (response == GTK_RESPONSE_OK)
|
||||||
|
emit dialog->accept();
|
||||||
|
else
|
||||||
|
emit dialog->reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGtkDialog::onParentWindowDestroyed() {
|
||||||
|
// The Gtk*DialogHelper classes own this object. Make sure the parent doesn't delete it.
|
||||||
|
setParent(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char *filterRegExp =
|
||||||
|
"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
|
||||||
|
|
||||||
|
// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
|
||||||
|
QStringList cleanFilterList(const QString &filter) {
|
||||||
|
QRegExp regexp(QString::fromLatin1(filterRegExp));
|
||||||
|
Q_ASSERT(regexp.isValid());
|
||||||
|
QString f = filter;
|
||||||
|
int i = regexp.indexIn(f);
|
||||||
|
if (i >= 0)
|
||||||
|
f = regexp.cap(2);
|
||||||
|
return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) : QDialog(parent)
|
||||||
|
, _windowTitle(caption)
|
||||||
|
, _initialDirectory(directory) {
|
||||||
|
auto filters = qt_make_filter_list(filter);
|
||||||
|
const int numFilters = filters.count();
|
||||||
|
_nameFilters.reserve(numFilters);
|
||||||
|
for (int i = 0; i < numFilters; ++i) {
|
||||||
|
_nameFilters << filters[i].simplified();
|
||||||
|
}
|
||||||
|
|
||||||
|
d.reset(new QGtkDialog(Libs::gtk_file_chooser_dialog_new("", nullptr,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||||
|
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL)));
|
||||||
|
connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
|
||||||
|
connect(d.data(), SIGNAL(reject()), this, SLOT(onRejected()));
|
||||||
|
|
||||||
|
Libs::g_signal_connect_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
|
||||||
|
Libs::g_signal_connect_swapped_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkFileDialog::~GtkFileDialog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) {
|
||||||
|
_dir.clear();
|
||||||
|
_selection.clear();
|
||||||
|
|
||||||
|
applyOptions();
|
||||||
|
return d->show(flags, modality, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::setVisible(bool visible) {
|
||||||
|
if (visible) {
|
||||||
|
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr);
|
||||||
|
} else {
|
||||||
|
hideHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
|
||||||
|
// updates the state correctly, but skips showing the non-native version:
|
||||||
|
setAttribute(Qt::WA_DontShowOnScreen);
|
||||||
|
|
||||||
|
QDialog::setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GtkFileDialog::exec() {
|
||||||
|
d->setModality(windowModality());
|
||||||
|
|
||||||
|
bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose, false);
|
||||||
|
|
||||||
|
bool wasShowModal = testAttribute(Qt::WA_ShowModal);
|
||||||
|
setAttribute(Qt::WA_ShowModal, true);
|
||||||
|
setResult(0);
|
||||||
|
|
||||||
|
show();
|
||||||
|
|
||||||
|
QPointer<QDialog> guard = this;
|
||||||
|
d->exec();
|
||||||
|
if (guard.isNull())
|
||||||
|
return QDialog::Rejected;
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_ShowModal, wasShowModal);
|
||||||
|
|
||||||
|
return result();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::hideHelper() {
|
||||||
|
// After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder()
|
||||||
|
// & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual
|
||||||
|
// values before hiding the dialog
|
||||||
|
_dir = directory().absolutePath();
|
||||||
|
_selection = selectedFiles();
|
||||||
|
|
||||||
|
d->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GtkFileDialog::defaultNameFilterDisables() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::setDirectory(const QString &directory) {
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), directory.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir GtkFileDialog::directory() const {
|
||||||
|
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder()
|
||||||
|
// returns a bogus value -> return the cached value before hiding
|
||||||
|
if (!_dir.isEmpty())
|
||||||
|
return _dir;
|
||||||
|
|
||||||
|
QString ret;
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
gchar *folder = Libs::gtk_file_chooser_get_current_folder(Libs::gtk_file_chooser_cast(gtkDialog));
|
||||||
|
if (folder) {
|
||||||
|
ret = QString::fromUtf8(folder);
|
||||||
|
Libs::g_free(folder);
|
||||||
|
}
|
||||||
|
return QDir(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::selectFile(const QString &filename) {
|
||||||
|
_initialFiles.clear();
|
||||||
|
_initialFiles.append(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList GtkFileDialog::selectedFiles() const {
|
||||||
|
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames()
|
||||||
|
// returns a bogus value -> return the cached value before hiding
|
||||||
|
if (!_selection.isEmpty())
|
||||||
|
return _selection;
|
||||||
|
|
||||||
|
QStringList selection;
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
GSList *filenames = Libs::gtk_file_chooser_get_filenames(Libs::gtk_file_chooser_cast(gtkDialog));
|
||||||
|
for (GSList *it = filenames; it; it = it->next)
|
||||||
|
selection += QString::fromUtf8((const char*)it->data);
|
||||||
|
Libs::g_slist_free(filenames);
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::setFilter() {
|
||||||
|
applyOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::selectNameFilter(const QString &filter) {
|
||||||
|
GtkFileFilter *gtkFilter = _filters.value(filter);
|
||||||
|
if (gtkFilter) {
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
Libs::gtk_file_chooser_set_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GtkFileDialog::selectedNameFilter() const {
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
GtkFileFilter *gtkFilter = Libs::gtk_file_chooser_get_filter(Libs::gtk_file_chooser_cast(gtkDialog));
|
||||||
|
return _filterNames.value(gtkFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::onAccepted() {
|
||||||
|
emit accept();
|
||||||
|
|
||||||
|
// QString filter = selectedNameFilter();
|
||||||
|
// if (filter.isEmpty())
|
||||||
|
// emit filterSelected(filter);
|
||||||
|
|
||||||
|
// QList<QUrl> files = selectedFiles();
|
||||||
|
// emit filesSelected(files);
|
||||||
|
// if (files.count() == 1)
|
||||||
|
// emit fileSelected(files.first());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::onRejected() {
|
||||||
|
emit reject();
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::onSelectionChanged(GtkDialog *gtkDialog, GtkFileDialog *helper) {
|
||||||
|
// QString selection;
|
||||||
|
// gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog));
|
||||||
|
// if (filename) {
|
||||||
|
// selection = QString::fromUtf8(filename);
|
||||||
|
// g_free(filename);
|
||||||
|
// }
|
||||||
|
// emit helper->currentChanged(QUrl::fromLocalFile(selection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) {
|
||||||
|
// emit dialog->directoryEntered(dialog->directory());
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) {
|
||||||
|
switch (fileMode) {
|
||||||
|
case QFileDialog::AnyFile:
|
||||||
|
case QFileDialog::ExistingFile:
|
||||||
|
case QFileDialog::ExistingFiles:
|
||||||
|
if (acceptMode == QFileDialog::AcceptOpen)
|
||||||
|
return GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||||
|
else
|
||||||
|
return GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||||
|
case QFileDialog::Directory:
|
||||||
|
case QFileDialog::DirectoryOnly:
|
||||||
|
default:
|
||||||
|
if (acceptMode == QFileDialog::AcceptOpen)
|
||||||
|
return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||||
|
else
|
||||||
|
return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CustomButtonsSupported() {
|
||||||
|
return (Libs::gtk_dialog_get_widget_for_response != nullptr)
|
||||||
|
&& (Libs::gtk_button_set_label != nullptr)
|
||||||
|
&& (Libs::gtk_button_get_type != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::applyOptions() {
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
|
||||||
|
Libs::gtk_window_set_title(Libs::gtk_window_cast(gtkDialog), _windowTitle.toUtf8());
|
||||||
|
Libs::gtk_file_chooser_set_local_only(Libs::gtk_file_chooser_cast(gtkDialog), true);
|
||||||
|
|
||||||
|
const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode);
|
||||||
|
Libs::gtk_file_chooser_set_action(Libs::gtk_file_chooser_cast(gtkDialog), action);
|
||||||
|
|
||||||
|
const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles);
|
||||||
|
Libs::gtk_file_chooser_set_select_multiple(Libs::gtk_file_chooser_cast(gtkDialog), selectMultiple);
|
||||||
|
|
||||||
|
const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite);
|
||||||
|
Libs::gtk_file_chooser_set_do_overwrite_confirmation(Libs::gtk_file_chooser_cast(gtkDialog), confirmOverwrite);
|
||||||
|
|
||||||
|
if (!_nameFilters.isEmpty())
|
||||||
|
setNameFilters(_nameFilters);
|
||||||
|
|
||||||
|
if (!_initialDirectory.isEmpty())
|
||||||
|
setDirectory(_initialDirectory);
|
||||||
|
|
||||||
|
for_const (const auto &filename, _initialFiles) {
|
||||||
|
if (_acceptMode == QFileDialog::AcceptSave) {
|
||||||
|
QFileInfo fi(filename);
|
||||||
|
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8());
|
||||||
|
Libs::gtk_file_chooser_set_current_name(Libs::gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8());
|
||||||
|
} else if (filename.endsWith('/')) {
|
||||||
|
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8());
|
||||||
|
} else {
|
||||||
|
Libs::gtk_file_chooser_select_filename(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front();
|
||||||
|
if (!initialNameFilter.isEmpty())
|
||||||
|
selectNameFilter(initialNameFilter);
|
||||||
|
|
||||||
|
if (CustomButtonsSupported()) {
|
||||||
|
GtkWidget *acceptButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK);
|
||||||
|
if (acceptButton) {
|
||||||
|
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
|
||||||
|
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8());
|
||||||
|
else*/ if (_acceptMode == QFileDialog::AcceptOpen)
|
||||||
|
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_OPEN);
|
||||||
|
else
|
||||||
|
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_SAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *rejectButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL);
|
||||||
|
if (rejectButton) {
|
||||||
|
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject))
|
||||||
|
Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8());
|
||||||
|
else*/
|
||||||
|
Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), GTK_STOCK_CANCEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkFileDialog::setNameFilters(const QStringList &filters) {
|
||||||
|
GtkDialog *gtkDialog = d->gtkDialog();
|
||||||
|
foreach (GtkFileFilter *filter, _filters)
|
||||||
|
Libs::gtk_file_chooser_remove_filter(Libs::gtk_file_chooser_cast(gtkDialog), filter);
|
||||||
|
|
||||||
|
_filters.clear();
|
||||||
|
_filterNames.clear();
|
||||||
|
|
||||||
|
foreach (const QString &filter, filters) {
|
||||||
|
GtkFileFilter *gtkFilter = Libs::gtk_file_filter_new();
|
||||||
|
const QString name = filter.left(filter.indexOf(QLatin1Char('(')));
|
||||||
|
const QStringList extensions = cleanFilterList(filter);
|
||||||
|
|
||||||
|
Libs::gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8());
|
||||||
|
foreach (const QString &ext, extensions)
|
||||||
|
Libs::gtk_file_filter_add_pattern(gtkFilter, ext.toUtf8());
|
||||||
|
|
||||||
|
Libs::gtk_file_chooser_add_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter);
|
||||||
|
|
||||||
|
_filters.insert(filter, gtkFilter);
|
||||||
|
_filterNames.insert(gtkFilter, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace FileDialog
|
||||||
|
} // namespace Platform
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/filedialog.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#undef signals
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#define signals public
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace FileDialog {
|
||||||
|
|
||||||
|
bool Supported();
|
||||||
|
|
||||||
|
bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile);
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// This is a patched copy of qgtk2 theme plugin.
|
||||||
|
// We need to use our own gtk file dialog instead of
|
||||||
|
// styling Qt file dialog, because Qt only works with gtk2.
|
||||||
|
// We need to be able to work with gtk2 and gtk3, because
|
||||||
|
// we use gtk3 to work with appindicator3.
|
||||||
|
class QGtkDialog : public QWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QGtkDialog(GtkWidget *gtkWidget);
|
||||||
|
~QGtkDialog();
|
||||||
|
|
||||||
|
GtkDialog *gtkDialog() const;
|
||||||
|
|
||||||
|
void exec();
|
||||||
|
void show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
|
||||||
|
void hide();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void accept();
|
||||||
|
void reject();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void onResponse(QGtkDialog *dialog, int response);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onParentWindowDestroyed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GtkWidget *gtkWidget;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GtkFileDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GtkFileDialog(QWidget *parent = Q_NULLPTR,
|
||||||
|
const QString &caption = QString(),
|
||||||
|
const QString &directory = QString(),
|
||||||
|
const QString &filter = QString());
|
||||||
|
~GtkFileDialog();
|
||||||
|
|
||||||
|
void setVisible(bool visible) override;
|
||||||
|
|
||||||
|
void setWindowTitle(const QString &windowTitle) {
|
||||||
|
_windowTitle = windowTitle;
|
||||||
|
}
|
||||||
|
void setAcceptMode(QFileDialog::AcceptMode acceptMode) {
|
||||||
|
_acceptMode = acceptMode;
|
||||||
|
}
|
||||||
|
void setFileMode(QFileDialog::FileMode fileMode) {
|
||||||
|
_fileMode = fileMode;
|
||||||
|
}
|
||||||
|
void setOption(QFileDialog::Option option, bool on = true) {
|
||||||
|
if (on) {
|
||||||
|
_options |= option;
|
||||||
|
} else {
|
||||||
|
_options &= ~option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exec() override;
|
||||||
|
|
||||||
|
bool defaultNameFilterDisables() const;
|
||||||
|
void setDirectory(const QString &directory);
|
||||||
|
QDir directory() const;
|
||||||
|
void selectFile(const QString &filename);
|
||||||
|
QStringList selectedFiles() const;
|
||||||
|
void setFilter();
|
||||||
|
void selectNameFilter(const QString &filter);
|
||||||
|
QString selectedNameFilter() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onAccepted();
|
||||||
|
void onRejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper);
|
||||||
|
static void onCurrentFolderChanged(GtkFileDialog *helper);
|
||||||
|
void applyOptions();
|
||||||
|
void setNameFilters(const QStringList &filters);
|
||||||
|
|
||||||
|
void showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
|
||||||
|
void hideHelper();
|
||||||
|
|
||||||
|
// Options
|
||||||
|
QFileDialog::Options _options = { 0 };
|
||||||
|
QString _windowTitle = "Choose file";
|
||||||
|
QString _initialDirectory;
|
||||||
|
QStringList _initialFiles;
|
||||||
|
QStringList _nameFilters;
|
||||||
|
QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen;
|
||||||
|
QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile;
|
||||||
|
|
||||||
|
QString _dir;
|
||||||
|
QStringList _selection;
|
||||||
|
QHash<QString, GtkFileFilter*> _filters;
|
||||||
|
QHash<GtkFileFilter*, QString> _filterNames;
|
||||||
|
QScopedPointer<QGtkDialog> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace FileDialog
|
||||||
|
} // namespace Platform
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "platform/linux/linux_gdk_helper.h"
|
||||||
|
|
||||||
|
#include "platform/linux/linux_libs.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#undef signals
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#define signals public
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
enum class GtkLoaded {
|
||||||
|
GtkNone,
|
||||||
|
Gtk2,
|
||||||
|
Gtk3,
|
||||||
|
};
|
||||||
|
|
||||||
|
GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone;
|
||||||
|
|
||||||
|
// To be able to compile with gtk-3.0 headers as well
|
||||||
|
#define GdkDrawable GdkWindow
|
||||||
|
|
||||||
|
// Gtk 2
|
||||||
|
using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*);
|
||||||
|
f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr;
|
||||||
|
|
||||||
|
using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*);
|
||||||
|
f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr;
|
||||||
|
|
||||||
|
// Gtk 3
|
||||||
|
using f_gdk_x11_window_get_type = GType (*)(void);
|
||||||
|
f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr;
|
||||||
|
|
||||||
|
// To be able to compile with gtk-2.0 headers as well
|
||||||
|
template <typename Object>
|
||||||
|
inline bool gdk_is_x11_window_check(Object *obj) {
|
||||||
|
return Libs::g_type_cit_helper(obj, gdk_x11_window_get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window);
|
||||||
|
f_gdk_window_get_display gdk_window_get_display = nullptr;
|
||||||
|
|
||||||
|
using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display);
|
||||||
|
f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr;
|
||||||
|
|
||||||
|
using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window);
|
||||||
|
f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr;
|
||||||
|
|
||||||
|
bool GdkHelperLoadGtk2(QLibrary &lib) {
|
||||||
|
if (!Libs::load(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false;
|
||||||
|
if (!Libs::load(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdkHelperLoadGtk3(QLibrary &lib) {
|
||||||
|
if (!Libs::load(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false;
|
||||||
|
if (!Libs::load(lib, "gdk_window_get_display", gdk_window_get_display)) return false;
|
||||||
|
if (!Libs::load(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false;
|
||||||
|
if (!Libs::load(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdkHelperLoad(QLibrary &lib) {
|
||||||
|
gdk_helper_loaded = GtkLoaded::GtkNone;
|
||||||
|
if (GdkHelperLoadGtk2(lib)) {
|
||||||
|
gdk_helper_loaded = GtkLoaded::Gtk2;
|
||||||
|
} else if (GdkHelperLoadGtk3(lib)) {
|
||||||
|
gdk_helper_loaded = GtkLoaded::Gtk3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdkHelperLoaded() {
|
||||||
|
return gdk_helper_loaded != GtkLoaded::GtkNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XSetTransientForHint(GdkWindow *window, quintptr winId) {
|
||||||
|
if (gdk_helper_loaded == GtkLoaded::Gtk2) {
|
||||||
|
::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window),
|
||||||
|
gdk_x11_drawable_get_xid(window),
|
||||||
|
winId);
|
||||||
|
} else if (gdk_helper_loaded == GtkLoaded::Gtk3) {
|
||||||
|
if (gdk_is_x11_window_check(window)) {
|
||||||
|
::XSetTransientForHint(gdk_x11_display_get_xdisplay(gdk_window_get_display(window)),
|
||||||
|
gdk_x11_window_get_xid(window),
|
||||||
|
winId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace Platform
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#undef signals
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#define signals public
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
void GdkHelperLoad(QLibrary &lib);
|
||||||
|
bool GdkHelperLoaded();
|
||||||
|
void XSetTransientForHint(GdkWindow *window, quintptr winId);
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace Platform
|
|
@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "platform/linux/linux_libs.h"
|
#include "platform/linux/linux_libs.h"
|
||||||
|
|
||||||
|
#include "platform/linux/linux_gdk_helper.h"
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Libs {
|
namespace Libs {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -51,15 +53,50 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||||
if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false;
|
if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false;
|
||||||
if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false;
|
if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false;
|
||||||
if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false;
|
if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false;
|
||||||
if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false;
|
if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false;
|
||||||
if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false;
|
if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false;
|
||||||
if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false;
|
if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false;
|
||||||
|
|
||||||
|
if (!load(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false;
|
||||||
|
if (!load(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false;
|
||||||
|
if (!load(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false;
|
||||||
|
|
||||||
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
|
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
|
||||||
|
if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
|
||||||
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
|
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
|
||||||
|
|
||||||
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
|
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
|
||||||
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
|
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
|
||||||
|
if (!load(lib_gtk, "g_free", g_free)) return false;
|
||||||
|
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
|
||||||
|
|
||||||
DEBUG_LOG(("Library gtk functions loaded!"));
|
DEBUG_LOG(("Library gtk functions loaded!"));
|
||||||
if (!gtk_init_check(0, 0)) {
|
if (!gtk_init_check(0, 0)) {
|
||||||
|
@ -92,10 +129,45 @@ f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr;
|
||||||
f_gtk_menu_shell_append gtk_menu_shell_append = nullptr;
|
f_gtk_menu_shell_append gtk_menu_shell_append = nullptr;
|
||||||
f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr;
|
f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr;
|
||||||
f_gtk_widget_show gtk_widget_show = nullptr;
|
f_gtk_widget_show gtk_widget_show = nullptr;
|
||||||
|
f_gtk_widget_hide gtk_widget_hide = nullptr;
|
||||||
f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr;
|
f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr;
|
||||||
f_gtk_widget_get_visible gtk_widget_get_visible = nullptr;
|
f_gtk_widget_get_visible gtk_widget_get_visible = nullptr;
|
||||||
|
f_gtk_widget_get_window gtk_widget_get_window = nullptr;
|
||||||
f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr;
|
f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr;
|
||||||
|
f_gtk_widget_realize gtk_widget_realize = nullptr;
|
||||||
|
f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr;
|
||||||
|
f_gtk_widget_destroy gtk_widget_destroy = nullptr;
|
||||||
|
f_gtk_clipboard_get gtk_clipboard_get = nullptr;
|
||||||
|
f_gtk_clipboard_store gtk_clipboard_store = nullptr;
|
||||||
|
f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr;
|
||||||
|
f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr;
|
||||||
|
f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder = nullptr;
|
||||||
|
f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder = nullptr;
|
||||||
|
f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name = nullptr;
|
||||||
|
f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename = nullptr;
|
||||||
|
f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames = nullptr;
|
||||||
|
f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter = nullptr;
|
||||||
|
f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter = nullptr;
|
||||||
|
f_gtk_window_get_type gtk_window_get_type = nullptr;
|
||||||
|
f_gtk_window_set_title gtk_window_set_title = nullptr;
|
||||||
|
f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only = nullptr;
|
||||||
|
f_gtk_file_chooser_set_action gtk_file_chooser_set_action = nullptr;
|
||||||
|
f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple = nullptr;
|
||||||
|
f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation = nullptr;
|
||||||
|
f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter = nullptr;
|
||||||
|
f_gtk_file_filter_set_name gtk_file_filter_set_name = nullptr;
|
||||||
|
f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern = nullptr;
|
||||||
|
f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter = nullptr;
|
||||||
|
f_gtk_file_filter_new gtk_file_filter_new = nullptr;
|
||||||
|
f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response = nullptr;
|
||||||
|
f_gtk_button_set_label gtk_button_set_label = nullptr;
|
||||||
|
f_gtk_button_get_type gtk_button_get_type = nullptr;
|
||||||
|
f_gdk_window_set_modal_hint gdk_window_set_modal_hint = nullptr;
|
||||||
|
f_gdk_window_focus gdk_window_focus = nullptr;
|
||||||
|
f_gtk_dialog_get_type gtk_dialog_get_type = nullptr;
|
||||||
|
f_gtk_dialog_run gtk_dialog_run = nullptr;
|
||||||
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
||||||
|
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
|
||||||
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
||||||
f_app_indicator_new app_indicator_new = nullptr;
|
f_app_indicator_new app_indicator_new = nullptr;
|
||||||
f_app_indicator_set_status app_indicator_set_status = nullptr;
|
f_app_indicator_set_status app_indicator_set_status = nullptr;
|
||||||
|
@ -118,9 +190,13 @@ f_gtk_get_current_event_time gtk_get_current_event_time = nullptr;
|
||||||
f_g_object_ref_sink g_object_ref_sink = nullptr;
|
f_g_object_ref_sink g_object_ref_sink = nullptr;
|
||||||
f_g_object_unref g_object_unref = nullptr;
|
f_g_object_unref g_object_unref = nullptr;
|
||||||
f_g_idle_add g_idle_add = nullptr;
|
f_g_idle_add g_idle_add = nullptr;
|
||||||
|
f_g_free g_free = nullptr;
|
||||||
|
f_g_slist_free g_slist_free = nullptr;
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
|
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
|
||||||
f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr;
|
f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr;
|
||||||
f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr;
|
f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr;
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
DEBUG_LOG(("Loading libraries"));
|
DEBUG_LOG(("Loading libraries"));
|
||||||
|
@ -170,10 +246,17 @@ void start() {
|
||||||
load(lib_gtk, "gtk_menu_popup", gtk_menu_popup);
|
load(lib_gtk, "gtk_menu_popup", gtk_menu_popup);
|
||||||
load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time);
|
load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time);
|
||||||
load(lib_gtk, "g_idle_add", g_idle_add);
|
load(lib_gtk, "g_idle_add", g_idle_add);
|
||||||
|
|
||||||
|
internal::GdkHelperLoad(lib_gtk);
|
||||||
|
|
||||||
|
load(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response);
|
||||||
|
load(lib_gtk, "gtk_button_set_label", gtk_button_set_label);
|
||||||
|
load(lib_gtk, "gtk_button_get_type", gtk_button_get_type);
|
||||||
} else {
|
} else {
|
||||||
LOG(("Could not load gtk-x11-2.0!"));
|
LOG(("Could not load gtk-x11-2.0!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) {
|
if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) {
|
||||||
QLibrary lib_unity(qstr("unity"), 9, 0);
|
QLibrary lib_unity(qstr("unity"), 9, 0);
|
||||||
loadLibrary(lib_unity, "unity", 9);
|
loadLibrary(lib_unity, "unity", 9);
|
||||||
|
@ -182,6 +265,7 @@ void start() {
|
||||||
load(lib_unity, "unity_launcher_entry_set_count", unity_launcher_entry_set_count);
|
load(lib_unity, "unity_launcher_entry_set_count", unity_launcher_entry_set_count);
|
||||||
load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
|
load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
|
||||||
}
|
}
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libs
|
} // namespace Libs
|
||||||
|
|
|
@ -24,10 +24,13 @@ extern "C" {
|
||||||
#undef signals
|
#undef signals
|
||||||
#include <libappindicator/app-indicator.h>
|
#include <libappindicator/app-indicator.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
#define signals public
|
#define signals public
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
#include <unity/unity/unity.h>
|
#include <unity/unity/unity.h>
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Libs {
|
namespace Libs {
|
||||||
|
@ -73,15 +76,102 @@ extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type;
|
||||||
typedef void (*f_gtk_widget_show)(GtkWidget *widget);
|
typedef void (*f_gtk_widget_show)(GtkWidget *widget);
|
||||||
extern f_gtk_widget_show gtk_widget_show;
|
extern f_gtk_widget_show gtk_widget_show;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_widget_hide)(GtkWidget *widget);
|
||||||
|
extern f_gtk_widget_hide gtk_widget_hide;
|
||||||
|
|
||||||
typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget);
|
typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget);
|
||||||
extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel;
|
extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel;
|
||||||
|
|
||||||
typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget);
|
typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget);
|
||||||
extern f_gtk_widget_get_visible gtk_widget_get_visible;
|
extern f_gtk_widget_get_visible gtk_widget_get_visible;
|
||||||
|
|
||||||
|
typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget);
|
||||||
|
extern f_gtk_widget_get_window gtk_widget_get_window;
|
||||||
|
|
||||||
typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
|
typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
|
||||||
extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive;
|
extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_widget_realize)(GtkWidget *widget);
|
||||||
|
extern f_gtk_widget_realize gtk_widget_realize;
|
||||||
|
|
||||||
|
typedef gboolean (*f_gtk_widget_hide_on_delete)(GtkWidget *widget);
|
||||||
|
extern f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_widget_destroy)(GtkWidget *widget);
|
||||||
|
extern f_gtk_widget_destroy gtk_widget_destroy;
|
||||||
|
|
||||||
|
typedef GtkClipboard* (*f_gtk_clipboard_get)(GdkAtom selection);
|
||||||
|
extern f_gtk_clipboard_get gtk_clipboard_get;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard);
|
||||||
|
extern f_gtk_clipboard_store gtk_clipboard_store;
|
||||||
|
|
||||||
|
typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED;
|
||||||
|
extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new;
|
||||||
|
|
||||||
|
typedef gboolean (*f_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename);
|
||||||
|
extern f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder;
|
||||||
|
|
||||||
|
typedef gchar *(*f_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
|
||||||
|
extern f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name);
|
||||||
|
extern f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name;
|
||||||
|
|
||||||
|
typedef gboolean (*f_gtk_file_chooser_select_filename)(GtkFileChooser *chooser, const char *filename);
|
||||||
|
extern f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename;
|
||||||
|
|
||||||
|
typedef GSList* (*f_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
|
||||||
|
extern f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
|
||||||
|
extern f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter;
|
||||||
|
|
||||||
|
typedef GtkFileFilter* (*f_gtk_file_chooser_get_filter)(GtkFileChooser *chooser);
|
||||||
|
extern f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_window_set_title)(GtkWindow *window, const gchar *title);
|
||||||
|
extern f_gtk_window_set_title gtk_window_set_title;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only);
|
||||||
|
extern f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action);
|
||||||
|
extern f_gtk_file_chooser_set_action gtk_file_chooser_set_action;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple);
|
||||||
|
extern f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
|
||||||
|
extern f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation;
|
||||||
|
|
||||||
|
typedef GtkWidget* (*f_gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id);
|
||||||
|
extern f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_button_set_label)(GtkButton *button, const gchar *label);
|
||||||
|
extern f_gtk_button_set_label gtk_button_set_label;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
|
||||||
|
extern f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name);
|
||||||
|
extern f_gtk_file_filter_set_name gtk_file_filter_set_name;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern);
|
||||||
|
extern f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern;
|
||||||
|
|
||||||
|
typedef void (*f_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
|
||||||
|
extern f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter;
|
||||||
|
|
||||||
|
typedef GtkFileFilter* (*f_gtk_file_filter_new)(void);
|
||||||
|
extern f_gtk_file_filter_new gtk_file_filter_new;
|
||||||
|
|
||||||
|
typedef void (*f_gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal);
|
||||||
|
extern f_gdk_window_set_modal_hint gdk_window_set_modal_hint;
|
||||||
|
|
||||||
|
typedef void (*f_gdk_window_focus)(GdkWindow *window, guint32 timestamp);
|
||||||
|
extern f_gdk_window_focus gdk_window_focus;
|
||||||
|
|
||||||
typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type);
|
typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type);
|
||||||
extern f_g_type_check_instance_cast g_type_check_instance_cast;
|
extern f_g_type_check_instance_cast g_type_check_instance_cast;
|
||||||
|
|
||||||
|
@ -89,21 +179,82 @@ template <typename Result, typename Object>
|
||||||
inline Result *g_type_cic_helper(Object *instance, GType iface_type) {
|
inline Result *g_type_cic_helper(Object *instance, GType iface_type) {
|
||||||
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
|
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Object>
|
template <typename Object>
|
||||||
inline GtkMenu *gtk_menu_cast(Object *obj) {
|
inline GtkMenu *gtk_menu_cast(Object *obj) {
|
||||||
return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type());
|
return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Object>
|
template <typename Object>
|
||||||
inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) {
|
inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) {
|
||||||
return g_type_cic_helper<GtkMenuShell, Object>(obj, gtk_menu_get_type());
|
return g_type_cic_helper<GtkMenuShell, Object>(obj, gtk_menu_get_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST;
|
||||||
|
extern f_gtk_dialog_get_type gtk_dialog_get_type;
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline GtkDialog *gtk_dialog_cast(Object *obj) {
|
||||||
|
return g_type_cic_helper<GtkDialog, Object>(obj, gtk_dialog_get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline GObject *g_object_cast(Object *obj) {
|
||||||
|
return g_type_cic_helper<GObject, Object>(obj, G_TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GType (*f_gtk_file_chooser_get_type)(void) G_GNUC_CONST;
|
||||||
|
extern f_gtk_file_chooser_get_type gtk_file_chooser_get_type;
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) {
|
||||||
|
return g_type_cic_helper<GtkFileChooser, Object>(obj, gtk_file_chooser_get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GType (*f_gtk_button_get_type)(void) G_GNUC_CONST;
|
||||||
|
extern f_gtk_button_get_type gtk_button_get_type;
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline GtkButton *gtk_button_cast(Object *obj) {
|
||||||
|
return g_type_cic_helper<GtkButton, Object>(obj, gtk_button_get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GType (*f_gtk_window_get_type)(void) G_GNUC_CONST;
|
||||||
|
extern f_gtk_window_get_type gtk_window_get_type;
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline GtkWindow *gtk_window_cast(Object *obj) {
|
||||||
|
return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef gboolean (*f_g_type_check_instance_is_a)(GTypeInstance *instance, GType iface_type) G_GNUC_PURE;
|
||||||
|
extern f_g_type_check_instance_is_a g_type_check_instance_is_a;
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
inline bool g_type_cit_helper(Object *instance, GType iface_type) {
|
||||||
|
if (!instance) return false;
|
||||||
|
|
||||||
|
auto ginstance = reinterpret_cast<GTypeInstance*>(instance);
|
||||||
|
if (ginstance->g_class && ginstance->g_class->g_type == iface_type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return g_type_check_instance_is_a(ginstance, iface_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef gint (*f_gtk_dialog_run)(GtkDialog *dialog);
|
||||||
|
extern f_gtk_dialog_run gtk_dialog_run;
|
||||||
|
|
||||||
typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
||||||
extern f_g_signal_connect_data g_signal_connect_data;
|
extern f_g_signal_connect_data g_signal_connect_data;
|
||||||
|
|
||||||
inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
||||||
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0);
|
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
||||||
|
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED);
|
||||||
|
}
|
||||||
|
|
||||||
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
|
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
|
||||||
extern f_app_indicator_new app_indicator_new;
|
extern f_app_indicator_new app_indicator_new;
|
||||||
|
|
||||||
|
@ -167,6 +318,13 @@ extern f_g_object_unref g_object_unref;
|
||||||
typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data);
|
typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data);
|
||||||
extern f_g_idle_add g_idle_add;
|
extern f_g_idle_add g_idle_add;
|
||||||
|
|
||||||
|
typedef void (*f_g_free)(gpointer mem);
|
||||||
|
extern f_g_free g_free;
|
||||||
|
|
||||||
|
typedef void (*f_g_slist_free)(GSList *list);
|
||||||
|
extern f_g_slist_free g_slist_free;
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value);
|
typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value);
|
||||||
extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count;
|
extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count;
|
||||||
|
|
||||||
|
@ -175,6 +333,7 @@ extern f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_v
|
||||||
|
|
||||||
typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id);
|
typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id);
|
||||||
extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id;
|
extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id;
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
} // namespace Libs
|
} // namespace Libs
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
|
@ -181,7 +181,9 @@ static gboolean _trayIconCheck(gpointer/* pIn*/) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
|
UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -319,6 +321,7 @@ void MainWindow::psUpdateCounter() {
|
||||||
int32 counter = App::histories().unreadBadge();
|
int32 counter = App::histories().unreadBadge();
|
||||||
|
|
||||||
setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
|
setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
if (_psUnityLauncherEntry) {
|
if (_psUnityLauncherEntry) {
|
||||||
if (counter > 0) {
|
if (counter > 0) {
|
||||||
Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter);
|
Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter);
|
||||||
|
@ -327,6 +330,7 @@ void MainWindow::psUpdateCounter() {
|
||||||
Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE);
|
Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
if (noQtTrayIcon) {
|
if (noQtTrayIcon) {
|
||||||
if (useAppIndicator) {
|
if (useAppIndicator) {
|
||||||
|
@ -416,12 +420,14 @@ void MainWindow::LibsLoaded() {
|
||||||
DEBUG_LOG(("Status icon api loaded!"));
|
DEBUG_LOG(("Status icon api loaded!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
|
useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
|
||||||
&& (Libs::unity_launcher_entry_set_count != nullptr)
|
&& (Libs::unity_launcher_entry_set_count != nullptr)
|
||||||
&& (Libs::unity_launcher_entry_set_count_visible != nullptr);
|
&& (Libs::unity_launcher_entry_set_count_visible != nullptr);
|
||||||
if (useUnityCount) {
|
if (useUnityCount) {
|
||||||
DEBUG_LOG(("Unity count api loaded!"));
|
DEBUG_LOG(("Unity count api loaded!"));
|
||||||
}
|
}
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psUpdateDelegate() {
|
void MainWindow::psUpdateDelegate() {
|
||||||
|
@ -598,6 +604,7 @@ void MainWindow::psCreateTrayIcon() {
|
||||||
void MainWindow::psFirstShow() {
|
void MainWindow::psFirstShow() {
|
||||||
psCreateTrayIcon();
|
psCreateTrayIcon();
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
if (useUnityCount) {
|
if (useUnityCount) {
|
||||||
_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
|
_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
|
||||||
if (_psUnityLauncherEntry) {
|
if (_psUnityLauncherEntry) {
|
||||||
|
@ -613,6 +620,7 @@ void MainWindow::psFirstShow() {
|
||||||
} else {
|
} else {
|
||||||
LOG(("Not using Unity Launcher count."));
|
LOG(("Not using Unity Launcher count."));
|
||||||
}
|
}
|
||||||
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
psUpdateMargins();
|
psUpdateMargins();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/filedialog.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
namespace Platform {
|
||||||
|
|
||||||
|
namespace FileDialog {
|
||||||
|
inline bool Supported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace FileDialog
|
||||||
|
} // namespace Platform
|
||||||
|
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||||
|
#include "platform/linux/file_dialog_linux.h"
|
||||||
|
#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX
|
||||||
|
namespace Platform {
|
||||||
|
namespace FileDialog {
|
||||||
|
inline bool Supported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace FileDialog
|
||||||
|
} // namespace Platform
|
||||||
|
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT
|
||||||
|
namespace Platform {
|
||||||
|
namespace FileDialog {
|
||||||
|
inline bool Supported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace FileDialog
|
||||||
|
} // namespace Platform
|
||||||
|
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
|
@ -975,8 +975,13 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
|
||||||
audioPlayer()->play(song);
|
audioPlayer()->play(song);
|
||||||
if (App::main()) App::main()->documentPlayProgress(song);
|
if (App::main()) App::main()->documentPlayProgress(song);
|
||||||
}
|
}
|
||||||
} else if (data->voice() || data->isVideo()) {
|
} else if (data->voice() || data->song() || data->isVideo()) {
|
||||||
psOpenFile(location.name());
|
auto filepath = location.name();
|
||||||
|
if (documentIsValidMediaFile(filepath)) {
|
||||||
|
psOpenFile(filepath);
|
||||||
|
} else {
|
||||||
|
psShowInFolder(filepath);
|
||||||
|
}
|
||||||
if (App::main()) App::main()->mediaMarkRead(data);
|
if (App::main()) App::main()->mediaMarkRead(data);
|
||||||
} else if (data->size < MediaViewImageSizeLimit) {
|
} else if (data->size < MediaViewImageSizeLimit) {
|
||||||
if (!data->data().isEmpty() && playAnimation) {
|
if (!data->data().isEmpty() && playAnimation) {
|
||||||
|
@ -1270,8 +1275,12 @@ void DocumentData::performActionOnLoad() {
|
||||||
psOpenFile(already, true);
|
psOpenFile(already, true);
|
||||||
}
|
}
|
||||||
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
||||||
if (voice() || isVideo()) {
|
if (voice() || song() || isVideo()) {
|
||||||
|
if (documentIsValidMediaFile(already)) {
|
||||||
psOpenFile(already);
|
psOpenFile(already);
|
||||||
|
} else {
|
||||||
|
psShowInFolder(already);
|
||||||
|
}
|
||||||
if (App::main()) App::main()->mediaMarkRead(this);
|
if (App::main()) App::main()->mediaMarkRead(this);
|
||||||
} else if (loc.accessEnable()) {
|
} else if (loc.accessEnable()) {
|
||||||
if (showImage && QImageReader(loc.name()).canRead()) {
|
if (showImage && QImageReader(loc.name()).canRead()) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "localstorage.h"
|
#include "localstorage.h"
|
||||||
|
#include "platform/platform_file_dialog.h"
|
||||||
|
|
||||||
void filedialogInit() {
|
void filedialogInit() {
|
||||||
if (cDialogLastPath().isEmpty()) {
|
if (cDialogLastPath().isEmpty()) {
|
||||||
|
@ -69,18 +70,23 @@ void filedialogInit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// multipleFiles: 1 - multi open, 0 - single open, -1 - single save, -2 - select dir
|
namespace FileDialog {
|
||||||
bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, int multipleFiles, QString startFile = QString()) {
|
namespace internal {
|
||||||
|
|
||||||
|
bool getFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, FileDialog::internal::Type type, QString startFile = QString()) {
|
||||||
filedialogInit();
|
filedialogInit();
|
||||||
|
|
||||||
|
if (Platform::FileDialog::Supported()) {
|
||||||
|
return Platform::FileDialog::Get(files, remoteContent, caption, filter, type, startFile);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined Q_OS_LINUX || defined Q_OS_MAC // use native
|
#if defined Q_OS_LINUX || defined Q_OS_MAC // use native
|
||||||
remoteContent = QByteArray();
|
remoteContent = QByteArray();
|
||||||
if (startFile.isEmpty() || startFile.at(0) != '/') {
|
if (startFile.isEmpty() || startFile.at(0) != '/') {
|
||||||
startFile = cDialogLastPath() + '/' + startFile;
|
startFile = cDialogLastPath() + '/' + startFile;
|
||||||
}
|
}
|
||||||
QString file;
|
QString file;
|
||||||
if (multipleFiles >= 0) {
|
if (type == Type::ReadFiles) {
|
||||||
files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath();
|
QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath();
|
||||||
if (!path.isEmpty() && path != cDialogLastPath()) {
|
if (!path.isEmpty() && path != cDialogLastPath()) {
|
||||||
|
@ -88,9 +94,9 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
return !files.isEmpty();
|
return !files.isEmpty();
|
||||||
} else if (multipleFiles < -1) {
|
} else if (type == Type::ReadFolder) {
|
||||||
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile);
|
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile);
|
||||||
} else if (multipleFiles < 0) {
|
} else if (type == Type::WriteFile) {
|
||||||
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
} else {
|
} else {
|
||||||
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
|
@ -113,10 +119,10 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
||||||
QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter);
|
QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter);
|
||||||
|
|
||||||
dialog.setModal(true);
|
dialog.setModal(true);
|
||||||
if (multipleFiles >= 0) { // open file or files
|
if (type == Type::ReadFile || type == Type::ReadFiles) {
|
||||||
dialog.setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
|
dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
|
||||||
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
} else if (multipleFiles < -1) { // save dir
|
} else if (type == Type::ReadFolder) { // save dir
|
||||||
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
dialog.setFileMode(QFileDialog::Directory);
|
dialog.setFileMode(QFileDialog::Directory);
|
||||||
dialog.setOption(QFileDialog::ShowDirsOnly);
|
dialog.setOption(QFileDialog::ShowDirsOnly);
|
||||||
|
@ -127,7 +133,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath());
|
if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath());
|
||||||
if (multipleFiles == -1) {
|
if (type == Type::WriteFile) {
|
||||||
QString toSelect(startFile);
|
QString toSelect(startFile);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
int32 lastSlash = toSelect.lastIndexOf('/');
|
int32 lastSlash = toSelect.lastIndexOf('/');
|
||||||
|
@ -151,12 +157,12 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == QDialog::Accepted) {
|
if (res == QDialog::Accepted) {
|
||||||
if (multipleFiles > 0) {
|
if (type == Type::ReadFiles) {
|
||||||
files = dialog.selectedFiles();
|
files = dialog.selectedFiles();
|
||||||
} else {
|
} else {
|
||||||
files = dialog.selectedFiles().mid(0, 1);
|
files = dialog.selectedFiles().mid(0, 1);
|
||||||
}
|
}
|
||||||
if (multipleFiles >= 0) {
|
if (type == Type::ReadFile || type == Type::ReadFiles) {
|
||||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
||||||
remoteContent = dialog.selectedRemoteContent();
|
remoteContent = dialog.selectedRemoteContent();
|
||||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||||
|
@ -169,13 +175,16 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace FileDialog
|
||||||
|
|
||||||
bool filedialogGetOpenFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter) {
|
bool filedialogGetOpenFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter) {
|
||||||
return _filedialogGetFiles(files, remoteContent, caption, filter, 1);
|
return FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QString &caption, const QString &filter) {
|
bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QString &caption, const QString &filter) {
|
||||||
QStringList files;
|
QStringList files;
|
||||||
bool result = _filedialogGetFiles(files, remoteContent, caption, filter, 0);
|
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile);
|
||||||
file = files.isEmpty() ? QString() : files.at(0);
|
file = files.isEmpty() ? QString() : files.at(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +192,7 @@ bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QStri
|
||||||
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName) {
|
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName) {
|
||||||
QStringList files;
|
QStringList files;
|
||||||
QByteArray remoteContent;
|
QByteArray remoteContent;
|
||||||
bool result = _filedialogGetFiles(files, remoteContent, caption, filter, -1, startName);
|
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, startName);
|
||||||
file = files.isEmpty() ? QString() : files.at(0);
|
file = files.isEmpty() ? QString() : files.at(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +200,7 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString
|
||||||
bool filedialogGetDir(QString &dir, const QString &caption) {
|
bool filedialogGetDir(QString &dir, const QString &caption) {
|
||||||
QStringList files;
|
QStringList files;
|
||||||
QByteArray remoteContent;
|
QByteArray remoteContent;
|
||||||
bool result = _filedialogGetFiles(files, remoteContent, caption, QString(), -2);
|
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder);
|
||||||
dir = files.isEmpty() ? QString() : files.at(0);
|
dir = files.isEmpty() ? QString() : files.at(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,16 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
|
||||||
QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString());
|
QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString());
|
||||||
|
|
||||||
namespace FileDialog {
|
namespace FileDialog {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
ReadFile,
|
||||||
|
ReadFiles,
|
||||||
|
ReadFolder,
|
||||||
|
WriteFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
using QueryId = uint64;
|
using QueryId = uint64;
|
||||||
struct QueryUpdate {
|
struct QueryUpdate {
|
||||||
|
|
|
@ -653,6 +653,8 @@ void ScrollArea::moveEvent(QMoveEvent *e) {
|
||||||
void ScrollArea::keyPressEvent(QKeyEvent *e) {
|
void ScrollArea::keyPressEvent(QKeyEvent *e) {
|
||||||
if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->modifiers().testFlag(Qt::AltModifier)) {
|
if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->modifiers().testFlag(Qt::AltModifier)) {
|
||||||
e->ignore();
|
e->ignore();
|
||||||
|
} else if(e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
|
||||||
|
((QObject*)widget())->event(e);
|
||||||
} else {
|
} else {
|
||||||
QScrollArea::keyPressEvent(e);
|
QScrollArea::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,9 @@ SOURCES += \
|
||||||
./SourceFiles/mtproto/scheme_auto.cpp \
|
./SourceFiles/mtproto/scheme_auto.cpp \
|
||||||
./SourceFiles/mtproto/session.cpp \
|
./SourceFiles/mtproto/session.cpp \
|
||||||
./SourceFiles/overview/overview_layout.cpp \
|
./SourceFiles/overview/overview_layout.cpp \
|
||||||
|
./SourceFiles/platform/linux/linux_gdk_helper.cpp \
|
||||||
./SourceFiles/platform/linux/linux_libs.cpp \
|
./SourceFiles/platform/linux/linux_libs.cpp \
|
||||||
|
./SourceFiles/platform/linux/file_dialog_linux.cpp \
|
||||||
./SourceFiles/platform/linux/main_window_linux.cpp \
|
./SourceFiles/platform/linux/main_window_linux.cpp \
|
||||||
./SourceFiles/profile/profile_actions_widget.cpp \
|
./SourceFiles/profile/profile_actions_widget.cpp \
|
||||||
./SourceFiles/profile/profile_block_widget.cpp \
|
./SourceFiles/profile/profile_block_widget.cpp \
|
||||||
|
@ -343,8 +345,11 @@ HEADERS += \
|
||||||
./SourceFiles/mtproto/scheme_auto.h \
|
./SourceFiles/mtproto/scheme_auto.h \
|
||||||
./SourceFiles/mtproto/session.h \
|
./SourceFiles/mtproto/session.h \
|
||||||
./SourceFiles/overview/overview_layout.h \
|
./SourceFiles/overview/overview_layout.h \
|
||||||
|
./SourceFiles/platform/platform_file_dialog.h \
|
||||||
./SourceFiles/platform/platform_main_window.h \
|
./SourceFiles/platform/platform_main_window.h \
|
||||||
|
./SourceFiles/platform/linux/linux_gdk_helper.h \
|
||||||
./SourceFiles/platform/linux/linux_libs.h \
|
./SourceFiles/platform/linux/linux_libs.h \
|
||||||
|
./SourceFiles/platform/linux/file_dialog_linux.h \
|
||||||
./SourceFiles/platform/linux/main_window_linux.h \
|
./SourceFiles/platform/linux/main_window_linux.h \
|
||||||
./SourceFiles/profile/profile_actions_widget.h \
|
./SourceFiles/profile/profile_actions_widget.h \
|
||||||
./SourceFiles/profile/profile_block_widget.h \
|
./SourceFiles/profile/profile_block_widget.h \
|
||||||
|
@ -479,14 +484,15 @@ INCLUDEPATH += \
|
||||||
./../../Libraries/breakpad/src
|
./../../Libraries/breakpad/src
|
||||||
|
|
||||||
INCLUDEPATH += "/usr/include/libappindicator-0.1"
|
INCLUDEPATH += "/usr/include/libappindicator-0.1"
|
||||||
|
#INCLUDEPATH += "/usr/include/gtk-3.0"
|
||||||
INCLUDEPATH += "/usr/include/gtk-2.0"
|
INCLUDEPATH += "/usr/include/gtk-2.0"
|
||||||
|
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
|
||||||
|
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
|
||||||
INCLUDEPATH += "/usr/include/glib-2.0"
|
INCLUDEPATH += "/usr/include/glib-2.0"
|
||||||
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
|
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
|
||||||
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
|
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
|
||||||
INCLUDEPATH += "/usr/include/cairo"
|
INCLUDEPATH += "/usr/include/cairo"
|
||||||
INCLUDEPATH += "/usr/include/pango-1.0"
|
INCLUDEPATH += "/usr/include/pango-1.0"
|
||||||
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
|
|
||||||
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
|
|
||||||
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
|
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
|
||||||
INCLUDEPATH += "/usr/include/atk-1.0"
|
INCLUDEPATH += "/usr/include/atk-1.0"
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
QT_TDESKTOP_VERSION_DEFAULT = 5.6.0
|
QT_TDESKTOP_VERSION_DEFAULT = 5.6.0
|
||||||
QT_TDESKTOP_PATH_DEFAULT = /usr/local/tdesktop/Qt-$${QT_TDESKTOP_VERSION_DEFAULT}
|
QT_TDESKTOP_PATH_DEFAULT = /usr/local/tdesktop/Qt-$${QT_TDESKTOP_VERSION_DEFAULT}
|
||||||
|
|
||||||
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
|
|
||||||
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH}
|
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH}
|
||||||
|
isEmpty(QT_TDESKTOP_PATH) {
|
||||||
|
QT_TDESKTOP_PATH = $$(QT_TDESKTOP_PATH)
|
||||||
isEmpty(QT_TDESKTOP_PATH) {
|
isEmpty(QT_TDESKTOP_PATH) {
|
||||||
message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT})
|
message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT})
|
||||||
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT}
|
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
|
||||||
|
isEmpty(QT_TDESKTOP_VERSION) {
|
||||||
|
QT_TDESKTOP_VERSION = $$(QT_TDESKTOP_VERSION)
|
||||||
isEmpty(QT_TDESKTOP_VERSION) {
|
isEmpty(QT_TDESKTOP_VERSION) {
|
||||||
message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT})
|
message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT})
|
||||||
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT}
|
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INCLUDEPATH += $${QT_TDESKTOP_PATH}/include/QtGui/$${QT_TDESKTOP_VERSION}/QtGui \
|
INCLUDEPATH += $${QT_TDESKTOP_PATH}/include/QtGui/$${QT_TDESKTOP_VERSION}/QtGui \
|
||||||
$${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION}/QtCore \
|
$${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION}/QtCore \
|
||||||
|
$${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION} \
|
||||||
$${QT_TDESKTOP_PATH}/include
|
$${QT_TDESKTOP_PATH}/include
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,36 @@
|
||||||
##Build instructions for Visual Studio 2015
|
# Build instructions for Visual Studio 2015
|
||||||
|
|
||||||
###Prepare folder
|
* [Prepare folder](#prepare-folder)
|
||||||
|
* [Clone source code](#clone-source-code)
|
||||||
|
* [Prepare libraries](#prepare-libraries)
|
||||||
|
+ [OpenSSL](#openssl)
|
||||||
|
+ [LZMA SDK 9.20](#lzma-sdk-920)
|
||||||
|
- [Building library](#building-library)
|
||||||
|
+ [zlib 1.2.8](#zlib-128)
|
||||||
|
- [Building library](#building-library-1)
|
||||||
|
+ [libexif 0.6.20](#libexif-0620)
|
||||||
|
- [Building library](#building-library-2)
|
||||||
|
+ [OpenAL Soft, slightly patched](#openal-soft-slightly-patched)
|
||||||
|
- [Building library](#building-library-3)
|
||||||
|
+ [Opus codec](#opus-codec)
|
||||||
|
- [Building libraries](#building-libraries)
|
||||||
|
+ [FFmpeg](#ffmpeg)
|
||||||
|
- [Building libraries](#building-libraries-1)
|
||||||
|
+ [Qt 5.6.0, slightly patched](#qt-560-slightly-patched)
|
||||||
|
- [Apply the patch](#apply-the-patch)
|
||||||
|
- [Install Windows SDKs](#install-windows-sdks)
|
||||||
|
- [Building library](#building-library-4)
|
||||||
|
+ [Qt5Package](#qt5package)
|
||||||
|
+ [Google Breakpad](#google-breakpad)
|
||||||
|
- [Install](#install)
|
||||||
|
- [Build](#build)
|
||||||
|
* [Building Telegram Desktop](#building-telegram-desktop)
|
||||||
|
|
||||||
|
## Prepare folder
|
||||||
|
|
||||||
Choose a folder for the future build, for example **D:\TBuild\**. There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app.
|
Choose a folder for the future build, for example **D:\TBuild\**. There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app.
|
||||||
|
|
||||||
###Clone source code
|
## Clone source code
|
||||||
|
|
||||||
By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and run
|
By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and run
|
||||||
|
|
||||||
|
@ -12,9 +38,9 @@ By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and r
|
||||||
|
|
||||||
or download in ZIP and extract to **D:\TBuild\**, rename **tdesktop-master** to **tdesktop** to have **D:\TBuild\tdesktop\Telegram.sln** solution
|
or download in ZIP and extract to **D:\TBuild\**, rename **tdesktop-master** to **tdesktop** to have **D:\TBuild\tdesktop\Telegram.sln** solution
|
||||||
|
|
||||||
###Prepare libraries
|
## Prepare libraries
|
||||||
|
|
||||||
####OpenSSL
|
### OpenSSL
|
||||||
|
|
||||||
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
|
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
|
||||||
|
|
||||||
|
@ -35,13 +61,13 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
nmake -f ms\nt.mak install
|
nmake -f ms\nt.mak install
|
||||||
|
|
||||||
|
|
||||||
####LZMA SDK 9.20
|
### LZMA SDK 9.20
|
||||||
|
|
||||||
http://www.7-zip.org/sdk.html > Download [**LZMA SDK (C, C++, C#, Java)** 9.20](http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2)
|
http://www.7-zip.org/sdk.html > Download [**LZMA SDK (C, C++, C#, Java)** 9.20](http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2)
|
||||||
|
|
||||||
Extract to **D:\TBuild\Libraries**
|
Extract to **D:\TBuild\Libraries**
|
||||||
|
|
||||||
#####Building library
|
#### Building library
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\lzma\C\Util\LzmaLib\LzmaLib.dsw** > One-way upgrade – **OK**
|
* Open in VS2015 **D:\TBuild\Libraries\lzma\C\Util\LzmaLib\LzmaLib.dsw** > One-way upgrade – **OK**
|
||||||
* For **Debug** and **Release** configurations
|
* For **Debug** and **Release** configurations
|
||||||
|
@ -53,13 +79,13 @@ Extract to **D:\TBuild\Libraries**
|
||||||
* Build Debug configuration
|
* Build Debug configuration
|
||||||
* Build Release configuration
|
* Build Release configuration
|
||||||
|
|
||||||
####zlib 1.2.8
|
### zlib 1.2.8
|
||||||
|
|
||||||
http://www.zlib.net/ > Download [**zlib source code, version 1.2.8, zipfile format**](http://zlib.net/zlib128.zip)
|
http://www.zlib.net/ > Download [**zlib source code, version 1.2.8, zipfile format**](http://zlib.net/zlib128.zip)
|
||||||
|
|
||||||
Extract to **D:\\TBuild\\Libraries\\**
|
Extract to **D:\\TBuild\\Libraries\\**
|
||||||
|
|
||||||
#####Building library
|
#### Building library
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\zlib-1.2.8\contrib\vstudio\vc11\zlibvc.sln** > One-way upgrade – **OK**
|
* Open in VS2015 **D:\TBuild\Libraries\zlib-1.2.8\contrib\vstudio\vc11\zlibvc.sln** > One-way upgrade – **OK**
|
||||||
* We are interested only in **zlibstat** project, but it depends on some custom pre-build step, so build all
|
* We are interested only in **zlibstat** project, but it depends on some custom pre-build step, so build all
|
||||||
|
@ -70,7 +96,7 @@ Extract to **D:\\TBuild\\Libraries\\**
|
||||||
* Build Solution for Debug configuration – only **zlibstat** project builds successfully
|
* Build Solution for Debug configuration – only **zlibstat** project builds successfully
|
||||||
* Build Solution for Release configuration – only **zlibstat** project builds successfully
|
* Build Solution for Release configuration – only **zlibstat** project builds successfully
|
||||||
|
|
||||||
####libexif 0.6.20
|
### libexif 0.6.20
|
||||||
|
|
||||||
Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
|
Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
|
||||||
|
|
||||||
|
@ -78,13 +104,13 @@ Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – i
|
||||||
|
|
||||||
or download in ZIP and extract to **D:\TBuild\Libraries\**, rename **libexif-0.6.20-master** to **libexif-0.6.20** to have **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** solution
|
or download in ZIP and extract to **D:\TBuild\Libraries\**, rename **libexif-0.6.20-master** to **libexif-0.6.20** to have **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** solution
|
||||||
|
|
||||||
#####Building library
|
#### Building library
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln**
|
* Open in VS2015 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln**
|
||||||
* Build Debug configuration
|
* Build Debug configuration
|
||||||
* Build Release configuration
|
* Build Release configuration
|
||||||
|
|
||||||
####OpenAL Soft, slightly patched
|
### OpenAL Soft, slightly patched
|
||||||
|
|
||||||
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
|
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
|
||||||
|
|
||||||
|
@ -93,7 +119,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
git checkout 90349b38
|
git checkout 90349b38
|
||||||
git apply ./../../tdesktop/Telegram/Patches/openal.diff
|
git apply ./../../tdesktop/Telegram/Patches/openal.diff
|
||||||
|
|
||||||
#####Building library
|
#### Building library
|
||||||
|
|
||||||
* Install [CMake](http://www.cmake.org/)
|
* Install [CMake](http://www.cmake.org/)
|
||||||
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\TBuild\Libraries\openal-soft\build\** and run
|
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\TBuild\Libraries\openal-soft\build\** and run
|
||||||
|
@ -102,7 +128,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\openal-soft\build\OpenAL.sln** and build Debug and Release configurations
|
* Open in VS2015 **D:\TBuild\Libraries\openal-soft\build\OpenAL.sln** and build Debug and Release configurations
|
||||||
|
|
||||||
####Opus codec
|
### Opus codec
|
||||||
|
|
||||||
Get sources by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
|
Get sources by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
|
||||||
|
|
||||||
|
@ -110,13 +136,13 @@ Get sources by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tb
|
||||||
|
|
||||||
to have **D:\TBuild\Libraries\opus\win32**
|
to have **D:\TBuild\Libraries\opus\win32**
|
||||||
|
|
||||||
#####Building libraries
|
#### Building libraries
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\opus\win32\VS2010\opus.sln**
|
* Open in VS2015 **D:\TBuild\Libraries\opus\win32\VS2010\opus.sln**
|
||||||
* Build Debug configuration
|
* Build Debug configuration
|
||||||
* Build Release configuration (it will be required in **FFmpeg** build!)
|
* Build Release configuration (it will be required in **FFmpeg** build!)
|
||||||
|
|
||||||
####FFmpeg
|
### FFmpeg
|
||||||
|
|
||||||
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) and run
|
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) and run
|
||||||
|
|
||||||
|
@ -126,7 +152,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
|
|
||||||
http://msys2.github.io/ > Download [msys2-x86_64-20150512.exe](http://sourceforge.net/projects/msys2/files/Base/x86_64/msys2-x86_64-20150512.exe/download) and install to **D:\\msys64**
|
http://msys2.github.io/ > Download [msys2-x86_64-20150512.exe](http://sourceforge.net/projects/msys2/files/Base/x86_64/msys2-x86_64-20150512.exe/download) and install to **D:\\msys64**
|
||||||
|
|
||||||
#####Building libraries
|
#### Building libraries
|
||||||
|
|
||||||
Download [yasm for Win64](http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe) from http://yasm.tortall.net/Download.html, rename **yasm-1.3.0-win64.exe** to **yasm.exe** and place it to your Visual C++ **bin** directory, like **\\Program Files (x86)\\Microsoft Visual Studio 14\\VC\\bin\\**
|
Download [yasm for Win64](http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe) from http://yasm.tortall.net/Download.html, rename **yasm-1.3.0-win64.exe** to **yasm.exe** and place it to your Visual C++ **bin** directory, like **\\Program Files (x86)\\Microsoft Visual Studio 14\\VC\\bin\\**
|
||||||
|
|
||||||
|
@ -148,7 +174,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
####Qt 5.6.0, slightly patched
|
### Qt 5.6.0, slightly patched
|
||||||
|
|
||||||
* Install Python 3.3.2 from https://www.python.org/download/releases/3.3.2 > [**Windows x86 MSI Installer (3.3.2)**](https://www.python.org/ftp/python/3.3.2/python-3.3.2.msi)
|
* Install Python 3.3.2 from https://www.python.org/download/releases/3.3.2 > [**Windows x86 MSI Installer (3.3.2)**](https://www.python.org/ftp/python/3.3.2/python-3.3.2.msi)
|
||||||
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
|
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
|
||||||
|
@ -168,17 +194,17 @@ and run
|
||||||
cd qtimageformats && git checkout v5.6.0 && cd ..
|
cd qtimageformats && git checkout v5.6.0 && cd ..
|
||||||
cd qtbase && git checkout v5.6.0 && cd ..
|
cd qtbase && git checkout v5.6.0 && cd ..
|
||||||
|
|
||||||
#####Apply the patch
|
#### Apply the patch
|
||||||
|
|
||||||
cd qtbase && git apply ../../../tdesktop/Telegram/Patches/qtbase_5_6_0.diff && cd ..
|
cd qtbase && git apply ../../../tdesktop/Telegram/Patches/qtbase_5_6_0.diff && cd ..
|
||||||
|
|
||||||
#####Install Windows SDKs
|
#### Install Windows SDKs
|
||||||
|
|
||||||
If you didn't install Windows SDKs before, you need to install them now. To install the SDKs just open Telegram solution at **D:\TBuild\tdesktop\Telegram.sln** and on startup Visual Studio 2015 will popup dialog box and ask to download and install extra components (including Windows 7 SDK).
|
If you didn't install Windows SDKs before, you need to install them now. To install the SDKs just open Telegram solution at **D:\TBuild\tdesktop\Telegram.sln** and on startup Visual Studio 2015 will popup dialog box and ask to download and install extra components (including Windows 7 SDK).
|
||||||
|
|
||||||
If you already have Windows SDKs then find the library folder and correct it at configure's command below (like **C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86**).
|
If you already have Windows SDKs then find the library folder and correct it at configure's command below (like **C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86**).
|
||||||
|
|
||||||
#####Building library
|
#### Building library
|
||||||
|
|
||||||
configure -debug-and-release -force-debug-info -opensource -confirm-license -static -I "D:\TBuild\Libraries\openssl\Release\include" -L "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib" -l Gdi32 -no-opengl -openssl-linked OPENSSL_LIBS_DEBUG="D:\TBuild\Libraries\openssl_debug\Debug\lib\ssleay32.lib D:\TBuild\Libraries\openssl_debug\Debug\lib\libeay32.lib" OPENSSL_LIBS_RELEASE="D:\TBuild\Libraries\openssl\Release\lib\ssleay32.lib D:\TBuild\Libraries\openssl\Release\lib\libeay32.lib" -mp -nomake examples -nomake tests -platform win32-msvc2015
|
configure -debug-and-release -force-debug-info -opensource -confirm-license -static -I "D:\TBuild\Libraries\openssl\Release\include" -L "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib" -l Gdi32 -no-opengl -openssl-linked OPENSSL_LIBS_DEBUG="D:\TBuild\Libraries\openssl_debug\Debug\lib\ssleay32.lib D:\TBuild\Libraries\openssl_debug\Debug\lib\libeay32.lib" OPENSSL_LIBS_RELEASE="D:\TBuild\Libraries\openssl\Release\lib\ssleay32.lib D:\TBuild\Libraries\openssl\Release\lib\libeay32.lib" -mp -nomake examples -nomake tests -platform win32-msvc2015
|
||||||
nmake
|
nmake
|
||||||
|
@ -186,15 +212,19 @@ If you already have Windows SDKs then find the library folder and correct it at
|
||||||
|
|
||||||
building (**nmake** command) will take really long time.
|
building (**nmake** command) will take really long time.
|
||||||
|
|
||||||
####Qt5Package
|
### Qt5Package
|
||||||
|
|
||||||
https://visualstudiogallery.msdn.microsoft.com/c89ff880-8509-47a4-a262-e4fa07168408
|
https://visualstudiogallery.msdn.microsoft.com/c89ff880-8509-47a4-a262-e4fa07168408
|
||||||
|
|
||||||
Download, close all VS2015 instances and install for VS2015
|
Download, close all VS2015 instances and install for VS2015
|
||||||
|
|
||||||
####Google Breakpad
|
### Google Breakpad
|
||||||
|
|
||||||
* Install Python 2.7.11 from https://www.python.org/downloads/release/python-2711/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.11/python-2.7.11.msi)
|
Breakpad is a set of client and server components which implement a crash-reporting system.
|
||||||
|
|
||||||
|
#### Install
|
||||||
|
|
||||||
|
* Install Python 2.7.12 from https://www.python.org/downloads/release/python-2712/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi). Make sure that python is added to your `PATH` (there is an option for this in the python installer).
|
||||||
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
|
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
|
||||||
|
|
||||||
There go to Libraries directory
|
There go to Libraries directory
|
||||||
|
@ -204,19 +234,18 @@ There go to Libraries directory
|
||||||
|
|
||||||
and run
|
and run
|
||||||
|
|
||||||
set PATH=C:\Python27;%PATH%
|
|
||||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||||
cd depot_tools
|
cd depot_tools
|
||||||
|
gclient config "https://chromium.googlesource.com/breakpad/breakpad.git"
|
||||||
gclient sync
|
gclient sync
|
||||||
cd ..
|
cd ..
|
||||||
md breakpad
|
md breakpad && cd breakpad
|
||||||
cd breakpad
|
|
||||||
..\depot_tools\fetch breakpad
|
..\depot_tools\fetch breakpad
|
||||||
..\depot_tools\gclient sync
|
..\depot_tools\gclient sync
|
||||||
|
xcopy src\src\* src /s /i
|
||||||
|
|
||||||
There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\src. Telegram only expects one src folder. Either via the command line or File Explorer, rename the top-level src folder and move the inner src folder one level up. This way, what was once breakpad\src\src\client is now breakpad\src\client, etc.
|
|
||||||
|
|
||||||
#####Building library
|
#### Build
|
||||||
|
|
||||||
* Open in VS2015 **D:\TBuild\Libraries\breakpad\src\client\windows\breakpad_client.sln**
|
* Open in VS2015 **D:\TBuild\Libraries\breakpad\src\client\windows\breakpad_client.sln**
|
||||||
* Change "Treat WChar_t As Built in Type" to "No" in all projects & configurations
|
* Change "Treat WChar_t As Built in Type" to "No" in all projects & configurations
|
||||||
|
@ -224,7 +253,7 @@ There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\s
|
||||||
* Build Debug configuration
|
* Build Debug configuration
|
||||||
* Build Release configuration
|
* Build Release configuration
|
||||||
|
|
||||||
###Building Telegram Desktop
|
## Building Telegram Desktop
|
||||||
|
|
||||||
* Launch VS2015 for configuring Qt5Package
|
* Launch VS2015 for configuring Qt5Package
|
||||||
* QT5 > Qt Options > Add
|
* QT5 > Qt Options > Add
|
||||||
|
|
|
@ -72,7 +72,7 @@ Building
|
||||||
cd "$srcdir/Libraries/QtStatic"
|
cd "$srcdir/Libraries/QtStatic"
|
||||||
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
|
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
|
||||||
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
|
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
|
||||||
-qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests
|
-qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests
|
||||||
make module-qtbase module-qtimageformats
|
make module-qtbase module-qtimageformats
|
||||||
make module-qtbase-install_subtargets module-qtimageformats-install_subtargets
|
make module-qtbase-install_subtargets module-qtimageformats-install_subtargets
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ Install some packages for Qt (see **/home/user/TBuild/Libraries/qt5_6_0/qtbase/s
|
||||||
|
|
||||||
In Terminal go to **/home/user/TBuild/Libraries/qt5_6_0** and there run
|
In Terminal go to **/home/user/TBuild/Libraries/qt5_6_0** and there run
|
||||||
|
|
||||||
OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -static -openssl-linked -nomake examples -nomake tests
|
OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -openssl-linked -nomake examples -nomake tests
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue