This commit is contained in:
John Preston 2016-07-07 19:16:18 +03:00
commit 7ce76a763e
26 changed files with 1752 additions and 514 deletions

View File

@ -3,14 +3,24 @@ sudo: required
language: cpp
env:
- BUILD_VERSION=""
- BUILD_VERSION="disable_autoupdate"
- BUILD_VERSION="disable_register_custom_scheme"
- BUILD_VERSION="disable_crash_reports"
- BUILD_VERSION="disable_network_proxy"
- BUILD_VERSION="disable_desktop_file_generation"
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="disable_autoupdate"
- BUILD_VERSION="disable_register_custom_scheme"
- BUILD_VERSION="disable_crash_reports"
- BUILD_VERSION="disable_network_proxy"
- BUILD_VERSION="disable_desktop_file_generation"
- BUILD_VERSION="disable_unity_integration"
matrix:
fast_finish: true
arch:
repos:
- home_ItachiSan_archlinux_Arch_Extra=http://download.opensuse.org/repositories/home:/ItachiSan:/archlinux/Arch_Extra/$arch
packages:
- bzr
- wget
@ -18,7 +28,7 @@ arch:
- git
- patch
- dee-fixed
- home_ItachiSan_archlinux_Arch_Extra/dee # Use fixed dee version (See #2005)
- libunity
- libappindicator-gtk2

View File

@ -83,6 +83,10 @@ prepare() {
options+="\nDEFINES += TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION"
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/gtk-2.0/include"'
options+='\nINCLUDEPATH += "/usr/include/opus"'
@ -104,7 +108,7 @@ build() {
cd "$srcdir/Libraries/qt${_qtver}"
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
-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 install

View File

@ -13,6 +13,7 @@ checkCommitMessage() {
if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then
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"
addMissingSignatureInfos
exit 1
else
success_msg "Commit message contains signature"
@ -20,6 +21,37 @@ checkCommitMessage() {
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
run

View File

@ -27,8 +27,6 @@ class MainWindow;
class MainWidget;
class SettingsWidget;
class ApiWrap;
class Font;
class Color;
class FileUploader;
#include "history.h"

View File

@ -215,3 +215,23 @@ style::sprite documentCorner(int32 colorIndex) {
RoundCorners documentCorners(int32 colorIndex) {
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);
}

View File

@ -83,6 +83,7 @@ style::color documentOverColor(int32 colorIndex);
style::color documentSelectedColor(int32 colorIndex);
style::sprite documentCorner(int32 colorIndex);
RoundCorners documentCorners(int32 colorIndex);
bool documentIsValidMediaFile(const QString &filepath);
class PaintContextBase {
public:

View File

@ -44,21 +44,9 @@ int main(int argc, char *argv[]) {
Logs::start(); // must be started before Platform is started
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;
{
Application app(a_argc, a_argv);
Application app(argc, argv);
result = app.exec();
}

View File

@ -1541,7 +1541,11 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
DocumentData *audio = audioId.audio;
QString filepath = audio->filepath(DocumentData::FilePathResolveSaveFromData);
if (!filepath.isEmpty()) {
psOpenFile(filepath);
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
} else {
psShowInFolder(filepath);
}
}
}
@ -1568,7 +1572,11 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
DocumentData *document = songId.song;
QString filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
if (!filepath.isEmpty()) {
psOpenFile(filepath);
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
} else {
psShowInFolder(filepath);
}
}
}

View File

@ -505,9 +505,7 @@ void MainWindow::clearWidgets() {
intro = 0;
}
if (_mediaView) {
if (!_mediaView->isHidden()) {
_mediaView->hide();
}
hideMediaview();
_mediaView->rpcClear();
}
title->updateBackButton();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "platform/linux/linux_libs.h"
#include "platform/linux/linux_gdk_helper.h"
namespace Platform {
namespace Libs {
namespace {
@ -42,27 +44,62 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) {
}
bool setupGtkBase(QLibrary &lib_gtk) {
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false;
if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false;
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false;
if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false;
if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false;
if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) 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_widget_show", gtk_widget_show)) 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_set_sensitive", gtk_widget_set_sensitive)) return false;
if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false;
if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) 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_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_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_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, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) 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_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_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;
DEBUG_LOG(("Library gtk functions loaded!"));
if (!gtk_init_check(0, 0)) {
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_free", g_free)) return false;
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
DEBUG_LOG(("Library gtk functions loaded!"));
if (!gtk_init_check(0, 0)) {
gtk_init_check = nullptr;
DEBUG_LOG(("Failed to gtk_init_check(0, 0)!"));
return false;
@ -73,12 +110,12 @@ bool setupGtkBase(QLibrary &lib_gtk) {
}
bool setupAppIndicator(QLibrary &lib_indicator) {
if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false;
if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false;
if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false;
if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false;
if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false;
if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false;
if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false;
if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false;
DEBUG_LOG(("Library appindicator functions loaded!"));
DEBUG_LOG(("Library appindicator functions loaded!"));
return true;
}
@ -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_get_type gtk_menu_shell_get_type = 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_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_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_is_a g_type_check_instance_is_a = nullptr;
f_g_signal_connect_data g_signal_connect_data = nullptr;
f_app_indicator_new app_indicator_new = 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_unref g_object_unref = 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_visible unity_launcher_entry_set_count_visible = nullptr;
f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
void start() {
DEBUG_LOG(("Loading libraries"));
@ -170,10 +246,17 @@ void start() {
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, "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 {
LOG(("Could not load gtk-x11-2.0!"));
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) {
QLibrary lib_unity(qstr("unity"), 9, 0);
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_visible", unity_launcher_entry_set_count_visible);
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
}
} // namespace Libs

View File

@ -24,10 +24,13 @@ extern "C" {
#undef signals
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#define signals public
} // extern "C"
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
#include <unity/unity/unity.h>
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
namespace Platform {
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);
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);
extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel;
typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget);
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);
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);
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) {
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
}
template <typename Object>
inline GtkMenu *gtk_menu_cast(Object *obj) {
return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type());
}
template <typename Object>
inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) {
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);
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) {
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);
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);
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);
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);
extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
} // namespace Libs
} // namespace Platform

View File

@ -181,7 +181,9 @@ static gboolean _trayIconCheck(gpointer/* pIn*/) {
return FALSE;
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
} // namespace
@ -319,6 +321,7 @@ void MainWindow::psUpdateCounter() {
int32 counter = App::histories().unreadBadge();
setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (_psUnityLauncherEntry) {
if (counter > 0) {
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);
}
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
if (noQtTrayIcon) {
if (useAppIndicator) {
@ -416,12 +420,14 @@ void MainWindow::LibsLoaded() {
DEBUG_LOG(("Status icon api loaded!"));
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
&& (Libs::unity_launcher_entry_set_count != nullptr)
&& (Libs::unity_launcher_entry_set_count_visible != nullptr);
if (useUnityCount) {
DEBUG_LOG(("Unity count api loaded!"));
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
}
void MainWindow::psUpdateDelegate() {
@ -598,6 +604,7 @@ void MainWindow::psCreateTrayIcon() {
void MainWindow::psFirstShow() {
psCreateTrayIcon();
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (useUnityCount) {
_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
if (_psUnityLauncherEntry) {
@ -613,6 +620,7 @@ void MainWindow::psFirstShow() {
} else {
LOG(("Not using Unity Launcher count."));
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
psUpdateMargins();

View File

@ -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

View File

@ -975,8 +975,13 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song);
}
} else if (data->voice() || data->isVideo()) {
psOpenFile(location.name());
} else if (data->voice() || data->song() || data->isVideo()) {
auto filepath = location.name();
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
} else {
psShowInFolder(filepath);
}
if (App::main()) App::main()->mediaMarkRead(data);
} else if (data->size < MediaViewImageSizeLimit) {
if (!data->data().isEmpty() && playAnimation) {
@ -1270,8 +1275,12 @@ void DocumentData::performActionOnLoad() {
psOpenFile(already, true);
}
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
if (voice() || isVideo()) {
psOpenFile(already);
if (voice() || song() || isVideo()) {
if (documentIsValidMediaFile(already)) {
psOpenFile(already);
} else {
psShowInFolder(already);
}
if (App::main()) App::main()->mediaMarkRead(this);
} else if (loc.accessEnable()) {
if (showImage && QImageReader(loc.name()).canRead()) {

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "application.h"
#include "localstorage.h"
#include "platform/platform_file_dialog.h"
void filedialogInit() {
if (cDialogLastPath().isEmpty()) {
@ -69,28 +70,33 @@ void filedialogInit() {
}
}
// multipleFiles: 1 - multi open, 0 - single open, -1 - single save, -2 - select dir
bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, int multipleFiles, QString startFile = QString()) {
namespace FileDialog {
namespace internal {
bool getFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, FileDialog::internal::Type type, QString startFile = QString()) {
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
remoteContent = QByteArray();
if (startFile.isEmpty() || startFile.at(0) != '/') {
startFile = cDialogLastPath() + '/' + startFile;
}
QString file;
if (multipleFiles >= 0) {
QString file;
if (type == Type::ReadFiles) {
files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath();
if (!path.isEmpty() && path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
}
return !files.isEmpty();
} else if (multipleFiles < -1) {
return !files.isEmpty();
} else if (type == Type::ReadFolder) {
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);
} else {
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
@ -112,11 +118,11 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
// hack for fast non-native dialog create
QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter);
dialog.setModal(true);
if (multipleFiles >= 0) { // open file or files
dialog.setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
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 (multipleFiles < -1) { // save dir
} else if (type == Type::ReadFolder) { // save dir
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::Directory);
dialog.setOption(QFileDialog::ShowDirsOnly);
@ -127,7 +133,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
dialog.show();
if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath());
if (multipleFiles == -1) {
if (type == Type::WriteFile) {
QString toSelect(startFile);
#ifdef Q_OS_WIN
int32 lastSlash = toSelect.lastIndexOf('/');
@ -151,12 +157,12 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
}
if (res == QDialog::Accepted) {
if (multipleFiles > 0) {
if (type == Type::ReadFiles) {
files = dialog.selectedFiles();
} else {
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
remoteContent = dialog.selectedRemoteContent();
#endif // Q_OS_WIN && !Q_OS_WINRT
@ -169,13 +175,16 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
return false;
}
} // namespace internal
} // namespace FileDialog
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) {
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);
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) {
QStringList files;
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);
return result;
}
@ -191,7 +200,7 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString
bool filedialogGetDir(QString &dir, const QString &caption) {
QStringList files;
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);
return result;
}

View File

@ -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());
namespace FileDialog {
namespace internal {
enum class Type {
ReadFile,
ReadFiles,
ReadFolder,
WriteFile,
};
} // namespace internal
using QueryId = uint64;
struct QueryUpdate {

View File

@ -653,6 +653,8 @@ void ScrollArea::moveEvent(QMoveEvent *e) {
void ScrollArea::keyPressEvent(QKeyEvent *e) {
if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->modifiers().testFlag(Qt::AltModifier)) {
e->ignore();
} else if(e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
((QObject*)widget())->event(e);
} else {
QScrollArea::keyPressEvent(e);
}

View File

@ -3,60 +3,60 @@ QT += core gui network widgets
CONFIG += plugin static c++14
CONFIG(debug, debug|release) {
DEFINES += _DEBUG
OBJECTS_DIR = ./../DebugIntermediate
MOC_DIR = ./GeneratedFiles/Debug
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Debug
DEFINES += _DEBUG
OBJECTS_DIR = ./../DebugIntermediate
MOC_DIR = ./GeneratedFiles/Debug
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Debug
}
CONFIG(release, debug|release) {
DEFINES += CUSTOM_API_ID
OBJECTS_DIR = ./../ReleaseIntermediate
MOC_DIR = ./GeneratedFiles/Release
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Release
DEFINES += CUSTOM_API_ID
OBJECTS_DIR = ./../ReleaseIntermediate
MOC_DIR = ./GeneratedFiles/Release
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Release
}
macx {
QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist
QMAKE_LFLAGS += -framework Cocoa
QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist
QMAKE_LFLAGS += -framework Cocoa
}
linux {
SOURCES += ./SourceFiles/pspecific_linux.cpp
HEADERS += ./SourceFiles/pspecific_linux.h
SOURCES += ./SourceFiles/pspecific_linux.cpp
HEADERS += ./SourceFiles/pspecific_linux.h
}
CONFIG(debug, debug|release) {
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
}
CONFIG(release, debug|release) {
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
}
file_style_basic.target = GeneratedFiles/styles/style_basic.cpp
@ -73,374 +73,379 @@ file_style_profile.target = GeneratedFiles/styles/style_profile.cpp
file_style_profile.depends = style_target
QMAKE_EXTRA_TARGETS += codegen_style codegen_numbers codegen_lang \
file_style_basic file_style_basic_types file_style_overview \
file_style_dialogs file_style_history file_style_profile
file_style_basic file_style_basic_types file_style_overview \
file_style_dialogs file_style_history file_style_profile
PRE_TARGETDEPS += style_target numbers_target lang_target
unix {
linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
linux-g++-32:QMAKE_TARGET.arch = x86
linux-g++-64:QMAKE_TARGET.arch = x86_64
linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
linux-g++-32:QMAKE_TARGET.arch = x86
linux-g++-64:QMAKE_TARGET.arch = x86_64
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += Q_OS_LINUX64
} else {
DEFINES += Q_OS_LINUX32
}
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += Q_OS_LINUX64
} else {
DEFINES += Q_OS_LINUX32
}
}
SOURCES += \
./GeneratedFiles/lang_auto.cpp \
./GeneratedFiles/numbers.cpp \
./GeneratedFiles/styles/style_basic.cpp \
./GeneratedFiles/styles/style_basic_types.cpp \
./GeneratedFiles/styles/style_dialogs.cpp \
./GeneratedFiles/styles/style_history.cpp \
./GeneratedFiles/styles/style_overview.cpp \
./GeneratedFiles/styles/style_profile.cpp \
./SourceFiles/main.cpp \
./SourceFiles/stdafx.cpp \
./SourceFiles/apiwrap.cpp \
./SourceFiles/app.cpp \
./SourceFiles/application.cpp \
./SourceFiles/audio.cpp \
./SourceFiles/autoupdater.cpp \
./SourceFiles/dialogswidget.cpp \
./SourceFiles/dropdown.cpp \
./SourceFiles/facades.cpp \
./SourceFiles/fileuploader.cpp \
./SourceFiles/history.cpp \
./SourceFiles/historywidget.cpp \
./SourceFiles/lang.cpp \
./SourceFiles/langloaderplain.cpp \
./SourceFiles/layerwidget.cpp \
./SourceFiles/layout.cpp \
./SourceFiles/mediaview.cpp \
./SourceFiles/observer_peer.cpp \
./SourceFiles/overviewwidget.cpp \
./SourceFiles/passcodewidget.cpp \
./SourceFiles/playerwidget.cpp \
./SourceFiles/localimageloader.cpp \
./SourceFiles/localstorage.cpp \
./SourceFiles/logs.cpp \
./SourceFiles/mainwidget.cpp \
./SourceFiles/settings.cpp \
./SourceFiles/settingswidget.cpp \
./SourceFiles/shortcuts.cpp \
./SourceFiles/structs.cpp \
./SourceFiles/sysbuttons.cpp \
./SourceFiles/title.cpp \
./SourceFiles/mainwindow.cpp \
./SourceFiles/boxes/aboutbox.cpp \
./SourceFiles/boxes/abstractbox.cpp \
./SourceFiles/boxes/addcontactbox.cpp \
./SourceFiles/boxes/autolockbox.cpp \
./SourceFiles/boxes/backgroundbox.cpp \
./SourceFiles/boxes/confirmbox.cpp \
./SourceFiles/boxes/connectionbox.cpp \
./SourceFiles/boxes/contactsbox.cpp \
./SourceFiles/boxes/downloadpathbox.cpp \
./SourceFiles/boxes/emojibox.cpp \
./SourceFiles/boxes/languagebox.cpp \
./SourceFiles/boxes/passcodebox.cpp \
./SourceFiles/boxes/photocropbox.cpp \
./SourceFiles/boxes/photosendbox.cpp \
./SourceFiles/boxes/report_box.cpp \
./SourceFiles/boxes/sessionsbox.cpp \
./SourceFiles/boxes/stickersetbox.cpp \
./SourceFiles/boxes/usernamebox.cpp \
./SourceFiles/core/basic_types.cpp \
./SourceFiles/core/click_handler.cpp \
./SourceFiles/core/click_handler_types.cpp \
./SourceFiles/core/observer.cpp \
./SourceFiles/data/data_abstract_structure.cpp \
./SourceFiles/data/data_drafts.cpp \
./SourceFiles/dialogs/dialogs_indexed_list.cpp \
./SourceFiles/dialogs/dialogs_layout.cpp \
./SourceFiles/dialogs/dialogs_list.cpp \
./SourceFiles/dialogs/dialogs_row.cpp \
./SourceFiles/history/field_autocomplete.cpp \
./SourceFiles/history/history_service_layout.cpp \
./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \
./SourceFiles/inline_bots/inline_bot_layout_item.cpp \
./SourceFiles/inline_bots/inline_bot_result.cpp \
./SourceFiles/inline_bots/inline_bot_send_data.cpp \
./SourceFiles/intro/introwidget.cpp \
./SourceFiles/intro/introcode.cpp \
./SourceFiles/intro/introphone.cpp \
./SourceFiles/intro/intropwdcheck.cpp \
./SourceFiles/intro/introsignup.cpp \
./SourceFiles/intro/introstart.cpp \
./SourceFiles/mtproto/facade.cpp \
./SourceFiles/mtproto/auth_key.cpp \
./SourceFiles/mtproto/connection.cpp \
./SourceFiles/mtproto/connection_abstract.cpp \
./SourceFiles/mtproto/connection_auto.cpp \
./SourceFiles/mtproto/connection_http.cpp \
./SourceFiles/mtproto/connection_tcp.cpp \
./SourceFiles/mtproto/core_types.cpp \
./SourceFiles/mtproto/dcenter.cpp \
./SourceFiles/mtproto/file_download.cpp \
./SourceFiles/mtproto/rsa_public_key.cpp \
./SourceFiles/mtproto/rpc_sender.cpp \
./SourceFiles/mtproto/scheme_auto.cpp \
./SourceFiles/mtproto/session.cpp \
./SourceFiles/overview/overview_layout.cpp \
./GeneratedFiles/lang_auto.cpp \
./GeneratedFiles/numbers.cpp \
./GeneratedFiles/styles/style_basic.cpp \
./GeneratedFiles/styles/style_basic_types.cpp \
./GeneratedFiles/styles/style_dialogs.cpp \
./GeneratedFiles/styles/style_history.cpp \
./GeneratedFiles/styles/style_overview.cpp \
./GeneratedFiles/styles/style_profile.cpp \
./SourceFiles/main.cpp \
./SourceFiles/stdafx.cpp \
./SourceFiles/apiwrap.cpp \
./SourceFiles/app.cpp \
./SourceFiles/application.cpp \
./SourceFiles/audio.cpp \
./SourceFiles/autoupdater.cpp \
./SourceFiles/dialogswidget.cpp \
./SourceFiles/dropdown.cpp \
./SourceFiles/facades.cpp \
./SourceFiles/fileuploader.cpp \
./SourceFiles/history.cpp \
./SourceFiles/historywidget.cpp \
./SourceFiles/lang.cpp \
./SourceFiles/langloaderplain.cpp \
./SourceFiles/layerwidget.cpp \
./SourceFiles/layout.cpp \
./SourceFiles/mediaview.cpp \
./SourceFiles/observer_peer.cpp \
./SourceFiles/overviewwidget.cpp \
./SourceFiles/passcodewidget.cpp \
./SourceFiles/playerwidget.cpp \
./SourceFiles/localimageloader.cpp \
./SourceFiles/localstorage.cpp \
./SourceFiles/logs.cpp \
./SourceFiles/mainwidget.cpp \
./SourceFiles/settings.cpp \
./SourceFiles/settingswidget.cpp \
./SourceFiles/shortcuts.cpp \
./SourceFiles/structs.cpp \
./SourceFiles/sysbuttons.cpp \
./SourceFiles/title.cpp \
./SourceFiles/mainwindow.cpp \
./SourceFiles/boxes/aboutbox.cpp \
./SourceFiles/boxes/abstractbox.cpp \
./SourceFiles/boxes/addcontactbox.cpp \
./SourceFiles/boxes/autolockbox.cpp \
./SourceFiles/boxes/backgroundbox.cpp \
./SourceFiles/boxes/confirmbox.cpp \
./SourceFiles/boxes/connectionbox.cpp \
./SourceFiles/boxes/contactsbox.cpp \
./SourceFiles/boxes/downloadpathbox.cpp \
./SourceFiles/boxes/emojibox.cpp \
./SourceFiles/boxes/languagebox.cpp \
./SourceFiles/boxes/passcodebox.cpp \
./SourceFiles/boxes/photocropbox.cpp \
./SourceFiles/boxes/photosendbox.cpp \
./SourceFiles/boxes/report_box.cpp \
./SourceFiles/boxes/sessionsbox.cpp \
./SourceFiles/boxes/stickersetbox.cpp \
./SourceFiles/boxes/usernamebox.cpp \
./SourceFiles/core/basic_types.cpp \
./SourceFiles/core/click_handler.cpp \
./SourceFiles/core/click_handler_types.cpp \
./SourceFiles/core/observer.cpp \
./SourceFiles/data/data_abstract_structure.cpp \
./SourceFiles/data/data_drafts.cpp \
./SourceFiles/dialogs/dialogs_indexed_list.cpp \
./SourceFiles/dialogs/dialogs_layout.cpp \
./SourceFiles/dialogs/dialogs_list.cpp \
./SourceFiles/dialogs/dialogs_row.cpp \
./SourceFiles/history/field_autocomplete.cpp \
./SourceFiles/history/history_service_layout.cpp \
./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \
./SourceFiles/inline_bots/inline_bot_layout_item.cpp \
./SourceFiles/inline_bots/inline_bot_result.cpp \
./SourceFiles/inline_bots/inline_bot_send_data.cpp \
./SourceFiles/intro/introwidget.cpp \
./SourceFiles/intro/introcode.cpp \
./SourceFiles/intro/introphone.cpp \
./SourceFiles/intro/intropwdcheck.cpp \
./SourceFiles/intro/introsignup.cpp \
./SourceFiles/intro/introstart.cpp \
./SourceFiles/mtproto/facade.cpp \
./SourceFiles/mtproto/auth_key.cpp \
./SourceFiles/mtproto/connection.cpp \
./SourceFiles/mtproto/connection_abstract.cpp \
./SourceFiles/mtproto/connection_auto.cpp \
./SourceFiles/mtproto/connection_http.cpp \
./SourceFiles/mtproto/connection_tcp.cpp \
./SourceFiles/mtproto/core_types.cpp \
./SourceFiles/mtproto/dcenter.cpp \
./SourceFiles/mtproto/file_download.cpp \
./SourceFiles/mtproto/rsa_public_key.cpp \
./SourceFiles/mtproto/rpc_sender.cpp \
./SourceFiles/mtproto/scheme_auto.cpp \
./SourceFiles/mtproto/session.cpp \
./SourceFiles/overview/overview_layout.cpp \
./SourceFiles/platform/linux/linux_gdk_helper.cpp \
./SourceFiles/platform/linux/linux_libs.cpp \
./SourceFiles/platform/linux/main_window_linux.cpp \
./SourceFiles/profile/profile_actions_widget.cpp \
./SourceFiles/profile/profile_block_widget.cpp \
./SourceFiles/profile/profile_cover_drop_area.cpp \
./SourceFiles/profile/profile_cover.cpp \
./SourceFiles/profile/profile_fixed_bar.cpp \
./SourceFiles/profile/profile_info_widget.cpp \
./SourceFiles/profile/profile_inner_widget.cpp \
./SourceFiles/profile/profile_invite_link_widget.cpp \
./SourceFiles/profile/profile_members_widget.cpp \
./SourceFiles/profile/profile_section_memento.cpp \
./SourceFiles/profile/profile_settings_widget.cpp \
./SourceFiles/profile/profile_shared_media_widget.cpp \
./SourceFiles/profile/profile_userpic_button.cpp \
./SourceFiles/profile/profile_widget.cpp \
./SourceFiles/serialize/serialize_common.cpp \
./SourceFiles/serialize/serialize_document.cpp \
./SourceFiles/ui/buttons/history_down_button.cpp \
./SourceFiles/ui/buttons/left_outline_button.cpp \
./SourceFiles/ui/buttons/peer_avatar_button.cpp \
./SourceFiles/ui/buttons/round_button.cpp \
./SourceFiles/ui/style/style_core.cpp \
./SourceFiles/ui/style/style_core_color.cpp \
./SourceFiles/ui/style/style_core_font.cpp \
./SourceFiles/ui/style/style_core_icon.cpp \
./SourceFiles/ui/style/style_core_types.cpp \
./SourceFiles/ui/text/text.cpp \
./SourceFiles/ui/text/text_block.cpp \
./SourceFiles/ui/text/text_entity.cpp \
./SourceFiles/ui/toast/toast.cpp \
./SourceFiles/ui/toast/toast_manager.cpp \
./SourceFiles/ui/toast/toast_widget.cpp \
./SourceFiles/ui/animation.cpp \
./SourceFiles/ui/boxshadow.cpp \
./SourceFiles/ui/button.cpp \
./SourceFiles/ui/popupmenu.cpp \
./SourceFiles/ui/countryinput.cpp \
./SourceFiles/ui/emoji_config.cpp \
./SourceFiles/ui/filedialog.cpp \
./SourceFiles/ui/flatbutton.cpp \
./SourceFiles/ui/flatcheckbox.cpp \
./SourceFiles/ui/flatinput.cpp \
./SourceFiles/ui/flatlabel.cpp \
./SourceFiles/ui/flattextarea.cpp \
./SourceFiles/ui/images.cpp \
./SourceFiles/ui/inner_dropdown.cpp \
./SourceFiles/ui/scrollarea.cpp \
./SourceFiles/ui/twidget.cpp \
./SourceFiles/window/main_window.cpp \
./SourceFiles/window/section_widget.cpp \
./SourceFiles/window/slide_animation.cpp \
./SourceFiles/window/top_bar_widget.cpp
./SourceFiles/platform/linux/file_dialog_linux.cpp \
./SourceFiles/platform/linux/main_window_linux.cpp \
./SourceFiles/profile/profile_actions_widget.cpp \
./SourceFiles/profile/profile_block_widget.cpp \
./SourceFiles/profile/profile_cover_drop_area.cpp \
./SourceFiles/profile/profile_cover.cpp \
./SourceFiles/profile/profile_fixed_bar.cpp \
./SourceFiles/profile/profile_info_widget.cpp \
./SourceFiles/profile/profile_inner_widget.cpp \
./SourceFiles/profile/profile_invite_link_widget.cpp \
./SourceFiles/profile/profile_members_widget.cpp \
./SourceFiles/profile/profile_section_memento.cpp \
./SourceFiles/profile/profile_settings_widget.cpp \
./SourceFiles/profile/profile_shared_media_widget.cpp \
./SourceFiles/profile/profile_userpic_button.cpp \
./SourceFiles/profile/profile_widget.cpp \
./SourceFiles/serialize/serialize_common.cpp \
./SourceFiles/serialize/serialize_document.cpp \
./SourceFiles/ui/buttons/history_down_button.cpp \
./SourceFiles/ui/buttons/left_outline_button.cpp \
./SourceFiles/ui/buttons/peer_avatar_button.cpp \
./SourceFiles/ui/buttons/round_button.cpp \
./SourceFiles/ui/style/style_core.cpp \
./SourceFiles/ui/style/style_core_color.cpp \
./SourceFiles/ui/style/style_core_font.cpp \
./SourceFiles/ui/style/style_core_icon.cpp \
./SourceFiles/ui/style/style_core_types.cpp \
./SourceFiles/ui/text/text.cpp \
./SourceFiles/ui/text/text_block.cpp \
./SourceFiles/ui/text/text_entity.cpp \
./SourceFiles/ui/toast/toast.cpp \
./SourceFiles/ui/toast/toast_manager.cpp \
./SourceFiles/ui/toast/toast_widget.cpp \
./SourceFiles/ui/animation.cpp \
./SourceFiles/ui/boxshadow.cpp \
./SourceFiles/ui/button.cpp \
./SourceFiles/ui/popupmenu.cpp \
./SourceFiles/ui/countryinput.cpp \
./SourceFiles/ui/emoji_config.cpp \
./SourceFiles/ui/filedialog.cpp \
./SourceFiles/ui/flatbutton.cpp \
./SourceFiles/ui/flatcheckbox.cpp \
./SourceFiles/ui/flatinput.cpp \
./SourceFiles/ui/flatlabel.cpp \
./SourceFiles/ui/flattextarea.cpp \
./SourceFiles/ui/images.cpp \
./SourceFiles/ui/inner_dropdown.cpp \
./SourceFiles/ui/scrollarea.cpp \
./SourceFiles/ui/twidget.cpp \
./SourceFiles/window/main_window.cpp \
./SourceFiles/window/section_widget.cpp \
./SourceFiles/window/slide_animation.cpp \
./SourceFiles/window/top_bar_widget.cpp
HEADERS += \
./GeneratedFiles/lang_auto.h \
./GeneratedFiles/numbers.h \
./GeneratedFiles/styles/style_basic.h \
./GeneratedFiles/styles/style_basic_types.h \
./GeneratedFiles/styles/style_dialogs.h \
./GeneratedFiles/styles/style_history.h \
./GeneratedFiles/styles/style_overview.h \
./GeneratedFiles/styles/style_profile.h \
./SourceFiles/stdafx.h \
./SourceFiles/apiwrap.h \
./SourceFiles/app.h \
./SourceFiles/application.h \
./SourceFiles/audio.h \
./SourceFiles/autoupdater.h \
./SourceFiles/config.h \
./SourceFiles/countries.h \
./SourceFiles/dialogswidget.h \
./SourceFiles/dropdown.h \
./SourceFiles/facades.h \
./SourceFiles/fileuploader.h \
./SourceFiles/history.h \
./SourceFiles/historywidget.h \
./SourceFiles/lang.h \
./SourceFiles/langloaderplain.h \
./SourceFiles/layerwidget.h \
./SourceFiles/layout.h \
./SourceFiles/mediaview.h \
./SourceFiles/observer_peer.h \
./SourceFiles/overviewwidget.h \
./SourceFiles/passcodewidget.h \
./SourceFiles/playerwidget.h \
./SourceFiles/localimageloader.h \
./SourceFiles/localstorage.h \
./SourceFiles/logs.h \
./SourceFiles/mainwidget.h \
./SourceFiles/settings.h \
./SourceFiles/settingswidget.h \
./SourceFiles/shortcuts.h \
./SourceFiles/structs.h \
./SourceFiles/sysbuttons.h \
./SourceFiles/title.h \
./SourceFiles/mainwindow.h \
./SourceFiles/boxes/aboutbox.h \
./SourceFiles/boxes/abstractbox.h \
./SourceFiles/boxes/addcontactbox.h \
./SourceFiles/boxes/autolockbox.h \
./SourceFiles/boxes/backgroundbox.h \
./SourceFiles/boxes/confirmbox.h \
./SourceFiles/boxes/connectionbox.h \
./SourceFiles/boxes/contactsbox.h \
./SourceFiles/boxes/downloadpathbox.h \
./SourceFiles/boxes/emojibox.h \
./SourceFiles/boxes/languagebox.h \
./SourceFiles/boxes/passcodebox.h \
./SourceFiles/boxes/photocropbox.h \
./SourceFiles/boxes/photosendbox.h \
./SourceFiles/boxes/report_box.h \
./SourceFiles/boxes/sessionsbox.h \
./SourceFiles/boxes/stickersetbox.h \
./SourceFiles/boxes/usernamebox.h \
./SourceFiles/core/basic_types.h \
./SourceFiles/core/click_handler.h \
./SourceFiles/core/click_handler_types.h \
./SourceFiles/core/observer.h \
./SourceFiles/core/vector_of_moveable.h \
./GeneratedFiles/lang_auto.h \
./GeneratedFiles/numbers.h \
./GeneratedFiles/styles/style_basic.h \
./GeneratedFiles/styles/style_basic_types.h \
./GeneratedFiles/styles/style_dialogs.h \
./GeneratedFiles/styles/style_history.h \
./GeneratedFiles/styles/style_overview.h \
./GeneratedFiles/styles/style_profile.h \
./SourceFiles/stdafx.h \
./SourceFiles/apiwrap.h \
./SourceFiles/app.h \
./SourceFiles/application.h \
./SourceFiles/audio.h \
./SourceFiles/autoupdater.h \
./SourceFiles/config.h \
./SourceFiles/countries.h \
./SourceFiles/dialogswidget.h \
./SourceFiles/dropdown.h \
./SourceFiles/facades.h \
./SourceFiles/fileuploader.h \
./SourceFiles/history.h \
./SourceFiles/historywidget.h \
./SourceFiles/lang.h \
./SourceFiles/langloaderplain.h \
./SourceFiles/layerwidget.h \
./SourceFiles/layout.h \
./SourceFiles/mediaview.h \
./SourceFiles/observer_peer.h \
./SourceFiles/overviewwidget.h \
./SourceFiles/passcodewidget.h \
./SourceFiles/playerwidget.h \
./SourceFiles/localimageloader.h \
./SourceFiles/localstorage.h \
./SourceFiles/logs.h \
./SourceFiles/mainwidget.h \
./SourceFiles/settings.h \
./SourceFiles/settingswidget.h \
./SourceFiles/shortcuts.h \
./SourceFiles/structs.h \
./SourceFiles/sysbuttons.h \
./SourceFiles/title.h \
./SourceFiles/mainwindow.h \
./SourceFiles/boxes/aboutbox.h \
./SourceFiles/boxes/abstractbox.h \
./SourceFiles/boxes/addcontactbox.h \
./SourceFiles/boxes/autolockbox.h \
./SourceFiles/boxes/backgroundbox.h \
./SourceFiles/boxes/confirmbox.h \
./SourceFiles/boxes/connectionbox.h \
./SourceFiles/boxes/contactsbox.h \
./SourceFiles/boxes/downloadpathbox.h \
./SourceFiles/boxes/emojibox.h \
./SourceFiles/boxes/languagebox.h \
./SourceFiles/boxes/passcodebox.h \
./SourceFiles/boxes/photocropbox.h \
./SourceFiles/boxes/photosendbox.h \
./SourceFiles/boxes/report_box.h \
./SourceFiles/boxes/sessionsbox.h \
./SourceFiles/boxes/stickersetbox.h \
./SourceFiles/boxes/usernamebox.h \
./SourceFiles/core/basic_types.h \
./SourceFiles/core/click_handler.h \
./SourceFiles/core/click_handler_types.h \
./SourceFiles/core/observer.h \
./SourceFiles/core/vector_of_moveable.h \
./SourceFiles/core/version.h \
./SourceFiles/data/data_abstract_structure.h \
./SourceFiles/data/data_drafts.h \
./SourceFiles/dialogs/dialogs_common.h \
./SourceFiles/dialogs/dialogs_indexed_list.h \
./SourceFiles/dialogs/dialogs_layout.h \
./SourceFiles/dialogs/dialogs_list.h \
./SourceFiles/dialogs/dialogs_row.h \
./SourceFiles/history/field_autocomplete.h \
./SourceFiles/history/history_common.h \
./SourceFiles/history/history_service_layout.h \
./SourceFiles/inline_bots/inline_bot_layout_internal.h \
./SourceFiles/inline_bots/inline_bot_layout_item.h \
./SourceFiles/inline_bots/inline_bot_result.h \
./SourceFiles/inline_bots/inline_bot_send_data.h \
./SourceFiles/intro/introwidget.h \
./SourceFiles/intro/introcode.h \
./SourceFiles/intro/introphone.h \
./SourceFiles/intro/intropwdcheck.h \
./SourceFiles/intro/introsignup.h \
./SourceFiles/intro/introstart.h \
./SourceFiles/mtproto/facade.h \
./SourceFiles/mtproto/auth_key.h \
./SourceFiles/mtproto/connection.h \
./SourceFiles/mtproto/connection_abstract.h \
./SourceFiles/mtproto/connection_auto.h \
./SourceFiles/mtproto/connection_http.h \
./SourceFiles/mtproto/connection_tcp.h \
./SourceFiles/mtproto/core_types.h \
./SourceFiles/mtproto/dcenter.h \
./SourceFiles/mtproto/file_download.h \
./SourceFiles/mtproto/rsa_public_key.h \
./SourceFiles/mtproto/rpc_sender.h \
./SourceFiles/mtproto/scheme_auto.h \
./SourceFiles/mtproto/session.h \
./SourceFiles/overview/overview_layout.h \
./SourceFiles/platform/platform_main_window.h \
./SourceFiles/data/data_abstract_structure.h \
./SourceFiles/data/data_drafts.h \
./SourceFiles/dialogs/dialogs_common.h \
./SourceFiles/dialogs/dialogs_indexed_list.h \
./SourceFiles/dialogs/dialogs_layout.h \
./SourceFiles/dialogs/dialogs_list.h \
./SourceFiles/dialogs/dialogs_row.h \
./SourceFiles/history/field_autocomplete.h \
./SourceFiles/history/history_common.h \
./SourceFiles/history/history_service_layout.h \
./SourceFiles/inline_bots/inline_bot_layout_internal.h \
./SourceFiles/inline_bots/inline_bot_layout_item.h \
./SourceFiles/inline_bots/inline_bot_result.h \
./SourceFiles/inline_bots/inline_bot_send_data.h \
./SourceFiles/intro/introwidget.h \
./SourceFiles/intro/introcode.h \
./SourceFiles/intro/introphone.h \
./SourceFiles/intro/intropwdcheck.h \
./SourceFiles/intro/introsignup.h \
./SourceFiles/intro/introstart.h \
./SourceFiles/mtproto/facade.h \
./SourceFiles/mtproto/auth_key.h \
./SourceFiles/mtproto/connection.h \
./SourceFiles/mtproto/connection_abstract.h \
./SourceFiles/mtproto/connection_auto.h \
./SourceFiles/mtproto/connection_http.h \
./SourceFiles/mtproto/connection_tcp.h \
./SourceFiles/mtproto/core_types.h \
./SourceFiles/mtproto/dcenter.h \
./SourceFiles/mtproto/file_download.h \
./SourceFiles/mtproto/rsa_public_key.h \
./SourceFiles/mtproto/rpc_sender.h \
./SourceFiles/mtproto/scheme_auto.h \
./SourceFiles/mtproto/session.h \
./SourceFiles/overview/overview_layout.h \
./SourceFiles/platform/platform_file_dialog.h \
./SourceFiles/platform/platform_main_window.h \
./SourceFiles/platform/linux/linux_gdk_helper.h \
./SourceFiles/platform/linux/linux_libs.h \
./SourceFiles/platform/linux/main_window_linux.h \
./SourceFiles/profile/profile_actions_widget.h \
./SourceFiles/profile/profile_block_widget.h \
./SourceFiles/profile/profile_cover_drop_area.h \
./SourceFiles/profile/profile_cover.h \
./SourceFiles/profile/profile_fixed_bar.h \
./SourceFiles/profile/profile_info_widget.h \
./SourceFiles/profile/profile_inner_widget.h \
./SourceFiles/profile/profile_invite_link_widget.h \
./SourceFiles/profile/profile_members_widget.h \
./SourceFiles/profile/profile_section_memento.h \
./SourceFiles/profile/profile_settings_widget.h \
./SourceFiles/profile/profile_shared_media_widget.h \
./SourceFiles/profile/profile_userpic_button.h \
./SourceFiles/profile/profile_widget.h \
./SourceFiles/pspecific.h \
./SourceFiles/serialize/serialize_common.h \
./SourceFiles/serialize/serialize_document.h \
./SourceFiles/ui/buttons/history_down_button.h \
./SourceFiles/ui/buttons/left_outline_button.h \
./SourceFiles/ui/buttons/peer_avatar_button.h \
./SourceFiles/ui/buttons/round_button.h \
./SourceFiles/ui/style/style_core.h \
./SourceFiles/ui/style/style_core_color.h \
./SourceFiles/ui/style/style_core_font.h \
./SourceFiles/ui/style/style_core_icon.h \
./SourceFiles/ui/style/style_core_types.h \
./SourceFiles/ui/text/text.h \
./SourceFiles/ui/text/text_block.h \
./SourceFiles/ui/text/text_entity.h \
./SourceFiles/ui/toast/toast.h \
./SourceFiles/ui/toast/toast_manager.h \
./SourceFiles/ui/toast/toast_widget.h \
./SourceFiles/ui/animation.h \
./SourceFiles/ui/boxshadow.h \
./SourceFiles/ui/button.h \
./SourceFiles/ui/popupmenu.h \
./SourceFiles/ui/countryinput.h \
./SourceFiles/ui/emoji_config.h \
./SourceFiles/ui/filedialog.h \
./SourceFiles/ui/flatbutton.h \
./SourceFiles/ui/flatcheckbox.h \
./SourceFiles/ui/flatinput.h \
./SourceFiles/ui/flatlabel.h \
./SourceFiles/ui/flattextarea.h \
./SourceFiles/ui/images.h \
./SourceFiles/ui/inner_dropdown.h \
./SourceFiles/ui/scrollarea.h \
./SourceFiles/ui/twidget.h \
./SourceFiles/window/main_window.h \
./SourceFiles/window/section_memento.h \
./SourceFiles/window/section_widget.h \
./SourceFiles/window/slide_animation.h \
./SourceFiles/window/top_bar_widget.h
./SourceFiles/platform/linux/file_dialog_linux.h \
./SourceFiles/platform/linux/main_window_linux.h \
./SourceFiles/profile/profile_actions_widget.h \
./SourceFiles/profile/profile_block_widget.h \
./SourceFiles/profile/profile_cover_drop_area.h \
./SourceFiles/profile/profile_cover.h \
./SourceFiles/profile/profile_fixed_bar.h \
./SourceFiles/profile/profile_info_widget.h \
./SourceFiles/profile/profile_inner_widget.h \
./SourceFiles/profile/profile_invite_link_widget.h \
./SourceFiles/profile/profile_members_widget.h \
./SourceFiles/profile/profile_section_memento.h \
./SourceFiles/profile/profile_settings_widget.h \
./SourceFiles/profile/profile_shared_media_widget.h \
./SourceFiles/profile/profile_userpic_button.h \
./SourceFiles/profile/profile_widget.h \
./SourceFiles/pspecific.h \
./SourceFiles/serialize/serialize_common.h \
./SourceFiles/serialize/serialize_document.h \
./SourceFiles/ui/buttons/history_down_button.h \
./SourceFiles/ui/buttons/left_outline_button.h \
./SourceFiles/ui/buttons/peer_avatar_button.h \
./SourceFiles/ui/buttons/round_button.h \
./SourceFiles/ui/style/style_core.h \
./SourceFiles/ui/style/style_core_color.h \
./SourceFiles/ui/style/style_core_font.h \
./SourceFiles/ui/style/style_core_icon.h \
./SourceFiles/ui/style/style_core_types.h \
./SourceFiles/ui/text/text.h \
./SourceFiles/ui/text/text_block.h \
./SourceFiles/ui/text/text_entity.h \
./SourceFiles/ui/toast/toast.h \
./SourceFiles/ui/toast/toast_manager.h \
./SourceFiles/ui/toast/toast_widget.h \
./SourceFiles/ui/animation.h \
./SourceFiles/ui/boxshadow.h \
./SourceFiles/ui/button.h \
./SourceFiles/ui/popupmenu.h \
./SourceFiles/ui/countryinput.h \
./SourceFiles/ui/emoji_config.h \
./SourceFiles/ui/filedialog.h \
./SourceFiles/ui/flatbutton.h \
./SourceFiles/ui/flatcheckbox.h \
./SourceFiles/ui/flatinput.h \
./SourceFiles/ui/flatlabel.h \
./SourceFiles/ui/flattextarea.h \
./SourceFiles/ui/images.h \
./SourceFiles/ui/inner_dropdown.h \
./SourceFiles/ui/scrollarea.h \
./SourceFiles/ui/twidget.h \
./SourceFiles/window/main_window.h \
./SourceFiles/window/section_memento.h \
./SourceFiles/window/section_widget.h \
./SourceFiles/window/slide_animation.h \
./SourceFiles/window/top_bar_widget.h
win32 {
SOURCES += \
./SourceFiles/pspecific_win.cpp \
./SourceFiles/platform/win/windows_app_user_model_id.cpp \
./SourceFiles/platform/win/windows_dlls.cpp \
./SourceFiles/platform/win/windows_event_filter.cpp \
./SourceFiles/platform/win/windows_toasts.cpp
./SourceFiles/pspecific_win.cpp \
./SourceFiles/platform/win/windows_app_user_model_id.cpp \
./SourceFiles/platform/win/windows_dlls.cpp \
./SourceFiles/platform/win/windows_event_filter.cpp \
./SourceFiles/platform/win/windows_toasts.cpp
HEADERS += \
./SourceFiles/pspecific_win.h \
./SourceFiles/platform/win/windows_app_user_model_id.h \
./SourceFiles/platform/win/windows_dlls.h \
./SourceFiles/platform/win/windows_event_filter.h \
./SourceFiles/platform/win/windows_toasts.h
./SourceFiles/pspecific_win.h \
./SourceFiles/platform/win/windows_app_user_model_id.h \
./SourceFiles/platform/win/windows_dlls.h \
./SourceFiles/platform/win/windows_event_filter.h \
./SourceFiles/platform/win/windows_toasts.h
}
winrt {
SOURCES += \
./SourceFiles/pspecific_winrt.cpp \
./SourceFiles/platform/winrt/main_window_winrt.cpp
./SourceFiles/pspecific_winrt.cpp \
./SourceFiles/platform/winrt/main_window_winrt.cpp
HEADERS += \
./SourceFiles/pspecific_winrt.h \
./Sourcefiles/platform/winrt/main_window_winrt.h
./SourceFiles/pspecific_winrt.h \
./Sourcefiles/platform/winrt/main_window_winrt.h
}
macx {
SOURCES += \
./SourceFiles/pspecific_mac.cpp
./SourceFiles/pspecific_mac.cpp
HEADERS += \
./SourceFiles/pspecific_mac.h
./SourceFiles/pspecific_mac.h
OBJECTIVE_SOURCES += \
./SourceFiles/pspecific_mac_p.mm \
./SourceFiles/platform/mac/main_window_mac.mm
./SourceFiles/pspecific_mac_p.mm \
./SourceFiles/platform/mac/main_window_mac.mm
HEADERS += \
./SourceFiles/pspecific_mac_p.h \
./SourceFiles/platform/mac/main_window_mac.h
./SourceFiles/pspecific_mac_p.h \
./SourceFiles/platform/mac/main_window_mac.h
}
SOURCES += \
./ThirdParty/minizip/zip.c \
./ThirdParty/minizip/ioapi.c
./ThirdParty/minizip/zip.c \
./ThirdParty/minizip/ioapi.c
CONFIG += precompile_header
@ -450,19 +455,19 @@ QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-v
QMAKE_CFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-variable -Wno-switch -Wno-comment -Wno-unused-but-set-variable
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g
QMAKE_LFLAGS_RELEASE -= -O1
QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g
QMAKE_LFLAGS_RELEASE -= -O1
QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++
}
# Linux 32bit fails Release link with Link-Time Optimization: virtual memory exhausted
unix {
!contains(QMAKE_TARGET.arch, x86_64) {
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -flto
QMAKE_LFLAGS_RELEASE -= -flto
}
}
!contains(QMAKE_TARGET.arch, x86_64) {
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -flto
QMAKE_LFLAGS_RELEASE -= -flto
}
}
}
CONFIG(debug, debug|release) {
QMAKE_LFLAGS_DEBUG += -g -rdynamic -static-libstdc++
@ -471,22 +476,23 @@ CONFIG(debug, debug|release) {
include(qt_static.pri)
INCLUDEPATH += \
/usr/local/include\
/usr/local/include/opus\
./SourceFiles\
./GeneratedFiles\
./ThirdParty/minizip\
./../../Libraries/breakpad/src
/usr/local/include\
/usr/local/include/opus\
./SourceFiles\
./GeneratedFiles\
./ThirdParty/minizip\
./../../Libraries/breakpad/src
INCLUDEPATH += "/usr/include/libappindicator-0.1"
#INCLUDEPATH += "/usr/include/gtk-3.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/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/include/cairo"
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/atk-1.0"
@ -502,21 +508,21 @@ LIBS += /usr/local/lib/libxkbcommon.a
LIBS += ./../../../Libraries/breakpad/src/client/linux/libbreakpad_client.a
RESOURCES += \
./Resources/telegram.qrc \
./Resources/telegram_linux.qrc \
./Resources/telegram_emojis.qrc
./Resources/telegram.qrc \
./Resources/telegram_linux.qrc \
./Resources/telegram_emojis.qrc
OTHER_FILES += \
./Resources/basic_types.style \
./Resources/basic.style \
./Resources/all_files.style \
./Resources/langs/lang.strings \
./Resources/langs/lang_it.strings \
./Resources/langs/lang_es.strings \
./Resources/langs/lang_de.strings \
./Resources/langs/lang_nl.strings \
./Resources/langs/lang_pt_BR.strings \
./SourceFiles/dialogs/dialogs.style \
./SourceFiles/history/history.style \
./SourceFiles/overview/overview.style \
./SourceFiles/profile/profile.style
./Resources/basic_types.style \
./Resources/basic.style \
./Resources/all_files.style \
./Resources/langs/lang.strings \
./Resources/langs/lang_it.strings \
./Resources/langs/lang_es.strings \
./Resources/langs/lang_de.strings \
./Resources/langs/lang_nl.strings \
./Resources/langs/lang_pt_BR.strings \
./SourceFiles/dialogs/dialogs.style \
./SourceFiles/history/history.style \
./SourceFiles/overview/overview.style \
./SourceFiles/profile/profile.style

View File

@ -1,20 +1,26 @@
QT_TDESKTOP_VERSION_DEFAULT = 5.6.0
QT_TDESKTOP_PATH_DEFAULT = /usr/local/tdesktop/Qt-$${QT_TDESKTOP_VERSION_DEFAULT}
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH}
isEmpty(QT_TDESKTOP_PATH) {
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)
isEmpty(QT_TDESKTOP_PATH) {
message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT})
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT}
}
}
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
isEmpty(QT_TDESKTOP_VERSION) {
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)
isEmpty(QT_TDESKTOP_VERSION) {
message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT})
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT}
}
}
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} \
$${QT_TDESKTOP_PATH}/include

View File

@ -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.
###Clone source code
## Clone source code
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
###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
@ -35,13 +61,13 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
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)
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**
* For **Debug** and **Release** configurations
@ -53,13 +79,13 @@ Extract to **D:\TBuild\Libraries**
* Build Debug 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)
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**
* 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 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
@ -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
#####Building library
#### Building library
* Open in VS2015 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln**
* Build Debug 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
@ -93,7 +119,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
git checkout 90349b38
git apply ./../../tdesktop/Telegram/Patches/openal.diff
#####Building library
#### Building library
* 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
@ -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
####Opus codec
### Opus codec
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**
#####Building libraries
#### Building libraries
* Open in VS2015 **D:\TBuild\Libraries\opus\win32\VS2010\opus.sln**
* Build Debug configuration
* 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
@ -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**
#####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\\**
@ -148,7 +174,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
make
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)
* 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 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 ..
#####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 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
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.
####Qt5Package
### Qt5Package
https://visualstudiogallery.msdn.microsoft.com/c89ff880-8509-47a4-a262-e4fa07168408
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)
There go to Libraries directory
@ -204,19 +234,18 @@ There go to Libraries directory
and run
set PATH=C:\Python27;%PATH%
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
cd depot_tools
gclient config "https://chromium.googlesource.com/breakpad/breakpad.git"
gclient sync
cd ..
md breakpad
cd breakpad
md breakpad && cd breakpad
..\depot_tools\fetch breakpad
..\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**
* 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 Release configuration
###Building Telegram Desktop
## Building Telegram Desktop
* Launch VS2015 for configuring Qt5Package
* QT5 > Qt Options > Add

View File

@ -72,7 +72,7 @@ Building
cd "$srcdir/Libraries/QtStatic"
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
-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-install_subtargets module-qtimageformats-install_subtargets

View File

@ -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
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
sudo make install